@veroai/chat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +579 -0
- package/dist/chunk-JI6KXOLF.js +920 -0
- package/dist/chunk-JI6KXOLF.js.map +1 -0
- package/dist/client-C63XKtNw.d.ts +502 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +187 -0
- package/dist/react/index.js +371 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
# @veroai/chat
|
|
2
|
+
|
|
3
|
+
Real-time messaging SDK for VeroAI applications. Provides HTTP API client, WebSocket connection management, and React integration for building chat interfaces with AI agents.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Real-time messaging** - WebSocket-based with auto-reconnect
|
|
8
|
+
- **Typing indicators** - Show when users are typing
|
|
9
|
+
- **Presence tracking** - Online/away/busy/offline status
|
|
10
|
+
- **Read receipts** - Track message read status
|
|
11
|
+
- **Voice/video calls** - LiveKit integration for WebRTC calls
|
|
12
|
+
- **AI agents** - Built-in support for AI agent conversations
|
|
13
|
+
- **React hooks** - Ready-to-use hooks for React applications
|
|
14
|
+
- **TypeScript** - Full type safety
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @veroai/chat
|
|
20
|
+
# or
|
|
21
|
+
pnpm add @veroai/chat
|
|
22
|
+
# or
|
|
23
|
+
yarn add @veroai/chat
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Vanilla TypeScript/JavaScript
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { ChatClient } from '@veroai/chat';
|
|
32
|
+
|
|
33
|
+
const chat = new ChatClient({
|
|
34
|
+
apiUrl: 'https://api.veroai.dev',
|
|
35
|
+
wsUrl: 'wss://ws.veroai.dev',
|
|
36
|
+
token: 'your-jwt-token',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Connect to real-time events
|
|
40
|
+
await chat.connect();
|
|
41
|
+
|
|
42
|
+
// Listen for new messages
|
|
43
|
+
chat.on('message:new', ({ message, conversationId }) => {
|
|
44
|
+
console.log('New message:', message.content);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Send a message
|
|
48
|
+
await chat.send(conversationId, 'Hello!');
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### React
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { ChatProvider, useChat, useConversation } from '@veroai/chat/react';
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return (
|
|
58
|
+
<ChatProvider
|
|
59
|
+
config={{
|
|
60
|
+
apiUrl: 'https://api.veroai.dev',
|
|
61
|
+
wsUrl: 'wss://ws.veroai.dev',
|
|
62
|
+
token: authToken,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<ChatApp />
|
|
66
|
+
</ChatProvider>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function ChatApp() {
|
|
71
|
+
const { conversations, isConnected } = useChat();
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div>
|
|
75
|
+
<p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
|
|
76
|
+
{conversations.map(conv => (
|
|
77
|
+
<ConversationItem key={conv.id} conversation={conv} />
|
|
78
|
+
))}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function ChatRoom({ conversationId }) {
|
|
84
|
+
const { messages, send, typingUsers, startTyping, stopTyping } = useConversation(conversationId);
|
|
85
|
+
const [input, setInput] = useState('');
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div>
|
|
89
|
+
{messages.map(m => <Message key={m.id} message={m} />)}
|
|
90
|
+
{typingUsers.length > 0 && <p>Someone is typing...</p>}
|
|
91
|
+
<input
|
|
92
|
+
value={input}
|
|
93
|
+
onChange={(e) => {
|
|
94
|
+
setInput(e.target.value);
|
|
95
|
+
startTyping();
|
|
96
|
+
}}
|
|
97
|
+
onBlur={stopTyping}
|
|
98
|
+
onKeyDown={(e) => {
|
|
99
|
+
if (e.key === 'Enter') {
|
|
100
|
+
send(input);
|
|
101
|
+
setInput('');
|
|
102
|
+
}
|
|
103
|
+
}}
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
interface ChatClientConfig {
|
|
114
|
+
/** VeroAI API URL */
|
|
115
|
+
apiUrl: string;
|
|
116
|
+
/** WebSocket URL for real-time events */
|
|
117
|
+
wsUrl?: string;
|
|
118
|
+
/** JWT authentication token */
|
|
119
|
+
token?: string;
|
|
120
|
+
/** Dynamic token getter (for token refresh) */
|
|
121
|
+
getToken?: () => string | null | Promise<string | null>;
|
|
122
|
+
/** Auto-connect to WebSocket on initialization */
|
|
123
|
+
autoConnect?: boolean;
|
|
124
|
+
/** Auto-reconnect on disconnect (default: true) */
|
|
125
|
+
autoReconnect?: boolean;
|
|
126
|
+
/** Reconnect interval in ms (default: 3000) */
|
|
127
|
+
reconnectInterval?: number;
|
|
128
|
+
/** Max reconnect attempts (default: 10) */
|
|
129
|
+
maxReconnectAttempts?: number;
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## API Reference
|
|
134
|
+
|
|
135
|
+
### ChatClient
|
|
136
|
+
|
|
137
|
+
#### Connection Management
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Connect to WebSocket
|
|
141
|
+
await chat.connect();
|
|
142
|
+
|
|
143
|
+
// Disconnect
|
|
144
|
+
chat.disconnect();
|
|
145
|
+
|
|
146
|
+
// Check connection status
|
|
147
|
+
chat.isConnected();
|
|
148
|
+
|
|
149
|
+
// Update auth token
|
|
150
|
+
chat.setToken(newToken);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Conversations
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// List all conversations
|
|
157
|
+
const conversations = await chat.listConversations();
|
|
158
|
+
|
|
159
|
+
// Get a specific conversation
|
|
160
|
+
const conversation = await chat.getConversation(conversationId);
|
|
161
|
+
|
|
162
|
+
// Create a new conversation
|
|
163
|
+
const newConv = await chat.createConversation({
|
|
164
|
+
type: 'direct', // 'direct' | 'group' | 'channel'
|
|
165
|
+
participantIds: ['user-id-1', 'user-id-2'],
|
|
166
|
+
name: 'Optional name for groups',
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Mark conversation as read
|
|
170
|
+
await chat.markConversationRead(conversationId);
|
|
171
|
+
|
|
172
|
+
// Leave a conversation
|
|
173
|
+
await chat.leaveConversation(conversationId);
|
|
174
|
+
|
|
175
|
+
// Subscribe to real-time updates
|
|
176
|
+
chat.subscribeToConversation(conversationId);
|
|
177
|
+
chat.unsubscribeFromConversation(conversationId);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Messages
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Get messages (paginated)
|
|
184
|
+
const { messages, hasMore, total } = await chat.getMessages(conversationId, {
|
|
185
|
+
limit: 50,
|
|
186
|
+
before: 'message-id', // For pagination
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Send a message
|
|
190
|
+
const message = await chat.sendMessage(conversationId, {
|
|
191
|
+
content: 'Hello!',
|
|
192
|
+
messageType: 'text', // 'text' | 'system' | 'agent' | 'file'
|
|
193
|
+
metadata: { custom: 'data' },
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Convenience method
|
|
197
|
+
await chat.send(conversationId, 'Hello!');
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### Typing Indicators
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Send typing indicator
|
|
204
|
+
chat.sendTypingStart(conversationId);
|
|
205
|
+
chat.sendTypingStop(conversationId);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### Users & Presence
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// List users (contacts)
|
|
212
|
+
const users = await chat.listUsers({ includeVirtual: true });
|
|
213
|
+
|
|
214
|
+
// Get online users
|
|
215
|
+
const onlineUsers = await chat.getOnlineUsers();
|
|
216
|
+
|
|
217
|
+
// Get current user profile
|
|
218
|
+
const me = await chat.getCurrentUser();
|
|
219
|
+
|
|
220
|
+
// Get specific user
|
|
221
|
+
const user = await chat.getUser(userId);
|
|
222
|
+
|
|
223
|
+
// Update presence status
|
|
224
|
+
await chat.updateStatus('online', 'Working on something cool');
|
|
225
|
+
// Status: 'online' | 'away' | 'busy' | 'offline'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
#### AI Agents
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
// List available agents
|
|
232
|
+
const agents = await chat.listAgents();
|
|
233
|
+
|
|
234
|
+
// Add agent to conversation
|
|
235
|
+
await chat.addAgentToConversation(conversationId, agentConfigId);
|
|
236
|
+
|
|
237
|
+
// Remove agent from conversation
|
|
238
|
+
await chat.removeAgentFromConversation(conversationId);
|
|
239
|
+
|
|
240
|
+
// Toggle agent enabled/disabled
|
|
241
|
+
await chat.toggleAgent(conversationId, true);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### Voice/Video Calls (LiveKit)
|
|
245
|
+
|
|
246
|
+
The SDK integrates with LiveKit for WebRTC voice and video calls. Call signaling (ring, accept, reject, end) is handled via WebSocket, while actual media streams go through LiveKit.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// Create a room
|
|
250
|
+
const room = await chat.createRoom({
|
|
251
|
+
name: 'call-room-123',
|
|
252
|
+
emptyTimeout: 300, // seconds
|
|
253
|
+
maxParticipants: 10,
|
|
254
|
+
});
|
|
255
|
+
// Returns: { name, wsUrl, token }
|
|
256
|
+
|
|
257
|
+
// Join an existing room
|
|
258
|
+
const room = await chat.joinRoom({
|
|
259
|
+
roomName: 'call-room-123',
|
|
260
|
+
participantName: 'John Doe',
|
|
261
|
+
canPublish: true,
|
|
262
|
+
canSubscribe: true,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Start a call (creates room + notifies participants)
|
|
266
|
+
const room = await chat.startCall(conversationId, 'video'); // 'audio' | 'video'
|
|
267
|
+
|
|
268
|
+
// Accept an incoming call
|
|
269
|
+
chat.on('call:ring', async ({ conversationId, roomName, callType }) => {
|
|
270
|
+
const room = await chat.acceptCall(conversationId, roomName, 'My Name');
|
|
271
|
+
// Connect to LiveKit using room.wsUrl and room.token
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Reject a call
|
|
275
|
+
chat.rejectCall(conversationId);
|
|
276
|
+
|
|
277
|
+
// End a call
|
|
278
|
+
chat.endCall(conversationId);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Events
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Connection events
|
|
285
|
+
chat.on('connected', () => { /* WebSocket connected */ });
|
|
286
|
+
chat.on('disconnected', (reason) => { /* WebSocket disconnected */ });
|
|
287
|
+
chat.on('error', (error) => { /* Error occurred */ });
|
|
288
|
+
|
|
289
|
+
// Message events
|
|
290
|
+
chat.on('message:new', ({ message, conversationId }) => { });
|
|
291
|
+
chat.on('message:updated', (message) => { });
|
|
292
|
+
chat.on('message:deleted', (messageId, conversationId) => { });
|
|
293
|
+
|
|
294
|
+
// Conversation events
|
|
295
|
+
chat.on('conversation:created', (conversation) => { });
|
|
296
|
+
chat.on('conversation:updated', (conversation) => { });
|
|
297
|
+
chat.on('participant:joined', (conversationId, participant) => { });
|
|
298
|
+
chat.on('participant:left', (conversationId, userId) => { });
|
|
299
|
+
|
|
300
|
+
// Presence events
|
|
301
|
+
chat.on('presence:updated', ({ userId, status, statusMessage }) => { });
|
|
302
|
+
|
|
303
|
+
// Typing events
|
|
304
|
+
chat.on('typing:start', ({ conversationId, userId, userName }) => { });
|
|
305
|
+
chat.on('typing:stop', ({ conversationId, userId }) => { });
|
|
306
|
+
|
|
307
|
+
// Read receipt events
|
|
308
|
+
chat.on('read:receipt', ({ conversationId, messageId, userId, readAt }) => { });
|
|
309
|
+
|
|
310
|
+
// Call events
|
|
311
|
+
chat.on('call:ring', ({ conversationId, userId, callType, roomName }) => { });
|
|
312
|
+
chat.on('call:accept', ({ conversationId, userId, roomName }) => { });
|
|
313
|
+
chat.on('call:reject', ({ conversationId, userId }) => { });
|
|
314
|
+
chat.on('call:end', ({ conversationId, userId }) => { });
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## React Hooks
|
|
318
|
+
|
|
319
|
+
### ChatProvider
|
|
320
|
+
|
|
321
|
+
Wrap your app with `ChatProvider` to enable chat functionality:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
import { ChatProvider } from '@veroai/chat/react';
|
|
325
|
+
|
|
326
|
+
<ChatProvider
|
|
327
|
+
config={{
|
|
328
|
+
apiUrl: 'https://api.veroai.dev',
|
|
329
|
+
wsUrl: 'wss://ws.veroai.dev',
|
|
330
|
+
token: authToken,
|
|
331
|
+
}}
|
|
332
|
+
autoFetchConversations={true}
|
|
333
|
+
autoFetchCurrentUser={true}
|
|
334
|
+
>
|
|
335
|
+
{children}
|
|
336
|
+
</ChatProvider>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### useChat
|
|
340
|
+
|
|
341
|
+
Access chat context and global state:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import { useChat } from '@veroai/chat/react';
|
|
345
|
+
|
|
346
|
+
function MyComponent() {
|
|
347
|
+
const {
|
|
348
|
+
client, // ChatClient instance
|
|
349
|
+
isConnected, // WebSocket connection status
|
|
350
|
+
currentUser, // Current user profile
|
|
351
|
+
conversations, // List of conversations
|
|
352
|
+
isLoadingConversations,
|
|
353
|
+
refreshConversations,
|
|
354
|
+
connect,
|
|
355
|
+
disconnect,
|
|
356
|
+
updateStatus,
|
|
357
|
+
} = useChat();
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### useChatClient
|
|
362
|
+
|
|
363
|
+
Get direct access to the ChatClient:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
import { useChatClient } from '@veroai/chat/react';
|
|
367
|
+
|
|
368
|
+
function MyComponent() {
|
|
369
|
+
const client = useChatClient();
|
|
370
|
+
// Use client directly for advanced operations
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### useConversation
|
|
375
|
+
|
|
376
|
+
Manage a single conversation with real-time updates:
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
import { useConversation } from '@veroai/chat/react';
|
|
380
|
+
|
|
381
|
+
function ChatRoom({ conversationId }) {
|
|
382
|
+
const {
|
|
383
|
+
conversation, // Conversation object
|
|
384
|
+
messages, // Messages array
|
|
385
|
+
isLoading, // Loading state
|
|
386
|
+
hasMore, // More messages available
|
|
387
|
+
typingUsers, // Users currently typing
|
|
388
|
+
sendMessage, // Send message with params
|
|
389
|
+
send, // Send text message (convenience)
|
|
390
|
+
loadMore, // Load older messages
|
|
391
|
+
refresh, // Refresh messages
|
|
392
|
+
markAsRead, // Mark conversation as read
|
|
393
|
+
startTyping, // Send typing indicator
|
|
394
|
+
stopTyping, // Stop typing indicator
|
|
395
|
+
error, // Error if any
|
|
396
|
+
} = useConversation(conversationId, {
|
|
397
|
+
autoFetchMessages: true,
|
|
398
|
+
initialMessageLimit: 50,
|
|
399
|
+
autoSubscribe: true,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### usePresence
|
|
405
|
+
|
|
406
|
+
Track online users and presence status:
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
import { usePresence } from '@veroai/chat/react';
|
|
410
|
+
|
|
411
|
+
function OnlineUsers() {
|
|
412
|
+
const {
|
|
413
|
+
onlineUsers, // Array of online users
|
|
414
|
+
isLoading,
|
|
415
|
+
getUserStatus, // Get status for specific user
|
|
416
|
+
refresh,
|
|
417
|
+
error,
|
|
418
|
+
} = usePresence();
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<ul>
|
|
422
|
+
{onlineUsers.map(user => (
|
|
423
|
+
<li key={user.id}>
|
|
424
|
+
{user.firstName} - {getUserStatus(user.id)}
|
|
425
|
+
</li>
|
|
426
|
+
))}
|
|
427
|
+
</ul>
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### useUserPresence
|
|
433
|
+
|
|
434
|
+
Track presence for a specific user:
|
|
435
|
+
|
|
436
|
+
```tsx
|
|
437
|
+
import { useUserPresence } from '@veroai/chat/react';
|
|
438
|
+
|
|
439
|
+
function UserStatus({ userId }) {
|
|
440
|
+
const { status, isOnline } = useUserPresence(userId);
|
|
441
|
+
|
|
442
|
+
return (
|
|
443
|
+
<span className={isOnline ? 'text-green-500' : 'text-gray-400'}>
|
|
444
|
+
{status}
|
|
445
|
+
</span>
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Types
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
// User types
|
|
454
|
+
type PresenceStatus = 'online' | 'away' | 'busy' | 'offline';
|
|
455
|
+
|
|
456
|
+
interface User {
|
|
457
|
+
id: string;
|
|
458
|
+
email?: string;
|
|
459
|
+
firstName?: string;
|
|
460
|
+
lastName?: string;
|
|
461
|
+
isVirtual?: boolean;
|
|
462
|
+
agentConfigId?: string;
|
|
463
|
+
status?: PresenceStatus;
|
|
464
|
+
statusMessage?: string;
|
|
465
|
+
lastSeen?: string;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Conversation types
|
|
469
|
+
type ConversationType = 'direct' | 'group' | 'channel' | 'support';
|
|
470
|
+
|
|
471
|
+
interface Conversation {
|
|
472
|
+
id: string;
|
|
473
|
+
name?: string;
|
|
474
|
+
type: ConversationType;
|
|
475
|
+
isActive: boolean;
|
|
476
|
+
lastMessageAt?: string;
|
|
477
|
+
agentEnabled?: boolean;
|
|
478
|
+
agentConfigId?: string;
|
|
479
|
+
participants?: Participant[];
|
|
480
|
+
unreadCount?: number;
|
|
481
|
+
metadata?: Record<string, unknown>;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Message types
|
|
485
|
+
type MessageType = 'text' | 'system' | 'agent' | 'file' | 'call';
|
|
486
|
+
|
|
487
|
+
interface Message {
|
|
488
|
+
id: string;
|
|
489
|
+
conversationId: string;
|
|
490
|
+
content: string;
|
|
491
|
+
messageType: MessageType;
|
|
492
|
+
senderId?: string;
|
|
493
|
+
sender?: User;
|
|
494
|
+
readBy?: ReadReceipt[];
|
|
495
|
+
metadata?: Record<string, unknown>;
|
|
496
|
+
createdAt?: string;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Call types
|
|
500
|
+
type CallAction = 'ring' | 'accept' | 'reject' | 'end';
|
|
501
|
+
type CallType = 'audio' | 'video';
|
|
502
|
+
|
|
503
|
+
interface CallEvent {
|
|
504
|
+
conversationId: string;
|
|
505
|
+
userId: string;
|
|
506
|
+
action: CallAction;
|
|
507
|
+
callType?: CallType;
|
|
508
|
+
roomName?: string;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Room info (for LiveKit)
|
|
512
|
+
interface RoomInfo {
|
|
513
|
+
name: string;
|
|
514
|
+
wsUrl: string;
|
|
515
|
+
token: string;
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
## Advanced Usage
|
|
520
|
+
|
|
521
|
+
### Custom Token Refresh
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
const chat = new ChatClient({
|
|
525
|
+
apiUrl: 'https://api.veroai.dev',
|
|
526
|
+
wsUrl: 'wss://ws.veroai.dev',
|
|
527
|
+
getToken: async () => {
|
|
528
|
+
// Check if token is expired
|
|
529
|
+
const token = localStorage.getItem('token');
|
|
530
|
+
if (isExpired(token)) {
|
|
531
|
+
const newToken = await refreshToken();
|
|
532
|
+
localStorage.setItem('token', newToken);
|
|
533
|
+
return newToken;
|
|
534
|
+
}
|
|
535
|
+
return token;
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Direct API Access
|
|
541
|
+
|
|
542
|
+
For server-side usage or when you don't need WebSocket:
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import { ChatApi } from '@veroai/chat';
|
|
546
|
+
|
|
547
|
+
const api = new ChatApi({
|
|
548
|
+
apiUrl: 'https://api.veroai.dev',
|
|
549
|
+
getToken: () => localStorage.getItem('token'),
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
// Use API directly without WebSocket
|
|
553
|
+
const conversations = await api.listConversations();
|
|
554
|
+
const room = await api.createRoom({ name: 'my-room' });
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Direct WebSocket Access
|
|
558
|
+
|
|
559
|
+
For custom WebSocket handling:
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
import { WebSocketManager } from '@veroai/chat';
|
|
563
|
+
|
|
564
|
+
const ws = new WebSocketManager({
|
|
565
|
+
url: 'wss://ws.veroai.dev',
|
|
566
|
+
getToken: () => localStorage.getItem('token'),
|
|
567
|
+
autoReconnect: true,
|
|
568
|
+
heartbeatInterval: 30000,
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
await ws.connect();
|
|
572
|
+
ws.on('message:new', handleNewMessage);
|
|
573
|
+
ws.sendTypingStart(conversationId);
|
|
574
|
+
ws.sendCallNotification(conversationId, 'ring', 'video', roomName);
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
## License
|
|
578
|
+
|
|
579
|
+
MIT
|