{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scope-chat",
  "title": "Scope Chat",
  "description": "AI scoping chat UI. Wire CONTENT.endpoint (Host API).",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@atroui/utils"
  ],
  "files": [
    {
      "path": "registry/default/blocks/scope-chat.tsx",
      "content": "\"use client\"\n\nimport { Bot, Loader2, Send, User } from \"lucide-react\"\nimport { useState, type FormEvent } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Scope chat UI shell. Wire CONTENT.endpoint to your AI host API.\n */\nconst CONTENT = {\n  endpoint: \"/api/scope\",\n  placeholder: \"Describe the product you want to ship…\",\n  emptyHint: \"Ask for a fixed-scope plan. Host API required for replies.\",\n  maxMessages: 40,\n}\n\ntype Msg = { role: \"user\" | \"assistant\"; content: string }\n\nexport function ScopeChat() {\n  const [messages, setMessages] = useState<Msg[]>([])\n  const [input, setInput] = useState(\"\")\n  const [loading, setLoading] = useState(false)\n  const [error, setError] = useState<string | null>(null)\n\n  async function onSubmit(e: FormEvent) {\n    e.preventDefault()\n    const text = input.trim()\n    if (!text || loading) return\n    setInput(\"\")\n    setError(null)\n    const next: Msg[] = [...messages, { role: \"user\", content: text }].slice(\n      -CONTENT.maxMessages\n    )\n    setMessages(next)\n    setLoading(true)\n    try {\n      const res = await fetch(CONTENT.endpoint, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ messages: next }),\n      })\n      if (!res.ok) throw new Error(`Request failed (${res.status})`)\n      const data = (await res.json()) as { reply?: string }\n      setMessages((m) =>\n        [\n          ...m,\n          {\n            role: \"assistant\" as const,\n            content: data.reply ?? \"No reply from host API.\",\n          },\n        ].slice(-CONTENT.maxMessages)\n      )\n    } catch (err) {\n      setError(err instanceof Error ? err.message : \"Request failed\")\n    } finally {\n      setLoading(false)\n    }\n  }\n\n  return (\n    <div className=\"flex min-h-[420px] flex-col overflow-hidden rounded-2xl border border-border-subtle bg-card/40\">\n      <div className=\"border-b border-border-subtle px-4 py-3\">\n        <p className=\"ms-stamp\">Scope chat</p>\n        <p className=\"mt-1 text-xs text-muted-foreground\">{CONTENT.emptyHint}</p>\n      </div>\n      <div className=\"flex-1 space-y-3 overflow-y-auto p-4\">\n        {messages.length === 0 ? (\n          <p className=\"text-sm text-muted-foreground\">{CONTENT.placeholder}</p>\n        ) : (\n          messages.map((m, i) => (\n            <div\n              key={`${m.role}-${i}`}\n              className={cn(\n                \"flex gap-2 text-sm\",\n                m.role === \"user\" ? \"justify-end\" : \"justify-start\"\n              )}\n            >\n              {m.role === \"assistant\" ? (\n                <Bot className=\"mt-0.5 size-4 shrink-0 text-brand\" />\n              ) : null}\n              <p\n                className={cn(\n                  \"max-w-[85%] rounded-2xl px-3 py-2\",\n                  m.role === \"user\"\n                    ? \"bg-brand text-white\"\n                    : \"border border-border-subtle bg-background\"\n                )}\n              >\n                {m.content}\n              </p>\n              {m.role === \"user\" ? (\n                <User className=\"mt-0.5 size-4 shrink-0 text-muted-foreground\" />\n              ) : null}\n            </div>\n          ))\n        )}\n        {error ? <p className=\"text-sm text-destructive\">{error}</p> : null}\n      </div>\n      <form\n        onSubmit={onSubmit}\n        className=\"flex gap-2 border-t border-border-subtle p-3\"\n      >\n        <input\n          value={input}\n          onChange={(e) => setInput(e.target.value)}\n          placeholder={CONTENT.placeholder}\n          className=\"min-w-0 flex-1 rounded-lg border border-border-subtle bg-background px-4 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n        />\n        <button\n          type=\"submit\"\n          disabled={loading}\n          className=\"inline-flex size-10 items-center justify-center rounded-lg bg-brand text-white disabled:opacity-60\"\n          aria-label=\"Send\"\n        >\n          {loading ? (\n            <Loader2 className=\"size-4 animate-spin\" />\n          ) : (\n            <Send className=\"size-4\" />\n          )}\n        </button>\n      </form>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/blocks/scope-chat.tsx"
    }
  ],
  "type": "registry:block"
}