108 lines
3.1 KiB
Markdown
108 lines
3.1 KiB
Markdown
# `@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
|