@aismarttalk/react-hooks
v1.5.10
Published
A collection of high-quality, reusable React hooks for integrating AI Smarttalk's AI Agents
Downloads
129
Readme
🤖 AI Smarttalk React Hooks
A collection of high-quality, reusable React hooks for integrating AI Smarttalk's AI Agents into your React application. This library provides hooks for managing chat messages, user state, and chat instance initialization with robust error handling, token validation, and localStorage persistence.
✨ Features
💬 Chat Interface for the AI Agent
- 🔄 Manage chat messages, WebSocket connections, typing notifications, and conversation history with a flexible configuration
- 👤 Handle user state with localStorage persistence, token validation (JWT), and automatic fallback to an anonymous user if needed
- 🚀 Initialize or reset a chat instance based on a given chat model and language, using API calls to create new instances when required
📝 Canvas System
The library includes a powerful canvas system for handling structured text content (like code or documents):
- 🤝 Real-time collaborative text editing with automatic synchronization across all connected clients
- ✍️ Line-by-line manipulation with support for inserting, updating, and deleting lines
- 📚 History tracking with localStorage persistence
- 🔢 Formatted output with line numbers for AI interactions
- 🔄 Simple text conversion for easy integration with LLMs
Example usage:
const ChatComponent = () => {
const {
messages,
canvasHistory, // Access the canvas system
// ... other chat features
} = useAISmarttalkChat({
chatModelId: 'your-model-id',
lang: 'en',
config: {
apiUrl: 'https://aismarttalk.tech',
wsUrl: 'wss://ws.223.io.aismarttalk.tech',
apiToken: 'your-api-token',
},
});
// Store code generated by AI
const handleAICode = (code: string[]) => {
canvasHistory.updateCanvas({
title: "Generated Code",
content: code
});
};
// Get formatted code with line numbers for AI context
const getNumberedCode = () => {
return canvasHistory.getNumberedLines();
};
// Update specific lines
const updateLine = (lineNumber: number, newContent: string) => {
canvasHistory.updateLineRange(lineNumber, lineNumber, [newContent]);
};
return (
// Your chat UI implementation
);
};The canvas system maintains synchronization across all connected clients automatically through WebSocket events, making it perfect for collaborative code review and document editing scenarios.
🚀 Installation
Install the package via npm or yarn:
npm install @aismarttalk/react-hooks
# or
yarn add @aismarttalk/react-hooks💡 Note: Replace
@aismarttalk/react-hookswith the actual package name if different.
🏁 Getting Started
Using useAiSmarttalkChat
import { useAISmarttalkChat } from '@aismarttalk/react-hooks';
const ChatComponent = () => {
const {
messages,
addMessage,
user,
setUser,
chatInstanceId,
resetChat,
socketStatus,
error,
clearError,
// ... and more
} = useAISmarttalkChat({
chatModelId: 'your-model-id',
lang: 'en',
config: {
apiUrl: 'https://aismarttalk.tech',
wsUrl: 'wss://ws.223.io.aismarttalk.tech',
apiToken: 'your-api-token',
},
});
return (
// Your chat UI implementation
);
};Using the Enhanced Error Handling System
The 1.5.0 update introduces a comprehensive error handling system that provides structured error information:
import { useAISmarttalkChat } from '@aismarttalk/react-hooks';
const ChatComponent = () => {
const { error, clearError, onSend, messages } = useAISmarttalkChat({
chatModelId: 'your-model-id',
lang: 'en',
config: {
apiUrl: 'https://aismarttalk.tech',
apiToken: 'your-api-token',
},
});
// Error contains structured information
// error = {
// message: "Unauthorized: You need to login to access this chat.",
// type: "auth",
// code: 401
// }
const renderErrorMessage = () => {
if (!error.message) return null;
// You can customize UI based on error type
switch (error.type) {
case 'auth':
return (
<div className="error auth-error">
🔒 {error.message}
<button onClick={() => handleLogin()}>Login</button>
</div>
);
case 'permission':
return <div className="error permission-error">⛔ {error.message}</div>;
case 'rate_limit':
return <div className="error rate-limit-error">⏱️ {error.message}</div>;
case 'server':
return <div className="error server-error">
🔧 {error.message}
<small>Error code: {error.code}</small>
</div>;
default:
return <div className="error">{error.message}</div>;
}
};
return (
<div className="chat-container">
{renderErrorMessage()}
<div className="messages">
{messages.map(msg => (
<div key={msg.id} className={msg.isSent ? 'sent' : 'received'}>
{msg.text}
</div>
))}
</div>
{/* Rest of chat UI */}
</div>
);
};Using useChatInstance
import React from 'react';
import useChatInstance from '@aismarttalk/react-hooks/hooks/useChatInstance';
const ChatInstanceComponent = () => {
const { chatInstanceId, resetInstance, error } = useChatInstance({
chatModelId: 'your-model-id',
lang: 'en',
config: {
apiUrl: 'https://aismarttalk.tech',
apiToken: 'your-api-token',
},
user: { token: 'user-token' },
});
return (
<div>
{error && <p style={{ color: 'red' }}>{error.message}</p>}
<h3>Chat Instance ID: {chatInstanceId}</h3>
<button onClick={resetInstance}>Reset Chat Instance</button>
</div>
);
};
export default ChatInstanceComponent;Using useChatModel
import React from 'react';
import { useChatModel } from '@aismarttalk/react-hooks';
const ChatModelComponent = () => {
const { chatModel, setChatModel } = useChatModel({
chatModelId: 'your-model-id',
config: {
apiUrl: 'https://aismarttalk.tech',
apiToken: 'your-api-token',
},
});
return (
<div>
{chatModel ? (
<div>
<h3>Chat Model: {chatModel.name}</h3>
<p>Description: {chatModel.description}</p>
<p>Provider: {chatModel.provider}</p>
{/* Display other model properties as needed */}
</div>
) : (
<p>Loading chat model...</p>
)}
</div>
);
};
export default ChatModelComponent;🔄 Message Handling Improvements
Message Deduplication System
Version 1.5.0 implements an intelligent message deduplication system that solves several common issues in real-time chat applications:
Temporary to Permanent Message Transition
- When a user sends a message, it's immediately displayed with a temporary ID
- When the WebSocket returns the server-validated message (with a permanent ID), the system smartly replaces the temporary message instead of showing a duplicate
"isSent" Property Calculation
- Messages are now correctly marked as "sent by current user" based on comprehensive identity checks
- Works reliably for both authenticated users and anonymous sessions
- Prevents UI inconsistencies where your own messages might temporarily appear as coming from someone else
Flickering Prevention
- Intelligent API refresh throttling when messages arrive via WebSocket
- Optimized message merging with preservation of user-specific properties
- Smart timestamp tracking to avoid unnecessary UI updates
Example Flow:
// Your component
const ChatComponent = () => {
const { messages, onSend } = useAISmarttalkChat({...config});
// When a user sends a message:
const handleSend = (text) => {
onSend(text);
// 1. Message immediately appears in the UI (with temp ID)
// 2. Message is sent to the server
// 3. Server processes and broadcasts via WebSocket
// 4. Hook receives the WebSocket message
// 5. Deduplication system identifies and replaces temp message
// 6. UI smoothly updates with no duplicates or flickering
};
return (
<div>
{messages.map(msg => (
<div key={msg.id} className={msg.isSent ? 'sent' : 'received'}>
{msg.text}
</div>
))}
<button onClick={() => handleSend("Hello world!")}>Send</button>
</div>
);
};This deduplication system works behind the scenes without requiring any special handling in your components.
📝 Changelog
1.5.0 ✨ Enhanced Error Handling & Message Stability
- 🛡️ Comprehensive Error Handling System
- Added structured error information with types (
auth,permission,rate_limit, etc.) - Improved HTTP status code handling (401, 403, 429, etc.)
- Enhanced error reporting with consistent formatting
- Added structured error information with types (
- 🔄 Message Deduplication & Stability Improvements
- Fixed temporary message duplication when receiving WebSocket responses
- Improved handling of message ownership and
isSentproperty calculation - Enhanced temporary to permanent message transition for smoother UX
- Fixed bug where messages would appear duplicated for a split second when sent
- Solved issues with
isSentproperty not being correctly calculated for logged-in users - Improved message ID tracking between temporary and permanent versions
- ⚡ Performance Optimizations
- Reduced API refresh flickering with better message merging
- Added intelligent caching to prevent unnecessary refreshes
- Improved WebSocket reconnection logic
- Added lastMessageReceivedRef tracking to prevent unnecessary API calls
- Enhanced message merging algorithm to preserve UI state during updates
1.4.0 ✨ Introduce useOtpAuth for Login
- 🔑 Added
useOtpAuthhook to facilitate user login via OTP. - 🧹 Removed unnecessary console logs to clean up the codebase.
- ⚡ Improved caching mechanisms for better performance.
- 📜 Enhanced chat history management for a more reliable user experience.
1.3.0 ✨ Add User Config
- 🛠️ Allow user configuration
const { user, messages, onSend /* ... other values */ } = useAISmarttalkChat({
chatModelId: "your-chat-model-id",
config: {
apiUrl: "your-api-url",
user: {
id: "custom-user-id",
email: "[email protected]",
name: "Custom User",
// Optional fields
image: "https://example.com/avatar.jpg",
token: "your-auth-token"
}
}
});1.2.4 Refactor: Split Responsibilities of useMessage
- 🔄 Restructured the useMessage hook to separate concerns, enhancing maintainability.
- ✅ Added support for features, enabling the client to communicate with the API regarding supported features (currently only Canva).
1.2.3 Enhanced History Management for Uninitialized States
- 🔄 Improved handling of chat history when it has not been initialized yet, ensuring a smoother user experience.
- ✅ Added checks to prevent errors when accessing uninitialized history, providing fallback mechanisms.
- 📈 Optimized performance for loading and displaying chat history
1.2.2 - Fix User Token expiration
- 🐛 Fixed user token expiration validation causing incorrect message attribution
- 🔄 Added proper token expiry checks to prevent wrong user identification
- ✅ Improved user session handling and authentication validation
1.2.1 - Fix Regression
- 🐛 Fixed regression where suggestions were not being returned from useAISmarttalkChat hook
- 🔄 Restored suggestions functionality to maintain expected behavior
- ✅ Added additional validation to prevent future regressions
1.2.0 - Canvas System Update
- ✨ Added canvas system for structured text handling
- 🔄 Real-time collaborative editing support
- 📚 Local history tracking
- 🔢 Line number formatting utilities
1.1.1 - 1.1.3 - Maintenance
- 🐛 Fix hardcoded urls in getChatModel
- 🧹 Refactor and remove duplicated code
1.1.0 - Major Update
- 🎉 Introducing consolidated
useAISmarttalkChathook - 📦 Simplified integration with reduced boilerplate
- 🔧 Enhanced TypeScript support
- ⚡ Improved performance
📄 License
This project is licensed under the Apache 2.0 Licence.
📞 Contact
For questions or support, please open an issue on the repository or contact the maintainer.
🌟 Contributing
We welcome contributions! Please feel free to submit a Pull Request.
Enjoy integrating chat functionality with AI Smarttalk React Hooks! 🚀
Usage
useFileUpload Hook
The useFileUpload hook now integrates with the chat state management system and uses the existing WebSocket connection from useSocketHandler for real-time canvas updates.
import React, { useReducer } from 'react';
import {
useFileUpload,
ChatActionTypes,
chatReducer,
initialChatState,
useSocketHandler
} from '@aismarttalk/react-hooks';
function ChatWithFileUpload() {
const [chatState, dispatch] = useReducer(chatReducer, initialChatState);
// Initialize socket handler (this manages the WebSocket connection)
const socketRef = useSocketHandler(
chatInstanceId,
user,
wsUrl,
apiUrl,
chatModelId,
dispatch,
setSocketStatus,
setTypingUsers,
setConversationStarters,
setActiveTool,
setUser,
debouncedTypingUsersUpdate,
canvasHistory,
chatState.messages
);
// Use file upload hook with chat state integration
const {
uploadFile,
fetchCanvases,
canvases,
isUploading,
error,
refreshCanvases
} = useFileUpload({
chatModelId: 'your-chat-model-id',
chatInstanceId: 'your-chat-instance-id',
config: {
apiUrl: 'https://your-api-url.com',
apiToken: 'your-api-token'
},
user: {
token: 'user-auth-token',
id: 'user-id'
},
canvases: chatState.canvases, // Canvas data from chat state
dispatch: dispatch // Chat dispatch function
});
const handleFileUpload = async (file: File) => {
const result = await uploadFile(file);
if (result.success) {
console.log('File uploaded successfully');
// Canvas updates will be received automatically via WebSocket
// and handled by the socket handler which dispatches UPDATE_CANVAS actions
}
};
return (
<div>
<input
type="file"
onChange={(e) => e.target.files?.[0] && handleFileUpload(e.target.files[0])}
/>
{isUploading && <div>Uploading...</div>}
{error && <div>Error: {error}</div>}
<div>
<h2>Canvases ({canvases.length})</h2>
{canvases.map(canvas => (
<div key={canvas.id}>
<h3>Canvas {canvas.id}</h3>
<pre>{canvas.content}</pre>
</div>
))}
</div>
<button onClick={refreshCanvases}>
Refresh Canvases
</button>
</div>
);
}Key Changes
Removed Socket Management: The
useFileUploadhook no longer manages its own WebSocket connection. Instead, it relies on the existinguseSocketHandlerfor real-time updates.State Integration: Canvas data is now managed through the chat reducer state, allowing for better integration with the overall chat system.
Real-time Updates: Canvas live updates are received through the
canvas-live-updateWebSocket event inuseSocketHandlerand automatically update the chat state via theUPDATE_CANVASaction.Simplified API: The hook now focuses on file operations and canvas data management, while WebSocket connectivity is handled centrally.
Canvas Live Updates
Canvas updates are automatically handled when received via WebSocket:
// In useSocketHandler.ts - this happens automatically
socket.on("canvas-live-update", (data: CanvasLiveUpdate) => {
dispatch({
type: ChatActionTypes.UPDATE_CANVAS,
payload: { canvas: data },
});
});The UPDATE_CANVAS action in the chat reducer applies line-by-line updates to the canvas content, ensuring real-time synchronization across all connected clients.
Types
CanvasLiveUpdate
interface CanvasLiveUpdate {
canvasId: string;
updates: LineUpdate[];
}LineUpdate
interface LineUpdate {
lineNumber: number;
oldContent: string;
newContent: string;
timestamp: Date;
}CanvasFullContent
interface CanvasFullContent {
id: string;
content: string;
}