@elqnt/chat 2.0.8 → 3.0.1

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.
Files changed (52) hide show
  1. package/README.md +433 -0
  2. package/dist/api/index.d.mts +250 -8
  3. package/dist/api/index.d.ts +250 -8
  4. package/dist/api/index.js +115 -0
  5. package/dist/api/index.js.map +1 -1
  6. package/dist/api/index.mjs +109 -0
  7. package/dist/api/index.mjs.map +1 -1
  8. package/dist/hooks/index.d.mts +80 -0
  9. package/dist/hooks/index.d.ts +80 -0
  10. package/dist/hooks/index.js +741 -0
  11. package/dist/hooks/index.js.map +1 -0
  12. package/dist/hooks/index.mjs +715 -0
  13. package/dist/hooks/index.mjs.map +1 -0
  14. package/dist/index.d.mts +4 -109
  15. package/dist/index.d.ts +4 -109
  16. package/dist/index.js +731 -2039
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +722 -2016
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/models/index.d.mts +76 -6
  21. package/dist/models/index.d.ts +76 -6
  22. package/dist/models/index.js +21 -0
  23. package/dist/models/index.js.map +1 -1
  24. package/dist/models/index.mjs +14 -0
  25. package/dist/models/index.mjs.map +1 -1
  26. package/dist/transport/index.d.mts +243 -0
  27. package/dist/transport/index.d.ts +243 -0
  28. package/dist/transport/index.js +972 -0
  29. package/dist/transport/index.js.map +1 -0
  30. package/dist/transport/index.mjs +940 -0
  31. package/dist/transport/index.mjs.map +1 -0
  32. package/dist/types-7UNI1iYv.d.ts +250 -0
  33. package/dist/types-CQHtUQ6p.d.mts +250 -0
  34. package/package.json +20 -38
  35. package/dist/hooks/use-websocket-chat-admin.d.mts +0 -17
  36. package/dist/hooks/use-websocket-chat-admin.d.ts +0 -17
  37. package/dist/hooks/use-websocket-chat-admin.js +0 -1196
  38. package/dist/hooks/use-websocket-chat-admin.js.map +0 -1
  39. package/dist/hooks/use-websocket-chat-admin.mjs +0 -1172
  40. package/dist/hooks/use-websocket-chat-admin.mjs.map +0 -1
  41. package/dist/hooks/use-websocket-chat-base.d.mts +0 -81
  42. package/dist/hooks/use-websocket-chat-base.d.ts +0 -81
  43. package/dist/hooks/use-websocket-chat-base.js +0 -1025
  44. package/dist/hooks/use-websocket-chat-base.js.map +0 -1
  45. package/dist/hooks/use-websocket-chat-base.mjs +0 -1001
  46. package/dist/hooks/use-websocket-chat-base.mjs.map +0 -1
  47. package/dist/hooks/use-websocket-chat-customer.d.mts +0 -24
  48. package/dist/hooks/use-websocket-chat-customer.d.ts +0 -24
  49. package/dist/hooks/use-websocket-chat-customer.js +0 -1092
  50. package/dist/hooks/use-websocket-chat-customer.js.map +0 -1
  51. package/dist/hooks/use-websocket-chat-customer.mjs +0 -1068
  52. package/dist/hooks/use-websocket-chat-customer.mjs.map +0 -1
@@ -0,0 +1,741 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // hooks/index.ts
22
+ var hooks_exports = {};
23
+ __export(hooks_exports, {
24
+ useChat: () => useChat
25
+ });
26
+ module.exports = __toCommonJS(hooks_exports);
27
+
28
+ // hooks/use-chat.ts
29
+ var import_react = require("react");
30
+
31
+ // transport/types.ts
32
+ function createLogger(debug = false) {
33
+ return {
34
+ debug: debug ? console.log.bind(console, "[chat]") : () => {
35
+ },
36
+ info: console.info.bind(console, "[chat]"),
37
+ warn: console.warn.bind(console, "[chat]"),
38
+ error: console.error.bind(console, "[chat]")
39
+ };
40
+ }
41
+ var DEFAULT_RETRY_CONFIG = {
42
+ maxRetries: 10,
43
+ intervals: [1e3, 2e3, 5e3],
44
+ backoffMultiplier: 1.5,
45
+ maxBackoffTime: 3e4
46
+ };
47
+ function calculateRetryInterval(retryCount, config = DEFAULT_RETRY_CONFIG) {
48
+ const {
49
+ intervals = DEFAULT_RETRY_CONFIG.intervals,
50
+ backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
51
+ maxBackoffTime = DEFAULT_RETRY_CONFIG.maxBackoffTime
52
+ } = config;
53
+ if (retryCount < intervals.length) {
54
+ return intervals[retryCount];
55
+ }
56
+ const baseInterval = intervals[intervals.length - 1] || 5e3;
57
+ const backoffTime = baseInterval * Math.pow(backoffMultiplier, retryCount - intervals.length + 1);
58
+ return Math.min(backoffTime, maxBackoffTime);
59
+ }
60
+
61
+ // transport/sse.ts
62
+ function createSSETransport(options = {}) {
63
+ const {
64
+ retryConfig = DEFAULT_RETRY_CONFIG,
65
+ debug = false,
66
+ logger = createLogger(debug)
67
+ } = options;
68
+ let eventSource;
69
+ let config;
70
+ let state = "disconnected";
71
+ let error;
72
+ let retryCount = 0;
73
+ let reconnectTimeout;
74
+ let intentionalDisconnect = false;
75
+ const metrics = {
76
+ latency: 0,
77
+ messagesSent: 0,
78
+ messagesReceived: 0,
79
+ messagesQueued: 0,
80
+ reconnectCount: 0,
81
+ transportType: "sse"
82
+ };
83
+ const globalHandlers = /* @__PURE__ */ new Set();
84
+ const typeHandlers = /* @__PURE__ */ new Map();
85
+ function emit(event) {
86
+ metrics.messagesReceived++;
87
+ metrics.lastMessageAt = Date.now();
88
+ globalHandlers.forEach((handler) => {
89
+ try {
90
+ handler(event);
91
+ } catch (err) {
92
+ logger.error("Error in message handler:", err);
93
+ }
94
+ });
95
+ const handlers = typeHandlers.get(event.type);
96
+ if (handlers) {
97
+ handlers.forEach((handler) => {
98
+ try {
99
+ handler(event);
100
+ } catch (err) {
101
+ logger.error(`Error in ${event.type} handler:`, err);
102
+ }
103
+ });
104
+ }
105
+ }
106
+ async function sendRest(endpoint, body) {
107
+ if (!config) {
108
+ throw new Error("Transport not connected");
109
+ }
110
+ const url = `${config.baseUrl}/${endpoint}`;
111
+ logger.debug(`POST ${endpoint}`, body);
112
+ const response = await fetch(url, {
113
+ method: "POST",
114
+ headers: { "Content-Type": "application/json" },
115
+ body: JSON.stringify(body)
116
+ });
117
+ if (!response.ok) {
118
+ const errorText = await response.text();
119
+ throw new Error(`API error: ${response.status} - ${errorText}`);
120
+ }
121
+ const json = await response.json();
122
+ if (json && typeof json === "object" && "data" in json) {
123
+ return json.data;
124
+ }
125
+ return json;
126
+ }
127
+ function handleMessage(event) {
128
+ if (!event.data || event.data === "") return;
129
+ try {
130
+ const data = JSON.parse(event.data);
131
+ logger.debug("Received:", data.type);
132
+ emit(data);
133
+ } catch (err) {
134
+ logger.error("Failed to parse SSE message:", err);
135
+ }
136
+ }
137
+ function setupEventListeners(es) {
138
+ es.addEventListener("message", handleMessage);
139
+ const eventTypes = [
140
+ "reconnected",
141
+ "typing",
142
+ "stopped_typing",
143
+ "waiting",
144
+ "waiting_for_agent",
145
+ "human_agent_joined",
146
+ "human_agent_left",
147
+ "chat_ended",
148
+ "chat_updated",
149
+ "load_chat_response",
150
+ "new_chat_created",
151
+ "show_csat_survey",
152
+ "csat_response",
153
+ "user_suggested_actions",
154
+ "agent_execution_started",
155
+ "agent_execution_ended",
156
+ "agent_context_update",
157
+ "plan_pending_approval",
158
+ "step_started",
159
+ "step_completed",
160
+ "step_failed",
161
+ "plan_completed",
162
+ "skills_changed",
163
+ "summary_update"
164
+ ];
165
+ eventTypes.forEach((type) => {
166
+ es.addEventListener(type, handleMessage);
167
+ });
168
+ }
169
+ function scheduleReconnect() {
170
+ if (intentionalDisconnect || !config) return;
171
+ const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;
172
+ if (retryCount >= maxRetries) {
173
+ logger.error(`Max retries (${maxRetries}) exceeded`);
174
+ error = {
175
+ code: "CONNECTION_FAILED",
176
+ message: `Max retries (${maxRetries}) exceeded`,
177
+ retryable: false,
178
+ timestamp: Date.now()
179
+ };
180
+ return;
181
+ }
182
+ const interval = calculateRetryInterval(retryCount, retryConfig);
183
+ retryCount++;
184
+ metrics.reconnectCount++;
185
+ logger.info(`Reconnecting in ${interval}ms (attempt ${retryCount})`);
186
+ state = "reconnecting";
187
+ reconnectTimeout = setTimeout(() => {
188
+ if (config) {
189
+ transport.connect(config).catch((err) => {
190
+ logger.error("Reconnect failed:", err);
191
+ });
192
+ }
193
+ }, interval);
194
+ }
195
+ const transport = {
196
+ async connect(cfg) {
197
+ config = cfg;
198
+ intentionalDisconnect = false;
199
+ if (eventSource) {
200
+ eventSource.close();
201
+ eventSource = void 0;
202
+ }
203
+ if (reconnectTimeout) {
204
+ clearTimeout(reconnectTimeout);
205
+ reconnectTimeout = void 0;
206
+ }
207
+ state = retryCount > 0 ? "reconnecting" : "connecting";
208
+ return new Promise((resolve, reject) => {
209
+ const connectionStart = Date.now();
210
+ const url = `${cfg.baseUrl}/stream?orgId=${cfg.orgId}&userId=${cfg.userId}&clientType=${cfg.clientType}${cfg.chatKey ? `&chatId=${cfg.chatKey}` : ""}`;
211
+ logger.debug("Connecting to:", url);
212
+ const es = new EventSource(url);
213
+ es.onopen = () => {
214
+ const connectionTime = Date.now() - connectionStart;
215
+ logger.info(`Connected in ${connectionTime}ms`);
216
+ state = "connected";
217
+ error = void 0;
218
+ retryCount = 0;
219
+ metrics.connectedAt = Date.now();
220
+ metrics.latency = connectionTime;
221
+ setupEventListeners(es);
222
+ resolve();
223
+ };
224
+ es.onerror = () => {
225
+ if (es.readyState === EventSource.CLOSED) {
226
+ const sseError = {
227
+ code: "CONNECTION_FAILED",
228
+ message: "SSE connection failed",
229
+ retryable: true,
230
+ timestamp: Date.now()
231
+ };
232
+ error = sseError;
233
+ metrics.lastError = sseError;
234
+ state = "disconnected";
235
+ if (!intentionalDisconnect) {
236
+ scheduleReconnect();
237
+ }
238
+ if (retryCount === 0) {
239
+ reject(sseError);
240
+ }
241
+ }
242
+ };
243
+ eventSource = es;
244
+ });
245
+ },
246
+ disconnect(intentional = true) {
247
+ logger.info("Disconnecting", { intentional });
248
+ intentionalDisconnect = intentional;
249
+ if (reconnectTimeout) {
250
+ clearTimeout(reconnectTimeout);
251
+ reconnectTimeout = void 0;
252
+ }
253
+ if (eventSource) {
254
+ eventSource.close();
255
+ eventSource = void 0;
256
+ }
257
+ state = "disconnected";
258
+ retryCount = 0;
259
+ },
260
+ async send(event) {
261
+ if (!config) {
262
+ throw new Error("Transport not connected");
263
+ }
264
+ switch (event.type) {
265
+ case "message":
266
+ await sendRest("send", {
267
+ orgId: event.orgId,
268
+ chatKey: event.chatKey,
269
+ userId: event.userId,
270
+ message: event.message
271
+ });
272
+ break;
273
+ case "typing":
274
+ await sendRest("typing", {
275
+ orgId: event.orgId,
276
+ chatKey: event.chatKey,
277
+ userId: event.userId,
278
+ typing: true
279
+ });
280
+ break;
281
+ case "stopped_typing":
282
+ await sendRest("typing", {
283
+ orgId: event.orgId,
284
+ chatKey: event.chatKey,
285
+ userId: event.userId,
286
+ typing: false
287
+ });
288
+ break;
289
+ case "load_chat":
290
+ await sendRest("load", {
291
+ orgId: event.orgId,
292
+ chatKey: event.chatKey,
293
+ userId: event.userId
294
+ });
295
+ break;
296
+ case "new_chat":
297
+ await sendRest("create", {
298
+ orgId: event.orgId,
299
+ userId: event.userId,
300
+ metadata: event.data
301
+ });
302
+ break;
303
+ case "end_chat":
304
+ await sendRest("end", {
305
+ orgId: event.orgId,
306
+ chatKey: event.chatKey,
307
+ userId: event.userId,
308
+ data: event.data
309
+ });
310
+ break;
311
+ default:
312
+ await sendRest("event", {
313
+ type: event.type,
314
+ orgId: event.orgId,
315
+ chatKey: event.chatKey,
316
+ userId: event.userId,
317
+ data: event.data
318
+ });
319
+ }
320
+ metrics.messagesSent++;
321
+ },
322
+ async sendMessage(message) {
323
+ if (!config) {
324
+ throw new Error("Transport not connected");
325
+ }
326
+ await sendRest("send", {
327
+ orgId: config.orgId,
328
+ chatKey: config.chatKey,
329
+ userId: config.userId,
330
+ message
331
+ });
332
+ metrics.messagesSent++;
333
+ },
334
+ async createChat(options2) {
335
+ if (!config) {
336
+ throw new Error("Transport not connected");
337
+ }
338
+ const response = await sendRest("create", {
339
+ orgId: options2.orgId,
340
+ userId: options2.userId,
341
+ metadata: options2.metadata
342
+ });
343
+ if (!response?.chatKey) {
344
+ throw new Error("Failed to create chat: no chatKey returned");
345
+ }
346
+ return { chatKey: response.chatKey };
347
+ },
348
+ async loadChatData(options2) {
349
+ if (!config) {
350
+ throw new Error("Transport not connected");
351
+ }
352
+ const response = await sendRest("load", {
353
+ orgId: options2.orgId,
354
+ chatKey: options2.chatKey,
355
+ userId: options2.userId
356
+ });
357
+ if (!response?.chat) {
358
+ throw new Error("Failed to load chat: no chat data returned");
359
+ }
360
+ return {
361
+ chat: response.chat,
362
+ agentId: response.agentId
363
+ };
364
+ },
365
+ onMessage(handler) {
366
+ globalHandlers.add(handler);
367
+ return () => globalHandlers.delete(handler);
368
+ },
369
+ on(eventType, handler) {
370
+ if (!typeHandlers.has(eventType)) {
371
+ typeHandlers.set(eventType, /* @__PURE__ */ new Set());
372
+ }
373
+ typeHandlers.get(eventType).add(handler);
374
+ return () => {
375
+ const handlers = typeHandlers.get(eventType);
376
+ if (handlers) {
377
+ handlers.delete(handler);
378
+ if (handlers.size === 0) {
379
+ typeHandlers.delete(eventType);
380
+ }
381
+ }
382
+ };
383
+ },
384
+ getState() {
385
+ return state;
386
+ },
387
+ getMetrics() {
388
+ return { ...metrics };
389
+ },
390
+ getError() {
391
+ return error;
392
+ },
393
+ clearError() {
394
+ error = void 0;
395
+ }
396
+ };
397
+ return transport;
398
+ }
399
+
400
+ // hooks/use-chat.ts
401
+ function getDefaultTransport(type, debug) {
402
+ return createSSETransport({ debug });
403
+ }
404
+ function useChat(options) {
405
+ const {
406
+ baseUrl,
407
+ orgId,
408
+ userId,
409
+ clientType = "customer",
410
+ transport: transportOption,
411
+ onMessage,
412
+ onError,
413
+ onConnectionChange,
414
+ autoConnect = false,
415
+ retryConfig,
416
+ debug = false
417
+ } = options;
418
+ const [connectionState, setConnectionState] = (0, import_react.useState)("disconnected");
419
+ const [currentChat, setCurrentChat] = (0, import_react.useState)(null);
420
+ const [chatKey, setChatKey] = (0, import_react.useState)(null);
421
+ const [messages, setMessages] = (0, import_react.useState)([]);
422
+ const [error, setError] = (0, import_react.useState)(null);
423
+ const [metrics, setMetrics] = (0, import_react.useState)({
424
+ latency: 0,
425
+ messagesSent: 0,
426
+ messagesReceived: 0,
427
+ messagesQueued: 0,
428
+ reconnectCount: 0
429
+ });
430
+ const transportRef = (0, import_react.useRef)(null);
431
+ const mountedRef = (0, import_react.useRef)(false);
432
+ const onMessageRef = (0, import_react.useRef)(onMessage);
433
+ const onErrorRef = (0, import_react.useRef)(onError);
434
+ const typingTimeoutRef = (0, import_react.useRef)(null);
435
+ (0, import_react.useEffect)(() => {
436
+ onMessageRef.current = onMessage;
437
+ onErrorRef.current = onError;
438
+ }, [onMessage, onError]);
439
+ (0, import_react.useEffect)(() => {
440
+ if (typeof transportOption === "object") {
441
+ transportRef.current = transportOption;
442
+ } else {
443
+ transportRef.current = getDefaultTransport(
444
+ transportOption,
445
+ debug
446
+ );
447
+ }
448
+ }, [transportOption, debug]);
449
+ const handleEvent = (0, import_react.useCallback)((event) => {
450
+ if (!mountedRef.current) return;
451
+ setMetrics((prev) => ({
452
+ ...prev,
453
+ messagesReceived: prev.messagesReceived + 1,
454
+ lastMessageAt: Date.now()
455
+ }));
456
+ switch (event.type) {
457
+ case "new_chat_created":
458
+ const newChatKey = event.data?.chatKey;
459
+ if (newChatKey) {
460
+ setChatKey(newChatKey);
461
+ }
462
+ break;
463
+ case "load_chat_response":
464
+ const chat = event.data?.chat;
465
+ if (chat) {
466
+ setCurrentChat(chat);
467
+ setChatKey(chat.key);
468
+ setMessages(chat.messages || []);
469
+ }
470
+ break;
471
+ case "message":
472
+ if (event.message) {
473
+ setMessages((prev) => [...prev, event.message]);
474
+ }
475
+ break;
476
+ case "chat_ended":
477
+ setCurrentChat(null);
478
+ setChatKey(null);
479
+ break;
480
+ case "error":
481
+ const errorMsg = event.data?.message;
482
+ if (errorMsg) {
483
+ const transportError = {
484
+ code: "NETWORK_ERROR",
485
+ message: errorMsg,
486
+ retryable: true,
487
+ timestamp: Date.now()
488
+ };
489
+ setError(transportError);
490
+ onErrorRef.current?.(transportError);
491
+ }
492
+ break;
493
+ }
494
+ onMessageRef.current?.(event);
495
+ }, []);
496
+ const connect = (0, import_react.useCallback)(async () => {
497
+ const transport = transportRef.current;
498
+ if (!transport) {
499
+ throw new Error("Transport not initialized");
500
+ }
501
+ if (!orgId) {
502
+ const err = {
503
+ code: "CONNECTION_FAILED",
504
+ message: "orgId is required",
505
+ retryable: false,
506
+ timestamp: Date.now()
507
+ };
508
+ setError(err);
509
+ throw err;
510
+ }
511
+ setConnectionState("connecting");
512
+ try {
513
+ const unsubscribe = transport.onMessage(handleEvent);
514
+ await transport.connect({
515
+ baseUrl,
516
+ orgId,
517
+ userId,
518
+ clientType,
519
+ chatKey: chatKey || void 0,
520
+ debug
521
+ });
522
+ setConnectionState("connected");
523
+ setError(null);
524
+ setMetrics(transport.getMetrics());
525
+ onConnectionChange?.("connected");
526
+ return;
527
+ } catch (err) {
528
+ const transportError = err;
529
+ setConnectionState("disconnected");
530
+ setError(transportError);
531
+ onErrorRef.current?.(transportError);
532
+ throw err;
533
+ }
534
+ }, [baseUrl, orgId, userId, clientType, chatKey, debug, handleEvent, onConnectionChange]);
535
+ const disconnect = (0, import_react.useCallback)(() => {
536
+ const transport = transportRef.current;
537
+ if (transport) {
538
+ transport.disconnect(true);
539
+ }
540
+ setConnectionState("disconnected");
541
+ onConnectionChange?.("disconnected");
542
+ }, [onConnectionChange]);
543
+ const startChat = (0, import_react.useCallback)(
544
+ async (metadata) => {
545
+ const transport = transportRef.current;
546
+ if (!transport) {
547
+ throw new Error("Transport not initialized");
548
+ }
549
+ const response = await transport.createChat({
550
+ orgId,
551
+ userId,
552
+ metadata
553
+ });
554
+ setChatKey(response.chatKey);
555
+ return response.chatKey;
556
+ },
557
+ [orgId, userId]
558
+ );
559
+ const loadChat = (0, import_react.useCallback)(
560
+ async (key) => {
561
+ const transport = transportRef.current;
562
+ if (!transport) {
563
+ throw new Error("Transport not initialized");
564
+ }
565
+ const response = await transport.loadChatData({
566
+ orgId,
567
+ chatKey: key,
568
+ userId
569
+ });
570
+ setCurrentChat(response.chat);
571
+ setChatKey(response.chat.key);
572
+ setMessages(response.chat.messages || []);
573
+ return response.chat;
574
+ },
575
+ [orgId, userId]
576
+ );
577
+ const sendMessage = (0, import_react.useCallback)(
578
+ async (content, attachments) => {
579
+ const transport = transportRef.current;
580
+ if (!transport) {
581
+ throw new Error("Transport not initialized");
582
+ }
583
+ if (!chatKey) {
584
+ throw new Error("No active chat");
585
+ }
586
+ const message = {
587
+ id: `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`,
588
+ role: "user",
589
+ content,
590
+ time: Date.now(),
591
+ status: "sending",
592
+ senderId: userId,
593
+ createdAt: Date.now(),
594
+ attachments
595
+ };
596
+ setMessages((prev) => [...prev, message]);
597
+ await transport.send({
598
+ type: "message",
599
+ orgId,
600
+ chatKey,
601
+ userId,
602
+ timestamp: Date.now(),
603
+ message
604
+ });
605
+ setMetrics((prev) => ({
606
+ ...prev,
607
+ messagesSent: prev.messagesSent + 1
608
+ }));
609
+ },
610
+ [orgId, chatKey, userId]
611
+ );
612
+ const endChat = (0, import_react.useCallback)(
613
+ async (reason) => {
614
+ const transport = transportRef.current;
615
+ if (!transport) {
616
+ throw new Error("Transport not initialized");
617
+ }
618
+ if (!chatKey) {
619
+ return;
620
+ }
621
+ await transport.send({
622
+ type: "end_chat",
623
+ orgId,
624
+ chatKey,
625
+ userId,
626
+ timestamp: Date.now(),
627
+ data: reason ? { reason } : void 0
628
+ });
629
+ setCurrentChat(null);
630
+ setChatKey(null);
631
+ },
632
+ [orgId, chatKey, userId]
633
+ );
634
+ const sendEvent = (0, import_react.useCallback)(
635
+ async (event) => {
636
+ const transport = transportRef.current;
637
+ if (!transport) {
638
+ throw new Error("Transport not initialized");
639
+ }
640
+ await transport.send({
641
+ ...event,
642
+ timestamp: Date.now()
643
+ });
644
+ },
645
+ []
646
+ );
647
+ const startTyping = (0, import_react.useCallback)(() => {
648
+ const transport = transportRef.current;
649
+ if (!transport || !chatKey) return;
650
+ if (typingTimeoutRef.current) {
651
+ clearTimeout(typingTimeoutRef.current);
652
+ }
653
+ transport.send({
654
+ type: "typing",
655
+ orgId,
656
+ chatKey,
657
+ userId,
658
+ timestamp: Date.now()
659
+ }).catch(() => {
660
+ });
661
+ typingTimeoutRef.current = setTimeout(() => {
662
+ stopTyping();
663
+ }, 3e3);
664
+ }, [orgId, chatKey, userId]);
665
+ const stopTyping = (0, import_react.useCallback)(() => {
666
+ const transport = transportRef.current;
667
+ if (!transport || !chatKey) return;
668
+ if (typingTimeoutRef.current) {
669
+ clearTimeout(typingTimeoutRef.current);
670
+ typingTimeoutRef.current = null;
671
+ }
672
+ transport.send({
673
+ type: "stopped_typing",
674
+ orgId,
675
+ chatKey,
676
+ userId,
677
+ timestamp: Date.now()
678
+ }).catch(() => {
679
+ });
680
+ }, [orgId, chatKey, userId]);
681
+ const on = (0, import_react.useCallback)(
682
+ (eventType, handler) => {
683
+ const transport = transportRef.current;
684
+ if (!transport) {
685
+ return () => {
686
+ };
687
+ }
688
+ return transport.on(eventType, handler);
689
+ },
690
+ []
691
+ );
692
+ const clearError = (0, import_react.useCallback)(() => {
693
+ setError(null);
694
+ transportRef.current?.clearError();
695
+ }, []);
696
+ (0, import_react.useEffect)(() => {
697
+ mountedRef.current = true;
698
+ if (autoConnect) {
699
+ connect().catch(() => {
700
+ });
701
+ }
702
+ return () => {
703
+ mountedRef.current = false;
704
+ if (typingTimeoutRef.current) {
705
+ clearTimeout(typingTimeoutRef.current);
706
+ }
707
+ disconnect();
708
+ };
709
+ }, []);
710
+ const isConnected = connectionState === "connected";
711
+ return {
712
+ // Connection
713
+ connect,
714
+ disconnect,
715
+ connectionState,
716
+ isConnected,
717
+ // Chat operations
718
+ startChat,
719
+ loadChat,
720
+ sendMessage,
721
+ sendEvent,
722
+ endChat,
723
+ // Typing
724
+ startTyping,
725
+ stopTyping,
726
+ // State
727
+ currentChat,
728
+ chatKey,
729
+ messages,
730
+ error,
731
+ metrics,
732
+ // Events
733
+ on,
734
+ clearError
735
+ };
736
+ }
737
+ // Annotate the CommonJS export names for ESM import in node:
738
+ 0 && (module.exports = {
739
+ useChat
740
+ });
741
+ //# sourceMappingURL=index.js.map