{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tool-call-card",
  "title": "Tool Call Card",
  "description": "Collapsible record of one tool call: name, status, duration, and the exact input and output on demand.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/miseui/ui/tool-call-card.tsx",
      "content": "import type * as React from \"react\"\nimport { Check, TriangleAlert } from \"lucide-react\"\nimport { cn } from \"@/registry/miseui/lib/utils\"\n\ntype ToolCallStatus = \"running\" | \"success\" | \"error\"\n\nconst MS_PER_SECOND = 1000\n/** \"1.2 s\" reads at a glance; more decimals is noise for a tool call. */\nconst SECONDS_DECIMALS = 1\nconst JSON_INDENT = 2\n\ninterface ToolCallCardProps extends React.ComponentProps<\"details\"> {\n  /** Tool name as the model called it, e.g. \"search_web\". */\n  name: string\n  status: ToolCallStatus\n  /** Arguments the tool was called with. Strings render as-is, anything else as pretty JSON. */\n  input?: unknown\n  /** What the tool returned. Omitted while running or when there is nothing to show. */\n  output?: unknown\n  durationMs?: number\n  /** Start expanded. The user can still collapse it. */\n  defaultOpen?: boolean\n}\n\nfunction formatDuration(ms: number) {\n  if (ms < MS_PER_SECOND) return `${Math.round(ms)} ms`\n  return `${(ms / MS_PER_SECOND).toFixed(SECONDS_DECIMALS)} s`\n}\n\nfunction stringifyValue(value: unknown) {\n  if (typeof value === \"string\") return value\n  try {\n    return JSON.stringify(value, null, JSON_INDENT) ?? String(value)\n  } catch {\n    // Circular structures cannot be serialized; show something rather than crash the card.\n    return String(value)\n  }\n}\n\nfunction ToolCallCard({\n  name,\n  status,\n  input,\n  output,\n  durationMs,\n  defaultOpen = false,\n  className,\n  children,\n  ...props\n}: ToolCallCardProps) {\n  const hasBody = input !== undefined || output !== undefined || children !== undefined\n\n  return (\n    <details\n      data-slot=\"tool-call-card\"\n      data-status={status}\n      open={defaultOpen}\n      className={cn(\"group rounded-lg border text-sm\", className)}\n      {...props}\n    >\n      <summary\n        aria-label={`${name}: ${status}`}\n        className={cn(\n          \"flex cursor-pointer list-none items-center gap-2 px-3 py-2 select-none\",\n          \"[&::-webkit-details-marker]:hidden\",\n          status === \"error\" && \"text-destructive\",\n        )}\n      >\n        <StatusMark status={status} />\n        <span className=\"font-mono\">{name}</span>\n        {durationMs !== undefined ? (\n          <span className=\"ml-auto text-xs text-muted-foreground tabular-nums\">{formatDuration(durationMs)}</span>\n        ) : null}\n      </summary>\n      {hasBody ? (\n        <div data-slot=\"tool-call-card-body\" className=\"flex flex-col gap-3 border-t px-3 py-2\">\n          {input !== undefined ? <ValueBlock label=\"Input\" value={input} /> : null}\n          {output !== undefined ? <ValueBlock label=\"Output\" value={output} /> : null}\n          {children}\n        </div>\n      ) : null}\n    </details>\n  )\n}\n\nfunction StatusMark({ status }: { status: ToolCallStatus }) {\n  if (status === \"success\") return <Check className=\"size-4 text-foreground\" aria-hidden=\"true\" />\n  if (status === \"error\") return <TriangleAlert className=\"size-4 text-destructive\" aria-hidden=\"true\" />\n  return <span className=\"size-2 rounded-full bg-mise animate-pulse motion-reduce:animate-none\" aria-hidden=\"true\" />\n}\n\nfunction ValueBlock({ label, value }: { label: string; value: unknown }) {\n  return (\n    <div data-slot=\"tool-call-card-block\" className=\"flex flex-col gap-1\">\n      <span className=\"text-xs font-medium text-muted-foreground\">{label}</span>\n      <pre className=\"overflow-x-auto rounded-md border px-2 py-1.5 font-mono text-xs whitespace-pre-wrap text-foreground\">\n        {stringifyValue(value)}\n      </pre>\n    </div>\n  )\n}\n\nexport { ToolCallCard, formatDuration, type ToolCallCardProps, type ToolCallStatus }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ai"
  ],
  "type": "registry:ui"
}