From c6c56ac2cfc3683d963ef33be18809165b25ca68 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:06:29 -0500 Subject: [PATCH] tweak: rename tail_tokens -> preserve_recent_tokens (#23491) --- packages/opencode/src/config/config.ts | 4 ++-- packages/opencode/src/session/compaction.ts | 15 +++++++++------ .../opencode/test/session/compaction.test.ts | 16 ++++++++-------- packages/sdk/js/src/v2/gen/types.gen.ts | 4 ++-- packages/sdk/openapi.json | 4 ++-- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 2b0c97eae9..55684fc70d 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -208,8 +208,8 @@ const InfoSchema = Schema.Struct({ description: "Number of recent user turns, including their following assistant/tool responses, to keep verbatim during compaction (default: 2)", }), - tail_tokens: Schema.optional(NonNegativeInt).annotate({ - description: "Token budget for retained recent turn spans during compaction", + preserve_recent_tokens: Schema.optional(NonNegativeInt).annotate({ + description: "Maximum number of tokens from recent turns to preserve verbatim after compaction", }), reserved: Schema.optional(NonNegativeInt).annotate({ description: "Token buffer for compaction. Leaves enough window to avoid overflow during compaction.", diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 8da6842397..b6d555afd5 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -34,18 +34,21 @@ export const PRUNE_MINIMUM = 20_000 export const PRUNE_PROTECT = 40_000 const PRUNE_PROTECTED_TOOLS = ["skill"] const DEFAULT_TAIL_TURNS = 2 -const MIN_TAIL_TOKENS = 2_000 -const MAX_TAIL_TOKENS = 8_000 +const MIN_PRESERVE_RECENT_TOKENS = 2_000 +const MAX_PRESERVE_RECENT_TOKENS = 8_000 type Turn = { start: number end: number id: MessageID } -function tailBudget(input: { cfg: Config.Info; model: Provider.Model }) { +function preserveRecentBudget(input: { cfg: Config.Info; model: Provider.Model }) { return ( - input.cfg.compaction?.tail_tokens ?? - Math.min(MAX_TAIL_TOKENS, Math.max(MIN_TAIL_TOKENS, Math.floor(usable(input) * 0.25))) + input.cfg.compaction?.preserve_recent_tokens ?? + Math.min( + MAX_PRESERVE_RECENT_TOKENS, + Math.max(MIN_PRESERVE_RECENT_TOKENS, Math.floor(usable(input) * 0.25)), + ) ) } @@ -134,7 +137,7 @@ export const layer: Layer.Layer< }) { const limit = input.cfg.compaction?.tail_turns ?? DEFAULT_TAIL_TURNS if (limit <= 0) return { head: input.messages, tail_start_id: undefined } - const budget = tailBudget({ cfg: input.cfg, model: input.model }) + const budget = preserveRecentBudget({ cfg: input.cfg, model: input.model }) const all = turns(input.messages) if (!all.length) return { head: input.messages, tail_start_id: undefined } const recent = all.slice(-limit) diff --git a/packages/opencode/test/session/compaction.test.ts b/packages/opencode/test/session/compaction.test.ts index ef5fb5db03..96c8e4ae8b 100644 --- a/packages/opencode/test/session/compaction.test.ts +++ b/packages/opencode/test/session/compaction.test.ts @@ -925,7 +925,7 @@ describe("session.compaction.process", () => { auto: false, }) - const rt = runtime("continue", Plugin.defaultLayer, wide(), cfg({ tail_turns: 2, tail_tokens: 10_000 })) + const rt = runtime("continue", Plugin.defaultLayer, wide(), cfg({ tail_turns: 2, preserve_recent_tokens: 10_000 })) try { const msgs = await svc.messages({ sessionID: session.id }) const parent = msgs.at(-1)?.info.id @@ -954,7 +954,7 @@ describe("session.compaction.process", () => { }) }) - test("shrinks retained tail to fit tail token budget", async () => { + test("shrinks retained tail to fit preserve token budget", async () => { await using tmp = await tmpdir() await Instance.provide({ directory: tmp.path, @@ -970,7 +970,7 @@ describe("session.compaction.process", () => { auto: false, }) - const rt = runtime("continue", Plugin.defaultLayer, wide(), cfg({ tail_turns: 2, tail_tokens: 100 })) + const rt = runtime("continue", Plugin.defaultLayer, wide(), cfg({ tail_turns: 2, preserve_recent_tokens: 100 })) try { const msgs = await svc.messages({ sessionID: session.id }) const parent = msgs.at(-1)?.info.id @@ -999,7 +999,7 @@ describe("session.compaction.process", () => { }) }) - test("falls back to full summary when even one recent turn exceeds tail budget", async () => { + test("falls back to full summary when even one recent turn exceeds preserve token budget", async () => { await using tmp = await tmpdir({ git: true }) const stub = llm() let captured = "" @@ -1021,7 +1021,7 @@ describe("session.compaction.process", () => { auto: false, }) - const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, tail_tokens: 20 })) + const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 20 })) try { const msgs = await svc.messages({ sessionID: session.id }) const parent = msgs.at(-1)?.info.id @@ -1051,7 +1051,7 @@ describe("session.compaction.process", () => { }) }) - test("falls back to full summary when retained tail media exceeds tail budget", async () => { + test("falls back to full summary when retained tail media exceeds preserve token budget", async () => { await using tmp = await tmpdir({ git: true }) const stub = llm() let captured = "" @@ -1082,7 +1082,7 @@ describe("session.compaction.process", () => { auto: false, }) - const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, tail_tokens: 100 })) + const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 1, preserve_recent_tokens: 100 })) try { const msgs = await svc.messages({ sessionID: session.id }) const parent = msgs.at(-1)?.info.id @@ -1544,7 +1544,7 @@ describe("session.compaction.process", () => { auto: false, }) - const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 2, tail_tokens: 10_000 })) + const rt = liveRuntime(stub.layer, wide(), cfg({ tail_turns: 2, preserve_recent_tokens: 10_000 })) try { let msgs = await svc.messages({ sessionID: session.id }) let parent = msgs.at(-1)?.info.id diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index e1b0dbd576..d14fab1919 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1648,9 +1648,9 @@ export type Config = { */ tail_turns?: number /** - * Token budget for retained recent turn spans during compaction + * Maximum number of tokens from recent turns to preserve verbatim after compaction */ - tail_tokens?: number + preserve_recent_tokens?: number /** * Token buffer for compaction. Leaves enough window to avoid overflow during compaction. */ diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 3ecb725d6d..dbd85874fc 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -11878,8 +11878,8 @@ "minimum": 0, "maximum": 9007199254740991 }, - "tail_tokens": { - "description": "Token budget for retained recent turn spans during compaction", + "preserve_recent_tokens": { + "description": "Maximum number of tokens from recent turns to preserve verbatim after compaction", "type": "integer", "minimum": 0, "maximum": 9007199254740991