@theonexai/chartsconnect-chat-widget 1.0.34 → 1.0.36
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/{ChatWidget-lohWj44a.js → ChatWidget-CYjfNp7_.js} +165 -105
- package/dist/ChatWidget-CYjfNp7_.js.map +1 -0
- package/dist/ChatWidget-CmD28RZX.cjs +2 -0
- package/dist/ChatWidget-CmD28RZX.cjs.map +1 -0
- package/dist/adapters/vue/useChatMode.d.ts +3 -4
- package/dist/adapters/vue/useChatMode.d.ts.map +1 -1
- package/dist/components/ChatWidget.d.ts +1 -3
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/core/stateManager.d.ts +6 -3
- package/dist/core/stateManager.d.ts.map +1 -1
- package/dist/core/types.d.ts +0 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/entry/vite.d.ts +1 -1
- package/dist/hooks/useChatMode.d.ts.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.esm.js +1063 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/nuxt.cjs.js +1 -1
- package/dist/nuxt.esm.js +2 -2
- package/dist/sanitize-DBcaF543.cjs +4 -0
- package/dist/sanitize-DBcaF543.cjs.map +1 -0
- package/dist/{types-BlZ1psq3.js → sanitize-qxjS5QaO.js} +30 -57
- package/dist/sanitize-qxjS5QaO.js.map +1 -0
- package/dist/services/chatService.d.ts +5 -19
- package/dist/services/chatService.d.ts.map +1 -1
- package/dist/services/dialogflowBackendService.d.ts +0 -2
- package/dist/services/dialogflowBackendService.d.ts.map +1 -1
- package/dist/services/dialogflowClient.d.ts +36 -0
- package/dist/services/dialogflowClient.d.ts.map +1 -0
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/vue.cjs.js +1 -1
- package/dist/vue.esm.js +2 -2
- package/package.json +4 -9
- package/dist/ChatWidget-B6IV4jti.cjs +0 -2
- package/dist/ChatWidget-B6IV4jti.cjs.map +0 -1
- package/dist/ChatWidget-C1DUqlCm.js +0 -1307
- package/dist/ChatWidget-C1DUqlCm.js.map +0 -1
- package/dist/ChatWidget-lohWj44a.js.map +0 -1
- package/dist/ChatWidget-tA9Ibu8c.cjs +0 -2
- package/dist/ChatWidget-tA9Ibu8c.cjs.map +0 -1
- package/dist/next.cjs.js +0 -2
- package/dist/next.cjs.js.map +0 -1
- package/dist/next.esm.js +0 -9
- package/dist/next.esm.js.map +0 -1
- package/dist/react.cjs.js +0 -2
- package/dist/react.cjs.js.map +0 -1
- package/dist/react.esm.js +0 -5
- package/dist/react.esm.js.map +0 -1
- package/dist/types-BlZ1psq3.js.map +0 -1
- package/dist/types-CSeUPcTU.cjs +0 -4
- package/dist/types-CSeUPcTU.cjs.map +0 -1
- package/dist/vite.cjs.js +0 -2
- package/dist/vite.cjs.js.map +0 -1
- package/dist/vite.esm.js +0 -5
- package/dist/vite.esm.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ref, computed, onUnmounted, watch, defineComponent, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createElementVNode, toDisplayString, withModifiers, createCommentVNode, createTextVNode, Fragment, renderList, normalizeClass } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { c as createChatService, a as createDialogflowSession, C as ChatResolvedError, s as sendDialogflowMessage, b as safeLinkifyText } from "./sanitize-qxjS5QaO.js";
|
|
3
3
|
class WidgetStateManager {
|
|
4
4
|
constructor(config) {
|
|
5
5
|
this.listeners = /* @__PURE__ */ new Set();
|
|
@@ -16,7 +16,6 @@ class WidgetStateManager {
|
|
|
16
16
|
this.historyLoaded = null;
|
|
17
17
|
this.typingTimeout = null;
|
|
18
18
|
this.agentTypingTimeout = null;
|
|
19
|
-
this.welcomePopupTimeout = null;
|
|
20
19
|
this.config = config;
|
|
21
20
|
this.state = {
|
|
22
21
|
isOpen: false,
|
|
@@ -28,15 +27,13 @@ class WidgetStateManager {
|
|
|
28
27
|
sessionId: null,
|
|
29
28
|
chatMode: "ai"
|
|
30
29
|
};
|
|
31
|
-
const baseUrl = this.config.backendBaseUrl || "http://localhost:8012";
|
|
32
|
-
const wsUrl = this.config.backendWsUrl || baseUrl.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
|
|
33
30
|
this.chatService = createChatService({
|
|
34
|
-
baseUrl,
|
|
35
|
-
wsUrl,
|
|
31
|
+
baseUrl: this.config.backendBaseUrl || "http://localhost:8012",
|
|
32
|
+
wsUrl: this.config.backendWsUrl || "ws://localhost:8012",
|
|
36
33
|
debug: this.config.debug || false
|
|
37
34
|
});
|
|
38
35
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
39
|
-
const savedMode = localStorage.getItem("
|
|
36
|
+
const savedMode = localStorage.getItem("chartsconnectect_chat_mode");
|
|
40
37
|
this.chatMode = savedMode === "HUMAN" ? "human" : "ai";
|
|
41
38
|
this.state.chatMode = this.chatMode;
|
|
42
39
|
this.chatId = localStorage.getItem("chartsconnect_chat_id");
|
|
@@ -96,7 +93,7 @@ class WidgetStateManager {
|
|
|
96
93
|
});
|
|
97
94
|
if (session.message) {
|
|
98
95
|
const welcomeMessage = {
|
|
99
|
-
id:
|
|
96
|
+
id: `welcome-${Date.now()}`,
|
|
100
97
|
text: session.message,
|
|
101
98
|
sender: "bot",
|
|
102
99
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -113,7 +110,7 @@ class WidgetStateManager {
|
|
|
113
110
|
error: error.message || "Failed to initialize chat"
|
|
114
111
|
});
|
|
115
112
|
const fallbackMessage = {
|
|
116
|
-
id:
|
|
113
|
+
id: `fallback-${Date.now()}`,
|
|
117
114
|
text: this.config.fallbackWelcomeMessage || "Hello! How can I help you today?",
|
|
118
115
|
sender: "bot",
|
|
119
116
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -139,11 +136,11 @@ class WidgetStateManager {
|
|
|
139
136
|
/**
|
|
140
137
|
* Toggle chat
|
|
141
138
|
*/
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
139
|
+
toggleChat() {
|
|
140
|
+
const willBeOpen = !this.state.isOpen;
|
|
141
|
+
this.setState({ isOpen: willBeOpen });
|
|
142
|
+
if (willBeOpen && this.state.showWelcomePopup) {
|
|
143
|
+
this.setState({ showWelcomePopup: false });
|
|
147
144
|
}
|
|
148
145
|
}
|
|
149
146
|
/**
|
|
@@ -167,7 +164,7 @@ class WidgetStateManager {
|
|
|
167
164
|
}
|
|
168
165
|
if (!skipUserMessage) {
|
|
169
166
|
const userMessage = {
|
|
170
|
-
id:
|
|
167
|
+
id: `user-${Date.now()}`,
|
|
171
168
|
text: text.trim(),
|
|
172
169
|
sender: "user",
|
|
173
170
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -198,7 +195,7 @@ class WidgetStateManager {
|
|
|
198
195
|
return;
|
|
199
196
|
}
|
|
200
197
|
const errorMessage = {
|
|
201
|
-
id:
|
|
198
|
+
id: `error-${Date.now()}`,
|
|
202
199
|
text: this.config.debug ? `Error: ${error.message || "Failed to send message"}` : error.message?.includes("CORS") || error.message?.includes("Failed to fetch") ? "Unable to connect to Dialogflow. Please check your configuration and network." : "Sorry, I'm having trouble processing your message. Please try again.",
|
|
203
200
|
sender: "bot",
|
|
204
201
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -248,73 +245,31 @@ class WidgetStateManager {
|
|
|
248
245
|
});
|
|
249
246
|
}
|
|
250
247
|
if (response.handoff === true) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
text: response.response,
|
|
255
|
-
sender: "bot",
|
|
256
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
257
|
-
richContent: response.richContent
|
|
258
|
-
};
|
|
259
|
-
this.setState({
|
|
260
|
-
messages: [...this.state.messages, botMessage],
|
|
261
|
-
isLoading: false
|
|
262
|
-
});
|
|
263
|
-
} else {
|
|
264
|
-
this.setState({ isLoading: false });
|
|
265
|
-
}
|
|
266
|
-
if (response.chat_id && response.support_session_id) {
|
|
267
|
-
this.chatId = response.chat_id;
|
|
268
|
-
this.supportSessionId = response.support_session_id;
|
|
269
|
-
if (typeof window !== "undefined" && window.localStorage) {
|
|
270
|
-
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
271
|
-
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
272
|
-
}
|
|
273
|
-
this.switchToHumanMode();
|
|
274
|
-
this.chatResolved = false;
|
|
275
|
-
this.agentAccepted = false;
|
|
276
|
-
const connectingMessage = {
|
|
277
|
-
id: generateMessageId("connecting"),
|
|
278
|
-
text: "Connecting you to a human agent...",
|
|
279
|
-
sender: "bot",
|
|
280
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
281
|
-
};
|
|
282
|
-
this.setState({
|
|
283
|
-
messages: [...this.state.messages, connectingMessage]
|
|
284
|
-
});
|
|
285
|
-
if (this.chatService) {
|
|
286
|
-
this.chatService.connectWebSocket(
|
|
287
|
-
this.chatId,
|
|
288
|
-
this.supportSessionId,
|
|
289
|
-
(message) => {
|
|
290
|
-
this.handleWebSocketMessage(message);
|
|
291
|
-
},
|
|
292
|
-
(connected) => {
|
|
293
|
-
this.wsConnected = connected;
|
|
294
|
-
}
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
this.isConnectingToAgent = false;
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const responseText = response.response || "";
|
|
303
|
-
if (responseText) {
|
|
304
|
-
const botMessage = {
|
|
305
|
-
id: generateMessageId("bot"),
|
|
306
|
-
text: responseText,
|
|
248
|
+
const botMessage2 = {
|
|
249
|
+
id: `bot-${Date.now()}`,
|
|
250
|
+
text: response.response || this.config.fallbackWelcomeMessage || "No response",
|
|
307
251
|
sender: "bot",
|
|
308
252
|
timestamp: /* @__PURE__ */ new Date(),
|
|
309
253
|
richContent: response.richContent
|
|
310
254
|
};
|
|
311
255
|
this.setState({
|
|
312
|
-
messages: [...this.state.messages,
|
|
256
|
+
messages: [...this.state.messages, botMessage2],
|
|
313
257
|
isLoading: false
|
|
314
258
|
});
|
|
315
|
-
|
|
316
|
-
|
|
259
|
+
await this.handleHandoff();
|
|
260
|
+
return;
|
|
317
261
|
}
|
|
262
|
+
const botMessage = {
|
|
263
|
+
id: `bot-${Date.now()}`,
|
|
264
|
+
text: response.response || this.config.fallbackWelcomeMessage || "No response",
|
|
265
|
+
sender: "bot",
|
|
266
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
267
|
+
richContent: response.richContent
|
|
268
|
+
};
|
|
269
|
+
this.setState({
|
|
270
|
+
messages: [...this.state.messages, botMessage],
|
|
271
|
+
isLoading: false
|
|
272
|
+
});
|
|
318
273
|
}
|
|
319
274
|
/**
|
|
320
275
|
* Send message to human support
|
|
@@ -322,7 +277,7 @@ class WidgetStateManager {
|
|
|
322
277
|
async sendHumanMessage(text) {
|
|
323
278
|
if (!this.chatId || !this.supportSessionId) {
|
|
324
279
|
const errorMessage = {
|
|
325
|
-
id:
|
|
280
|
+
id: `error-${Date.now()}`,
|
|
326
281
|
text: "Chat session not initialized. Please try again.",
|
|
327
282
|
sender: "bot",
|
|
328
283
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -364,10 +319,7 @@ class WidgetStateManager {
|
|
|
364
319
|
}
|
|
365
320
|
try {
|
|
366
321
|
const newSession = await this.chatService.startSupportChat(
|
|
367
|
-
this.state.sessionId || null
|
|
368
|
-
null,
|
|
369
|
-
null,
|
|
370
|
-
null
|
|
322
|
+
this.state.sessionId || null
|
|
371
323
|
);
|
|
372
324
|
this.chatId = newSession.chat_id;
|
|
373
325
|
this.supportSessionId = newSession.session_id;
|
|
@@ -422,14 +374,129 @@ class WidgetStateManager {
|
|
|
422
374
|
initializeWelcomePopup() {
|
|
423
375
|
if (this.config.showWelcomePopup !== false) {
|
|
424
376
|
const delay = this.config.welcomePopupDelay || 1500;
|
|
425
|
-
|
|
426
|
-
this.welcomePopupTimeout = null;
|
|
377
|
+
setTimeout(() => {
|
|
427
378
|
if (!this.state.isOpen) {
|
|
428
379
|
this.setState({ showWelcomePopup: true });
|
|
429
380
|
}
|
|
430
381
|
}, delay);
|
|
431
382
|
}
|
|
432
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Handle handoff from Dialogflow to human support
|
|
386
|
+
*/
|
|
387
|
+
async handleHandoff() {
|
|
388
|
+
if (!this.chatService) {
|
|
389
|
+
throw new Error("Chat service not initialized");
|
|
390
|
+
}
|
|
391
|
+
try {
|
|
392
|
+
this.isConnectingToAgent = true;
|
|
393
|
+
const dialogflowSessionId = this.state.sessionId;
|
|
394
|
+
const session = await this.chatService.ensureChatInitialized(
|
|
395
|
+
this.chatId,
|
|
396
|
+
this.supportSessionId,
|
|
397
|
+
dialogflowSessionId || null
|
|
398
|
+
);
|
|
399
|
+
if (!session || !session.chat_id) {
|
|
400
|
+
throw new Error("Failed to initialize chat session");
|
|
401
|
+
}
|
|
402
|
+
const currentChatId = session.chat_id;
|
|
403
|
+
const currentSupportSessionId = session.session_id;
|
|
404
|
+
if (currentChatId !== this.chatId) {
|
|
405
|
+
this.chatId = currentChatId;
|
|
406
|
+
this.supportSessionId = currentSupportSessionId;
|
|
407
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
408
|
+
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
409
|
+
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
410
|
+
}
|
|
411
|
+
if (this.config.debug) {
|
|
412
|
+
console.log("✅ Chat initialized:", { chatId: currentChatId, sessionId: currentSupportSessionId });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
await this.chatService.requestHandoff(
|
|
417
|
+
currentChatId,
|
|
418
|
+
currentSupportSessionId,
|
|
419
|
+
"Customer requested human agent",
|
|
420
|
+
dialogflowSessionId || null
|
|
421
|
+
);
|
|
422
|
+
if (this.config.debug) {
|
|
423
|
+
console.log("✅ Handoff requested successfully");
|
|
424
|
+
}
|
|
425
|
+
} catch (handoffError) {
|
|
426
|
+
if (handoffError.message?.includes("Invalid chat_id") || handoffError.message?.includes("Chat not found") || handoffError.message?.includes("unauthorized") || handoffError.message?.includes("400") || handoffError.message?.includes("401") || handoffError.message?.includes("404") || handoffError.message?.includes("expired")) {
|
|
427
|
+
if (this.config.debug) {
|
|
428
|
+
console.log("⚠️ Chat expired or not found. Re-initializing chat...");
|
|
429
|
+
}
|
|
430
|
+
this.chatId = null;
|
|
431
|
+
this.supportSessionId = null;
|
|
432
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
433
|
+
localStorage.removeItem("chartsconnect_chat_id");
|
|
434
|
+
localStorage.removeItem("chartsconnect_session_id");
|
|
435
|
+
}
|
|
436
|
+
const newSession = await this.chatService.startSupportChat(
|
|
437
|
+
dialogflowSessionId || null
|
|
438
|
+
);
|
|
439
|
+
if (!newSession || !newSession.chat_id) {
|
|
440
|
+
throw new Error("Failed to re-initialize chat session");
|
|
441
|
+
}
|
|
442
|
+
this.chatId = newSession.chat_id;
|
|
443
|
+
this.supportSessionId = newSession.session_id;
|
|
444
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
445
|
+
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
446
|
+
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
447
|
+
}
|
|
448
|
+
await this.chatService.requestHandoff(
|
|
449
|
+
this.chatId,
|
|
450
|
+
this.supportSessionId,
|
|
451
|
+
"Customer requested human agent",
|
|
452
|
+
dialogflowSessionId || null
|
|
453
|
+
);
|
|
454
|
+
if (this.config.debug) {
|
|
455
|
+
console.log("✅ Handoff requested successfully after retry");
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
throw handoffError;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
this.switchToHumanMode();
|
|
462
|
+
this.chatResolved = false;
|
|
463
|
+
this.agentAccepted = false;
|
|
464
|
+
const connectingMessage = {
|
|
465
|
+
id: `connecting-${Date.now()}`,
|
|
466
|
+
text: "Connecting you to a human agent...",
|
|
467
|
+
sender: "bot",
|
|
468
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
469
|
+
};
|
|
470
|
+
this.setState({
|
|
471
|
+
messages: [...this.state.messages, connectingMessage]
|
|
472
|
+
});
|
|
473
|
+
if (currentChatId && currentSupportSessionId) {
|
|
474
|
+
this.chatService.connectWebSocket(
|
|
475
|
+
currentChatId,
|
|
476
|
+
currentSupportSessionId,
|
|
477
|
+
(message) => {
|
|
478
|
+
this.handleWebSocketMessage(message);
|
|
479
|
+
},
|
|
480
|
+
(connected) => {
|
|
481
|
+
this.wsConnected = connected;
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
this.isConnectingToAgent = false;
|
|
486
|
+
} catch (error) {
|
|
487
|
+
console.error("Error handling handoff:", error);
|
|
488
|
+
const errorMessage = {
|
|
489
|
+
id: `error-${Date.now()}`,
|
|
490
|
+
text: this.config.debug ? `Handoff error: ${error.message}` : "Failed to connect to agent. Please try again.",
|
|
491
|
+
sender: "bot",
|
|
492
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
493
|
+
};
|
|
494
|
+
this.setState({
|
|
495
|
+
messages: [...this.state.messages, errorMessage]
|
|
496
|
+
});
|
|
497
|
+
this.isConnectingToAgent = false;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
433
500
|
/**
|
|
434
501
|
* Handle WebSocket messages
|
|
435
502
|
*/
|
|
@@ -439,7 +506,7 @@ class WidgetStateManager {
|
|
|
439
506
|
if (message.content) {
|
|
440
507
|
if (message.sender_type === "agent" || !message.sender_type) {
|
|
441
508
|
const agentMessage = {
|
|
442
|
-
id: message.id ||
|
|
509
|
+
id: message.id || `agent-${Date.now()}`,
|
|
443
510
|
text: message.content,
|
|
444
511
|
sender: "agent",
|
|
445
512
|
timestamp: new Date(message.timestamp || Date.now())
|
|
@@ -485,7 +552,7 @@ class WidgetStateManager {
|
|
|
485
552
|
name: message.to_agent
|
|
486
553
|
};
|
|
487
554
|
const systemMessage = {
|
|
488
|
-
id:
|
|
555
|
+
id: `system-${Date.now()}`,
|
|
489
556
|
text: message.from_agent ? `Chat has been transferred from ${message.from_agent} to ${message.to_agent}` : `Chat has been transferred to ${message.to_agent}`,
|
|
490
557
|
sender: "bot",
|
|
491
558
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -499,7 +566,7 @@ class WidgetStateManager {
|
|
|
499
566
|
this.agentAccepted = true;
|
|
500
567
|
this.isConnectingToAgent = false;
|
|
501
568
|
const acceptedMessage = {
|
|
502
|
-
id: message.id ||
|
|
569
|
+
id: message.id || `agent-accepted-${Date.now()}`,
|
|
503
570
|
text: "You can chat now, the agent has accepted your request.",
|
|
504
571
|
sender: "bot",
|
|
505
572
|
timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
|
|
@@ -538,7 +605,7 @@ class WidgetStateManager {
|
|
|
538
605
|
case "error":
|
|
539
606
|
console.error("WebSocket error:", message.error);
|
|
540
607
|
const errorMessage = {
|
|
541
|
-
id:
|
|
608
|
+
id: `error-${Date.now()}`,
|
|
542
609
|
text: message.error || "An error occurred. Please try again.",
|
|
543
610
|
sender: "bot",
|
|
544
611
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -571,7 +638,7 @@ class WidgetStateManager {
|
|
|
571
638
|
localStorage.removeItem("chartsconnect_session_id");
|
|
572
639
|
}
|
|
573
640
|
const thankYouMessage = {
|
|
574
|
-
id:
|
|
641
|
+
id: `resolved-${Date.now()}`,
|
|
575
642
|
text: "Thank you for contacting us!",
|
|
576
643
|
sender: "bot",
|
|
577
644
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -604,7 +671,7 @@ class WidgetStateManager {
|
|
|
604
671
|
});
|
|
605
672
|
if (session.message) {
|
|
606
673
|
const welcomeMessage = {
|
|
607
|
-
id:
|
|
674
|
+
id: `welcome-${Date.now()}`,
|
|
608
675
|
text: session.message,
|
|
609
676
|
sender: "bot",
|
|
610
677
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -621,7 +688,7 @@ class WidgetStateManager {
|
|
|
621
688
|
error: error.message || "Failed to initialize chat"
|
|
622
689
|
});
|
|
623
690
|
const fallbackMessage = {
|
|
624
|
-
id:
|
|
691
|
+
id: `fallback-${Date.now()}`,
|
|
625
692
|
text: this.config.fallbackWelcomeMessage || "Hello! How can I help you today?",
|
|
626
693
|
sender: "bot",
|
|
627
694
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -644,7 +711,7 @@ class WidgetStateManager {
|
|
|
644
711
|
if (this.chatId && this.supportSessionId) {
|
|
645
712
|
const history = await this.chatService.loadMessageHistory(this.chatId, this.supportSessionId);
|
|
646
713
|
const historyMessages = history.map((msg) => ({
|
|
647
|
-
id: msg.id ||
|
|
714
|
+
id: msg.id || `history-${Date.now()}-${Math.random()}`,
|
|
648
715
|
text: msg.content,
|
|
649
716
|
sender: msg.sender_type === "agent" ? "agent" : "user",
|
|
650
717
|
timestamp: new Date(msg.timestamp)
|
|
@@ -668,7 +735,7 @@ class WidgetStateManager {
|
|
|
668
735
|
console.error("Error loading message history:", error);
|
|
669
736
|
if (this.config.debug) {
|
|
670
737
|
const errorMessage = {
|
|
671
|
-
id:
|
|
738
|
+
id: `error-${Date.now()}`,
|
|
672
739
|
text: `Failed to load chat history: ${error.message}`,
|
|
673
740
|
sender: "bot",
|
|
674
741
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -783,9 +850,7 @@ const _hoisted_3 = { class: "custom-welcome-message" };
|
|
|
783
850
|
const _hoisted_4 = { class: "custom-welcome-cta" };
|
|
784
851
|
const _hoisted_5 = {
|
|
785
852
|
key: 2,
|
|
786
|
-
class: "custom-chat-window"
|
|
787
|
-
role: "dialog",
|
|
788
|
-
"aria-label": "Chat window"
|
|
853
|
+
class: "custom-chat-window"
|
|
789
854
|
};
|
|
790
855
|
const _hoisted_6 = { class: "custom-chat-header" };
|
|
791
856
|
const _hoisted_7 = { class: "custom-chat-header-content" };
|
|
@@ -844,7 +909,7 @@ const _hoisted_26 = {
|
|
|
844
909
|
key: 4,
|
|
845
910
|
class: "custom-agent-typing-indicator"
|
|
846
911
|
};
|
|
847
|
-
const _hoisted_27 = ["value", "placeholder", "
|
|
912
|
+
const _hoisted_27 = ["value", "placeholder", "disabled"];
|
|
848
913
|
const _hoisted_28 = ["disabled"];
|
|
849
914
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
850
915
|
...{
|
|
@@ -869,8 +934,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
869
934
|
fallbackWelcomeMessage: { default: "Hello! I'm Charts Connect AI Assistant. How can I help you today?" },
|
|
870
935
|
inputPlaceholder: { default: "Type your message..." },
|
|
871
936
|
emptyStateMessage: { default: "Hi! I'm Charts Connect AI Assistant. How can I help you today?" },
|
|
872
|
-
debug: { type: Boolean, default: false }
|
|
873
|
-
noMatchMessage: {}
|
|
937
|
+
debug: { type: Boolean, default: false }
|
|
874
938
|
},
|
|
875
939
|
setup(__props) {
|
|
876
940
|
const props = __props;
|
|
@@ -1013,10 +1077,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1013
1077
|
createElementVNode("div", {
|
|
1014
1078
|
class: "custom-chat-messages",
|
|
1015
1079
|
ref_key: "messagesContainer",
|
|
1016
|
-
ref: messagesContainer
|
|
1017
|
-
role: "log",
|
|
1018
|
-
"aria-live": "polite",
|
|
1019
|
-
"aria-label": "Chat messages"
|
|
1080
|
+
ref: messagesContainer
|
|
1020
1081
|
}, [
|
|
1021
1082
|
isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_15, [..._cache[2] || (_cache[2] = [
|
|
1022
1083
|
createElementVNode("div", { class: "custom-typing-indicator" }, [
|
|
@@ -1040,7 +1101,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1040
1101
|
}, [
|
|
1041
1102
|
createElementVNode("div", {
|
|
1042
1103
|
class: normalizeClass(["custom-message-content", { "custom-handoff-content": isHandoffMessage(message.text) }]),
|
|
1043
|
-
innerHTML: unref(safeLinkifyText)(message.text)
|
|
1104
|
+
innerHTML: unref(safeLinkifyText)(message.text).replace(/\n/g, "<br>")
|
|
1044
1105
|
}, null, 10, _hoisted_17),
|
|
1045
1106
|
message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_18, [
|
|
1046
1107
|
(openBlock(true), createElementBlock(Fragment, null, renderList(message.richContent, (contentGroup, groupIndex) => {
|
|
@@ -1116,7 +1177,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1116
1177
|
value: unref(state).inputValue,
|
|
1117
1178
|
onInput: handleInput,
|
|
1118
1179
|
placeholder: config.value.inputPlaceholder,
|
|
1119
|
-
"aria-label": config.value.inputPlaceholder,
|
|
1120
1180
|
disabled: unref(state).isLoading || isInitializing.value || isStartingNewChat.value
|
|
1121
1181
|
}, null, 40, _hoisted_27),
|
|
1122
1182
|
createElementVNode("button", {
|
|
@@ -1156,10 +1216,10 @@ const _export_sfc = (sfc, props) => {
|
|
|
1156
1216
|
}
|
|
1157
1217
|
return target;
|
|
1158
1218
|
};
|
|
1159
|
-
const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
1219
|
+
const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-11671761"]]);
|
|
1160
1220
|
export {
|
|
1161
1221
|
ChatWidgetComponent as C,
|
|
1162
1222
|
WidgetStateManager as W,
|
|
1163
1223
|
useChatWidget as u
|
|
1164
1224
|
};
|
|
1165
|
-
//# sourceMappingURL=ChatWidget-
|
|
1225
|
+
//# sourceMappingURL=ChatWidget-CYjfNp7_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatWidget-CYjfNp7_.js","sources":["../src/core/stateManager.ts","../src/composables/useChatWidget.ts","../src/components/ChatWidget.vue"],"sourcesContent":["/**\n * State Manager - Framework Agnostic\n * Manages widget state independently of framework\n */\n\nimport type { WidgetState, WidgetConfig, ChatMessage } from './types';\nimport {\n createDialogflowSession,\n sendDialogflowMessage,\n type DialogflowBackendConfig,\n} from '../services/dialogflowBackendService';\nimport { \n createChatService, \n ChatResolvedError,\n type WebSocketMessage\n} from '../services/chatService';\n\nexport class WidgetStateManager {\n private state: WidgetState;\n private config: WidgetConfig;\n private listeners: Set<(state: WidgetState) => void> = new Set();\n private chatMode: 'ai' | 'human' = 'ai';\n private chatId: string | null = null;\n private supportSessionId: string | null = null;\n private chatService: ReturnType<typeof createChatService> | null = null;\n \n // Additional state for human support\n private wsConnected: boolean = false;\n private agentTyping: boolean = false;\n private currentAgent: { name: string; id?: string } = { name: 'Agent' };\n private isConnectingToAgent: boolean = false;\n private agentAccepted: boolean = false;\n private chatResolved: boolean = false;\n private historyLoaded: string | null = null;\n \n // Typing timeout refs (stored as class properties since we can't use refs)\n private typingTimeout: NodeJS.Timeout | null = null;\n private agentTypingTimeout: NodeJS.Timeout | null = null;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.state = {\n isOpen: false,\n showWelcomePopup: false,\n messages: [],\n inputValue: '',\n isLoading: false,\n error: null,\n sessionId: null,\n chatMode: 'ai',\n };\n \n // Initialize ChatService\n this.chatService = createChatService({\n baseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n wsUrl: this.config.backendWsUrl || 'ws://localhost:8012',\n debug: this.config.debug || false,\n });\n \n // Load chat mode and chat IDs from localStorage if available\n if (typeof window !== 'undefined' && window.localStorage) {\n const savedMode = localStorage.getItem('chartsconnectect_chat_mode');\n this.chatMode = savedMode === 'HUMAN' ? 'human' : 'ai';\n this.state.chatMode = this.chatMode;\n \n this.chatId = localStorage.getItem('chartsconnect_chat_id');\n this.supportSessionId = localStorage.getItem('chartsconnect_session_id');\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: (state: WidgetState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return { ...this.state };\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<WidgetState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach(listener => listener(this.getState()));\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<WidgetConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Open chat\n */\n async openChat(): Promise<void> {\n this.setState({ isOpen: true });\n if (this.state.showWelcomePopup) {\n this.setState({ showWelcomePopup: false });\n }\n \n // Initialize Dialogflow session when chat opens (if in AI mode and no session exists)\n if (this.state.chatMode === 'ai' && !this.state.sessionId && this.config.dfProjectId && this.config.dfAgentId) {\n try {\n this.setState({ isLoading: true });\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n \n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ \n sessionId: session.session_id,\n isLoading: false,\n });\n \n // Add welcome message from Dialogflow if available\n if (session.message) {\n const welcomeMessage: ChatMessage = {\n id: `welcome-${Date.now()}`,\n text: session.message,\n sender: 'bot',\n timestamp: new Date(),\n richContent: session.richContent,\n };\n this.setState({\n messages: [welcomeMessage],\n });\n }\n } catch (error: any) {\n console.error('Error initializing Dialogflow session:', error);\n this.setState({ \n isLoading: false,\n error: error.message || 'Failed to initialize chat',\n });\n \n // Show fallback welcome message\n const fallbackMessage: ChatMessage = {\n id: `fallback-${Date.now()}`,\n text: this.config.fallbackWelcomeMessage || 'Hello! How can I help you today?',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [fallbackMessage],\n });\n }\n }\n }\n\n /**\n * Close chat\n */\n closeChat(): void {\n this.setState({ isOpen: false });\n }\n\n /**\n * Close welcome popup\n */\n closeWelcomePopup(): void {\n this.setState({ showWelcomePopup: false });\n }\n\n /**\n * Toggle chat\n */\n toggleChat(): void {\n const willBeOpen = !this.state.isOpen;\n this.setState({ isOpen: willBeOpen });\n if (willBeOpen && this.state.showWelcomePopup) {\n this.setState({ showWelcomePopup: false });\n }\n }\n\n /**\n * Set input value\n */\n setInputValue(value: string): void {\n this.setState({ inputValue: value });\n }\n\n /**\n * Clear error\n */\n clearError(): void {\n this.setState({ error: null });\n }\n\n /**\n * Send message\n */\n async sendMessage(text: string, skipUserMessage: boolean = false): Promise<void> {\n if (!text.trim() || this.state.isLoading) {\n return;\n }\n\n // Add user message unless skipped (e.g., when chip button already added it)\n if (!skipUserMessage) {\n const userMessage: ChatMessage = {\n id: `user-${Date.now()}`,\n text: text.trim(),\n sender: 'user',\n timestamp: new Date(),\n };\n\n this.setState({\n messages: [...this.state.messages, userMessage],\n inputValue: '',\n isLoading: true,\n error: null,\n });\n } else {\n this.setState({\n inputValue: '',\n isLoading: true,\n error: null,\n });\n }\n\n try {\n if (this.state.chatMode === 'human') {\n // Human support mode\n await this.sendHumanMessage(text);\n } else {\n // AI mode (Dialogflow)\n await this.sendAIMessage(text);\n }\n } catch (error: any) {\n console.error('Error sending message:', error);\n \n // chat_resolved is a normal terminal condition, not an error\n if (error instanceof ChatResolvedError || error?.name === 'ChatResolvedError' || error?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n \n // Add error message to chat\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: this.config.debug \n ? `Error: ${error.message || 'Failed to send message'}`\n : error.message?.includes('CORS') || error.message?.includes('Failed to fetch')\n ? 'Unable to connect to Dialogflow. Please check your configuration and network.'\n : 'Sorry, I\\'m having trouble processing your message. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n \n this.setState({\n messages: [...this.state.messages, errorMessage],\n error: error.message || 'Failed to send message',\n isLoading: false,\n });\n }\n }\n\n /**\n * Send message to Dialogflow\n */\n private async sendAIMessage(text: string): Promise<void> {\n if (!this.config.dfProjectId || !this.config.dfAgentId) {\n throw new Error('Dialogflow configuration is missing');\n }\n\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId!,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId!,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n\n // Create session if needed\n if (!this.state.sessionId) {\n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ sessionId: session.session_id });\n }\n\n // Send message (correct parameter order: message, sessionId, config)\n if (this.config.debug) {\n console.log('Sending message to Dialogflow:', {\n message: text,\n sessionId: this.state.sessionId,\n hasConfig: !!dialogflowConfig,\n });\n }\n \n const response = await sendDialogflowMessage(\n text,\n this.state.sessionId!,\n dialogflowConfig\n );\n\n if (this.config.debug) {\n console.log('Dialogflow response:', {\n response: response.response,\n hasRichContent: !!response.richContent,\n richContent: response.richContent,\n });\n }\n\n // Check for handoff\n if (response.handoff === true) {\n // Add bot response first\n const botMessage: ChatMessage = {\n id: `bot-${Date.now()}`,\n text: response.response || this.config.fallbackWelcomeMessage || 'No response',\n sender: 'bot',\n timestamp: new Date(),\n richContent: response.richContent,\n };\n this.setState({\n messages: [...this.state.messages, botMessage],\n isLoading: false,\n });\n \n // Proceed directly with handoff — user details collected by Dialogflow via webhook\n await this.handleHandoff();\n return;\n }\n \n const botMessage: ChatMessage = {\n id: `bot-${Date.now()}`,\n text: response.response || this.config.fallbackWelcomeMessage || 'No response',\n sender: 'bot',\n timestamp: new Date(),\n richContent: response.richContent,\n };\n\n this.setState({\n messages: [...this.state.messages, botMessage],\n isLoading: false,\n });\n }\n\n /**\n * Send message to human support\n */\n private async sendHumanMessage(text: string): Promise<void> {\n if (!this.chatId || !this.supportSessionId) {\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: 'Chat session not initialized. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n isLoading: false,\n });\n return;\n }\n\n if (!this.chatService) {\n throw new Error('Chat service not initialized');\n }\n\n // Send typing_stop before sending message\n this.chatService.sendTypingIndicator('typing_stop');\n if (this.typingTimeout) {\n clearTimeout(this.typingTimeout);\n this.typingTimeout = null;\n }\n\n try {\n // Try WebSocket first, fallback to REST API\n const sentViaWs = this.chatService.sendMessageViaWebSocket(text.trim());\n \n if (!sentViaWs) {\n // Fallback to REST API\n await this.chatService.sendMessageToAgent(this.chatId, this.supportSessionId, text.trim());\n }\n \n this.setState({ isLoading: false });\n } catch (error: any) {\n // chat_resolved is a normal terminal condition, not an error\n if (error instanceof ChatResolvedError || error?.name === 'ChatResolvedError' || error?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n\n // Handle 401/404 - clear chat_id and reinitialize\n if (error.message?.includes('Chat not found') ||\n error.message?.includes('unauthorized') ||\n error.message?.includes('401') ||\n error.message?.includes('404')) {\n if (this.config.debug) {\n console.log('⚠️ Chat expired. Re-initializing...');\n }\n \n // Clear chat_id\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Try to reinitialize chat\n try {\n const newSession = await this.chatService.startSupportChat(\n this.state.sessionId || null\n );\n this.chatId = newSession.chat_id;\n this.supportSessionId = newSession.session_id;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n \n // Retry sending message\n if (this.chatId && this.supportSessionId) {\n await this.chatService.sendMessageToAgent(\n this.chatId,\n this.supportSessionId,\n text.trim()\n );\n }\n this.setState({ isLoading: false });\n return;\n } catch (retryError: any) {\n if (retryError instanceof ChatResolvedError || retryError?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n throw retryError;\n }\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Switch to human mode\n */\n switchToHumanMode(): void {\n this.chatMode = 'human';\n this.setState({ chatMode: 'human' });\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_mode', 'HUMAN');\n }\n }\n\n /**\n * Switch to AI mode\n */\n switchToBotMode(): void {\n this.chatMode = 'ai';\n this.setState({ chatMode: 'ai' });\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_mode', 'BOT');\n }\n }\n\n /**\n * Initialize welcome popup\n */\n initializeWelcomePopup(): void {\n if (this.config.showWelcomePopup !== false) {\n const delay = this.config.welcomePopupDelay || 1500;\n setTimeout(() => {\n if (!this.state.isOpen) {\n this.setState({ showWelcomePopup: true });\n }\n }, delay);\n }\n }\n\n /**\n * Handle handoff from Dialogflow to human support\n */\n async handleHandoff(): Promise<void> {\n if (!this.chatService) {\n throw new Error('Chat service not initialized');\n }\n\n try {\n this.isConnectingToAgent = true;\n \n // Get Dialogflow session ID if available\n const dialogflowSessionId = this.state.sessionId;\n \n // STEP 1: Ensure chat is initialized\n const session = await this.chatService.ensureChatInitialized(\n this.chatId,\n this.supportSessionId,\n dialogflowSessionId || null\n );\n \n if (!session || !session.chat_id) {\n throw new Error('Failed to initialize chat session');\n }\n \n const currentChatId = session.chat_id;\n const currentSupportSessionId = session.session_id;\n \n // Update state if chat was newly initialized\n if (currentChatId !== this.chatId) {\n this.chatId = currentChatId;\n this.supportSessionId = currentSupportSessionId;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n if (this.config.debug) {\n console.log('✅ Chat initialized:', { chatId: currentChatId, sessionId: currentSupportSessionId });\n }\n }\n\n // STEP 2: Request handoff\n try {\n await this.chatService.requestHandoff(\n currentChatId,\n currentSupportSessionId,\n 'Customer requested human agent',\n dialogflowSessionId || null\n );\n \n if (this.config.debug) {\n console.log('✅ Handoff requested successfully');\n }\n } catch (handoffError: any) {\n // Handle 401/404 or \"chat not found\" - clear chat_id and retry\n if (handoffError.message?.includes('Invalid chat_id') || \n handoffError.message?.includes('Chat not found') ||\n handoffError.message?.includes('unauthorized') ||\n handoffError.message?.includes('400') ||\n handoffError.message?.includes('401') ||\n handoffError.message?.includes('404') ||\n handoffError.message?.includes('expired')) {\n if (this.config.debug) {\n console.log('⚠️ Chat expired or not found. Re-initializing chat...');\n }\n \n // Clear old chat_id\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Create new chat session\n const newSession = await this.chatService.startSupportChat(\n dialogflowSessionId || null\n );\n \n if (!newSession || !newSession.chat_id) {\n throw new Error('Failed to re-initialize chat session');\n }\n \n this.chatId = newSession.chat_id;\n this.supportSessionId = newSession.session_id;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n \n // Retry handoff with new chat_id\n await this.chatService.requestHandoff(\n this.chatId,\n this.supportSessionId,\n 'Customer requested human agent',\n dialogflowSessionId || null\n );\n \n if (this.config.debug) {\n console.log('✅ Handoff requested successfully after retry');\n }\n } else {\n throw handoffError;\n }\n }\n\n // Switch to human mode\n this.switchToHumanMode();\n this.chatResolved = false;\n this.agentAccepted = false;\n\n // Add connecting message\n const connectingMessage: ChatMessage = {\n id: `connecting-${Date.now()}`,\n text: 'Connecting you to a human agent...',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, connectingMessage],\n });\n\n // Connect WebSocket with handlers\n if (currentChatId && currentSupportSessionId) {\n this.chatService.connectWebSocket(\n currentChatId,\n currentSupportSessionId,\n (message: WebSocketMessage) => {\n this.handleWebSocketMessage(message);\n },\n (connected: boolean) => {\n this.wsConnected = connected;\n }\n );\n }\n \n this.isConnectingToAgent = false;\n } catch (error: any) {\n console.error('Error handling handoff:', error);\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: this.config.debug\n ? `Handoff error: ${error.message}`\n : 'Failed to connect to agent. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n this.isConnectingToAgent = false;\n }\n }\n\n /**\n * Handle WebSocket messages\n */\n private handleWebSocketMessage(message: WebSocketMessage): void {\n switch (message.type) {\n case 'message':\n if (message.content) {\n // Only display messages from agent\n if (message.sender_type === 'agent' || !message.sender_type) {\n const agentMessage: ChatMessage = {\n id: message.id || `agent-${Date.now()}`,\n text: message.content,\n sender: 'agent',\n timestamp: new Date(message.timestamp || Date.now()),\n };\n \n // Avoid duplicate messages\n const existingIds = new Set(this.state.messages.map(m => m.id));\n if (!existingIds.has(agentMessage.id)) {\n this.setState({\n messages: [...this.state.messages, agentMessage],\n });\n }\n \n // Hide typing indicator when message received\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n }\n }\n break;\n\n case 'typing_start':\n if (message.sender_type === 'agent') {\n this.agentTyping = true;\n // Auto-hide after 3 seconds if no message received\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n }\n this.agentTypingTimeout = setTimeout(() => {\n this.agentTyping = false;\n }, 3000);\n }\n break;\n\n case 'typing_stop':\n if (message.sender_type === 'agent') {\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n }\n break;\n\n case 'agent_changed':\n if (message.to_agent) {\n this.currentAgent = {\n id: message.to_agent_id,\n name: message.to_agent,\n };\n\n // Add system message to chat\n const systemMessage: ChatMessage = {\n id: `system-${Date.now()}`,\n text: message.from_agent\n ? `Chat has been transferred from ${message.from_agent} to ${message.to_agent}`\n : `Chat has been transferred to ${message.to_agent}`,\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, systemMessage],\n });\n }\n break;\n\n case 'agent_accepted':\n this.agentAccepted = true;\n this.isConnectingToAgent = false;\n const acceptedMessage: ChatMessage = {\n id: message.id || `agent-accepted-${Date.now()}`,\n text: 'You can chat now, the agent has accepted your request.',\n sender: 'bot',\n timestamp: message.timestamp ? new Date(message.timestamp) : new Date(),\n };\n const existingIds = new Set(this.state.messages.map(m => m.id));\n if (!existingIds.has(acceptedMessage.id)) {\n this.setState({\n messages: [...this.state.messages, acceptedMessage],\n });\n }\n if (message.to_agent) {\n this.currentAgent = {\n name: message.to_agent,\n id: message.to_agent_id,\n };\n }\n break;\n\n case 'chat_resolved':\n case 'chat_ended':\n this.enterResolvedState(message.chat_id || null);\n break;\n\n case 'chat_info':\n if (message.status === 'active') {\n this.isConnectingToAgent = false;\n this.agentAccepted = true;\n } else if (message.status === 'resolved' || message.status === 'ended') {\n this.enterResolvedState(message.chat_id || null);\n }\n if (message.agent_id) {\n this.currentAgent = {\n ...this.currentAgent,\n id: message.agent_id,\n };\n }\n break;\n\n case 'error':\n console.error('WebSocket error:', message.error);\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: message.error || 'An error occurred. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n break;\n }\n }\n\n /**\n * Enter resolved state\n */\n private enterResolvedState(resolvedChatId?: string | null): void {\n this.chatResolved = true;\n this.isConnectingToAgent = false;\n this.agentAccepted = false;\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n\n // Stop WS + prevent any reuse of the old chat_id\n if (this.chatService) {\n this.chatService.disconnectWebSocket();\n }\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Add thank you message before reset\n const thankYouMessage: ChatMessage = {\n id: `resolved-${Date.now()}`,\n text: 'Thank you for contacting us!',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, thankYouMessage],\n });\n \n // Automatically reset to BOT mode after showing thank you message\n setTimeout(async () => {\n this.switchToBotMode();\n this.chatResolved = false;\n this.setState({\n messages: [],\n sessionId: null, // Clear session ID to force recreation\n });\n // Recreate Dialogflow session to start fresh\n if (this.config.dfProjectId && this.config.dfAgentId && this.state.isOpen) {\n try {\n this.setState({ isLoading: true });\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n \n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ \n sessionId: session.session_id,\n isLoading: false,\n });\n \n // Add welcome message from Dialogflow if available\n if (session.message) {\n const welcomeMessage: ChatMessage = {\n id: `welcome-${Date.now()}`,\n text: session.message,\n sender: 'bot',\n timestamp: new Date(),\n richContent: session.richContent,\n };\n this.setState({\n messages: [welcomeMessage],\n });\n }\n } catch (error: any) {\n console.error('Error recreating Dialogflow session after handoff:', error);\n this.setState({ \n isLoading: false,\n error: error.message || 'Failed to initialize chat',\n });\n \n // Show fallback welcome message\n const fallbackMessage: ChatMessage = {\n id: `fallback-${Date.now()}`,\n text: this.config.fallbackWelcomeMessage || 'Hello! How can I help you today?',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [fallbackMessage],\n });\n }\n }\n }, 2000);\n }\n\n /**\n * Load message history\n */\n async loadMessageHistory(preserveExisting: boolean = false): Promise<void> {\n if (!this.chatService || !this.chatId || !this.supportSessionId) {\n return;\n }\n\n try {\n if (this.chatId && this.supportSessionId) {\n const history = await this.chatService.loadMessageHistory(this.chatId, this.supportSessionId);\n \n const historyMessages: ChatMessage[] = history.map((msg: any) => ({\n id: msg.id || `history-${Date.now()}-${Math.random()}`,\n text: msg.content,\n sender: msg.sender_type === 'agent' ? 'agent' : 'user',\n timestamp: new Date(msg.timestamp),\n }));\n\n if (preserveExisting) {\n // Merge with existing messages, avoiding duplicates\n const existingIds = new Set(this.state.messages.map(m => m.id));\n const newMessages = historyMessages.filter(m => !existingIds.has(m.id));\n \n // Combine existing messages with new history messages\n // Sort by timestamp to maintain chronological order\n const combined = [...this.state.messages, ...newMessages].sort((a, b) => \n a.timestamp.getTime() - b.timestamp.getTime()\n );\n \n this.setState({\n messages: combined,\n });\n } else {\n // Replace all messages\n this.setState({\n messages: historyMessages,\n });\n }\n }\n } catch (error: any) {\n console.error('Error loading message history:', error);\n if (this.config.debug) {\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: `Failed to load chat history: ${error.message}`,\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n }\n }\n }\n\n /**\n * Get additional state for UI (not in WidgetState but needed by components)\n */\n getAdditionalState() {\n return {\n wsConnected: this.wsConnected,\n agentTyping: this.agentTyping,\n currentAgent: this.currentAgent,\n isConnectingToAgent: this.isConnectingToAgent,\n agentAccepted: this.agentAccepted,\n chatResolved: this.chatResolved,\n };\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n if (this.typingTimeout) {\n clearTimeout(this.typingTimeout);\n }\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n }\n if (this.chatService) {\n this.chatService.disconnectWebSocket();\n }\n this.listeners.clear();\n }\n}\n","/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n isConnectingToAgent: Readonly<Ref<boolean>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n const isConnectingToAgent = ref(false);\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n isConnectingToAgent.value = additional.isConnectingToAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n isConnectingToAgent: isConnectingToAgent as Readonly<Ref<boolean>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n","<template>\n <div class=\"custom-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"custom-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"custom-welcome-header\">\n <div class=\"custom-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"custom-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"custom-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"custom-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"custom-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"custom-chat-window\">\n <div class=\"custom-chat-header\">\n <div class=\"custom-chat-header-content\">\n <div class=\"custom-chat-title\">{{ config.title }}</div>\n <div class=\"custom-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"custom-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-agent-info\">\n <span class=\"custom-agent-label\">Agent:</span>\n <span class=\"custom-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"custom-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"custom-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"custom-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <p>Initializing chat...</p>\n </div>\n <div v-else-if=\"!isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'custom-message', \n `custom-message-${message.sender}`,\n { 'custom-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"custom-message-content\"\n :class=\"{ 'custom-handoff-content': isHandoffMessage(message.text) }\"\n v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"\n ></div>\n \n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"custom-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"custom-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Connecting to Agent Indicator -->\n <div v-if=\"isConnectingToAgent\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <div class=\"custom-message-content\">\n Connecting to agent...\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"custom-agent-typing-indicator\">\n <span class=\"custom-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"custom-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"custom-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"custom-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading || isInitializing || isStartingNewChat\"\n />\n <button\n type=\"submit\"\n class=\"custom-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading || isInitializing || isStartingNewChat\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 Charts Connect AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to Charts Connect',\n welcomeMessage: \"My name is Charts Connect AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm Charts Connect AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm Charts Connect AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n isConnectingToAgent: isConnectingToAgentFromComposable,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Computed state for initialization and connection (matching React component)\nconst isInitializing = computed(() => {\n return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;\n});\n\nconst isStartingNewChat = computed(() => {\n // This would be tracked in manager if needed, for now return false\n return false;\n});\n\n// Use isConnectingToAgent from composable (already computed in manager)\nconst isConnectingToAgent = isConnectingToAgentFromComposable;\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["botMessage","existingIds","_openBlock","_createElementBlock","_mergeProps","$attrs","_unref","_createElementVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass"],"mappings":"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"}
|