@veroai/chat 0.1.1 → 0.1.3
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/dist/{chunk-KYGXVRDI.js → chunk-PQNJZUZM.js} +83 -97
- package/dist/chunk-PQNJZUZM.js.map +1 -0
- package/dist/{client-DNgp4zPO.d.ts → client-DhKvlhe8.d.ts} +98 -45
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react/index.d.ts +17 -31
- package/dist/react/index.js +6 -73
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-KYGXVRDI.js.map +0 -1
|
@@ -5,6 +5,54 @@ var ChatApi = class {
|
|
|
5
5
|
constructor(config) {
|
|
6
6
|
this.apiUrl = config.apiUrl.replace(/\/$/, "");
|
|
7
7
|
this.getToken = config.getToken;
|
|
8
|
+
this.apiKey = config.apiKey;
|
|
9
|
+
}
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Token Generation (Server-side only)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Generate a chat token for a user (server-side only)
|
|
15
|
+
*
|
|
16
|
+
* This method is used by client backends to generate tokens for their users.
|
|
17
|
+
* Requires an API key to be configured.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // On your backend
|
|
22
|
+
* const chatApi = new ChatApi({
|
|
23
|
+
* apiUrl: 'https://chat-api.veroai.dev',
|
|
24
|
+
* apiKey: process.env.VERO_API_KEY,
|
|
25
|
+
* getToken: () => null, // Not needed for token generation
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* const { token } = await chatApi.generateToken({
|
|
29
|
+
* userId: user.id,
|
|
30
|
+
* name: user.displayName,
|
|
31
|
+
* avatar: user.avatarUrl,
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Return token to your frontend
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
async generateToken(options) {
|
|
38
|
+
if (!this.apiKey) {
|
|
39
|
+
throw new Error("API key is required for token generation. Set apiKey in config.");
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(`${this.apiUrl}/v1/auth/token`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"Content-Type": "application/json",
|
|
45
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
userId: options.userId,
|
|
49
|
+
name: options.name,
|
|
50
|
+
avatar: options.avatar,
|
|
51
|
+
metadata: options.metadata,
|
|
52
|
+
expiresIn: options.expiresIn
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
return this.handleResponse(response);
|
|
8
56
|
}
|
|
9
57
|
async getHeaders() {
|
|
10
58
|
const token = await this.getToken();
|
|
@@ -132,66 +180,6 @@ var ChatApi = class {
|
|
|
132
180
|
return transformMessage(data.message);
|
|
133
181
|
}
|
|
134
182
|
// ============================================================================
|
|
135
|
-
// Users
|
|
136
|
-
// ============================================================================
|
|
137
|
-
/**
|
|
138
|
-
* List all users (contacts)
|
|
139
|
-
*/
|
|
140
|
-
async listUsers(options) {
|
|
141
|
-
const searchParams = new URLSearchParams();
|
|
142
|
-
if (options?.includeVirtual) searchParams.set("include_virtual", "true");
|
|
143
|
-
const url = `${this.apiUrl}/v1/chat/users?${searchParams}`;
|
|
144
|
-
const response = await fetch(url, {
|
|
145
|
-
headers: await this.getHeaders()
|
|
146
|
-
});
|
|
147
|
-
const data = await this.handleResponse(response);
|
|
148
|
-
return data.users.map(transformUser);
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get online users
|
|
152
|
-
*/
|
|
153
|
-
async getOnlineUsers() {
|
|
154
|
-
const response = await fetch(`${this.apiUrl}/v1/chat/users/online`, {
|
|
155
|
-
headers: await this.getHeaders()
|
|
156
|
-
});
|
|
157
|
-
const data = await this.handleResponse(response);
|
|
158
|
-
return data.users.map(transformUser);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Get current user profile
|
|
162
|
-
*/
|
|
163
|
-
async getCurrentUser() {
|
|
164
|
-
const response = await fetch(`${this.apiUrl}/v1/chat/users/me`, {
|
|
165
|
-
headers: await this.getHeaders()
|
|
166
|
-
});
|
|
167
|
-
const data = await this.handleResponse(response);
|
|
168
|
-
return transformUser(data.user);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Get a specific user
|
|
172
|
-
*/
|
|
173
|
-
async getUser(userId) {
|
|
174
|
-
const response = await fetch(`${this.apiUrl}/v1/chat/users/${userId}`, {
|
|
175
|
-
headers: await this.getHeaders()
|
|
176
|
-
});
|
|
177
|
-
const data = await this.handleResponse(response);
|
|
178
|
-
return transformUser(data.user);
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Update current user's presence status
|
|
182
|
-
*/
|
|
183
|
-
async updateStatus(status, statusMessage) {
|
|
184
|
-
const response = await fetch(`${this.apiUrl}/v1/chat/users/me/status`, {
|
|
185
|
-
method: "PUT",
|
|
186
|
-
headers: await this.getHeaders(),
|
|
187
|
-
body: JSON.stringify({
|
|
188
|
-
status,
|
|
189
|
-
status_message: statusMessage
|
|
190
|
-
})
|
|
191
|
-
});
|
|
192
|
-
await this.handleResponse(response);
|
|
193
|
-
}
|
|
194
|
-
// ============================================================================
|
|
195
183
|
// Agents
|
|
196
184
|
// ============================================================================
|
|
197
185
|
/**
|
|
@@ -336,6 +324,8 @@ function transformMessage(raw) {
|
|
|
336
324
|
content: raw.content,
|
|
337
325
|
messageType: raw.message_type,
|
|
338
326
|
senderId: raw.sender_id,
|
|
327
|
+
senderName: raw.sender_name,
|
|
328
|
+
senderAvatar: raw.sender_avatar,
|
|
339
329
|
sender: raw.sender ? transformUser(raw.sender) : void 0,
|
|
340
330
|
readBy: raw.read_by?.map((r) => ({
|
|
341
331
|
userId: r.user_id,
|
|
@@ -617,7 +607,8 @@ var ChatClient = class extends EventEmitter {
|
|
|
617
607
|
this.tokenGetter = config.getToken || (() => config.token || null);
|
|
618
608
|
this.api = new ChatApi({
|
|
619
609
|
apiUrl: config.apiUrl,
|
|
620
|
-
getToken: this.tokenGetter
|
|
610
|
+
getToken: this.tokenGetter,
|
|
611
|
+
apiKey: config.apiKey
|
|
621
612
|
});
|
|
622
613
|
if (config.wsUrl) {
|
|
623
614
|
this.ws = new WebSocketManager({
|
|
@@ -666,6 +657,35 @@ var ChatClient = class extends EventEmitter {
|
|
|
666
657
|
this.config.token = token;
|
|
667
658
|
}
|
|
668
659
|
// ============================================================================
|
|
660
|
+
// Token Generation (Server-side only)
|
|
661
|
+
// ============================================================================
|
|
662
|
+
/**
|
|
663
|
+
* Generate a chat token for a user (server-side only)
|
|
664
|
+
*
|
|
665
|
+
* This method is used by client backends to generate tokens for their users.
|
|
666
|
+
* Requires an API key to be configured.
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```typescript
|
|
670
|
+
* // On your backend
|
|
671
|
+
* const chat = new ChatClient({
|
|
672
|
+
* apiUrl: 'https://chat-api.veroai.dev',
|
|
673
|
+
* apiKey: process.env.VERO_API_KEY,
|
|
674
|
+
* });
|
|
675
|
+
*
|
|
676
|
+
* const { token, expiresAt } = await chat.generateToken({
|
|
677
|
+
* userId: user.id,
|
|
678
|
+
* name: user.displayName,
|
|
679
|
+
* avatar: user.avatarUrl,
|
|
680
|
+
* });
|
|
681
|
+
*
|
|
682
|
+
* // Return token to your frontend
|
|
683
|
+
* ```
|
|
684
|
+
*/
|
|
685
|
+
async generateToken(options) {
|
|
686
|
+
return this.api.generateToken(options);
|
|
687
|
+
}
|
|
688
|
+
// ============================================================================
|
|
669
689
|
// Conversations
|
|
670
690
|
// ============================================================================
|
|
671
691
|
/**
|
|
@@ -754,40 +774,6 @@ var ChatClient = class extends EventEmitter {
|
|
|
754
774
|
this.ws?.sendTypingStop(conversationId);
|
|
755
775
|
}
|
|
756
776
|
// ============================================================================
|
|
757
|
-
// Users & Presence
|
|
758
|
-
// ============================================================================
|
|
759
|
-
/**
|
|
760
|
-
* List all users (contacts)
|
|
761
|
-
*/
|
|
762
|
-
async listUsers(options) {
|
|
763
|
-
return this.api.listUsers(options);
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Get online users
|
|
767
|
-
*/
|
|
768
|
-
async getOnlineUsers() {
|
|
769
|
-
return this.api.getOnlineUsers();
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* Get current user profile
|
|
773
|
-
*/
|
|
774
|
-
async getCurrentUser() {
|
|
775
|
-
return this.api.getCurrentUser();
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Get a specific user
|
|
779
|
-
*/
|
|
780
|
-
async getUser(userId) {
|
|
781
|
-
return this.api.getUser(userId);
|
|
782
|
-
}
|
|
783
|
-
/**
|
|
784
|
-
* Update current user's presence status
|
|
785
|
-
*/
|
|
786
|
-
async updateStatus(status, statusMessage) {
|
|
787
|
-
await this.api.updateStatus(status, statusMessage);
|
|
788
|
-
this.ws?.updatePresence(status, statusMessage);
|
|
789
|
-
}
|
|
790
|
-
// ============================================================================
|
|
791
777
|
// Agents
|
|
792
778
|
// ============================================================================
|
|
793
779
|
/**
|
|
@@ -916,5 +902,5 @@ var ChatClient = class extends EventEmitter {
|
|
|
916
902
|
};
|
|
917
903
|
|
|
918
904
|
export { ChatApi, ChatClient, WebSocketManager };
|
|
919
|
-
//# sourceMappingURL=chunk-
|
|
920
|
-
//# sourceMappingURL=chunk-
|
|
905
|
+
//# sourceMappingURL=chunk-PQNJZUZM.js.map
|
|
906
|
+
//# sourceMappingURL=chunk-PQNJZUZM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/index.ts","../src/websocket.ts","../src/client.ts"],"names":["EventEmitter"],"mappings":"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","file":"chunk-PQNJZUZM.js","sourcesContent":["/**\n * VeroAI Chat API Client\n *\n * HTTP client for the VeroAI Chat API\n */\n\nimport type {\n Conversation,\n CreateConversationParams,\n Message,\n SendMessageParams,\n GetMessagesParams,\n PaginatedMessages,\n User,\n PresenceStatus,\n AgentConfig,\n GenerateTokenOptions,\n GenerateTokenResult,\n} from '../types';\n\nexport interface ApiClientConfig {\n apiUrl: string;\n getToken: () => string | null | Promise<string | null>;\n /** API key for server-side token generation */\n apiKey?: string;\n}\n\n/**\n * Chat API Client for HTTP requests\n */\nexport class ChatApi {\n private apiUrl: string;\n private getToken: () => string | null | Promise<string | null>;\n private apiKey?: string;\n\n constructor(config: ApiClientConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '');\n this.getToken = config.getToken;\n this.apiKey = config.apiKey;\n }\n\n // ============================================================================\n // Token Generation (Server-side only)\n // ============================================================================\n\n /**\n * Generate a chat token for a user (server-side only)\n *\n * This method is used by client backends to generate tokens for their users.\n * Requires an API key to be configured.\n *\n * @example\n * ```typescript\n * // On your backend\n * const chatApi = new ChatApi({\n * apiUrl: 'https://chat-api.veroai.dev',\n * apiKey: process.env.VERO_API_KEY,\n * getToken: () => null, // Not needed for token generation\n * });\n *\n * const { token } = await chatApi.generateToken({\n * userId: user.id,\n * name: user.displayName,\n * avatar: user.avatarUrl,\n * });\n *\n * // Return token to your frontend\n * ```\n */\n async generateToken(options: GenerateTokenOptions): Promise<GenerateTokenResult> {\n if (!this.apiKey) {\n throw new Error('API key is required for token generation. Set apiKey in config.');\n }\n\n const response = await fetch(`${this.apiUrl}/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n userId: options.userId,\n name: options.name,\n avatar: options.avatar,\n metadata: options.metadata,\n expiresIn: options.expiresIn,\n }),\n });\n\n return this.handleResponse<GenerateTokenResult>(response);\n }\n\n private async getHeaders(): Promise<HeadersInit> {\n const token = await this.getToken();\n return {\n 'Content-Type': 'application/json',\n ...(token && { Authorization: `Bearer ${token}` }),\n };\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error?.message || errorJson.message || errorText;\n } catch {\n errorMessage = errorText;\n }\n throw new Error(errorMessage);\n }\n return response.json();\n }\n\n // ============================================================================\n // Conversations\n // ============================================================================\n\n /**\n * List all conversations for the current user\n */\n async listConversations(): Promise<Conversation[]> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ conversations: RawConversation[] }>(response);\n return data.conversations.map(transformConversation);\n }\n\n /**\n * Get a specific conversation\n */\n async getConversation(conversationId: string): Promise<Conversation> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ conversation: RawConversation }>(response);\n return transformConversation(data.conversation);\n }\n\n /**\n * Create a new conversation\n */\n async createConversation(params: CreateConversationParams): Promise<Conversation> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n type: params.type || 'direct',\n name: params.name,\n participant_ids: params.participantIds,\n agent_config_id: params.agentConfigId,\n metadata: params.metadata,\n }),\n });\n const data = await this.handleResponse<{ conversation: RawConversation }>(response);\n return transformConversation(data.conversation);\n }\n\n /**\n * Mark conversation as read\n */\n async markConversationRead(conversationId: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/read`, {\n method: 'POST',\n headers: await this.getHeaders(),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Leave a conversation\n */\n async leaveConversation(conversationId: string): Promise<void> {\n const response = await fetch(\n `${this.apiUrl}/v1/chat/conversations/${conversationId}/participants/me`,\n {\n method: 'DELETE',\n headers: await this.getHeaders(),\n }\n );\n await this.handleResponse<void>(response);\n }\n\n // ============================================================================\n // Messages\n // ============================================================================\n\n /**\n * Get messages for a conversation\n */\n async getMessages(conversationId: string, params?: GetMessagesParams): Promise<PaginatedMessages> {\n const searchParams = new URLSearchParams();\n if (params?.limit) searchParams.set('limit', String(params.limit));\n if (params?.offset) searchParams.set('offset', String(params.offset));\n if (params?.before) searchParams.set('before', params.before);\n\n const url = `${this.apiUrl}/v1/chat/conversations/${conversationId}/messages?${searchParams}`;\n const response = await fetch(url, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<RawPaginatedMessages>(response);\n return {\n messages: data.messages.map(transformMessage),\n total: data.total,\n hasMore: data.has_more,\n limit: data.limit,\n offset: data.offset,\n };\n }\n\n /**\n * Send a message to a conversation\n */\n async sendMessage(conversationId: string, params: SendMessageParams): Promise<Message> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/messages`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n content: params.content,\n message_type: params.messageType || 'text',\n metadata: params.metadata,\n }),\n });\n const data = await this.handleResponse<{ message: RawMessage }>(response);\n return transformMessage(data.message);\n }\n\n // ============================================================================\n // Agents\n // ============================================================================\n\n /**\n * Add agent to conversation\n */\n async addAgentToConversation(\n conversationId: string,\n agentConfigId: string,\n addAsParticipant = true\n ): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n agent_config_id: agentConfigId,\n add_as_participant: addAsParticipant,\n }),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Remove agent from conversation\n */\n async removeAgentFromConversation(conversationId: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'DELETE',\n headers: await this.getHeaders(),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Toggle agent enabled/disabled\n */\n async toggleAgent(conversationId: string, enabled: boolean): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'PATCH',\n headers: await this.getHeaders(),\n body: JSON.stringify({ enabled }),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * List available agents\n */\n async listAgents(): Promise<AgentConfig[]> {\n const response = await fetch(`${this.apiUrl}/v1/agent-configurations`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<AgentConfig[]>(response);\n return data;\n }\n\n // ============================================================================\n // Voice Rooms\n // ============================================================================\n\n /**\n * Create a new voice/video room\n */\n async createRoom(params: {\n name: string;\n emptyTimeout?: number;\n maxParticipants?: number;\n }): Promise<RoomInfo> {\n const response = await fetch(`${this.apiUrl}/v1/voice/rooms`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n name: params.name,\n empty_timeout: params.emptyTimeout,\n max_participants: params.maxParticipants,\n }),\n });\n const data = await this.handleResponse<{ room: RawRoomInfo }>(response);\n return transformRoomInfo(data.room);\n }\n\n /**\n * Join an existing room and get access token\n */\n async joinRoom(params: {\n roomName: string;\n participantName: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n }): Promise<RoomInfo> {\n const response = await fetch(\n `${this.apiUrl}/v1/voice/rooms/${encodeURIComponent(params.roomName)}/join`,\n {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n participant_name: params.participantName,\n can_publish: params.canPublish ?? true,\n can_subscribe: params.canSubscribe ?? true,\n }),\n }\n );\n const data = await this.handleResponse<RawJoinRoomResponse>(response);\n return {\n name: data.room_name,\n wsUrl: data.ws_url,\n token: data.token,\n };\n }\n\n /**\n * Get room token for an existing room\n * Convenience method for getting a token without creating\n */\n async getRoomToken(roomName: string, participantName: string): Promise<RoomInfo> {\n return this.joinRoom({ roomName, participantName });\n }\n}\n\n// ============================================================================\n// Raw API Types (snake_case from server)\n// ============================================================================\n\ninterface RawUser {\n id: string;\n email?: string;\n first_name?: string;\n last_name?: string;\n is_virtual?: boolean;\n agent_config_id?: string;\n status?: PresenceStatus;\n status_message?: string;\n last_seen?: string;\n created_at?: string;\n}\n\ninterface RawParticipant {\n user_id: string;\n role: 'admin' | 'member';\n is_active: boolean;\n joined_at?: string;\n last_seen?: string;\n user?: RawUser;\n}\n\ninterface RawConversation {\n id: string;\n name?: string;\n type: string;\n is_active: boolean;\n last_message_at?: string;\n agent_enabled?: boolean;\n agent_config_id?: string;\n participants?: RawParticipant[];\n unread_count?: number;\n metadata?: Record<string, unknown>;\n created_at?: string;\n updated_at?: string;\n}\n\ninterface RawReadReceipt {\n user_id: string;\n read_at?: string;\n}\n\ninterface RawMessage {\n id: string;\n conversation_id: string;\n content: string;\n message_type: string;\n sender_id?: string;\n sender_name?: string;\n sender_avatar?: string;\n sender?: RawUser;\n read_by?: RawReadReceipt[];\n metadata?: Record<string, unknown>;\n created_at?: string;\n edited_at?: string;\n}\n\ninterface RawPaginatedMessages {\n messages: RawMessage[];\n total: number;\n has_more: boolean;\n limit: number;\n offset: number;\n}\n\ninterface RawRoomInfo {\n id?: string;\n name: string;\n ws_url: string;\n token: string;\n}\n\ninterface RawJoinRoomResponse {\n room_name: string;\n ws_url: string;\n token: string;\n}\n\n// Exported room types\nexport interface RoomInfo {\n name: string;\n wsUrl: string;\n token: string;\n}\n\n// ============================================================================\n// Transform Functions (snake_case to camelCase)\n// ============================================================================\n\nfunction transformUser(raw: RawUser): User {\n return {\n id: raw.id,\n email: raw.email,\n firstName: raw.first_name,\n lastName: raw.last_name,\n isVirtual: raw.is_virtual,\n agentConfigId: raw.agent_config_id,\n status: raw.status,\n statusMessage: raw.status_message,\n lastSeen: raw.last_seen,\n createdAt: raw.created_at,\n };\n}\n\nfunction transformParticipant(raw: RawParticipant) {\n return {\n userId: raw.user_id,\n role: raw.role,\n isActive: raw.is_active,\n joinedAt: raw.joined_at,\n lastSeen: raw.last_seen,\n user: raw.user ? transformUser(raw.user) : undefined,\n };\n}\n\nfunction transformConversation(raw: RawConversation): Conversation {\n return {\n id: raw.id,\n name: raw.name,\n type: raw.type as Conversation['type'],\n isActive: raw.is_active,\n lastMessageAt: raw.last_message_at,\n agentEnabled: raw.agent_enabled,\n agentConfigId: raw.agent_config_id,\n participants: raw.participants?.map(transformParticipant),\n unreadCount: raw.unread_count,\n metadata: raw.metadata,\n createdAt: raw.created_at,\n updatedAt: raw.updated_at,\n };\n}\n\nfunction transformMessage(raw: RawMessage): Message {\n return {\n id: raw.id,\n conversationId: raw.conversation_id,\n content: raw.content,\n messageType: raw.message_type as Message['messageType'],\n senderId: raw.sender_id,\n senderName: raw.sender_name,\n senderAvatar: raw.sender_avatar,\n sender: raw.sender ? transformUser(raw.sender) : undefined,\n readBy: raw.read_by?.map((r) => ({\n userId: r.user_id,\n readAt: r.read_at,\n })),\n metadata: raw.metadata,\n createdAt: raw.created_at,\n editedAt: raw.edited_at,\n };\n}\n\nfunction transformRoomInfo(raw: RawRoomInfo): RoomInfo {\n return {\n name: raw.name,\n wsUrl: raw.ws_url,\n token: raw.token,\n };\n}\n","/**\n * VeroAI Chat WebSocket Manager\n *\n * Handles WebSocket connection, reconnection, and message handling\n */\n\nimport EventEmitter from 'eventemitter3';\nimport type {\n ChatEvents,\n WebSocketMessage,\n NewMessageEvent,\n TypingEvent,\n PresenceEvent,\n ReadReceiptEvent,\n CallEvent,\n CallAction,\n CallType,\n Message,\n Conversation,\n Participant,\n} from './types';\n\nexport interface WebSocketConfig {\n url: string;\n getToken: () => string | null | Promise<string | null>;\n autoReconnect?: boolean;\n reconnectInterval?: number;\n maxReconnectAttempts?: number;\n heartbeatInterval?: number;\n}\n\ntype ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\n/**\n * WebSocket connection manager with auto-reconnect\n */\nexport class WebSocketManager extends EventEmitter<ChatEvents> {\n private config: Required<WebSocketConfig>;\n private ws: WebSocket | null = null;\n private state: ConnectionState = 'disconnected';\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private pendingMessages: string[] = [];\n\n constructor(config: WebSocketConfig) {\n super();\n this.config = {\n url: config.url,\n getToken: config.getToken,\n autoReconnect: config.autoReconnect ?? true,\n reconnectInterval: config.reconnectInterval ?? 3000,\n maxReconnectAttempts: config.maxReconnectAttempts ?? 10,\n heartbeatInterval: config.heartbeatInterval ?? 30000,\n };\n }\n\n /**\n * Get current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.state === 'connected' && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n if (this.state === 'connecting' || this.state === 'connected') {\n return;\n }\n\n this.state = 'connecting';\n const token = await this.config.getToken();\n\n if (!token) {\n this.state = 'disconnected';\n throw new Error('No authentication token available');\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Build WebSocket URL with token\n const url = new URL(this.config.url);\n url.searchParams.set('token', token);\n\n this.ws = new WebSocket(url.toString());\n\n this.ws.onopen = () => {\n this.state = 'connected';\n this.reconnectAttempts = 0;\n this.startHeartbeat();\n this.flushPendingMessages();\n this.emit('connected');\n resolve();\n };\n\n this.ws.onclose = (event) => {\n this.handleClose(event.reason);\n };\n\n this.ws.onerror = (event) => {\n const error = new Error('WebSocket error');\n this.emit('error', error);\n if (this.state === 'connecting') {\n reject(error);\n }\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n } catch (error) {\n this.state = 'disconnected';\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the WebSocket server\n */\n disconnect(): void {\n this.config.autoReconnect = false;\n this.clearTimers();\n\n if (this.ws) {\n this.ws.close(1000, 'Client disconnect');\n this.ws = null;\n }\n\n this.state = 'disconnected';\n }\n\n /**\n * Send a message through the WebSocket\n */\n send(type: string, payload: unknown): void {\n const message = JSON.stringify({ type, payload, timestamp: new Date().toISOString() });\n\n if (this.isConnected()) {\n this.ws!.send(message);\n } else {\n // Queue message for when connection is restored\n this.pendingMessages.push(message);\n }\n }\n\n /**\n * Send typing indicator\n */\n sendTypingStart(conversationId: string): void {\n this.send('typing:start', { conversationId });\n }\n\n /**\n * Stop typing indicator\n */\n sendTypingStop(conversationId: string): void {\n this.send('typing:stop', { conversationId });\n }\n\n /**\n * Subscribe to a conversation for real-time updates\n */\n subscribeToConversation(conversationId: string): void {\n this.send('subscribe', { conversationId });\n }\n\n /**\n * Unsubscribe from a conversation\n */\n unsubscribeFromConversation(conversationId: string): void {\n this.send('unsubscribe', { conversationId });\n }\n\n /**\n * Update presence status\n */\n updatePresence(status: string, statusMessage?: string): void {\n this.send('presence:update', { status, statusMessage });\n }\n\n /**\n * Send call notification (ring, accept, reject, end)\n * Note: Actual WebRTC signaling is handled by LiveKit\n */\n sendCallNotification(\n conversationId: string,\n action: CallAction,\n callType?: CallType,\n roomName?: string\n ): void {\n this.send('call', { conversationId, action, callType, roomName });\n }\n\n private handleClose(reason?: string): void {\n this.stopHeartbeat();\n const wasConnected = this.state === 'connected';\n this.state = 'disconnected';\n this.ws = null;\n\n if (wasConnected) {\n this.emit('disconnected', reason);\n }\n\n // Attempt reconnection if enabled\n if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return;\n }\n\n this.state = 'reconnecting';\n this.reconnectAttempts++;\n\n const delay = Math.min(\n this.config.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1),\n 30000 // Max 30 seconds\n );\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n try {\n await this.connect();\n } catch (error) {\n // Connect will handle scheduling next reconnect\n }\n }, delay);\n }\n\n private handleMessage(data: string): void {\n try {\n const message = JSON.parse(data) as WebSocketMessage;\n\n switch (message.type) {\n case 'message:new':\n this.emit('message:new', message.payload as NewMessageEvent);\n break;\n\n case 'message:updated':\n this.emit('message:updated', message.payload as Message);\n break;\n\n case 'message:deleted': {\n const { messageId, conversationId } = message.payload as {\n messageId: string;\n conversationId: string;\n };\n this.emit('message:deleted', messageId, conversationId);\n break;\n }\n\n case 'conversation:created':\n this.emit('conversation:created', message.payload as Conversation);\n break;\n\n case 'conversation:updated':\n this.emit('conversation:updated', message.payload as Conversation);\n break;\n\n case 'participant:joined': {\n const { conversationId, participant } = message.payload as {\n conversationId: string;\n participant: Participant;\n };\n this.emit('participant:joined', conversationId, participant);\n break;\n }\n\n case 'participant:left': {\n const payload = message.payload as { conversationId: string; userId: string };\n this.emit('participant:left', payload.conversationId, payload.userId);\n break;\n }\n\n case 'presence:updated':\n this.emit('presence:updated', message.payload as PresenceEvent);\n break;\n\n case 'typing:start':\n this.emit('typing:start', message.payload as TypingEvent);\n break;\n\n case 'typing:stop':\n this.emit('typing:stop', message.payload as TypingEvent);\n break;\n\n case 'read:receipt':\n this.emit('read:receipt', message.payload as ReadReceiptEvent);\n break;\n\n case 'call:ring':\n this.emit('call:ring', message.payload as CallEvent);\n break;\n\n case 'call:accept':\n this.emit('call:accept', message.payload as CallEvent);\n break;\n\n case 'call:reject':\n this.emit('call:reject', message.payload as CallEvent);\n break;\n\n case 'call:end':\n this.emit('call:end', message.payload as CallEvent);\n break;\n }\n } catch (error) {\n console.error('[ChatWS] Failed to parse message:', error);\n }\n }\n\n private flushPendingMessages(): void {\n while (this.pendingMessages.length > 0 && this.isConnected()) {\n const message = this.pendingMessages.shift();\n if (message) {\n this.ws!.send(message);\n }\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n if (this.isConnected()) {\n this.send('ping', {});\n }\n }, this.config.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private clearTimers(): void {\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n}\n","/**\n * VeroAI Chat Client\n *\n * Main entry point for the Chat SDK - combines HTTP API and WebSocket\n */\n\nimport EventEmitter from 'eventemitter3';\nimport { ChatApi, type RoomInfo } from './api';\nimport { WebSocketManager } from './websocket';\nimport type {\n ChatClientConfig,\n ChatEvents,\n Conversation,\n CreateConversationParams,\n Message,\n SendMessageParams,\n GetMessagesParams,\n PaginatedMessages,\n AgentConfig,\n GenerateTokenOptions,\n GenerateTokenResult,\n} from './types';\n\n/**\n * VeroAI Chat Client\n *\n * Provides a unified interface for chat functionality:\n * - HTTP API for CRUD operations\n * - WebSocket for real-time events\n *\n * @example\n * ```typescript\n * const chat = new ChatClient({\n * apiUrl: 'https://api.veroai.dev',\n * wsUrl: 'wss://ws.veroai.dev',\n * token: 'your-jwt-token',\n * });\n *\n * // Connect to real-time events\n * await chat.connect();\n *\n * // Listen for new messages\n * chat.on('message:new', ({ message, conversationId }) => {\n * console.log('New message:', message);\n * });\n *\n * // Send a message\n * await chat.sendMessage(conversationId, { content: 'Hello!' });\n * ```\n */\nexport class ChatClient extends EventEmitter<ChatEvents> {\n private api: ChatApi;\n private ws: WebSocketManager | null = null;\n private config: ChatClientConfig;\n private tokenGetter: () => string | null | Promise<string | null>;\n\n constructor(config: ChatClientConfig) {\n super();\n this.config = config;\n\n // Create token getter\n this.tokenGetter = config.getToken || (() => config.token || null);\n\n // Initialize API client\n this.api = new ChatApi({\n apiUrl: config.apiUrl,\n getToken: this.tokenGetter,\n apiKey: config.apiKey,\n });\n\n // Initialize WebSocket if URL provided\n if (config.wsUrl) {\n this.ws = new WebSocketManager({\n url: config.wsUrl,\n getToken: this.tokenGetter,\n autoReconnect: config.autoReconnect ?? true,\n reconnectInterval: config.reconnectInterval,\n maxReconnectAttempts: config.maxReconnectAttempts,\n });\n\n // Forward WebSocket events\n this.forwardWebSocketEvents();\n }\n\n // Auto-connect if enabled\n if (config.autoConnect && config.wsUrl) {\n this.connect().catch((error) => {\n console.error('[ChatClient] Auto-connect failed:', error);\n });\n }\n }\n\n // ============================================================================\n // Connection Management\n // ============================================================================\n\n /**\n * Connect to WebSocket for real-time updates\n */\n async connect(): Promise<void> {\n if (!this.ws) {\n throw new Error('WebSocket URL not configured');\n }\n await this.ws.connect();\n }\n\n /**\n * Disconnect from WebSocket\n */\n disconnect(): void {\n this.ws?.disconnect();\n }\n\n /**\n * Check if WebSocket is connected\n */\n isConnected(): boolean {\n return this.ws?.isConnected() ?? false;\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string): void {\n this.config.token = token;\n }\n\n // ============================================================================\n // Token Generation (Server-side only)\n // ============================================================================\n\n /**\n * Generate a chat token for a user (server-side only)\n *\n * This method is used by client backends to generate tokens for their users.\n * Requires an API key to be configured.\n *\n * @example\n * ```typescript\n * // On your backend\n * const chat = new ChatClient({\n * apiUrl: 'https://chat-api.veroai.dev',\n * apiKey: process.env.VERO_API_KEY,\n * });\n *\n * const { token, expiresAt } = await chat.generateToken({\n * userId: user.id,\n * name: user.displayName,\n * avatar: user.avatarUrl,\n * });\n *\n * // Return token to your frontend\n * ```\n */\n async generateToken(options: GenerateTokenOptions): Promise<GenerateTokenResult> {\n return this.api.generateToken(options);\n }\n\n // ============================================================================\n // Conversations\n // ============================================================================\n\n /**\n * List all conversations for the current user\n */\n async listConversations(): Promise<Conversation[]> {\n return this.api.listConversations();\n }\n\n /**\n * Get a specific conversation\n */\n async getConversation(conversationId: string): Promise<Conversation> {\n return this.api.getConversation(conversationId);\n }\n\n /**\n * Create a new conversation\n */\n async createConversation(params: CreateConversationParams): Promise<Conversation> {\n const conversation = await this.api.createConversation(params);\n\n // Subscribe to real-time updates for new conversation\n if (this.ws?.isConnected()) {\n this.ws.subscribeToConversation(conversation.id);\n }\n\n return conversation;\n }\n\n /**\n * Mark conversation as read\n */\n async markConversationRead(conversationId: string): Promise<void> {\n return this.api.markConversationRead(conversationId);\n }\n\n /**\n * Leave a conversation\n */\n async leaveConversation(conversationId: string): Promise<void> {\n // Unsubscribe from real-time updates\n if (this.ws?.isConnected()) {\n this.ws.unsubscribeFromConversation(conversationId);\n }\n\n return this.api.leaveConversation(conversationId);\n }\n\n /**\n * Subscribe to real-time updates for a conversation\n */\n subscribeToConversation(conversationId: string): void {\n this.ws?.subscribeToConversation(conversationId);\n }\n\n /**\n * Unsubscribe from real-time updates for a conversation\n */\n unsubscribeFromConversation(conversationId: string): void {\n this.ws?.unsubscribeFromConversation(conversationId);\n }\n\n // ============================================================================\n // Messages\n // ============================================================================\n\n /**\n * Get messages for a conversation\n */\n async getMessages(conversationId: string, params?: GetMessagesParams): Promise<PaginatedMessages> {\n return this.api.getMessages(conversationId, params);\n }\n\n /**\n * Send a message to a conversation\n */\n async sendMessage(conversationId: string, params: SendMessageParams): Promise<Message> {\n return this.api.sendMessage(conversationId, params);\n }\n\n /**\n * Send a text message (convenience method)\n */\n async send(conversationId: string, content: string): Promise<Message> {\n return this.sendMessage(conversationId, { content });\n }\n\n // ============================================================================\n // Typing Indicators\n // ============================================================================\n\n /**\n * Send typing start indicator\n */\n sendTypingStart(conversationId: string): void {\n this.ws?.sendTypingStart(conversationId);\n }\n\n /**\n * Send typing stop indicator\n */\n sendTypingStop(conversationId: string): void {\n this.ws?.sendTypingStop(conversationId);\n }\n\n // ============================================================================\n // Agents\n // ============================================================================\n\n /**\n * Add agent to conversation\n */\n async addAgentToConversation(\n conversationId: string,\n agentConfigId: string,\n addAsParticipant = true\n ): Promise<void> {\n return this.api.addAgentToConversation(conversationId, agentConfigId, addAsParticipant);\n }\n\n /**\n * Remove agent from conversation\n */\n async removeAgentFromConversation(conversationId: string): Promise<void> {\n return this.api.removeAgentFromConversation(conversationId);\n }\n\n /**\n * Toggle agent enabled/disabled\n */\n async toggleAgent(conversationId: string, enabled: boolean): Promise<void> {\n return this.api.toggleAgent(conversationId, enabled);\n }\n\n /**\n * List available agents\n */\n async listAgents(): Promise<AgentConfig[]> {\n return this.api.listAgents();\n }\n\n // ============================================================================\n // Voice/Video Calls\n // ============================================================================\n\n /**\n * Create a new voice/video room\n *\n * @example\n * ```typescript\n * const room = await chat.createRoom({ name: `call-${conversationId}` });\n * // Use room.wsUrl and room.token with voice client\n * ```\n */\n async createRoom(params: {\n name: string;\n emptyTimeout?: number;\n maxParticipants?: number;\n }): Promise<RoomInfo> {\n return this.api.createRoom(params);\n }\n\n /**\n * Join an existing room and get access token\n *\n * @example\n * ```typescript\n * const room = await chat.joinRoom({\n * roomName: `call-${conversationId}`,\n * participantName: 'John Doe',\n * });\n * // Connect to room using voice client SDK with room.wsUrl and room.token\n * ```\n */\n async joinRoom(params: {\n roomName: string;\n participantName: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n }): Promise<RoomInfo> {\n return this.api.joinRoom(params);\n }\n\n /**\n * Initiate a call in a conversation\n * This notifies other participants that you're calling\n *\n * @example\n * ```typescript\n * // Start a video call\n * const room = await chat.startCall(conversationId, 'video');\n * // room contains { name, wsUrl, token } for Vero Voice\n * ```\n */\n async startCall(\n conversationId: string,\n callType: 'audio' | 'video' = 'audio'\n ): Promise<RoomInfo> {\n // Create room\n const roomName = `call-${conversationId}-${Date.now()}`;\n const room = await this.api.createRoom({ name: roomName });\n\n // Notify other participants via WebSocket\n this.ws?.sendCallNotification(conversationId, 'ring', callType, roomName);\n\n return room;\n }\n\n /**\n * Accept an incoming call\n *\n * @example\n * ```typescript\n * chat.on('call:ring', async ({ conversationId, roomName, callType }) => {\n * const room = await chat.acceptCall(conversationId, roomName);\n * // Connect to room using voice client SDK\n * });\n * ```\n */\n async acceptCall(\n conversationId: string,\n roomName: string,\n participantName: string\n ): Promise<RoomInfo> {\n const room = await this.api.joinRoom({ roomName, participantName });\n\n // Notify caller that we accepted\n this.ws?.sendCallNotification(conversationId, 'accept', undefined, roomName);\n\n return room;\n }\n\n /**\n * Reject an incoming call\n */\n rejectCall(conversationId: string): void {\n this.ws?.sendCallNotification(conversationId, 'reject');\n }\n\n /**\n * End an ongoing call\n */\n endCall(conversationId: string): void {\n this.ws?.sendCallNotification(conversationId, 'end');\n }\n\n // ============================================================================\n // Internal\n // ============================================================================\n\n private forwardWebSocketEvents(): void {\n if (!this.ws) return;\n\n // Forward all events from WebSocket manager to ChatClient\n this.ws.on('connected', () => this.emit('connected'));\n this.ws.on('disconnected', (reason) => this.emit('disconnected', reason));\n this.ws.on('error', (error) => this.emit('error', error));\n this.ws.on('message:new', (event) => this.emit('message:new', event));\n this.ws.on('message:updated', (msg) => this.emit('message:updated', msg));\n this.ws.on('message:deleted', (msgId, convId) => this.emit('message:deleted', msgId, convId));\n this.ws.on('conversation:created', (conv) => this.emit('conversation:created', conv));\n this.ws.on('conversation:updated', (conv) => this.emit('conversation:updated', conv));\n this.ws.on('participant:joined', (convId, p) => this.emit('participant:joined', convId, p));\n this.ws.on('participant:left', (convId, userId) => this.emit('participant:left', convId, userId));\n this.ws.on('presence:updated', (event) => this.emit('presence:updated', event));\n this.ws.on('typing:start', (event) => this.emit('typing:start', event));\n this.ws.on('typing:stop', (event) => this.emit('typing:stop', event));\n this.ws.on('read:receipt', (event) => this.emit('read:receipt', event));\n this.ws.on('call:ring', (event) => this.emit('call:ring', event));\n this.ws.on('call:accept', (event) => this.emit('call:accept', event));\n this.ws.on('call:reject', (event) => this.emit('call:reject', event));\n this.ws.on('call:end', (event) => this.emit('call:end', event));\n }\n}\n"]}
|
|
@@ -12,6 +12,8 @@ interface ChatClientConfig {
|
|
|
12
12
|
token?: string;
|
|
13
13
|
/** Token getter function for dynamic token retrieval */
|
|
14
14
|
getToken?: () => string | null | Promise<string | null>;
|
|
15
|
+
/** API key for server-side token generation (use with generateToken) */
|
|
16
|
+
apiKey?: string;
|
|
15
17
|
/** Auto-connect to WebSocket on initialization */
|
|
16
18
|
autoConnect?: boolean;
|
|
17
19
|
/** Auto-reconnect on disconnect */
|
|
@@ -21,6 +23,44 @@ interface ChatClientConfig {
|
|
|
21
23
|
/** Max reconnect attempts */
|
|
22
24
|
maxReconnectAttempts?: number;
|
|
23
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Options for generating a chat token
|
|
28
|
+
* Used by client backends to generate tokens for their users
|
|
29
|
+
*/
|
|
30
|
+
interface GenerateTokenOptions {
|
|
31
|
+
/** User ID from client's system */
|
|
32
|
+
userId: string;
|
|
33
|
+
/** Display name for the user */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Avatar URL */
|
|
36
|
+
avatar?: string;
|
|
37
|
+
/** Custom metadata to include in token */
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
/** Token expiration in seconds (default: 3600, max: 30 days) */
|
|
40
|
+
expiresIn?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Result of token generation
|
|
44
|
+
*/
|
|
45
|
+
interface GenerateTokenResult {
|
|
46
|
+
/** JWT token for chat operations */
|
|
47
|
+
token: string;
|
|
48
|
+
/** Unix timestamp when token expires */
|
|
49
|
+
expiresAt: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* User context extracted from chat token
|
|
53
|
+
*/
|
|
54
|
+
interface ChatUser {
|
|
55
|
+
/** User ID from client's system */
|
|
56
|
+
id: string;
|
|
57
|
+
/** Display name */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Avatar URL */
|
|
60
|
+
avatar?: string;
|
|
61
|
+
/** Custom metadata */
|
|
62
|
+
metadata?: Record<string, unknown>;
|
|
63
|
+
}
|
|
24
64
|
interface User {
|
|
25
65
|
id: string;
|
|
26
66
|
email?: string;
|
|
@@ -78,6 +118,11 @@ interface Message {
|
|
|
78
118
|
content: string;
|
|
79
119
|
messageType: MessageType;
|
|
80
120
|
senderId?: string;
|
|
121
|
+
/** Denormalized sender display name (from token at write time) */
|
|
122
|
+
senderName?: string;
|
|
123
|
+
/** Denormalized sender avatar URL (from token at write time) */
|
|
124
|
+
senderAvatar?: string;
|
|
125
|
+
/** @deprecated Use senderName/senderAvatar instead. Full sender object (requires lookup) */
|
|
81
126
|
sender?: User;
|
|
82
127
|
readBy?: ReadReceipt[];
|
|
83
128
|
metadata?: Record<string, unknown>;
|
|
@@ -186,6 +231,8 @@ interface ChatEvents {
|
|
|
186
231
|
interface ApiClientConfig {
|
|
187
232
|
apiUrl: string;
|
|
188
233
|
getToken: () => string | null | Promise<string | null>;
|
|
234
|
+
/** API key for server-side token generation */
|
|
235
|
+
apiKey?: string;
|
|
189
236
|
}
|
|
190
237
|
/**
|
|
191
238
|
* Chat API Client for HTTP requests
|
|
@@ -193,7 +240,33 @@ interface ApiClientConfig {
|
|
|
193
240
|
declare class ChatApi {
|
|
194
241
|
private apiUrl;
|
|
195
242
|
private getToken;
|
|
243
|
+
private apiKey?;
|
|
196
244
|
constructor(config: ApiClientConfig);
|
|
245
|
+
/**
|
|
246
|
+
* Generate a chat token for a user (server-side only)
|
|
247
|
+
*
|
|
248
|
+
* This method is used by client backends to generate tokens for their users.
|
|
249
|
+
* Requires an API key to be configured.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* // On your backend
|
|
254
|
+
* const chatApi = new ChatApi({
|
|
255
|
+
* apiUrl: 'https://chat-api.veroai.dev',
|
|
256
|
+
* apiKey: process.env.VERO_API_KEY,
|
|
257
|
+
* getToken: () => null, // Not needed for token generation
|
|
258
|
+
* });
|
|
259
|
+
*
|
|
260
|
+
* const { token } = await chatApi.generateToken({
|
|
261
|
+
* userId: user.id,
|
|
262
|
+
* name: user.displayName,
|
|
263
|
+
* avatar: user.avatarUrl,
|
|
264
|
+
* });
|
|
265
|
+
*
|
|
266
|
+
* // Return token to your frontend
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
generateToken(options: GenerateTokenOptions): Promise<GenerateTokenResult>;
|
|
197
270
|
private getHeaders;
|
|
198
271
|
private handleResponse;
|
|
199
272
|
/**
|
|
@@ -224,28 +297,6 @@ declare class ChatApi {
|
|
|
224
297
|
* Send a message to a conversation
|
|
225
298
|
*/
|
|
226
299
|
sendMessage(conversationId: string, params: SendMessageParams): Promise<Message>;
|
|
227
|
-
/**
|
|
228
|
-
* List all users (contacts)
|
|
229
|
-
*/
|
|
230
|
-
listUsers(options?: {
|
|
231
|
-
includeVirtual?: boolean;
|
|
232
|
-
}): Promise<User[]>;
|
|
233
|
-
/**
|
|
234
|
-
* Get online users
|
|
235
|
-
*/
|
|
236
|
-
getOnlineUsers(): Promise<User[]>;
|
|
237
|
-
/**
|
|
238
|
-
* Get current user profile
|
|
239
|
-
*/
|
|
240
|
-
getCurrentUser(): Promise<User>;
|
|
241
|
-
/**
|
|
242
|
-
* Get a specific user
|
|
243
|
-
*/
|
|
244
|
-
getUser(userId: string): Promise<User>;
|
|
245
|
-
/**
|
|
246
|
-
* Update current user's presence status
|
|
247
|
-
*/
|
|
248
|
-
updateStatus(status: PresenceStatus, statusMessage?: string): Promise<void>;
|
|
249
300
|
/**
|
|
250
301
|
* Add agent to conversation
|
|
251
302
|
*/
|
|
@@ -346,6 +397,30 @@ declare class ChatClient extends EventEmitter<ChatEvents> {
|
|
|
346
397
|
* Update authentication token
|
|
347
398
|
*/
|
|
348
399
|
setToken(token: string): void;
|
|
400
|
+
/**
|
|
401
|
+
* Generate a chat token for a user (server-side only)
|
|
402
|
+
*
|
|
403
|
+
* This method is used by client backends to generate tokens for their users.
|
|
404
|
+
* Requires an API key to be configured.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* // On your backend
|
|
409
|
+
* const chat = new ChatClient({
|
|
410
|
+
* apiUrl: 'https://chat-api.veroai.dev',
|
|
411
|
+
* apiKey: process.env.VERO_API_KEY,
|
|
412
|
+
* });
|
|
413
|
+
*
|
|
414
|
+
* const { token, expiresAt } = await chat.generateToken({
|
|
415
|
+
* userId: user.id,
|
|
416
|
+
* name: user.displayName,
|
|
417
|
+
* avatar: user.avatarUrl,
|
|
418
|
+
* });
|
|
419
|
+
*
|
|
420
|
+
* // Return token to your frontend
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
generateToken(options: GenerateTokenOptions): Promise<GenerateTokenResult>;
|
|
349
424
|
/**
|
|
350
425
|
* List all conversations for the current user
|
|
351
426
|
*/
|
|
@@ -394,28 +469,6 @@ declare class ChatClient extends EventEmitter<ChatEvents> {
|
|
|
394
469
|
* Send typing stop indicator
|
|
395
470
|
*/
|
|
396
471
|
sendTypingStop(conversationId: string): void;
|
|
397
|
-
/**
|
|
398
|
-
* List all users (contacts)
|
|
399
|
-
*/
|
|
400
|
-
listUsers(options?: {
|
|
401
|
-
includeVirtual?: boolean;
|
|
402
|
-
}): Promise<User[]>;
|
|
403
|
-
/**
|
|
404
|
-
* Get online users
|
|
405
|
-
*/
|
|
406
|
-
getOnlineUsers(): Promise<User[]>;
|
|
407
|
-
/**
|
|
408
|
-
* Get current user profile
|
|
409
|
-
*/
|
|
410
|
-
getCurrentUser(): Promise<User>;
|
|
411
|
-
/**
|
|
412
|
-
* Get a specific user
|
|
413
|
-
*/
|
|
414
|
-
getUser(userId: string): Promise<User>;
|
|
415
|
-
/**
|
|
416
|
-
* Update current user's presence status
|
|
417
|
-
*/
|
|
418
|
-
updateStatus(status: PresenceStatus, statusMessage?: string): Promise<void>;
|
|
419
472
|
/**
|
|
420
473
|
* Add agent to conversation
|
|
421
474
|
*/
|
|
@@ -499,4 +552,4 @@ declare class ChatClient extends EventEmitter<ChatEvents> {
|
|
|
499
552
|
private forwardWebSocketEvents;
|
|
500
553
|
}
|
|
501
554
|
|
|
502
|
-
export { type AgentConfig as A, type ChatEvents as C, type
|
|
555
|
+
export { type AgentConfig as A, type ChatEvents as C, type GenerateTokenOptions as G, type Message as M, type NewMessageEvent as N, type PaginatedMessages as P, type ReadReceipt as R, type SendMessageParams as S, type TypingEvent as T, type User as U, type WebSocketEventType as W, type CallAction as a, type CallType as b, type ApiError as c, type ApiResponse as d, type CallEvent as e, ChatApi as f, ChatClient as g, type ChatClientConfig as h, type ChatUser as i, type Conversation as j, type ConversationType as k, type CreateConversationParams as l, type GenerateTokenResult as m, type GetMessagesParams as n, type MessageType as o, type Participant as p, type PresenceEvent as q, type PresenceStatus as r, type ReadReceiptEvent as s, type RoomInfo as t, type UserPresence as u, type WebSocketMessage as v };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ChatEvents, a as CallAction, b as CallType } from './client-
|
|
2
|
-
export { A as AgentConfig, c as ApiError, d as ApiResponse, e as CallEvent, f as ChatApi, g as ChatClient, h as ChatClientConfig, i as
|
|
1
|
+
import { C as ChatEvents, a as CallAction, b as CallType } from './client-DhKvlhe8.js';
|
|
2
|
+
export { A as AgentConfig, c as ApiError, d as ApiResponse, e as CallEvent, f as ChatApi, g as ChatClient, h as ChatClientConfig, i as ChatUser, j as Conversation, k as ConversationType, l as CreateConversationParams, G as GenerateTokenOptions, m as GenerateTokenResult, n as GetMessagesParams, M as Message, o as MessageType, N as NewMessageEvent, P as PaginatedMessages, p as Participant, q as PresenceEvent, r as PresenceStatus, R as ReadReceipt, s as ReadReceiptEvent, t as RoomInfo, S as SendMessageParams, T as TypingEvent, U as User, u as UserPresence, W as WebSocketEventType, v as WebSocketMessage } from './client-DhKvlhe8.js';
|
|
3
3
|
import EventEmitter from 'eventemitter3';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { g as ChatClient,
|
|
3
|
+
import { g as ChatClient, j as Conversation, h as ChatClientConfig, M as Message, S as SendMessageParams, r as PresenceStatus } from '../client-DhKvlhe8.js';
|
|
4
4
|
import 'eventemitter3';
|
|
5
5
|
|
|
6
6
|
interface ChatContextValue {
|
|
@@ -8,8 +8,6 @@ interface ChatContextValue {
|
|
|
8
8
|
client: ChatClient | null;
|
|
9
9
|
/** Whether the WebSocket is connected */
|
|
10
10
|
isConnected: boolean;
|
|
11
|
-
/** Current user profile */
|
|
12
|
-
currentUser: User | null;
|
|
13
11
|
/** List of conversations */
|
|
14
12
|
conversations: Conversation[];
|
|
15
13
|
/** Loading state for conversations */
|
|
@@ -20,8 +18,6 @@ interface ChatContextValue {
|
|
|
20
18
|
connect: () => Promise<void>;
|
|
21
19
|
/** Disconnect from WebSocket */
|
|
22
20
|
disconnect: () => void;
|
|
23
|
-
/** Update current user's status */
|
|
24
|
-
updateStatus: (status: PresenceStatus, statusMessage?: string) => Promise<void>;
|
|
25
21
|
}
|
|
26
22
|
interface ChatProviderProps {
|
|
27
23
|
children: React.ReactNode;
|
|
@@ -29,8 +25,6 @@ interface ChatProviderProps {
|
|
|
29
25
|
config: ChatClientConfig;
|
|
30
26
|
/** Auto-fetch conversations on mount */
|
|
31
27
|
autoFetchConversations?: boolean;
|
|
32
|
-
/** Auto-fetch current user on mount */
|
|
33
|
-
autoFetchCurrentUser?: boolean;
|
|
34
28
|
}
|
|
35
29
|
/**
|
|
36
30
|
* ChatProvider - Provides chat functionality to React components
|
|
@@ -43,7 +37,7 @@ interface ChatProviderProps {
|
|
|
43
37
|
* config={{
|
|
44
38
|
* apiUrl: 'https://api.veroai.dev',
|
|
45
39
|
* wsUrl: 'wss://ws.veroai.dev',
|
|
46
|
-
*
|
|
40
|
+
* getToken: () => myAuthToken,
|
|
47
41
|
* }}
|
|
48
42
|
* >
|
|
49
43
|
* <ChatApp />
|
|
@@ -52,7 +46,7 @@ interface ChatProviderProps {
|
|
|
52
46
|
* }
|
|
53
47
|
* ```
|
|
54
48
|
*/
|
|
55
|
-
declare function ChatProvider({ children, config, autoFetchConversations,
|
|
49
|
+
declare function ChatProvider({ children, config, autoFetchConversations, }: ChatProviderProps): react_jsx_runtime.JSX.Element;
|
|
56
50
|
/**
|
|
57
51
|
* useChat - Access chat context
|
|
58
52
|
*
|
|
@@ -140,44 +134,36 @@ declare function useConversation(conversationId: string | undefined, options?: U
|
|
|
140
134
|
/**
|
|
141
135
|
* usePresence Hook
|
|
142
136
|
*
|
|
143
|
-
* Track
|
|
137
|
+
* Track user presence/online status via WebSocket events.
|
|
138
|
+
* The chat backend is user-agnostic - presence is tracked via real-time events only.
|
|
144
139
|
*/
|
|
145
140
|
|
|
146
141
|
interface UsePresenceReturn {
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
/** Whether loading online users */
|
|
150
|
-
isLoading: boolean;
|
|
142
|
+
/** Map of userId to their presence status */
|
|
143
|
+
presenceMap: Map<string, PresenceStatus>;
|
|
151
144
|
/** Get presence status for a specific user */
|
|
152
145
|
getUserStatus: (userId: string) => PresenceStatus;
|
|
153
|
-
/** Refresh online users list */
|
|
154
|
-
refresh: () => Promise<void>;
|
|
155
|
-
/** Error if any */
|
|
156
|
-
error: Error | null;
|
|
157
146
|
}
|
|
158
147
|
/**
|
|
159
|
-
* usePresence - Track
|
|
148
|
+
* usePresence - Track user presence via WebSocket events
|
|
149
|
+
*
|
|
150
|
+
* Note: The chat backend is user-agnostic. This hook only tracks presence
|
|
151
|
+
* updates received via WebSocket. To know who is online, you need to
|
|
152
|
+
* implement presence tracking in your own system.
|
|
160
153
|
*
|
|
161
154
|
* @example
|
|
162
155
|
* ```tsx
|
|
163
|
-
* function
|
|
164
|
-
* const {
|
|
156
|
+
* function UserStatus({ userId }: { userId: string }) {
|
|
157
|
+
* const { getUserStatus } = usePresence();
|
|
158
|
+
* const status = getUserStatus(userId);
|
|
165
159
|
*
|
|
166
|
-
* return
|
|
167
|
-
* <div>
|
|
168
|
-
* {onlineUsers.map(user => (
|
|
169
|
-
* <div key={user.id}>
|
|
170
|
-
* {user.firstName} - {getUserStatus(user.id)}
|
|
171
|
-
* </div>
|
|
172
|
-
* ))}
|
|
173
|
-
* </div>
|
|
174
|
-
* );
|
|
160
|
+
* return <span className={`status-${status}`}>{status}</span>;
|
|
175
161
|
* }
|
|
176
162
|
* ```
|
|
177
163
|
*/
|
|
178
164
|
declare function usePresence(): UsePresenceReturn;
|
|
179
165
|
/**
|
|
180
|
-
* useUserPresence - Track presence for a specific user
|
|
166
|
+
* useUserPresence - Track presence for a specific user via WebSocket events
|
|
181
167
|
*/
|
|
182
168
|
declare function useUserPresence(userId: string | undefined): {
|
|
183
169
|
status: PresenceStatus;
|
package/dist/react/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatClient } from '../chunk-
|
|
1
|
+
import { ChatClient } from '../chunk-PQNJZUZM.js';
|
|
2
2
|
import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -6,12 +6,10 @@ var ChatContext = createContext(null);
|
|
|
6
6
|
function ChatProvider({
|
|
7
7
|
children,
|
|
8
8
|
config,
|
|
9
|
-
autoFetchConversations = true
|
|
10
|
-
autoFetchCurrentUser = true
|
|
9
|
+
autoFetchConversations = true
|
|
11
10
|
}) {
|
|
12
11
|
const [client, setClient] = useState(null);
|
|
13
12
|
const [isConnected, setIsConnected] = useState(false);
|
|
14
|
-
const [currentUser, setCurrentUser] = useState(null);
|
|
15
13
|
const [conversations, setConversations] = useState([]);
|
|
16
14
|
const [isLoadingConversations, setIsLoadingConversations] = useState(false);
|
|
17
15
|
const clientRef = useRef(null);
|
|
@@ -48,10 +46,6 @@ function ChatProvider({
|
|
|
48
46
|
chatClient.removeAllListeners();
|
|
49
47
|
};
|
|
50
48
|
}, [config.apiUrl, config.wsUrl, config.token]);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if (!client || !autoFetchCurrentUser) return;
|
|
53
|
-
client.getCurrentUser().then(setCurrentUser).catch(console.error);
|
|
54
|
-
}, [client, autoFetchCurrentUser]);
|
|
55
49
|
const refreshConversations = useCallback(async () => {
|
|
56
50
|
if (!client) return;
|
|
57
51
|
setIsLoadingConversations(true);
|
|
@@ -77,27 +71,14 @@ function ChatProvider({
|
|
|
77
71
|
const disconnect = useCallback(() => {
|
|
78
72
|
client?.disconnect();
|
|
79
73
|
}, [client]);
|
|
80
|
-
const updateStatus = useCallback(
|
|
81
|
-
async (status, statusMessage) => {
|
|
82
|
-
if (client) {
|
|
83
|
-
await client.updateStatus(status, statusMessage);
|
|
84
|
-
setCurrentUser(
|
|
85
|
-
(prev) => prev ? { ...prev, status, statusMessage } : prev
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
[client]
|
|
90
|
-
);
|
|
91
74
|
const value = {
|
|
92
75
|
client,
|
|
93
76
|
isConnected,
|
|
94
|
-
currentUser,
|
|
95
77
|
conversations,
|
|
96
78
|
isLoadingConversations,
|
|
97
79
|
refreshConversations,
|
|
98
80
|
connect,
|
|
99
|
-
disconnect
|
|
100
|
-
updateStatus
|
|
81
|
+
disconnect
|
|
101
82
|
};
|
|
102
83
|
return /* @__PURE__ */ jsx(ChatContext.Provider, { value, children });
|
|
103
84
|
}
|
|
@@ -271,36 +252,7 @@ function useConversation(conversationId, options = {}) {
|
|
|
271
252
|
}
|
|
272
253
|
function usePresence() {
|
|
273
254
|
const { client } = useChat();
|
|
274
|
-
const [onlineUsers, setOnlineUsers] = useState([]);
|
|
275
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
276
|
-
const [error, setError] = useState(null);
|
|
277
255
|
const [presenceMap, setPresenceMap] = useState(/* @__PURE__ */ new Map());
|
|
278
|
-
const refresh = useCallback(async () => {
|
|
279
|
-
if (!client) return;
|
|
280
|
-
setIsLoading(true);
|
|
281
|
-
setError(null);
|
|
282
|
-
try {
|
|
283
|
-
const users = await client.getOnlineUsers();
|
|
284
|
-
setOnlineUsers(users);
|
|
285
|
-
const newMap = /* @__PURE__ */ new Map();
|
|
286
|
-
users.forEach((user) => {
|
|
287
|
-
if (user.status) {
|
|
288
|
-
newMap.set(user.id, user.status);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
setPresenceMap(newMap);
|
|
292
|
-
} catch (err) {
|
|
293
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
294
|
-
console.error("[usePresence] Failed to fetch online users:", err);
|
|
295
|
-
} finally {
|
|
296
|
-
setIsLoading(false);
|
|
297
|
-
}
|
|
298
|
-
}, [client]);
|
|
299
|
-
useEffect(() => {
|
|
300
|
-
if (client) {
|
|
301
|
-
refresh();
|
|
302
|
-
}
|
|
303
|
-
}, [client, refresh]);
|
|
304
256
|
useEffect(() => {
|
|
305
257
|
if (!client) return;
|
|
306
258
|
const handlePresenceUpdate = ({ userId, status }) => {
|
|
@@ -309,25 +261,12 @@ function usePresence() {
|
|
|
309
261
|
newMap.set(userId, status);
|
|
310
262
|
return newMap;
|
|
311
263
|
});
|
|
312
|
-
if (status === "offline") {
|
|
313
|
-
setOnlineUsers((prev) => prev.filter((u) => u.id !== userId));
|
|
314
|
-
} else {
|
|
315
|
-
setOnlineUsers((prev) => {
|
|
316
|
-
const exists = prev.some((u) => u.id === userId);
|
|
317
|
-
if (!exists) {
|
|
318
|
-
refresh();
|
|
319
|
-
}
|
|
320
|
-
return prev.map(
|
|
321
|
-
(u) => u.id === userId ? { ...u, status } : u
|
|
322
|
-
);
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
264
|
};
|
|
326
265
|
client.on("presence:updated", handlePresenceUpdate);
|
|
327
266
|
return () => {
|
|
328
267
|
client.off("presence:updated", handlePresenceUpdate);
|
|
329
268
|
};
|
|
330
|
-
}, [client
|
|
269
|
+
}, [client]);
|
|
331
270
|
const getUserStatus = useCallback(
|
|
332
271
|
(userId) => {
|
|
333
272
|
return presenceMap.get(userId) || "offline";
|
|
@@ -335,11 +274,8 @@ function usePresence() {
|
|
|
335
274
|
[presenceMap]
|
|
336
275
|
);
|
|
337
276
|
return {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
getUserStatus,
|
|
341
|
-
refresh,
|
|
342
|
-
error
|
|
277
|
+
presenceMap,
|
|
278
|
+
getUserStatus
|
|
343
279
|
};
|
|
344
280
|
}
|
|
345
281
|
function useUserPresence(userId) {
|
|
@@ -347,9 +283,6 @@ function useUserPresence(userId) {
|
|
|
347
283
|
const [status, setStatus] = useState("offline");
|
|
348
284
|
useEffect(() => {
|
|
349
285
|
if (!client || !userId) return;
|
|
350
|
-
client.getUser(userId).then((user) => {
|
|
351
|
-
setStatus(user.status || "offline");
|
|
352
|
-
}).catch(console.error);
|
|
353
286
|
const handlePresenceUpdate = ({ userId: eventUserId, status: newStatus }) => {
|
|
354
287
|
if (eventUserId === userId) {
|
|
355
288
|
setStatus(newStatus);
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/provider.tsx","../../src/react/hooks/useConversation.ts","../../src/react/hooks/usePresence.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * VeroAI Chat React Provider\n *\n * Provides ChatClient context to React components\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback, useRef } from 'react';\nimport { ChatClient } from '../client';\nimport type { ChatClientConfig, Conversation, Message, User, PresenceStatus } from '../types';\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface ChatContextValue {\n /** The ChatClient instance */\n client: ChatClient | null;\n /** Whether the WebSocket is connected */\n isConnected: boolean;\n /** Current user profile */\n currentUser: User | null;\n /** List of conversations */\n conversations: Conversation[];\n /** Loading state for conversations */\n isLoadingConversations: boolean;\n /** Refresh conversations from server */\n refreshConversations: () => Promise<void>;\n /** Connect to WebSocket */\n connect: () => Promise<void>;\n /** Disconnect from WebSocket */\n disconnect: () => void;\n /** Update current user's status */\n updateStatus: (status: PresenceStatus, statusMessage?: string) => Promise<void>;\n}\n\nconst ChatContext = createContext<ChatContextValue | null>(null);\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\nexport interface ChatProviderProps {\n children: React.ReactNode;\n /** ChatClient configuration */\n config: ChatClientConfig;\n /** Auto-fetch conversations on mount */\n autoFetchConversations?: boolean;\n /** Auto-fetch current user on mount */\n autoFetchCurrentUser?: boolean;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * ChatProvider - Provides chat functionality to React components\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <ChatProvider\n * config={{\n * apiUrl: 'https://api.veroai.dev',\n * wsUrl: 'wss://ws.veroai.dev',\n * token: authToken,\n * }}\n * >\n * <ChatApp />\n * </ChatProvider>\n * );\n * }\n * ```\n */\nexport function ChatProvider({\n children,\n config,\n autoFetchConversations = true,\n autoFetchCurrentUser = true,\n}: ChatProviderProps) {\n const [client, setClient] = useState<ChatClient | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [currentUser, setCurrentUser] = useState<User | null>(null);\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [isLoadingConversations, setIsLoadingConversations] = useState(false);\n const clientRef = useRef<ChatClient | null>(null);\n\n // Initialize client\n useEffect(() => {\n const chatClient = new ChatClient({\n ...config,\n autoConnect: false, // We'll connect manually to handle state\n });\n\n clientRef.current = chatClient;\n setClient(chatClient);\n\n // Set up event listeners\n chatClient.on('connected', () => setIsConnected(true));\n chatClient.on('disconnected', () => setIsConnected(false));\n\n // Handle real-time conversation updates\n chatClient.on('conversation:created', (conv) => {\n setConversations((prev) => [conv, ...prev]);\n });\n\n chatClient.on('conversation:updated', (conv) => {\n setConversations((prev) =>\n prev.map((c) => (c.id === conv.id ? conv : c))\n );\n });\n\n // Handle new messages - update conversation's lastMessageAt\n chatClient.on('message:new', ({ conversationId }) => {\n setConversations((prev) =>\n prev.map((c) =>\n c.id === conversationId\n ? { ...c, lastMessageAt: new Date().toISOString() }\n : c\n )\n );\n });\n\n // Connect if wsUrl provided\n if (config.wsUrl && config.autoConnect !== false) {\n chatClient.connect().catch(console.error);\n }\n\n return () => {\n chatClient.disconnect();\n chatClient.removeAllListeners();\n };\n }, [config.apiUrl, config.wsUrl, config.token]);\n\n // Fetch current user\n useEffect(() => {\n if (!client || !autoFetchCurrentUser) return;\n\n client.getCurrentUser()\n .then(setCurrentUser)\n .catch(console.error);\n }, [client, autoFetchCurrentUser]);\n\n // Fetch conversations\n const refreshConversations = useCallback(async () => {\n if (!client) return;\n\n setIsLoadingConversations(true);\n try {\n const convs = await client.listConversations();\n setConversations(convs);\n } catch (error) {\n console.error('[ChatProvider] Failed to fetch conversations:', error);\n } finally {\n setIsLoadingConversations(false);\n }\n }, [client]);\n\n useEffect(() => {\n if (autoFetchConversations && client) {\n refreshConversations();\n }\n }, [autoFetchConversations, client, refreshConversations]);\n\n // Connect function\n const connect = useCallback(async () => {\n if (client) {\n await client.connect();\n }\n }, [client]);\n\n // Disconnect function\n const disconnect = useCallback(() => {\n client?.disconnect();\n }, [client]);\n\n // Update status\n const updateStatus = useCallback(\n async (status: PresenceStatus, statusMessage?: string) => {\n if (client) {\n await client.updateStatus(status, statusMessage);\n setCurrentUser((prev) =>\n prev ? { ...prev, status, statusMessage } : prev\n );\n }\n },\n [client]\n );\n\n const value: ChatContextValue = {\n client,\n isConnected,\n currentUser,\n conversations,\n isLoadingConversations,\n refreshConversations,\n connect,\n disconnect,\n updateStatus,\n };\n\n return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * useChat - Access chat context\n *\n * @example\n * ```tsx\n * function ChatList() {\n * const { conversations, isConnected } = useChat();\n * return <div>{conversations.map(c => <div key={c.id}>{c.name}</div>)}</div>;\n * }\n * ```\n */\nexport function useChat(): ChatContextValue {\n const context = useContext(ChatContext);\n if (!context) {\n throw new Error('useChat must be used within a ChatProvider');\n }\n return context;\n}\n\n/**\n * useChatClient - Access the ChatClient instance directly\n */\nexport function useChatClient(): ChatClient | null {\n const { client } = useChat();\n return client;\n}\n","/**\n * useConversation Hook\n *\n * Manage a single conversation with real-time updates\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useChat } from '../provider';\nimport type { Conversation, Message, SendMessageParams, PaginatedMessages, TypingEvent } from '../../types';\n\nexport interface UseConversationOptions {\n /** Auto-fetch messages on mount */\n autoFetchMessages?: boolean;\n /** Number of messages to fetch initially */\n initialMessageLimit?: number;\n /** Auto-subscribe to real-time updates */\n autoSubscribe?: boolean;\n}\n\nexport interface UseConversationReturn {\n /** The conversation object */\n conversation: Conversation | null;\n /** Messages in the conversation */\n messages: Message[];\n /** Whether messages are loading */\n isLoading: boolean;\n /** Whether more messages are available */\n hasMore: boolean;\n /** Users currently typing */\n typingUsers: string[];\n /** Send a message */\n sendMessage: (params: SendMessageParams) => Promise<Message>;\n /** Send a text message (convenience) */\n send: (content: string) => Promise<Message>;\n /** Load more (older) messages */\n loadMore: () => Promise<void>;\n /** Refresh messages from server */\n refresh: () => Promise<void>;\n /** Mark conversation as read */\n markAsRead: () => Promise<void>;\n /** Start typing indicator */\n startTyping: () => void;\n /** Stop typing indicator */\n stopTyping: () => void;\n /** Error if any */\n error: Error | null;\n}\n\n/**\n * useConversation - Manage a single conversation\n *\n * @example\n * ```tsx\n * function ChatRoom({ conversationId }) {\n * const {\n * messages,\n * send,\n * isLoading,\n * typingUsers,\n * } = useConversation(conversationId);\n *\n * return (\n * <div>\n * {messages.map(m => <Message key={m.id} message={m} />)}\n * {typingUsers.length > 0 && <div>Someone is typing...</div>}\n * <input onKeyDown={(e) => e.key === 'Enter' && send(e.target.value)} />\n * </div>\n * );\n * }\n * ```\n */\nexport function useConversation(\n conversationId: string | undefined,\n options: UseConversationOptions = {}\n): UseConversationReturn {\n const {\n autoFetchMessages = true,\n initialMessageLimit = 50,\n autoSubscribe = true,\n } = options;\n\n const { client, conversations } = useChat();\n\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [typingUsers, setTypingUsers] = useState<string[]>([]);\n const [error, setError] = useState<Error | null>(null);\n\n // Get conversation from context or fetch\n useEffect(() => {\n if (!conversationId) {\n setConversation(null);\n setMessages([]);\n return;\n }\n\n // Try to find in existing conversations\n const existing = conversations.find((c) => c.id === conversationId);\n if (existing) {\n setConversation(existing);\n } else if (client) {\n // Fetch from server\n client.getConversation(conversationId)\n .then(setConversation)\n .catch((err) => {\n setError(err);\n console.error('[useConversation] Failed to fetch conversation:', err);\n });\n }\n }, [conversationId, conversations, client]);\n\n // Fetch messages\n const fetchMessages = useCallback(async (before?: string) => {\n if (!client || !conversationId) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await client.getMessages(conversationId, {\n limit: initialMessageLimit,\n before,\n });\n\n if (before) {\n // Append older messages\n setMessages((prev) => [...prev, ...result.messages]);\n } else {\n // Initial load\n setMessages(result.messages);\n }\n\n setHasMore(result.hasMore);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n console.error('[useConversation] Failed to fetch messages:', err);\n } finally {\n setIsLoading(false);\n }\n }, [client, conversationId, initialMessageLimit]);\n\n // Auto-fetch messages\n useEffect(() => {\n if (autoFetchMessages && conversationId && client) {\n fetchMessages();\n }\n }, [autoFetchMessages, conversationId, client, fetchMessages]);\n\n // Subscribe to real-time updates\n useEffect(() => {\n if (!client || !conversationId || !autoSubscribe) return;\n\n client.subscribeToConversation(conversationId);\n\n // Handle new messages\n const handleNewMessage = ({ message, conversationId: convId }: { message: Message; conversationId: string }) => {\n if (convId === conversationId) {\n setMessages((prev) => [message, ...prev]);\n }\n };\n\n // Handle message updates\n const handleMessageUpdated = (message: Message) => {\n if (message.conversationId === conversationId) {\n setMessages((prev) =>\n prev.map((m) => (m.id === message.id ? message : m))\n );\n }\n };\n\n // Handle message deletion\n const handleMessageDeleted = (messageId: string, convId: string) => {\n if (convId === conversationId) {\n setMessages((prev) => prev.filter((m) => m.id !== messageId));\n }\n };\n\n // Handle typing indicators\n const handleTypingStart = ({ conversationId: convId, userId }: TypingEvent) => {\n if (convId === conversationId) {\n setTypingUsers((prev) =>\n prev.includes(userId) ? prev : [...prev, userId]\n );\n }\n };\n\n const handleTypingStop = ({ conversationId: convId, userId }: TypingEvent) => {\n if (convId === conversationId) {\n setTypingUsers((prev) => prev.filter((id) => id !== userId));\n }\n };\n\n client.on('message:new', handleNewMessage);\n client.on('message:updated', handleMessageUpdated);\n client.on('message:deleted', handleMessageDeleted);\n client.on('typing:start', handleTypingStart);\n client.on('typing:stop', handleTypingStop);\n\n return () => {\n client.unsubscribeFromConversation(conversationId);\n client.off('message:new', handleNewMessage);\n client.off('message:updated', handleMessageUpdated);\n client.off('message:deleted', handleMessageDeleted);\n client.off('typing:start', handleTypingStart);\n client.off('typing:stop', handleTypingStop);\n };\n }, [client, conversationId, autoSubscribe]);\n\n // Send message\n const sendMessage = useCallback(\n async (params: SendMessageParams): Promise<Message> => {\n if (!client || !conversationId) {\n throw new Error('No conversation selected');\n }\n return client.sendMessage(conversationId, params);\n },\n [client, conversationId]\n );\n\n // Send text message\n const send = useCallback(\n async (content: string): Promise<Message> => {\n return sendMessage({ content });\n },\n [sendMessage]\n );\n\n // Load more messages\n const loadMore = useCallback(async () => {\n if (!hasMore || isLoading || messages.length === 0) return;\n\n const oldestMessage = messages[messages.length - 1];\n await fetchMessages(oldestMessage.createdAt);\n }, [hasMore, isLoading, messages, fetchMessages]);\n\n // Refresh messages\n const refresh = useCallback(async () => {\n setMessages([]);\n setHasMore(true);\n await fetchMessages();\n }, [fetchMessages]);\n\n // Mark as read\n const markAsRead = useCallback(async () => {\n if (!client || !conversationId) return;\n await client.markConversationRead(conversationId);\n }, [client, conversationId]);\n\n // Typing indicators\n const startTyping = useCallback(() => {\n if (conversationId) {\n client?.sendTypingStart(conversationId);\n }\n }, [client, conversationId]);\n\n const stopTyping = useCallback(() => {\n if (conversationId) {\n client?.sendTypingStop(conversationId);\n }\n }, [client, conversationId]);\n\n return {\n conversation,\n messages,\n isLoading,\n hasMore,\n typingUsers,\n sendMessage,\n send,\n loadMore,\n refresh,\n markAsRead,\n startTyping,\n stopTyping,\n error,\n };\n}\n","/**\n * usePresence Hook\n *\n * Track and manage user presence/online status\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useChat } from '../provider';\nimport type { User, PresenceStatus, PresenceEvent } from '../../types';\n\nexport interface UsePresenceReturn {\n /** Online users */\n onlineUsers: User[];\n /** Whether loading online users */\n isLoading: boolean;\n /** Get presence status for a specific user */\n getUserStatus: (userId: string) => PresenceStatus;\n /** Refresh online users list */\n refresh: () => Promise<void>;\n /** Error if any */\n error: Error | null;\n}\n\n/**\n * usePresence - Track online users and presence\n *\n * @example\n * ```tsx\n * function OnlineUsers() {\n * const { onlineUsers, getUserStatus } = usePresence();\n *\n * return (\n * <div>\n * {onlineUsers.map(user => (\n * <div key={user.id}>\n * {user.firstName} - {getUserStatus(user.id)}\n * </div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function usePresence(): UsePresenceReturn {\n const { client } = useChat();\n\n const [onlineUsers, setOnlineUsers] = useState<User[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [presenceMap, setPresenceMap] = useState<Map<string, PresenceStatus>>(new Map());\n\n // Fetch online users\n const refresh = useCallback(async () => {\n if (!client) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const users = await client.getOnlineUsers();\n setOnlineUsers(users);\n\n // Update presence map\n const newMap = new Map<string, PresenceStatus>();\n users.forEach((user) => {\n if (user.status) {\n newMap.set(user.id, user.status);\n }\n });\n setPresenceMap(newMap);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n console.error('[usePresence] Failed to fetch online users:', err);\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n // Initial fetch\n useEffect(() => {\n if (client) {\n refresh();\n }\n }, [client, refresh]);\n\n // Listen for presence updates\n useEffect(() => {\n if (!client) return;\n\n const handlePresenceUpdate = ({ userId, status }: PresenceEvent) => {\n setPresenceMap((prev) => {\n const newMap = new Map(prev);\n newMap.set(userId, status);\n return newMap;\n });\n\n // Update online users list\n if (status === 'offline') {\n setOnlineUsers((prev) => prev.filter((u) => u.id !== userId));\n } else {\n // If user came online, refresh to get their info\n setOnlineUsers((prev) => {\n const exists = prev.some((u) => u.id === userId);\n if (!exists) {\n // Trigger a refresh to get the new online user\n refresh();\n }\n return prev.map((u) =>\n u.id === userId ? { ...u, status } : u\n );\n });\n }\n };\n\n client.on('presence:updated', handlePresenceUpdate);\n\n return () => {\n client.off('presence:updated', handlePresenceUpdate);\n };\n }, [client, refresh]);\n\n // Get status for a specific user\n const getUserStatus = useCallback(\n (userId: string): PresenceStatus => {\n return presenceMap.get(userId) || 'offline';\n },\n [presenceMap]\n );\n\n return {\n onlineUsers,\n isLoading,\n getUserStatus,\n refresh,\n error,\n };\n}\n\n/**\n * useUserPresence - Track presence for a specific user\n */\nexport function useUserPresence(userId: string | undefined): {\n status: PresenceStatus;\n isOnline: boolean;\n} {\n const { client } = useChat();\n const [status, setStatus] = useState<PresenceStatus>('offline');\n\n useEffect(() => {\n if (!client || !userId) return;\n\n // Fetch initial status\n client.getUser(userId)\n .then((user) => {\n setStatus(user.status || 'offline');\n })\n .catch(console.error);\n\n // Listen for updates\n const handlePresenceUpdate = ({ userId: eventUserId, status: newStatus }: PresenceEvent) => {\n if (eventUserId === userId) {\n setStatus(newStatus);\n }\n };\n\n client.on('presence:updated', handlePresenceUpdate);\n\n return () => {\n client.off('presence:updated', handlePresenceUpdate);\n };\n }, [client, userId]);\n\n return {\n status,\n isOnline: status !== 'offline',\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/provider.tsx","../../src/react/hooks/useConversation.ts","../../src/react/hooks/usePresence.ts"],"names":["useState","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * VeroAI Chat React Provider\n *\n * Provides ChatClient context to React components\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback, useRef } from 'react';\nimport { ChatClient } from '../client';\nimport type { ChatClientConfig, Conversation } from '../types';\n\n// ============================================================================\n// Context Types\n// ============================================================================\n\nexport interface ChatContextValue {\n /** The ChatClient instance */\n client: ChatClient | null;\n /** Whether the WebSocket is connected */\n isConnected: boolean;\n /** List of conversations */\n conversations: Conversation[];\n /** Loading state for conversations */\n isLoadingConversations: boolean;\n /** Refresh conversations from server */\n refreshConversations: () => Promise<void>;\n /** Connect to WebSocket */\n connect: () => Promise<void>;\n /** Disconnect from WebSocket */\n disconnect: () => void;\n}\n\nconst ChatContext = createContext<ChatContextValue | null>(null);\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\nexport interface ChatProviderProps {\n children: React.ReactNode;\n /** ChatClient configuration */\n config: ChatClientConfig;\n /** Auto-fetch conversations on mount */\n autoFetchConversations?: boolean;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * ChatProvider - Provides chat functionality to React components\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <ChatProvider\n * config={{\n * apiUrl: 'https://api.veroai.dev',\n * wsUrl: 'wss://ws.veroai.dev',\n * getToken: () => myAuthToken,\n * }}\n * >\n * <ChatApp />\n * </ChatProvider>\n * );\n * }\n * ```\n */\nexport function ChatProvider({\n children,\n config,\n autoFetchConversations = true,\n}: ChatProviderProps) {\n const [client, setClient] = useState<ChatClient | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [isLoadingConversations, setIsLoadingConversations] = useState(false);\n const clientRef = useRef<ChatClient | null>(null);\n\n // Initialize client\n useEffect(() => {\n const chatClient = new ChatClient({\n ...config,\n autoConnect: false, // We'll connect manually to handle state\n });\n\n clientRef.current = chatClient;\n setClient(chatClient);\n\n // Set up event listeners\n chatClient.on('connected', () => setIsConnected(true));\n chatClient.on('disconnected', () => setIsConnected(false));\n\n // Handle real-time conversation updates\n chatClient.on('conversation:created', (conv) => {\n setConversations((prev) => [conv, ...prev]);\n });\n\n chatClient.on('conversation:updated', (conv) => {\n setConversations((prev) =>\n prev.map((c) => (c.id === conv.id ? conv : c))\n );\n });\n\n // Handle new messages - update conversation's lastMessageAt\n chatClient.on('message:new', ({ conversationId }) => {\n setConversations((prev) =>\n prev.map((c) =>\n c.id === conversationId\n ? { ...c, lastMessageAt: new Date().toISOString() }\n : c\n )\n );\n });\n\n // Connect if wsUrl provided\n if (config.wsUrl && config.autoConnect !== false) {\n chatClient.connect().catch(console.error);\n }\n\n return () => {\n chatClient.disconnect();\n chatClient.removeAllListeners();\n };\n }, [config.apiUrl, config.wsUrl, config.token]);\n\n // Fetch conversations\n const refreshConversations = useCallback(async () => {\n if (!client) return;\n\n setIsLoadingConversations(true);\n try {\n const convs = await client.listConversations();\n setConversations(convs);\n } catch (error) {\n console.error('[ChatProvider] Failed to fetch conversations:', error);\n } finally {\n setIsLoadingConversations(false);\n }\n }, [client]);\n\n useEffect(() => {\n if (autoFetchConversations && client) {\n refreshConversations();\n }\n }, [autoFetchConversations, client, refreshConversations]);\n\n // Connect function\n const connect = useCallback(async () => {\n if (client) {\n await client.connect();\n }\n }, [client]);\n\n // Disconnect function\n const disconnect = useCallback(() => {\n client?.disconnect();\n }, [client]);\n\n const value: ChatContextValue = {\n client,\n isConnected,\n conversations,\n isLoadingConversations,\n refreshConversations,\n connect,\n disconnect,\n };\n\n return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * useChat - Access chat context\n *\n * @example\n * ```tsx\n * function ChatList() {\n * const { conversations, isConnected } = useChat();\n * return <div>{conversations.map(c => <div key={c.id}>{c.name}</div>)}</div>;\n * }\n * ```\n */\nexport function useChat(): ChatContextValue {\n const context = useContext(ChatContext);\n if (!context) {\n throw new Error('useChat must be used within a ChatProvider');\n }\n return context;\n}\n\n/**\n * useChatClient - Access the ChatClient instance directly\n */\nexport function useChatClient(): ChatClient | null {\n const { client } = useChat();\n return client;\n}\n","/**\n * useConversation Hook\n *\n * Manage a single conversation with real-time updates\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useChat } from '../provider';\nimport type { Conversation, Message, SendMessageParams, PaginatedMessages, TypingEvent } from '../../types';\n\nexport interface UseConversationOptions {\n /** Auto-fetch messages on mount */\n autoFetchMessages?: boolean;\n /** Number of messages to fetch initially */\n initialMessageLimit?: number;\n /** Auto-subscribe to real-time updates */\n autoSubscribe?: boolean;\n}\n\nexport interface UseConversationReturn {\n /** The conversation object */\n conversation: Conversation | null;\n /** Messages in the conversation */\n messages: Message[];\n /** Whether messages are loading */\n isLoading: boolean;\n /** Whether more messages are available */\n hasMore: boolean;\n /** Users currently typing */\n typingUsers: string[];\n /** Send a message */\n sendMessage: (params: SendMessageParams) => Promise<Message>;\n /** Send a text message (convenience) */\n send: (content: string) => Promise<Message>;\n /** Load more (older) messages */\n loadMore: () => Promise<void>;\n /** Refresh messages from server */\n refresh: () => Promise<void>;\n /** Mark conversation as read */\n markAsRead: () => Promise<void>;\n /** Start typing indicator */\n startTyping: () => void;\n /** Stop typing indicator */\n stopTyping: () => void;\n /** Error if any */\n error: Error | null;\n}\n\n/**\n * useConversation - Manage a single conversation\n *\n * @example\n * ```tsx\n * function ChatRoom({ conversationId }) {\n * const {\n * messages,\n * send,\n * isLoading,\n * typingUsers,\n * } = useConversation(conversationId);\n *\n * return (\n * <div>\n * {messages.map(m => <Message key={m.id} message={m} />)}\n * {typingUsers.length > 0 && <div>Someone is typing...</div>}\n * <input onKeyDown={(e) => e.key === 'Enter' && send(e.target.value)} />\n * </div>\n * );\n * }\n * ```\n */\nexport function useConversation(\n conversationId: string | undefined,\n options: UseConversationOptions = {}\n): UseConversationReturn {\n const {\n autoFetchMessages = true,\n initialMessageLimit = 50,\n autoSubscribe = true,\n } = options;\n\n const { client, conversations } = useChat();\n\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [typingUsers, setTypingUsers] = useState<string[]>([]);\n const [error, setError] = useState<Error | null>(null);\n\n // Get conversation from context or fetch\n useEffect(() => {\n if (!conversationId) {\n setConversation(null);\n setMessages([]);\n return;\n }\n\n // Try to find in existing conversations\n const existing = conversations.find((c) => c.id === conversationId);\n if (existing) {\n setConversation(existing);\n } else if (client) {\n // Fetch from server\n client.getConversation(conversationId)\n .then(setConversation)\n .catch((err) => {\n setError(err);\n console.error('[useConversation] Failed to fetch conversation:', err);\n });\n }\n }, [conversationId, conversations, client]);\n\n // Fetch messages\n const fetchMessages = useCallback(async (before?: string) => {\n if (!client || !conversationId) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await client.getMessages(conversationId, {\n limit: initialMessageLimit,\n before,\n });\n\n if (before) {\n // Append older messages\n setMessages((prev) => [...prev, ...result.messages]);\n } else {\n // Initial load\n setMessages(result.messages);\n }\n\n setHasMore(result.hasMore);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n console.error('[useConversation] Failed to fetch messages:', err);\n } finally {\n setIsLoading(false);\n }\n }, [client, conversationId, initialMessageLimit]);\n\n // Auto-fetch messages\n useEffect(() => {\n if (autoFetchMessages && conversationId && client) {\n fetchMessages();\n }\n }, [autoFetchMessages, conversationId, client, fetchMessages]);\n\n // Subscribe to real-time updates\n useEffect(() => {\n if (!client || !conversationId || !autoSubscribe) return;\n\n client.subscribeToConversation(conversationId);\n\n // Handle new messages\n const handleNewMessage = ({ message, conversationId: convId }: { message: Message; conversationId: string }) => {\n if (convId === conversationId) {\n setMessages((prev) => [message, ...prev]);\n }\n };\n\n // Handle message updates\n const handleMessageUpdated = (message: Message) => {\n if (message.conversationId === conversationId) {\n setMessages((prev) =>\n prev.map((m) => (m.id === message.id ? message : m))\n );\n }\n };\n\n // Handle message deletion\n const handleMessageDeleted = (messageId: string, convId: string) => {\n if (convId === conversationId) {\n setMessages((prev) => prev.filter((m) => m.id !== messageId));\n }\n };\n\n // Handle typing indicators\n const handleTypingStart = ({ conversationId: convId, userId }: TypingEvent) => {\n if (convId === conversationId) {\n setTypingUsers((prev) =>\n prev.includes(userId) ? prev : [...prev, userId]\n );\n }\n };\n\n const handleTypingStop = ({ conversationId: convId, userId }: TypingEvent) => {\n if (convId === conversationId) {\n setTypingUsers((prev) => prev.filter((id) => id !== userId));\n }\n };\n\n client.on('message:new', handleNewMessage);\n client.on('message:updated', handleMessageUpdated);\n client.on('message:deleted', handleMessageDeleted);\n client.on('typing:start', handleTypingStart);\n client.on('typing:stop', handleTypingStop);\n\n return () => {\n client.unsubscribeFromConversation(conversationId);\n client.off('message:new', handleNewMessage);\n client.off('message:updated', handleMessageUpdated);\n client.off('message:deleted', handleMessageDeleted);\n client.off('typing:start', handleTypingStart);\n client.off('typing:stop', handleTypingStop);\n };\n }, [client, conversationId, autoSubscribe]);\n\n // Send message\n const sendMessage = useCallback(\n async (params: SendMessageParams): Promise<Message> => {\n if (!client || !conversationId) {\n throw new Error('No conversation selected');\n }\n return client.sendMessage(conversationId, params);\n },\n [client, conversationId]\n );\n\n // Send text message\n const send = useCallback(\n async (content: string): Promise<Message> => {\n return sendMessage({ content });\n },\n [sendMessage]\n );\n\n // Load more messages\n const loadMore = useCallback(async () => {\n if (!hasMore || isLoading || messages.length === 0) return;\n\n const oldestMessage = messages[messages.length - 1];\n await fetchMessages(oldestMessage.createdAt);\n }, [hasMore, isLoading, messages, fetchMessages]);\n\n // Refresh messages\n const refresh = useCallback(async () => {\n setMessages([]);\n setHasMore(true);\n await fetchMessages();\n }, [fetchMessages]);\n\n // Mark as read\n const markAsRead = useCallback(async () => {\n if (!client || !conversationId) return;\n await client.markConversationRead(conversationId);\n }, [client, conversationId]);\n\n // Typing indicators\n const startTyping = useCallback(() => {\n if (conversationId) {\n client?.sendTypingStart(conversationId);\n }\n }, [client, conversationId]);\n\n const stopTyping = useCallback(() => {\n if (conversationId) {\n client?.sendTypingStop(conversationId);\n }\n }, [client, conversationId]);\n\n return {\n conversation,\n messages,\n isLoading,\n hasMore,\n typingUsers,\n sendMessage,\n send,\n loadMore,\n refresh,\n markAsRead,\n startTyping,\n stopTyping,\n error,\n };\n}\n","/**\n * usePresence Hook\n *\n * Track user presence/online status via WebSocket events.\n * The chat backend is user-agnostic - presence is tracked via real-time events only.\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useChat } from '../provider';\nimport type { PresenceStatus, PresenceEvent } from '../../types';\n\nexport interface UsePresenceReturn {\n /** Map of userId to their presence status */\n presenceMap: Map<string, PresenceStatus>;\n /** Get presence status for a specific user */\n getUserStatus: (userId: string) => PresenceStatus;\n}\n\n/**\n * usePresence - Track user presence via WebSocket events\n *\n * Note: The chat backend is user-agnostic. This hook only tracks presence\n * updates received via WebSocket. To know who is online, you need to\n * implement presence tracking in your own system.\n *\n * @example\n * ```tsx\n * function UserStatus({ userId }: { userId: string }) {\n * const { getUserStatus } = usePresence();\n * const status = getUserStatus(userId);\n *\n * return <span className={`status-${status}`}>{status}</span>;\n * }\n * ```\n */\nexport function usePresence(): UsePresenceReturn {\n const { client } = useChat();\n\n const [presenceMap, setPresenceMap] = useState<Map<string, PresenceStatus>>(new Map());\n\n // Listen for presence updates via WebSocket\n useEffect(() => {\n if (!client) return;\n\n const handlePresenceUpdate = ({ userId, status }: PresenceEvent) => {\n setPresenceMap((prev) => {\n const newMap = new Map(prev);\n newMap.set(userId, status);\n return newMap;\n });\n };\n\n client.on('presence:updated', handlePresenceUpdate);\n\n return () => {\n client.off('presence:updated', handlePresenceUpdate);\n };\n }, [client]);\n\n // Get status for a specific user\n const getUserStatus = useCallback(\n (userId: string): PresenceStatus => {\n return presenceMap.get(userId) || 'offline';\n },\n [presenceMap]\n );\n\n return {\n presenceMap,\n getUserStatus,\n };\n}\n\n/**\n * useUserPresence - Track presence for a specific user via WebSocket events\n */\nexport function useUserPresence(userId: string | undefined): {\n status: PresenceStatus;\n isOnline: boolean;\n} {\n const { client } = useChat();\n const [status, setStatus] = useState<PresenceStatus>('offline');\n\n useEffect(() => {\n if (!client || !userId) return;\n\n // Listen for updates via WebSocket\n const handlePresenceUpdate = ({ userId: eventUserId, status: newStatus }: PresenceEvent) => {\n if (eventUserId === userId) {\n setStatus(newStatus);\n }\n };\n\n client.on('presence:updated', handlePresenceUpdate);\n\n return () => {\n client.off('presence:updated', handlePresenceUpdate);\n };\n }, [client, userId]);\n\n return {\n status,\n isOnline: status !== 'offline',\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/index.ts","../src/websocket.ts","../src/client.ts"],"names":["EventEmitter"],"mappings":"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","file":"chunk-KYGXVRDI.js","sourcesContent":["/**\n * VeroAI Chat API Client\n *\n * HTTP client for the VeroAI Chat API\n */\n\nimport type {\n Conversation,\n CreateConversationParams,\n Message,\n SendMessageParams,\n GetMessagesParams,\n PaginatedMessages,\n User,\n UserPresence,\n PresenceStatus,\n AgentConfig,\n} from '../types';\n\nexport interface ApiClientConfig {\n apiUrl: string;\n getToken: () => string | null | Promise<string | null>;\n}\n\n/**\n * Chat API Client for HTTP requests\n */\nexport class ChatApi {\n private apiUrl: string;\n private getToken: () => string | null | Promise<string | null>;\n\n constructor(config: ApiClientConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '');\n this.getToken = config.getToken;\n }\n\n private async getHeaders(): Promise<HeadersInit> {\n const token = await this.getToken();\n return {\n 'Content-Type': 'application/json',\n ...(token && { Authorization: `Bearer ${token}` }),\n };\n }\n\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.error?.message || errorJson.message || errorText;\n } catch {\n errorMessage = errorText;\n }\n throw new Error(errorMessage);\n }\n return response.json();\n }\n\n // ============================================================================\n // Conversations\n // ============================================================================\n\n /**\n * List all conversations for the current user\n */\n async listConversations(): Promise<Conversation[]> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ conversations: RawConversation[] }>(response);\n return data.conversations.map(transformConversation);\n }\n\n /**\n * Get a specific conversation\n */\n async getConversation(conversationId: string): Promise<Conversation> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ conversation: RawConversation }>(response);\n return transformConversation(data.conversation);\n }\n\n /**\n * Create a new conversation\n */\n async createConversation(params: CreateConversationParams): Promise<Conversation> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n type: params.type || 'direct',\n name: params.name,\n participant_ids: params.participantIds,\n agent_config_id: params.agentConfigId,\n metadata: params.metadata,\n }),\n });\n const data = await this.handleResponse<{ conversation: RawConversation }>(response);\n return transformConversation(data.conversation);\n }\n\n /**\n * Mark conversation as read\n */\n async markConversationRead(conversationId: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/read`, {\n method: 'POST',\n headers: await this.getHeaders(),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Leave a conversation\n */\n async leaveConversation(conversationId: string): Promise<void> {\n const response = await fetch(\n `${this.apiUrl}/v1/chat/conversations/${conversationId}/participants/me`,\n {\n method: 'DELETE',\n headers: await this.getHeaders(),\n }\n );\n await this.handleResponse<void>(response);\n }\n\n // ============================================================================\n // Messages\n // ============================================================================\n\n /**\n * Get messages for a conversation\n */\n async getMessages(conversationId: string, params?: GetMessagesParams): Promise<PaginatedMessages> {\n const searchParams = new URLSearchParams();\n if (params?.limit) searchParams.set('limit', String(params.limit));\n if (params?.offset) searchParams.set('offset', String(params.offset));\n if (params?.before) searchParams.set('before', params.before);\n\n const url = `${this.apiUrl}/v1/chat/conversations/${conversationId}/messages?${searchParams}`;\n const response = await fetch(url, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<RawPaginatedMessages>(response);\n return {\n messages: data.messages.map(transformMessage),\n total: data.total,\n hasMore: data.has_more,\n limit: data.limit,\n offset: data.offset,\n };\n }\n\n /**\n * Send a message to a conversation\n */\n async sendMessage(conversationId: string, params: SendMessageParams): Promise<Message> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/messages`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n content: params.content,\n message_type: params.messageType || 'text',\n metadata: params.metadata,\n }),\n });\n const data = await this.handleResponse<{ message: RawMessage }>(response);\n return transformMessage(data.message);\n }\n\n // ============================================================================\n // Users\n // ============================================================================\n\n /**\n * List all users (contacts)\n */\n async listUsers(options?: { includeVirtual?: boolean }): Promise<User[]> {\n const searchParams = new URLSearchParams();\n if (options?.includeVirtual) searchParams.set('include_virtual', 'true');\n\n const url = `${this.apiUrl}/v1/chat/users?${searchParams}`;\n const response = await fetch(url, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ users: RawUser[] }>(response);\n return data.users.map(transformUser);\n }\n\n /**\n * Get online users\n */\n async getOnlineUsers(): Promise<User[]> {\n const response = await fetch(`${this.apiUrl}/v1/chat/users/online`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ users: RawUser[] }>(response);\n return data.users.map(transformUser);\n }\n\n /**\n * Get current user profile\n */\n async getCurrentUser(): Promise<User> {\n const response = await fetch(`${this.apiUrl}/v1/chat/users/me`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ user: RawUser }>(response);\n return transformUser(data.user);\n }\n\n /**\n * Get a specific user\n */\n async getUser(userId: string): Promise<User> {\n const response = await fetch(`${this.apiUrl}/v1/chat/users/${userId}`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<{ user: RawUser }>(response);\n return transformUser(data.user);\n }\n\n /**\n * Update current user's presence status\n */\n async updateStatus(status: PresenceStatus, statusMessage?: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/users/me/status`, {\n method: 'PUT',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n status,\n status_message: statusMessage,\n }),\n });\n await this.handleResponse<void>(response);\n }\n\n // ============================================================================\n // Agents\n // ============================================================================\n\n /**\n * Add agent to conversation\n */\n async addAgentToConversation(\n conversationId: string,\n agentConfigId: string,\n addAsParticipant = true\n ): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n agent_config_id: agentConfigId,\n add_as_participant: addAsParticipant,\n }),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Remove agent from conversation\n */\n async removeAgentFromConversation(conversationId: string): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'DELETE',\n headers: await this.getHeaders(),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * Toggle agent enabled/disabled\n */\n async toggleAgent(conversationId: string, enabled: boolean): Promise<void> {\n const response = await fetch(`${this.apiUrl}/v1/chat/conversations/${conversationId}/agent`, {\n method: 'PATCH',\n headers: await this.getHeaders(),\n body: JSON.stringify({ enabled }),\n });\n await this.handleResponse<void>(response);\n }\n\n /**\n * List available agents\n */\n async listAgents(): Promise<AgentConfig[]> {\n const response = await fetch(`${this.apiUrl}/v1/agent-configurations`, {\n headers: await this.getHeaders(),\n });\n const data = await this.handleResponse<AgentConfig[]>(response);\n return data;\n }\n\n // ============================================================================\n // Voice Rooms\n // ============================================================================\n\n /**\n * Create a new voice/video room\n */\n async createRoom(params: {\n name: string;\n emptyTimeout?: number;\n maxParticipants?: number;\n }): Promise<RoomInfo> {\n const response = await fetch(`${this.apiUrl}/v1/voice/rooms`, {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n name: params.name,\n empty_timeout: params.emptyTimeout,\n max_participants: params.maxParticipants,\n }),\n });\n const data = await this.handleResponse<{ room: RawRoomInfo }>(response);\n return transformRoomInfo(data.room);\n }\n\n /**\n * Join an existing room and get access token\n */\n async joinRoom(params: {\n roomName: string;\n participantName: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n }): Promise<RoomInfo> {\n const response = await fetch(\n `${this.apiUrl}/v1/voice/rooms/${encodeURIComponent(params.roomName)}/join`,\n {\n method: 'POST',\n headers: await this.getHeaders(),\n body: JSON.stringify({\n participant_name: params.participantName,\n can_publish: params.canPublish ?? true,\n can_subscribe: params.canSubscribe ?? true,\n }),\n }\n );\n const data = await this.handleResponse<RawJoinRoomResponse>(response);\n return {\n name: data.room_name,\n wsUrl: data.ws_url,\n token: data.token,\n };\n }\n\n /**\n * Get room token for an existing room\n * Convenience method for getting a token without creating\n */\n async getRoomToken(roomName: string, participantName: string): Promise<RoomInfo> {\n return this.joinRoom({ roomName, participantName });\n }\n}\n\n// ============================================================================\n// Raw API Types (snake_case from server)\n// ============================================================================\n\ninterface RawUser {\n id: string;\n email?: string;\n first_name?: string;\n last_name?: string;\n is_virtual?: boolean;\n agent_config_id?: string;\n status?: PresenceStatus;\n status_message?: string;\n last_seen?: string;\n created_at?: string;\n}\n\ninterface RawParticipant {\n user_id: string;\n role: 'admin' | 'member';\n is_active: boolean;\n joined_at?: string;\n last_seen?: string;\n user?: RawUser;\n}\n\ninterface RawConversation {\n id: string;\n name?: string;\n type: string;\n is_active: boolean;\n last_message_at?: string;\n agent_enabled?: boolean;\n agent_config_id?: string;\n participants?: RawParticipant[];\n unread_count?: number;\n metadata?: Record<string, unknown>;\n created_at?: string;\n updated_at?: string;\n}\n\ninterface RawReadReceipt {\n user_id: string;\n read_at?: string;\n}\n\ninterface RawMessage {\n id: string;\n conversation_id: string;\n content: string;\n message_type: string;\n sender_id?: string;\n sender?: RawUser;\n read_by?: RawReadReceipt[];\n metadata?: Record<string, unknown>;\n created_at?: string;\n edited_at?: string;\n}\n\ninterface RawPaginatedMessages {\n messages: RawMessage[];\n total: number;\n has_more: boolean;\n limit: number;\n offset: number;\n}\n\ninterface RawRoomInfo {\n id?: string;\n name: string;\n ws_url: string;\n token: string;\n}\n\ninterface RawJoinRoomResponse {\n room_name: string;\n ws_url: string;\n token: string;\n}\n\n// Exported room types\nexport interface RoomInfo {\n name: string;\n wsUrl: string;\n token: string;\n}\n\n// ============================================================================\n// Transform Functions (snake_case to camelCase)\n// ============================================================================\n\nfunction transformUser(raw: RawUser): User {\n return {\n id: raw.id,\n email: raw.email,\n firstName: raw.first_name,\n lastName: raw.last_name,\n isVirtual: raw.is_virtual,\n agentConfigId: raw.agent_config_id,\n status: raw.status,\n statusMessage: raw.status_message,\n lastSeen: raw.last_seen,\n createdAt: raw.created_at,\n };\n}\n\nfunction transformParticipant(raw: RawParticipant) {\n return {\n userId: raw.user_id,\n role: raw.role,\n isActive: raw.is_active,\n joinedAt: raw.joined_at,\n lastSeen: raw.last_seen,\n user: raw.user ? transformUser(raw.user) : undefined,\n };\n}\n\nfunction transformConversation(raw: RawConversation): Conversation {\n return {\n id: raw.id,\n name: raw.name,\n type: raw.type as Conversation['type'],\n isActive: raw.is_active,\n lastMessageAt: raw.last_message_at,\n agentEnabled: raw.agent_enabled,\n agentConfigId: raw.agent_config_id,\n participants: raw.participants?.map(transformParticipant),\n unreadCount: raw.unread_count,\n metadata: raw.metadata,\n createdAt: raw.created_at,\n updatedAt: raw.updated_at,\n };\n}\n\nfunction transformMessage(raw: RawMessage): Message {\n return {\n id: raw.id,\n conversationId: raw.conversation_id,\n content: raw.content,\n messageType: raw.message_type as Message['messageType'],\n senderId: raw.sender_id,\n sender: raw.sender ? transformUser(raw.sender) : undefined,\n readBy: raw.read_by?.map((r) => ({\n userId: r.user_id,\n readAt: r.read_at,\n })),\n metadata: raw.metadata,\n createdAt: raw.created_at,\n editedAt: raw.edited_at,\n };\n}\n\nfunction transformRoomInfo(raw: RawRoomInfo): RoomInfo {\n return {\n name: raw.name,\n wsUrl: raw.ws_url,\n token: raw.token,\n };\n}\n","/**\n * VeroAI Chat WebSocket Manager\n *\n * Handles WebSocket connection, reconnection, and message handling\n */\n\nimport EventEmitter from 'eventemitter3';\nimport type {\n ChatEvents,\n WebSocketMessage,\n NewMessageEvent,\n TypingEvent,\n PresenceEvent,\n ReadReceiptEvent,\n CallEvent,\n CallAction,\n CallType,\n Message,\n Conversation,\n Participant,\n} from './types';\n\nexport interface WebSocketConfig {\n url: string;\n getToken: () => string | null | Promise<string | null>;\n autoReconnect?: boolean;\n reconnectInterval?: number;\n maxReconnectAttempts?: number;\n heartbeatInterval?: number;\n}\n\ntype ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\n/**\n * WebSocket connection manager with auto-reconnect\n */\nexport class WebSocketManager extends EventEmitter<ChatEvents> {\n private config: Required<WebSocketConfig>;\n private ws: WebSocket | null = null;\n private state: ConnectionState = 'disconnected';\n private reconnectAttempts = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private pendingMessages: string[] = [];\n\n constructor(config: WebSocketConfig) {\n super();\n this.config = {\n url: config.url,\n getToken: config.getToken,\n autoReconnect: config.autoReconnect ?? true,\n reconnectInterval: config.reconnectInterval ?? 3000,\n maxReconnectAttempts: config.maxReconnectAttempts ?? 10,\n heartbeatInterval: config.heartbeatInterval ?? 30000,\n };\n }\n\n /**\n * Get current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.state === 'connected' && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n if (this.state === 'connecting' || this.state === 'connected') {\n return;\n }\n\n this.state = 'connecting';\n const token = await this.config.getToken();\n\n if (!token) {\n this.state = 'disconnected';\n throw new Error('No authentication token available');\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Build WebSocket URL with token\n const url = new URL(this.config.url);\n url.searchParams.set('token', token);\n\n this.ws = new WebSocket(url.toString());\n\n this.ws.onopen = () => {\n this.state = 'connected';\n this.reconnectAttempts = 0;\n this.startHeartbeat();\n this.flushPendingMessages();\n this.emit('connected');\n resolve();\n };\n\n this.ws.onclose = (event) => {\n this.handleClose(event.reason);\n };\n\n this.ws.onerror = (event) => {\n const error = new Error('WebSocket error');\n this.emit('error', error);\n if (this.state === 'connecting') {\n reject(error);\n }\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data);\n };\n } catch (error) {\n this.state = 'disconnected';\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the WebSocket server\n */\n disconnect(): void {\n this.config.autoReconnect = false;\n this.clearTimers();\n\n if (this.ws) {\n this.ws.close(1000, 'Client disconnect');\n this.ws = null;\n }\n\n this.state = 'disconnected';\n }\n\n /**\n * Send a message through the WebSocket\n */\n send(type: string, payload: unknown): void {\n const message = JSON.stringify({ type, payload, timestamp: new Date().toISOString() });\n\n if (this.isConnected()) {\n this.ws!.send(message);\n } else {\n // Queue message for when connection is restored\n this.pendingMessages.push(message);\n }\n }\n\n /**\n * Send typing indicator\n */\n sendTypingStart(conversationId: string): void {\n this.send('typing:start', { conversationId });\n }\n\n /**\n * Stop typing indicator\n */\n sendTypingStop(conversationId: string): void {\n this.send('typing:stop', { conversationId });\n }\n\n /**\n * Subscribe to a conversation for real-time updates\n */\n subscribeToConversation(conversationId: string): void {\n this.send('subscribe', { conversationId });\n }\n\n /**\n * Unsubscribe from a conversation\n */\n unsubscribeFromConversation(conversationId: string): void {\n this.send('unsubscribe', { conversationId });\n }\n\n /**\n * Update presence status\n */\n updatePresence(status: string, statusMessage?: string): void {\n this.send('presence:update', { status, statusMessage });\n }\n\n /**\n * Send call notification (ring, accept, reject, end)\n * Note: Actual WebRTC signaling is handled by LiveKit\n */\n sendCallNotification(\n conversationId: string,\n action: CallAction,\n callType?: CallType,\n roomName?: string\n ): void {\n this.send('call', { conversationId, action, callType, roomName });\n }\n\n private handleClose(reason?: string): void {\n this.stopHeartbeat();\n const wasConnected = this.state === 'connected';\n this.state = 'disconnected';\n this.ws = null;\n\n if (wasConnected) {\n this.emit('disconnected', reason);\n }\n\n // Attempt reconnection if enabled\n if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return;\n }\n\n this.state = 'reconnecting';\n this.reconnectAttempts++;\n\n const delay = Math.min(\n this.config.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1),\n 30000 // Max 30 seconds\n );\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n try {\n await this.connect();\n } catch (error) {\n // Connect will handle scheduling next reconnect\n }\n }, delay);\n }\n\n private handleMessage(data: string): void {\n try {\n const message = JSON.parse(data) as WebSocketMessage;\n\n switch (message.type) {\n case 'message:new':\n this.emit('message:new', message.payload as NewMessageEvent);\n break;\n\n case 'message:updated':\n this.emit('message:updated', message.payload as Message);\n break;\n\n case 'message:deleted': {\n const { messageId, conversationId } = message.payload as {\n messageId: string;\n conversationId: string;\n };\n this.emit('message:deleted', messageId, conversationId);\n break;\n }\n\n case 'conversation:created':\n this.emit('conversation:created', message.payload as Conversation);\n break;\n\n case 'conversation:updated':\n this.emit('conversation:updated', message.payload as Conversation);\n break;\n\n case 'participant:joined': {\n const { conversationId, participant } = message.payload as {\n conversationId: string;\n participant: Participant;\n };\n this.emit('participant:joined', conversationId, participant);\n break;\n }\n\n case 'participant:left': {\n const payload = message.payload as { conversationId: string; userId: string };\n this.emit('participant:left', payload.conversationId, payload.userId);\n break;\n }\n\n case 'presence:updated':\n this.emit('presence:updated', message.payload as PresenceEvent);\n break;\n\n case 'typing:start':\n this.emit('typing:start', message.payload as TypingEvent);\n break;\n\n case 'typing:stop':\n this.emit('typing:stop', message.payload as TypingEvent);\n break;\n\n case 'read:receipt':\n this.emit('read:receipt', message.payload as ReadReceiptEvent);\n break;\n\n case 'call:ring':\n this.emit('call:ring', message.payload as CallEvent);\n break;\n\n case 'call:accept':\n this.emit('call:accept', message.payload as CallEvent);\n break;\n\n case 'call:reject':\n this.emit('call:reject', message.payload as CallEvent);\n break;\n\n case 'call:end':\n this.emit('call:end', message.payload as CallEvent);\n break;\n }\n } catch (error) {\n console.error('[ChatWS] Failed to parse message:', error);\n }\n }\n\n private flushPendingMessages(): void {\n while (this.pendingMessages.length > 0 && this.isConnected()) {\n const message = this.pendingMessages.shift();\n if (message) {\n this.ws!.send(message);\n }\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n if (this.isConnected()) {\n this.send('ping', {});\n }\n }, this.config.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private clearTimers(): void {\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n}\n","/**\n * VeroAI Chat Client\n *\n * Main entry point for the Chat SDK - combines HTTP API and WebSocket\n */\n\nimport EventEmitter from 'eventemitter3';\nimport { ChatApi, type RoomInfo } from './api';\nimport { WebSocketManager } from './websocket';\nimport type {\n ChatClientConfig,\n ChatEvents,\n Conversation,\n CreateConversationParams,\n Message,\n SendMessageParams,\n GetMessagesParams,\n PaginatedMessages,\n User,\n PresenceStatus,\n AgentConfig,\n} from './types';\n\n/**\n * VeroAI Chat Client\n *\n * Provides a unified interface for chat functionality:\n * - HTTP API for CRUD operations\n * - WebSocket for real-time events\n *\n * @example\n * ```typescript\n * const chat = new ChatClient({\n * apiUrl: 'https://api.veroai.dev',\n * wsUrl: 'wss://ws.veroai.dev',\n * token: 'your-jwt-token',\n * });\n *\n * // Connect to real-time events\n * await chat.connect();\n *\n * // Listen for new messages\n * chat.on('message:new', ({ message, conversationId }) => {\n * console.log('New message:', message);\n * });\n *\n * // Send a message\n * await chat.sendMessage(conversationId, { content: 'Hello!' });\n * ```\n */\nexport class ChatClient extends EventEmitter<ChatEvents> {\n private api: ChatApi;\n private ws: WebSocketManager | null = null;\n private config: ChatClientConfig;\n private tokenGetter: () => string | null | Promise<string | null>;\n\n constructor(config: ChatClientConfig) {\n super();\n this.config = config;\n\n // Create token getter\n this.tokenGetter = config.getToken || (() => config.token || null);\n\n // Initialize API client\n this.api = new ChatApi({\n apiUrl: config.apiUrl,\n getToken: this.tokenGetter,\n });\n\n // Initialize WebSocket if URL provided\n if (config.wsUrl) {\n this.ws = new WebSocketManager({\n url: config.wsUrl,\n getToken: this.tokenGetter,\n autoReconnect: config.autoReconnect ?? true,\n reconnectInterval: config.reconnectInterval,\n maxReconnectAttempts: config.maxReconnectAttempts,\n });\n\n // Forward WebSocket events\n this.forwardWebSocketEvents();\n }\n\n // Auto-connect if enabled\n if (config.autoConnect && config.wsUrl) {\n this.connect().catch((error) => {\n console.error('[ChatClient] Auto-connect failed:', error);\n });\n }\n }\n\n // ============================================================================\n // Connection Management\n // ============================================================================\n\n /**\n * Connect to WebSocket for real-time updates\n */\n async connect(): Promise<void> {\n if (!this.ws) {\n throw new Error('WebSocket URL not configured');\n }\n await this.ws.connect();\n }\n\n /**\n * Disconnect from WebSocket\n */\n disconnect(): void {\n this.ws?.disconnect();\n }\n\n /**\n * Check if WebSocket is connected\n */\n isConnected(): boolean {\n return this.ws?.isConnected() ?? false;\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string): void {\n this.config.token = token;\n }\n\n // ============================================================================\n // Conversations\n // ============================================================================\n\n /**\n * List all conversations for the current user\n */\n async listConversations(): Promise<Conversation[]> {\n return this.api.listConversations();\n }\n\n /**\n * Get a specific conversation\n */\n async getConversation(conversationId: string): Promise<Conversation> {\n return this.api.getConversation(conversationId);\n }\n\n /**\n * Create a new conversation\n */\n async createConversation(params: CreateConversationParams): Promise<Conversation> {\n const conversation = await this.api.createConversation(params);\n\n // Subscribe to real-time updates for new conversation\n if (this.ws?.isConnected()) {\n this.ws.subscribeToConversation(conversation.id);\n }\n\n return conversation;\n }\n\n /**\n * Mark conversation as read\n */\n async markConversationRead(conversationId: string): Promise<void> {\n return this.api.markConversationRead(conversationId);\n }\n\n /**\n * Leave a conversation\n */\n async leaveConversation(conversationId: string): Promise<void> {\n // Unsubscribe from real-time updates\n if (this.ws?.isConnected()) {\n this.ws.unsubscribeFromConversation(conversationId);\n }\n\n return this.api.leaveConversation(conversationId);\n }\n\n /**\n * Subscribe to real-time updates for a conversation\n */\n subscribeToConversation(conversationId: string): void {\n this.ws?.subscribeToConversation(conversationId);\n }\n\n /**\n * Unsubscribe from real-time updates for a conversation\n */\n unsubscribeFromConversation(conversationId: string): void {\n this.ws?.unsubscribeFromConversation(conversationId);\n }\n\n // ============================================================================\n // Messages\n // ============================================================================\n\n /**\n * Get messages for a conversation\n */\n async getMessages(conversationId: string, params?: GetMessagesParams): Promise<PaginatedMessages> {\n return this.api.getMessages(conversationId, params);\n }\n\n /**\n * Send a message to a conversation\n */\n async sendMessage(conversationId: string, params: SendMessageParams): Promise<Message> {\n return this.api.sendMessage(conversationId, params);\n }\n\n /**\n * Send a text message (convenience method)\n */\n async send(conversationId: string, content: string): Promise<Message> {\n return this.sendMessage(conversationId, { content });\n }\n\n // ============================================================================\n // Typing Indicators\n // ============================================================================\n\n /**\n * Send typing start indicator\n */\n sendTypingStart(conversationId: string): void {\n this.ws?.sendTypingStart(conversationId);\n }\n\n /**\n * Send typing stop indicator\n */\n sendTypingStop(conversationId: string): void {\n this.ws?.sendTypingStop(conversationId);\n }\n\n // ============================================================================\n // Users & Presence\n // ============================================================================\n\n /**\n * List all users (contacts)\n */\n async listUsers(options?: { includeVirtual?: boolean }): Promise<User[]> {\n return this.api.listUsers(options);\n }\n\n /**\n * Get online users\n */\n async getOnlineUsers(): Promise<User[]> {\n return this.api.getOnlineUsers();\n }\n\n /**\n * Get current user profile\n */\n async getCurrentUser(): Promise<User> {\n return this.api.getCurrentUser();\n }\n\n /**\n * Get a specific user\n */\n async getUser(userId: string): Promise<User> {\n return this.api.getUser(userId);\n }\n\n /**\n * Update current user's presence status\n */\n async updateStatus(status: PresenceStatus, statusMessage?: string): Promise<void> {\n // Update via HTTP API\n await this.api.updateStatus(status, statusMessage);\n\n // Also notify via WebSocket for real-time propagation\n this.ws?.updatePresence(status, statusMessage);\n }\n\n // ============================================================================\n // Agents\n // ============================================================================\n\n /**\n * Add agent to conversation\n */\n async addAgentToConversation(\n conversationId: string,\n agentConfigId: string,\n addAsParticipant = true\n ): Promise<void> {\n return this.api.addAgentToConversation(conversationId, agentConfigId, addAsParticipant);\n }\n\n /**\n * Remove agent from conversation\n */\n async removeAgentFromConversation(conversationId: string): Promise<void> {\n return this.api.removeAgentFromConversation(conversationId);\n }\n\n /**\n * Toggle agent enabled/disabled\n */\n async toggleAgent(conversationId: string, enabled: boolean): Promise<void> {\n return this.api.toggleAgent(conversationId, enabled);\n }\n\n /**\n * List available agents\n */\n async listAgents(): Promise<AgentConfig[]> {\n return this.api.listAgents();\n }\n\n // ============================================================================\n // Voice/Video Calls\n // ============================================================================\n\n /**\n * Create a new voice/video room\n *\n * @example\n * ```typescript\n * const room = await chat.createRoom({ name: `call-${conversationId}` });\n * // Use room.wsUrl and room.token with voice client\n * ```\n */\n async createRoom(params: {\n name: string;\n emptyTimeout?: number;\n maxParticipants?: number;\n }): Promise<RoomInfo> {\n return this.api.createRoom(params);\n }\n\n /**\n * Join an existing room and get access token\n *\n * @example\n * ```typescript\n * const room = await chat.joinRoom({\n * roomName: `call-${conversationId}`,\n * participantName: 'John Doe',\n * });\n * // Connect to room using voice client SDK with room.wsUrl and room.token\n * ```\n */\n async joinRoom(params: {\n roomName: string;\n participantName: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n }): Promise<RoomInfo> {\n return this.api.joinRoom(params);\n }\n\n /**\n * Initiate a call in a conversation\n * This notifies other participants that you're calling\n *\n * @example\n * ```typescript\n * // Start a video call\n * const room = await chat.startCall(conversationId, 'video');\n * // room contains { name, wsUrl, token } for Vero Voice\n * ```\n */\n async startCall(\n conversationId: string,\n callType: 'audio' | 'video' = 'audio'\n ): Promise<RoomInfo> {\n // Create room\n const roomName = `call-${conversationId}-${Date.now()}`;\n const room = await this.api.createRoom({ name: roomName });\n\n // Notify other participants via WebSocket\n this.ws?.sendCallNotification(conversationId, 'ring', callType, roomName);\n\n return room;\n }\n\n /**\n * Accept an incoming call\n *\n * @example\n * ```typescript\n * chat.on('call:ring', async ({ conversationId, roomName, callType }) => {\n * const room = await chat.acceptCall(conversationId, roomName);\n * // Connect to room using voice client SDK\n * });\n * ```\n */\n async acceptCall(\n conversationId: string,\n roomName: string,\n participantName: string\n ): Promise<RoomInfo> {\n const room = await this.api.joinRoom({ roomName, participantName });\n\n // Notify caller that we accepted\n this.ws?.sendCallNotification(conversationId, 'accept', undefined, roomName);\n\n return room;\n }\n\n /**\n * Reject an incoming call\n */\n rejectCall(conversationId: string): void {\n this.ws?.sendCallNotification(conversationId, 'reject');\n }\n\n /**\n * End an ongoing call\n */\n endCall(conversationId: string): void {\n this.ws?.sendCallNotification(conversationId, 'end');\n }\n\n // ============================================================================\n // Internal\n // ============================================================================\n\n private forwardWebSocketEvents(): void {\n if (!this.ws) return;\n\n // Forward all events from WebSocket manager to ChatClient\n this.ws.on('connected', () => this.emit('connected'));\n this.ws.on('disconnected', (reason) => this.emit('disconnected', reason));\n this.ws.on('error', (error) => this.emit('error', error));\n this.ws.on('message:new', (event) => this.emit('message:new', event));\n this.ws.on('message:updated', (msg) => this.emit('message:updated', msg));\n this.ws.on('message:deleted', (msgId, convId) => this.emit('message:deleted', msgId, convId));\n this.ws.on('conversation:created', (conv) => this.emit('conversation:created', conv));\n this.ws.on('conversation:updated', (conv) => this.emit('conversation:updated', conv));\n this.ws.on('participant:joined', (convId, p) => this.emit('participant:joined', convId, p));\n this.ws.on('participant:left', (convId, userId) => this.emit('participant:left', convId, userId));\n this.ws.on('presence:updated', (event) => this.emit('presence:updated', event));\n this.ws.on('typing:start', (event) => this.emit('typing:start', event));\n this.ws.on('typing:stop', (event) => this.emit('typing:stop', event));\n this.ws.on('read:receipt', (event) => this.emit('read:receipt', event));\n this.ws.on('call:ring', (event) => this.emit('call:ring', event));\n this.ws.on('call:accept', (event) => this.emit('call:accept', event));\n this.ws.on('call:reject', (event) => this.emit('call:reject', event));\n this.ws.on('call:end', (event) => this.emit('call:end', event));\n }\n}\n"]}
|