{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ai-tool",
  "title": "AI: Tool",
  "description": "Renders a single tool invocation with header, collapsible input and output.",
  "dependencies": [
    "@untitledui/icons@^0.0.22"
  ],
  "registryDependencies": [
    "@nx-ui/utils",
    "@nx-ui/badge",
    "@nx-ui/collapsible",
    "@nx-ui/ai-code-block",
    "@nx-ui/ai-types"
  ],
  "files": [
    {
      "path": "components/ai/tool.tsx",
      "content": "\"use client\"\n\nimport { type ComponentProps, type ReactNode, isValidElement } from \"react\"\nimport {\n  CheckCircle,\n  ChevronDown,\n  Circle,\n  Clock,\n  Tool01,\n  XCircle,\n} from \"@untitledui/icons\"\n\nimport { Badge } from \"@/components/ui/badge\"\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\"\nimport { cn } from \"@/lib/utils\"\n\nimport { CodeBlock } from \"./code-block\"\nimport type { ToolUIPart } from \"./types\"\n\nexport type ToolProps = ComponentProps<typeof Collapsible>\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n  <Collapsible\n    className={cn(\"not-prose mb-4 w-full rounded-lg border\", className)}\n    {...props}\n  />\n)\n\nexport type ToolHeaderProps = {\n  title?: string\n  type: ToolUIPart[\"type\"]\n  state: ToolUIPart[\"state\"]\n  className?: string\n}\n\nconst getStatusBadge = (status: ToolUIPart[\"state\"]) => {\n  const labels: Record<ToolUIPart[\"state\"], string> = {\n    \"input-streaming\": \"Pending\",\n    \"input-available\": \"Running\",\n    \"approval-requested\": \"Awaiting Approval\",\n    \"approval-responded\": \"Responded\",\n    \"output-available\": \"Completed\",\n    \"output-error\": \"Error\",\n    \"output-denied\": \"Denied\",\n  }\n\n  const icons: Record<ToolUIPart[\"state\"], ReactNode> = {\n    \"input-streaming\": <Circle className=\"size-4\" />,\n    \"input-available\": <Clock className=\"size-4 animate-pulse\" />,\n    \"approval-requested\": <Clock className=\"size-4 text-utility-yellow-600\" />,\n    \"approval-responded\": <CheckCircle className=\"size-4 text-utility-blue-600\" />,\n    \"output-available\": <CheckCircle className=\"size-4 text-utility-green-600\" />,\n    \"output-error\": <XCircle className=\"size-4 text-utility-red-600\" />,\n    \"output-denied\": <XCircle className=\"size-4 text-utility-orange-600\" />,\n  }\n\n  return (\n    <Badge className=\"gap-1.5 rounded-full text-xs\" variant=\"secondary\">\n      {icons[status]}\n      {labels[status]}\n    </Badge>\n  )\n}\n\nexport const ToolHeader = ({\n  className,\n  title,\n  type,\n  state,\n  ...props\n}: ToolHeaderProps) => (\n  <CollapsibleTrigger\n    className={cn(\n      \"group flex w-full items-center justify-between gap-4 p-3\",\n      className\n    )}\n    {...props}\n  >\n    <div className=\"flex items-center gap-2\">\n      <Tool01 className=\"size-4 text-muted-foreground\" />\n      <span className=\"font-medium text-sm\">\n        {title ?? type.split(\"-\").slice(1).join(\"-\")}\n      </span>\n      {getStatusBadge(state)}\n    </div>\n    <ChevronDown className=\"size-4 text-muted-foreground transition-transform group-data-panel-open:rotate-180\" />\n  </CollapsibleTrigger>\n)\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n  <CollapsibleContent\n    className={cn(\n      \"data-closed:fade-out-0 data-closed:slide-out-to-top-2 data-open:slide-in-from-top-2 text-popover-foreground outline-none data-closed:animate-out data-open:animate-in\",\n      className\n    )}\n    {...props}\n  />\n)\n\nexport type ToolInputProps = ComponentProps<\"div\"> & {\n  input: ToolUIPart[\"input\"]\n}\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n  <div className={cn(\"space-y-2 overflow-hidden p-4\", className)} {...props}>\n    <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n      Parameters\n    </h4>\n    <div className=\"rounded-md bg-muted/50\">\n      <CodeBlock code={JSON.stringify(input, null, 2)} language=\"json\" />\n    </div>\n  </div>\n)\n\nexport type ToolOutputProps = ComponentProps<\"div\"> & {\n  output: ToolUIPart[\"output\"]\n  errorText: ToolUIPart[\"errorText\"]\n}\n\nexport const ToolOutput = ({\n  className,\n  output,\n  errorText,\n  ...props\n}: ToolOutputProps) => {\n  if (!(output || errorText)) {\n    return null\n  }\n\n  let Output = <div>{output as ReactNode}</div>\n\n  if (typeof output === \"object\" && !isValidElement(output)) {\n    Output = <CodeBlock code={JSON.stringify(output, null, 2)} language=\"json\" />\n  } else if (typeof output === \"string\") {\n    Output = <CodeBlock code={output} language=\"json\" />\n  }\n\n  return (\n    <div className={cn(\"space-y-2 p-4\", className)} {...props}>\n      <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n        {errorText ? \"Error\" : \"Result\"}\n      </h4>\n      <div\n        className={cn(\n          \"overflow-x-auto rounded-md text-xs [&_table]:w-full\",\n          errorText\n            ? \"bg-destructive/10 text-destructive\"\n            : \"bg-muted/50 text-foreground\"\n        )}\n      >\n        {errorText && <div>{errorText}</div>}\n        {Output}\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:ui",
      "target": "components/ai/tool.tsx"
    }
  ],
  "type": "registry:ui"
}