{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "command-agent-chat-example",
  "title": "Command Agent Chat Example",
  "description": "Atomic example for the Ink UI Command component.",
  "registryDependencies": [
    "command",
    "input-group"
  ],
  "files": [
    {
      "path": "registry/default/examples/command-agent-chat-example.tsx",
      "content": "import {\n  ArrowUpIcon,\n  BugIcon,\n  ChatCircleIcon,\n  CloudIcon,\n  FileTextIcon,\n  GitBranchIcon,\n  LightningIcon,\n  PlugsIcon,\n  PlusIcon,\n  SparkleIcon,\n  TargetIcon,\n} from \"@phosphor-icons/react\";\nimport { useRef, useState } from \"react\";\nimport {\n  Command,\n  CommandCollection,\n  CommandContent,\n  CommandEmpty,\n  CommandGroup,\n  CommandGroupLabel,\n  CommandInput,\n  CommandItem,\n  CommandItemDescription,\n  CommandItemLabel,\n  CommandList,\n  createCommandTrigger,\n} from \"registry/default/ui/command\";\nimport { InputGroup, InputGroupAddon, InputGroupButton } from \"registry/default/ui/input-group\";\n\nconst commandGroups = [\n  {\n    items: [\n      {\n        description: \"Don't work in a project\",\n        icon: ChatCircleIcon,\n        label: \"Chat\",\n        value: \"chat\",\n      },\n      {\n        description: \"Run this chat in the cloud\",\n        icon: CloudIcon,\n        label: \"Cloud\",\n        value: \"cloud\",\n      },\n      {\n        description: \"Set a goal to keep pursuing\",\n        icon: TargetIcon,\n        label: \"Goal\",\n        value: \"goal\",\n      },\n      {\n        description: \"2x speed, increased usage\",\n        icon: LightningIcon,\n        label: \"Fast\",\n        value: \"fast\",\n      },\n    ],\n    value: \"Session\",\n  },\n  {\n    items: [\n      {\n        description: \"Review uncommitted changes or compare against a branch\",\n        icon: BugIcon,\n        label: \"Code review\",\n        value: \"review\",\n      },\n      {\n        description: \"Run this chat in a new worktree\",\n        icon: GitBranchIcon,\n        label: \"Worktree\",\n        value: \"worktree\",\n      },\n      { description: \"Create an AGENTS.md file\", icon: FileTextIcon, label: \"Init\", value: \"init\" },\n      { description: \"Show MCP server status\", icon: PlugsIcon, label: \"MCP\", value: \"mcp\" },\n    ],\n    value: \"Project\",\n  },\n  {\n    items: [\n      {\n        description: \"Review the current diff for bugs\",\n        icon: SparkleIcon,\n        kind: \"skill\",\n        label: \"code-review\",\n        value: \"code-review\",\n      },\n      {\n        description: \"Open a pull request for this branch\",\n        icon: SparkleIcon,\n        kind: \"skill\",\n        label: \"create-pr\",\n        value: \"create-pr\",\n      },\n      {\n        description: \"Simplify the changed code\",\n        icon: SparkleIcon,\n        kind: \"skill\",\n        label: \"simplify\",\n        value: \"simplify\",\n      },\n    ],\n    value: \"Skills\",\n  },\n];\n\nconst fileGroups = [\n  {\n    items: [\n      \"AGENTS.md\",\n      \"package.json\",\n      \"registry/default/ui/command.tsx\",\n      \"registry/default/ui/input-group.tsx\",\n      \"registry/default/examples/command-agent-chat-example.tsx\",\n      \"src/styles/app.css\",\n    ].map((path) => ({\n      description: path,\n      icon: FileTextIcon,\n      kind: \"file\" as const,\n      label: path.split(\"/\").at(-1) ?? path,\n      value: path,\n    })),\n    value: \"Files\",\n  },\n];\n\ntype CommandGroupValue = (typeof commandGroups)[number] | (typeof fileGroups)[number];\ntype CommandItemValue = CommandGroupValue[\"items\"][number];\n\nconst slashTrigger = createCommandTrigger([\"/\", \"、\"]);\nconst fileTrigger = createCommandTrigger(\"@\", { position: \"anywhere\" });\nconst chatTrigger = (value: string, caret: number) =>\n  fileTrigger(value, caret) ?? slashTrigger(value, caret);\n\nexport function AgentChatCommandExample() {\n  const inputRef = useRef<HTMLInputElement>(null);\n  const [value, setValue] = useState(\"\");\n  const [isFileMention, setIsFileMention] = useState(false);\n  const [log, setLog] = useState<string[]>([]);\n\n  const submit = () => {\n    const text = value.trim();\n    if (!text) return;\n    setLog((entries) => [...entries, text].slice(-3));\n    setValue(\"\");\n  };\n\n  return (\n    <div className=\"flex w-full max-w-2xl flex-col gap-3\">\n      <div className=\"min-h-18 text-sm text-muted-foreground\">\n        {log.length === 0\n          ? \"Type / for commands or @ to reference a file.\"\n          : log.map((entry, index) => <p key={index}>{entry}</p>)}\n      </div>\n      <Command\n        confirmKey=\"both\"\n        items={isFileMention ? fileGroups : commandGroups}\n        itemToStringValue={(command: CommandItemValue) =>\n          \"kind\" in command && command.kind === \"file\" ? command.value : command.label\n        }\n        onSelect={(command: CommandItemValue, { match, value: next }) => {\n          if (\"kind\" in command && command.kind === \"file\") {\n            const at = match?.start ?? next.length;\n            const reference = `@${command.value}`;\n            const suffix = next.slice(at);\n            const separator = suffix.startsWith(\" \") ? \"\" : \" \";\n            setValue(`${next.slice(0, at)}${reference}${separator}${suffix}`);\n            requestAnimationFrame(() => {\n              const caret = at + reference.length + 1;\n              inputRef.current?.setSelectionRange(caret, caret);\n            });\n            return;\n          }\n          if (\"kind\" in command && command.kind === \"skill\") {\n            setValue(`/${command.value} `);\n            return;\n          }\n          setLog((entries) => [...entries, `Ran /${command.value}`].slice(-3));\n        }}\n        onValueChange={(next, eventDetails) => {\n          setValue(next);\n          if (eventDetails.reason === \"input-change\") {\n            const caret = inputRef.current?.selectionStart ?? next.length;\n            setIsFileMention(fileTrigger(next, caret) !== null);\n          }\n        }}\n        trigger={chatTrigger}\n        value={value}\n      >\n        <InputGroup className=\"items-stretch rounded-2xl bg-background\">\n          <CommandInput\n            className=\"min-h-16 py-4 text-base\"\n            multiline\n            onKeyDown={(event) => {\n              if (event.key === \"Enter\" && !event.shiftKey) {\n                event.preventDefault();\n                submit();\n              }\n            }}\n            placeholder=\"Ask anything. Type / for commands, @ for files\"\n            ref={inputRef}\n          />\n          <InputGroupAddon align=\"block-end\" className=\"justify-between gap-3 pt-3\">\n            <div className=\"flex items-center gap-2\">\n              <InputGroupButton aria-label=\"Attach file\" size=\"icon-sm\" variant=\"outline\">\n                <PlusIcon />\n              </InputGroupButton>\n            </div>\n            <InputGroupButton\n              aria-label=\"Submit message\"\n              onClick={submit}\n              size=\"icon-sm\"\n              variant=\"default\"\n            >\n              <ArrowUpIcon />\n            </InputGroupButton>\n          </InputGroupAddon>\n        </InputGroup>\n        <CommandContent>\n          <CommandEmpty>{isFileMention ? \"No files found.\" : \"No commands found.\"}</CommandEmpty>\n          <CommandList>\n            {(group: CommandGroupValue) => (\n              <CommandGroup items={group.items} key={group.value}>\n                <CommandGroupLabel>{group.value}</CommandGroupLabel>\n                <CommandCollection>\n                  {(command: CommandItemValue) => (\n                    <CommandItem key={command.value} value={command}>\n                      <command.icon />\n                      <CommandItemLabel>{command.label}</CommandItemLabel>\n                      <CommandItemDescription>{command.description}</CommandItemDescription>\n                    </CommandItem>\n                  )}\n                </CommandCollection>\n              </CommandGroup>\n            )}\n          </CommandList>\n        </CommandContent>\n      </Command>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/command-agent-chat-example.tsx"
    }
  ],
  "type": "registry:component"
}