Migrate LLM compaction tail tests (#26734)

This commit is contained in:
Kit Langton
2026-05-10 19:41:28 -04:00
committed by GitHub
parent 8f5f75db12
commit ca8a42c973

View File

@@ -1106,22 +1106,18 @@ describe("session.compaction.process", () => {
{ git: true }, { git: true },
) )
test("falls back to full summary when retained tail media exceeds preserve token budget", async () => { itProcess.instance(
await using tmp = await tmpdir({ git: true }) "falls back to full summary when retained tail media exceeds preserve token budget",
const stub = llm() () => {
let captured = "" const stub = llm()
stub.push( let captured = ""
reply("summary", (input) => { stub.push(reply("summary", (input) => (captured = JSON.stringify(input.messages))))
captured = JSON.stringify(input.messages) return Effect.gen(function* () {
}), const ssn = yield* SessionNs.Service
) const session = yield* ssn.create({})
await WithInstance.provide({ yield* createUserMessage(session.id, "older")
directory: tmp.path, const recent = yield* createUserMessage(session.id, "recent image turn")
fn: async () => { yield* ssn.updatePart({
const session = await svc.create({})
await user(session.id, "older")
const recent = await user(session.id, "recent image turn")
await svc.updatePart({
id: PartID.ascending(), id: PartID.ascending(),
messageID: recent.id, messageID: recent.id,
sessionID: session.id, sessionID: session.id,
@@ -1130,112 +1126,81 @@ describe("session.compaction.process", () => {
filename: "big.png", filename: "big.png",
url: `data:image/png;base64,${"a".repeat(4_000)}`, url: `data:image/png;base64,${"a".repeat(4_000)}`,
}) })
await SessionCompaction.create({ yield* createSummaryCompaction(session.id)
sessionID: session.id,
agent: "build",
model: ref,
auto: false,
})
const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 100 })) const msgs = yield* ssn.messages({ sessionID: session.id })
try { const parent = msgs.at(-1)?.info.id
const msgs = await svc.messages({ sessionID: session.id }) expect(parent).toBeTruthy()
const parent = msgs.at(-1)?.info.id yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
expect(parent).toBeTruthy()
await rt.runPromise(
SessionCompaction.Service.use((svc) =>
svc.process({
parentID: parent!,
messages: msgs,
sessionID: session.id,
auto: false,
}),
),
)
const part = await lastCompactionPart(session.id) const part = yield* readCompactionPart(session.id)
expect(part?.type).toBe("compaction") expect(part?.type).toBe("compaction")
expect(part?.tail_start_id).toBeUndefined() expect(part?.tail_start_id).toBeUndefined()
expect(captured).toContain("recent image turn") expect(captured).toContain("recent image turn")
expect(captured).toContain("Attached image/png: big.png") expect(captured).toContain("Attached image/png: big.png")
} finally { }).pipe(
await rt.dispose() Effect.provide(
} compactionProcessLayer({ llm: stub.layer, config: cfg({ tail_turns: 1, preserve_recent_tokens: 100 }) }),
}, ),
}) )
}) },
{ git: true },
)
test("retains a split turn suffix when a later message fits the preserve token budget", async () => { itProcess.instance(
await using tmp = await tmpdir({ git: true }) "retains a split turn suffix when a later message fits the preserve token budget",
const stub = llm() () => {
let captured = "" const stub = llm()
stub.push( let captured = ""
reply("summary", (input) => { stub.push(reply("summary", (input) => (captured = JSON.stringify(input.messages))))
captured = JSON.stringify(input.messages) return Effect.gen(function* () {
}), const test = yield* TestInstance
) const ssn = yield* SessionNs.Service
await WithInstance.provide({ const session = yield* ssn.create({})
directory: tmp.path, yield* createUserMessage(session.id, "older")
fn: async () => { const recent = yield* createUserMessage(session.id, "recent turn")
const session = await svc.create({}) const large = yield* createAssistantMessage(session.id, recent.id, test.directory)
await user(session.id, "older") yield* ssn.updatePart({
const recent = await user(session.id, "recent turn")
const large = await assistant(session.id, recent.id, tmp.path)
await svc.updatePart({
id: PartID.ascending(), id: PartID.ascending(),
messageID: large.id, messageID: large.id,
sessionID: session.id, sessionID: session.id,
type: "text", type: "text",
text: "z".repeat(2_000), text: "z".repeat(2_000),
}) })
const keep = await assistant(session.id, recent.id, tmp.path) const keep = yield* createAssistantMessage(session.id, recent.id, test.directory)
await svc.updatePart({ yield* ssn.updatePart({
id: PartID.ascending(), id: PartID.ascending(),
messageID: keep.id, messageID: keep.id,
sessionID: session.id, sessionID: session.id,
type: "text", type: "text",
text: "keep tail", text: "keep tail",
}) })
await SessionCompaction.create({ yield* createSummaryCompaction(session.id)
sessionID: session.id,
agent: "build",
model: ref,
auto: false,
})
const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 100 })) const msgs = yield* ssn.messages({ sessionID: session.id })
try { const parent = msgs.at(-1)?.info.id
const msgs = await svc.messages({ sessionID: session.id }) expect(parent).toBeTruthy()
const parent = msgs.at(-1)?.info.id yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
expect(parent).toBeTruthy()
await rt.runPromise(
SessionCompaction.Service.use((svc) =>
svc.process({
parentID: parent!,
messages: msgs,
sessionID: session.id,
auto: false,
}),
),
)
const part = await lastCompactionPart(session.id) const part = yield* readCompactionPart(session.id)
expect(part?.type).toBe("compaction") expect(part?.type).toBe("compaction")
expect(part?.tail_start_id).toBe(keep.id) expect(part?.tail_start_id).toBe(keep.id)
expect(captured).toContain("zzzz") expect(captured).toContain("zzzz")
expect(captured).not.toContain("keep tail") expect(captured).not.toContain("keep tail")
const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id)) const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
expect(filtered.map((msg) => msg.info.id).slice(0, 3)).toEqual([parent!, expect.any(String), 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).toBe("assistant")
expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true) expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true)
expect(filtered.map((msg) => msg.info.id)).not.toContain(large.id) expect(filtered.map((msg) => msg.info.id)).not.toContain(large.id)
} finally { }).pipe(
await rt.dispose() Effect.provide(
} compactionProcessLayer({ llm: stub.layer, config: cfg({ tail_turns: 1, preserve_recent_tokens: 100 }) }),
}, ),
}) )
}) },
{ git: true },
)
test("allows plugins to disable synthetic continue prompt", async () => { test("allows plugins to disable synthetic continue prompt", async () => {
await using tmp = await tmpdir() await using tmp = await tmpdir()