diff --git a/apps/desktop/src/acp/types.ts b/apps/desktop/src/acp/types.ts index ba18e2ba7..dc50da097 100644 --- a/apps/desktop/src/acp/types.ts +++ b/apps/desktop/src/acp/types.ts @@ -594,6 +594,8 @@ export type SessionUpdate = kind: "toolCallUpdate"; id: string; title?: string; + /** The call's input when it arrives after the call (Claude Code sends a Bash command so). */ + input?: Json; status?: ToolStatus; output?: string; outputDelta?: string; @@ -752,6 +754,9 @@ export function parseSessionUpdate(params: JsonObject): SessionUpdate { kind: "toolCallUpdate", id: str(update.toolCallId) ?? "", title: str(update.title), + ...(update.rawInput !== undefined && update.rawInput !== null + ? { input: update.rawInput as Json } + : {}), status: parseToolStatus(update.status), output: toolOutput(update), outputDelta: str(meta?.outputDelta), diff --git a/apps/desktop/src/state/thread.test.ts b/apps/desktop/src/state/thread.test.ts index e55a58f4e..61e4c69ec 100644 --- a/apps/desktop/src/state/thread.test.ts +++ b/apps/desktop/src/state/thread.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { parseSessionUpdate, type SessionUpdate } from "../acp/types"; import { sentMessages } from "./compose"; import type { Link } from "./orchestration"; +import { createdPull } from "./pullWatch"; import { agentStepLabel, appendSteer, @@ -85,6 +86,24 @@ describe("thread reducer", () => { expect(s.items[0]).toMatchObject({ kind: "tool", status: "completed", output: "a\nb\n", exitCode: 0 }); }); + test("an input that arrives in an update fills the call, so a created pull request is seen", () => { + const s = apply([ + { kind: "toolCall", id: "c", title: "Terminal", diffs: [] }, + { kind: "toolCallUpdate", id: "c", input: { command: "gh pr create --fill" }, diffs: [] }, + { + kind: "toolCallUpdate", + id: "c", + status: "completed", + output: "https://github.com/o/r/pull/7", + diffs: [], + }, + ]); + const item = s.items[0]; + expect(item).toMatchObject({ kind: "tool", input: { command: "gh pr create --fill" } }); + if (item?.kind !== "tool") throw new Error("no tool row"); + expect(createdPull(item.input, item.output ?? "")).toEqual({ repo: "o/r", number: 7 }); + }); + test("an auto-allowed call says so on its own row, and later updates keep it", () => { const s = apply([ { kind: "user", text: "go" }, diff --git a/apps/desktop/src/state/thread.ts b/apps/desktop/src/state/thread.ts index c106dc6fa..e06c72680 100644 --- a/apps/desktop/src/state/thread.ts +++ b/apps/desktop/src/state/thread.ts @@ -728,6 +728,7 @@ export function applyUpdate(state: ThreadState, update: SessionUpdate, now = Dat parent: item.parent ?? update.parent, endedAt: item.endedAt ?? (ended ? now : undefined), title: update.title ?? item.title, + input: update.input ?? item.input, status: background ? "in_progress" : (update.status ?? (item.status === "pending" ? "in_progress" : item.status)),