@elqnt/chat 1.0.8 → 1.0.11
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.js +345 -8
- package/dist/hooks/use-websocket-chat-admin.js.map +1 -1
- package/dist/hooks/use-websocket-chat-admin.mjs +345 -8
- package/dist/hooks/use-websocket-chat-admin.mjs.map +1 -1
- package/dist/hooks/use-websocket-chat-base.d.mts +13 -2
- package/dist/hooks/use-websocket-chat-base.d.ts +13 -2
- package/dist/hooks/use-websocket-chat-base.js +345 -8
- package/dist/hooks/use-websocket-chat-base.js.map +1 -1
- package/dist/hooks/use-websocket-chat-base.mjs +345 -8
- package/dist/hooks/use-websocket-chat-base.mjs.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.js +345 -8
- package/dist/hooks/use-websocket-chat-customer.js.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.mjs +345 -8
- package/dist/hooks/use-websocket-chat-customer.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +354 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +351 -8
- package/dist/index.mjs.map +1 -1
- package/dist/models/index.d.mts +18 -7
- package/dist/models/index.d.ts +18 -7
- package/dist/models/index.js +9 -0
- package/dist/models/index.js.map +1 -1
- package/dist/models/index.mjs +6 -0
- package/dist/models/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ var DEFAULT_QUEUE_CONFIG = {
|
|
|
25
25
|
};
|
|
26
26
|
var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
|
|
27
27
|
var DEFAULT_HEARTBEAT_TIMEOUT = 5e3;
|
|
28
|
+
var DEFAULT_TRANSPORT = "websocket";
|
|
28
29
|
function isChatEvent(data) {
|
|
29
30
|
return data && typeof data === "object" && (typeof data.type === "string" || data.message);
|
|
30
31
|
}
|
|
@@ -39,7 +40,8 @@ var useWebSocketChatBase = ({
|
|
|
39
40
|
debug = false,
|
|
40
41
|
logger = createDefaultLogger(debug),
|
|
41
42
|
heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL,
|
|
42
|
-
heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT
|
|
43
|
+
heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT,
|
|
44
|
+
transport = DEFAULT_TRANSPORT
|
|
43
45
|
}) => {
|
|
44
46
|
const [connectionState, setConnectionState] = useState("disconnected");
|
|
45
47
|
const [error, setError] = useState(void 0);
|
|
@@ -49,9 +51,15 @@ var useWebSocketChatBase = ({
|
|
|
49
51
|
messagesSent: 0,
|
|
50
52
|
messagesReceived: 0,
|
|
51
53
|
messagesQueued: 0,
|
|
52
|
-
reconnectCount: 0
|
|
54
|
+
reconnectCount: 0,
|
|
55
|
+
transportType: transport
|
|
53
56
|
});
|
|
54
57
|
const wsRef = useRef(void 0);
|
|
58
|
+
const sseRef = useRef(void 0);
|
|
59
|
+
const transportRef = useRef(transport);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
transportRef.current = transport;
|
|
62
|
+
}, [transport]);
|
|
55
63
|
const reconnectTimeoutRef = useRef(void 0);
|
|
56
64
|
const retryCountRef = useRef(0);
|
|
57
65
|
const messageQueueRef = useRef([]);
|
|
@@ -181,6 +189,10 @@ var useWebSocketChatBase = ({
|
|
|
181
189
|
wsRef.current.close(1e3, "Cleanup");
|
|
182
190
|
}
|
|
183
191
|
wsRef.current = void 0;
|
|
192
|
+
if (sseRef.current) {
|
|
193
|
+
sseRef.current.close();
|
|
194
|
+
sseRef.current = void 0;
|
|
195
|
+
}
|
|
184
196
|
if (reconnectTimeoutRef.current) {
|
|
185
197
|
clearTimeout(reconnectTimeoutRef.current);
|
|
186
198
|
reconnectTimeoutRef.current = void 0;
|
|
@@ -198,6 +210,35 @@ var useWebSocketChatBase = ({
|
|
|
198
210
|
});
|
|
199
211
|
loadChatRetryMapRef.current.clear();
|
|
200
212
|
}, [stopHeartbeat]);
|
|
213
|
+
const getRestApiUrl = useCallback((endpoint) => {
|
|
214
|
+
const httpUrl = serverBaseUrl.replace(/^wss:/, "https:").replace(/^ws:/, "http:");
|
|
215
|
+
return `${httpUrl}/${endpoint}`;
|
|
216
|
+
}, [serverBaseUrl]);
|
|
217
|
+
const sendRestMessage = useCallback(
|
|
218
|
+
async (endpoint, body) => {
|
|
219
|
+
const url = getRestApiUrl(endpoint);
|
|
220
|
+
logger.debug(`SSE REST API call: POST ${endpoint}`, body);
|
|
221
|
+
try {
|
|
222
|
+
const response = await fetch(url, {
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: {
|
|
225
|
+
"Content-Type": "application/json"
|
|
226
|
+
},
|
|
227
|
+
body: JSON.stringify(body)
|
|
228
|
+
});
|
|
229
|
+
if (!response.ok) {
|
|
230
|
+
const errorText = await response.text();
|
|
231
|
+
throw new Error(`REST API error: ${response.status} - ${errorText}`);
|
|
232
|
+
}
|
|
233
|
+
const data = await response.json();
|
|
234
|
+
return data;
|
|
235
|
+
} catch (error2) {
|
|
236
|
+
logger.error(`SSE REST API error for ${endpoint}:`, error2);
|
|
237
|
+
throw error2;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
[getRestApiUrl, logger]
|
|
241
|
+
);
|
|
201
242
|
const connect = useCallback(
|
|
202
243
|
async (userId) => {
|
|
203
244
|
if (!mountedRef.current) {
|
|
@@ -215,7 +256,11 @@ var useWebSocketChatBase = ({
|
|
|
215
256
|
return Promise.reject(error2);
|
|
216
257
|
}
|
|
217
258
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
218
|
-
logger.debug("Already connected");
|
|
259
|
+
logger.debug("Already connected (WebSocket)");
|
|
260
|
+
return Promise.resolve();
|
|
261
|
+
}
|
|
262
|
+
if (sseRef.current?.readyState === EventSource.OPEN) {
|
|
263
|
+
logger.debug("Already connected (SSE)");
|
|
219
264
|
return Promise.resolve();
|
|
220
265
|
}
|
|
221
266
|
if (connectionState === "connecting" || connectionState === "reconnecting") {
|
|
@@ -241,8 +286,169 @@ var useWebSocketChatBase = ({
|
|
|
241
286
|
intentionalDisconnectRef.current = false;
|
|
242
287
|
return new Promise((resolve, reject) => {
|
|
243
288
|
try {
|
|
244
|
-
const wsUrl = `${serverBaseUrl}?orgId=${orgId}&userId=${userId}&clientType=${clientType}&product=${product}`;
|
|
245
289
|
const connectionStartTime = Date.now();
|
|
290
|
+
logger.info(`\u{1F504} Connecting with transport: ${transportRef.current}`);
|
|
291
|
+
if (transportRef.current === "sse") {
|
|
292
|
+
const sseUrl = getRestApiUrl(`stream?orgId=${orgId}&userId=${userId}&clientType=${clientType}&chatId=${currentChatKeyRef.current || ""}`);
|
|
293
|
+
logger.debug("Connecting to SSE:", sseUrl);
|
|
294
|
+
console.log(`\u23F3 Initiating SSE connection to ${serverBaseUrl}...`);
|
|
295
|
+
const eventSource = new EventSource(sseUrl);
|
|
296
|
+
eventSource.onopen = () => {
|
|
297
|
+
if (!mountedRef.current) {
|
|
298
|
+
eventSource.close();
|
|
299
|
+
reject(new Error("Component unmounted"));
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const connectionTimeMs = Date.now() - connectionStartTime;
|
|
303
|
+
const connectionTimeSec = (connectionTimeMs / 1e3).toFixed(2);
|
|
304
|
+
logger.info("\u2705 SSE connected", {
|
|
305
|
+
userId,
|
|
306
|
+
retryCount: retryCountRef.current,
|
|
307
|
+
connectionTime: `${connectionTimeSec}s (${connectionTimeMs}ms)`
|
|
308
|
+
});
|
|
309
|
+
console.log(`\u{1F50C} SSE connection established in ${connectionTimeSec} seconds`);
|
|
310
|
+
setConnectionState("connected");
|
|
311
|
+
setError(void 0);
|
|
312
|
+
const wasReconnecting = retryCountRef.current > 0;
|
|
313
|
+
retryCountRef.current = 0;
|
|
314
|
+
updateMetrics({
|
|
315
|
+
connectedAt: Date.now(),
|
|
316
|
+
latency: connectionTimeMs,
|
|
317
|
+
transportType: "sse",
|
|
318
|
+
reconnectCount: wasReconnecting ? metrics.reconnectCount + 1 : metrics.reconnectCount
|
|
319
|
+
});
|
|
320
|
+
currentUserIdRef.current = userId;
|
|
321
|
+
if (currentChatKeyRef.current) {
|
|
322
|
+
logger.info("Loading chat after SSE reconnection:", currentChatKeyRef.current);
|
|
323
|
+
sendRestMessage("load", {
|
|
324
|
+
orgId,
|
|
325
|
+
chatKey: currentChatKeyRef.current,
|
|
326
|
+
userId
|
|
327
|
+
}).then((response) => {
|
|
328
|
+
if (response.success && response.data?.chat) {
|
|
329
|
+
const chatEvent = {
|
|
330
|
+
type: "load_chat_response",
|
|
331
|
+
orgId,
|
|
332
|
+
chatKey: currentChatKeyRef.current,
|
|
333
|
+
userId,
|
|
334
|
+
timestamp: Date.now(),
|
|
335
|
+
data: response.data
|
|
336
|
+
};
|
|
337
|
+
emit("load_chat_response", chatEvent);
|
|
338
|
+
if (onMessageRef.current) {
|
|
339
|
+
onMessageRef.current(chatEvent);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}).catch((err) => {
|
|
343
|
+
logger.error("Failed to load chat after SSE reconnection:", err);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
emit("connected", { userId, wasReconnecting, transport: "sse" });
|
|
347
|
+
resolve();
|
|
348
|
+
};
|
|
349
|
+
const handleSSEMessage = (event) => {
|
|
350
|
+
if (!mountedRef.current) return;
|
|
351
|
+
try {
|
|
352
|
+
const data = JSON.parse(event.data);
|
|
353
|
+
if (!isChatEvent(data)) {
|
|
354
|
+
logger.warn("Received invalid SSE message format:", data);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const chatEvent = data;
|
|
358
|
+
logger.debug("SSE message received:", chatEvent.type);
|
|
359
|
+
updateMetrics({
|
|
360
|
+
messagesReceived: metrics.messagesReceived + 1,
|
|
361
|
+
lastMessageAt: Date.now()
|
|
362
|
+
});
|
|
363
|
+
switch (chatEvent.type) {
|
|
364
|
+
case "new_chat_created":
|
|
365
|
+
const newChatKey = chatEvent.data?.chatKey;
|
|
366
|
+
if (newChatKey) {
|
|
367
|
+
logger.info("New chat created with key:", newChatKey);
|
|
368
|
+
currentChatKeyRef.current = newChatKey;
|
|
369
|
+
if (chatCreationPromiseRef.current) {
|
|
370
|
+
chatCreationPromiseRef.current.resolve(newChatKey);
|
|
371
|
+
chatCreationPromiseRef.current = null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
break;
|
|
375
|
+
case "load_chat_response":
|
|
376
|
+
const chat = chatEvent.data?.chat;
|
|
377
|
+
if (chat && chat.key) {
|
|
378
|
+
logger.info("Chat loaded with key:", chat.key);
|
|
379
|
+
currentChatKeyRef.current = chat.key;
|
|
380
|
+
}
|
|
381
|
+
break;
|
|
382
|
+
case "chat_ended":
|
|
383
|
+
logger.info("Chat ended, clearing key");
|
|
384
|
+
currentChatKeyRef.current = void 0;
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
emit(chatEvent.type || "message", chatEvent);
|
|
388
|
+
if (onMessageRef.current) {
|
|
389
|
+
onMessageRef.current(chatEvent);
|
|
390
|
+
}
|
|
391
|
+
} catch (error2) {
|
|
392
|
+
logger.error("Failed to parse SSE message:", error2);
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
eventSource.addEventListener("message", handleSSEMessage);
|
|
396
|
+
eventSource.addEventListener("reconnected", handleSSEMessage);
|
|
397
|
+
eventSource.addEventListener("typing", handleSSEMessage);
|
|
398
|
+
eventSource.addEventListener("stopped_typing", handleSSEMessage);
|
|
399
|
+
eventSource.addEventListener("waiting", handleSSEMessage);
|
|
400
|
+
eventSource.addEventListener("waiting_for_agent", handleSSEMessage);
|
|
401
|
+
eventSource.addEventListener("human_agent_joined", handleSSEMessage);
|
|
402
|
+
eventSource.addEventListener("human_agent_left", handleSSEMessage);
|
|
403
|
+
eventSource.addEventListener("chat_ended", handleSSEMessage);
|
|
404
|
+
eventSource.addEventListener("chat_updated", handleSSEMessage);
|
|
405
|
+
eventSource.addEventListener("load_chat_response", handleSSEMessage);
|
|
406
|
+
eventSource.addEventListener("new_chat_created", handleSSEMessage);
|
|
407
|
+
eventSource.addEventListener("error", handleSSEMessage);
|
|
408
|
+
eventSource.addEventListener("show_csat_survey", handleSSEMessage);
|
|
409
|
+
eventSource.addEventListener("csat_response", handleSSEMessage);
|
|
410
|
+
eventSource.addEventListener("user_suggested_actions", handleSSEMessage);
|
|
411
|
+
eventSource.addEventListener("agent_execution_started", handleSSEMessage);
|
|
412
|
+
eventSource.addEventListener("agent_execution_ended", handleSSEMessage);
|
|
413
|
+
eventSource.addEventListener("agent_context_update", handleSSEMessage);
|
|
414
|
+
eventSource.addEventListener("plan_pending_approval", handleSSEMessage);
|
|
415
|
+
eventSource.addEventListener("step_started", handleSSEMessage);
|
|
416
|
+
eventSource.addEventListener("step_completed", handleSSEMessage);
|
|
417
|
+
eventSource.addEventListener("step_failed", handleSSEMessage);
|
|
418
|
+
eventSource.addEventListener("plan_completed", handleSSEMessage);
|
|
419
|
+
eventSource.addEventListener("skills_changed", handleSSEMessage);
|
|
420
|
+
eventSource.addEventListener("summary_update", handleSSEMessage);
|
|
421
|
+
eventSource.onerror = (error2) => {
|
|
422
|
+
logger.error("SSE error:", error2);
|
|
423
|
+
if (!mountedRef.current) return;
|
|
424
|
+
if (eventSource.readyState === EventSource.CLOSED) {
|
|
425
|
+
const sseError = {
|
|
426
|
+
code: "CONNECTION_FAILED",
|
|
427
|
+
message: "SSE connection failed",
|
|
428
|
+
retryable: true,
|
|
429
|
+
timestamp: Date.now()
|
|
430
|
+
};
|
|
431
|
+
setError(sseError);
|
|
432
|
+
updateMetrics({ lastError: sseError });
|
|
433
|
+
setConnectionState("disconnected");
|
|
434
|
+
emit("disconnected", { reason: "SSE error" });
|
|
435
|
+
if (!intentionalDisconnectRef.current && mountedRef.current) {
|
|
436
|
+
const retryInterval = calculateRetryInterval(retryCountRef.current);
|
|
437
|
+
retryCountRef.current++;
|
|
438
|
+
logger.info(`SSE reconnecting in ${retryInterval}ms (attempt ${retryCountRef.current})`);
|
|
439
|
+
if (reconnectTimeoutRef.current) {
|
|
440
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
441
|
+
}
|
|
442
|
+
reconnectTimeoutRef.current = setTimeout(() => {
|
|
443
|
+
connect(userId);
|
|
444
|
+
}, retryInterval);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
sseRef.current = eventSource;
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
const wsUrl = `${serverBaseUrl}?orgId=${orgId}&userId=${userId}&clientType=${clientType}&product=${product}`;
|
|
246
452
|
logger.debug("Connecting to WebSocket:", wsUrl);
|
|
247
453
|
console.log(`\u23F3 Initiating WebSocket connection to ${serverBaseUrl}...`);
|
|
248
454
|
const ws = new WebSocket(wsUrl);
|
|
@@ -514,7 +720,7 @@ var useWebSocketChatBase = ({
|
|
|
514
720
|
);
|
|
515
721
|
const sendMessage = useCallback(
|
|
516
722
|
(event, overrideUserId) => {
|
|
517
|
-
return new Promise((resolve, reject) => {
|
|
723
|
+
return new Promise(async (resolve, reject) => {
|
|
518
724
|
if (!mountedRef.current) {
|
|
519
725
|
reject(new Error("Component not mounted"));
|
|
520
726
|
return;
|
|
@@ -523,8 +729,139 @@ var useWebSocketChatBase = ({
|
|
|
523
729
|
...event,
|
|
524
730
|
timestamp: Date.now()
|
|
525
731
|
};
|
|
526
|
-
const messageId = `${fullEvent.type}_${fullEvent.timestamp}_${Math.random()}`;
|
|
527
732
|
logger.debug("Sending message:", fullEvent.type);
|
|
733
|
+
if (transportRef.current === "sse") {
|
|
734
|
+
if (!sseRef.current || sseRef.current.readyState !== EventSource.OPEN) {
|
|
735
|
+
logger.debug("SSE not connected, attempting to connect");
|
|
736
|
+
if (connectionState === "disconnected" && overrideUserId) {
|
|
737
|
+
try {
|
|
738
|
+
await connect(overrideUserId);
|
|
739
|
+
} catch (error2) {
|
|
740
|
+
reject(error2);
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
} else {
|
|
744
|
+
reject(new Error("SSE not connected"));
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
try {
|
|
749
|
+
switch (fullEvent.type) {
|
|
750
|
+
case "message":
|
|
751
|
+
await sendRestMessage("send", {
|
|
752
|
+
orgId: fullEvent.orgId,
|
|
753
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
754
|
+
userId: fullEvent.userId,
|
|
755
|
+
message: fullEvent.message
|
|
756
|
+
});
|
|
757
|
+
break;
|
|
758
|
+
case "typing":
|
|
759
|
+
await sendRestMessage("typing", {
|
|
760
|
+
orgId: fullEvent.orgId,
|
|
761
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
762
|
+
userId: fullEvent.userId,
|
|
763
|
+
typing: true
|
|
764
|
+
});
|
|
765
|
+
break;
|
|
766
|
+
case "stopped_typing":
|
|
767
|
+
await sendRestMessage("typing", {
|
|
768
|
+
orgId: fullEvent.orgId,
|
|
769
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
770
|
+
userId: fullEvent.userId,
|
|
771
|
+
typing: false
|
|
772
|
+
});
|
|
773
|
+
break;
|
|
774
|
+
case "load_chat":
|
|
775
|
+
const loadResponse = await sendRestMessage("load", {
|
|
776
|
+
orgId: fullEvent.orgId,
|
|
777
|
+
chatKey: fullEvent.chatKey,
|
|
778
|
+
userId: fullEvent.userId
|
|
779
|
+
});
|
|
780
|
+
if (loadResponse.success && loadResponse.data?.chat) {
|
|
781
|
+
currentChatKeyRef.current = loadResponse.data.chat.key;
|
|
782
|
+
const chatEvent = {
|
|
783
|
+
type: "load_chat_response",
|
|
784
|
+
orgId: fullEvent.orgId,
|
|
785
|
+
chatKey: loadResponse.data.chat.key,
|
|
786
|
+
userId: fullEvent.userId,
|
|
787
|
+
timestamp: Date.now(),
|
|
788
|
+
data: loadResponse.data
|
|
789
|
+
};
|
|
790
|
+
emit("load_chat_response", chatEvent);
|
|
791
|
+
if (onMessageRef.current) {
|
|
792
|
+
onMessageRef.current(chatEvent);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
break;
|
|
796
|
+
case "new_chat":
|
|
797
|
+
const createResponse = await sendRestMessage("create", {
|
|
798
|
+
orgId: fullEvent.orgId,
|
|
799
|
+
userId: fullEvent.userId,
|
|
800
|
+
metadata: fullEvent.data
|
|
801
|
+
});
|
|
802
|
+
if (createResponse.success && createResponse.data?.chatKey) {
|
|
803
|
+
currentChatKeyRef.current = createResponse.data.chatKey;
|
|
804
|
+
const newChatEvent = {
|
|
805
|
+
type: "new_chat_created",
|
|
806
|
+
orgId: fullEvent.orgId,
|
|
807
|
+
chatKey: createResponse.data.chatKey,
|
|
808
|
+
userId: fullEvent.userId,
|
|
809
|
+
timestamp: Date.now(),
|
|
810
|
+
data: { chatKey: createResponse.data.chatKey }
|
|
811
|
+
};
|
|
812
|
+
emit("new_chat_created", newChatEvent);
|
|
813
|
+
if (onMessageRef.current) {
|
|
814
|
+
onMessageRef.current(newChatEvent);
|
|
815
|
+
}
|
|
816
|
+
if (chatCreationPromiseRef.current) {
|
|
817
|
+
chatCreationPromiseRef.current.resolve(createResponse.data.chatKey);
|
|
818
|
+
chatCreationPromiseRef.current = null;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
break;
|
|
822
|
+
case "end_chat":
|
|
823
|
+
await sendRestMessage("end", {
|
|
824
|
+
orgId: fullEvent.orgId,
|
|
825
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
826
|
+
userId: fullEvent.userId,
|
|
827
|
+
data: fullEvent.data
|
|
828
|
+
});
|
|
829
|
+
break;
|
|
830
|
+
case "human_agent_join":
|
|
831
|
+
await sendRestMessage("agent-join", {
|
|
832
|
+
orgId: fullEvent.orgId,
|
|
833
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
834
|
+
user: fullEvent.data?.user
|
|
835
|
+
});
|
|
836
|
+
break;
|
|
837
|
+
case "human_agent_leave":
|
|
838
|
+
await sendRestMessage("agent-leave", {
|
|
839
|
+
orgId: fullEvent.orgId,
|
|
840
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
841
|
+
user: fullEvent.data?.user
|
|
842
|
+
});
|
|
843
|
+
break;
|
|
844
|
+
default:
|
|
845
|
+
logger.warn("Unrecognized event type for SSE REST:", fullEvent.type);
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
updateMetrics({ messagesSent: metrics.messagesSent + 1 });
|
|
849
|
+
logger.debug("SSE REST message sent successfully");
|
|
850
|
+
resolve();
|
|
851
|
+
} catch (error2) {
|
|
852
|
+
logger.error("Failed to send SSE REST message:", error2);
|
|
853
|
+
const sendError = {
|
|
854
|
+
code: "SEND_FAILED",
|
|
855
|
+
message: error2 instanceof Error ? error2.message : "Failed to send message",
|
|
856
|
+
retryable: true,
|
|
857
|
+
timestamp: Date.now()
|
|
858
|
+
};
|
|
859
|
+
setError(sendError);
|
|
860
|
+
updateMetrics({ lastError: sendError });
|
|
861
|
+
reject(sendError);
|
|
862
|
+
}
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
528
865
|
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
|
|
529
866
|
if (addToQueue(fullEvent)) {
|
|
530
867
|
logger.debug("Message queued, attempting to connect");
|
|
@@ -561,7 +898,7 @@ var useWebSocketChatBase = ({
|
|
|
561
898
|
}
|
|
562
899
|
});
|
|
563
900
|
},
|
|
564
|
-
[connectionState, connect, addToQueue, logger, metrics, updateMetrics]
|
|
901
|
+
[connectionState, connect, addToQueue, logger, metrics, updateMetrics, sendRestMessage, emit]
|
|
565
902
|
);
|
|
566
903
|
const startNewChat = useCallback(
|
|
567
904
|
(userId, data) => {
|
|
@@ -599,7 +936,7 @@ var useWebSocketChatBase = ({
|
|
|
599
936
|
);
|
|
600
937
|
const disconnect = useCallback(
|
|
601
938
|
(intentional = true) => {
|
|
602
|
-
logger.info("Disconnecting
|
|
939
|
+
logger.info("Disconnecting", { intentional, transport: transportRef.current });
|
|
603
940
|
intentionalDisconnectRef.current = intentional;
|
|
604
941
|
cleanup();
|
|
605
942
|
setConnectionState("disconnected");
|