diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 020e626cba8..6b21565794d 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1080,6 +1080,7 @@ export namespace Config { .optional() .describe("Tools that should only be available to primary agents."), continue_loop_on_deny: z.boolean().optional().describe("Continue the agent loop when a tool call is denied"), + context_compaction_threshold: z.number().min(10).max(100).optional().describe("Percentage of usable context space at which to trigger compaction (10-100)"), mcp_timeout: z .number() .int() diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index fb382530291..d1641762261 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -5,6 +5,8 @@ import { Identifier } from "../id/id" import { Instance } from "../project/instance" import { Provider } from "../provider/provider" import { MessageV2 } from "./message-v2" +import { Config } from "../config/config" +import { Flag } from "../flag/flag" import z from "zod" import { SessionPrompt } from "./prompt" import { Token } from "../util/token" @@ -13,7 +15,6 @@ import { SessionProcessor } from "./processor" import { fn } from "@/util/fn" import { Agent } from "@/agent/agent" import { Plugin } from "@/plugin" -import { Config } from "@/config/config" export namespace SessionCompaction { const log = Log.create({ service: "session.compaction" }) @@ -28,6 +29,7 @@ export namespace SessionCompaction { } export async function isOverflow(input: { tokens: MessageV2.Assistant["tokens"]; model: Provider.Model }) { + if (Flag.OPENCODE_DISABLE_AUTOCOMPACT) return false const config = await Config.get() if (config.compaction?.auto === false) return false const context = input.model.limit.context @@ -35,7 +37,14 @@ export namespace SessionCompaction { const count = input.tokens.input + input.tokens.cache.read + input.tokens.output const output = Math.min(input.model.limit.output, SessionPrompt.OUTPUT_TOKEN_MAX) || SessionPrompt.OUTPUT_TOKEN_MAX const usable = input.model.limit.input || context - output - return count > usable + + // Get configurable threshold (default 100% to maintain current behavior) + const threshold = config.experimental?.context_compaction_threshold ?? 100 + const thresholdMultiplier = threshold / 100 + const thresholdedUsable = usable * thresholdMultiplier + + log.debug("Checking overflow", { count, usable, thresholdedUsable, threshold }) + return count > thresholdedUsable } export const PRUNE_MINIMUM = 20_000