@elqnt/chat 1.0.9 → 1.0.12
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 +367 -8
- package/dist/hooks/use-websocket-chat-admin.js.map +1 -1
- package/dist/hooks/use-websocket-chat-admin.mjs +367 -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 +367 -8
- package/dist/hooks/use-websocket-chat-base.js.map +1 -1
- package/dist/hooks/use-websocket-chat-base.mjs +367 -8
- package/dist/hooks/use-websocket-chat-base.mjs.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.js +367 -8
- package/dist/hooks/use-websocket-chat-customer.js.map +1 -1
- package/dist/hooks/use-websocket-chat-customer.mjs +367 -8
- package/dist/hooks/use-websocket-chat-customer.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +367 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +367 -8
- package/dist/index.mjs.map +1 -1
- package/dist/models/index.d.mts +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js.map +1 -1
- package/dist/models/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -45,6 +45,7 @@ var DEFAULT_QUEUE_CONFIG = {
|
|
|
45
45
|
};
|
|
46
46
|
var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
|
|
47
47
|
var DEFAULT_HEARTBEAT_TIMEOUT = 5e3;
|
|
48
|
+
var DEFAULT_TRANSPORT = "websocket";
|
|
48
49
|
function isChatEvent(data) {
|
|
49
50
|
return data && typeof data === "object" && (typeof data.type === "string" || data.message);
|
|
50
51
|
}
|
|
@@ -59,7 +60,8 @@ var useWebSocketChatBase = ({
|
|
|
59
60
|
debug = false,
|
|
60
61
|
logger = createDefaultLogger(debug),
|
|
61
62
|
heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL,
|
|
62
|
-
heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT
|
|
63
|
+
heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT,
|
|
64
|
+
transport = DEFAULT_TRANSPORT
|
|
63
65
|
}) => {
|
|
64
66
|
const [connectionState, setConnectionState] = (0, import_react.useState)("disconnected");
|
|
65
67
|
const [error, setError] = (0, import_react.useState)(void 0);
|
|
@@ -69,9 +71,15 @@ var useWebSocketChatBase = ({
|
|
|
69
71
|
messagesSent: 0,
|
|
70
72
|
messagesReceived: 0,
|
|
71
73
|
messagesQueued: 0,
|
|
72
|
-
reconnectCount: 0
|
|
74
|
+
reconnectCount: 0,
|
|
75
|
+
transportType: transport
|
|
73
76
|
});
|
|
74
77
|
const wsRef = (0, import_react.useRef)(void 0);
|
|
78
|
+
const sseRef = (0, import_react.useRef)(void 0);
|
|
79
|
+
const transportRef = (0, import_react.useRef)(transport);
|
|
80
|
+
(0, import_react.useEffect)(() => {
|
|
81
|
+
transportRef.current = transport;
|
|
82
|
+
}, [transport]);
|
|
75
83
|
const reconnectTimeoutRef = (0, import_react.useRef)(void 0);
|
|
76
84
|
const retryCountRef = (0, import_react.useRef)(0);
|
|
77
85
|
const messageQueueRef = (0, import_react.useRef)([]);
|
|
@@ -201,6 +209,10 @@ var useWebSocketChatBase = ({
|
|
|
201
209
|
wsRef.current.close(1e3, "Cleanup");
|
|
202
210
|
}
|
|
203
211
|
wsRef.current = void 0;
|
|
212
|
+
if (sseRef.current) {
|
|
213
|
+
sseRef.current.close();
|
|
214
|
+
sseRef.current = void 0;
|
|
215
|
+
}
|
|
204
216
|
if (reconnectTimeoutRef.current) {
|
|
205
217
|
clearTimeout(reconnectTimeoutRef.current);
|
|
206
218
|
reconnectTimeoutRef.current = void 0;
|
|
@@ -218,6 +230,35 @@ var useWebSocketChatBase = ({
|
|
|
218
230
|
});
|
|
219
231
|
loadChatRetryMapRef.current.clear();
|
|
220
232
|
}, [stopHeartbeat]);
|
|
233
|
+
const getRestApiUrl = (0, import_react.useCallback)((endpoint) => {
|
|
234
|
+
const httpUrl = serverBaseUrl.replace(/^wss:/, "https:").replace(/^ws:/, "http:");
|
|
235
|
+
return `${httpUrl}/${endpoint}`;
|
|
236
|
+
}, [serverBaseUrl]);
|
|
237
|
+
const sendRestMessage = (0, import_react.useCallback)(
|
|
238
|
+
async (endpoint, body) => {
|
|
239
|
+
const url = getRestApiUrl(endpoint);
|
|
240
|
+
logger.debug(`SSE REST API call: POST ${endpoint}`, body);
|
|
241
|
+
try {
|
|
242
|
+
const response = await fetch(url, {
|
|
243
|
+
method: "POST",
|
|
244
|
+
headers: {
|
|
245
|
+
"Content-Type": "application/json"
|
|
246
|
+
},
|
|
247
|
+
body: JSON.stringify(body)
|
|
248
|
+
});
|
|
249
|
+
if (!response.ok) {
|
|
250
|
+
const errorText = await response.text();
|
|
251
|
+
throw new Error(`REST API error: ${response.status} - ${errorText}`);
|
|
252
|
+
}
|
|
253
|
+
const data = await response.json();
|
|
254
|
+
return data;
|
|
255
|
+
} catch (error2) {
|
|
256
|
+
logger.error(`SSE REST API error for ${endpoint}:`, error2);
|
|
257
|
+
throw error2;
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
[getRestApiUrl, logger]
|
|
261
|
+
);
|
|
221
262
|
const connect = (0, import_react.useCallback)(
|
|
222
263
|
async (userId) => {
|
|
223
264
|
if (!mountedRef.current) {
|
|
@@ -235,7 +276,11 @@ var useWebSocketChatBase = ({
|
|
|
235
276
|
return Promise.reject(error2);
|
|
236
277
|
}
|
|
237
278
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
238
|
-
logger.debug("Already connected");
|
|
279
|
+
logger.debug("Already connected (WebSocket)");
|
|
280
|
+
return Promise.resolve();
|
|
281
|
+
}
|
|
282
|
+
if (sseRef.current?.readyState === EventSource.OPEN) {
|
|
283
|
+
logger.debug("Already connected (SSE)");
|
|
239
284
|
return Promise.resolve();
|
|
240
285
|
}
|
|
241
286
|
if (connectionState === "connecting" || connectionState === "reconnecting") {
|
|
@@ -261,8 +306,169 @@ var useWebSocketChatBase = ({
|
|
|
261
306
|
intentionalDisconnectRef.current = false;
|
|
262
307
|
return new Promise((resolve, reject) => {
|
|
263
308
|
try {
|
|
264
|
-
const wsUrl = `${serverBaseUrl}?orgId=${orgId}&userId=${userId}&clientType=${clientType}&product=${product}`;
|
|
265
309
|
const connectionStartTime = Date.now();
|
|
310
|
+
logger.info(`\u{1F504} Connecting with transport: ${transportRef.current}`);
|
|
311
|
+
if (transportRef.current === "sse") {
|
|
312
|
+
const sseUrl = getRestApiUrl(`stream?orgId=${orgId}&userId=${userId}&clientType=${clientType}&chatId=${currentChatKeyRef.current || ""}`);
|
|
313
|
+
logger.debug("Connecting to SSE:", sseUrl);
|
|
314
|
+
console.log(`\u23F3 Initiating SSE connection to ${sseUrl}...`);
|
|
315
|
+
const eventSource = new EventSource(sseUrl);
|
|
316
|
+
eventSource.onopen = () => {
|
|
317
|
+
if (!mountedRef.current) {
|
|
318
|
+
eventSource.close();
|
|
319
|
+
reject(new Error("Component unmounted"));
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const connectionTimeMs = Date.now() - connectionStartTime;
|
|
323
|
+
const connectionTimeSec = (connectionTimeMs / 1e3).toFixed(2);
|
|
324
|
+
logger.info("\u2705 SSE connected", {
|
|
325
|
+
userId,
|
|
326
|
+
retryCount: retryCountRef.current,
|
|
327
|
+
connectionTime: `${connectionTimeSec}s (${connectionTimeMs}ms)`
|
|
328
|
+
});
|
|
329
|
+
console.log(`\u{1F50C} SSE connection established in ${connectionTimeSec} seconds`);
|
|
330
|
+
setConnectionState("connected");
|
|
331
|
+
setError(void 0);
|
|
332
|
+
const wasReconnecting = retryCountRef.current > 0;
|
|
333
|
+
retryCountRef.current = 0;
|
|
334
|
+
updateMetrics({
|
|
335
|
+
connectedAt: Date.now(),
|
|
336
|
+
latency: connectionTimeMs,
|
|
337
|
+
transportType: "sse",
|
|
338
|
+
reconnectCount: wasReconnecting ? metrics.reconnectCount + 1 : metrics.reconnectCount
|
|
339
|
+
});
|
|
340
|
+
currentUserIdRef.current = userId;
|
|
341
|
+
if (currentChatKeyRef.current) {
|
|
342
|
+
logger.info("Loading chat after SSE reconnection:", currentChatKeyRef.current);
|
|
343
|
+
sendRestMessage("load", {
|
|
344
|
+
orgId,
|
|
345
|
+
chatKey: currentChatKeyRef.current,
|
|
346
|
+
userId
|
|
347
|
+
}).then((response) => {
|
|
348
|
+
if (response.success && response.data?.chat) {
|
|
349
|
+
const chatEvent = {
|
|
350
|
+
type: "load_chat_response",
|
|
351
|
+
orgId,
|
|
352
|
+
chatKey: currentChatKeyRef.current,
|
|
353
|
+
userId,
|
|
354
|
+
timestamp: Date.now(),
|
|
355
|
+
data: response.data
|
|
356
|
+
};
|
|
357
|
+
emit("load_chat_response", chatEvent);
|
|
358
|
+
if (onMessageRef.current) {
|
|
359
|
+
onMessageRef.current(chatEvent);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}).catch((err) => {
|
|
363
|
+
logger.error("Failed to load chat after SSE reconnection:", err);
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
emit("connected", { userId, wasReconnecting, transport: "sse" });
|
|
367
|
+
resolve();
|
|
368
|
+
};
|
|
369
|
+
const handleSSEMessage = (event) => {
|
|
370
|
+
if (!mountedRef.current) return;
|
|
371
|
+
try {
|
|
372
|
+
const data = JSON.parse(event.data);
|
|
373
|
+
if (!isChatEvent(data)) {
|
|
374
|
+
logger.warn("Received invalid SSE message format:", data);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const chatEvent = data;
|
|
378
|
+
logger.debug("SSE message received:", chatEvent.type);
|
|
379
|
+
updateMetrics({
|
|
380
|
+
messagesReceived: metrics.messagesReceived + 1,
|
|
381
|
+
lastMessageAt: Date.now()
|
|
382
|
+
});
|
|
383
|
+
switch (chatEvent.type) {
|
|
384
|
+
case "new_chat_created":
|
|
385
|
+
const newChatKey = chatEvent.data?.chatKey;
|
|
386
|
+
if (newChatKey) {
|
|
387
|
+
logger.info("New chat created with key:", newChatKey);
|
|
388
|
+
currentChatKeyRef.current = newChatKey;
|
|
389
|
+
if (chatCreationPromiseRef.current) {
|
|
390
|
+
chatCreationPromiseRef.current.resolve(newChatKey);
|
|
391
|
+
chatCreationPromiseRef.current = null;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
case "load_chat_response":
|
|
396
|
+
const chat = chatEvent.data?.chat;
|
|
397
|
+
if (chat && chat.key) {
|
|
398
|
+
logger.info("Chat loaded with key:", chat.key);
|
|
399
|
+
currentChatKeyRef.current = chat.key;
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
case "chat_ended":
|
|
403
|
+
logger.info("Chat ended, clearing key");
|
|
404
|
+
currentChatKeyRef.current = void 0;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
emit(chatEvent.type || "message", chatEvent);
|
|
408
|
+
if (onMessageRef.current) {
|
|
409
|
+
onMessageRef.current(chatEvent);
|
|
410
|
+
}
|
|
411
|
+
} catch (error2) {
|
|
412
|
+
logger.error("Failed to parse SSE message:", error2);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
eventSource.addEventListener("message", handleSSEMessage);
|
|
416
|
+
eventSource.addEventListener("reconnected", handleSSEMessage);
|
|
417
|
+
eventSource.addEventListener("typing", handleSSEMessage);
|
|
418
|
+
eventSource.addEventListener("stopped_typing", handleSSEMessage);
|
|
419
|
+
eventSource.addEventListener("waiting", handleSSEMessage);
|
|
420
|
+
eventSource.addEventListener("waiting_for_agent", handleSSEMessage);
|
|
421
|
+
eventSource.addEventListener("human_agent_joined", handleSSEMessage);
|
|
422
|
+
eventSource.addEventListener("human_agent_left", handleSSEMessage);
|
|
423
|
+
eventSource.addEventListener("chat_ended", handleSSEMessage);
|
|
424
|
+
eventSource.addEventListener("chat_updated", handleSSEMessage);
|
|
425
|
+
eventSource.addEventListener("load_chat_response", handleSSEMessage);
|
|
426
|
+
eventSource.addEventListener("new_chat_created", handleSSEMessage);
|
|
427
|
+
eventSource.addEventListener("error", handleSSEMessage);
|
|
428
|
+
eventSource.addEventListener("show_csat_survey", handleSSEMessage);
|
|
429
|
+
eventSource.addEventListener("csat_response", handleSSEMessage);
|
|
430
|
+
eventSource.addEventListener("user_suggested_actions", handleSSEMessage);
|
|
431
|
+
eventSource.addEventListener("agent_execution_started", handleSSEMessage);
|
|
432
|
+
eventSource.addEventListener("agent_execution_ended", handleSSEMessage);
|
|
433
|
+
eventSource.addEventListener("agent_context_update", handleSSEMessage);
|
|
434
|
+
eventSource.addEventListener("plan_pending_approval", handleSSEMessage);
|
|
435
|
+
eventSource.addEventListener("step_started", handleSSEMessage);
|
|
436
|
+
eventSource.addEventListener("step_completed", handleSSEMessage);
|
|
437
|
+
eventSource.addEventListener("step_failed", handleSSEMessage);
|
|
438
|
+
eventSource.addEventListener("plan_completed", handleSSEMessage);
|
|
439
|
+
eventSource.addEventListener("skills_changed", handleSSEMessage);
|
|
440
|
+
eventSource.addEventListener("summary_update", handleSSEMessage);
|
|
441
|
+
eventSource.onerror = (error2) => {
|
|
442
|
+
logger.error("SSE error:", error2);
|
|
443
|
+
if (!mountedRef.current) return;
|
|
444
|
+
if (eventSource.readyState === EventSource.CLOSED) {
|
|
445
|
+
const sseError = {
|
|
446
|
+
code: "CONNECTION_FAILED",
|
|
447
|
+
message: "SSE connection failed",
|
|
448
|
+
retryable: true,
|
|
449
|
+
timestamp: Date.now()
|
|
450
|
+
};
|
|
451
|
+
setError(sseError);
|
|
452
|
+
updateMetrics({ lastError: sseError });
|
|
453
|
+
setConnectionState("disconnected");
|
|
454
|
+
emit("disconnected", { reason: "SSE error" });
|
|
455
|
+
if (!intentionalDisconnectRef.current && mountedRef.current) {
|
|
456
|
+
const retryInterval = calculateRetryInterval(retryCountRef.current);
|
|
457
|
+
retryCountRef.current++;
|
|
458
|
+
logger.info(`SSE reconnecting in ${retryInterval}ms (attempt ${retryCountRef.current})`);
|
|
459
|
+
if (reconnectTimeoutRef.current) {
|
|
460
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
461
|
+
}
|
|
462
|
+
reconnectTimeoutRef.current = setTimeout(() => {
|
|
463
|
+
connect(userId);
|
|
464
|
+
}, retryInterval);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
sseRef.current = eventSource;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const wsUrl = `${serverBaseUrl}?orgId=${orgId}&userId=${userId}&clientType=${clientType}&product=${product}`;
|
|
266
472
|
logger.debug("Connecting to WebSocket:", wsUrl);
|
|
267
473
|
console.log(`\u23F3 Initiating WebSocket connection to ${serverBaseUrl}...`);
|
|
268
474
|
const ws = new WebSocket(wsUrl);
|
|
@@ -534,7 +740,7 @@ var useWebSocketChatBase = ({
|
|
|
534
740
|
);
|
|
535
741
|
const sendMessage = (0, import_react.useCallback)(
|
|
536
742
|
(event, overrideUserId) => {
|
|
537
|
-
return new Promise((resolve, reject) => {
|
|
743
|
+
return new Promise(async (resolve, reject) => {
|
|
538
744
|
if (!mountedRef.current) {
|
|
539
745
|
reject(new Error("Component not mounted"));
|
|
540
746
|
return;
|
|
@@ -543,8 +749,161 @@ var useWebSocketChatBase = ({
|
|
|
543
749
|
...event,
|
|
544
750
|
timestamp: Date.now()
|
|
545
751
|
};
|
|
546
|
-
const messageId = `${fullEvent.type}_${fullEvent.timestamp}_${Math.random()}`;
|
|
547
752
|
logger.debug("Sending message:", fullEvent.type);
|
|
753
|
+
if (transportRef.current === "sse") {
|
|
754
|
+
if (!sseRef.current || sseRef.current.readyState !== EventSource.OPEN) {
|
|
755
|
+
logger.debug("SSE not connected, attempting to connect");
|
|
756
|
+
if (connectionState === "disconnected" && overrideUserId) {
|
|
757
|
+
try {
|
|
758
|
+
await connect(overrideUserId);
|
|
759
|
+
} catch (error2) {
|
|
760
|
+
reject(error2);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
} else {
|
|
764
|
+
reject(new Error("SSE not connected"));
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
try {
|
|
769
|
+
switch (fullEvent.type) {
|
|
770
|
+
case "message":
|
|
771
|
+
await sendRestMessage("send", {
|
|
772
|
+
orgId: fullEvent.orgId,
|
|
773
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
774
|
+
userId: fullEvent.userId,
|
|
775
|
+
message: fullEvent.message
|
|
776
|
+
});
|
|
777
|
+
break;
|
|
778
|
+
case "typing":
|
|
779
|
+
await sendRestMessage("typing", {
|
|
780
|
+
orgId: fullEvent.orgId,
|
|
781
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
782
|
+
userId: fullEvent.userId,
|
|
783
|
+
typing: true
|
|
784
|
+
});
|
|
785
|
+
break;
|
|
786
|
+
case "stopped_typing":
|
|
787
|
+
await sendRestMessage("typing", {
|
|
788
|
+
orgId: fullEvent.orgId,
|
|
789
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
790
|
+
userId: fullEvent.userId,
|
|
791
|
+
typing: false
|
|
792
|
+
});
|
|
793
|
+
break;
|
|
794
|
+
case "load_chat":
|
|
795
|
+
const loadResponse = await sendRestMessage("load", {
|
|
796
|
+
orgId: fullEvent.orgId,
|
|
797
|
+
chatKey: fullEvent.chatKey,
|
|
798
|
+
userId: fullEvent.userId
|
|
799
|
+
});
|
|
800
|
+
if (loadResponse.success && loadResponse.data?.chat) {
|
|
801
|
+
currentChatKeyRef.current = loadResponse.data.chat.key;
|
|
802
|
+
const chatEvent = {
|
|
803
|
+
type: "load_chat_response",
|
|
804
|
+
orgId: fullEvent.orgId,
|
|
805
|
+
chatKey: loadResponse.data.chat.key,
|
|
806
|
+
userId: fullEvent.userId,
|
|
807
|
+
timestamp: Date.now(),
|
|
808
|
+
data: loadResponse.data
|
|
809
|
+
};
|
|
810
|
+
emit("load_chat_response", chatEvent);
|
|
811
|
+
if (onMessageRef.current) {
|
|
812
|
+
onMessageRef.current(chatEvent);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
break;
|
|
816
|
+
case "new_chat":
|
|
817
|
+
const createResponse = await sendRestMessage("create", {
|
|
818
|
+
orgId: fullEvent.orgId,
|
|
819
|
+
userId: fullEvent.userId,
|
|
820
|
+
metadata: fullEvent.data
|
|
821
|
+
});
|
|
822
|
+
if (createResponse.success && createResponse.data?.chatKey) {
|
|
823
|
+
currentChatKeyRef.current = createResponse.data.chatKey;
|
|
824
|
+
const newChatEvent = {
|
|
825
|
+
type: "new_chat_created",
|
|
826
|
+
orgId: fullEvent.orgId,
|
|
827
|
+
chatKey: createResponse.data.chatKey,
|
|
828
|
+
userId: fullEvent.userId,
|
|
829
|
+
timestamp: Date.now(),
|
|
830
|
+
data: { chatKey: createResponse.data.chatKey }
|
|
831
|
+
};
|
|
832
|
+
emit("new_chat_created", newChatEvent);
|
|
833
|
+
if (onMessageRef.current) {
|
|
834
|
+
onMessageRef.current(newChatEvent);
|
|
835
|
+
}
|
|
836
|
+
if (chatCreationPromiseRef.current) {
|
|
837
|
+
chatCreationPromiseRef.current.resolve(createResponse.data.chatKey);
|
|
838
|
+
chatCreationPromiseRef.current = null;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
break;
|
|
842
|
+
case "end_chat":
|
|
843
|
+
await sendRestMessage("end", {
|
|
844
|
+
orgId: fullEvent.orgId,
|
|
845
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
846
|
+
userId: fullEvent.userId,
|
|
847
|
+
data: fullEvent.data
|
|
848
|
+
});
|
|
849
|
+
break;
|
|
850
|
+
case "human_agent_join":
|
|
851
|
+
await sendRestMessage("agent-join", {
|
|
852
|
+
orgId: fullEvent.orgId,
|
|
853
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
854
|
+
user: fullEvent.data?.user
|
|
855
|
+
});
|
|
856
|
+
break;
|
|
857
|
+
case "human_agent_leave":
|
|
858
|
+
await sendRestMessage("agent-leave", {
|
|
859
|
+
orgId: fullEvent.orgId,
|
|
860
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
861
|
+
user: fullEvent.data?.user
|
|
862
|
+
});
|
|
863
|
+
break;
|
|
864
|
+
// Event types that use the generic /event endpoint
|
|
865
|
+
case "load_agent_context":
|
|
866
|
+
case "skill_activate":
|
|
867
|
+
case "skill_deactivate":
|
|
868
|
+
case "sync_metadata":
|
|
869
|
+
case "plan_approved":
|
|
870
|
+
case "plan_rejected":
|
|
871
|
+
await sendRestMessage("event", {
|
|
872
|
+
type: fullEvent.type,
|
|
873
|
+
orgId: fullEvent.orgId,
|
|
874
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
875
|
+
userId: fullEvent.userId,
|
|
876
|
+
data: fullEvent.data
|
|
877
|
+
});
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
logger.warn("Sending unrecognized event type via generic endpoint:", fullEvent.type);
|
|
881
|
+
await sendRestMessage("event", {
|
|
882
|
+
type: fullEvent.type,
|
|
883
|
+
orgId: fullEvent.orgId,
|
|
884
|
+
chatKey: fullEvent.chatKey || currentChatKeyRef.current,
|
|
885
|
+
userId: fullEvent.userId,
|
|
886
|
+
data: fullEvent.data
|
|
887
|
+
});
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
updateMetrics({ messagesSent: metrics.messagesSent + 1 });
|
|
891
|
+
logger.debug("SSE REST message sent successfully");
|
|
892
|
+
resolve();
|
|
893
|
+
} catch (error2) {
|
|
894
|
+
logger.error("Failed to send SSE REST message:", error2);
|
|
895
|
+
const sendError = {
|
|
896
|
+
code: "SEND_FAILED",
|
|
897
|
+
message: error2 instanceof Error ? error2.message : "Failed to send message",
|
|
898
|
+
retryable: true,
|
|
899
|
+
timestamp: Date.now()
|
|
900
|
+
};
|
|
901
|
+
setError(sendError);
|
|
902
|
+
updateMetrics({ lastError: sendError });
|
|
903
|
+
reject(sendError);
|
|
904
|
+
}
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
548
907
|
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
|
|
549
908
|
if (addToQueue(fullEvent)) {
|
|
550
909
|
logger.debug("Message queued, attempting to connect");
|
|
@@ -581,7 +940,7 @@ var useWebSocketChatBase = ({
|
|
|
581
940
|
}
|
|
582
941
|
});
|
|
583
942
|
},
|
|
584
|
-
[connectionState, connect, addToQueue, logger, metrics, updateMetrics]
|
|
943
|
+
[connectionState, connect, addToQueue, logger, metrics, updateMetrics, sendRestMessage, emit]
|
|
585
944
|
);
|
|
586
945
|
const startNewChat = (0, import_react.useCallback)(
|
|
587
946
|
(userId, data) => {
|
|
@@ -619,7 +978,7 @@ var useWebSocketChatBase = ({
|
|
|
619
978
|
);
|
|
620
979
|
const disconnect = (0, import_react.useCallback)(
|
|
621
980
|
(intentional = true) => {
|
|
622
|
-
logger.info("Disconnecting
|
|
981
|
+
logger.info("Disconnecting", { intentional, transport: transportRef.current });
|
|
623
982
|
intentionalDisconnectRef.current = intentional;
|
|
624
983
|
cleanup();
|
|
625
984
|
setConnectionState("disconnected");
|