From 469dc9095f9446108f88cc6b54156af6cd937a45 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 12 Sep 2025 06:33:59 -0400 Subject: [PATCH] add microcompact --- packages/opencode/src/session/index.ts | 47 ++++++++++----------- packages/opencode/src/session/message-v2.ts | 3 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index cdbecbb4..8f8f42e0 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -84,12 +84,6 @@ export namespace Session { .optional(), title: z.string(), version: z.string(), - compaction: z - .object({ - full: z.string().optional(), - micro: z.string().optional(), - }) - .optional(), time: z.object({ created: z.number(), updated: z.number(), @@ -726,12 +720,7 @@ export namespace Session { return Provider.defaultModel() })().then((x) => Provider.getModel(x.providerID, x.modelID)) - let msgs = await messages(input.sessionID) - const lastSummary = Math.max( - 0, - msgs.findLastIndex((msg) => msg.info.role === "assistant" && msg.info.summary === true), - ) - msgs = msgs.slice(lastSummary) + let msgs = await messages(input.sessionID).then((x) => sinceSummary(x)) const lastAssistant = msgs.findLast((msg) => msg.info.role === "assistant") if ( @@ -1001,9 +990,6 @@ export namespace Session { }) }, async prepareStep({ messages, steps }) { - log.info("search", { - length: messages.length, - }) const step = steps.at(-1) if ( step && @@ -1130,6 +1116,7 @@ export namespace Session { item.callback(result) } state().queued.delete(input.sessionID) + Session.microcompact(input) return result } @@ -1814,13 +1801,7 @@ export namespace Session { draft.time.compacting = undefined }) }) - const msgs = await messages(input.sessionID) - const start = Math.max( - 0, - msgs.findLastIndex((msg) => msg.info.role === "assistant" && msg.info.summary === true), - ) - log.info("summarizing", { start }) - const toSummarize = msgs.slice(start) + const toSummarize = await messages(input.sessionID).then((x) => sinceSummary(x)) const model = await Provider.getModel(input.providerID, input.modelID) const system = [ ...SystemPrompt.summarize(model.providerID), @@ -1901,24 +1882,42 @@ export namespace Session { } } + function sinceSummary(msgs: { info: MessageV2.Info; parts: MessageV2.Part[] }[]) { + const result = [] + for (let i = msgs.length - 1; i >= 0; i--) { + const msg = msgs[i] + result.push(msg) + if (msg.info.role === "assistant" && msg.info.summary) break + } + return result.toReversed() + } + function needsCompaction(input: { tokens: MessageV2.Assistant["tokens"]; model: ModelsDev.Model }) { const count = input.tokens.input + input.tokens.cache.read + input.tokens.output const output = Math.min(input.model.limit.output, OUTPUT_TOKEN_MAX) || OUTPUT_TOKEN_MAX const usable = input.model.limit.context - output - return count > usable / 2 + return count > usable } export async function microcompact(input: { sessionID: string }) { const msgs = await messages(input.sessionID) let sum = 0 - for (let msgIndex = msgs.length - 1; msgIndex >= 0; msgIndex--) { + for (let msgIndex = msgs.length - 2; msgIndex >= 0; msgIndex--) { const msg = msgs[msgIndex] + if (msg.info.role === "assistant" && msg.info.summary) return for (let partIndex = msg.parts.length - 1; partIndex >= 0; partIndex--) { const part = msg.parts[partIndex] if (part.type === "tool") if (part.state.status === "completed") { + if (part.state.time.compacted) return sum += Token.estimate(part.state.output) if (sum > 40_000) { + log.info("microcompacting", { + sum, + id: part.id, + }) + part.state.time.compacted = Date.now() + await updatePart(part) } } } diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index fd14afbd..3102a611 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -52,6 +52,7 @@ export namespace MessageV2 { time: z.object({ start: z.number(), end: z.number(), + compacted: z.number().optional(), }), }) .openapi({ @@ -528,7 +529,7 @@ export namespace MessageV2 { state: "output-available", toolCallId: part.callID, input: part.state.input, - output: part.state.output, + output: part.state.time.compacted ? "[Old tool result content cleared]" : part.state.output, }, ] if (part.state.status === "error")