fix(coding-agent): clarify truncated recovery failure

closes #8130
This commit is contained in:
Vegard Stikbakke 2026-08-17 11:03:07 +02:00
parent 86d001d36b
commit c7c763f5c4
3 changed files with 35 additions and 3 deletions

View file

@ -6,6 +6,7 @@
- Fixed `pi.registerFlag()` accepting default values that do not match the declared flag type ([#8064](https://github.com/earendil-works/pi/issues/8064)).
- Fixed Z.AI Coding Plan defaults referencing the removed GLM-5.1 model ([#8096](https://github.com/earendil-works/pi/issues/8096)).
- Fixed repeated ambiguous truncated-response recovery being mislabeled as context overflow ([#8130](https://github.com/earendil-works/pi/issues/8130)).
## [0.84.2] - 2026-08-14

View file

@ -2008,8 +2008,9 @@ export class AgentSession {
// Automatic cases 1 and 2: context overflow.
// A length stop is recoverable when output ended below the model's original desired limit,
// independent of the configured context size or any context-clamped provider request limit.
const contextOverflow = sameModel && isContextOverflow(assistantMessage, contextWindow);
const recoverableLength = sameModel && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
if (sameModel && (isContextOverflow(assistantMessage, contextWindow) || recoverableLength)) {
if (contextOverflow || recoverableLength) {
const willRetry = assistantMessage.stopReason !== "stop";
// Case 2: the response completed successfully. Compact, but do not retry because
@ -2019,14 +2020,16 @@ export class AgentSession {
}
if (this._overflowRecoveryAttempted) {
const errorMessage = contextOverflow
? "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model."
: "Truncated response recovery failed after one compact-and-retry attempt.";
this._emit({
type: "compaction_end",
reason: "overflow",
result: undefined,
aborted: false,
willRetry: false,
errorMessage:
"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
errorMessage,
});
return false;
}

View file

@ -353,6 +353,34 @@ describe("AgentSession compaction characterization", () => {
expect(harness.faux.state.callCount).toBe(2);
expect(harness.eventsOfType("compaction_start").filter((event) => event.reason === "overflow")).toHaveLength(1);
expect(harness.eventsOfType("compaction_end").at(-1)?.errorMessage).toBe(
"Truncated response recovery failed after one compact-and-retry attempt.",
);
});
it("keeps overflow wording when a repeated length stop fills the context window", async () => {
const harness = await createHarness({
models: [{ id: "faux-1", contextWindow: 100, maxTokens: 100 }],
});
harnesses.push(harness);
const sessionInternals = harness.session as unknown as SessionWithCompactionInternals;
const lengthOverflowMessage = createAssistant(harness, {
stopReason: "length",
totalTokens: 100,
timestamp: Date.now(),
});
const runAutoCompactionSpy = vi.spyOn(sessionInternals, "_runAutoCompaction").mockResolvedValue(false);
const compactionErrors: string[] = [];
harness.session.subscribe((event) => {
if (event.type === "compaction_end" && event.errorMessage) {
compactionErrors.push(event.errorMessage);
}
});
await sessionInternals._checkCompaction(lengthOverflowMessage);
await sessionInternals._checkCompaction({ ...lengthOverflowMessage, timestamp: Date.now() + 1 });
expect(runAutoCompactionSpy).toHaveBeenCalledTimes(1);
expect(compactionErrors).toContain(
"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
);
});