Chatbot
new 7.4 kB<hk-chatbot>A complete assistant surface with the vendor left out. The engine is plain TypeScript: it owns the transcript, streams tokens into the current message, runs whatever tools you registered and feeds the results back for another round. What talks to a model is a single function you supply, so the demo runs on a local transport with no key and no network, and going live is one swap. Voice is both directions — dictation into the composer, synthesis out of it — and both are feature-detected, so a browser without them simply does not show the button.
Live demo
Running in this page — interact with it.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| transport | HkChatTransport | — | Turns a request into an async stream of chunks. The only thing that knows about a model. |
| systemPrompt | string | '' | Seeded as the first message and restored on reset(). Never rendered as a bubble. |
| tools | HkTool[] | [] | Initial tool registry. Add to it later with registerTool(). |
| maxToolRounds | number | 3 | How many tool rounds one turn may take, so a model that keeps calling itself cannot loop forever. |
| speakReplies | boolean | false | Read replies aloud as they stream, a sentence at a time. |
Outputs
onChange(messages: HkChatMessage[]) => voidFires on every mutation with a fresh array, so a signal can hold it.
onToolCall(call: HkToolCall) => voidFires per finished call, with args, result and elapsed ms.
Methods
send(text)(text: string) => Promise<void>Runs a full turn: stream, tool calls, and the rounds they trigger.
registerTool(tool)(tool: HkTool) => voidAdd or replace a tool, including mid-conversation.
abort()() => voidCancels the in-flight turn and keeps whatever already streamed.
reset()() => voidClears the transcript back to the system prompt.
Keyboard
- Enter Send
- Shift + Enter Newline
- Esc Stop the in-flight reply
Theming
Component tokens, each falling back to a global one:
| Property | Default | Controls |
|---|---|---|
| --hk-chat-bubble-user | var(--hk-accent) | User bubble fill. |
| --hk-chat-bubble-bot | var(--hk-surface) | Assistant bubble fill. |
| --hk-chat-log-height | 20rem | Transcript height before it scrolls. |
Accessibility
- The transcript is role="log" with aria-live="polite", so a reply is announced without interrupting.
- Dictation and speech are feature-detected: an unsupported browser gets no dead button.
- Recording is signalled by colour, an animated ring and aria-pressed together, never colour alone.
- Every animation here — the caret, the tool spinner, the mic ring — stops under prefers-reduced-motion.