# `@bytelyst/ai-ui`

AI-native UI primitives for ByteLyst products. The flagship deliverable
of Wave 2 in `learning_ai_uxui_web/docs/ROADMAP_2026.md`.

> **Status:** `0.1.0` MVP — 3 components + 1 hook + 1 utility.
> Subsequent 0.x bumps add `<ToolCallCard>`, `<CitationChip>`,
> `<AgentTimeline>`, `<ModelPicker>`, `<ToolPalette>`, and the
> `useToolCalls` / `usePromptHistory` / `useTokenCount` hooks.

## Quick start

```tsx
import { ChatStream } from '@bytelyst/ai-ui';

export function ChatPage() {
  return (
    <div style={{ height: '70vh' }}>
      <ChatStream
        endpoint="/api/chat"
        placeholder="Ask anything…"
        emptyState={<EmptyHint />}
      />
    </div>
  );
}
```

## Architectural decisions

Per `learning_ai_common_plat/docs/ROADMAP_2026_DECISIONS.md`:

- **§10 hook shape** — `useChat()` returns the **same shape as Vercel
  AI SDK's `useChat`**. Drop-in compatible for any engineer who has
  already written a chat UI with the AI SDK.
- **Transport is pluggable** — products inject `endpoint`,
  `streamProtocol`, `fetcher`, or `headers`. We are not locked to
  Vercel's SSE wire format.

## Components

### `<ChatStream>`

Opinionated composition of `useChat` + `<MessageBubble>` +
`<PromptComposer>`. Auto-scrolls (sticky-bottom), shows Stop while
streaming, surfaces transport errors inline.

### `<MessageBubble>`

Single chat message atom. Variants by role (user / assistant / system /
tool). Built-in "thinking" indicator while streaming with no content
yet. Honors `--bl-*` design tokens.

### `<PromptComposer>`

Multi-line input. Enter submits, Shift+Enter newlines, Cmd/Ctrl+Enter
alternates submit. Auto-grows up to `maxLines`. Slot for leading
actions (slash-commands etc.).

## Hooks

### `useChat(options?)`

Vercel-AI-SDK-shaped:

```ts
const {
  messages, input, setInput, handleInputChange, handleSubmit,
  append, isLoading, error, stop, reload, setMessages
} = useChat({
  endpoint: '/api/chat',
  streamProtocol: 'text',   // 'text' | 'sse' | 'data'
  initialMessages: [],
  onFinish: (msg) => console.log('done', msg),
  onError:  (err) => console.error(err),
});
```

### `streamText(response, protocol?, signal?)`

Low-level async generator that yields text deltas from a streaming
HTTP response. Supports `'text'`, `'sse'`, and `'data'` protocols.

## Wire protocols

| Protocol | Body format | Use when |
|---|---|---|
| `'text'` (default) | Plain text, streamed chunk-by-chunk | Any backend that pipes an LLM stream directly |
| `'sse'` | Server-Sent Events with `data: ...` frames | OpenAI-compatible, Anthropic, most HF inference |
| `'data'` | Vercel AI SDK "data stream" prefix protocol | Backends using `streamText()` from `ai/server` |

For tool calls / citations / images, use `'sse'` or `'data'` once the
matching components ship in `0.2.x`.

## Tests

```sh
pnpm --filter @bytelyst/ai-ui test
```

## Roadmap

- `0.2.0` — `<ToolCallCard>`, `<CitationChip>`, `useToolCalls()`
- `0.3.0` — `<AgentTimeline>`, `<ModelPicker>`
- `0.4.0` — `<ToolPalette>` with MCP discovery
- `0.5.0` — `<Markdown>` + `<CodeDiff>` (Wave 2 stretch)
- `1.0.0` — API freeze when 3+ products consume in production
