Make compaction bounded and report it once per turn

The fixed three-message tool window collapsed long transcripts to a handful of messages: a 405-message run kept two of 202 tool calls, and the model re-ran what it could no longer see. Pruning now drops reasoning first and keeps the widest recent tool tail that fits a ladder, the SDK carries that view into later steps, and the turn emits one compaction event instead of one per step.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Muhammad Zakir Ramadhan
2026-09-03 16:42:02 +07:00
co-authored by Sisyphus
parent 9e03512cb0
commit 83f4399e64
4 changed files with 227 additions and 9 deletions
+24
View File
@@ -252,6 +252,30 @@ test('a compacted turn still shows the model the tool calls it already made', as
}
}), 20_000);
test('a multi-step turn emits one compacted event', async () =>
inTempDir(async () => {
await Bun.write(join(process.cwd(), 'big.txt'), 'lorem ipsum dolor sit amet\n'.repeat(1500));
let call = 0;
const session = new Session({
compactThreshold: 4000,
maxSteps: 8,
model: new MockLanguageModelV4({
doStream: async () => {
const n = call++;
return n < 3 ? stream(reasoningToolStep(n)) : stream(text('done'));
},
}),
askApproval: async () => 'deny',
});
const events: AgentEvent[] = [];
for await (const ev of session.send('read big.txt a few times')) events.push(ev);
expect(events.filter((ev) => ev.type === 'compacted')).toHaveLength(1);
expect(call).toBe(4);
}), 20_000);
test('a compacted turn sends no assistant item reference whose reasoning was pruned', async () =>
inTempDir(async () => {
await Bun.write(join(process.cwd(), 'big.txt'), 'lorem ipsum dolor sit amet\n'.repeat(1500));