|
|
@@ -216,4 +216,131 @@ describe("StatusIndicator", () => {
|
|
|
expect(output).toContain("Cancelling...")
|
|
|
expect(output).not.toContain("Thinking...")
|
|
|
})
|
|
|
+
|
|
|
+ it("should show indicator after checkpoint_saved when task is still running", () => {
|
|
|
+ // This reproduces the bug from issue #5251
|
|
|
+ // After a checkpoint is saved, the indicator disappears because:
|
|
|
+ // 1. The checkpoint_saved message is not partial
|
|
|
+ // 2. The previous api_req_started has a cost (finished)
|
|
|
+ // 3. The next api_req_started hasn't been sent yet
|
|
|
+ // But the task is still running, so we should show an indicator
|
|
|
+
|
|
|
+ const messages: ExtensionChatMessage[] = [
|
|
|
+ // User started a task
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "text",
|
|
|
+ ts: 1000,
|
|
|
+ text: "Starting task...",
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ // API request completed (has cost)
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "api_req_started",
|
|
|
+ ts: 2000,
|
|
|
+ text: JSON.stringify({ cost: 0.001, tokensIn: 100, tokensOut: 50 }),
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ // Checkpoint was saved - this is the last message
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "checkpoint_saved",
|
|
|
+ ts: 3000,
|
|
|
+ text: "abc123",
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ store.set(chatMessagesAtom, messages)
|
|
|
+
|
|
|
+ const { lastFrame } = render(
|
|
|
+ <JotaiProvider store={store}>
|
|
|
+ <StatusIndicator disabled={false} />
|
|
|
+ </JotaiProvider>,
|
|
|
+ )
|
|
|
+
|
|
|
+ const output = lastFrame()
|
|
|
+ // The task is still running (no completion_result), so we should show an indicator
|
|
|
+ // Currently this fails because isStreamingAtom returns false
|
|
|
+ expect(output).toMatch(/(?:Thinking|Processing)\.\.\./)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should NOT show indicator after completion_result", () => {
|
|
|
+ // When the task is complete, we should NOT show any indicator
|
|
|
+ const messages: ExtensionChatMessage[] = [
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "text",
|
|
|
+ ts: 1000,
|
|
|
+ text: "Starting task...",
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "api_req_started",
|
|
|
+ ts: 2000,
|
|
|
+ text: JSON.stringify({ cost: 0.001, tokensIn: 100, tokensOut: 50 }),
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "completion_result",
|
|
|
+ ts: 3000,
|
|
|
+ text: "Task completed successfully",
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ store.set(chatMessagesAtom, messages)
|
|
|
+
|
|
|
+ const { lastFrame } = render(
|
|
|
+ <JotaiProvider store={store}>
|
|
|
+ <StatusIndicator disabled={false} />
|
|
|
+ </JotaiProvider>,
|
|
|
+ )
|
|
|
+
|
|
|
+ const output = lastFrame()
|
|
|
+ // Task is complete, should NOT show Thinking or Processing
|
|
|
+ expect(output).not.toContain("Thinking...")
|
|
|
+ expect(output).not.toContain("Processing...")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should NOT show indicator when waiting for tool approval", () => {
|
|
|
+ // When waiting for user to approve a tool, we should NOT show indicator
|
|
|
+ const messages: ExtensionChatMessage[] = [
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "text",
|
|
|
+ ts: 1000,
|
|
|
+ text: "Starting task...",
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "say",
|
|
|
+ say: "api_req_started",
|
|
|
+ ts: 2000,
|
|
|
+ text: JSON.stringify({ cost: 0.001, tokensIn: 100, tokensOut: 50 }),
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ // Tool asking for approval
|
|
|
+ {
|
|
|
+ type: "ask",
|
|
|
+ ask: "tool",
|
|
|
+ ts: 3000,
|
|
|
+ text: JSON.stringify({ tool: "write_to_file", path: "test.txt" }),
|
|
|
+ partial: false,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ store.set(chatMessagesAtom, messages)
|
|
|
+
|
|
|
+ const { lastFrame } = render(
|
|
|
+ <JotaiProvider store={store}>
|
|
|
+ <StatusIndicator disabled={false} />
|
|
|
+ </JotaiProvider>,
|
|
|
+ )
|
|
|
+
|
|
|
+ const output = lastFrame()
|
|
|
+ // Waiting for approval, should NOT show Thinking or Processing
|
|
|
+ expect(output).not.toContain("Thinking...")
|
|
|
+ expect(output).not.toContain("Processing...")
|
|
|
+ })
|
|
|
})
|