From 41b92cbcc02dfbe5d83e398bb60d54bcdbf5c15f Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sun, 29 Mar 2026 13:19:37 -0400 Subject: [PATCH] restore prompt runtime after rebase drift --- packages/opencode/src/session/prompt.ts | 31 ++++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 6916ddced6..938f3af196 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -73,6 +73,11 @@ export namespace SessionPrompt { queue: Deferred.Deferred[] } + interface ShellEntry { + fiber: Fiber.Fiber + abort: AbortController + } + export interface Interface { readonly assertNotBusy: (sessionID: SessionID) => Effect.Effect readonly cancel: (sessionID: SessionID) => Effect.Effect @@ -105,9 +110,15 @@ export namespace SessionPrompt { const cache = yield* InstanceState.make( Effect.fn("SessionPrompt.state")(function* () { const loops = new Map() - const shells = new Map>() + const shells = new Map() yield* Effect.addFinalizer(() => - Fiber.interruptAll([...loops.values().flatMap((e) => (e.fiber ? [e.fiber] : [])), ...shells.values()]), + Effect.gen(function* () { + for (const item of shells.values()) item.abort.abort() + yield* Fiber.interruptAll([ + ...loops.values().flatMap((e) => (e.fiber ? [e.fiber] : [])), + ...shells.values().map((x) => x.fiber), + ]) + }), ) return { loops, shells } }), @@ -133,8 +144,7 @@ export namespace SessionPrompt { s.loops.delete(sessionID) } if (shellEntry) { - yield* Fiber.interrupt(shellEntry) - s.shells.delete(sessionID) + shellEntry.abort.abort() } yield* status.set(sessionID, { type: "idle" }) }) @@ -826,7 +836,7 @@ export namespace SessionPrompt { return yield* lastAssistant(sessionID) }) - type State = { loops: Map; shells: Map> } + type State = { loops: Map; shells: Map } const awaitFiber = (fiber: Fiber.Fiber, fallback: Effect.Effect) => Effect.gen(function* () { @@ -890,15 +900,18 @@ export namespace SessionPrompt { throw new Session.BusyError(input.sessionID) } - const fiber = yield* Effect.promise((signal) => shellImpl(input, signal)).pipe( + yield* status.set(input.sessionID, { type: "busy" }) + const ctrl = new AbortController() + const fiber = yield* Effect.promise(() => shellImpl(input, ctrl.signal)).pipe( Effect.ensuring( Effect.gen(function* () { - s.shells.delete(input.sessionID) + const entry = s.shells.get(input.sessionID) + if (entry?.fiber === fiber) s.shells.delete(input.sessionID) // If callers queued a loop while the shell was running, start it const pending = s.loops.get(input.sessionID) if (pending && pending.queue.length > 0) { yield* startLoop(s, input.sessionID).pipe(Effect.ignore, Effect.forkIn(scope)) - } else { + } else if (!s.loops.has(input.sessionID) && !s.shells.has(input.sessionID)) { yield* status.set(input.sessionID, { type: "idle" }) } }), @@ -906,7 +919,7 @@ export namespace SessionPrompt { Effect.forkChild, ) - s.shells.set(input.sessionID, fiber) + s.shells.set(input.sessionID, { fiber, abort: ctrl }) return yield* awaitFiber(fiber, lastAssistant(input.sessionID)) })