fix(coding-agent): avoid retrying successful overflow compaction
closes #5720
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed successful overflow-triggered auto-compaction to avoid retrying completed assistant responses ([#5720](https://github.com/earendil-works/pi/issues/5720)).
|
||||||
|
|
||||||
## [0.79.7] - 2026-06-18
|
## [0.79.7] - 2026-06-18
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|||||||
@@ -1824,8 +1824,17 @@ export class AgentSession {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case 1: Overflow - LLM returned context overflow error
|
// Case 1: Overflow - LLM returned context overflow error, or reported usage exceeded
|
||||||
|
// the configured window. A successful response over the configured window should compact
|
||||||
|
// but must not retry: the assistant answer already completed and agent.continue() cannot
|
||||||
|
// continue from an assistant message.
|
||||||
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
||||||
|
const willRetry = assistantMessage.stopReason !== "stop";
|
||||||
|
|
||||||
|
if (!willRetry) {
|
||||||
|
return await this._runAutoCompaction("overflow", false);
|
||||||
|
}
|
||||||
|
|
||||||
if (this._overflowRecoveryAttempted) {
|
if (this._overflowRecoveryAttempted) {
|
||||||
this._emit({
|
this._emit({
|
||||||
type: "compaction_end",
|
type: "compaction_end",
|
||||||
@@ -1846,7 +1855,7 @@ export class AgentSession {
|
|||||||
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
||||||
this.agent.state.messages = messages.slice(0, -1);
|
this.agent.state.messages = messages.slice(0, -1);
|
||||||
}
|
}
|
||||||
return await this._runAutoCompaction("overflow", true);
|
return await this._runAutoCompaction("overflow", willRetry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case 2: Threshold - context is getting large
|
// Case 2: Threshold - context is getting large
|
||||||
|
|||||||
@@ -248,6 +248,37 @@ describe("AgentSession compaction characterization", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("compacts successful overflow responses without retrying", async () => {
|
||||||
|
const harness = await createHarness({
|
||||||
|
settings: { compaction: { enabled: true, keepRecentTokens: 1, reserveTokens: 0 } },
|
||||||
|
models: [{ id: "faux-1", contextWindow: 1, maxTokens: 100 }],
|
||||||
|
extensionFactories: [
|
||||||
|
(pi) => {
|
||||||
|
pi.on("session_before_compact", async (event) => ({
|
||||||
|
compaction: {
|
||||||
|
summary: "successful overflow compacted",
|
||||||
|
firstKeptEntryId: event.preparation.firstKeptEntryId,
|
||||||
|
tokensBefore: event.preparation.tokensBefore,
|
||||||
|
details: {},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
harnesses.push(harness);
|
||||||
|
harness.setResponses([fauxAssistantMessage("completed answer")]);
|
||||||
|
|
||||||
|
await expect(harness.session.prompt("hello")).resolves.toBeUndefined();
|
||||||
|
|
||||||
|
const compactionEnd = harness.eventsOfType("compaction_end").at(-1);
|
||||||
|
expect(compactionEnd).toMatchObject({
|
||||||
|
reason: "overflow",
|
||||||
|
aborted: false,
|
||||||
|
willRetry: false,
|
||||||
|
});
|
||||||
|
expect(harness.faux.state.callCount).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("ignores stale pre-compaction assistant usage on pre-prompt checks", async () => {
|
it("ignores stale pre-compaction assistant usage on pre-prompt checks", async () => {
|
||||||
const harness = await createHarness();
|
const harness = await createHarness();
|
||||||
harnesses.push(harness);
|
harnesses.push(harness);
|
||||||
|
|||||||
Reference in New Issue
Block a user