/** * ToolCallCard shows one tool call the agent is running, in the spirit of * Zed's agent panel: a collapsible card with the tool kind, a live status, * touched locations, and the call's output (text, or a file diff). * * @example * */ import type { ToolCall } from "../reducer"; import type { AcpToolCallContent } from "../protocol"; import { Markdown } from "./Markdown"; const kindIcons: Record = { read: "📖", edit: "✏️", delete: "🗑️", move: "📦", search: "🔍", execute: "⚡", think: "💭", fetch: "🌐", switch_mode: "🔀", other: "🔧", }; const statusLabels: Record = { pending: "pending", in_progress: "running", completed: "done", failed: "failed", }; export function ToolCallCard({ call }: { call: ToolCall }) { return (
{kindIcons[call.toolKind] ?? kindIcons.other} {call.title} {statusLabels[call.status] ?? call.status}
{call.locations.length > 0 && (
    {call.locations.map((location, index) => ( // biome-ignore lint/suspicious/noArrayIndexKey: tool-call locations carry no id and the list is replaced wholesale on every update.
  • {location.path} {location.line != null ? `:${location.line}` : ""}
  • ))}
)} {call.contents.map((content, index) => ( // biome-ignore lint/suspicious/noArrayIndexKey: tool-call contents carry no id and the list is replaced wholesale on every update. ))}
); } function ToolContent({ content }: { content: AcpToolCallContent }) { switch (content.type) { case "content": return content.content?.text ? ( ) : null; case "diff": return (
{content.path} {content.oldText != null && (
							{prefixLines(content.oldText, "- ")}
						
)}
						{prefixLines(content.newText ?? "", "+ ")}
					
); case "terminal": return

terminal: {content.terminalId}

; default: return null; } } function prefixLines(text: string, prefix: string): string { return text .split("\n") .map((line) => prefix + line) .join("\n"); }