diff --git a/packages/coding-agent/src/core/compaction/changes.md b/packages/coding-agent/src/core/compaction/changes.md index f99eb8c2d2..83a658277a 100644 --- a/packages/coding-agent/src/core/compaction/changes.md +++ b/packages/coding-agent/src/core/compaction/changes.md @@ -222,8 +222,10 @@ - `stream-watchdog.ts`: `consumeStreamWithIdleTimeout()` accepts an optional `maxDurationMs` and throws the new `StreamDurationBudgetError` when one stream outlives it. The budget is a single absolute deadline for the whole stream, not a per-read timer, and it is cleared alongside the idle timer. Caller aborts still win over the budget. -- `DEFAULT_SUMMARIZATION_MAX_DURATION_MS` = 120s, applied by `compaction.ts` `completeSummarization()` and the - extension's `speculative.ts` request path. `retryAssistantCall` applies it per attempt. +- `DEFAULT_SUMMARIZATION_MAX_DURATION_MS` = 900s, applied by `compaction.ts` `completeSummarization()` and the + extension's `speculative.ts` request path. `retryAssistantCall` applies it per attempt. The 120s cap aborted + legitimate large-session summaries (observed: 257k tokens on Grok 4.6) while the stream was still live; idle + timeout (300s silence) still kills a hung connection. ### Why diff --git a/packages/coding-agent/src/core/compaction/stream-watchdog.ts b/packages/coding-agent/src/core/compaction/stream-watchdog.ts index 99cd78e7f6..d2c75fd735 100644 --- a/packages/coding-agent/src/core/compaction/stream-watchdog.ts +++ b/packages/coding-agent/src/core/compaction/stream-watchdog.ts @@ -38,12 +38,13 @@ export class StreamDurationBudgetError extends Error { export const DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS = 300_000; /** - * Total time one summarization attempt may hold the session. Well above healthy - * summarizations (tens of seconds) and below the idle budget, so a live-but-slow - * provider fails fast enough to keep the session interactive. Retries apply this - * budget per attempt. + * Total time one summarization attempt may hold the session. Large sessions + * (200k+ tokens) on slower models take minutes, not tens of seconds; 15 minutes + * still bounds a live-but-slow provider so the session is not stuck forever. + * Silence is a different class and stays on the 300s idle timeout. Retries apply + * this budget per attempt. */ -export const DEFAULT_SUMMARIZATION_MAX_DURATION_MS = 120_000; +export const DEFAULT_SUMMARIZATION_MAX_DURATION_MS = 900_000; export interface ConsumeStreamWithIdleTimeoutOptions { /** Silence budget per read; the timer resets on every event. */ diff --git a/packages/coding-agent/test/compaction/summarization-duration-constant.test.ts b/packages/coding-agent/test/compaction/summarization-duration-constant.test.ts new file mode 100644 index 0000000000..91744ca630 --- /dev/null +++ b/packages/coding-agent/test/compaction/summarization-duration-constant.test.ts @@ -0,0 +1,8 @@ +import { describe, expect, it } from "vitest"; +import { DEFAULT_SUMMARIZATION_MAX_DURATION_MS } from "../../src/core/compaction/stream-watchdog.ts"; + +describe("DEFAULT_SUMMARIZATION_MAX_DURATION_MS", () => { + it("gives large-session summarization 15 minutes", () => { + expect(DEFAULT_SUMMARIZATION_MAX_DURATION_MS).toBe(900_000); + }); +}); diff --git a/packages/coding-agent/test/compaction/summarization-wall-clock-budget.test.ts b/packages/coding-agent/test/compaction/summarization-wall-clock-budget.test.ts index b0ece0f465..de2c9587f9 100644 --- a/packages/coding-agent/test/compaction/summarization-wall-clock-budget.test.ts +++ b/packages/coding-agent/test/compaction/summarization-wall-clock-budget.test.ts @@ -125,6 +125,6 @@ describe("consumeStreamWithIdleTimeout wall-clock budget", () => { }); it("exposes a default wall-clock budget below the idle timeout", () => { - expect(DEFAULT_SUMMARIZATION_MAX_DURATION_MS).toBe(120_000); + expect(DEFAULT_SUMMARIZATION_MAX_DURATION_MS).toBe(900_000); }); });