{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "agent-trace",
  "type": "registry:ui",
  "title": "Agent trace",
  "description": "React timeline of an AI agent run: each tool step shows pending, running, done or error, reports its duration and folds out details. The header sums up the run.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/agent-trace.tsx",
      "type": "registry:ui",
      "target": "components/ui/agent-trace.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { CheckIcon, ChevronRightIcon, LoaderCircleIcon, XIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\ntype Step = {\n  id: string\n  name: string\n  status?: \"running\" | \"done\" | \"error\" | \"pending\"\n  detail?: string\n  /** e.g. \"1.2s\" */\n  duration?: string\n}\n\n/**\n * AgentTrace — an agent run as a timeline. A hairline rail connects the steps;\n * the running step pulses, finished steps report their time, details fold out.\n */\nfunction AgentTrace({\n  steps,\n  className,\n  title = \"Agent run\",\n  meta,\n}: {\n  steps: Step[]\n  className?: string\n  title?: string\n  /** Right-aligned summary, e.g. \"4 tools · 3.1s · $0.012\". */\n  meta?: React.ReactNode\n}) {\n  const done = steps.filter((s) => s.status === \"done\").length\n  const running = steps.some((s) => s.status === \"running\")\n  const [open, setOpen] = React.useState<string | null>(null)\n  return (\n    <div data-slot=\"agent-trace\" className={cn(\"w-full max-w-lg overflow-hidden rounded-xl border border-border bg-surface shadow-raised\", className)}>\n      <div className=\"flex items-center justify-between gap-3 border-b border-border px-4 py-3\">\n        <div className=\"flex items-center gap-2\">\n          <span className={cn(\"size-2 rounded-full\", running ? \"animate-[pulse-ring_1.4s_infinite] bg-accent\" : done === steps.length ? \"bg-success\" : \"bg-fg-subtle\")} />\n          <p className=\"text-[0.8125rem] font-medium text-fg\">{title}</p>\n        </div>\n        <p className=\"font-mono text-[11px] text-fg-subtle\">{meta ?? `${done}/${steps.length} steps`}</p>\n      </div>\n      <ol className=\"relative px-4 py-3\">\n        {steps.map((s, i) => {\n          const st = s.status ?? \"pending\"\n          const last = i === steps.length - 1\n          const isOpen = open === s.id\n          return (\n            <li key={s.id} className=\"relative pl-8\">\n              {!last ? <span aria-hidden className={cn(\"absolute top-6 bottom-0 left-[9px] w-px\", st === \"done\" ? \"bg-success/40\" : \"bg-border\")} /> : null}\n              <span\n                aria-hidden\n                className={cn(\n                  \"absolute top-1.5 left-0 grid size-[19px] place-items-center rounded-full border\",\n                  st === \"done\" && \"border-success/30 bg-success/10 text-success\",\n                  st === \"running\" && \"border-accent-line bg-accent-soft text-accent-fg\",\n                  st === \"error\" && \"border-danger/30 bg-danger/10 text-danger\",\n                  st === \"pending\" && \"border-border bg-surface text-fg-subtle\"\n                )}\n              >\n                {st === \"done\" ? <CheckIcon className=\"size-3\" strokeWidth={2.75} /> : st === \"running\" ? <LoaderCircleIcon className=\"size-3 animate-spin\" /> : st === \"error\" ? <XIcon className=\"size-3\" strokeWidth={2.75} /> : <span className=\"size-1 rounded-full bg-current\" />}\n              </span>\n              <button\n                type=\"button\"\n                disabled={!s.detail}\n                onClick={() => setOpen(isOpen ? null : s.id)}\n                aria-expanded={s.detail ? isOpen : undefined}\n                className=\"flex min-h-8 w-full items-center gap-2 rounded-md py-1 text-left outline-none enabled:cursor-pointer focus-visible:ring-2 focus-visible:ring-accent\"\n              >\n                <span className={cn(\"flex-1 truncate font-mono text-[12.5px]\", st === \"pending\" ? \"text-fg-subtle\" : \"text-fg\")}>{s.name}</span>\n                {st === \"running\" ? <span className=\"text-[11px] font-medium text-accent-fg\">running</span> : s.duration ? <span className=\"font-mono text-[11px] text-fg-subtle\">{s.duration}</span> : null}\n                {s.detail ? <ChevronRightIcon className={cn(\"size-3.5 text-fg-subtle transition-transform duration-200 ease-hairline\", isOpen && \"rotate-90\")} /> : null}\n              </button>\n              {s.detail ? (\n                <div className={cn(\"grid transition-[grid-template-rows] duration-200 ease-hairline\", isOpen ? \"grid-rows-[1fr]\" : \"grid-rows-[0fr]\")}>\n                  <div className=\"min-h-0 overflow-hidden\">\n                    <p className=\"mb-2 rounded-lg border border-border bg-sunken/70 px-3 py-2 font-mono text-[11.5px] leading-[1.6] text-fg-muted\">{s.detail}</p>\n                  </div>\n                </div>\n              ) : null}\n              {!last ? <div className=\"h-1.5\" /> : null}\n            </li>\n          )\n        })}\n      </ol>\n    </div>\n  )\n}\nexport { AgentTrace }\n"
    }
  ]
}
