Просмотр исходного кода

fix(opencode): SessionPrompt.shell() now triggers loop if messages are queued (#10987)

Goni Zahavy 2 месяцев назад
Родитель
Сommit
def907ae4b

+ 1 - 1
packages/opencode/src/server/routes/session.ts

@@ -539,7 +539,7 @@ export const SessionRoutes = lazy(() =>
           },
           auto: body.auto,
         })
-        await SessionPrompt.loop(sessionID)
+        await SessionPrompt.loop({ sessionID })
         return c.json(true)
       },
     )

+ 29 - 4
packages/opencode/src/session/prompt.ts

@@ -174,7 +174,7 @@ export namespace SessionPrompt {
       return message
     }
 
-    return loop(input.sessionID)
+    return loop({sessionID: input.sessionID})
   })
 
   export async function resolvePromptParts(template: string): Promise<PromptInput["parts"]> {
@@ -239,6 +239,13 @@ export namespace SessionPrompt {
     return controller.signal
   }
 
+  function resume(sessionID: string) {
+    const s = state()
+    if (!s[sessionID]) return
+
+    return s[sessionID].abort.signal
+  }
+
   export function cancel(sessionID: string) {
     log.info("cancel", { sessionID })
     const s = state()
@@ -253,8 +260,14 @@ export namespace SessionPrompt {
     return
   }
 
-  export const loop = fn(Identifier.schema("session"), async (sessionID) => {
-    const abort = start(sessionID)
+  export const LoopInput = z.object({
+    sessionID: Identifier.schema("session"),
+    resume_existing: z.boolean().optional(),
+  })
+  export const loop = fn(LoopInput, async (input) => {
+    const { sessionID, resume_existing } = input
+
+    const abort = resume_existing ? resume(sessionID) : start(sessionID)
     if (!abort) {
       return new Promise<MessageV2.WithParts>((resolve, reject) => {
         const callbacks = state()[sessionID].callbacks
@@ -1366,7 +1379,19 @@ NOTE: At any point in time through this workflow you should feel free to ask the
     if (!abort) {
       throw new Session.BusyError(input.sessionID)
     }
-    using _ = defer(() => cancel(input.sessionID))
+
+    using _ = defer(() => {
+      // If no queued callbacks, cancel (the default)
+      const callbacks = state()[input.sessionID]?.callbacks ?? []
+      if (callbacks.length === 0) {
+        cancel(input.sessionID)
+      } else {
+        // Otherwise, trigger the session loop to process queued items
+        loop({sessionID: input.sessionID, resume_existing: true}).catch((error) => {
+          log.error("session loop failed to resume after shell command", { sessionID: input.sessionID, error  })
+        })
+      }
+    })
 
     const session = await Session.get(input.sessionID)
     if (session.revert) {