Skip to content

Commit f228c71

Browse files
siripr4claude
andcommitted
fix(session): make SessionConfig.compaction match runtime; close #158
Align the public SessionConfig.compaction type and docstring with how compaction actually behaves. The wiring itself (maybeCompact settings parameter + Session.#runCompaction passthrough) already landed; this finishes the remaining items from #158: - Widen the public type to Partial<CompactionSettings> so { enabled: false } and single-field overrides type-check. The stored config (session.config.compaction) is also Partial, so the shapes now match. - Rewrite the docstring: compaction is on by default, opt out with { enabled: false }, individual fields fall back to built-in defaults. - Add a Session-level integration test asserting enabled: false actually suppresses compaction when the threshold is crossed. - Restore the tunable-knobs example in the configuration guide, with both opt-out and threshold-override patterns plus when-it-fires notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5f5de7b commit f228c71

3 files changed

Lines changed: 56 additions & 3 deletions

File tree

docs/src/content/docs/guides/configuration.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,32 @@ Thinking can also be overridden per `ask()` — see [API Keys and Providers](/me
196196

197197
### Context Compaction
198198

199-
When conversations grow long, megasthenes automatically summarizes older messages to stay within the model's context window. Compaction is enabled by default.
199+
When conversations grow long, megasthenes automatically summarizes older messages to stay within the model's context window. Compaction is enabled by default — set `compaction: { enabled: false }` to opt out, or override individual fields to tune when it fires. Any fields you leave unset fall back to the defaults shown below.
200+
201+
```ts
202+
// Opt out entirely
203+
await client.connect({
204+
repo: { url: "https://github.com/owner/repo" },
205+
model: { provider: "anthropic", id: "claude-sonnet-4-6" },
206+
maxIterations: 20,
207+
compaction: { enabled: false },
208+
});
209+
210+
// Tune the thresholds (e.g. for a 1M-context model)
211+
await client.connect({
212+
repo: { url: "https://github.com/owner/repo" },
213+
model: { provider: "anthropic", id: "claude-sonnet-4-6" },
214+
maxIterations: 20,
215+
compaction: {
216+
enabled: true, // default: true
217+
contextWindow: 1_000_000, // default: 200_000 — total usable context
218+
reserveTokens: 16_384, // default: 16_384 — tokens held back for the response
219+
keepRecentTokens: 20_000, // default: 20_000 — recent messages kept unsummarized
220+
},
221+
});
222+
```
223+
224+
Compaction fires when estimated context tokens exceed `contextWindow - reserveTokens`. The most recent messages totalling roughly `keepRecentTokens` are retained verbatim; everything before that is replaced with an LLM-generated summary. See the [`compaction` event in Handling Responses](/megasthenes/guides/handling-responses/) for how to observe it at runtime.
200225

201226
### Tracing
202227

src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,14 @@ export interface SessionConfig {
8585
maxIterations: number;
8686
/** Thinking/reasoning configuration. If omitted, thinking is off. */
8787
thinking?: ThinkingConfig;
88-
/** Context compaction settings. If omitted, compaction is off. */
89-
compaction?: CompactionSettings;
88+
/**
89+
* Context compaction settings. Compaction is on by default — pass
90+
* `{ enabled: false }` to opt out, or override individual fields
91+
* (`contextWindow`, `reserveTokens`, `keepRecentTokens`) to tune when
92+
* compaction fires. Unset fields fall back to built-in defaults
93+
* (200K context window, 16K reserve, 20K recent-keep).
94+
*/
95+
compaction?: Partial<CompactionSettings>;
9096
/** Prior turns to seed the session with. Restores LLM context from previous conversation. */
9197
initialTurns?: TurnResult[];
9298
/** Last compaction summary from a prior session. Required for compaction continuity when restoring with initialTurns. */

test/compaction.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,4 +592,26 @@ describe("Session compaction integration", () => {
592592

593593
expect(events.find((e) => e.type === "compaction")).toBeDefined();
594594
});
595+
596+
test("config.compaction.enabled=false suppresses compaction even when the threshold is crossed", async () => {
597+
// Same threshold-crushing settings as the trigger-compaction test above —
598+
// if `enabled: false` weren't threaded through, this would compact.
599+
const session = new Session(createMockRepo(), {
600+
model: {} as Model<Api>,
601+
systemPrompt: "You are a test assistant",
602+
tools: [],
603+
maxIterations: 5,
604+
executeTool: async () => "mock",
605+
logger: nullLogger,
606+
stream: createSessionMockStream(),
607+
compaction: { enabled: false, contextWindow: 0, reserveTokens: 0, keepRecentTokens: 1 },
608+
});
609+
610+
const events: StreamEvent[] = [];
611+
for await (const ev of session.ask("anything")) {
612+
events.push(ev);
613+
}
614+
615+
expect(events.find((e) => e.type === "compaction")).toBeUndefined();
616+
});
595617
});

0 commit comments

Comments
 (0)