/* Copyright 2026 Marimo. All rights reserved. */ import { BanIcon, CheckCircleIcon, Loader2, WrenchIcon } from "lucide-react"; import React from "react"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { logNever } from "@/utils/assertNever"; import { cn } from "@/utils/cn"; import { formatToolName, type ToolApproval, type ToolState } from "./shared"; import { ToolArgsRenderer } from "./tool-args"; import { ResultRenderer } from "./tool-result"; // States considered "inert" — they represent past or background work that the // user does not need to act on. export type HistoryState = Exclude< ToolState, "approval-requested" | "output-error" >; const STATUS_LABEL: Record = { "input-streaming": "Generating", "input-available": "Running", "approval-responded": "Awaiting result", "output-available": "Done", "output-denied": "Denied", }; const StatusIcon: React.FC<{ state: HistoryState }> = ({ state }) => { switch (state) { case "input-streaming": case "input-available": case "approval-responded": return ; case "output-available": return ; case "output-denied": return ; default: logNever(state); return ; } }; function getTriggerToneClass(state: HistoryState): string { switch (state) { case "output-available": return "text-(--grass-11)/80"; case "output-denied": return "text-muted-foreground"; case "input-streaming": case "input-available": case "approval-responded": return ""; default: logNever(state); return ""; } } interface ToolHistoryRowProps { toolName: string; state: HistoryState; input: unknown; result?: unknown; approval?: ToolApproval; index?: number; className?: string; } export const ToolHistoryRow: React.FC = ({ toolName, state, input, result, approval, index = 0, className, }) => { return ( svg]:rotate-180 hover:no-underline", getTriggerToneClass(state), )} > {STATUS_LABEL[state]}: {formatToolName(toolName)} ); }; const HistoryContent: React.FC<{ state: HistoryState; input: unknown; result?: unknown; approval?: ToolApproval; }> = ({ state, input, result, approval }) => { switch (state) { case "input-streaming": case "input-available": case "approval-responded": return ; case "output-available": return (
{result != null && }
); case "output-denied": return (
Tool execution was denied {approval?.reason ? `: ${approval.reason}` : "."}
); default: logNever(state); return null; } };