{"_id":"@backendkit-labs/agent-web-ui","_rev":"2-8037db63d1e65e088b1d331b638a11b4","name":"@backendkit-labs/agent-web-ui","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@backendkit-labs/agent-web-ui","version":"0.1.0","_id":"@backendkit-labs/agent-web-ui@0.1.0","maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"dist":{"shasum":"9cc8e49ac8d298061d1271301cc052df47ec7f3c","tarball":"https://registry.npmjs.org/@backendkit-labs/agent-web-ui/-/agent-web-ui-0.1.0.tgz","fileCount":69,"integrity":"sha512-2Q0ITAaPE+ZnT1fbqGHdvS61MbNU6phnE5+pbiXlBdWfq82ql9mhLJLgYYoBJ5NR1cYOxmdg2TVcLBJdUbhrLg==","signatures":[{"sig":"MEQCIFSzo/+QKvhLZ+BY53QuQvnR1gVm0eBZ1PsNlKkGO6SYAiB33MC4AESOZpK0OYYMB0V3BTje800mchsgx3fHmH3pBg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":453126},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./style.css":"./dist/index.css"},"gitHead":"b33488e90949a87a4bd50a2ecf3ccd5691285b7c","scripts":{"dev":"vite","lint":"eslint .","build":"vite build","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json","prepublishOnly":"npm run build:lib"},"_npmUser":{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"},"_npmVersion":"11.8.0","description":"React chat + kanban monitor UI for @backendkit-labs/agent-web — streaming, tool badges, real-time agent activity board","directories":{},"_nodeVersion":"24.16.0","dependencies":{"clsx":"^2.1.1","remark-gfm":"^4.0.1","lucide-react":"^1.17.0","react-markdown":"^10.1.0","tailwind-merge":"^3.6.0","@radix-ui/react-slot":"^1.2.5","@radix-ui/react-avatar":"^1.1.12","@radix-ui/react-tooltip":"^1.2.9","class-variance-authority":"^0.7.1","@radix-ui/react-separator":"^1.1.9","@radix-ui/react-scroll-area":"^1.2.11","@radix-ui/react-dropdown-menu":"^2.1.17"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.12","eslint":"^10.3.0","globals":"^17.6.0","@eslint/js":"^10.0.1","typescript":"~6.0.2","@types/node":"^24.13.2","tailwindcss":"^4.3.0","@types/react":"^19.2.14","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.2.3","@tailwindcss/vite":"^4.3.0","typescript-eslint":"^8.59.2","@vitejs/plugin-react":"^6.0.1","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-react-refresh":"^0.5.2"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/agent-web-ui_0.1.0_1781174332190_0.877356157945101","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@backendkit-labs/agent-web-ui","version":"0.1.1","description":"React chat + kanban monitor UI for @backendkit-labs/agent-web — streaming, tool badges, real-time agent activity board","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./style.css":"./dist/index.css"},"scripts":{"dev":"vite","build":"vite build","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json","preview":"vite preview","lint":"eslint .","prepublishOnly":"npm run build:lib"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"dependencies":{"@radix-ui/react-avatar":"^1.1.12","@radix-ui/react-dropdown-menu":"^2.1.17","@radix-ui/react-scroll-area":"^1.2.11","@radix-ui/react-separator":"^1.1.9","@radix-ui/react-slot":"^1.2.5","@radix-ui/react-tooltip":"^1.2.9","class-variance-authority":"^0.7.1","clsx":"^2.1.1","lucide-react":"^1.17.0","react-markdown":"^10.1.0","remark-gfm":"^4.0.1","tailwind-merge":"^3.6.0"},"devDependencies":{"@eslint/js":"^10.0.1","@tailwindcss/vite":"^4.3.0","@types/node":"^24.13.2","@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@vitejs/plugin-react":"^6.0.1","eslint":"^10.3.0","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-react-refresh":"^0.5.2","globals":"^17.6.0","tailwindcss":"^4.3.0","typescript":"~6.0.2","typescript-eslint":"^8.59.2","vite":"^8.0.12","vite-plugin-dts":"^4.5.4"},"publishConfig":{"access":"public"},"engines":{"node":">=20.0.0"},"gitHead":"34c3a9ecdd1f90b38ff468ec087a0871029f96de","_id":"@backendkit-labs/agent-web-ui@0.1.1","_nodeVersion":"24.16.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-Uyfoh4ht3MIM6BZRvQmLdDdwcSLeQ1qybpVgwYEteOEpqQeC41rdW92V9BIzhAF6v5VQzeWvGzcFktJFzG2kiw==","shasum":"ae3a308a3f94afa6232360ae8de7903bdbcf6380","tarball":"https://registry.npmjs.org/@backendkit-labs/agent-web-ui/-/agent-web-ui-0.1.1.tgz","fileCount":69,"unpackedSize":465741,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAHa8ll7HrEmUokQp0XO1+Ov1qWvilnK0C9zAgEGOGeiAiEAtJMOfLrbPlafzIzf3lPrYesIZKe6n3IHOmWC1xUgOOo="}]},"_npmUser":{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"},"directories":{},"maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-web-ui_0.1.1_1781194721430_0.08308793385107593"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-11T10:38:52.044Z","modified":"2026-06-11T16:18:41.763Z","0.1.0":"2026-06-11T10:38:52.363Z","0.1.1":"2026-06-11T16:18:41.611Z"},"description":"React chat + kanban monitor UI for @backendkit-labs/agent-web — streaming, tool badges, real-time agent activity board","maintainers":[{"name":"backendkit.dev","email":"backendkit.dev@gmail.com"}],"readme":"# @backendkit-labs/agent-web-ui\n\nReact component library and hooks for building chat interfaces and real-time monitoring dashboards that connect to `@backendkit-labs/agent-web`.\n\nShips two ready-to-use app templates (`ChatApp`, `KanbanApp`) and composable primitives for building custom UIs.\n\n[![npm](https://img.shields.io/npm/v/@backendkit-labs/agent-web-ui)](https://www.npmjs.com/package/@backendkit-labs/agent-web-ui)\n\n## Table of contents\n\n- [Installation](#installation)\n- [Quick start](#quick-start)\n- [ChatApp — full chat interface](#chatapp--full-chat-interface)\n- [KanbanApp — real-time monitor](#kanbanapp--real-time-monitor)\n- [useAgentSession hook](#useagentsession-hook)\n- [useKanbanMonitor hook](#usekanbanmonitor-hook)\n- [Chat components](#chat-components)\n- [Kanban components](#kanban-components)\n- [NavTabs](#navtabs)\n- [Building a custom chat UI](#building-a-custom-chat-ui)\n- [Building a custom kanban](#building-a-custom-kanban)\n- [Styling](#styling)\n\n---\n\n## Installation\n\n```bash\nnpm install @backendkit-labs/agent-web-ui\n```\n\n**Peer dependencies** (install separately):\n\n```bash\nnpm install react react-dom\n```\n\n**Import styles** in your app entry point:\n\n```typescript\nimport '@backendkit-labs/agent-web-ui/style.css';\n```\n\n---\n\n## Quick start\n\nDrop in the full chat + kanban app with two components:\n\n```typescript\nimport '@backendkit-labs/agent-web-ui/style.css';\nimport ChatApp from '@backendkit-labs/agent-web-ui/ChatApp';\nimport KanbanApp from '@backendkit-labs/agent-web-ui/KanbanApp';\n\n// Full chat interface — connects to ws://localhost:3000/chat\nfunction App() {\n  return <ChatApp wsUrl=\"ws://localhost:3000/chat\" />;\n}\n\n// Full kanban monitor — connects to ws://localhost:3000/monitor\nfunction Monitor() {\n  return <KanbanApp wsUrl=\"ws://localhost:3000/monitor\" />;\n}\n```\n\n---\n\n## ChatApp — full chat interface\n\nA complete streaming chat UI with message bubbles, tool call badges, markdown rendering, and an input bar.\n\n```typescript\nimport ChatApp from '@backendkit-labs/agent-web-ui';\n\n<ChatApp\n  wsUrl=\"ws://localhost:3000/chat\"\n  token=\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"  // optional JWT\n  placeholder=\"Ask me anything...\"                   // optional\n  className=\"h-screen\"                               // optional CSS class\n/>\n```\n\n### With JWT authentication\n\nWhen your `AgentServer` requires JWT auth, pass the token. The component appends `?token=<jwt>` to the WebSocket URL (which is how `agent-web` validates browser WS connections that can't set `Authorization` headers):\n\n```typescript\n// Log in and store the token\nconst { token } = await fetch('/api/login', {\n  method: 'POST',\n  body: JSON.stringify({ email, password }),\n}).then(r => r.json());\n\n// Pass to ChatApp\n<ChatApp wsUrl=\"ws://api.company.com/chat\" token={token} />\n```\n\n---\n\n## KanbanApp — real-time monitor\n\nA Kanban board that shows all agent runs across all sessions in real time, organized into columns by status.\n\n```typescript\nimport KanbanApp from '@backendkit-labs/agent-web-ui';\n\n<KanbanApp\n  wsUrl=\"ws://localhost:3000/monitor\"\n  token={adminToken}    // optional JWT\n  className=\"h-screen\"\n/>\n```\n\n**Columns:**\n- **Pending** — triggered runs waiting to start\n- **Running** — actively executing (shows live token stream)\n- **Done** — completed successfully\n- **Error** — runs that failed\n\nEach card shows: session ID, agent name, input prompt, output preview, tool calls, and duration.\n\n---\n\n## useAgentSession hook\n\nThe core hook for building custom chat UIs. Manages the WebSocket connection, message state, and streaming.\n\n```typescript\nimport { useAgentSession } from '@backendkit-labs/agent-web-ui';\n\nfunction MyChat() {\n  const {\n    messages,       // ChatMessage[] — full conversation\n    status,         // 'idle' | 'connecting' | 'connected' | 'running' | 'error' | 'closed'\n    isRunning,      // boolean — a run is in progress\n    send,           // (text: string) => void — send a message\n    abort,          // () => void — cancel the current run\n  } = useAgentSession({\n    wsUrl: 'ws://localhost:3000/chat',\n    token: myJwtToken,         // optional\n    onError: (err) => console.error(err),\n    onDone:  (msg) => console.log('Run done:', msg),\n  });\n\n  return (\n    <div>\n      {messages.map(msg => (\n        <div key={msg.id} className={`message ${msg.role}`}>\n          {msg.content}\n        </div>\n      ))}\n      <button onClick={() => send('Hello!')} disabled={isRunning}>\n        Send\n      </button>\n    </div>\n  );\n}\n```\n\n### ChatMessage type\n\n```typescript\ninterface ChatMessage {\n  id:         string;\n  role:       'user' | 'assistant' | 'system';\n  content:    string;          // full text (built incrementally from tokens)\n  toolCalls?: ToolCall[];      // tools called during this message\n  isStreaming: boolean;        // true while tokens are still arriving\n  timestamp:  number;\n}\n\ninterface ToolCall {\n  name:   string;\n  args:   unknown;\n  result: string;\n}\n```\n\n### UseAgentSessionOptions\n\n```typescript\ninterface UseAgentSessionOptions {\n  wsUrl:      string;\n  token?:     string;                    // JWT token\n  onError?:   (err: string) => void;\n  onDone?:    (finalMessage: string) => void;\n  onConnect?: () => void;\n  onClose?:   () => void;\n}\n```\n\n### Connection status\n\n```typescript\ntype ConnectionStatus =\n  | 'idle'          // not yet connected\n  | 'connecting'    // WebSocket opening\n  | 'connected'     // open, waiting for input\n  | 'running'       // agent is generating a response\n  | 'error'         // connection or agent error\n  | 'closed';       // connection closed\n```\n\n---\n\n## useKanbanMonitor hook\n\nConnects to the `/monitor` WebSocket endpoint and provides live run state for building custom kanban boards.\n\n```typescript\nimport { useKanbanMonitor } from '@backendkit-labs/agent-web-ui';\n\nfunction MyMonitor() {\n  const {\n    columns,    // KanbanColumn[] — { id, title, runs: KanbanRun[] }\n    status,     // MonitorStatus\n    sessionIds, // string[] — all active session IDs\n  } = useKanbanMonitor({\n    wsUrl: 'ws://localhost:3000/monitor',\n    token: adminToken,\n  });\n\n  return (\n    <div className=\"grid grid-cols-4 gap-4\">\n      {columns.map(col => (\n        <div key={col.id}>\n          <h3>{col.title} ({col.runs.length})</h3>\n          {col.runs.map(run => (\n            <div key={run.sessionId} className=\"card\">\n              <p>{run.input}</p>\n              <p>{run.output}</p>\n              <span>{run.agentId}</span>\n            </div>\n          ))}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n### KanbanRun type\n\n```typescript\ninterface KanbanRun {\n  sessionId:  string;\n  input:      string;         // the user message that started the run\n  output:     string;         // accumulated output so far (live-updated)\n  agentId:    string;         // which agent is running\n  toolCalls:  KanbanToolCall[];\n  startedAt:  number;\n  endedAt?:   number;\n  error?:     string;\n}\n\ninterface KanbanToolCall {\n  name:   string;\n  args:   unknown;\n  result: string;\n}\n```\n\n### Column IDs\n\nThe four columns correspond to the run lifecycle:\n\n| Column ID | Title | Condition |\n|-----------|-------|-----------|\n| `pending` | Pending | Run started, waiting |\n| `running` | Running | Active token stream |\n| `done` | Done | `done` event received |\n| `error` | Error | `error` event received |\n\n---\n\n## Chat components\n\nIndividual chat components for building custom layouts:\n\n### ChatWindow\n\nContainer that renders a scrollable list of messages:\n\n```typescript\nimport { ChatWindow } from '@backendkit-labs/agent-web-ui';\n\n<ChatWindow\n  messages={messages}      // ChatMessage[]\n  className=\"flex-1\"\n/>\n```\n\n### MessageBubble\n\nA single message bubble with Markdown rendering and tool call badges:\n\n```typescript\nimport { MessageBubble } from '@backendkit-labs/agent-web-ui';\n\n<MessageBubble\n  message={msg}           // ChatMessage\n  showToolCalls={true}    // default: true\n/>\n```\n\n### InputBar\n\nThe text input with send button and abort support:\n\n```typescript\nimport { InputBar } from '@backendkit-labs/agent-web-ui';\n\n<InputBar\n  onSend={(text) => send(text)}\n  onAbort={() => abort()}\n  disabled={isRunning}\n  placeholder=\"Ask me anything...\"\n/>\n```\n\n### ToolCallBadge\n\nA collapsible badge showing a tool call and its result:\n\n```typescript\nimport { ToolCallBadge } from '@backendkit-labs/agent-web-ui';\n\n<ToolCallBadge\n  toolCall={{\n    name:   'search_files',\n    args:   { query: 'authentication' },\n    result: 'Found 3 files: src/auth/...',\n  }}\n/>\n```\n\n---\n\n## Kanban components\n\n### KanbanBoard\n\nThe board container:\n\n```typescript\nimport { KanbanBoard } from '@backendkit-labs/agent-web-ui';\n\n<KanbanBoard columns={columns} />   // KanbanColumn[]\n```\n\n### KanbanCard\n\nA single run card:\n\n```typescript\nimport { KanbanCard } from '@backendkit-labs/agent-web-ui';\n\n<KanbanCard run={run} />   // KanbanRun\n```\n\n---\n\n## NavTabs\n\nA tab bar for switching between Chat and Kanban views with hash routing (`#chat`, `#kanban`):\n\n```typescript\nimport { NavTabs } from '@backendkit-labs/agent-web-ui';\n\n<NavTabs\n  tabs={[\n    { id: 'chat',   label: 'Chat' },\n    { id: 'kanban', label: 'Monitor' },\n  ]}\n  activeTab={activeTab}\n  onTabChange={setActiveTab}\n/>\n```\n\n---\n\n## Building a custom chat UI\n\nFull example with custom styling:\n\n```typescript\nimport { useAgentSession, MessageBubble, InputBar } from '@backendkit-labs/agent-web-ui';\nimport '@backendkit-labs/agent-web-ui/style.css';\n\nfunction MyCustomChat({ wsUrl, token }: { wsUrl: string; token?: string }) {\n  const { messages, status, isRunning, send, abort } = useAgentSession({\n    wsUrl,\n    token,\n  });\n\n  return (\n    <div className=\"flex flex-col h-screen bg-gray-50\">\n      {/* Status bar */}\n      <div className=\"px-4 py-2 bg-white border-b text-sm text-gray-500\">\n        {status === 'connected' && 'Connected'}\n        {status === 'running' && '⟳ Generating...'}\n        {status === 'error' && '✗ Connection error'}\n      </div>\n\n      {/* Messages */}\n      <div className=\"flex-1 overflow-y-auto p-4 space-y-3\">\n        {messages.map(msg => (\n          <MessageBubble key={msg.id} message={msg} />\n        ))}\n      </div>\n\n      {/* Input */}\n      <div className=\"border-t bg-white p-4\">\n        <InputBar\n          onSend={send}\n          onAbort={abort}\n          disabled={status !== 'connected' && !isRunning}\n          placeholder=\"Type a message...\"\n        />\n      </div>\n    </div>\n  );\n}\n```\n\n---\n\n## Building a custom kanban\n\n```typescript\nimport { useKanbanMonitor } from '@backendkit-labs/agent-web-ui';\nimport '@backendkit-labs/agent-web-ui/style.css';\n\nconst COLUMN_COLORS = {\n  pending: 'bg-yellow-50',\n  running: 'bg-blue-50',\n  done:    'bg-green-50',\n  error:   'bg-red-50',\n};\n\nfunction MyKanban({ wsUrl }: { wsUrl: string }) {\n  const { columns, status } = useKanbanMonitor({ wsUrl });\n\n  if (status === 'connecting') return <p>Connecting to monitor...</p>;\n\n  return (\n    <div className=\"flex gap-4 p-4 h-screen overflow-x-auto\">\n      {columns.map(col => (\n        <div key={col.id} className={`w-72 flex-shrink-0 rounded-lg p-3 ${COLUMN_COLORS[col.id]}`}>\n          <h2 className=\"font-semibold mb-3\">{col.title} ({col.runs.length})</h2>\n          <div className=\"space-y-2\">\n            {col.runs.map(run => (\n              <div key={run.sessionId} className=\"bg-white rounded p-3 shadow-sm text-sm\">\n                <div className=\"font-mono text-xs text-gray-400 mb-1\">{run.sessionId.slice(0, 8)}</div>\n                <div className=\"font-medium\">{run.agentId}</div>\n                <div className=\"text-gray-600 truncate\">{run.input}</div>\n                {run.output && (\n                  <div className=\"text-gray-500 text-xs mt-1 truncate\">{run.output.slice(0, 100)}</div>\n                )}\n                {run.toolCalls.length > 0 && (\n                  <div className=\"text-xs text-blue-500 mt-1\">\n                    {run.toolCalls.length} tool call{run.toolCalls.length > 1 ? 's' : ''}\n                  </div>\n                )}\n                {run.error && (\n                  <div className=\"text-red-500 text-xs mt-1\">{run.error}</div>\n                )}\n              </div>\n            ))}\n          </div>\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n---\n\n## Styling\n\nThe library uses Tailwind CSS internally. Import the stylesheet once in your app:\n\n```typescript\nimport '@backendkit-labs/agent-web-ui/style.css';\n```\n\n### Custom CSS variables\n\nOverride the theme by setting CSS variables in your app's root:\n\n```css\n:root {\n  --bk-primary:     #6366f1;   /* button and accent color */\n  --bk-bg:          #ffffff;   /* chat background */\n  --bk-user-bg:     #eff6ff;   /* user message bubble */\n  --bk-assistant-bg:#f9fafb;   /* assistant message bubble */\n}\n```\n\n### Integrating with existing Tailwind projects\n\nIf your project already uses Tailwind, add the library to your `content` array to avoid conflicts:\n\n```javascript\n// tailwind.config.js\nexport default {\n  content: [\n    './src/**/*.{ts,tsx}',\n    './node_modules/@backendkit-labs/agent-web-ui/src/**/*.{ts,tsx}',\n  ],\n};\n```\n","readmeFilename":"README.md"}