@hanzo/chat
v1.0.0
Published
The simple Hanzo chat UI — a small, composable React chat surface (hanzo.chat, and the chat pane of hanzo.app). Built on @hanzo/ai (headless client) and @hanzo/gui (Radix-free primitives).
Downloads
337
Readme
@hanzo/chat
The simple Hanzo chat UI — a small, composable React chat surface. This is the "dumbed-down" chat that powers hanzo.chat, and the chat pane of hanzo.app.
It is two things:
<Chat/>— a batteries-included surface: model picker, streaming transcript, composer. Drop it in and go.- Pieces + hooks —
MessageList,MessageBubble,Composer,ModelPicker,ConversationList, and the headlessuseChat/useConversationshooks. Compose your own surface when you need control.
Built on:
@hanzo/ai— the headless client: chat completions, streaming, and the portable conversation store (chats+chats.messages). All API/streaming lives there; this package never re-implements it.@hanzo/gui— the UI primitives (XStack,Button,TextArea,Select,ScrollView, …). No Radix, no Tailwind, no shadcn.
Install
npm install @hanzo/chat @hanzo/ai @hanzo/gui react react-dom@hanzo/ai, @hanzo/gui, and react are peer dependencies.
React version:
@hanzo/gui@7requires React ≥ 19. The headless hooks (useChat,useConversations) work on React ≥ 18, but the rendered components inherit@hanzo/gui's React 19 requirement.
Setup
@hanzo/chat renders @hanzo/gui components, so your app must be wrapped in a
GuiProvider with a Gui config, and have react-native-web available (the gui
web renderer). This is the standard @hanzo/gui app setup — see its docs. In
short:
import { GuiProvider } from "@hanzo/gui";
import config from "./gui.config"; // your createGui(...) config
export function App({ children }: { children: React.ReactNode }) {
return <GuiProvider config={config} defaultTheme="dark">{children}</GuiProvider>;
}Quick start
import { createAiClient, Chat } from "@hanzo/chat";
const client = createAiClient({
// Defaults to https://api.hanzo.ai. Bearer token from @hanzo/iam.
getToken: () => session.accessToken,
});
export function ChatPage() {
return <Chat client={client} model="zen-1" />;
}That's the whole hanzo.chat surface: pick a model, type, watch it stream.
Compose it yourself
<Chat/> is just useChat + the pieces. Wire them up directly for full control:
import {
createAiClient,
useChat,
MessageList,
Composer,
ModelPicker,
} from "@hanzo/chat";
import { YStack } from "@hanzo/gui";
import { useState } from "react";
const client = createAiClient({ getToken });
function MyChat() {
const [model, setModel] = useState("zen-1");
const chat = useChat({ client, model, options: { temperature: 0.7 } });
return (
<YStack flex={1}>
<ModelPicker client={client} value={model} onChange={setModel} />
<MessageList messages={chat.messages} />
<Composer
onSend={chat.send}
onStop={chat.stop}
busy={chat.isLoading}
disabled={!model}
/>
</YStack>
);
}Conversations
useConversations binds the portable @hanzo/ai chat store — list, open, new,
and delete threads that follow the user across hanzo.chat, hanzo.app, and the
desktop app.
import { useConversations, ConversationList } from "@hanzo/chat";
function Sidebar({ client, user }) {
const convos = useConversations({ client, user });
return (
<ConversationList
conversations={convos.conversations}
onSelect={async (chat) => {
const messages = await convos.loadMessages(chat);
/* hand `messages` to useChat via setMessages */
}}
onNew={() => convos.create("New chat")}
onDelete={convos.remove}
loading={convos.loading}
/>
);
}API
<Chat client model? options? hideModelPicker? placeholder? emptyState? initialMessages? />
The composed surface. client is required; model selects the initial model.
useChat({ client, model, initialMessages?, options?, onFinish?, onError? })
The headless brain. Returns { messages, status, isLoading, error, send, stop,
setMessages, clear }. Drives one streaming completion at a time via
client.chat.completions.create({ stream: true }).
useConversations({ client, user, store?, autoLoad? })
Returns { conversations, loading, error, refresh, loadMessages, create,
remove } over the @hanzo/ai chats store.
Components
MessageList, MessageBubble, Composer, ModelPicker, ConversationList —
all pure presentation over @hanzo/gui. See their prop types.
License
Apache-2.0 © Hanzo AI Inc.
