@elqnt/chat 1.0.2 → 1.0.4
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/hooks/use-websocket-chat-admin.d.mts +3 -2
- package/dist/hooks/use-websocket-chat-admin.d.ts +3 -2
- package/dist/hooks/use-websocket-chat-admin.js +829 -4
- package/dist/hooks/use-websocket-chat-admin.js.map +1 -1
- package/dist/hooks/use-websocket-chat-admin.mjs +805 -4
- package/dist/hooks/use-websocket-chat-admin.mjs.map +1 -1
- package/dist/hooks/use-websocket-chat-base.d.mts +68 -2
- package/dist/hooks/use-websocket-chat-base.d.ts +68 -2
- package/dist/hooks/use-websocket-chat-base.js +661 -6
- package/dist/hooks/use-websocket-chat-base.js.map +1 -1
- package/dist/hooks/use-websocket-chat-base.mjs +634 -3
- package/dist/hooks/use-websocket-chat-base.mjs.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.d.mts +3 -2
- package/dist/hooks/use-websocket-chat-customer.d.ts +3 -2
- package/dist/hooks/use-websocket-chat-customer.js +726 -5
- package/dist/hooks/use-websocket-chat-customer.js.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.mjs +701 -4
- package/dist/hooks/use-websocket-chat-customer.mjs.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1685 -590
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1064 -197
- package/dist/index.mjs.map +1 -1
- package/dist/{use-websocket-chat-base-CZDONnTz.d.ts → models/index.d.mts} +2 -66
- package/dist/{use-websocket-chat-base-CZDONnTz.d.mts → models/index.d.ts} +2 -66
- package/dist/models/index.js +555 -0
- package/dist/models/index.js.map +1 -0
- package/dist/{chunk-AC5J5LX5.mjs → models/index.mjs} +146 -318
- package/dist/models/index.mjs.map +1 -0
- package/package.json +6 -1
- package/dist/chunk-3PXNBY7J.js +0 -73
- package/dist/chunk-3PXNBY7J.js.map +0 -1
- package/dist/chunk-AC5J5LX5.mjs.map +0 -1
- package/dist/chunk-DTFTLFSY.js +0 -637
- package/dist/chunk-DTFTLFSY.js.map +0 -1
- package/dist/chunk-E2FJX52R.js +0 -529
- package/dist/chunk-E2FJX52R.js.map +0 -1
- package/dist/chunk-F6OOS4ZM.mjs +0 -637
- package/dist/chunk-F6OOS4ZM.mjs.map +0 -1
- package/dist/chunk-XVYABY2Z.mjs +0 -73
- package/dist/chunk-XVYABY2Z.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,185 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
AgentStatusAway,
|
|
3
|
-
AgentStatusBusy,
|
|
4
|
-
AgentStatusOffline,
|
|
5
|
-
AgentStatusOnline,
|
|
6
|
-
AssignChatToAgentSubject,
|
|
7
|
-
AttachmentTypeActions,
|
|
8
|
-
AttachmentTypeArticles,
|
|
9
|
-
AttachmentTypeAudio,
|
|
10
|
-
AttachmentTypeBullets,
|
|
11
|
-
AttachmentTypeData,
|
|
12
|
-
AttachmentTypeDocument,
|
|
13
|
-
AttachmentTypeDocumentAnalysis,
|
|
14
|
-
AttachmentTypeDocumentSources,
|
|
15
|
-
AttachmentTypeImage,
|
|
16
|
-
AttachmentTypeKGNodes,
|
|
17
|
-
AttachmentTypeLocation,
|
|
18
|
-
AttachmentTypeRecords,
|
|
19
|
-
AttachmentTypeReferences,
|
|
20
|
-
AttachmentTypeSticker,
|
|
21
|
-
AttachmentTypeSubsections,
|
|
22
|
-
AttachmentTypeVideo,
|
|
23
|
-
ChatArchiveSubjectPattern,
|
|
24
|
-
ChatEventTypeAgentActivityPing,
|
|
25
|
-
ChatEventTypeAgentChatAssigned,
|
|
26
|
-
ChatEventTypeAgentChatCompleted,
|
|
27
|
-
ChatEventTypeAgentContextUpdate,
|
|
28
|
-
ChatEventTypeAgentExecutionEnded,
|
|
29
|
-
ChatEventTypeAgentExecutionStarted,
|
|
30
|
-
ChatEventTypeAgentSessionEnd,
|
|
31
|
-
ChatEventTypeAgentSessionStart,
|
|
32
|
-
ChatEventTypeAgentStatusChange,
|
|
33
|
-
ChatEventTypeBlockUser,
|
|
34
|
-
ChatEventTypeCSATRequest,
|
|
35
|
-
ChatEventTypeCSATResponse,
|
|
36
|
-
ChatEventTypeCSATSurvey,
|
|
37
|
-
ChatEventTypeChatEnded,
|
|
38
|
-
ChatEventTypeChatRemoved,
|
|
39
|
-
ChatEventTypeChatUpdated,
|
|
40
|
-
ChatEventTypeClientAction,
|
|
41
|
-
ChatEventTypeClientActionCallback,
|
|
42
|
-
ChatEventTypeCreateRoom,
|
|
43
|
-
ChatEventTypeDeleteRoom,
|
|
44
|
-
ChatEventTypeDelivered,
|
|
45
|
-
ChatEventTypeEndChat,
|
|
46
|
-
ChatEventTypeError,
|
|
47
|
-
ChatEventTypeGetAgents,
|
|
48
|
-
ChatEventTypeGetAgentsResponse,
|
|
49
|
-
ChatEventTypeGetOnlineUsers,
|
|
50
|
-
ChatEventTypeHumanAgentJoined,
|
|
51
|
-
ChatEventTypeHumanAgentLeft,
|
|
52
|
-
ChatEventTypeInviteUser,
|
|
53
|
-
ChatEventTypeJoinRoom,
|
|
54
|
-
ChatEventTypeLeaveRoom,
|
|
55
|
-
ChatEventTypeListChats,
|
|
56
|
-
ChatEventTypeListRooms,
|
|
57
|
-
ChatEventTypeLoadAgentContext,
|
|
58
|
-
ChatEventTypeLoadAgentContextResponse,
|
|
59
|
-
ChatEventTypeLoadChat,
|
|
60
|
-
ChatEventTypeLoadChatResponse,
|
|
61
|
-
ChatEventTypeMentionUser,
|
|
62
|
-
ChatEventTypeMessage,
|
|
63
|
-
ChatEventTypeMessageDeleted,
|
|
64
|
-
ChatEventTypeMessageDeletedResponse,
|
|
65
|
-
ChatEventTypeMessageEdited,
|
|
66
|
-
ChatEventTypeMessageEditedResponse,
|
|
67
|
-
ChatEventTypeMessageReaction,
|
|
68
|
-
ChatEventTypeMessageReactionResponse,
|
|
69
|
-
ChatEventTypeMessageReply,
|
|
70
|
-
ChatEventTypeMessageStatusUpdate,
|
|
71
|
-
ChatEventTypeNewChat,
|
|
72
|
-
ChatEventTypeNewChatCreated,
|
|
73
|
-
ChatEventTypeObserverJoined,
|
|
74
|
-
ChatEventTypeObserverLeft,
|
|
75
|
-
ChatEventTypeOnlineUsersResponse,
|
|
76
|
-
ChatEventTypePing,
|
|
77
|
-
ChatEventTypePlanApproved,
|
|
78
|
-
ChatEventTypePlanCompleted,
|
|
79
|
-
ChatEventTypePlanPendingApproval,
|
|
80
|
-
ChatEventTypePlanRejected,
|
|
81
|
-
ChatEventTypePong,
|
|
82
|
-
ChatEventTypeRead,
|
|
83
|
-
ChatEventTypeReconnected,
|
|
84
|
-
ChatEventTypeRoomCreated,
|
|
85
|
-
ChatEventTypeRoomDeleted,
|
|
86
|
-
ChatEventTypeRoomUpdated,
|
|
87
|
-
ChatEventTypeRoomUserJoined,
|
|
88
|
-
ChatEventTypeRoomUserLeft,
|
|
89
|
-
ChatEventTypeRoomsResponse,
|
|
90
|
-
ChatEventTypeStepCompleted,
|
|
91
|
-
ChatEventTypeStepFailed,
|
|
92
|
-
ChatEventTypeStepStarted,
|
|
93
|
-
ChatEventTypeStoppedTyping,
|
|
94
|
-
ChatEventTypeSummaryUpdate,
|
|
95
|
-
ChatEventTypeSyncMetadata,
|
|
96
|
-
ChatEventTypeSyncMetadataResponse,
|
|
97
|
-
ChatEventTypeSyncUserSession,
|
|
98
|
-
ChatEventTypeSyncUserSessionResponse,
|
|
99
|
-
ChatEventTypeTyping,
|
|
100
|
-
ChatEventTypeUpdateRoom,
|
|
101
|
-
ChatEventTypeUserActivity,
|
|
102
|
-
ChatEventTypeUserActivityUpdate,
|
|
103
|
-
ChatEventTypeUserInvited,
|
|
104
|
-
ChatEventTypeUserJoined,
|
|
105
|
-
ChatEventTypeUserLeft,
|
|
106
|
-
ChatEventTypeUserPresenceChanged,
|
|
107
|
-
ChatEventTypeUserPresenceEnd,
|
|
108
|
-
ChatEventTypeUserPresenceStart,
|
|
109
|
-
ChatEventTypeUserRemoved,
|
|
110
|
-
ChatEventTypeUserStatusChange,
|
|
111
|
-
ChatEventTypeUserSuggestedActionSelected,
|
|
112
|
-
ChatEventTypeUserSuggestedActions,
|
|
113
|
-
ChatEventTypeWaiting,
|
|
114
|
-
ChatEventTypeWaitingForAgent,
|
|
115
|
-
ChatRoleAI,
|
|
116
|
-
ChatRoleDataQuery,
|
|
117
|
-
ChatRoleEvent,
|
|
118
|
-
ChatRoleHumanAgent,
|
|
119
|
-
ChatRoleObserver,
|
|
120
|
-
ChatRoleSystem,
|
|
121
|
-
ChatRoleTool,
|
|
122
|
-
ChatRoleUser,
|
|
123
|
-
ChatSessionStatusActive,
|
|
124
|
-
ChatSessionStatusExpired,
|
|
125
|
-
ChatSessionStatusIdle,
|
|
126
|
-
ChatStatusAbandoned,
|
|
127
|
-
ChatStatusActive,
|
|
128
|
-
ChatStatusArchived,
|
|
129
|
-
ChatStatusClosed,
|
|
130
|
-
ChatStatusDisconnected,
|
|
131
|
-
ChatTypeCustomerSupport,
|
|
132
|
-
ChatTypeDirect,
|
|
133
|
-
ChatTypeGroup,
|
|
134
|
-
ChatTypePrivateRoom,
|
|
135
|
-
ChatTypePublicRoom,
|
|
136
|
-
CompleteChatByAgentSubject,
|
|
137
|
-
CreateAgentQueueSubject,
|
|
138
|
-
DeleteAgentQueueSubject,
|
|
139
|
-
EndAgentSessionSubject,
|
|
140
|
-
GetActiveChatCountSubject,
|
|
141
|
-
GetActiveChatsSubject,
|
|
142
|
-
GetAgentQueuesSubject,
|
|
143
|
-
GetAgentSessionSubject,
|
|
144
|
-
GetChatSubject,
|
|
145
|
-
GetDailyChatCountSubject,
|
|
146
|
-
GetOnlineAgentCountSubject,
|
|
147
|
-
GetOnlineAgentsSubject,
|
|
148
|
-
GetOnlineUsersSubject,
|
|
149
|
-
GetQueueChatCountSubject,
|
|
150
|
-
GetQueueChatsSubject,
|
|
151
|
-
GetUserChatsSubject,
|
|
152
|
-
GetWaitingForAgentChatCountSubject,
|
|
153
|
-
GetWaitingForAgentChatsSubject,
|
|
154
|
-
MessageStatusDelivered,
|
|
155
|
-
MessageStatusFailed,
|
|
156
|
-
MessageStatusRead,
|
|
157
|
-
MessageStatusSending,
|
|
158
|
-
MessageStatusSent,
|
|
159
|
-
QueueTypeComplexity,
|
|
160
|
-
QueueTypeDepartment,
|
|
161
|
-
QueueTypePriority,
|
|
162
|
-
QueueTypeSkill,
|
|
163
|
-
QueueTypes,
|
|
164
|
-
SetupOrgSubject,
|
|
165
|
-
StartAgentSessionSubject,
|
|
166
|
-
TriggerAnalyticsScanSubject,
|
|
167
|
-
UpdateAgentLastActivitySubject,
|
|
168
|
-
UpdateAgentQueueSubject,
|
|
169
|
-
UpdateAgentStatusSubject,
|
|
170
|
-
UpdateUserStatusSubject,
|
|
171
|
-
UserStatusAway,
|
|
172
|
-
UserStatusBusy,
|
|
173
|
-
UserStatusOffline,
|
|
174
|
-
UserStatusOnline,
|
|
175
|
-
useWebSocketChatAdmin
|
|
176
|
-
} from "./chunk-AC5J5LX5.mjs";
|
|
177
|
-
import {
|
|
178
|
-
useWebSocketChatCustomer
|
|
179
|
-
} from "./chunk-XVYABY2Z.mjs";
|
|
180
|
-
import {
|
|
181
|
-
useWebSocketChatBase
|
|
182
|
-
} from "./chunk-F6OOS4ZM.mjs";
|
|
1
|
+
"use client";
|
|
183
2
|
|
|
184
3
|
// components/admin/admin-chat-input.tsx
|
|
185
4
|
import { useUserContext } from "@elqnt/auth";
|
|
@@ -383,10 +202,1058 @@ var __iconNode14 = [
|
|
|
383
202
|
var User = createLucideIcon("User", __iconNode14);
|
|
384
203
|
|
|
385
204
|
// components/admin/admin-chat-input.tsx
|
|
386
|
-
import { useRef, useState } from "react";
|
|
205
|
+
import { useRef as useRef2, useState as useState4 } from "react";
|
|
387
206
|
|
|
388
207
|
// context/websocket-chat-admin-context.tsx
|
|
389
208
|
import { createContext, useContext } from "react";
|
|
209
|
+
|
|
210
|
+
// hooks/use-websocket-chat-admin.ts
|
|
211
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
212
|
+
|
|
213
|
+
// models/chat-models.ts
|
|
214
|
+
var ChatStatusActive = "active";
|
|
215
|
+
var ChatStatusDisconnected = "disconnected";
|
|
216
|
+
var ChatStatusAbandoned = "abandoned";
|
|
217
|
+
var ChatStatusClosed = "closed";
|
|
218
|
+
var ChatStatusArchived = "archived";
|
|
219
|
+
var ChatTypeCustomerSupport = "customer_support";
|
|
220
|
+
var ChatTypePublicRoom = "public_room";
|
|
221
|
+
var ChatTypePrivateRoom = "private_room";
|
|
222
|
+
var ChatTypeDirect = "direct";
|
|
223
|
+
var ChatTypeGroup = "group";
|
|
224
|
+
var ChatRoleUser = "user";
|
|
225
|
+
var ChatRoleAI = "ai";
|
|
226
|
+
var ChatRoleEvent = "event";
|
|
227
|
+
var ChatRoleHumanAgent = "humanAgent";
|
|
228
|
+
var ChatRoleObserver = "observer";
|
|
229
|
+
var ChatRoleDataQuery = "dataQuery";
|
|
230
|
+
var ChatRoleSystem = "system";
|
|
231
|
+
var ChatRoleTool = "tool";
|
|
232
|
+
var AgentStatusOnline = "online";
|
|
233
|
+
var AgentStatusAway = "away";
|
|
234
|
+
var AgentStatusBusy = "busy";
|
|
235
|
+
var AgentStatusOffline = "offline";
|
|
236
|
+
var ChatEventTypeUserJoined = "user_joined";
|
|
237
|
+
var ChatEventTypeUserLeft = "user_left";
|
|
238
|
+
var ChatEventTypeTyping = "typing";
|
|
239
|
+
var ChatEventTypeStoppedTyping = "stopped_typing";
|
|
240
|
+
var ChatEventTypeRead = "read";
|
|
241
|
+
var ChatEventTypeDelivered = "delivered";
|
|
242
|
+
var ChatEventTypeReconnected = "reconnected";
|
|
243
|
+
var ChatEventTypeError = "error";
|
|
244
|
+
var ChatEventTypeWaiting = "waiting";
|
|
245
|
+
var ChatEventTypeLoadChat = "load_chat";
|
|
246
|
+
var ChatEventTypeLoadChatResponse = "load_chat_response";
|
|
247
|
+
var ChatEventTypeMessage = "message";
|
|
248
|
+
var ChatEventTypeWaitingForAgent = "waiting_for_agent";
|
|
249
|
+
var ChatEventTypeMessageStatusUpdate = "message_status_update";
|
|
250
|
+
var ChatEventTypeHumanAgentJoined = "human_agent_joined";
|
|
251
|
+
var ChatEventTypeHumanAgentLeft = "human_agent_left";
|
|
252
|
+
var ChatEventTypeObserverJoined = "observer_joined";
|
|
253
|
+
var ChatEventTypeObserverLeft = "observer_left";
|
|
254
|
+
var ChatEventTypeListChats = "list_chats";
|
|
255
|
+
var ChatEventTypeChatUpdated = "chat_updated";
|
|
256
|
+
var ChatEventTypeChatRemoved = "chat_removed";
|
|
257
|
+
var ChatEventTypeSyncMetadata = "sync_metadata";
|
|
258
|
+
var ChatEventTypeSyncMetadataResponse = "sync_metadata_response";
|
|
259
|
+
var ChatEventTypeSyncUserSession = "sync_user_session";
|
|
260
|
+
var ChatEventTypeSyncUserSessionResponse = "sync_user_session_response";
|
|
261
|
+
var ChatEventTypeClientAction = "client_action";
|
|
262
|
+
var ChatEventTypeClientActionCallback = "client_action_callback";
|
|
263
|
+
var ChatEventTypeBlockUser = "block_user";
|
|
264
|
+
var ChatEventTypeCreateRoom = "create_room";
|
|
265
|
+
var ChatEventTypeRoomCreated = "room_created";
|
|
266
|
+
var ChatEventTypeJoinRoom = "join_room";
|
|
267
|
+
var ChatEventTypeLeaveRoom = "leave_room";
|
|
268
|
+
var ChatEventTypeDeleteRoom = "delete_room";
|
|
269
|
+
var ChatEventTypeRoomDeleted = "room_deleted";
|
|
270
|
+
var ChatEventTypeUpdateRoom = "update_room";
|
|
271
|
+
var ChatEventTypeRoomUpdated = "room_updated";
|
|
272
|
+
var ChatEventTypeInviteUser = "invite_user";
|
|
273
|
+
var ChatEventTypeUserInvited = "user_invited";
|
|
274
|
+
var ChatEventTypeRoomUserJoined = "room_user_joined";
|
|
275
|
+
var ChatEventTypeRoomUserLeft = "room_user_left";
|
|
276
|
+
var ChatEventTypeUserRemoved = "user_removed";
|
|
277
|
+
var ChatEventTypeListRooms = "list_rooms";
|
|
278
|
+
var ChatEventTypeRoomsResponse = "rooms_response";
|
|
279
|
+
var ChatEventTypeMessageEdited = "message_edited";
|
|
280
|
+
var ChatEventTypeMessageDeleted = "message_deleted";
|
|
281
|
+
var ChatEventTypeMessageReaction = "message_reaction";
|
|
282
|
+
var ChatEventTypeMessageReply = "message_reply";
|
|
283
|
+
var ChatEventTypeMentionUser = "mention_user";
|
|
284
|
+
var ChatEventTypeMessageEditedResponse = "message_edited_response";
|
|
285
|
+
var ChatEventTypeMessageDeletedResponse = "message_deleted_response";
|
|
286
|
+
var ChatEventTypeMessageReactionResponse = "message_reaction_response";
|
|
287
|
+
var ChatEventTypeUserPresenceStart = "user_presence_start";
|
|
288
|
+
var ChatEventTypeUserPresenceEnd = "user_presence_end";
|
|
289
|
+
var ChatEventTypeUserStatusChange = "user_status_change";
|
|
290
|
+
var ChatEventTypeUserActivity = "user_activity";
|
|
291
|
+
var ChatEventTypeUserPresenceChanged = "user_presence_changed";
|
|
292
|
+
var ChatEventTypeUserActivityUpdate = "user_activity_update";
|
|
293
|
+
var ChatEventTypeGetOnlineUsers = "get_online_users";
|
|
294
|
+
var ChatEventTypeOnlineUsersResponse = "online_users";
|
|
295
|
+
var ChatEventTypeEndChat = "end_chat";
|
|
296
|
+
var ChatEventTypeChatEnded = "chat_ended";
|
|
297
|
+
var ChatEventTypeAgentSessionStart = "agent_session_start";
|
|
298
|
+
var ChatEventTypeAgentSessionEnd = "agent_session_end";
|
|
299
|
+
var ChatEventTypeAgentStatusChange = "agent_status_change";
|
|
300
|
+
var ChatEventTypeAgentActivityPing = "agent_activity_ping";
|
|
301
|
+
var ChatEventTypeAgentChatAssigned = "agent_chat_assigned";
|
|
302
|
+
var ChatEventTypeAgentChatCompleted = "agent_chat_completed";
|
|
303
|
+
var ChatEventTypeGetAgents = "get_agents";
|
|
304
|
+
var ChatEventTypeGetAgentsResponse = "get_agents_response";
|
|
305
|
+
var ChatEventTypeCSATRequest = "csat_request";
|
|
306
|
+
var ChatEventTypeCSATSurvey = "show_csat_survey";
|
|
307
|
+
var ChatEventTypeCSATResponse = "csat_response";
|
|
308
|
+
var ChatEventTypeUserSuggestedActions = "user_suggested_actions";
|
|
309
|
+
var ChatEventTypeUserSuggestedActionSelected = "user_suggested_action_selected";
|
|
310
|
+
var ChatEventTypeSummaryUpdate = "summary_update";
|
|
311
|
+
var ChatEventTypeAgentContextUpdate = "agent_context_update";
|
|
312
|
+
var ChatEventTypeAgentExecutionStarted = "agent_execution_started";
|
|
313
|
+
var ChatEventTypeAgentExecutionEnded = "agent_execution_ended";
|
|
314
|
+
var ChatEventTypeLoadAgentContext = "load_agent_context";
|
|
315
|
+
var ChatEventTypeLoadAgentContextResponse = "load_agent_context_response";
|
|
316
|
+
var ChatEventTypePlanPendingApproval = "plan_pending_approval";
|
|
317
|
+
var ChatEventTypePlanApproved = "plan_approved";
|
|
318
|
+
var ChatEventTypePlanRejected = "plan_rejected";
|
|
319
|
+
var ChatEventTypePlanCompleted = "plan_completed";
|
|
320
|
+
var ChatEventTypeStepStarted = "step_started";
|
|
321
|
+
var ChatEventTypeStepCompleted = "step_completed";
|
|
322
|
+
var ChatEventTypeStepFailed = "step_failed";
|
|
323
|
+
var ChatEventTypeNewChat = "new_chat";
|
|
324
|
+
var ChatEventTypeNewChatCreated = "new_chat_created";
|
|
325
|
+
var ChatEventTypePing = "ping";
|
|
326
|
+
var ChatEventTypePong = "pong";
|
|
327
|
+
var MessageStatusSending = "sending";
|
|
328
|
+
var MessageStatusSent = "sent";
|
|
329
|
+
var MessageStatusDelivered = "delivered";
|
|
330
|
+
var MessageStatusRead = "read";
|
|
331
|
+
var MessageStatusFailed = "failed";
|
|
332
|
+
var AttachmentTypeDocument = "document";
|
|
333
|
+
var AttachmentTypeDocumentAnalysis = "document_analysis";
|
|
334
|
+
var AttachmentTypeImage = "image";
|
|
335
|
+
var AttachmentTypeAudio = "audio";
|
|
336
|
+
var AttachmentTypeVideo = "video";
|
|
337
|
+
var AttachmentTypeLocation = "location";
|
|
338
|
+
var AttachmentTypeReferences = "references";
|
|
339
|
+
var AttachmentTypeSubsections = "subsections";
|
|
340
|
+
var AttachmentTypeArticles = "articles";
|
|
341
|
+
var AttachmentTypeRecords = "records";
|
|
342
|
+
var AttachmentTypeActions = "actions";
|
|
343
|
+
var AttachmentTypeBullets = "bullets";
|
|
344
|
+
var AttachmentTypeSticker = "sticker";
|
|
345
|
+
var AttachmentTypeData = "data";
|
|
346
|
+
var AttachmentTypeKGNodes = "kgNodes";
|
|
347
|
+
var AttachmentTypeDocumentSources = "document_sources";
|
|
348
|
+
var ChatSessionStatusActive = "active";
|
|
349
|
+
var ChatSessionStatusIdle = "idle";
|
|
350
|
+
var ChatSessionStatusExpired = "expired";
|
|
351
|
+
var UserStatusOnline = "online";
|
|
352
|
+
var UserStatusAway = "away";
|
|
353
|
+
var UserStatusBusy = "busy";
|
|
354
|
+
var UserStatusOffline = "offline";
|
|
355
|
+
var QueueTypes = {
|
|
356
|
+
skill: { value: "skill", label: "Skill-based", description: "Route by agent expertise and skills" },
|
|
357
|
+
priority: { value: "priority", label: "Priority-based", description: "Route by customer tier and urgency level" },
|
|
358
|
+
department: { value: "department", label: "Department-based", description: "Route by business function alignment" },
|
|
359
|
+
complexity: { value: "complexity", label: "Complexity-based", description: "Route by issue difficulty assessment" }
|
|
360
|
+
};
|
|
361
|
+
var QueueTypeSkill = "skill";
|
|
362
|
+
var QueueTypePriority = "priority";
|
|
363
|
+
var QueueTypeDepartment = "department";
|
|
364
|
+
var QueueTypeComplexity = "complexity";
|
|
365
|
+
var GetWaitingForAgentChatCountSubject = "chat.get_waiting_for_agent_chat_count";
|
|
366
|
+
var GetActiveChatCountSubject = "chat.get_active_chat_count";
|
|
367
|
+
var GetWaitingForAgentChatsSubject = "chat.get_waiting_for_agent_chats";
|
|
368
|
+
var GetActiveChatsSubject = "chat.get_active_chats";
|
|
369
|
+
var GetUserChatsSubject = "chat.get_user_chats";
|
|
370
|
+
var GetChatSubject = "chat.get_chat";
|
|
371
|
+
var ChatArchiveSubjectPattern = "chat.archive.%s.server";
|
|
372
|
+
var StartAgentSessionSubject = "chat.agent_session.start";
|
|
373
|
+
var EndAgentSessionSubject = "chat.agent_session.end";
|
|
374
|
+
var UpdateAgentStatusSubject = "chat.agent_session.update_status";
|
|
375
|
+
var UpdateAgentLastActivitySubject = "chat.agent_session.update_last_activity";
|
|
376
|
+
var AssignChatToAgentSubject = "chat.agent_session.assign_chat";
|
|
377
|
+
var CompleteChatByAgentSubject = "chat.agent_session.complete_chat";
|
|
378
|
+
var GetAgentSessionSubject = "chat.agent_session.get";
|
|
379
|
+
var GetOnlineAgentsSubject = "chat.agent_session.get_online_agents";
|
|
380
|
+
var GetOnlineAgentCountSubject = "chat.agent_session.get_online_agent_count";
|
|
381
|
+
var CreateAgentQueueSubject = "chat.agent_queue.create";
|
|
382
|
+
var GetAgentQueuesSubject = "chat.agent_queue.get";
|
|
383
|
+
var UpdateAgentQueueSubject = "chat.agent_queue.update";
|
|
384
|
+
var DeleteAgentQueueSubject = "chat.agent_queue.delete";
|
|
385
|
+
var GetQueueChatsSubject = "chat.queue.get_chats";
|
|
386
|
+
var GetQueueChatCountSubject = "chat.queue.get_chat_count";
|
|
387
|
+
var GetDailyChatCountSubject = "chat.get_daily_chat_count";
|
|
388
|
+
var UpdateUserStatusSubject = "chat.user.status.update";
|
|
389
|
+
var GetOnlineUsersSubject = "chat.users.online.get";
|
|
390
|
+
var TriggerAnalyticsScanSubject = "chat.analytics.trigger-scan";
|
|
391
|
+
var SetupOrgSubject = "chat.org.setup";
|
|
392
|
+
|
|
393
|
+
// hooks/use-websocket-chat-base.ts
|
|
394
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
395
|
+
var createDefaultLogger = (debug) => ({
|
|
396
|
+
debug: debug ? console.log : () => {
|
|
397
|
+
},
|
|
398
|
+
info: console.info,
|
|
399
|
+
warn: console.warn,
|
|
400
|
+
error: console.error
|
|
401
|
+
});
|
|
402
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
403
|
+
maxRetries: 10,
|
|
404
|
+
intervals: [1e3, 2e3, 5e3],
|
|
405
|
+
backoffMultiplier: 1.5,
|
|
406
|
+
maxBackoffTime: 3e4
|
|
407
|
+
};
|
|
408
|
+
var DEFAULT_QUEUE_CONFIG = {
|
|
409
|
+
maxSize: 100,
|
|
410
|
+
dropStrategy: "oldest"
|
|
411
|
+
};
|
|
412
|
+
var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
|
|
413
|
+
var DEFAULT_HEARTBEAT_TIMEOUT = 5e3;
|
|
414
|
+
function isChatEvent(data) {
|
|
415
|
+
return data && typeof data === "object" && (typeof data.type === "string" || data.message);
|
|
416
|
+
}
|
|
417
|
+
var useWebSocketChatBase = ({
|
|
418
|
+
serverBaseUrl,
|
|
419
|
+
orgId,
|
|
420
|
+
clientType,
|
|
421
|
+
product,
|
|
422
|
+
onMessage,
|
|
423
|
+
retryConfig = DEFAULT_RETRY_CONFIG,
|
|
424
|
+
queueConfig = DEFAULT_QUEUE_CONFIG,
|
|
425
|
+
debug = false,
|
|
426
|
+
logger = createDefaultLogger(debug),
|
|
427
|
+
heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL,
|
|
428
|
+
heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT
|
|
429
|
+
}) => {
|
|
430
|
+
const [connectionState, setConnectionState] = useState("disconnected");
|
|
431
|
+
const [error, setError] = useState(void 0);
|
|
432
|
+
const [startTime, setStartTime] = useState(void 0);
|
|
433
|
+
const [metrics, setMetrics] = useState({
|
|
434
|
+
latency: 0,
|
|
435
|
+
messagesSent: 0,
|
|
436
|
+
messagesReceived: 0,
|
|
437
|
+
messagesQueued: 0,
|
|
438
|
+
reconnectCount: 0
|
|
439
|
+
});
|
|
440
|
+
const wsRef = useRef(void 0);
|
|
441
|
+
const reconnectTimeoutRef = useRef(void 0);
|
|
442
|
+
const retryCountRef = useRef(0);
|
|
443
|
+
const messageQueueRef = useRef([]);
|
|
444
|
+
const mountedRef = useRef(false);
|
|
445
|
+
const currentChatKeyRef = useRef(void 0);
|
|
446
|
+
const currentUserIdRef = useRef(void 0);
|
|
447
|
+
const intentionalDisconnectRef = useRef(false);
|
|
448
|
+
const eventHandlersRef = useRef(
|
|
449
|
+
/* @__PURE__ */ new Map()
|
|
450
|
+
);
|
|
451
|
+
const onMessageRef = useRef(onMessage);
|
|
452
|
+
const pendingMessagesRef = useRef(/* @__PURE__ */ new Map());
|
|
453
|
+
const heartbeatIntervalRef = useRef(void 0);
|
|
454
|
+
const heartbeatTimeoutRef = useRef(void 0);
|
|
455
|
+
const lastPongRef = useRef(Date.now());
|
|
456
|
+
const chatCreationPromiseRef = useRef(null);
|
|
457
|
+
const loadChatRetryMapRef = useRef(/* @__PURE__ */ new Map());
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
onMessageRef.current = onMessage;
|
|
460
|
+
}, [onMessage]);
|
|
461
|
+
const isConnected = connectionState === "connected";
|
|
462
|
+
const on = useCallback((eventType, handler) => {
|
|
463
|
+
if (!eventHandlersRef.current.has(eventType)) {
|
|
464
|
+
eventHandlersRef.current.set(eventType, /* @__PURE__ */ new Set());
|
|
465
|
+
}
|
|
466
|
+
eventHandlersRef.current.get(eventType).add(handler);
|
|
467
|
+
return () => off(eventType, handler);
|
|
468
|
+
}, []);
|
|
469
|
+
const off = useCallback((eventType, handler) => {
|
|
470
|
+
const handlers = eventHandlersRef.current.get(eventType);
|
|
471
|
+
if (handlers) {
|
|
472
|
+
handlers.delete(handler);
|
|
473
|
+
if (handlers.size === 0) {
|
|
474
|
+
eventHandlersRef.current.delete(eventType);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}, []);
|
|
478
|
+
const emit = useCallback(
|
|
479
|
+
(eventType, data) => {
|
|
480
|
+
const handlers = eventHandlersRef.current.get(eventType);
|
|
481
|
+
if (handlers) {
|
|
482
|
+
handlers.forEach((handler) => {
|
|
483
|
+
try {
|
|
484
|
+
handler(data);
|
|
485
|
+
} catch (error2) {
|
|
486
|
+
logger.error(`Error in event handler for ${eventType}:`, error2);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
[logger]
|
|
492
|
+
);
|
|
493
|
+
const updateMetrics = useCallback((updates) => {
|
|
494
|
+
setMetrics((prev) => ({ ...prev, ...updates }));
|
|
495
|
+
}, []);
|
|
496
|
+
const addToQueue = useCallback(
|
|
497
|
+
(event) => {
|
|
498
|
+
const currentQueueSize = messageQueueRef.current.length;
|
|
499
|
+
const maxSize = queueConfig.maxSize || DEFAULT_QUEUE_CONFIG.maxSize;
|
|
500
|
+
if (currentQueueSize >= maxSize) {
|
|
501
|
+
if (queueConfig.dropStrategy === "newest") {
|
|
502
|
+
logger.warn("Message queue full, dropping new message");
|
|
503
|
+
return false;
|
|
504
|
+
} else {
|
|
505
|
+
const dropped = messageQueueRef.current.shift();
|
|
506
|
+
logger.warn("Message queue full, dropped oldest message", dropped);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
messageQueueRef.current.push(event);
|
|
510
|
+
updateMetrics({ messagesQueued: messageQueueRef.current.length });
|
|
511
|
+
return true;
|
|
512
|
+
},
|
|
513
|
+
[queueConfig, logger, updateMetrics]
|
|
514
|
+
);
|
|
515
|
+
const calculateRetryInterval = useCallback(
|
|
516
|
+
(retryCount) => {
|
|
517
|
+
const config = { ...DEFAULT_RETRY_CONFIG, ...retryConfig };
|
|
518
|
+
const {
|
|
519
|
+
intervals = [],
|
|
520
|
+
backoffMultiplier = 1.5,
|
|
521
|
+
maxBackoffTime = 3e4
|
|
522
|
+
} = config;
|
|
523
|
+
if (retryCount < intervals.length) {
|
|
524
|
+
return intervals[retryCount];
|
|
525
|
+
}
|
|
526
|
+
const baseInterval = intervals[intervals.length - 1] || 5e3;
|
|
527
|
+
const backoffTime = baseInterval * Math.pow(backoffMultiplier, retryCount - intervals.length + 1);
|
|
528
|
+
return Math.min(backoffTime, maxBackoffTime);
|
|
529
|
+
},
|
|
530
|
+
[retryConfig]
|
|
531
|
+
);
|
|
532
|
+
const startHeartbeat = useCallback(() => {
|
|
533
|
+
if (!heartbeatInterval || heartbeatInterval <= 0) return;
|
|
534
|
+
const sendPing = () => {
|
|
535
|
+
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
536
|
+
const pingTime = Date.now();
|
|
537
|
+
wsRef.current.send(
|
|
538
|
+
JSON.stringify({ type: "ping", timestamp: pingTime })
|
|
539
|
+
);
|
|
540
|
+
heartbeatTimeoutRef.current = setTimeout(() => {
|
|
541
|
+
logger.warn("Heartbeat timeout - no pong received");
|
|
542
|
+
if (wsRef.current) {
|
|
543
|
+
wsRef.current.close(4e3, "Heartbeat timeout");
|
|
544
|
+
}
|
|
545
|
+
}, heartbeatTimeout);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
if (heartbeatIntervalRef.current) {
|
|
549
|
+
clearInterval(heartbeatIntervalRef.current);
|
|
550
|
+
}
|
|
551
|
+
heartbeatIntervalRef.current = setInterval(sendPing, heartbeatInterval);
|
|
552
|
+
logger.debug("Heartbeat started");
|
|
553
|
+
}, [heartbeatInterval, heartbeatTimeout, logger]);
|
|
554
|
+
const stopHeartbeat = useCallback(() => {
|
|
555
|
+
if (heartbeatIntervalRef.current) {
|
|
556
|
+
clearInterval(heartbeatIntervalRef.current);
|
|
557
|
+
heartbeatIntervalRef.current = void 0;
|
|
558
|
+
}
|
|
559
|
+
if (heartbeatTimeoutRef.current) {
|
|
560
|
+
clearTimeout(heartbeatTimeoutRef.current);
|
|
561
|
+
heartbeatTimeoutRef.current = void 0;
|
|
562
|
+
}
|
|
563
|
+
logger.debug("Heartbeat stopped");
|
|
564
|
+
}, [logger]);
|
|
565
|
+
const cleanup = useCallback(() => {
|
|
566
|
+
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
|
|
567
|
+
wsRef.current.close(1e3, "Cleanup");
|
|
568
|
+
}
|
|
569
|
+
wsRef.current = void 0;
|
|
570
|
+
if (reconnectTimeoutRef.current) {
|
|
571
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
572
|
+
reconnectTimeoutRef.current = void 0;
|
|
573
|
+
}
|
|
574
|
+
stopHeartbeat();
|
|
575
|
+
pendingMessagesRef.current.forEach(({ reject, timeout }) => {
|
|
576
|
+
clearTimeout(timeout);
|
|
577
|
+
reject(new Error("Connection closed"));
|
|
578
|
+
});
|
|
579
|
+
pendingMessagesRef.current.clear();
|
|
580
|
+
loadChatRetryMapRef.current.forEach((retryState) => {
|
|
581
|
+
if (retryState.timeoutId) {
|
|
582
|
+
clearTimeout(retryState.timeoutId);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
loadChatRetryMapRef.current.clear();
|
|
586
|
+
}, [stopHeartbeat]);
|
|
587
|
+
const connect = useCallback(
|
|
588
|
+
async (userId) => {
|
|
589
|
+
if (!mountedRef.current) {
|
|
590
|
+
mountedRef.current = true;
|
|
591
|
+
}
|
|
592
|
+
if (!orgId) {
|
|
593
|
+
const error2 = {
|
|
594
|
+
code: "CONNECTION_FAILED",
|
|
595
|
+
message: "Cannot connect: orgId is undefined",
|
|
596
|
+
retryable: false,
|
|
597
|
+
timestamp: Date.now()
|
|
598
|
+
};
|
|
599
|
+
logger.error("Cannot connect: orgId is undefined");
|
|
600
|
+
setError(error2);
|
|
601
|
+
return Promise.reject(error2);
|
|
602
|
+
}
|
|
603
|
+
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
604
|
+
logger.debug("Already connected");
|
|
605
|
+
return Promise.resolve();
|
|
606
|
+
}
|
|
607
|
+
if (connectionState === "connecting" || connectionState === "reconnecting") {
|
|
608
|
+
logger.debug("Connection already in progress");
|
|
609
|
+
return Promise.resolve();
|
|
610
|
+
}
|
|
611
|
+
const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;
|
|
612
|
+
if (retryCountRef.current >= maxRetries && !intentionalDisconnectRef.current) {
|
|
613
|
+
const error2 = {
|
|
614
|
+
code: "CONNECTION_FAILED",
|
|
615
|
+
message: `Max retries (${maxRetries}) exceeded`,
|
|
616
|
+
retryable: false,
|
|
617
|
+
timestamp: Date.now()
|
|
618
|
+
};
|
|
619
|
+
setError(error2);
|
|
620
|
+
updateMetrics({ lastError: error2 });
|
|
621
|
+
return Promise.reject(error2);
|
|
622
|
+
}
|
|
623
|
+
cleanup();
|
|
624
|
+
setConnectionState(
|
|
625
|
+
retryCountRef.current > 0 ? "reconnecting" : "connecting"
|
|
626
|
+
);
|
|
627
|
+
intentionalDisconnectRef.current = false;
|
|
628
|
+
return new Promise((resolve, reject) => {
|
|
629
|
+
try {
|
|
630
|
+
const wsUrl = `${serverBaseUrl}?orgId=${orgId}&userId=${userId}&clientType=${clientType}&product=${product}`;
|
|
631
|
+
const connectionStartTime = Date.now();
|
|
632
|
+
logger.debug("Connecting to WebSocket:", wsUrl);
|
|
633
|
+
console.log(`\u23F3 Initiating WebSocket connection to ${serverBaseUrl}...`);
|
|
634
|
+
const ws = new WebSocket(wsUrl);
|
|
635
|
+
ws.onopen = () => {
|
|
636
|
+
if (!mountedRef.current) {
|
|
637
|
+
ws.close(1e3, "Component unmounted");
|
|
638
|
+
reject(new Error("Component unmounted"));
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const connectionTimeMs = Date.now() - connectionStartTime;
|
|
642
|
+
const connectionTimeSec = (connectionTimeMs / 1e3).toFixed(2);
|
|
643
|
+
logger.info("\u2705 WebSocket connected", {
|
|
644
|
+
userId,
|
|
645
|
+
retryCount: retryCountRef.current,
|
|
646
|
+
connectionTime: `${connectionTimeSec}s (${connectionTimeMs}ms)`
|
|
647
|
+
});
|
|
648
|
+
console.log(`\u{1F50C} WebSocket connection established in ${connectionTimeSec} seconds`);
|
|
649
|
+
setConnectionState("connected");
|
|
650
|
+
setError(void 0);
|
|
651
|
+
const wasReconnecting = retryCountRef.current > 0;
|
|
652
|
+
retryCountRef.current = 0;
|
|
653
|
+
updateMetrics({
|
|
654
|
+
connectedAt: Date.now(),
|
|
655
|
+
latency: connectionTimeMs,
|
|
656
|
+
reconnectCount: wasReconnecting ? metrics.reconnectCount + 1 : metrics.reconnectCount
|
|
657
|
+
});
|
|
658
|
+
while (messageQueueRef.current.length > 0 && ws.readyState === WebSocket.OPEN) {
|
|
659
|
+
const event = messageQueueRef.current.shift();
|
|
660
|
+
if (event) {
|
|
661
|
+
ws.send(JSON.stringify({ ...event, timestamp: Date.now() }));
|
|
662
|
+
updateMetrics({
|
|
663
|
+
messagesSent: metrics.messagesSent + 1,
|
|
664
|
+
messagesQueued: messageQueueRef.current.length
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
currentUserIdRef.current = userId;
|
|
669
|
+
if (currentChatKeyRef.current) {
|
|
670
|
+
if (!orgId) {
|
|
671
|
+
logger.error("Cannot resubscribe to chat: orgId is undefined");
|
|
672
|
+
} else {
|
|
673
|
+
logger.info(
|
|
674
|
+
"Resubscribing to chat after reconnection:",
|
|
675
|
+
currentChatKeyRef.current
|
|
676
|
+
);
|
|
677
|
+
const resubscribeEvent = {
|
|
678
|
+
type: "load_chat",
|
|
679
|
+
orgId,
|
|
680
|
+
chatKey: currentChatKeyRef.current,
|
|
681
|
+
userId,
|
|
682
|
+
timestamp: Date.now(),
|
|
683
|
+
data: {}
|
|
684
|
+
};
|
|
685
|
+
ws.send(JSON.stringify(resubscribeEvent));
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
startHeartbeat();
|
|
689
|
+
emit("connected", { userId, wasReconnecting });
|
|
690
|
+
resolve();
|
|
691
|
+
};
|
|
692
|
+
ws.onmessage = (event) => {
|
|
693
|
+
if (!mountedRef.current) return;
|
|
694
|
+
try {
|
|
695
|
+
const data = JSON.parse(event.data);
|
|
696
|
+
if (!isChatEvent(data)) {
|
|
697
|
+
logger.warn("Received invalid message format:", data);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
const chatEvent = data;
|
|
701
|
+
logger.debug("Message received:", chatEvent.type);
|
|
702
|
+
updateMetrics({
|
|
703
|
+
messagesReceived: metrics.messagesReceived + 1,
|
|
704
|
+
lastMessageAt: Date.now()
|
|
705
|
+
});
|
|
706
|
+
if (chatEvent.type === "pong") {
|
|
707
|
+
if (heartbeatTimeoutRef.current) {
|
|
708
|
+
clearTimeout(heartbeatTimeoutRef.current);
|
|
709
|
+
heartbeatTimeoutRef.current = void 0;
|
|
710
|
+
}
|
|
711
|
+
const latency = Date.now() - (chatEvent.timestamp || Date.now());
|
|
712
|
+
lastPongRef.current = Date.now();
|
|
713
|
+
updateMetrics({ latency });
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
switch (chatEvent.type) {
|
|
717
|
+
case "new_chat_created":
|
|
718
|
+
const newChatKey = chatEvent.data?.chatKey;
|
|
719
|
+
if (newChatKey) {
|
|
720
|
+
logger.info("New chat created with key:", newChatKey);
|
|
721
|
+
currentChatKeyRef.current = newChatKey;
|
|
722
|
+
if (chatCreationPromiseRef.current) {
|
|
723
|
+
chatCreationPromiseRef.current.resolve(newChatKey);
|
|
724
|
+
chatCreationPromiseRef.current = null;
|
|
725
|
+
}
|
|
726
|
+
if (!orgId) {
|
|
727
|
+
logger.error("Cannot send load_chat: orgId is undefined");
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const loadChatEvent = {
|
|
731
|
+
type: "load_chat",
|
|
732
|
+
orgId,
|
|
733
|
+
chatKey: newChatKey,
|
|
734
|
+
userId: currentUserIdRef.current || userId,
|
|
735
|
+
timestamp: Date.now(),
|
|
736
|
+
data: {}
|
|
737
|
+
};
|
|
738
|
+
ws.send(JSON.stringify(loadChatEvent));
|
|
739
|
+
}
|
|
740
|
+
break;
|
|
741
|
+
case "load_chat_response":
|
|
742
|
+
const chat = chatEvent.data?.chat;
|
|
743
|
+
if (chat && chat.key) {
|
|
744
|
+
logger.info("Chat loaded with key:", chat.key);
|
|
745
|
+
currentChatKeyRef.current = chat.key;
|
|
746
|
+
const retryState = loadChatRetryMapRef.current.get(chat.key);
|
|
747
|
+
if (retryState) {
|
|
748
|
+
if (retryState.timeoutId) {
|
|
749
|
+
clearTimeout(retryState.timeoutId);
|
|
750
|
+
}
|
|
751
|
+
loadChatRetryMapRef.current.delete(chat.key);
|
|
752
|
+
}
|
|
753
|
+
} else if (!chat) {
|
|
754
|
+
logger.warn("Chat load failed, clearing key");
|
|
755
|
+
currentChatKeyRef.current = void 0;
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
case "chat_ended":
|
|
759
|
+
logger.info("Chat ended, clearing key");
|
|
760
|
+
currentChatKeyRef.current = void 0;
|
|
761
|
+
break;
|
|
762
|
+
case "error":
|
|
763
|
+
const errorMessage = chatEvent.data?.message || "Unknown error";
|
|
764
|
+
logger.error("Received error from server:", errorMessage);
|
|
765
|
+
if (errorMessage.includes("nats: key not found") || errorMessage.includes("Failed to load chat")) {
|
|
766
|
+
const chatKeyFromError = currentChatKeyRef.current;
|
|
767
|
+
if (chatKeyFromError) {
|
|
768
|
+
const maxRetries2 = 5;
|
|
769
|
+
let retryState = loadChatRetryMapRef.current.get(chatKeyFromError);
|
|
770
|
+
if (!retryState) {
|
|
771
|
+
retryState = { retryCount: 0, timeoutId: null };
|
|
772
|
+
loadChatRetryMapRef.current.set(chatKeyFromError, retryState);
|
|
773
|
+
}
|
|
774
|
+
if (retryState.retryCount < maxRetries2) {
|
|
775
|
+
const delay = 200 * Math.pow(2, retryState.retryCount);
|
|
776
|
+
retryState.retryCount++;
|
|
777
|
+
logger.info(
|
|
778
|
+
`Chat load failed, retrying (${retryState.retryCount}/${maxRetries2}) in ${delay}ms...`,
|
|
779
|
+
chatKeyFromError
|
|
780
|
+
);
|
|
781
|
+
retryState.timeoutId = setTimeout(() => {
|
|
782
|
+
if (!wsRef.current || !mountedRef.current) return;
|
|
783
|
+
if (!orgId) {
|
|
784
|
+
logger.error("Cannot retry load_chat: orgId is undefined", chatKeyFromError);
|
|
785
|
+
loadChatRetryMapRef.current.delete(chatKeyFromError);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
logger.debug("Retrying load_chat:", chatKeyFromError);
|
|
789
|
+
const retryLoadEvent = {
|
|
790
|
+
type: "load_chat",
|
|
791
|
+
orgId,
|
|
792
|
+
chatKey: chatKeyFromError,
|
|
793
|
+
userId: currentUserIdRef.current || "",
|
|
794
|
+
timestamp: Date.now(),
|
|
795
|
+
data: {}
|
|
796
|
+
};
|
|
797
|
+
ws.send(JSON.stringify(retryLoadEvent));
|
|
798
|
+
}, delay);
|
|
799
|
+
} else {
|
|
800
|
+
logger.error("Max retries reached for loading chat:", chatKeyFromError);
|
|
801
|
+
loadChatRetryMapRef.current.delete(chatKeyFromError);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
const wsError = {
|
|
806
|
+
code: "NETWORK_ERROR",
|
|
807
|
+
message: errorMessage,
|
|
808
|
+
retryable: true,
|
|
809
|
+
timestamp: Date.now()
|
|
810
|
+
};
|
|
811
|
+
setError(wsError);
|
|
812
|
+
updateMetrics({ lastError: wsError });
|
|
813
|
+
break;
|
|
814
|
+
}
|
|
815
|
+
emit(chatEvent.type || "message", chatEvent);
|
|
816
|
+
if (onMessageRef.current) {
|
|
817
|
+
onMessageRef.current(chatEvent);
|
|
818
|
+
}
|
|
819
|
+
} catch (error2) {
|
|
820
|
+
logger.error("Failed to parse WebSocket message:", error2);
|
|
821
|
+
const parseError = {
|
|
822
|
+
code: "PARSE_ERROR",
|
|
823
|
+
message: "Failed to parse message",
|
|
824
|
+
retryable: false,
|
|
825
|
+
timestamp: Date.now()
|
|
826
|
+
};
|
|
827
|
+
setError(parseError);
|
|
828
|
+
updateMetrics({ lastError: parseError });
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
ws.onclose = (event) => {
|
|
832
|
+
if (!mountedRef.current) return;
|
|
833
|
+
logger.info("WebSocket closed", {
|
|
834
|
+
code: event.code,
|
|
835
|
+
reason: event.reason
|
|
836
|
+
});
|
|
837
|
+
setConnectionState("disconnected");
|
|
838
|
+
wsRef.current = void 0;
|
|
839
|
+
stopHeartbeat();
|
|
840
|
+
emit("disconnected", { code: event.code, reason: event.reason });
|
|
841
|
+
if (event.code !== 1e3 && !intentionalDisconnectRef.current && mountedRef.current) {
|
|
842
|
+
const retryInterval = calculateRetryInterval(
|
|
843
|
+
retryCountRef.current
|
|
844
|
+
);
|
|
845
|
+
retryCountRef.current++;
|
|
846
|
+
logger.info(
|
|
847
|
+
`Reconnecting in ${retryInterval}ms (attempt ${retryCountRef.current})`
|
|
848
|
+
);
|
|
849
|
+
if (reconnectTimeoutRef.current) {
|
|
850
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
851
|
+
}
|
|
852
|
+
reconnectTimeoutRef.current = setTimeout(() => {
|
|
853
|
+
connect(userId);
|
|
854
|
+
}, retryInterval);
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
ws.onerror = (error2) => {
|
|
858
|
+
logger.error("WebSocket error:", error2);
|
|
859
|
+
if (!mountedRef.current) return;
|
|
860
|
+
const wsError = {
|
|
861
|
+
code: "CONNECTION_FAILED",
|
|
862
|
+
message: "WebSocket connection failed",
|
|
863
|
+
retryable: true,
|
|
864
|
+
timestamp: Date.now()
|
|
865
|
+
};
|
|
866
|
+
setError(wsError);
|
|
867
|
+
updateMetrics({ lastError: wsError });
|
|
868
|
+
reject(wsError);
|
|
869
|
+
};
|
|
870
|
+
wsRef.current = ws;
|
|
871
|
+
} catch (error2) {
|
|
872
|
+
logger.error("Failed to create WebSocket:", error2);
|
|
873
|
+
const wsError = {
|
|
874
|
+
code: "CONNECTION_FAILED",
|
|
875
|
+
message: error2 instanceof Error ? error2.message : "Failed to create connection",
|
|
876
|
+
retryable: true,
|
|
877
|
+
timestamp: Date.now()
|
|
878
|
+
};
|
|
879
|
+
setError(wsError);
|
|
880
|
+
updateMetrics({ lastError: wsError });
|
|
881
|
+
reject(wsError);
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
},
|
|
885
|
+
[
|
|
886
|
+
serverBaseUrl,
|
|
887
|
+
orgId,
|
|
888
|
+
clientType,
|
|
889
|
+
product,
|
|
890
|
+
connectionState,
|
|
891
|
+
logger,
|
|
892
|
+
retryConfig,
|
|
893
|
+
metrics,
|
|
894
|
+
updateMetrics,
|
|
895
|
+
cleanup,
|
|
896
|
+
calculateRetryInterval,
|
|
897
|
+
startHeartbeat,
|
|
898
|
+
emit
|
|
899
|
+
]
|
|
900
|
+
);
|
|
901
|
+
const sendMessage = useCallback(
|
|
902
|
+
(event, overrideUserId) => {
|
|
903
|
+
return new Promise((resolve, reject) => {
|
|
904
|
+
if (!mountedRef.current) {
|
|
905
|
+
reject(new Error("Component not mounted"));
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const fullEvent = {
|
|
909
|
+
...event,
|
|
910
|
+
timestamp: Date.now()
|
|
911
|
+
};
|
|
912
|
+
const messageId = `${fullEvent.type}_${fullEvent.timestamp}_${Math.random()}`;
|
|
913
|
+
logger.debug("Sending message:", fullEvent.type);
|
|
914
|
+
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
|
|
915
|
+
if (addToQueue(fullEvent)) {
|
|
916
|
+
logger.debug("Message queued, attempting to connect");
|
|
917
|
+
if (connectionState === "disconnected" && overrideUserId) {
|
|
918
|
+
connect(overrideUserId).then(() => resolve()).catch(reject);
|
|
919
|
+
} else {
|
|
920
|
+
resolve();
|
|
921
|
+
}
|
|
922
|
+
} else {
|
|
923
|
+
reject(new Error("Message queue full"));
|
|
924
|
+
}
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
try {
|
|
928
|
+
wsRef.current.send(JSON.stringify(fullEvent));
|
|
929
|
+
updateMetrics({ messagesSent: metrics.messagesSent + 1 });
|
|
930
|
+
logger.debug("Message sent successfully");
|
|
931
|
+
resolve();
|
|
932
|
+
} catch (error2) {
|
|
933
|
+
logger.error("Failed to send message:", error2);
|
|
934
|
+
if (addToQueue(fullEvent)) {
|
|
935
|
+
resolve();
|
|
936
|
+
} else {
|
|
937
|
+
const sendError = {
|
|
938
|
+
code: "SEND_FAILED",
|
|
939
|
+
message: error2 instanceof Error ? error2.message : "Failed to send message",
|
|
940
|
+
retryable: true,
|
|
941
|
+
timestamp: Date.now()
|
|
942
|
+
};
|
|
943
|
+
setError(sendError);
|
|
944
|
+
updateMetrics({ lastError: sendError });
|
|
945
|
+
reject(sendError);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
},
|
|
950
|
+
[connectionState, connect, addToQueue, logger, metrics, updateMetrics]
|
|
951
|
+
);
|
|
952
|
+
const startNewChat = useCallback(
|
|
953
|
+
(userId, data) => {
|
|
954
|
+
return new Promise((resolve, reject) => {
|
|
955
|
+
if (!userId) {
|
|
956
|
+
reject(new Error("User ID is required"));
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
logger.info("Requesting new chat from server with userId:", userId);
|
|
960
|
+
setStartTime(/* @__PURE__ */ new Date());
|
|
961
|
+
chatCreationPromiseRef.current = { resolve, reject };
|
|
962
|
+
sendMessage(
|
|
963
|
+
{
|
|
964
|
+
type: "new_chat",
|
|
965
|
+
orgId,
|
|
966
|
+
chatKey: "",
|
|
967
|
+
// Server will generate
|
|
968
|
+
userId,
|
|
969
|
+
data: data ?? {}
|
|
970
|
+
},
|
|
971
|
+
userId
|
|
972
|
+
).catch((error2) => {
|
|
973
|
+
chatCreationPromiseRef.current = null;
|
|
974
|
+
reject(error2);
|
|
975
|
+
});
|
|
976
|
+
setTimeout(() => {
|
|
977
|
+
if (chatCreationPromiseRef.current) {
|
|
978
|
+
chatCreationPromiseRef.current = null;
|
|
979
|
+
reject(new Error("Chat creation timed out"));
|
|
980
|
+
}
|
|
981
|
+
}, 3e4);
|
|
982
|
+
});
|
|
983
|
+
},
|
|
984
|
+
[sendMessage, orgId, logger]
|
|
985
|
+
);
|
|
986
|
+
const disconnect = useCallback(
|
|
987
|
+
(intentional = true) => {
|
|
988
|
+
logger.info("Disconnecting WebSocket", { intentional });
|
|
989
|
+
intentionalDisconnectRef.current = intentional;
|
|
990
|
+
cleanup();
|
|
991
|
+
setConnectionState("disconnected");
|
|
992
|
+
messageQueueRef.current = [];
|
|
993
|
+
retryCountRef.current = 0;
|
|
994
|
+
mountedRef.current = false;
|
|
995
|
+
currentChatKeyRef.current = void 0;
|
|
996
|
+
currentUserIdRef.current = void 0;
|
|
997
|
+
},
|
|
998
|
+
[cleanup, logger]
|
|
999
|
+
);
|
|
1000
|
+
const clearError = useCallback(() => {
|
|
1001
|
+
setError(void 0);
|
|
1002
|
+
}, []);
|
|
1003
|
+
useEffect(() => {
|
|
1004
|
+
mountedRef.current = true;
|
|
1005
|
+
return () => {
|
|
1006
|
+
mountedRef.current = false;
|
|
1007
|
+
disconnect(true);
|
|
1008
|
+
};
|
|
1009
|
+
}, []);
|
|
1010
|
+
return {
|
|
1011
|
+
connectionState,
|
|
1012
|
+
isConnected,
|
|
1013
|
+
sendMessage,
|
|
1014
|
+
error,
|
|
1015
|
+
connect,
|
|
1016
|
+
startNewChat,
|
|
1017
|
+
startTime,
|
|
1018
|
+
disconnect,
|
|
1019
|
+
metrics,
|
|
1020
|
+
on,
|
|
1021
|
+
off,
|
|
1022
|
+
clearError
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
// hooks/use-websocket-chat-admin.ts
|
|
1027
|
+
var useWebSocketChatAdmin = ({
|
|
1028
|
+
serverBaseUrl,
|
|
1029
|
+
orgId,
|
|
1030
|
+
product
|
|
1031
|
+
}) => {
|
|
1032
|
+
const [chats, setChats] = useState2(/* @__PURE__ */ new Map());
|
|
1033
|
+
const [selectedChat, setSelectedChat] = useState2(void 0);
|
|
1034
|
+
const handleMessage = useCallback2(
|
|
1035
|
+
(chatEvent) => {
|
|
1036
|
+
switch (chatEvent.type) {
|
|
1037
|
+
case "message":
|
|
1038
|
+
if (!selectedChat || !chatEvent.message) return;
|
|
1039
|
+
setChats((prev) => {
|
|
1040
|
+
const newMap = new Map(prev);
|
|
1041
|
+
newMap.set(selectedChat.key, {
|
|
1042
|
+
...selectedChat,
|
|
1043
|
+
messages: [...selectedChat.messages, chatEvent.message]
|
|
1044
|
+
});
|
|
1045
|
+
return newMap;
|
|
1046
|
+
});
|
|
1047
|
+
setSelectedChat((prev) => {
|
|
1048
|
+
if (!prev) return prev;
|
|
1049
|
+
return {
|
|
1050
|
+
...prev,
|
|
1051
|
+
messages: [...prev.messages, chatEvent.message]
|
|
1052
|
+
};
|
|
1053
|
+
});
|
|
1054
|
+
break;
|
|
1055
|
+
case "list_chats":
|
|
1056
|
+
const chatList = chatEvent.data?.chats;
|
|
1057
|
+
if (!chatList) return;
|
|
1058
|
+
setChats(new Map(chatList.map((chat) => [chat.key, chat])));
|
|
1059
|
+
break;
|
|
1060
|
+
case "chat_updated":
|
|
1061
|
+
const updatedChat = chatEvent.data?.chat?.value;
|
|
1062
|
+
if (updatedChat) {
|
|
1063
|
+
setChats((prev) => new Map(prev).set(updatedChat.key, updatedChat));
|
|
1064
|
+
}
|
|
1065
|
+
break;
|
|
1066
|
+
case "chat_removed":
|
|
1067
|
+
const chatKey = chatEvent.data?.chatKey?.value;
|
|
1068
|
+
if (chatKey) {
|
|
1069
|
+
setChats((prev) => {
|
|
1070
|
+
const newMap = new Map(prev);
|
|
1071
|
+
newMap.delete(chatKey);
|
|
1072
|
+
return newMap;
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
break;
|
|
1076
|
+
case "load_chat":
|
|
1077
|
+
const history = chatEvent.data?.chat?.value;
|
|
1078
|
+
if (history) {
|
|
1079
|
+
setChats((prev) => {
|
|
1080
|
+
const existingChat = prev.get(history.key);
|
|
1081
|
+
if (!existingChat) return prev;
|
|
1082
|
+
return new Map(prev).set(history.key, {
|
|
1083
|
+
...existingChat,
|
|
1084
|
+
messages: history.messages
|
|
1085
|
+
});
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
[selectedChat]
|
|
1092
|
+
);
|
|
1093
|
+
const base = useWebSocketChatBase({
|
|
1094
|
+
serverBaseUrl,
|
|
1095
|
+
orgId,
|
|
1096
|
+
clientType: "humanAgent",
|
|
1097
|
+
onMessage: handleMessage,
|
|
1098
|
+
product
|
|
1099
|
+
});
|
|
1100
|
+
const selectChat = useCallback2(
|
|
1101
|
+
(chatKey) => {
|
|
1102
|
+
const chat = chats.get(chatKey);
|
|
1103
|
+
if (!chat) {
|
|
1104
|
+
console.error("Unable to select chat", chatKey);
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
setSelectedChat(chat);
|
|
1108
|
+
},
|
|
1109
|
+
[chats, orgId, base.sendMessage]
|
|
1110
|
+
);
|
|
1111
|
+
const addUserToChat = useCallback2(
|
|
1112
|
+
(orgId2, chatKey, user) => {
|
|
1113
|
+
base.sendMessage({
|
|
1114
|
+
type: "human_agent_joined",
|
|
1115
|
+
orgId: orgId2,
|
|
1116
|
+
chatKey,
|
|
1117
|
+
userId: user.email,
|
|
1118
|
+
data: { user }
|
|
1119
|
+
});
|
|
1120
|
+
setChats((prev) => {
|
|
1121
|
+
const newMap = new Map(prev);
|
|
1122
|
+
const chat = newMap.get(chatKey);
|
|
1123
|
+
if (!chat) return prev;
|
|
1124
|
+
newMap.set(chatKey, {
|
|
1125
|
+
...chat,
|
|
1126
|
+
humanAgentEngaged: user.role === ChatRoleHumanAgent,
|
|
1127
|
+
users: [...chat?.users ?? [], user]
|
|
1128
|
+
});
|
|
1129
|
+
return newMap;
|
|
1130
|
+
});
|
|
1131
|
+
setSelectedChat((prev) => {
|
|
1132
|
+
if (!prev) return prev;
|
|
1133
|
+
return {
|
|
1134
|
+
...prev,
|
|
1135
|
+
humanAgentEngaged: user.role === ChatRoleHumanAgent,
|
|
1136
|
+
users: [...prev.users ?? [], user]
|
|
1137
|
+
};
|
|
1138
|
+
});
|
|
1139
|
+
},
|
|
1140
|
+
[base.sendMessage]
|
|
1141
|
+
);
|
|
1142
|
+
const removeUserFromChat = useCallback2(
|
|
1143
|
+
(orgId2, chatKey, userId) => {
|
|
1144
|
+
const chat = chats.get(chatKey);
|
|
1145
|
+
if (!chat) return;
|
|
1146
|
+
const user = chat.users?.find((u) => u.id === userId);
|
|
1147
|
+
if (!user) return;
|
|
1148
|
+
base.sendMessage({
|
|
1149
|
+
type: "human_agent_left",
|
|
1150
|
+
orgId: orgId2,
|
|
1151
|
+
chatKey,
|
|
1152
|
+
userId,
|
|
1153
|
+
data: { user }
|
|
1154
|
+
});
|
|
1155
|
+
setChats((prev) => {
|
|
1156
|
+
const newMap = new Map(prev);
|
|
1157
|
+
const chat2 = newMap.get(chatKey);
|
|
1158
|
+
if (!chat2) return prev;
|
|
1159
|
+
newMap.set(chatKey, {
|
|
1160
|
+
...chat2,
|
|
1161
|
+
humanAgentEngaged: false,
|
|
1162
|
+
users: chat2.users?.filter((u) => u.id !== userId)
|
|
1163
|
+
});
|
|
1164
|
+
return newMap;
|
|
1165
|
+
});
|
|
1166
|
+
},
|
|
1167
|
+
[chats, base.sendMessage]
|
|
1168
|
+
);
|
|
1169
|
+
const blockUser = useCallback2(
|
|
1170
|
+
(orgId2, chatKey, userId) => {
|
|
1171
|
+
base.sendMessage({
|
|
1172
|
+
type: "block_user",
|
|
1173
|
+
orgId: orgId2,
|
|
1174
|
+
chatKey,
|
|
1175
|
+
userId
|
|
1176
|
+
});
|
|
1177
|
+
},
|
|
1178
|
+
[base.sendMessage]
|
|
1179
|
+
);
|
|
1180
|
+
return {
|
|
1181
|
+
...base,
|
|
1182
|
+
chats,
|
|
1183
|
+
selectedChat,
|
|
1184
|
+
selectChat,
|
|
1185
|
+
addUserToChat,
|
|
1186
|
+
removeUserFromChat,
|
|
1187
|
+
blockUser
|
|
1188
|
+
};
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
// hooks/use-websocket-chat-customer.ts
|
|
1192
|
+
import { useCallback as useCallback3, useState as useState3 } from "react";
|
|
1193
|
+
var useWebSocketChatCustomer = ({
|
|
1194
|
+
serverBaseUrl,
|
|
1195
|
+
orgId,
|
|
1196
|
+
chatKey,
|
|
1197
|
+
product
|
|
1198
|
+
}) => {
|
|
1199
|
+
const [currentChat, setCurrentChat] = useState3(void 0);
|
|
1200
|
+
const handleMessage = useCallback3((chatEvent) => {
|
|
1201
|
+
console.log("Received event:", chatEvent.type);
|
|
1202
|
+
switch (chatEvent.type) {
|
|
1203
|
+
case "message":
|
|
1204
|
+
if (!chatEvent.message) return;
|
|
1205
|
+
console.log(
|
|
1206
|
+
"got message:",
|
|
1207
|
+
chatEvent.message.role,
|
|
1208
|
+
":",
|
|
1209
|
+
chatEvent.message.content
|
|
1210
|
+
);
|
|
1211
|
+
setCurrentChat((prev) => {
|
|
1212
|
+
if (!prev) return prev;
|
|
1213
|
+
return {
|
|
1214
|
+
...prev,
|
|
1215
|
+
messages: [...prev.messages, chatEvent.message]
|
|
1216
|
+
};
|
|
1217
|
+
});
|
|
1218
|
+
break;
|
|
1219
|
+
case "chat_updated":
|
|
1220
|
+
const chat = chatEvent.data?.chat?.value;
|
|
1221
|
+
if (chat) {
|
|
1222
|
+
setCurrentChat(chat);
|
|
1223
|
+
}
|
|
1224
|
+
break;
|
|
1225
|
+
case "load_chat":
|
|
1226
|
+
const history = chatEvent.data?.chat;
|
|
1227
|
+
if (!history) return;
|
|
1228
|
+
setCurrentChat(history);
|
|
1229
|
+
break;
|
|
1230
|
+
default:
|
|
1231
|
+
break;
|
|
1232
|
+
}
|
|
1233
|
+
}, []);
|
|
1234
|
+
const base = useWebSocketChatBase({
|
|
1235
|
+
serverBaseUrl,
|
|
1236
|
+
orgId,
|
|
1237
|
+
clientType: "customer",
|
|
1238
|
+
onMessage: handleMessage,
|
|
1239
|
+
product
|
|
1240
|
+
});
|
|
1241
|
+
return {
|
|
1242
|
+
...base,
|
|
1243
|
+
chatKey,
|
|
1244
|
+
title: currentChat?.title,
|
|
1245
|
+
messages: currentChat?.messages ?? [],
|
|
1246
|
+
users: currentChat?.users ?? [],
|
|
1247
|
+
isWaiting: currentChat?.isWaiting ?? false,
|
|
1248
|
+
isWaitingForAgent: currentChat?.isWaitingForAgent ?? false,
|
|
1249
|
+
aiEngaged: currentChat?.aiEngaged ?? false,
|
|
1250
|
+
humanAgentEngaged: currentChat?.humanAgentEngaged ?? false,
|
|
1251
|
+
metadata: currentChat?.metadata ?? {},
|
|
1252
|
+
status: currentChat?.status
|
|
1253
|
+
};
|
|
1254
|
+
};
|
|
1255
|
+
|
|
1256
|
+
// context/websocket-chat-admin-context.tsx
|
|
390
1257
|
import { jsx } from "react/jsx-runtime";
|
|
391
1258
|
var WebSocketChatAdminContext = createContext(void 0);
|
|
392
1259
|
function WebSocketChatAdminProvider(props) {
|
|
@@ -416,10 +1283,10 @@ var AdminChatInput = ({
|
|
|
416
1283
|
}) => {
|
|
417
1284
|
const { sendMessage } = useWebSocketChatAdminContext();
|
|
418
1285
|
const { user, selectedOrgId } = useUserContext();
|
|
419
|
-
const [input, setInput] =
|
|
420
|
-
const [isUploading, setIsUploading] =
|
|
421
|
-
const [isSending, setIsSending] =
|
|
422
|
-
const fileInputRef =
|
|
1286
|
+
const [input, setInput] = useState4("");
|
|
1287
|
+
const [isUploading, setIsUploading] = useState4(false);
|
|
1288
|
+
const [isSending, setIsSending] = useState4(false);
|
|
1289
|
+
const fileInputRef = useRef2(null);
|
|
423
1290
|
const MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
424
1291
|
const handleSend = async () => {
|
|
425
1292
|
if (!input.trim() && !isUploading || isSending) return;
|
|
@@ -799,15 +1666,15 @@ var ChatHeader = () => {
|
|
|
799
1666
|
// components/customer/chat-input.tsx
|
|
800
1667
|
import { useUserContext as useUserContext3 } from "@elqnt/auth";
|
|
801
1668
|
import KSUID2 from "ksuid";
|
|
802
|
-
import { useRef as
|
|
1669
|
+
import { useRef as useRef3, useState as useState5 } from "react";
|
|
803
1670
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
804
1671
|
var ChatInput = ({ onFileUpload }) => {
|
|
805
1672
|
const { sendMessage, chatKey } = useWebSocketChatCustomerContext();
|
|
806
1673
|
const { user, selectedOrgId } = useUserContext3();
|
|
807
|
-
const [input, setInput] =
|
|
808
|
-
const [isUploading, setIsUploading] =
|
|
809
|
-
const [isSending, setIsSending] =
|
|
810
|
-
const fileInputRef =
|
|
1674
|
+
const [input, setInput] = useState5("");
|
|
1675
|
+
const [isUploading, setIsUploading] = useState5(false);
|
|
1676
|
+
const [isSending, setIsSending] = useState5(false);
|
|
1677
|
+
const fileInputRef = useRef3(null);
|
|
811
1678
|
const MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
812
1679
|
const handleSend = async () => {
|
|
813
1680
|
if (!input.trim() && !isUploading || isSending) return;
|
|
@@ -932,7 +1799,7 @@ var ChatInput = ({ onFileUpload }) => {
|
|
|
932
1799
|
};
|
|
933
1800
|
|
|
934
1801
|
// components/customer/chat-messages.tsx
|
|
935
|
-
import { useEffect, useRef as
|
|
1802
|
+
import { useEffect as useEffect2, useRef as useRef4 } from "react";
|
|
936
1803
|
|
|
937
1804
|
// ../../node_modules/date-fns/constants.js
|
|
938
1805
|
var daysInYear = 365.2425;
|
|
@@ -2629,11 +3496,11 @@ var ChatMessages = ({
|
|
|
2629
3496
|
onRetry,
|
|
2630
3497
|
messages
|
|
2631
3498
|
}) => {
|
|
2632
|
-
const messageEndRef =
|
|
3499
|
+
const messageEndRef = useRef4(null);
|
|
2633
3500
|
const scrollToBottom = () => {
|
|
2634
3501
|
messageEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2635
3502
|
};
|
|
2636
|
-
|
|
3503
|
+
useEffect2(() => {
|
|
2637
3504
|
scrollToBottom();
|
|
2638
3505
|
}, [messages]);
|
|
2639
3506
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -2677,12 +3544,12 @@ var ChatTypingIndicator = ({
|
|
|
2677
3544
|
|
|
2678
3545
|
// components/customer/generic-chat-widget.tsx
|
|
2679
3546
|
import { Alert } from "@elqnt/react";
|
|
2680
|
-
import { useState as
|
|
3547
|
+
import { useState as useState6 } from "react";
|
|
2681
3548
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2682
3549
|
var GenericChatWidget = ({
|
|
2683
3550
|
onFileUpload
|
|
2684
3551
|
}) => {
|
|
2685
|
-
const [typingUsers] =
|
|
3552
|
+
const [typingUsers] = useState6(/* @__PURE__ */ new Set());
|
|
2686
3553
|
const { error, messages } = useWebSocketChatCustomerContext();
|
|
2687
3554
|
const handleRetry = (messageId) => {
|
|
2688
3555
|
};
|