From d4157d9a9603c099e650af4f6c369a56d3878179 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 18 Jun 2025 14:11:33 -0400 Subject: [PATCH] ctrl+c should gracefully clean up pending sessions --- packages/opencode/src/index.ts | 2 +- packages/opencode/src/session/index.ts | 37 ++++++++++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 63f1021d..10de7fa5 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -101,7 +101,7 @@ const cli = yargs(hideBin(process.argv)) })() await proc.exited - await server.stop() + server.stop() return "done" }) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 61457c9d..2672d93d 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -73,15 +73,25 @@ export namespace Session { ), } - const state = App.state("session", () => { - const sessions = new Map() - const messages = new Map() + const state = App.state( + "session", + () => { + const sessions = new Map() + const messages = new Map() + const pending = new Map() - return { - sessions, - messages, - } - }) + return { + sessions, + messages, + pending, + } + }, + async (state) => { + for (const [_, controller] of state.pending) { + controller.abort() + } + }, + ) export async function create(parentID?: string) { const result: Info = { @@ -174,10 +184,10 @@ export namespace Session { } export function abort(sessionID: string) { - const controller = pending.get(sessionID) + const controller = state().pending.get(sessionID) if (!controller) return false controller.abort() - pending.delete(sessionID) + state().pending.delete(sessionID) return true } @@ -737,17 +747,16 @@ export namespace Session { await updateMessage(next) } - const pending = new Map() function lock(sessionID: string) { log.info("locking", { sessionID }) - if (pending.has(sessionID)) throw new BusyError(sessionID) + if (state().pending.has(sessionID)) throw new BusyError(sessionID) const controller = new AbortController() - pending.set(sessionID, controller) + state().pending.set(sessionID, controller) return { signal: controller.signal, [Symbol.dispose]() { log.info("unlocking", { sessionID }) - pending.delete(sessionID) + state().pending.delete(sessionID) }, } }