@elqnt/chat 3.1.0 → 3.5.0

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/index.mjs CHANGED
@@ -1,1408 +1,3 @@
1
- "use client";
2
-
3
- // hooks/use-chat.ts
4
- import { useCallback, useEffect, useRef, useState } from "react";
5
-
6
- // transport/types.ts
7
- function createLogger(debug = false) {
8
- return {
9
- debug: debug ? console.log.bind(console, "[chat]") : () => {
10
- },
11
- info: console.info.bind(console, "[chat]"),
12
- warn: console.warn.bind(console, "[chat]"),
13
- error: console.error.bind(console, "[chat]")
14
- };
15
- }
16
- var DEFAULT_RETRY_CONFIG = {
17
- maxRetries: 10,
18
- intervals: [1e3, 2e3, 5e3],
19
- backoffMultiplier: 1.5,
20
- maxBackoffTime: 3e4
21
- };
22
- function calculateRetryInterval(retryCount, config = DEFAULT_RETRY_CONFIG) {
23
- const {
24
- intervals = DEFAULT_RETRY_CONFIG.intervals,
25
- backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
26
- maxBackoffTime = DEFAULT_RETRY_CONFIG.maxBackoffTime
27
- } = config;
28
- if (retryCount < intervals.length) {
29
- return intervals[retryCount];
30
- }
31
- const baseInterval = intervals[intervals.length - 1] || 5e3;
32
- const backoffTime = baseInterval * Math.pow(backoffMultiplier, retryCount - intervals.length + 1);
33
- return Math.min(backoffTime, maxBackoffTime);
34
- }
35
-
36
- // transport/sse.ts
37
- function createSSETransport(options = {}) {
38
- const {
39
- retryConfig = DEFAULT_RETRY_CONFIG,
40
- debug = false,
41
- logger = createLogger(debug)
42
- } = options;
43
- let eventSource;
44
- let config;
45
- let state = "disconnected";
46
- let error;
47
- let retryCount = 0;
48
- let reconnectTimeout;
49
- let intentionalDisconnect = false;
50
- const metrics = {
51
- latency: 0,
52
- messagesSent: 0,
53
- messagesReceived: 0,
54
- messagesQueued: 0,
55
- reconnectCount: 0,
56
- transportType: "sse"
57
- };
58
- const globalHandlers = /* @__PURE__ */ new Set();
59
- const typeHandlers = /* @__PURE__ */ new Map();
60
- function emit(event) {
61
- metrics.messagesReceived++;
62
- metrics.lastMessageAt = Date.now();
63
- globalHandlers.forEach((handler) => {
64
- try {
65
- handler(event);
66
- } catch (err) {
67
- logger.error("Error in message handler:", err);
68
- }
69
- });
70
- const handlers = typeHandlers.get(event.type);
71
- if (handlers) {
72
- handlers.forEach((handler) => {
73
- try {
74
- handler(event);
75
- } catch (err) {
76
- logger.error(`Error in ${event.type} handler:`, err);
77
- }
78
- });
79
- }
80
- }
81
- async function sendRest(endpoint, body) {
82
- if (!config) {
83
- throw new Error("Transport not connected");
84
- }
85
- const url = `${config.baseUrl}/${endpoint}`;
86
- logger.debug(`POST ${endpoint}`, body);
87
- const response = await fetch(url, {
88
- method: "POST",
89
- headers: { "Content-Type": "application/json" },
90
- body: JSON.stringify(body)
91
- });
92
- if (!response.ok) {
93
- const errorText = await response.text();
94
- throw new Error(`API error: ${response.status} - ${errorText}`);
95
- }
96
- const json = await response.json();
97
- if (json && typeof json === "object" && "data" in json) {
98
- return json.data;
99
- }
100
- return json;
101
- }
102
- function handleMessage(event) {
103
- if (!event.data || event.data === "") return;
104
- try {
105
- const data = JSON.parse(event.data);
106
- logger.debug("Received:", data.type);
107
- emit(data);
108
- } catch (err) {
109
- logger.error("Failed to parse SSE message:", err);
110
- }
111
- }
112
- function setupEventListeners(es) {
113
- es.addEventListener("message", handleMessage);
114
- const eventTypes = [
115
- "reconnected",
116
- "typing",
117
- "stopped_typing",
118
- "waiting",
119
- "waiting_for_agent",
120
- "human_agent_joined",
121
- "human_agent_left",
122
- "chat_ended",
123
- "chat_updated",
124
- "load_chat_response",
125
- "new_chat_created",
126
- "show_csat_survey",
127
- "csat_response",
128
- "user_suggested_actions",
129
- "agent_execution_started",
130
- "agent_execution_ended",
131
- "agent_context_update",
132
- "plan_pending_approval",
133
- "step_started",
134
- "step_completed",
135
- "step_failed",
136
- "plan_completed",
137
- "skills_changed",
138
- "summary_update"
139
- ];
140
- eventTypes.forEach((type) => {
141
- es.addEventListener(type, handleMessage);
142
- });
143
- }
144
- function scheduleReconnect() {
145
- if (intentionalDisconnect || !config) return;
146
- const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;
147
- if (retryCount >= maxRetries) {
148
- logger.error(`Max retries (${maxRetries}) exceeded`);
149
- error = {
150
- code: "CONNECTION_FAILED",
151
- message: `Max retries (${maxRetries}) exceeded`,
152
- retryable: false,
153
- timestamp: Date.now()
154
- };
155
- return;
156
- }
157
- const interval = calculateRetryInterval(retryCount, retryConfig);
158
- retryCount++;
159
- metrics.reconnectCount++;
160
- logger.info(`Reconnecting in ${interval}ms (attempt ${retryCount})`);
161
- state = "reconnecting";
162
- reconnectTimeout = setTimeout(() => {
163
- if (config) {
164
- transport.connect(config).catch((err) => {
165
- logger.error("Reconnect failed:", err);
166
- });
167
- }
168
- }, interval);
169
- }
170
- const transport = {
171
- async connect(cfg) {
172
- config = cfg;
173
- intentionalDisconnect = false;
174
- if (eventSource) {
175
- eventSource.close();
176
- eventSource = void 0;
177
- }
178
- if (reconnectTimeout) {
179
- clearTimeout(reconnectTimeout);
180
- reconnectTimeout = void 0;
181
- }
182
- state = retryCount > 0 ? "reconnecting" : "connecting";
183
- return new Promise((resolve, reject) => {
184
- const connectionStart = Date.now();
185
- const url = `${cfg.baseUrl}/stream?orgId=${cfg.orgId}&userId=${cfg.userId}&clientType=${cfg.clientType}${cfg.chatKey ? `&chatId=${cfg.chatKey}` : ""}`;
186
- logger.debug("Connecting to:", url);
187
- const es = new EventSource(url);
188
- es.onopen = () => {
189
- const connectionTime = Date.now() - connectionStart;
190
- logger.info(`Connected in ${connectionTime}ms`);
191
- state = "connected";
192
- error = void 0;
193
- retryCount = 0;
194
- metrics.connectedAt = Date.now();
195
- metrics.latency = connectionTime;
196
- setupEventListeners(es);
197
- resolve();
198
- };
199
- es.onerror = () => {
200
- if (es.readyState === EventSource.CLOSED) {
201
- const sseError = {
202
- code: "CONNECTION_FAILED",
203
- message: "SSE connection failed",
204
- retryable: true,
205
- timestamp: Date.now()
206
- };
207
- error = sseError;
208
- metrics.lastError = sseError;
209
- state = "disconnected";
210
- if (!intentionalDisconnect) {
211
- scheduleReconnect();
212
- }
213
- if (retryCount === 0) {
214
- reject(sseError);
215
- }
216
- }
217
- };
218
- eventSource = es;
219
- });
220
- },
221
- disconnect(intentional = true) {
222
- logger.info("Disconnecting", { intentional });
223
- intentionalDisconnect = intentional;
224
- if (reconnectTimeout) {
225
- clearTimeout(reconnectTimeout);
226
- reconnectTimeout = void 0;
227
- }
228
- if (eventSource) {
229
- eventSource.close();
230
- eventSource = void 0;
231
- }
232
- state = "disconnected";
233
- retryCount = 0;
234
- },
235
- async send(event) {
236
- if (!config) {
237
- throw new Error("Transport not connected");
238
- }
239
- switch (event.type) {
240
- case "message":
241
- await sendRest("send", {
242
- orgId: event.orgId,
243
- chatKey: event.chatKey,
244
- userId: event.userId,
245
- message: event.message,
246
- ...event.data ? { data: event.data } : {}
247
- });
248
- break;
249
- case "typing":
250
- await sendRest("typing", {
251
- orgId: event.orgId,
252
- chatKey: event.chatKey,
253
- userId: event.userId,
254
- typing: true
255
- });
256
- break;
257
- case "stopped_typing":
258
- await sendRest("typing", {
259
- orgId: event.orgId,
260
- chatKey: event.chatKey,
261
- userId: event.userId,
262
- typing: false
263
- });
264
- break;
265
- case "load_chat":
266
- await sendRest("load", {
267
- orgId: event.orgId,
268
- chatKey: event.chatKey,
269
- userId: event.userId
270
- });
271
- break;
272
- case "new_chat":
273
- await sendRest("create", {
274
- orgId: event.orgId,
275
- userId: event.userId,
276
- metadata: event.data
277
- });
278
- break;
279
- case "end_chat":
280
- await sendRest("end", {
281
- orgId: event.orgId,
282
- chatKey: event.chatKey,
283
- userId: event.userId,
284
- data: event.data
285
- });
286
- break;
287
- default:
288
- await sendRest("event", {
289
- type: event.type,
290
- orgId: event.orgId,
291
- chatKey: event.chatKey,
292
- userId: event.userId,
293
- data: event.data
294
- });
295
- }
296
- metrics.messagesSent++;
297
- },
298
- async sendMessage(message) {
299
- if (!config) {
300
- throw new Error("Transport not connected");
301
- }
302
- await sendRest("send", {
303
- orgId: config.orgId,
304
- chatKey: config.chatKey,
305
- userId: config.userId,
306
- message
307
- });
308
- metrics.messagesSent++;
309
- },
310
- async createChat(options2) {
311
- if (!config) {
312
- throw new Error("Transport not connected");
313
- }
314
- const response = await sendRest("create", {
315
- orgId: options2.orgId,
316
- userId: options2.userId,
317
- metadata: options2.metadata
318
- });
319
- if (!response?.chatKey) {
320
- throw new Error("Failed to create chat: no chatKey returned");
321
- }
322
- return { chatKey: response.chatKey };
323
- },
324
- async loadChatData(options2) {
325
- if (!config) {
326
- throw new Error("Transport not connected");
327
- }
328
- const response = await sendRest("load", {
329
- orgId: options2.orgId,
330
- chatKey: options2.chatKey,
331
- userId: options2.userId
332
- });
333
- if (!response?.chat) {
334
- throw new Error("Failed to load chat: no chat data returned");
335
- }
336
- return {
337
- chat: response.chat,
338
- agentId: response.agentId
339
- };
340
- },
341
- onMessage(handler) {
342
- globalHandlers.add(handler);
343
- return () => globalHandlers.delete(handler);
344
- },
345
- on(eventType, handler) {
346
- if (!typeHandlers.has(eventType)) {
347
- typeHandlers.set(eventType, /* @__PURE__ */ new Set());
348
- }
349
- typeHandlers.get(eventType).add(handler);
350
- return () => {
351
- const handlers = typeHandlers.get(eventType);
352
- if (handlers) {
353
- handlers.delete(handler);
354
- if (handlers.size === 0) {
355
- typeHandlers.delete(eventType);
356
- }
357
- }
358
- };
359
- },
360
- getState() {
361
- return state;
362
- },
363
- getMetrics() {
364
- return { ...metrics };
365
- },
366
- getError() {
367
- return error;
368
- },
369
- clearError() {
370
- error = void 0;
371
- }
372
- };
373
- return transport;
374
- }
375
-
376
- // transport/sse-fetch.ts
377
- function createFetchSSETransport(options = {}) {
378
- const {
379
- retryConfig = DEFAULT_RETRY_CONFIG,
380
- debug = false,
381
- logger = createLogger(debug),
382
- customFetch = fetch
383
- } = options;
384
- let abortController;
385
- let config;
386
- let state = "disconnected";
387
- let error;
388
- let retryCount = 0;
389
- let reconnectTimeout;
390
- let intentionalDisconnect = false;
391
- const metrics = {
392
- latency: 0,
393
- messagesSent: 0,
394
- messagesReceived: 0,
395
- messagesQueued: 0,
396
- reconnectCount: 0,
397
- transportType: "sse-fetch"
398
- };
399
- const globalHandlers = /* @__PURE__ */ new Set();
400
- const typeHandlers = /* @__PURE__ */ new Map();
401
- function emit(event) {
402
- metrics.messagesReceived++;
403
- metrics.lastMessageAt = Date.now();
404
- globalHandlers.forEach((handler) => {
405
- try {
406
- handler(event);
407
- } catch (err) {
408
- logger.error("Error in message handler:", err);
409
- }
410
- });
411
- const handlers = typeHandlers.get(event.type);
412
- if (handlers) {
413
- handlers.forEach((handler) => {
414
- try {
415
- handler(event);
416
- } catch (err) {
417
- logger.error(`Error in ${event.type} handler:`, err);
418
- }
419
- });
420
- }
421
- }
422
- async function sendRest(endpoint, body) {
423
- if (!config) {
424
- throw new Error("Transport not connected");
425
- }
426
- const url = `${config.baseUrl}/${endpoint}`;
427
- logger.debug(`POST ${endpoint}`, body);
428
- const response = await customFetch(url, {
429
- method: "POST",
430
- headers: { "Content-Type": "application/json" },
431
- body: JSON.stringify(body)
432
- });
433
- if (!response.ok) {
434
- const errorText = await response.text();
435
- throw new Error(`API error: ${response.status} - ${errorText}`);
436
- }
437
- const json = await response.json();
438
- if (json && typeof json === "object" && "data" in json) {
439
- return json.data;
440
- }
441
- return json;
442
- }
443
- function parseSSEChunk(chunk) {
444
- const events = [];
445
- const lines = chunk.split("\n");
446
- let eventType = "message";
447
- let data = "";
448
- for (const line of lines) {
449
- if (line.startsWith("event:")) {
450
- eventType = line.slice(6).trim();
451
- } else if (line.startsWith("data:")) {
452
- data = line.slice(5).trim();
453
- } else if (line === "" && data) {
454
- try {
455
- const parsed = JSON.parse(data);
456
- events.push(parsed);
457
- } catch {
458
- logger.warn("Failed to parse SSE data:", data);
459
- }
460
- eventType = "message";
461
- data = "";
462
- }
463
- }
464
- return events;
465
- }
466
- async function startStream(cfg) {
467
- const url = `${cfg.baseUrl}/stream?orgId=${cfg.orgId}&userId=${cfg.userId}&clientType=${cfg.clientType}${cfg.chatKey ? `&chatId=${cfg.chatKey}` : ""}`;
468
- logger.debug("Connecting to:", url);
469
- abortController = new AbortController();
470
- const response = await customFetch(url, {
471
- method: "GET",
472
- headers: {
473
- Accept: "text/event-stream",
474
- "Cache-Control": "no-cache"
475
- },
476
- signal: abortController.signal
477
- });
478
- if (!response.ok) {
479
- throw new Error(`Stream connection failed: ${response.status}`);
480
- }
481
- if (!response.body) {
482
- throw new Error("Response body is null - ReadableStream not supported");
483
- }
484
- const reader = response.body.getReader();
485
- const decoder = new TextDecoder();
486
- let buffer = "";
487
- const readStream = async () => {
488
- try {
489
- while (true) {
490
- const { done, value } = await reader.read();
491
- if (done) {
492
- logger.info("Stream ended");
493
- break;
494
- }
495
- buffer += decoder.decode(value, { stream: true });
496
- const lastNewline = buffer.lastIndexOf("\n\n");
497
- if (lastNewline !== -1) {
498
- const complete = buffer.slice(0, lastNewline + 2);
499
- buffer = buffer.slice(lastNewline + 2);
500
- const events = parseSSEChunk(complete);
501
- events.forEach(emit);
502
- }
503
- }
504
- } catch (err) {
505
- if (err.name === "AbortError") {
506
- logger.debug("Stream aborted");
507
- return;
508
- }
509
- logger.error("Stream error:", err);
510
- throw err;
511
- }
512
- if (!intentionalDisconnect) {
513
- state = "disconnected";
514
- scheduleReconnect();
515
- }
516
- };
517
- readStream().catch((err) => {
518
- if (!intentionalDisconnect) {
519
- error = {
520
- code: "CONNECTION_FAILED",
521
- message: err.message,
522
- retryable: true,
523
- timestamp: Date.now(),
524
- originalError: err
525
- };
526
- metrics.lastError = error;
527
- state = "disconnected";
528
- scheduleReconnect();
529
- }
530
- });
531
- }
532
- function scheduleReconnect() {
533
- if (intentionalDisconnect || !config) return;
534
- const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;
535
- if (retryCount >= maxRetries) {
536
- logger.error(`Max retries (${maxRetries}) exceeded`);
537
- error = {
538
- code: "CONNECTION_FAILED",
539
- message: `Max retries (${maxRetries}) exceeded`,
540
- retryable: false,
541
- timestamp: Date.now()
542
- };
543
- return;
544
- }
545
- const interval = calculateRetryInterval(retryCount, retryConfig);
546
- retryCount++;
547
- metrics.reconnectCount++;
548
- logger.info(`Reconnecting in ${interval}ms (attempt ${retryCount})`);
549
- state = "reconnecting";
550
- reconnectTimeout = setTimeout(() => {
551
- if (config) {
552
- transport.connect(config).catch((err) => {
553
- logger.error("Reconnect failed:", err);
554
- });
555
- }
556
- }, interval);
557
- }
558
- const transport = {
559
- async connect(cfg) {
560
- config = cfg;
561
- intentionalDisconnect = false;
562
- if (abortController) {
563
- abortController.abort();
564
- abortController = void 0;
565
- }
566
- if (reconnectTimeout) {
567
- clearTimeout(reconnectTimeout);
568
- reconnectTimeout = void 0;
569
- }
570
- state = retryCount > 0 ? "reconnecting" : "connecting";
571
- const connectionStart = Date.now();
572
- try {
573
- await startStream(cfg);
574
- const connectionTime = Date.now() - connectionStart;
575
- logger.info(`Connected in ${connectionTime}ms`);
576
- state = "connected";
577
- error = void 0;
578
- retryCount = 0;
579
- metrics.connectedAt = Date.now();
580
- metrics.latency = connectionTime;
581
- } catch (err) {
582
- const connectError = {
583
- code: "CONNECTION_FAILED",
584
- message: err.message,
585
- retryable: true,
586
- timestamp: Date.now(),
587
- originalError: err
588
- };
589
- error = connectError;
590
- metrics.lastError = connectError;
591
- state = "disconnected";
592
- if (!intentionalDisconnect) {
593
- scheduleReconnect();
594
- }
595
- throw connectError;
596
- }
597
- },
598
- disconnect(intentional = true) {
599
- logger.info("Disconnecting", { intentional });
600
- intentionalDisconnect = intentional;
601
- if (reconnectTimeout) {
602
- clearTimeout(reconnectTimeout);
603
- reconnectTimeout = void 0;
604
- }
605
- if (abortController) {
606
- abortController.abort();
607
- abortController = void 0;
608
- }
609
- state = "disconnected";
610
- retryCount = 0;
611
- },
612
- async send(event) {
613
- if (!config) {
614
- throw new Error("Transport not connected");
615
- }
616
- switch (event.type) {
617
- case "message":
618
- await sendRest("send", {
619
- orgId: event.orgId,
620
- chatKey: event.chatKey,
621
- userId: event.userId,
622
- message: event.message
623
- });
624
- break;
625
- case "typing":
626
- await sendRest("typing", {
627
- orgId: event.orgId,
628
- chatKey: event.chatKey,
629
- userId: event.userId,
630
- typing: true
631
- });
632
- break;
633
- case "stopped_typing":
634
- await sendRest("typing", {
635
- orgId: event.orgId,
636
- chatKey: event.chatKey,
637
- userId: event.userId,
638
- typing: false
639
- });
640
- break;
641
- case "load_chat":
642
- await sendRest("load", {
643
- orgId: event.orgId,
644
- chatKey: event.chatKey,
645
- userId: event.userId
646
- });
647
- break;
648
- case "new_chat":
649
- await sendRest("create", {
650
- orgId: event.orgId,
651
- userId: event.userId,
652
- metadata: event.data
653
- });
654
- break;
655
- case "end_chat":
656
- await sendRest("end", {
657
- orgId: event.orgId,
658
- chatKey: event.chatKey,
659
- userId: event.userId,
660
- data: event.data
661
- });
662
- break;
663
- default:
664
- await sendRest("event", {
665
- type: event.type,
666
- orgId: event.orgId,
667
- chatKey: event.chatKey,
668
- userId: event.userId,
669
- data: event.data
670
- });
671
- }
672
- metrics.messagesSent++;
673
- },
674
- async sendMessage(message) {
675
- if (!config) {
676
- throw new Error("Transport not connected");
677
- }
678
- await sendRest("send", {
679
- orgId: config.orgId,
680
- chatKey: config.chatKey,
681
- userId: config.userId,
682
- message
683
- });
684
- metrics.messagesSent++;
685
- },
686
- async createChat(options2) {
687
- if (!config) {
688
- throw new Error("Transport not connected");
689
- }
690
- const response = await sendRest("create", {
691
- orgId: options2.orgId,
692
- userId: options2.userId,
693
- metadata: options2.metadata
694
- });
695
- if (!response?.chatKey) {
696
- throw new Error("Failed to create chat: no chatKey returned");
697
- }
698
- return { chatKey: response.chatKey };
699
- },
700
- async loadChatData(options2) {
701
- if (!config) {
702
- throw new Error("Transport not connected");
703
- }
704
- const response = await sendRest("load", {
705
- orgId: options2.orgId,
706
- chatKey: options2.chatKey,
707
- userId: options2.userId
708
- });
709
- if (!response?.chat) {
710
- throw new Error("Failed to load chat: no chat data returned");
711
- }
712
- return {
713
- chat: response.chat,
714
- agentId: response.agentId
715
- };
716
- },
717
- onMessage(handler) {
718
- globalHandlers.add(handler);
719
- return () => globalHandlers.delete(handler);
720
- },
721
- on(eventType, handler) {
722
- if (!typeHandlers.has(eventType)) {
723
- typeHandlers.set(eventType, /* @__PURE__ */ new Set());
724
- }
725
- typeHandlers.get(eventType).add(handler);
726
- return () => {
727
- const handlers = typeHandlers.get(eventType);
728
- if (handlers) {
729
- handlers.delete(handler);
730
- if (handlers.size === 0) {
731
- typeHandlers.delete(eventType);
732
- }
733
- }
734
- };
735
- },
736
- getState() {
737
- return state;
738
- },
739
- getMetrics() {
740
- return { ...metrics };
741
- },
742
- getError() {
743
- return error;
744
- },
745
- clearError() {
746
- error = void 0;
747
- }
748
- };
749
- return transport;
750
- }
751
-
752
- // hooks/use-chat.ts
753
- function getDefaultTransport(type, debug) {
754
- if (type === "sse-fetch") {
755
- return createFetchSSETransport({ debug });
756
- }
757
- if (type === "sse") {
758
- return createSSETransport({ debug });
759
- }
760
- const isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
761
- if (isReactNative || typeof EventSource === "undefined") {
762
- return createFetchSSETransport({ debug });
763
- }
764
- return createSSETransport({ debug });
765
- }
766
- function useChat(options) {
767
- const {
768
- baseUrl,
769
- orgId,
770
- userId,
771
- clientType = "customer",
772
- transport: transportOption,
773
- onMessage,
774
- onError,
775
- onConnectionChange,
776
- autoConnect = false,
777
- retryConfig,
778
- debug = false
779
- } = options;
780
- const [connectionState, setConnectionState] = useState("disconnected");
781
- const [currentChat, setCurrentChat] = useState(null);
782
- const [chatKey, setChatKey] = useState(null);
783
- const [messages, setMessages] = useState([]);
784
- const [error, setError] = useState(null);
785
- const [metrics, setMetrics] = useState({
786
- latency: 0,
787
- messagesSent: 0,
788
- messagesReceived: 0,
789
- messagesQueued: 0,
790
- reconnectCount: 0
791
- });
792
- const transportRef = useRef(null);
793
- const mountedRef = useRef(false);
794
- const onMessageRef = useRef(onMessage);
795
- const onErrorRef = useRef(onError);
796
- const typingTimeoutRef = useRef(null);
797
- useEffect(() => {
798
- onMessageRef.current = onMessage;
799
- onErrorRef.current = onError;
800
- }, [onMessage, onError]);
801
- useEffect(() => {
802
- if (typeof transportOption === "object") {
803
- transportRef.current = transportOption;
804
- } else {
805
- transportRef.current = getDefaultTransport(
806
- transportOption,
807
- debug
808
- );
809
- }
810
- }, [transportOption, debug]);
811
- const handleEvent = useCallback((event) => {
812
- if (!mountedRef.current) return;
813
- setMetrics((prev) => ({
814
- ...prev,
815
- messagesReceived: prev.messagesReceived + 1,
816
- lastMessageAt: Date.now()
817
- }));
818
- switch (event.type) {
819
- case "new_chat_created":
820
- const newChatKey = event.data?.chatKey;
821
- if (newChatKey) {
822
- setChatKey(newChatKey);
823
- }
824
- break;
825
- case "load_chat_response":
826
- const chat = event.data?.chat;
827
- if (chat) {
828
- setCurrentChat(chat);
829
- setChatKey(chat.key);
830
- setMessages(chat.messages || []);
831
- }
832
- break;
833
- case "message":
834
- if (event.message) {
835
- setMessages((prev) => [...prev, event.message]);
836
- }
837
- break;
838
- case "chat_ended":
839
- setCurrentChat(null);
840
- setChatKey(null);
841
- break;
842
- case "error":
843
- const errorMsg = event.data?.message;
844
- if (errorMsg) {
845
- const transportError = {
846
- code: "NETWORK_ERROR",
847
- message: errorMsg,
848
- retryable: true,
849
- timestamp: Date.now()
850
- };
851
- setError(transportError);
852
- onErrorRef.current?.(transportError);
853
- }
854
- break;
855
- }
856
- onMessageRef.current?.(event);
857
- }, []);
858
- const connect = useCallback(async () => {
859
- const transport = transportRef.current;
860
- if (!transport) {
861
- throw new Error("Transport not initialized");
862
- }
863
- if (!orgId) {
864
- const err = {
865
- code: "CONNECTION_FAILED",
866
- message: "orgId is required",
867
- retryable: false,
868
- timestamp: Date.now()
869
- };
870
- setError(err);
871
- throw err;
872
- }
873
- setConnectionState("connecting");
874
- onConnectionChange?.("connecting");
875
- try {
876
- const unsubscribe = transport.onMessage(handleEvent);
877
- await transport.connect({
878
- baseUrl,
879
- orgId,
880
- userId,
881
- clientType,
882
- chatKey: chatKey || void 0,
883
- debug
884
- });
885
- setConnectionState("connected");
886
- setError(null);
887
- setMetrics(transport.getMetrics());
888
- onConnectionChange?.("connected");
889
- return;
890
- } catch (err) {
891
- const transportError = err;
892
- setConnectionState("disconnected");
893
- onConnectionChange?.("disconnected");
894
- setError(transportError);
895
- onErrorRef.current?.(transportError);
896
- throw err;
897
- }
898
- }, [baseUrl, orgId, userId, clientType, chatKey, debug, handleEvent, onConnectionChange]);
899
- const disconnect = useCallback(() => {
900
- const transport = transportRef.current;
901
- if (transport) {
902
- transport.disconnect(true);
903
- }
904
- setConnectionState("disconnected");
905
- onConnectionChange?.("disconnected");
906
- }, [onConnectionChange]);
907
- const startChat = useCallback(
908
- async (metadata) => {
909
- const transport = transportRef.current;
910
- if (!transport) {
911
- throw new Error("Transport not initialized");
912
- }
913
- const response = await transport.createChat({
914
- orgId,
915
- userId,
916
- metadata
917
- });
918
- setChatKey(response.chatKey);
919
- return response.chatKey;
920
- },
921
- [orgId, userId]
922
- );
923
- const loadChat2 = useCallback(
924
- async (key) => {
925
- const transport = transportRef.current;
926
- if (!transport) {
927
- throw new Error("Transport not initialized");
928
- }
929
- const response = await transport.loadChatData({
930
- orgId,
931
- chatKey: key,
932
- userId
933
- });
934
- setCurrentChat(response.chat);
935
- setChatKey(response.chat.key);
936
- setMessages(response.chat.messages || []);
937
- return response.chat;
938
- },
939
- [orgId, userId]
940
- );
941
- const sendMessage = useCallback(
942
- async (content, attachments) => {
943
- const transport = transportRef.current;
944
- if (!transport) {
945
- throw new Error("Transport not initialized");
946
- }
947
- if (!chatKey) {
948
- throw new Error("No active chat");
949
- }
950
- const message = {
951
- id: `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`,
952
- role: "user",
953
- content,
954
- time: Date.now(),
955
- status: "sending",
956
- senderId: userId,
957
- createdAt: Date.now(),
958
- attachments
959
- };
960
- setMessages((prev) => [...prev, message]);
961
- await transport.send({
962
- type: "message",
963
- orgId,
964
- chatKey,
965
- userId,
966
- timestamp: Date.now(),
967
- message
968
- });
969
- setMetrics((prev) => ({
970
- ...prev,
971
- messagesSent: prev.messagesSent + 1
972
- }));
973
- },
974
- [orgId, chatKey, userId]
975
- );
976
- const endChat2 = useCallback(
977
- async (reason) => {
978
- const transport = transportRef.current;
979
- if (!transport) {
980
- throw new Error("Transport not initialized");
981
- }
982
- if (!chatKey) {
983
- return;
984
- }
985
- await transport.send({
986
- type: "end_chat",
987
- orgId,
988
- chatKey,
989
- userId,
990
- timestamp: Date.now(),
991
- data: reason ? { reason } : void 0
992
- });
993
- setCurrentChat(null);
994
- setChatKey(null);
995
- },
996
- [orgId, chatKey, userId]
997
- );
998
- const sendEvent2 = useCallback(
999
- async (event) => {
1000
- const transport = transportRef.current;
1001
- if (!transport) {
1002
- throw new Error("Transport not initialized");
1003
- }
1004
- await transport.send({
1005
- ...event,
1006
- timestamp: Date.now()
1007
- });
1008
- },
1009
- []
1010
- );
1011
- const startTyping = useCallback(() => {
1012
- const transport = transportRef.current;
1013
- if (!transport || !chatKey) return;
1014
- if (typingTimeoutRef.current) {
1015
- clearTimeout(typingTimeoutRef.current);
1016
- }
1017
- transport.send({
1018
- type: "typing",
1019
- orgId,
1020
- chatKey,
1021
- userId,
1022
- timestamp: Date.now()
1023
- }).catch(() => {
1024
- });
1025
- typingTimeoutRef.current = setTimeout(() => {
1026
- stopTyping();
1027
- }, 3e3);
1028
- }, [orgId, chatKey, userId]);
1029
- const stopTyping = useCallback(() => {
1030
- const transport = transportRef.current;
1031
- if (!transport || !chatKey) return;
1032
- if (typingTimeoutRef.current) {
1033
- clearTimeout(typingTimeoutRef.current);
1034
- typingTimeoutRef.current = null;
1035
- }
1036
- transport.send({
1037
- type: "stopped_typing",
1038
- orgId,
1039
- chatKey,
1040
- userId,
1041
- timestamp: Date.now()
1042
- }).catch(() => {
1043
- });
1044
- }, [orgId, chatKey, userId]);
1045
- const on = useCallback(
1046
- (eventType, handler) => {
1047
- const transport = transportRef.current;
1048
- if (!transport) {
1049
- return () => {
1050
- };
1051
- }
1052
- return transport.on(eventType, handler);
1053
- },
1054
- []
1055
- );
1056
- const clearError = useCallback(() => {
1057
- setError(null);
1058
- transportRef.current?.clearError();
1059
- }, []);
1060
- useEffect(() => {
1061
- mountedRef.current = true;
1062
- if (autoConnect) {
1063
- connect().catch(() => {
1064
- });
1065
- }
1066
- return () => {
1067
- mountedRef.current = false;
1068
- if (typingTimeoutRef.current) {
1069
- clearTimeout(typingTimeoutRef.current);
1070
- }
1071
- disconnect();
1072
- };
1073
- }, []);
1074
- const isConnected = connectionState === "connected";
1075
- return {
1076
- // Connection
1077
- connect,
1078
- disconnect,
1079
- connectionState,
1080
- isConnected,
1081
- // Chat operations
1082
- startChat,
1083
- loadChat: loadChat2,
1084
- sendMessage,
1085
- sendEvent: sendEvent2,
1086
- endChat: endChat2,
1087
- // Typing
1088
- startTyping,
1089
- stopTyping,
1090
- // State
1091
- currentChat,
1092
- chatKey,
1093
- messages,
1094
- error,
1095
- metrics,
1096
- // Events
1097
- on,
1098
- clearError
1099
- };
1100
- }
1101
-
1102
- // hooks/use-chat-history.ts
1103
- import { useMemo } from "react";
1104
-
1105
- // api/index.ts
1106
- import { browserApiRequest as browserApiRequest2 } from "@elqnt/api-client/browser";
1107
-
1108
- // api/memory.ts
1109
- import { browserApiRequest } from "@elqnt/api-client/browser";
1110
- var patchProfileApi = (patch, o) => browserApiRequest("/api/v1/memory/profile", { method: "PATCH", body: patch, ...o });
1111
- var replaceProfileApi = (p, o) => browserApiRequest("/api/v1/memory/profile", { method: "PUT", body: p, ...o });
1112
- var clearProfileApi = (o) => browserApiRequest("/api/v1/memory/profile", { method: "DELETE", ...o });
1113
- var deleteContactApi = (name, o) => browserApiRequest(`/api/v1/memory/profile/contacts/${encodeURIComponent(name)}`, { method: "DELETE", ...o });
1114
- var deleteNoteApi = (index, o) => browserApiRequest(`/api/v1/memory/profile/notes/${index}`, { method: "DELETE", ...o });
1115
- var clearSummaryApi = (chatKey, o) => browserApiRequest(`/api/v1/chats/${chatKey}/summary`, { method: "DELETE", ...o });
1116
- var regenerateSummaryApi = (chatKey, o) => browserApiRequest(`/api/v1/chats/${chatKey}/summary/regenerate`, { method: "POST", ...o });
1117
-
1118
- // api/index.ts
1119
- async function getChatHistoryApi(options) {
1120
- return browserApiRequest2("/api/v1/chats", {
1121
- method: "POST",
1122
- body: {
1123
- limit: options.limit || 15,
1124
- offset: options.offset || 0,
1125
- ...options.skipCache ? { skipCache: true } : {}
1126
- },
1127
- ...options
1128
- });
1129
- }
1130
- async function getChatApi(chatKey, options) {
1131
- return browserApiRequest2(`/api/v1/chats/${chatKey}`, {
1132
- method: "GET",
1133
- ...options
1134
- });
1135
- }
1136
- async function updateChatApi(chatKey, updates, options) {
1137
- return browserApiRequest2(`/api/v1/chats/${chatKey}`, {
1138
- method: "PATCH",
1139
- body: updates,
1140
- ...options
1141
- });
1142
- }
1143
- async function deleteChatApi(chatKey, options) {
1144
- return browserApiRequest2(`/api/v1/chats/${chatKey}`, {
1145
- method: "DELETE",
1146
- ...options
1147
- });
1148
- }
1149
- async function getActiveChatsCountApi(options) {
1150
- return browserApiRequest2("/api/v1/chats/active/count", {
1151
- method: "GET",
1152
- ...options
1153
- });
1154
- }
1155
- async function getActiveChatsApi(options) {
1156
- const params = new URLSearchParams();
1157
- if (options.pastHours) params.set("pastHours", String(options.pastHours));
1158
- const queryString = params.toString();
1159
- return browserApiRequest2(`/api/v1/chats/active${queryString ? `?${queryString}` : ""}`, {
1160
- method: "GET",
1161
- ...options
1162
- });
1163
- }
1164
- async function getWaitingChatsCountApi(options) {
1165
- return browserApiRequest2("/api/v1/chats/waiting/count", {
1166
- method: "GET",
1167
- ...options
1168
- });
1169
- }
1170
- async function getChatsByUserApi(userEmail, options) {
1171
- return browserApiRequest2(`/api/v1/chats/user/${encodeURIComponent(userEmail)}`, {
1172
- method: "GET",
1173
- ...options
1174
- });
1175
- }
1176
- async function listQueuesApi(options) {
1177
- return browserApiRequest2("/api/v1/queues", {
1178
- method: "GET",
1179
- ...options
1180
- });
1181
- }
1182
- async function getOnlineSessionsApi(options) {
1183
- return browserApiRequest2("/api/v1/agents/sessions/online", {
1184
- method: "GET",
1185
- ...options
1186
- });
1187
- }
1188
- async function getAgentSessionApi(agentId, options) {
1189
- return browserApiRequest2(`/api/v1/agents/sessions/${agentId}`, {
1190
- method: "GET",
1191
- ...options
1192
- });
1193
- }
1194
-
1195
- // hooks/use-chat-history.ts
1196
- import { useApiAsync } from "@elqnt/api-client/hooks";
1197
-
1198
- // hooks/use-options-ref.ts
1199
- import { useRef as useRef2, useEffect as useEffect2 } from "react";
1200
- function useOptionsRef(options) {
1201
- const optionsRef = useRef2(options);
1202
- useEffect2(() => {
1203
- optionsRef.current = options;
1204
- }, [options]);
1205
- return optionsRef;
1206
- }
1207
-
1208
- // hooks/use-chat-history.ts
1209
- function useChatHistory(options) {
1210
- const optionsRef = useOptionsRef(options);
1211
- const { execute: getChatHistory, loading: listLoading, error: listError } = useApiAsync(
1212
- (params) => getChatHistoryApi({ ...optionsRef.current, ...params }),
1213
- (data) => ({
1214
- chats: data.chats,
1215
- total: data.total,
1216
- hasMore: data.hasMore
1217
- }),
1218
- { chats: [], total: 0, hasMore: false }
1219
- );
1220
- const { execute: getChat, loading: getLoading, error: getError } = useApiAsync(
1221
- (chatKey) => getChatApi(chatKey, optionsRef.current),
1222
- (data) => data.chat || null,
1223
- null
1224
- );
1225
- const { execute: updateChat, loading: updateLoading, error: updateError } = useApiAsync(
1226
- (chatKey, updates) => updateChatApi(chatKey, updates, optionsRef.current),
1227
- (data) => !!data.chatKey,
1228
- false
1229
- );
1230
- const { execute: deleteChat, loading: deleteLoading, error: deleteError } = useApiAsync(
1231
- (chatKey) => deleteChatApi(chatKey, optionsRef.current),
1232
- (data) => data.success,
1233
- false
1234
- );
1235
- const { execute: getChatsByUser, loading: userChatsLoading, error: userChatsError } = useApiAsync(
1236
- (userEmail) => getChatsByUserApi(userEmail, optionsRef.current),
1237
- (data) => data.chats,
1238
- []
1239
- );
1240
- const loading = listLoading || getLoading || updateLoading || deleteLoading || userChatsLoading;
1241
- const error = listError || getError || updateError || deleteError || userChatsError;
1242
- return useMemo(
1243
- () => ({
1244
- loading,
1245
- error,
1246
- getChatHistory,
1247
- getChat,
1248
- updateChat,
1249
- deleteChat,
1250
- getChatsByUser
1251
- }),
1252
- [loading, error, getChatHistory, getChat, updateChat, deleteChat, getChatsByUser]
1253
- );
1254
- }
1255
-
1256
- // hooks/use-chat-monitoring.ts
1257
- import { useMemo as useMemo2 } from "react";
1258
- import { useApiAsync as useApiAsync2 } from "@elqnt/api-client/hooks";
1259
- function useChatMonitoring(options) {
1260
- const optionsRef = useOptionsRef(options);
1261
- const { execute: getActiveChats, loading: activeLoading, error: activeError } = useApiAsync2(
1262
- (pastHours) => getActiveChatsApi({ ...optionsRef.current, pastHours }),
1263
- (data) => data.chats,
1264
- []
1265
- );
1266
- const { execute: getActiveChatsCount, loading: activeCountLoading, error: activeCountError } = useApiAsync2(
1267
- () => getActiveChatsCountApi(optionsRef.current),
1268
- (data) => data.count,
1269
- 0
1270
- );
1271
- const { execute: getWaitingChatsCount, loading: waitingCountLoading, error: waitingCountError } = useApiAsync2(
1272
- () => getWaitingChatsCountApi(optionsRef.current),
1273
- (data) => data.count,
1274
- 0
1275
- );
1276
- const { execute: listQueues, loading: queuesLoading, error: queuesError } = useApiAsync2(
1277
- () => listQueuesApi(optionsRef.current),
1278
- (data) => data.queues,
1279
- []
1280
- );
1281
- const loading = activeLoading || activeCountLoading || waitingCountLoading || queuesLoading;
1282
- const error = activeError || activeCountError || waitingCountError || queuesError;
1283
- return useMemo2(
1284
- () => ({
1285
- loading,
1286
- error,
1287
- getActiveChats,
1288
- getActiveChatsCount,
1289
- getWaitingChatsCount,
1290
- listQueues
1291
- }),
1292
- [loading, error, getActiveChats, getActiveChatsCount, getWaitingChatsCount, listQueues]
1293
- );
1294
- }
1295
-
1296
- // hooks/use-human-agent-sessions.ts
1297
- import { useMemo as useMemo3 } from "react";
1298
- import { useApiAsync as useApiAsync3 } from "@elqnt/api-client/hooks";
1299
- function useHumanAgentSessions(options) {
1300
- const optionsRef = useOptionsRef(options);
1301
- const { execute: getOnlineSessions, loading: onlineLoading, error: onlineError } = useApiAsync3(
1302
- () => getOnlineSessionsApi(optionsRef.current),
1303
- (data) => data.sessions,
1304
- []
1305
- );
1306
- const { execute: getAgentSession, loading: sessionLoading, error: sessionError } = useApiAsync3(
1307
- (agentId) => getAgentSessionApi(agentId, optionsRef.current),
1308
- (data) => data.session || null,
1309
- null
1310
- );
1311
- const loading = onlineLoading || sessionLoading;
1312
- const error = onlineError || sessionError;
1313
- return useMemo3(
1314
- () => ({
1315
- loading,
1316
- error,
1317
- getOnlineSessions,
1318
- getAgentSession
1319
- }),
1320
- [loading, error, getOnlineSessions, getAgentSession]
1321
- );
1322
- }
1323
-
1324
- // hooks/use-memory.ts
1325
- import { useCallback as useCallback2, useRef as useRef3, useState as useState2 } from "react";
1326
- function useMemory(options, initialProfile = null) {
1327
- const [profile, setProfile] = useState2(initialProfile);
1328
- const [loading, setLoading] = useState2(false);
1329
- const requestCountRef = useRef3(0);
1330
- const runProfileMutation = useCallback2(
1331
- async (fn) => {
1332
- requestCountRef.current += 1;
1333
- setLoading(true);
1334
- try {
1335
- const response = await fn();
1336
- if (!response.error && response.data) {
1337
- setProfile(response.data);
1338
- return response.data;
1339
- }
1340
- return null;
1341
- } catch {
1342
- return null;
1343
- } finally {
1344
- requestCountRef.current -= 1;
1345
- if (requestCountRef.current === 0) {
1346
- setLoading(false);
1347
- }
1348
- }
1349
- },
1350
- []
1351
- );
1352
- const optionsRef = useRef3(options);
1353
- optionsRef.current = options;
1354
- const patchProfile = useCallback2(
1355
- (patch) => runProfileMutation(() => patchProfileApi(patch, optionsRef.current)),
1356
- [runProfileMutation]
1357
- );
1358
- const replaceProfile = useCallback2(
1359
- (p) => runProfileMutation(() => replaceProfileApi(p, optionsRef.current)),
1360
- [runProfileMutation]
1361
- );
1362
- const clearProfile = useCallback2(
1363
- () => runProfileMutation(() => clearProfileApi(optionsRef.current)),
1364
- [runProfileMutation]
1365
- );
1366
- const deleteContact = useCallback2(
1367
- (name) => runProfileMutation(() => deleteContactApi(name, optionsRef.current)),
1368
- [runProfileMutation]
1369
- );
1370
- const deleteNote = useCallback2(
1371
- (index) => runProfileMutation(() => deleteNoteApi(index, optionsRef.current)),
1372
- [runProfileMutation]
1373
- );
1374
- const clearSummary = useCallback2(
1375
- async (chatKey) => {
1376
- await clearSummaryApi(chatKey, optionsRef.current);
1377
- },
1378
- []
1379
- );
1380
- const regenerateSummary = useCallback2(
1381
- async (chatKey) => {
1382
- const response = await regenerateSummaryApi(chatKey, optionsRef.current);
1383
- if (!response.error && response.data) {
1384
- return response.data;
1385
- }
1386
- return null;
1387
- },
1388
- []
1389
- );
1390
- return {
1391
- profile,
1392
- loading,
1393
- patchProfile,
1394
- replaceProfile,
1395
- clearProfile,
1396
- deleteContact,
1397
- deleteNote,
1398
- clearSummary,
1399
- regenerateSummary
1400
- };
1401
- }
1402
-
1403
- // hooks/index.ts
1404
- import { useApiAsync as useApiAsync4 } from "@elqnt/api-client/hooks";
1405
-
1406
1
  // models/chat-models.ts
1407
2
  var ChatStatusActive = "active";
1408
3
  var ChatStatusDisconnected = "disconnected";
@@ -1434,6 +29,7 @@ var ChatEventTypeStoppedTyping = "stopped_typing";
1434
29
  var ChatEventTypeRead = "read";
1435
30
  var ChatEventTypeDelivered = "delivered";
1436
31
  var ChatEventTypeReconnected = "reconnected";
32
+ var ChatEventTypeTransportReconnected = "transport_reconnected";
1437
33
  var ChatEventTypeError = "error";
1438
34
  var ChatEventTypeWaiting = "waiting";
1439
35
  var ChatEventTypeLoadChat = "load_chat";
@@ -1573,6 +169,9 @@ var GetActiveChatsSubject = "chat.get_active_chats";
1573
169
  var GetUserChatsSubject = "chat.get_user_chats";
1574
170
  var GetChatSubject = "chat.get_chat";
1575
171
  var ChatArchiveSubjectPattern = "chat.archive.%s.server";
172
+ var ListIdleChatsSubject = "chat.maintenance.list_idle_chats";
173
+ var CloseAndDeleteChatSubject = "chat.maintenance.close_and_delete_chat";
174
+ var MarkChatClosedSubject = "chat.maintenance.mark_closed";
1576
175
  var StartAgentSessionSubject = "chat.agent_session.start";
1577
176
  var EndAgentSessionSubject = "chat.agent_session.end";
1578
177
  var UpdateAgentStatusSubject = "chat.agent_session.update_status";
@@ -1703,6 +302,7 @@ export {
1703
302
  ChatEventTypeSyncMetadataResponse,
1704
303
  ChatEventTypeSyncUserSession,
1705
304
  ChatEventTypeSyncUserSessionResponse,
305
+ ChatEventTypeTransportReconnected,
1706
306
  ChatEventTypeTyping,
1707
307
  ChatEventTypeUpdateRoom,
1708
308
  ChatEventTypeUserActivity,
@@ -1741,6 +341,7 @@ export {
1741
341
  ChatTypeGroup,
1742
342
  ChatTypePrivateRoom,
1743
343
  ChatTypePublicRoom,
344
+ CloseAndDeleteChatSubject,
1744
345
  CompleteChatByAgentSubject,
1745
346
  CreateAgentQueueSubject,
1746
347
  DeleteAgentQueueSubject,
@@ -1760,6 +361,8 @@ export {
1760
361
  GetUserChatsSubject,
1761
362
  GetWaitingForAgentChatCountSubject,
1762
363
  GetWaitingForAgentChatsSubject,
364
+ ListIdleChatsSubject,
365
+ MarkChatClosedSubject,
1763
366
  MessageStatusDelivered,
1764
367
  MessageStatusFailed,
1765
368
  MessageStatusRead,
@@ -1781,13 +384,6 @@ export {
1781
384
  UserStatusAway,
1782
385
  UserStatusBusy,
1783
386
  UserStatusOffline,
1784
- UserStatusOnline,
1785
- useApiAsync4 as useApiAsync,
1786
- useChat,
1787
- useChatHistory,
1788
- useChatMonitoring,
1789
- useHumanAgentSessions,
1790
- useMemory,
1791
- useOptionsRef
387
+ UserStatusOnline
1792
388
  };
1793
389
  //# sourceMappingURL=index.mjs.map