Chat SDK
useChatContext
Access chat state and methods from any component within ChatProvider.
Usage
import { useChatContext } from 'react-chat-agent';
function MyComponent() {
const {
messages,
sendMsg,
isStreaming,
isLoading,
abort,
messageManager,
sessionId
} = useChatContext();
return <div>Chat Component</div>;
}Return Value
interface ChatContextValue {
// Messages
messages: Message[];
messageManager: MessageManager;
// State
isLoading: boolean;
isStreaming: boolean;
isResponseStarted: boolean;
isInitialLoading: boolean;
isLoadingMore: boolean;
// Actions
sendMsg: (params?: SendMessageParams) => Promise<void>;
abort: () => void;
retryLastMessage: () => Promise<void>;
// History
getHistory: () => Promise<void>;
loadMoreMessages: () => Promise<void>;
hasMoreMessages: boolean;
enableHistory: boolean;
// Errors
error: any;
streamError: any;
clearStreamError: () => void;
// Session
sessionId: string | undefined;
setSessionId: (id: string | undefined) => void;
instanceId: string;
// Configuration
welcome: any;
statusRegistry: StatusRegistry;
markdownComponents: any;
typingAnimation: TypingAnimationConfig;
statusComponents?: any;
loadingComponent?: ComponentType;
headerComponent?: ReactNode;
debug?: boolean;
// Files
currentSelectedFile: any;
setCurrentSelectedFile: (file: any) => void;
}Examples
Send Message
function SendButton() {
const { sendMsg, isLoading } = useChatContext();
const handleClick = async () => {
await sendMsg({
message: 'Hello, agent!',
attachedFiles: []
});
};
return (
<button onClick={handleClick} disabled={isLoading}>
Send
</button>
);
}Display Messages
function MessageList() {
const { messages } = useChatContext();
return (
<div>
{messages.map(msg => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
);
}Stream Control
function StreamControls() {
const { isStreaming, abort } = useChatContext();
if (!isStreaming) return null;
return (
<button onClick={abort}>
Stop Generation
</button>
);
}Message History
function HistoryLoader() {
const {
hasMoreMessages,
isLoadingMore,
loadMoreMessages
} = useChatContext();
if (!hasMoreMessages) return null;
return (
<button onClick={loadMoreMessages} disabled={isLoadingMore}>
{isLoadingMore ? 'Loading...' : 'Load More'}
</button>
);
}Error Handling
function ErrorDisplay() {
const { streamError, clearStreamError } = useChatContext();
if (!streamError) return null;
return (
<div className="error">
<p>{streamError.message}</p>
<button onClick={clearStreamError}>Dismiss</button>
</div>
);
}useForwarding
Intercept and forward streaming data to external components.
Signature
// Single handler
function useForwarding(
action: string,
handler: ForwardingHandler,
options?: Partial<ForwardingHandlerConfig>
): UseForwardingReturn;
// Multiple handlers
function useForwarding(
handlers: ForwardingHandlers
): UseForwardingReturn;
// Access manager only
function useForwarding(): UseForwardingReturn;Handler Function
type ForwardingHandler = (
incrementalText: string,
fullText: string,
metadata: {
action: string;
isLive: boolean;
event: 'chunk' | 'end';
}
) => void;Options
interface ForwardingHandlerConfig {
handler: ForwardingHandler;
mode?: 'dual' | 'replace' | 'raw';
animated?: boolean;
subscriptionMode?: 'delta' | 'full';
}Usage
Basic Forwarding
import { useForwarding } from 'react-chat-agent';
function Editor() {
const editorRef = useRef();
useForwarding('prompt_create', (incremental, full, meta) => {
if (editorRef.current) {
editorRef.current.setValue(full);
}
});
return <div ref={editorRef} />;
}With Options
useForwarding('stream_data', handler, {
mode: 'replace', // Don't show in chat
subscriptionMode: 'delta', // Get incremental updates
animated: false // No typing animation
});Multiple Actions
useForwarding({
prompt_create: {
handler: (inc, full, meta) => updateEditor(full),
mode: 'replace'
},
code_generation: {
handler: (inc, full, meta) => updateCodeBlock(full),
mode: 'dual'
}
});Manager API
const forwarding = useForwarding();
// Register dynamically
forwarding.register('custom_action', handler, options);
// Unregister
forwarding.unregister('custom_action');
// Get active sessions
const activeSessions = forwarding.getActiveSessions();useStatusSubscription
Listen to agent events, tool executions, and status updates.
Signature
// Single action
function useStatusSubscription(
action: string,
handler: StatusHandler,
options?: { instanceId?: string }
): void;
// Multiple actions
function useStatusSubscription(
handlers: StatusHandlers,
handler?: never,
options?: { instanceId?: string }
): void;Handler Function
type StatusHandler = (statusData: any) => void;Usage
Single Action
import { useStatusSubscription } from 'react-chat-agent';
function ToolMonitor() {
useStatusSubscription('tool_call', (statusData) => {
console.log('Tool:', statusData.tool_name);
console.log('State:', statusData.status.state);
console.log('Result:', statusData.result);
});
return <div>Monitoring tools...</div>;
}Multiple Actions
function EventMonitor() {
useStatusSubscription({
tool_call: (data) => {
console.log('Tool executed:', data.tool_name);
},
edit_file: (data) => {
console.log('File edited:', data.file_path);
},
error: (data) => {
console.error('Error:', data.error);
}
});
return <div>Monitoring events...</div>;
}Global Listener
useStatusSubscription('*', (statusData) => {
// Receives all status messages
console.log('Status:', statusData);
});Multi-Instance
// Listen to specific agent instance
useStatusSubscription('tool_call', handler, {
instanceId: 'agent-123'
});UI Updates
function ToolStatus() {
const [currentTool, setCurrentTool] = useState(null);
useStatusSubscription('tool_call', (data) => {
if (data.statusType === 'started') {
setCurrentTool(data.tool_name);
} else if (data.statusType === 'finished') {
setCurrentTool(null);
}
});
return currentTool ? (
<div>Executing: {currentTool}</div>
) : null;
}Message Manager
Manipulate messages programmatically.
API
interface MessageManager {
messages: Message[];
subscribers: Set<(messages: Message[]) => void>;
addMessage(msg: Partial<Message>): Message;
updateMessage(id: string, updates: Partial<Message>, options?: { silent?: boolean }): Message;
removeMessage(id: string): boolean;
getMessage(id: string): Message | undefined;
insertMessages(messages: Message[], position?: 'start' | 'end'): void;
subscribe(callback: (messages: Message[]) => void): () => void;
clear(): void;
get count(): number;
}Usage
function MessageControls() {
const { messageManager } = useChatContext();
const addCustomMessage = () => {
messageManager.addMessage({
role: 'assistant',
content: 'This is a custom message'
});
};
const clearAllMessages = () => {
messageManager.clear();
};
const updateMessage = (msgId: string) => {
messageManager.updateMessage(msgId, {
content: 'Updated content'
});
};
return (
<div>
<button onClick={addCustomMessage}>Add Message</button>
<button onClick={clearAllMessages}>Clear All</button>
<p>Total: {messageManager.count}</p>
</div>
);
}Typing Animation Config
Configure how responses appear.
<ChatProvider
authConfig={authConfig}
typingAnimation={{
mode: 'char', // 'char' | 'word' | 'batch' | 'instant'
speed: 50, // units per second
batchSize: 10 // for 'batch' mode
}}
>
<ChatPanel />
</ChatProvider>Next Steps
- Status & Events - Deep dive into event system
- Stream Forwarding - Advanced forwarding patterns
- Advanced - Complex use cases