React AI
The useAIStream hook and AIStreamProvider connect your React components to the AI streaming WebSocket. Import from @absolutejs/ai/react.
#useAIStream
The primary hook for AI streaming. Pass the WebSocket path and an optional conversation ID. It manages the connection, message state, and streaming lifecycle.
TSX
import { useAIStream } from '@absolutejs/ai/react';
export const Chat = ({ conversationId }: { conversationId?: string }) => {
const { messages, send, cancel, branch, isStreaming, error } =
useAIStream('/chat', conversationId);
const handleSend = (text: string) => {
send(text);
};
return (
<div>
{messages.map((msg) => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
{msg.thinking && (
<details>
<summary>Thinking</summary>
<p>{msg.thinking}</p>
</details>
)}
{msg.toolCalls?.map((tool) => (
<details key={tool.name}>
<summary>Tool: {tool.name}</summary>
<pre>{tool.result}</pre>
</details>
))}
</div>
))}
{isStreaming && <button onClick={cancel}>Stop</button>}
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
};#Return Type
TS
// useAIStream return type
{
// Send a message with optional file attachments
send: (content: string, attachments?: AIAttachment[]) => void;
// Cancel the current streaming response
cancel: () => void;
// Branch conversation from a specific message
branch: (messageId: string, content: string) => void;
// Current conversation messages
messages: AIMessage[];
// Whether a response is currently streaming
isStreaming: boolean;
// Error message or null
error: string | null;
}#AIStreamProvider
Wrap your component tree with AIStreamProvider to share a single WebSocket connection across multiple components. Child components can call useAIStream() without a path argument to use the shared connection.
TSX
import { AIStreamProvider } from '@absolutejs/ai/react';
// Wrap your app to share a single WebSocket connection
export const App = ({ children }: { children: React.ReactNode }) => (
<AIStreamProvider path="/chat">
{children}
</AIStreamProvider>
);
// Any descendant can call useAIStream() without a path
import { useAIStream } from '@absolutejs/ai/react';
const ChatWidget = () => {
// Uses the connection from AIStreamProvider
const { messages, send } = useAIStream();
// ...
};#File Attachments
Send images and PDFs alongside messages by converting files to base64 and passing them as the second argument to send().
TSX
import { useAIStream } from '@absolutejs/ai/react';
import type { AIAttachment } from '@absolutejs/absolute';
const ChatWithFiles = () => {
const { send } = useAIStream('/chat');
const handleFileUpload = async (file: File) => {
const buffer = await file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));
const attachment: AIAttachment = {
data: base64,
media_type: file.type as AIAttachment['media_type'],
name: file.name,
};
send('Describe this image', [attachment]);
};
return <input type="file" onChange={(e) => {
if (e.target.files?.[0]) handleFileUpload(e.target.files[0]);
}} />;
};