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

fix(tui): keep session running until execution settles (#35136)

Shoubhit Dash 1 месяц назад
Родитель
Сommit
8d790a9ed5
2 измененных файлов с 35 добавлено и 2 удалено
  1. 4 2
      packages/tui/src/context/data.tsx
  2. 31 0
      packages/tui/test/cli/tui/data.test.tsx

+ 4 - 2
packages/tui/src/context/data.tsx

@@ -344,7 +344,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
           })
           break
         case "session.next.step.ended":
-          setStore("session", "status", event.data.sessionID, event.data.finish === "tool-calls" ? "running" : "idle")
+          setStore("session", "status", event.data.sessionID, "running")
           message.update(event.data.sessionID, (draft, index) => {
             const currentAssistant = message.assistant(draft, index, event.data.assistantMessageID)
             if (!currentAssistant) return
@@ -357,7 +357,6 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
           })
           break
         case "session.next.step.failed":
-          setStore("session", "status", event.data.sessionID, "idle")
           message.update(event.data.sessionID, (draft, index) => {
             const currentAssistant = message.assistant(draft, index, event.data.assistantMessageID)
             if (!currentAssistant) return
@@ -527,6 +526,9 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
         case "session.next.compaction.started":
           setStore("session", "status", event.data.sessionID, "running")
           break
+        case "session.next.execution.settled":
+          setStore("session", "status", event.data.sessionID, "idle")
+          break
         case "session.next.revert.staged":
           if (store.session.info[event.data.sessionID])
             setStore("session", "info", event.data.sessionID, "revert", event.data.revert)

+ 31 - 0
packages/tui/test/cli/tui/data.test.tsx

@@ -283,6 +283,21 @@ test("tracks session status from active sessions and execution events", async ()
         tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
       },
     })
+    await wait(() => {
+      const assistant = data.session.message.get("session-live", "message-live")
+      return assistant?.type === "assistant" && assistant.finish === "stop"
+    })
+    expect(data.session.status("session-live")).toBe("running")
+
+    emitEvent(events, {
+      id: "evt_execution_settled",
+      type: "session.next.execution.settled",
+      data: {
+        sessionID: "session-live",
+        timestamp: 3,
+        outcome: "success",
+      },
+    })
     await wait(() => data.session.status("session-live") === "idle")
 
     emitEvent(events, {
@@ -308,6 +323,22 @@ test("tracks session status from active sessions and execution events", async ()
         error: { type: "unknown", message: "Provider unavailable" },
       },
     })
+    await wait(() => {
+      const assistant = data.session.message.get("session-failed", "message-failed")
+      return assistant?.type === "assistant" && assistant.finish === "error"
+    })
+    expect(data.session.status("session-failed")).toBe("running")
+
+    emitEvent(events, {
+      id: "evt_failed_execution_settled",
+      type: "session.next.execution.settled",
+      data: {
+        sessionID: "session-failed",
+        timestamp: 5,
+        outcome: "failure",
+        error: { type: "unknown", message: "Provider unavailable" },
+      },
+    })
     await wait(() => data.session.status("session-failed") === "idle")
   } finally {
     app.renderer.destroy()