From 88060ae98cc49178cd933c078691adcd3f0fda77 Mon Sep 17 00:00:00 2001 From: ryanwyler Date: Tue, 30 Dec 2025 07:18:59 -0700 Subject: [PATCH] fix: resolve broken forked sessions with compactions due to missing parent-child message references When forking a session, message IDs are regenerated but parentID references in assistant messages were not updated to point to the new IDs. This broke features that rely on parent-child relationships, such as compaction breakpoints. ## Problem Forking a compacted session would fail with: ``` prompt is too long: 203573 tokens > 200000 maximum ``` The forked session didn't honor the compaction breakpoint because the parent-child message relationships were broken. ## Fix Added an ID mapping that tracks old ID -> new ID, then updates parentID references when cloning assistant messages. ## Changes - packages/opencode/src/session/index.ts - Add ID mapping in fork function to preserve parent-child relationships --- packages/opencode/src/session/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 4285223bc5c9..c64d569235d1 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -147,12 +147,19 @@ export namespace Session { directory: Instance.directory, }) const msgs = await messages({ sessionID: input.sessionID }) + const idMap = new Map() + for (const msg of msgs) { if (input.messageID && msg.info.id >= input.messageID) break + const newID = Identifier.ascending("message") + idMap.set(msg.info.id, newID) + + const parentID = msg.info.role === "assistant" && msg.info.parentID ? idMap.get(msg.info.parentID) : undefined const cloned = await updateMessage({ ...msg.info, sessionID: session.id, - id: Identifier.ascending("message"), + id: newID, + ...(parentID && { parentID }), }) for (const part of msg.parts) {