{"$schema":"https://ui.shadcn.com/schema/registry-item.json","dependencies":["ai","lucide-react"],"description":"AI-powered tool component.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/registry/default/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\nimport type { DynamicToolUIPart, ToolUIPart } from \"ai\";\nimport {\n  CheckCircleIcon,\n  ChevronDownIcon,\n  CircleIcon,\n  ClockIcon,\n  WrenchIcon,\n  XCircleIcon,\n} from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { isValidElement } from \"react\";\n\nimport { CodeBlock } from \"./code-block\";\n\nexport type ToolProps = ComponentProps<typeof Collapsible>;\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n  <Collapsible\n    className={cn(\"group not-prose mb-4 w-full rounded-md border\", className)}\n    {...props}\n  />\n);\n\nexport type ToolPart = ToolUIPart | DynamicToolUIPart;\n\nexport type ToolHeaderProps = {\n  title?: string;\n  className?: string;\n} & (\n  | { type: ToolUIPart[\"type\"]; state: ToolUIPart[\"state\"]; toolName?: never }\n  | {\n      type: DynamicToolUIPart[\"type\"];\n      state: DynamicToolUIPart[\"state\"];\n      toolName: string;\n    }\n);\n\nconst statusLabels: Record<ToolPart[\"state\"], string> = {\n  \"approval-requested\": \"Awaiting Approval\",\n  \"approval-responded\": \"Responded\",\n  \"input-available\": \"Running\",\n  \"input-streaming\": \"Pending\",\n  \"output-available\": \"Completed\",\n  \"output-denied\": \"Denied\",\n  \"output-error\": \"Error\",\n};\n\nconst statusIcons: Record<ToolPart[\"state\"], ReactNode> = {\n  \"approval-requested\": <ClockIcon className=\"size-4 text-yellow-600\" />,\n  \"approval-responded\": <CheckCircleIcon className=\"size-4 text-blue-600\" />,\n  \"input-available\": <ClockIcon className=\"size-4 animate-pulse\" />,\n  \"input-streaming\": <CircleIcon className=\"size-4\" />,\n  \"output-available\": <CheckCircleIcon className=\"size-4 text-green-600\" />,\n  \"output-denied\": <XCircleIcon className=\"size-4 text-orange-600\" />,\n  \"output-error\": <XCircleIcon className=\"size-4 text-red-600\" />,\n};\n\nexport const getStatusBadge = (status: ToolPart[\"state\"]) => (\n  <Badge className=\"gap-1.5 rounded-full text-xs\" variant=\"secondary\">\n    {statusIcons[status]}\n    {statusLabels[status]}\n  </Badge>\n);\n\nexport const ToolHeader = ({\n  className,\n  title,\n  type,\n  state,\n  toolName,\n  ...props\n}: ToolHeaderProps) => {\n  const derivedName =\n    type === \"dynamic-tool\" ? toolName : type.split(\"-\").slice(1).join(\"-\");\n\n  return (\n    <CollapsibleTrigger\n      className={cn(\n        \"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        <WrenchIcon className=\"size-4 text-muted-foreground\" />\n        <span className=\"font-medium text-sm\">{title ?? derivedName}</span>\n        {getStatusBadge(state)}\n      </div>\n      <ChevronDownIcon className=\"size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180\" />\n    </CollapsibleTrigger>\n  );\n};\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n  <CollapsibleContent\n    className={cn(\n      \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 space-y-4 p-4 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n      className\n    )}\n    {...props}\n  />\n);\n\nexport type ToolInputProps = ComponentProps<\"div\"> & {\n  input: ToolPart[\"input\"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n  <div className={cn(\"space-y-2 overflow-hidden\", 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: ToolPart[\"output\"];\n  errorText: ToolPart[\"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 = (\n      <CodeBlock code={JSON.stringify(output, null, 2)} language=\"json\" />\n    );\n  } else if (typeof output === \"string\") {\n    Output = <CodeBlock code={output} language=\"json\" />;\n  }\n\n  return (\n    <div className={cn(\"space-y-2\", 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","path":"registry/default/ai-elements/tool.tsx","target":"components/ai-elements/tool.tsx","type":"registry:component"}],"name":"tool","registryDependencies":["badge","collapsible","https://elements.ai-sdk.dev/api/registry/code-block.json"],"title":"Tool","type":"registry:component"}