Sfoglia il codice sorgente

fix(compaction): order compaction summary before retained tail (#25851)

Shoubhit Dash 3 mesi fa
parent
commit
811954880e

+ 26 - 0
packages/opencode/src/session/message-v2.ts

@@ -1104,6 +1104,32 @@ export function filterCompacted(msgs: Iterable<WithParts>) {
       completed.add(msg.info.parentID)
   }
   result.reverse()
+  const compactionIndex = result.findLastIndex(
+    (msg) =>
+      msg.info.role === "user" &&
+      msg.parts.some((item): item is CompactionPart => item.type === "compaction" && item.tail_start_id !== undefined),
+  )
+  const compaction = result[compactionIndex]
+  const part = compaction?.parts.find(
+    (item): item is CompactionPart => item.type === "compaction" && item.tail_start_id !== undefined,
+  )
+  const summaryIndex = compaction
+    ? result.findIndex(
+        (msg, index) =>
+          index > compactionIndex &&
+          msg.info.role === "assistant" &&
+          msg.info.summary &&
+          msg.info.parentID === compaction.info.id,
+      )
+    : -1
+  const tailIndex = part?.tail_start_id ? result.findIndex((msg) => msg.info.id === part.tail_start_id) : -1
+  if (tailIndex >= 0 && tailIndex < compactionIndex && summaryIndex > compactionIndex) {
+    return [
+      ...result.slice(compactionIndex, summaryIndex + 1),
+      ...result.slice(tailIndex, compactionIndex),
+      ...result.slice(summaryIndex + 1),
+    ]
+  }
   return result
 }
 

+ 3 - 1
packages/opencode/test/session/compaction.test.ts

@@ -1218,7 +1218,9 @@ describe("session.compaction.process", () => {
           expect(captured).not.toContain("keep tail")
 
           const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
-          expect(filtered[0]?.info.id).toBe(keep.id)
+          expect(filtered.map((msg) => msg.info.id).slice(0, 3)).toEqual([parent!, expect.any(String), keep.id])
+          expect(filtered[1]?.info.role).toBe("assistant")
+          expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true)
           expect(filtered.map((msg) => msg.info.id)).not.toContain(large.id)
         } finally {
           await rt.dispose()

+ 4 - 4
packages/opencode/test/session/messages-pagination.test.ts

@@ -834,7 +834,7 @@ describe("MessageV2.filterCompacted", () => {
 
         const result = MessageV2.filterCompacted(MessageV2.stream(session.id))
 
-        expect(result.map((item) => item.info.id)).toEqual([u2, a2, c1, s1, u3, a3])
+        expect(result.map((item) => item.info.id)).toEqual([c1, s1, u2, a2, u3, a3])
 
         await svc.remove(session.id)
       },
@@ -889,7 +889,7 @@ describe("MessageV2.filterCompacted", () => {
         })
 
         const parentFiltered = MessageV2.filterCompacted(MessageV2.stream(session.id))
-        expect(parentFiltered.map((item) => item.info.id)).toEqual([u2, a2, c1, s1, u3, a3])
+        expect(parentFiltered.map((item) => item.info.id)).toEqual([c1, s1, u2, a2, u3, a3])
 
         const forked = await svc.fork({ sessionID: session.id })
         const childFiltered = MessageV2.filterCompacted(MessageV2.stream(forked.id))
@@ -964,7 +964,7 @@ describe("MessageV2.filterCompacted", () => {
 
         const result = MessageV2.filterCompacted(MessageV2.stream(session.id))
 
-        expect(result.map((item) => item.info.id)).toEqual([a3, c1, s1, u3, a4])
+        expect(result.map((item) => item.info.id)).toEqual([c1, s1, a3, u3, a4])
 
         await svc.remove(session.id)
       },
@@ -1041,7 +1041,7 @@ describe("MessageV2.filterCompacted", () => {
 
         const result = MessageV2.filterCompacted(MessageV2.stream(session.id))
 
-        expect(result.map((item) => item.info.id)).toEqual([u3, a3, c2, s2, u4, a4])
+        expect(result.map((item) => item.info.id)).toEqual([c2, s2, u3, a3, u4, a4])
 
         await svc.remove(session.id)
       },