{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tool",
  "type": "registry:component",
  "title": "Tool",
  "description": "Tool display/interaction component",
  "registryDependencies": [
    "tabs",
    "accordion"
  ],
  "files": [
    {
      "path": "components/chatcn/ai/tool.tsx",
      "content": "\"use client\";\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from \"@/components/ui/accordion\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport {\n  Loading03Icon,\n  CheckmarkCircle01Icon,\n  CancelCircleIcon,\n} from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\nimport { useContext, createContext, useState, useEffect } from \"react\";\n\ntype State = \"LOADING\" | \"COMPLETED\" | \"ERROR\";\n\ntype ToolContextType = {\n  output?: Record<string, unknown>;\n  input?: Record<string, unknown>;\n  errorText?: string;\n  state: State;\n  setState: React.Dispatch<React.SetStateAction<State>>;\n};\n\nconst ToolContext = createContext<ToolContextType | null>(null);\n\nexport function useToolContext() {\n  const ctx = useContext(ToolContext);\n  if (!ctx) {\n    throw new Error(\"useToolContext must be used within a Tool\");\n  }\n  return ctx;\n}\n\nexport type StateBadgeProps = {\n  className?: string;\n};\n\nexport function ToolStateBadge({ className }: StateBadgeProps) {\n  const { state } = useToolContext();\n  const getBadgeStyles = () => {\n    switch (state) {\n      case \"LOADING\":\n        return \"bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400\";\n      case \"COMPLETED\":\n        return \"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400\";\n      case \"ERROR\":\n        return \"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400\";\n      default:\n        return \"\";\n    }\n  };\n\n  const getIcon = () => {\n    switch (state) {\n      case \"LOADING\":\n        return (\n          <HugeiconsIcon\n            icon={Loading03Icon}\n            className=\"animate-spin w-3.5 h-3.5\"\n          />\n        );\n      case \"COMPLETED\":\n        return (\n          <HugeiconsIcon icon={CheckmarkCircle01Icon} className=\"w-3.5 h-3.5\" />\n        );\n      case \"ERROR\":\n        return (\n          <HugeiconsIcon icon={CancelCircleIcon} className=\"w-3.5 h-3.5\" />\n        );\n      default:\n        return null;\n    }\n  };\n\n  return (\n    <Badge\n      className={cn(\n        \"flex items-center gap-1 rounded-full\",\n        getBadgeStyles(),\n        className\n      )}\n    >\n      {getIcon()}\n      <span className=\"lowercase first-letter:uppercase\">{state}</span>\n    </Badge>\n  );\n}\n\nconst getTriggerIcon = (state: string) => {\n  switch (state) {\n    case \"LOADING\":\n      return (\n        <HugeiconsIcon\n          icon={Loading03Icon}\n          className=\"animate-spin text-muted-foreground\"\n          size={18}\n        />\n      );\n    case \"COMPLETED\":\n      return (\n        <HugeiconsIcon\n          icon={CheckmarkCircle01Icon}\n          className=\"text-green-500\"\n          size={18}\n        />\n      );\n    case \"ERROR\":\n      return (\n        <HugeiconsIcon\n          icon={CancelCircleIcon}\n          className=\"text-red-500\"\n          size={18}\n        />\n      );\n    default:\n      return null;\n  }\n};\n\ntype RenderTableProps = {\n  data: Record<string, unknown> | undefined;\n};\n\nfunction RenderTable({ data }: RenderTableProps) {\n  if (!data) return null;\n  return (\n    <div className=\"border p-2 px-3 rounded text-sm max-h-64 overflow-auto\">\n      {Object.entries(data).map(([key, value]) => (\n        <div\n          key={key}\n          className=\"border-b-1 mb-2 last:border-0 pb-2 grid grid-cols-3\"\n        >\n          <span className=\"text-muted-foreground font-mono\">{key}:</span>\n          <pre className=\"col-span-2 text-sm overflow-x-hidden\">\n            {typeof value === \"object\"\n              ? JSON.stringify(value, null, 2)\n              : String(value)}\n          </pre>\n        </div>\n      ))}\n    </div>\n  );\n}\n\ntype ToolProps = {\n  children?: React.ReactNode;\n  output?: Record<string, unknown>;\n  input?: Record<string, unknown>;\n  name: string;\n  errorText?: string;\n  state: State;\n};\n\nexport function Tool({\n  children,\n  output,\n  input,\n  errorText,\n  state,\n  name,\n}: ToolProps) {\n  const [badgeState, setbadgeState] = useState<State>(state);\n  useEffect(() => {\n    setbadgeState(state);\n  }, [state]);\n  return (\n    <ToolContext.Provider\n      value={{\n        state: badgeState,\n        setState: setbadgeState,\n        output,\n        input,\n        errorText,\n      }}\n    >\n      <Accordion\n        type=\"single\"\n        collapsible\n        className=\"border rounded-md px-3 w-md\"\n      >\n        <AccordionItem value=\"item-1\">\n          <AccordionTrigger className=\"no-underline hover:no-underline\">\n            <div className=\"flex gap-2 items-center\">\n              {getTriggerIcon(badgeState)}\n              {name}\n              {children}\n            </div>\n          </AccordionTrigger>\n          <AccordionContent className=\"flex justify-center\">\n            <Tabs defaultValue=\"table\" className=\"w-[400px]\">\n              <TabsList className=\"bg-transparent w-full\">\n                <TabsTrigger\n                  value=\"table\"\n                  className=\"text-muted-foreground data-[state=active]:text-foreground px-0 text-sm data-[state=active]:shadow-none dark:data-[state=active]:border-transparent dark:data-[state=active]:bg-transparent\"\n                >\n                  Table\n                </TabsTrigger>\n                <TabsTrigger\n                  value=\"json\"\n                  className=\"text-muted-foreground data-[state=active]:text-foreground px-0 text-sm data-[state=active]:shadow-none dark:data-[state=active]:border-transparent dark:data-[state=active]:bg-transparent\"\n                >\n                  JSON\n                </TabsTrigger>\n              </TabsList>\n              <TabsContent value=\"table\" className=\"space-y-4\">\n                {badgeState === \"LOADING\" && (\n                  <p className=\"animate-pulse\">Processing...</p>\n                )}\n\n                {badgeState === \"ERROR\" && errorText && (\n                  <div className=\"space-y-2\">\n                    <p className=\"text-muted-foreground\">Error</p>\n                    <div className=\"border p-2 rounded text-sm text-red-500 bg-red-50 dark:bg-red-900/20\">\n                      {errorText}\n                    </div>\n                  </div>\n                )}\n\n                {badgeState === \"COMPLETED\" && (\n                  <>\n                    <div className=\"space-y-2\">\n                      <p className=\"text-muted-foreground\">Input</p>\n                      <RenderTable data={input} />\n                    </div>\n                    <div className=\"space-y-2\">\n                      <p className=\"text-muted-foreground\">Output</p>\n\n                      <RenderTable data={output} />\n                    </div>\n                  </>\n                )}\n              </TabsContent>\n              <TabsContent value=\"json\">\n                {badgeState === \"LOADING\" && (\n                  <p className=\"animate-pulse\">Processing...</p>\n                )}\n\n                {badgeState === \"ERROR\" && errorText && (\n                  <div className=\"space-y-2\">\n                    <p className=\"text-muted-foreground\">Error</p>\n                    <div className=\"border p-2 rounded text-sm text-red-500 bg-red-50 dark:bg-red-900/20\">\n                      {errorText}\n                    </div>\n                  </div>\n                )}\n                {badgeState === \"COMPLETED\" && (\n                  <>\n                    <div className=\"space-y-2\">\n                      <p className=\"text-muted-foreground\">Input</p>\n                      <div className=\"space-y-3\">\n                        <pre className=\"whitespace-pre-wrap break-words max-h-28 overflow-auto border p-2 rounded text-sm b\">\n                          {JSON.stringify(input ?? {}, null, 2)}\n                        </pre>\n                        <div className=\"space-y-2\">\n                          <p className=\"text-muted-foreground\">Output</p>\n                          <pre className=\"whitespace-pre-wrap break-words max-h-72 overflow-auto border p-2 rounded text-sm\">\n                            {JSON.stringify(output ?? {}, null, 2)}\n                          </pre>\n                        </div>\n                      </div>\n                    </div>\n                  </>\n                )}\n              </TabsContent>\n            </Tabs>\n          </AccordionContent>\n        </AccordionItem>\n      </Accordion>\n    </ToolContext.Provider>\n  );\n}\n",
      "type": "registry:component"
    }
  ]
}