From 4ab22439905e3872369847158821f97d3e4295a2 Mon Sep 17 00:00:00 2001 From: shrijit-ctrl Date: Tue, 26 May 2026 11:47:37 +0530 Subject: [PATCH] fix(compaction): make compaction limits configurable and improve prompt detail retention - Add tool_output_max_chars config: controls how much tool output text the compaction model sees. Default 2000, can be raised to e.g. 16000. - Add summary_template config: custom Markdown template replacing the hardcoded template. Lets users tailor sections to their workflow. - Add model config: route compaction to a specific model (e.g. 'anthropic/claude-opus-4') separate from the session model. - Add preserve_recent_tokens_max config: upper bound for tokens kept verbatim from recent turns. Default raised from 8000 to 32000. - Revise compaction system prompt to emphasize preserving exact error messages, file paths, command outputs, identifiers, and user preferences over terse bullets. Closes #25746 Refs #21478, #20246, #16333, #13946 --- .../opencode/src/agent/prompt/compaction.txt | 13 +++++- packages/opencode/src/config/config.ts | 16 ++++++++ packages/opencode/src/session/compaction.ts | 40 ++++++++++++++----- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/packages/opencode/src/agent/prompt/compaction.txt b/packages/opencode/src/agent/prompt/compaction.txt index c7cb838bbaa0..0e5034b995f1 100644 --- a/packages/opencode/src/agent/prompt/compaction.txt +++ b/packages/opencode/src/agent/prompt/compaction.txt @@ -4,6 +4,17 @@ Summarize only the conversation history you are given. The newest turns may be k If the prompt includes a block, treat it as the current anchored summary. Update it with the new history by preserving still-true details, removing stale details, and merging in new facts. -Always follow the exact output structure requested by the user prompt. Keep every section, preserve exact file paths and identifiers when known, and prefer terse bullets over paragraphs. +Always follow the exact output structure requested by the user prompt. Keep every section. + +CRITICAL — Preserve detail that matters for continuing work: +- Exact error messages, stack traces, and failure modes +- Exact file paths, line numbers, function and variable names +- Exact command outputs, return values, and data structures +- User preferences, specifications, style guidance, and constraints +- Architectural decisions and why alternatives were rejected +- Tool configurations, API endpoints, environment details +- Active todos, progress state, and workflow phase + +Prefer substantive detail over brevity. A few specific, accurate sentences are better than a terse bullet that loses meaning. When preserving a file path, error message, or identifier, include the exact text so the next agent can use it without guessing. Do not answer the conversation itself. Do not mention that you are summarizing, compacting, or merging context. Respond in the same language as the conversation. diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 545e48e64d9f..350a979d0480 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -266,9 +266,25 @@ export const Info = Schema.Struct({ preserve_recent_tokens: Schema.optional(NonNegativeInt).annotate({ description: "Maximum number of tokens from recent turns to preserve verbatim after compaction", }), + preserve_recent_tokens_max: Schema.optional(NonNegativeInt).annotate({ + description: + "Upper bound on tokens preserved verbatim from recent turns (default: 32000). Only used when preserve_recent_tokens is not set.", + }), reserved: Schema.optional(NonNegativeInt).annotate({ description: "Token buffer for compaction. Leaves enough window to avoid overflow during compaction.", }), + tool_output_max_chars: Schema.optional(PositiveInt).annotate({ + description: + "Max characters of tool output text to include when building compaction context (default: 2000). Increase for more detailed summaries.", + }), + summary_template: Schema.optional(Schema.String).annotate({ + description: + "Custom Markdown template for compaction summaries. Replaces the built-in template. Should include sections like Goal, Progress, Key Decisions, etc.", + }), + model: Schema.optional(Schema.String).annotate({ + description: + "Model ID override for compaction, e.g. 'anthropic/claude-opus-4'. Defaults to the session model.", + }), }), ), experimental: Schema.optional( diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index bc3327c07d42..942be9db943b 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -36,11 +36,11 @@ export const Event = { export const PRUNE_MINIMUM = 20_000 export const PRUNE_PROTECT = 40_000 -const TOOL_OUTPUT_MAX_CHARS = 2_000 +const DEFAULT_TOOL_OUTPUT_MAX_CHARS = 2_000 const PRUNE_PROTECTED_TOOLS = ["skill"] const DEFAULT_TAIL_TURNS = 2 const MIN_PRESERVE_RECENT_TOKENS = 2_000 -const MAX_PRESERVE_RECENT_TOKENS = 8_000 +const DEFAULT_MAX_PRESERVE_RECENT_TOKENS = 32_000 const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside