Merge pull request #3236 from code-yeongyu/fix/compaction-failure-toast

fix(preemptive-compaction): notify user on failure and reduce timeout
This commit is contained in:
YeonGyu-Kim
2026-04-08 20:15:09 +09:00
committed by GitHub
2 changed files with 69 additions and 2 deletions
+49
View File
@@ -284,10 +284,57 @@ describe("preemptive-compaction", () => {
//#then
expect(logMock).toHaveBeenCalledWith("[preemptive-compaction] Compaction failed", {
sessionID,
providerID: "anthropic",
modelID: "claude-sonnet-4-6",
error: String(summarizeError),
})
})
// #given compaction fails
// #when tool.execute.after completes the catch block
// #then should show a warning toast explaining the failure to the user
it("should show a warning toast when preemptive compaction fails", async () => {
//#given
const hook = createPreemptiveCompactionHook(ctx as never, {} as never)
const sessionID = "ses_toast_on_failure"
const summarizeError = new Error("upstream rate limited")
ctx.client.session.summarize.mockRejectedValueOnce(summarizeError)
await hook.event({
event: {
type: "message.updated",
properties: {
info: {
role: "assistant",
sessionID,
providerID: "anthropic",
modelID: "claude-sonnet-4-6",
finish: true,
tokens: {
input: 170000,
output: 0,
reasoning: 0,
cache: { read: 10000, write: 0 },
},
},
},
},
})
//#when
await hook["tool.execute.after"](
{ tool: "bash", sessionID, callID: "call_toast" },
{ title: "", output: "test", metadata: null },
)
//#then
expect(ctx.client.tui.showToast).toHaveBeenCalledTimes(1)
const toastCall = ctx.client.tui.showToast.mock.calls[0]?.[0]
expect(toastCall?.body?.title).toBe("Preemptive compaction failed")
expect(toastCall?.body?.variant).toBe("warning")
expect(String(toastCall?.body?.message)).toContain("upstream rate limited")
})
// #given compaction fails
// #when tool.execute.after is called again immediately
// #then should NOT retry due to cooldown
@@ -475,6 +522,8 @@ describe("preemptive-compaction", () => {
expect(ctx.client.session.summarize).toHaveBeenCalledTimes(1)
expect(logMock).toHaveBeenCalledWith("[preemptive-compaction] Compaction failed", {
sessionID,
providerID: "anthropic",
modelID: "claude-sonnet-4-6",
error: expect.stringContaining("Compaction summarize timed out"),
})
+20 -2
View File
@@ -8,7 +8,7 @@ import {
import { resolveCompactionModel } from "./shared/compaction-model-resolver"
import { createPostCompactionDegradationMonitor } from "./preemptive-compaction-degradation-monitor"
const PREEMPTIVE_COMPACTION_TIMEOUT_MS = 120_000
const PREEMPTIVE_COMPACTION_TIMEOUT_MS = 60_000
const PREEMPTIVE_COMPACTION_THRESHOLD = 0.78
const PREEMPTIVE_COMPACTION_COOLDOWN_MS = 60_000
@@ -134,7 +134,25 @@ export function createPreemptiveCompactionHook(
compactedSessions.add(sessionID)
} catch (error) {
log("[preemptive-compaction] Compaction failed", { sessionID, error: String(error) })
log("[preemptive-compaction] Compaction failed", {
sessionID,
providerID: cached.providerID,
modelID: cached.modelID,
error: String(error),
})
ctx.client.tui.showToast({
body: {
title: "Preemptive compaction failed",
message: `Context window is above ${Math.round(PREEMPTIVE_COMPACTION_THRESHOLD * 100)}% and auto-compaction could not run. The session may grow large. Error: ${String(error)}`,
variant: "warning",
duration: 10000,
},
}).catch((toastError: unknown) => {
log("[preemptive-compaction] Failed to show toast", {
sessionID,
toastError: String(toastError),
})
})
} finally {
compactionInProgress.delete(sessionID)
}