From f36a9eaf335d64a95456200140f77d7fa127aa62 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Sun, 7 Dec 2025 03:08:27 -0500 Subject: [PATCH 1/6] feat: Add /continue command for interrupted conversations - Remove /continue alias from /session command in autocomplete - Add new /continue command to continue interrupted conversations - Add server endpoint /session/:id/continue with logic to detect unfinished assistant messages - Add TUI command handler for session.continue with proper error handling - Regenerate JS SDK to include continue method - Add basic tests for continue functionality Resolves #5150 --- .../cmd/tui/component/prompt/autocomplete.tsx | 17 +++-- .../src/cli/cmd/tui/routes/session/index.tsx | 23 +++++++ packages/opencode/src/server/server.ts | 69 +++++++++++++++++++ .../opencode/test/session/session.test.ts | 18 +++++ packages/sdk/js/openapi.json | 55 +++++++++++++++ packages/sdk/js/src/gen/sdk.gen.ts | 13 ++++ packages/sdk/js/src/gen/types.gen.ts | 33 +++++++++ 7 files changed, 222 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index c397bc23c00..84a7f644df6 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -242,6 +242,11 @@ export function Autocomplete(props: { description: "toggle thinking visibility", onSelect: () => command.trigger("session.toggle.thinking"), }, + { + display: "/continue", + description: "continue interrupted conversation", + onSelect: () => command.trigger("session.continue"), + }, ) if (sync.data.config.share !== "disabled") { results.push({ @@ -270,12 +275,12 @@ export function Autocomplete(props: { description: "list agents", onSelect: () => command.trigger("agent.list"), }, - { - display: "/session", - aliases: ["/resume", "/continue"], - description: "list sessions", - onSelect: () => command.trigger("session.list"), - }, + { + display: "/session", + aliases: ["/resume"], + description: "list sessions", + onSelect: () => command.trigger("session.list"), + }, { display: "/status", aliases: ["/mcp"], diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index b28010ac665..e0cca8af19e 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -408,6 +408,29 @@ export function Session() { }) }, }, + { + title: "Continue interrupted conversation", + value: "session.continue", + keybind: "session_continue", + category: "Session", + onSelect: async (dialog) => { + const status = sync.data.session_status[route.sessionID] + if (status?.type !== "idle") await sdk.client.session.abort({ path: { id: route.sessionID } }).catch(() => {}) + + const result = await sdk.client.session.continue({ + path: { + id: route.sessionID, + }, + }) + + if (result.data) { + toBottom() + } else { + // Show message that there's nothing to continue + dialog.clear() + } + }, + }, { title: sidebarVisible() ? "Hide sidebar" : "Show sidebar", value: "session.sidebar.toggle", diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 7a105e7467c..9dea375221b 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -1286,6 +1286,75 @@ export namespace Server { return c.json(session) }, ) + .post( + "/session/:id/continue", + describeRoute({ + description: "Continue interrupted conversation", + operationId: "session.continue", + responses: { + 200: { + description: "Conversation continued", + content: { + "application/json": { + schema: resolver(z.boolean()), + }, + }, + }, + ...errors(400, 404), + }, + }), + validator( + "param", + z.object({ + id: z.string(), + }), + ), + async (c) => { + const id = c.req.valid("param").id + + // Check if session has an unfinished assistant message + const msgs = await Session.messages({ sessionID: id }) + let lastAssistant: MessageV2.Assistant | undefined + + for (let i = msgs.length - 1; i >= 0; i--) { + const msg = msgs[i] + if (msg.info.role === "assistant") { + lastAssistant = msg.info as MessageV2.Assistant + break + } + } + + // If no unfinished assistant message, return false + if (!lastAssistant || (lastAssistant.finish && !["tool-calls", "unknown"].includes(lastAssistant.finish))) { + return c.json(false) + } + + // Find the last user message to revert to + let lastUser: MessageV2.User | undefined + for (let i = msgs.length - 1; i >= 0; i--) { + const msg = msgs[i] + if (msg.info.role === "user") { + lastUser = msg.info as MessageV2.User + break + } + } + + if (!lastUser) { + return c.json(false) + } + + // Revert the unfinished assistant message + await SessionRevert.revert({ + sessionID: id, + messageID: lastUser.id, + }) + + // Start the conversation loop to continue + await SessionPrompt.loop(id) + + return c.json(true) + }, + ) .post( "/session/:id/permissions/:permissionID", describeRoute({ diff --git a/packages/opencode/test/session/session.test.ts b/packages/opencode/test/session/session.test.ts index 219cef12713..61d3a262a59 100644 --- a/packages/opencode/test/session/session.test.ts +++ b/packages/opencode/test/session/session.test.ts @@ -68,4 +68,22 @@ describe("session.started event", () => { }, }) }) + + describe("session continue functionality", () => { + test("should identify unfinished assistant messages correctly", async () => { + await Instance.provide({ + directory: projectRoot, + fn: async () => { + // Create a session + const session = await Session.create({}) + + // Test that empty session has no messages + const emptyMsgs = await Session.messages({ sessionID: session.id }) + expect(emptyMsgs).toEqual([]) + + await Session.remove(session.id) + }, + }) + }) + }) }) diff --git a/packages/sdk/js/openapi.json b/packages/sdk/js/openapi.json index 057dad47346..41bd17258f6 100644 --- a/packages/sdk/js/openapi.json +++ b/packages/sdk/js/openapi.json @@ -2235,6 +2235,61 @@ } } }, + "/session/{id}/continue": { + "post": { + "operationId": "session.continue", + "parameters": [ + { + "in": "query", + "name": "directory", + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true + } + ], + "description": "Continue interrupted conversation", + "responses": { + "200": { + "description": "Conversation continued", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + }, + "400": { + "description": "Bad request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + } + } + } + }, "/session/{id}/permissions/{permissionID}": { "post": { "operationId": "postSession:idPermissions:permissionID", diff --git a/packages/sdk/js/src/gen/sdk.gen.ts b/packages/sdk/js/src/gen/sdk.gen.ts index d04277cbc81..e9a68aad21c 100644 --- a/packages/sdk/js/src/gen/sdk.gen.ts +++ b/packages/sdk/js/src/gen/sdk.gen.ts @@ -109,6 +109,9 @@ import type { SessionUnrevertData, SessionUnrevertResponses, SessionUnrevertErrors, + SessionContinueData, + SessionContinueResponses, + SessionContinueErrors, PostSessionIdPermissionsPermissionIdData, PostSessionIdPermissionsPermissionIdResponses, PostSessionIdPermissionsPermissionIdErrors, @@ -682,6 +685,16 @@ class Session extends _HeyApiClient { ...options, }) } + + /** + * Continue interrupted conversation + */ + public continue(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/continue", + ...options, + }) + } } class Command extends _HeyApiClient { diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index c640f41a719..3823251211b 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -2826,6 +2826,39 @@ export type SessionUnrevertResponses = { export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses] +export type SessionContinueData = { + body?: never + path: { + id: string + } + query?: { + directory?: string + } + url: "/session/{id}/continue" +} + +export type SessionContinueErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionContinueError = SessionContinueErrors[keyof SessionContinueErrors] + +export type SessionContinueResponses = { + /** + * Conversation continued + */ + 200: boolean +} + +export type SessionContinueResponse = SessionContinueResponses[keyof SessionContinueResponses] + export type PostSessionIdPermissionsPermissionIdData = { body?: { response: "once" | "always" | "reject" From 1213887103acd75090e44542fd5bcc071afa6798 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Sun, 7 Dec 2025 21:29:53 -0500 Subject: [PATCH 2/6] tidy: unwanted indentation. --- .../cli/cmd/tui/component/prompt/autocomplete.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 0d524467089..592a52fb676 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -306,12 +306,12 @@ export function Autocomplete(props: { description: "list agents", onSelect: () => command.trigger("agent.list"), }, - { - display: "/session", - aliases: ["/resume"], - description: "list sessions", - onSelect: () => command.trigger("session.list"), - }, + { + display: "/session", + aliases: ["/resume"], + description: "list sessions", + onSelect: () => command.trigger("session.list"), + }, { display: "/status", aliases: ["/mcp"], From b31cb9d6bf0232ac397a985327eaccd91af9452f Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Mon, 8 Dec 2025 14:24:57 -0500 Subject: [PATCH 3/6] fix: resolve TypeScript errors after dev merge - Remove invalid cacheKey property from FileContents in desktop package - Update SDK method calls to use v2 API (abort/prompt with sessionID parameter) --- packages/desktop/src/pages/session.tsx | 1 - .../opencode/src/cli/cmd/tui/routes/session/index.tsx | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 81f4dc1cbc4..d46360eb7e7 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -493,7 +493,6 @@ export default function Page() { file={{ name: f().path, contents: f().content?.content ?? "", - cacheKey: checksum(f().content?.content ?? ""), }} overflow="scroll" class="pb-40" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index bd109e7bab9..fc49bb477bb 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -395,12 +395,10 @@ export function Session() { category: "Session", onSelect: async (dialog) => { const status = sync.data.session_status[route.sessionID] - if (status?.type !== "idle") await sdk.client.session.abort({ path: { id: route.sessionID } }).catch(() => {}) + if (status?.type !== "idle") await sdk.client.session.abort({ sessionID: route.sessionID }).catch(() => {}) - const result = await sdk.client.session.continue({ - path: { - id: route.sessionID, - }, + const result = await sdk.client.session.prompt({ + sessionID: route.sessionID, }) if (result.data) { From c600ac68d1ace4405d1a2f8aa52e8cec03073e4a Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Mon, 8 Dec 2025 18:22:18 -0500 Subject: [PATCH 4/6] fix: make /continue command work correctly - Regenerate v2 SDK to include session.continue() method - Update TUI to call session.continue() instead of session.prompt() - Simplify server continue endpoint logic to avoid race conditions - Cancel existing session state before starting new loop to prevent double abort errors Closes #5150 --- .../src/cli/cmd/tui/routes/session/index.tsx | 6 +- packages/opencode/src/server/server.ts | 42 +--- packages/sdk/js/openapi.json | 216 ------------------ packages/sdk/js/src/v2/gen/sdk.gen.ts | 30 +++ packages/sdk/js/src/v2/gen/types.gen.ts | 33 +++ 5 files changed, 72 insertions(+), 255 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index fc49bb477bb..884ec4f9657 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -394,17 +394,13 @@ export function Session() { keybind: "session_continue", category: "Session", onSelect: async (dialog) => { - const status = sync.data.session_status[route.sessionID] - if (status?.type !== "idle") await sdk.client.session.abort({ sessionID: route.sessionID }).catch(() => {}) - - const result = await sdk.client.session.prompt({ + const result = await sdk.client.session.continue({ sessionID: route.sessionID, }) if (result.data) { toBottom() } else { - // Show message that there's nothing to continue dialog.clear() } }, diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 6246d97f759..60d39d54879 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -1358,45 +1358,19 @@ export namespace Server { async (c) => { const sessionID = c.req.valid("param").sessionID - // Check if session has an unfinished assistant message + // Check if there's a user message to continue from const msgs = await Session.messages({ sessionID }) - let lastAssistant: MessageV2.Assistant | undefined - - for (let i = msgs.length - 1; i >= 0; i--) { - const msg = msgs[i] - if (msg.info.role === "assistant") { - lastAssistant = msg.info as MessageV2.Assistant - break - } - } - - // If no unfinished assistant message, return false - if (!lastAssistant || (lastAssistant.finish && !["tool-calls", "unknown"].includes(lastAssistant.finish))) { + const hasUserMessage = msgs.some((m) => m.info.role === "user") + if (!hasUserMessage) { return c.json(false) } - // Find the last user message to revert to - let lastUser: MessageV2.User | undefined - for (let i = msgs.length - 1; i >= 0; i--) { - const msg = msgs[i] - if (msg.info.role === "user") { - lastUser = msg.info as MessageV2.User - break - } - } - - if (!lastUser) { - return c.json(false) - } + // Cancel any existing session state to ensure clean start + SessionPrompt.cancel(sessionID) - // Revert unfinished assistant message - await SessionRevert.revert({ - sessionID, - messageID: lastUser.id, - }) - - // Start conversation loop to continue - await SessionPrompt.loop(sessionID) + // Start conversation loop - it will continue from where it left off + // The loop handles incomplete assistant messages automatically + SessionPrompt.loop(sessionID) return c.json(true) }, diff --git a/packages/sdk/js/openapi.json b/packages/sdk/js/openapi.json index 5a00fe66fd6..9113abb78de 100644 --- a/packages/sdk/js/openapi.json +++ b/packages/sdk/js/openapi.json @@ -41,14 +41,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List all projects", @@ -86,14 +78,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get current project", @@ -128,14 +112,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List PTY sessions", @@ -483,14 +459,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get configuration", @@ -576,14 +544,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List tool IDs", @@ -688,14 +648,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Dispose instance", @@ -730,14 +682,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get paths", @@ -772,14 +716,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get VCS info", @@ -814,14 +750,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List sessions", @@ -919,14 +847,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get session status", @@ -2757,14 +2677,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List commands", @@ -2802,14 +2714,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List config providers", @@ -2865,14 +2769,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List providers", @@ -3134,14 +3030,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get provider auth methods", @@ -3631,14 +3519,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get file status", @@ -3762,14 +3642,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "List agents", @@ -3807,14 +3679,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get MCP status", @@ -4203,14 +4067,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get LSP status", @@ -4248,14 +4104,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get formatter status", @@ -4354,14 +4202,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Open help dialog", @@ -4396,14 +4236,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Open sessions dialog", @@ -4438,14 +4270,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Open themes dialog", @@ -4480,14 +4304,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Open models dialog", @@ -4522,14 +4338,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Submit TUI prompt", @@ -4564,14 +4372,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Clear TUI prompt", @@ -4799,14 +4599,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Get next TUI request", @@ -4953,14 +4745,6 @@ "schema": { "type": "string" } - }, - { - "schema": { - "type": "string" - }, - "in": "path", - "name": "name", - "required": true } ], "summary": "Subscribe to events", diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 77e3ba1f50d..3bac9b30f27 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -72,6 +72,8 @@ import type { SessionChildrenResponses, SessionCommandErrors, SessionCommandResponses, + SessionContinueErrors, + SessionContinueResponses, SessionCreateErrors, SessionCreateResponses, SessionDeleteErrors, @@ -1421,6 +1423,34 @@ export class Session extends HeyApiClient { ...params, }) } + + /** + * Continue interrupted conversation + */ + public continue( + parameters: { + sessionID: string + directory?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post({ + url: "/session/{sessionID}/continue", + ...options, + ...params, + }) + } } export class Permission extends HeyApiClient { diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index ffd7ee37314..f5d8f59a2e9 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -2870,6 +2870,39 @@ export type SessionUnrevertResponses = { export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses] +export type SessionContinueData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/continue" +} + +export type SessionContinueErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionContinueError = SessionContinueErrors[keyof SessionContinueErrors] + +export type SessionContinueResponses = { + /** + * Conversation continued + */ + 200: boolean +} + +export type SessionContinueResponse = SessionContinueResponses[keyof SessionContinueResponses] + export type PermissionRespondData = { body?: { response: "once" | "always" | "reject" From ac88fc3541a4019e898c8092657ba54104faa74e Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Mon, 8 Dec 2025 20:55:45 -0500 Subject: [PATCH 5/6] fix: restore corrupted file --- packages/desktop/src/pages/session.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/desktop/src/pages/session.tsx b/packages/desktop/src/pages/session.tsx index 49c613064a0..f9e71767418 100644 --- a/packages/desktop/src/pages/session.tsx +++ b/packages/desktop/src/pages/session.tsx @@ -494,6 +494,7 @@ export default function Page() { file={{ name: f().path, contents: f().content?.content ?? "", + cacheKey: checksum(f().content?.content ?? ""), }} overflow="scroll" class="pb-40" From cfdfd5d14c69c0281efc7afe1f86b4e2628c6498 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Fri, 12 Dec 2025 15:45:02 -0500 Subject: [PATCH 6/6] tidy: revert unwanted change. --- packages/opencode/test/session/session.test.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/opencode/test/session/session.test.ts b/packages/opencode/test/session/session.test.ts index 61d3a262a59..219cef12713 100644 --- a/packages/opencode/test/session/session.test.ts +++ b/packages/opencode/test/session/session.test.ts @@ -68,22 +68,4 @@ describe("session.started event", () => { }, }) }) - - describe("session continue functionality", () => { - test("should identify unfinished assistant messages correctly", async () => { - await Instance.provide({ - directory: projectRoot, - fn: async () => { - // Create a session - const session = await Session.create({}) - - // Test that empty session has no messages - const emptyMsgs = await Session.messages({ sessionID: session.id }) - expect(emptyMsgs).toEqual([]) - - await Session.remove(session.id) - }, - }) - }) - }) })