Skip to content

Commit ca8a42c

Browse files
authored
Migrate LLM compaction tail tests (#26734)
1 parent 8f5f75d commit ca8a42c

1 file changed

Lines changed: 70 additions & 105 deletions

File tree

packages/opencode/test/session/compaction.test.ts

Lines changed: 70 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,22 +1106,18 @@ describe("session.compaction.process", () => {
11061106
{ git: true },
11071107
)
11081108

1109-
test("falls back to full summary when retained tail media exceeds preserve token budget", async () => {
1110-
await using tmp = await tmpdir({ git: true })
1111-
const stub = llm()
1112-
let captured = ""
1113-
stub.push(
1114-
reply("summary", (input) => {
1115-
captured = JSON.stringify(input.messages)
1116-
}),
1117-
)
1118-
await WithInstance.provide({
1119-
directory: tmp.path,
1120-
fn: async () => {
1121-
const session = await svc.create({})
1122-
await user(session.id, "older")
1123-
const recent = await user(session.id, "recent image turn")
1124-
await svc.updatePart({
1109+
itProcess.instance(
1110+
"falls back to full summary when retained tail media exceeds preserve token budget",
1111+
() => {
1112+
const stub = llm()
1113+
let captured = ""
1114+
stub.push(reply("summary", (input) => (captured = JSON.stringify(input.messages))))
1115+
return Effect.gen(function* () {
1116+
const ssn = yield* SessionNs.Service
1117+
const session = yield* ssn.create({})
1118+
yield* createUserMessage(session.id, "older")
1119+
const recent = yield* createUserMessage(session.id, "recent image turn")
1120+
yield* ssn.updatePart({
11251121
id: PartID.ascending(),
11261122
messageID: recent.id,
11271123
sessionID: session.id,
@@ -1130,112 +1126,81 @@ describe("session.compaction.process", () => {
11301126
filename: "big.png",
11311127
url: `data:image/png;base64,${"a".repeat(4_000)}`,
11321128
})
1133-
await SessionCompaction.create({
1134-
sessionID: session.id,
1135-
agent: "build",
1136-
model: ref,
1137-
auto: false,
1138-
})
1129+
yield* createSummaryCompaction(session.id)
11391130

1140-
const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 100 }))
1141-
try {
1142-
const msgs = await svc.messages({ sessionID: session.id })
1143-
const parent = msgs.at(-1)?.info.id
1144-
expect(parent).toBeTruthy()
1145-
await rt.runPromise(
1146-
SessionCompaction.Service.use((svc) =>
1147-
svc.process({
1148-
parentID: parent!,
1149-
messages: msgs,
1150-
sessionID: session.id,
1151-
auto: false,
1152-
}),
1153-
),
1154-
)
1131+
const msgs = yield* ssn.messages({ sessionID: session.id })
1132+
const parent = msgs.at(-1)?.info.id
1133+
expect(parent).toBeTruthy()
1134+
yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
11551135

1156-
const part = await lastCompactionPart(session.id)
1157-
expect(part?.type).toBe("compaction")
1158-
expect(part?.tail_start_id).toBeUndefined()
1159-
expect(captured).toContain("recent image turn")
1160-
expect(captured).toContain("Attached image/png: big.png")
1161-
} finally {
1162-
await rt.dispose()
1163-
}
1164-
},
1165-
})
1166-
})
1136+
const part = yield* readCompactionPart(session.id)
1137+
expect(part?.type).toBe("compaction")
1138+
expect(part?.tail_start_id).toBeUndefined()
1139+
expect(captured).toContain("recent image turn")
1140+
expect(captured).toContain("Attached image/png: big.png")
1141+
}).pipe(
1142+
Effect.provide(
1143+
compactionProcessLayer({ llm: stub.layer, config: cfg({ tail_turns: 1, preserve_recent_tokens: 100 }) }),
1144+
),
1145+
)
1146+
},
1147+
{ git: true },
1148+
)
11671149

1168-
test("retains a split turn suffix when a later message fits the preserve token budget", async () => {
1169-
await using tmp = await tmpdir({ git: true })
1170-
const stub = llm()
1171-
let captured = ""
1172-
stub.push(
1173-
reply("summary", (input) => {
1174-
captured = JSON.stringify(input.messages)
1175-
}),
1176-
)
1177-
await WithInstance.provide({
1178-
directory: tmp.path,
1179-
fn: async () => {
1180-
const session = await svc.create({})
1181-
await user(session.id, "older")
1182-
const recent = await user(session.id, "recent turn")
1183-
const large = await assistant(session.id, recent.id, tmp.path)
1184-
await svc.updatePart({
1150+
itProcess.instance(
1151+
"retains a split turn suffix when a later message fits the preserve token budget",
1152+
() => {
1153+
const stub = llm()
1154+
let captured = ""
1155+
stub.push(reply("summary", (input) => (captured = JSON.stringify(input.messages))))
1156+
return Effect.gen(function* () {
1157+
const test = yield* TestInstance
1158+
const ssn = yield* SessionNs.Service
1159+
const session = yield* ssn.create({})
1160+
yield* createUserMessage(session.id, "older")
1161+
const recent = yield* createUserMessage(session.id, "recent turn")
1162+
const large = yield* createAssistantMessage(session.id, recent.id, test.directory)
1163+
yield* ssn.updatePart({
11851164
id: PartID.ascending(),
11861165
messageID: large.id,
11871166
sessionID: session.id,
11881167
type: "text",
11891168
text: "z".repeat(2_000),
11901169
})
1191-
const keep = await assistant(session.id, recent.id, tmp.path)
1192-
await svc.updatePart({
1170+
const keep = yield* createAssistantMessage(session.id, recent.id, test.directory)
1171+
yield* ssn.updatePart({
11931172
id: PartID.ascending(),
11941173
messageID: keep.id,
11951174
sessionID: session.id,
11961175
type: "text",
11971176
text: "keep tail",
11981177
})
1199-
await SessionCompaction.create({
1200-
sessionID: session.id,
1201-
agent: "build",
1202-
model: ref,
1203-
auto: false,
1204-
})
1205-
1206-
const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 100 }))
1207-
try {
1208-
const msgs = await svc.messages({ sessionID: session.id })
1209-
const parent = msgs.at(-1)?.info.id
1210-
expect(parent).toBeTruthy()
1211-
await rt.runPromise(
1212-
SessionCompaction.Service.use((svc) =>
1213-
svc.process({
1214-
parentID: parent!,
1215-
messages: msgs,
1216-
sessionID: session.id,
1217-
auto: false,
1218-
}),
1219-
),
1220-
)
1178+
yield* createSummaryCompaction(session.id)
12211179

1222-
const part = await lastCompactionPart(session.id)
1223-
expect(part?.type).toBe("compaction")
1224-
expect(part?.tail_start_id).toBe(keep.id)
1225-
expect(captured).toContain("zzzz")
1226-
expect(captured).not.toContain("keep tail")
1180+
const msgs = yield* ssn.messages({ sessionID: session.id })
1181+
const parent = msgs.at(-1)?.info.id
1182+
expect(parent).toBeTruthy()
1183+
yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
12271184

1228-
const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
1229-
expect(filtered.map((msg) => msg.info.id).slice(0, 3)).toEqual([parent!, expect.any(String), keep.id])
1230-
expect(filtered[1]?.info.role).toBe("assistant")
1231-
expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true)
1232-
expect(filtered.map((msg) => msg.info.id)).not.toContain(large.id)
1233-
} finally {
1234-
await rt.dispose()
1235-
}
1236-
},
1237-
})
1238-
})
1185+
const part = yield* readCompactionPart(session.id)
1186+
expect(part?.type).toBe("compaction")
1187+
expect(part?.tail_start_id).toBe(keep.id)
1188+
expect(captured).toContain("zzzz")
1189+
expect(captured).not.toContain("keep tail")
1190+
1191+
const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
1192+
expect(filtered.map((msg) => msg.info.id).slice(0, 3)).toEqual([parent!, expect.any(String), keep.id])
1193+
expect(filtered[1]?.info.role).toBe("assistant")
1194+
expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true)
1195+
expect(filtered.map((msg) => msg.info.id)).not.toContain(large.id)
1196+
}).pipe(
1197+
Effect.provide(
1198+
compactionProcessLayer({ llm: stub.layer, config: cfg({ tail_turns: 1, preserve_recent_tokens: 100 }) }),
1199+
),
1200+
)
1201+
},
1202+
{ git: true },
1203+
)
12391204

12401205
test("allows plugins to disable synthetic continue prompt", async () => {
12411206
await using tmp = await tmpdir()

0 commit comments

Comments
 (0)