;
const tool = (toolUse.name ?? "").toLowerCase();
// Bash: show the command with shell highlighting
if (tool === "bash" && typeof obj.command === "string") {
return (
{typeof obj.description === "string" && (
{obj.description}
)}
);
}
// Write: render new content as code with the file path as the chrome label
if (tool === "write" && typeof obj.file_path === "string" && typeof obj.content === "string") {
return (
);
}
// Edit: side-by-side old/new
if (tool === "edit" && typeof obj.file_path === "string") {
const lang = langFromPath(obj.file_path);
return (
{obj.file_path}
{obj.replace_all === true && (
replace all
)}
{typeof obj.old_string === "string" && (
)}
{typeof obj.new_string === "string" && (
)}
);
}
// Read: just show the path with offset/limit
if (tool === "read" && typeof obj.file_path === "string") {
return (
{obj.file_path}
{(typeof obj.offset === "number" || typeof obj.limit === "number") && (
{typeof obj.offset === "number" ? `:${obj.offset}` : ""}
{typeof obj.limit === "number" ? `+${obj.limit}` : ""}
)}
);
}
// Grep: pattern + path
if (tool === "grep" && typeof obj.pattern === "string") {
return (
Pattern
{obj.pattern}
{typeof obj.path === "string" && (
Path
{obj.path}
)}
{typeof obj.glob === "string" && (
Glob
{obj.glob}
)}
);
}
// Default: pretty JSON
return ;
}
/** Render the result pane: detect diff/json/text. */
function renderResult(toolResult: TranscriptContent, toolName: string) {
const text = toolResult.output ?? "";
if (text.length === 0) return (empty)
;
const isError = !!toolResult.is_error;
const tool = toolName.toLowerCase();
const label = isError ? "Error" : "Output";
// Heuristics for language
let lang = "plain";
const trimmed = text.trim();
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
try {
JSON.parse(trimmed);
lang = "json";
} catch {
// fall through
}
} else if (/^(\+\+\+|---|@@) /m.test(text) || /^diff --git /m.test(text)) {
lang = "diff";
} else if (tool === "bash") {
lang = "bash";
}
return ;
}
export function ToolCallBlock({ toolUse, toolResult }: ToolCallBlockProps) {
const [expanded, setExpanded] = useState(false);
const isError = toolResult?.is_error;
const hasResult = toolResult != null;
const summary = buildSummary(toolUse);
const style = styleForTool(toolUse.name);
const Icon = style.Icon;
const wrapperBorder = isError ? "border-red-500/30" : style.border;
const wrapperBg = isError ? "bg-red-500/5" : "bg-surface-2/60";
return (
{/* Collapsed/expanded toggle */}
{/* Expanded body */}
{expanded && (
{renderInput(toolUse)}
{hasResult && renderResult(toolResult, toolUse.name ?? "")}
)}
);
}