fix(coding-agent): stop overflow auto-compaction cascades

fixes #1319
This commit is contained in:
Mario Zechner 2026-03-03 17:19:42 +01:00
parent 7b96041068
commit 6b4b920425
2 changed files with 75 additions and 2 deletions

View file

@ -2,7 +2,7 @@ import { existsSync, mkdirSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Agent } from "@mariozechner/pi-agent-core";
import { getModel } from "@mariozechner/pi-ai";
import { type AssistantMessage, getModel } from "@mariozechner/pi-ai";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { AgentSession } from "../src/core/agent-session.js";
import { AuthStorage } from "../src/core/auth-storage.js";
@ -94,4 +94,58 @@ describe("AgentSession auto-compaction queue resume", () => {
expect(continueSpy).toHaveBeenCalledTimes(1);
});
it("should not compact repeatedly after overflow recovery already attempted", async () => {
const model = session.model!;
const overflowMessage: AssistantMessage = {
role: "assistant",
content: [{ type: "text", text: "" }],
api: model.api,
provider: model.provider,
model: model.id,
usage: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
totalTokens: 0,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
},
stopReason: "error",
errorMessage: "prompt is too long",
timestamp: Date.now(),
};
const runAutoCompactionSpy = vi
.spyOn(
session as unknown as {
_runAutoCompaction: (reason: "overflow" | "threshold", willRetry: boolean) => Promise<void>;
},
"_runAutoCompaction",
)
.mockResolvedValue();
const events: Array<{ type: string; errorMessage?: string }> = [];
session.subscribe((event) => {
if (event.type === "auto_compaction_end") {
events.push({ type: event.type, errorMessage: event.errorMessage });
}
});
const checkCompaction = (
session as unknown as {
_checkCompaction: (assistantMessage: AssistantMessage, skipAbortedCheck?: boolean) => Promise<void>;
}
)._checkCompaction.bind(session);
await checkCompaction(overflowMessage);
await checkCompaction({ ...overflowMessage, timestamp: Date.now() + 1 });
expect(runAutoCompactionSpy).toHaveBeenCalledTimes(1);
expect(events).toContainEqual({
type: "auto_compaction_end",
errorMessage:
"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
});
});
});