@om_patel_26/chat-widget 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +276 -0
- package/dist/_virtual/_plugin-vue_export-helper.cjs.js +2 -0
- package/dist/_virtual/_plugin-vue_export-helper.cjs.js.map +1 -0
- package/dist/_virtual/_plugin-vue_export-helper.esm.js +11 -0
- package/dist/_virtual/_plugin-vue_export-helper.esm.js.map +1 -0
- package/dist/adapters/vue/index.d.ts +7 -0
- package/dist/adapters/vue/index.d.ts.map +1 -0
- package/dist/adapters/vue/useChatMode.d.ts +21 -0
- package/dist/adapters/vue/useChatMode.d.ts.map +1 -0
- package/dist/components/ChatWidget.d.ts +43 -0
- package/dist/components/ChatWidget.d.ts.map +1 -0
- package/dist/components/ChatWidget.vue.cjs.js +2 -0
- package/dist/components/ChatWidget.vue.cjs.js.map +1 -0
- package/dist/components/ChatWidget.vue.cjs2.js +2 -0
- package/dist/components/ChatWidget.vue.cjs2.js.map +1 -0
- package/dist/components/ChatWidget.vue.esm.js +8 -0
- package/dist/components/ChatWidget.vue.esm.js.map +1 -0
- package/dist/components/ChatWidget.vue.esm2.js +331 -0
- package/dist/components/ChatWidget.vue.esm2.js.map +1 -0
- package/dist/composables/useChatWidget.cjs.js +2 -0
- package/dist/composables/useChatWidget.cjs.js.map +1 -0
- package/dist/composables/useChatWidget.d.ts +34 -0
- package/dist/composables/useChatWidget.d.ts.map +1 -0
- package/dist/composables/useChatWidget.esm.js +72 -0
- package/dist/composables/useChatWidget.esm.js.map +1 -0
- package/dist/core/stateManager.cjs.js +2 -0
- package/dist/core/stateManager.cjs.js.map +1 -0
- package/dist/core/stateManager.d.ts +136 -0
- package/dist/core/stateManager.d.ts.map +1 -0
- package/dist/core/stateManager.esm.js +907 -0
- package/dist/core/stateManager.esm.js.map +1 -0
- package/dist/core/types.d.ts +66 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/entry/next.d.ts +9 -0
- package/dist/entry/next.d.ts.map +1 -0
- package/dist/entry/nuxt.d.ts +10 -0
- package/dist/entry/nuxt.d.ts.map +1 -0
- package/dist/entry/react.d.ts +10 -0
- package/dist/entry/react.d.ts.map +1 -0
- package/dist/entry/vanilla.d.ts +33 -0
- package/dist/entry/vanilla.d.ts.map +1 -0
- package/dist/entry/vite.d.ts +11 -0
- package/dist/entry/vite.d.ts.map +1 -0
- package/dist/entry/vue.d.ts +11 -0
- package/dist/entry/vue.d.ts.map +1 -0
- package/dist/hooks/useChatMode.d.ts +17 -0
- package/dist/hooks/useChatMode.d.ts.map +1 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +25 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js +21 -0
- package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js +84 -0
- package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js +72 -0
- package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js +22 -0
- package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/key/import.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/key/import.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/key/import.esm.js +11 -0
- package/dist/node_modules/jose/dist/browser/key/import.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js +18 -0
- package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js +77 -0
- package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js +101 -0
- package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js +5 -0
- package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js +32 -0
- package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js +25 -0
- package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js +20 -0
- package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js +20 -0
- package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/secs.esm.js +59 -0
- package/dist/node_modules/jose/dist/browser/lib/secs.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js +34 -0
- package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js +103 -0
- package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js +43 -0
- package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js +12 -0
- package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js +25 -0
- package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js +13 -0
- package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js +107 -0
- package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js +71 -0
- package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js +14 -0
- package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js +32 -0
- package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js +7 -0
- package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/util/errors.cjs.js +2 -0
- package/dist/node_modules/jose/dist/browser/util/errors.cjs.js.map +1 -0
- package/dist/node_modules/jose/dist/browser/util/errors.esm.js +131 -0
- package/dist/node_modules/jose/dist/browser/util/errors.esm.js.map +1 -0
- package/dist/nuxt.cjs.js +2 -0
- package/dist/nuxt.cjs.js.map +1 -0
- package/dist/nuxt.esm.js +8 -0
- package/dist/nuxt.esm.js.map +1 -0
- package/dist/services/chatService.cjs.js +2 -0
- package/dist/services/chatService.cjs.js.map +1 -0
- package/dist/services/chatService.d.ts +144 -0
- package/dist/services/chatService.d.ts.map +1 -0
- package/dist/services/chatService.esm.js +482 -0
- package/dist/services/chatService.esm.js.map +1 -0
- package/dist/services/dialogflowClient.cjs.js +2 -0
- package/dist/services/dialogflowClient.cjs.js.map +1 -0
- package/dist/services/dialogflowClient.d.ts +36 -0
- package/dist/services/dialogflowClient.d.ts.map +1 -0
- package/dist/services/dialogflowClient.esm.js +282 -0
- package/dist/services/dialogflowClient.esm.js.map +1 -0
- package/dist/services/sessionManager.cjs.js +2 -0
- package/dist/services/sessionManager.cjs.js.map +1 -0
- package/dist/services/sessionManager.d.ts +13 -0
- package/dist/services/sessionManager.d.ts.map +1 -0
- package/dist/services/sessionManager.esm.js +48 -0
- package/dist/services/sessionManager.esm.js.map +1 -0
- package/dist/styles.css +0 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/dialogflowHandler.d.ts +31 -0
- package/dist/utils/dialogflowHandler.d.ts.map +1 -0
- package/dist/utils/frameworkDetector.d.ts +17 -0
- package/dist/utils/frameworkDetector.d.ts.map +1 -0
- package/dist/utils/sanitize.cjs.js +2 -0
- package/dist/utils/sanitize.cjs.js.map +1 -0
- package/dist/utils/sanitize.d.ts +25 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.esm.js +57 -0
- package/dist/utils/sanitize.esm.js.map +1 -0
- package/dist/utils/ssr.cjs.js +2 -0
- package/dist/utils/ssr.cjs.js.map +1 -0
- package/dist/utils/ssr.d.ts +35 -0
- package/dist/utils/ssr.d.ts.map +1 -0
- package/dist/utils/ssr.esm.js +48 -0
- package/dist/utils/ssr.esm.js.map +1 -0
- package/dist/vue.cjs.js +2 -0
- package/dist/vue.cjs.js.map +1 -0
- package/dist/vue.esm.js +10 -0
- package/dist/vue.esm.js.map +1 -0
- package/package.json +145 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export interface SupportChatSession {
|
|
2
|
+
chat_id: string;
|
|
3
|
+
session_id: string;
|
|
4
|
+
}
|
|
5
|
+
export interface SupportMessage {
|
|
6
|
+
id?: string;
|
|
7
|
+
sender_type: "customer" | "agent";
|
|
8
|
+
content: string;
|
|
9
|
+
timestamp: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ChatInfo {
|
|
12
|
+
status: "waiting" | "active";
|
|
13
|
+
agent_id?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface WebSocketMessage {
|
|
16
|
+
type: "message" | "chat_info" | "error" | "typing_start" | "typing_stop" | "agent_changed" | "agent_accepted" | "chat_resolved" | "chat_ended" | "ping" | "pong";
|
|
17
|
+
id?: string;
|
|
18
|
+
chat_id?: string;
|
|
19
|
+
sender_type?: "customer" | "agent";
|
|
20
|
+
sender_id?: string;
|
|
21
|
+
content?: string;
|
|
22
|
+
timestamp?: string;
|
|
23
|
+
status?: "waiting" | "active" | "resolved" | "ended";
|
|
24
|
+
agent_id?: string;
|
|
25
|
+
error?: string;
|
|
26
|
+
from_agent?: string;
|
|
27
|
+
to_agent?: string;
|
|
28
|
+
to_agent_id?: string;
|
|
29
|
+
reason?: string;
|
|
30
|
+
message?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare class ChatResolvedError extends Error {
|
|
33
|
+
reason: "chat_resolved";
|
|
34
|
+
constructor(message?: string);
|
|
35
|
+
}
|
|
36
|
+
export interface ChatServiceConfig {
|
|
37
|
+
baseUrl?: string;
|
|
38
|
+
wsUrl?: string;
|
|
39
|
+
debug?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface StartSupportChatOptions {
|
|
42
|
+
dialogflowSessionId?: string | null;
|
|
43
|
+
customerName?: string | null;
|
|
44
|
+
customerEmail?: string | null;
|
|
45
|
+
customerMobile?: string | null;
|
|
46
|
+
}
|
|
47
|
+
declare class ChatService {
|
|
48
|
+
private baseUrl;
|
|
49
|
+
private wsUrl;
|
|
50
|
+
private debug;
|
|
51
|
+
private ws;
|
|
52
|
+
private wsReconnectAttempts;
|
|
53
|
+
private maxReconnectAttempts;
|
|
54
|
+
private reconnectTimeout;
|
|
55
|
+
private pingInterval;
|
|
56
|
+
private currentChatId;
|
|
57
|
+
private currentSessionId;
|
|
58
|
+
private messageHandlers;
|
|
59
|
+
private connectionHandlers;
|
|
60
|
+
private sessionManager;
|
|
61
|
+
constructor(config?: ChatServiceConfig);
|
|
62
|
+
/**
|
|
63
|
+
* Start a new support chat session
|
|
64
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
65
|
+
* @param customerName - Optional: Customer name
|
|
66
|
+
* @param customerEmail - Optional: Customer email
|
|
67
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
68
|
+
*/
|
|
69
|
+
startSupportChat(dialogflowSessionId?: string | null, customerName?: string | null, customerEmail?: string | null, customerMobile?: string | null): Promise<SupportChatSession>;
|
|
70
|
+
/**
|
|
71
|
+
* Request handoff to human agent
|
|
72
|
+
* @param chatId - Chat ID (must be valid, not undefined)
|
|
73
|
+
* @param sessionId - Session ID
|
|
74
|
+
* @param reason - Optional: Reason for handoff
|
|
75
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
76
|
+
* @param customerName - Optional: Customer name
|
|
77
|
+
* @param customerEmail - Optional: Customer email
|
|
78
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
79
|
+
*/
|
|
80
|
+
requestHandoff(chatId: string, sessionId: string, reason?: string, dialogflowSessionId?: string | null, customerName?: string | null, customerEmail?: string | null, customerMobile?: string | null): Promise<{
|
|
81
|
+
success: boolean;
|
|
82
|
+
message?: string;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Send message to agent via REST API
|
|
86
|
+
*/
|
|
87
|
+
sendMessageToAgent(chatId: string, sessionId: string, message: string): Promise<SupportMessage>;
|
|
88
|
+
/**
|
|
89
|
+
* Ensure chat is initialized - helper method
|
|
90
|
+
* Returns existing chat_id if valid, otherwise initializes new chat
|
|
91
|
+
* @param existingChatId - Existing chat ID to validate
|
|
92
|
+
* @param existingSessionId - Existing session ID
|
|
93
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
94
|
+
* @param customerName - Optional: Customer name
|
|
95
|
+
* @param customerEmail - Optional: Customer email
|
|
96
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
97
|
+
* @returns Promise with chat_id and session_id
|
|
98
|
+
*/
|
|
99
|
+
ensureChatInitialized(existingChatId?: string | null, existingSessionId?: string | null, dialogflowSessionId?: string | null, customerName?: string | null, customerEmail?: string | null, customerMobile?: string | null): Promise<SupportChatSession>;
|
|
100
|
+
/**
|
|
101
|
+
* Load message history
|
|
102
|
+
*/
|
|
103
|
+
loadMessageHistory(chatId: string, sessionId: string): Promise<SupportMessage[]>;
|
|
104
|
+
/**
|
|
105
|
+
* Connect to WebSocket
|
|
106
|
+
*/
|
|
107
|
+
connectWebSocket(chatId: string, sessionId: string, onMessage?: (message: WebSocketMessage) => void, onConnectionChange?: (connected: boolean) => void, onClose?: (event: CloseEvent) => void): void;
|
|
108
|
+
/**
|
|
109
|
+
* Send message via WebSocket
|
|
110
|
+
*/
|
|
111
|
+
sendMessageViaWebSocket(message: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Send typing indicator via WebSocket
|
|
114
|
+
*/
|
|
115
|
+
sendTypingIndicator(type: "typing_start" | "typing_stop"): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Start ping interval to keep connection alive
|
|
118
|
+
*/
|
|
119
|
+
private startPingInterval;
|
|
120
|
+
/**
|
|
121
|
+
* Stop ping interval
|
|
122
|
+
*/
|
|
123
|
+
private stopPingInterval;
|
|
124
|
+
/**
|
|
125
|
+
* Disconnect WebSocket
|
|
126
|
+
*/
|
|
127
|
+
disconnectWebSocket(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Check if WebSocket is connected
|
|
130
|
+
*/
|
|
131
|
+
isWebSocketConnected(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Remove message handler
|
|
134
|
+
*/
|
|
135
|
+
removeMessageHandler(handler: (message: WebSocketMessage) => void): void;
|
|
136
|
+
/**
|
|
137
|
+
* Remove connection handler
|
|
138
|
+
*/
|
|
139
|
+
removeConnectionHandler(handler: (connected: boolean) => void): void;
|
|
140
|
+
}
|
|
141
|
+
export declare function getChatService(config?: ChatServiceConfig): ChatService;
|
|
142
|
+
export declare function createChatService(config: ChatServiceConfig): ChatService;
|
|
143
|
+
export {};
|
|
144
|
+
//# sourceMappingURL=chatService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatService.d.ts","sourceRoot":"","sources":["../../src/services/chatService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { getSessionManager } from "./sessionManager.esm.js";
|
|
2
|
+
class ChatResolvedError extends Error {
|
|
3
|
+
constructor(message = "chat_resolved") {
|
|
4
|
+
super(message);
|
|
5
|
+
this.reason = "chat_resolved";
|
|
6
|
+
this.name = "ChatResolvedError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const DEFAULT_BASE_URL = typeof process !== "undefined" && process.env?.REACT_APP_BACKEND_BASE_URL;
|
|
10
|
+
const DEFAULT_WS_URL = typeof process !== "undefined" && process.env?.REACT_APP_BACKEND_WS_URL;
|
|
11
|
+
class ChatService {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.ws = null;
|
|
14
|
+
this.wsReconnectAttempts = 0;
|
|
15
|
+
this.maxReconnectAttempts = 5;
|
|
16
|
+
this.reconnectTimeout = null;
|
|
17
|
+
this.pingInterval = null;
|
|
18
|
+
this.currentChatId = null;
|
|
19
|
+
this.currentSessionId = null;
|
|
20
|
+
this.messageHandlers = /* @__PURE__ */ new Set();
|
|
21
|
+
this.connectionHandlers = /* @__PURE__ */ new Set();
|
|
22
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
23
|
+
this.wsUrl = config.wsUrl || DEFAULT_WS_URL;
|
|
24
|
+
this.debug = config.debug || false;
|
|
25
|
+
this.sessionManager = getSessionManager();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Start a new support chat session
|
|
29
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
30
|
+
* @param customerName - Optional: Customer name
|
|
31
|
+
* @param customerEmail - Optional: Customer email
|
|
32
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
33
|
+
*/
|
|
34
|
+
async startSupportChat(dialogflowSessionId, customerName, customerEmail, customerMobile) {
|
|
35
|
+
try {
|
|
36
|
+
const headers = {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
...this.sessionManager.getSessionHeader()
|
|
39
|
+
};
|
|
40
|
+
if (dialogflowSessionId) {
|
|
41
|
+
headers["X-Session-ID"] = dialogflowSessionId;
|
|
42
|
+
}
|
|
43
|
+
const body = {};
|
|
44
|
+
if (customerName) body.name = customerName;
|
|
45
|
+
if (customerEmail) body.email = customerEmail;
|
|
46
|
+
if (customerMobile) body.mobile = customerMobile;
|
|
47
|
+
const response = await fetch(`${this.baseUrl}/api/support/chat/start`, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers,
|
|
50
|
+
body: JSON.stringify(body)
|
|
51
|
+
});
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const error = await response.json().catch(() => ({}));
|
|
54
|
+
throw new Error(
|
|
55
|
+
error.message || `HTTP error! status: ${response.status}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
this.sessionManager.updateSessionFromResponse(data);
|
|
60
|
+
if (data.status && data.data) {
|
|
61
|
+
return {
|
|
62
|
+
chat_id: data.data.chat_id,
|
|
63
|
+
session_id: data.data.session_id
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (data.chat_id && data.session_id) {
|
|
67
|
+
return {
|
|
68
|
+
chat_id: data.chat_id,
|
|
69
|
+
session_id: data.session_id
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
throw new Error("Invalid response format from chat start endpoint");
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error("Error starting support chat:", error);
|
|
75
|
+
throw new Error(
|
|
76
|
+
error.message || "Failed to start support chat session"
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Request handoff to human agent
|
|
82
|
+
* @param chatId - Chat ID (must be valid, not undefined)
|
|
83
|
+
* @param sessionId - Session ID
|
|
84
|
+
* @param reason - Optional: Reason for handoff
|
|
85
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
86
|
+
* @param customerName - Optional: Customer name
|
|
87
|
+
* @param customerEmail - Optional: Customer email
|
|
88
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
89
|
+
*/
|
|
90
|
+
async requestHandoff(chatId, sessionId, reason, dialogflowSessionId, customerName, customerEmail, customerMobile) {
|
|
91
|
+
if (!chatId || chatId === "undefined" || chatId === "null") {
|
|
92
|
+
throw new Error("Invalid chat_id. Chat must be initialized first.");
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const headers = {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
...this.sessionManager.getSessionHeader()
|
|
98
|
+
};
|
|
99
|
+
if (sessionId) {
|
|
100
|
+
headers["X-Session-ID"] = sessionId;
|
|
101
|
+
} else if (dialogflowSessionId) {
|
|
102
|
+
headers["X-Session-ID"] = dialogflowSessionId;
|
|
103
|
+
}
|
|
104
|
+
const body = {};
|
|
105
|
+
if (reason) body.reason = reason;
|
|
106
|
+
if (customerName) body.name = customerName;
|
|
107
|
+
if (customerEmail) body.email = customerEmail;
|
|
108
|
+
if (customerMobile) body.mobile = customerMobile;
|
|
109
|
+
const response = await fetch(
|
|
110
|
+
`${this.baseUrl}/api/support/chat/${chatId}/handoff`,
|
|
111
|
+
{
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers,
|
|
114
|
+
body: JSON.stringify(body)
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
if (response.status === 400 || response.status === 404) {
|
|
118
|
+
const error = await response.json().catch(() => ({}));
|
|
119
|
+
throw new Error(
|
|
120
|
+
error.message || "Invalid chat_id. Chat may have expired."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const error = await response.json().catch(() => ({}));
|
|
125
|
+
throw new Error(
|
|
126
|
+
error.message || `HTTP error! status: ${response.status}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const data = await response.json();
|
|
130
|
+
this.sessionManager.updateSessionFromResponse(data);
|
|
131
|
+
if (data.status) {
|
|
132
|
+
return {
|
|
133
|
+
success: true,
|
|
134
|
+
message: data.message || data.data?.message
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
success: true,
|
|
139
|
+
message: data.message
|
|
140
|
+
};
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error("Error requesting handoff:", error);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Send message to agent via REST API
|
|
148
|
+
*/
|
|
149
|
+
async sendMessageToAgent(chatId, sessionId, message) {
|
|
150
|
+
try {
|
|
151
|
+
const headers = {
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
...this.sessionManager.getSessionHeader()
|
|
154
|
+
};
|
|
155
|
+
if (sessionId) {
|
|
156
|
+
headers["X-Session-ID"] = sessionId;
|
|
157
|
+
}
|
|
158
|
+
const response = await fetch(
|
|
159
|
+
`${this.baseUrl}/api/support/chat/${chatId}/message`,
|
|
160
|
+
{
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers,
|
|
163
|
+
body: JSON.stringify({
|
|
164
|
+
content: message
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
if (response.status === 401 || response.status === 404) {
|
|
169
|
+
const error = await response.json().catch(() => ({}));
|
|
170
|
+
throw new Error(
|
|
171
|
+
error.message || "Chat not found or unauthorized"
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const error = await response.json().catch(() => ({}));
|
|
176
|
+
throw new Error(
|
|
177
|
+
error.message || `HTTP error! status: ${response.status}`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
const data = await response.json();
|
|
181
|
+
this.sessionManager.updateSessionFromResponse(data);
|
|
182
|
+
if (data?.ignored === true && data?.reason === "chat_resolved") {
|
|
183
|
+
throw new ChatResolvedError();
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
id: data.id,
|
|
187
|
+
sender_type: "customer",
|
|
188
|
+
content: message,
|
|
189
|
+
timestamp: data.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (error instanceof ChatResolvedError || error?.name === "ChatResolvedError") {
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
console.error("Error sending message to agent:", error);
|
|
196
|
+
throw new Error(error.message || "Failed to send message to agent");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Ensure chat is initialized - helper method
|
|
201
|
+
* Returns existing chat_id if valid, otherwise initializes new chat
|
|
202
|
+
* @param existingChatId - Existing chat ID to validate
|
|
203
|
+
* @param existingSessionId - Existing session ID
|
|
204
|
+
* @param dialogflowSessionId - Optional: Dialogflow session ID
|
|
205
|
+
* @param customerName - Optional: Customer name
|
|
206
|
+
* @param customerEmail - Optional: Customer email
|
|
207
|
+
* @param customerMobile - Optional: Customer mobile number
|
|
208
|
+
* @returns Promise with chat_id and session_id
|
|
209
|
+
*/
|
|
210
|
+
async ensureChatInitialized(existingChatId, existingSessionId, dialogflowSessionId, customerName, customerEmail, customerMobile) {
|
|
211
|
+
if (existingChatId && existingChatId !== "undefined" && existingChatId !== "null" && existingSessionId) {
|
|
212
|
+
return {
|
|
213
|
+
chat_id: existingChatId,
|
|
214
|
+
session_id: existingSessionId
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return await this.startSupportChat(
|
|
218
|
+
dialogflowSessionId || null,
|
|
219
|
+
customerName || null,
|
|
220
|
+
customerEmail || null,
|
|
221
|
+
customerMobile || null
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Load message history
|
|
226
|
+
*/
|
|
227
|
+
async loadMessageHistory(chatId, sessionId) {
|
|
228
|
+
try {
|
|
229
|
+
const headers = {
|
|
230
|
+
...this.sessionManager.getSessionHeader()
|
|
231
|
+
};
|
|
232
|
+
if (sessionId) {
|
|
233
|
+
headers["X-Session-ID"] = sessionId;
|
|
234
|
+
}
|
|
235
|
+
const response = await fetch(
|
|
236
|
+
`${this.baseUrl}/api/support/chat/${chatId}/messages`,
|
|
237
|
+
{
|
|
238
|
+
method: "GET",
|
|
239
|
+
headers
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
if (response.status === 401 || response.status === 404) {
|
|
243
|
+
const error = await response.json().catch(() => ({}));
|
|
244
|
+
throw new Error(
|
|
245
|
+
error.message || "Chat not found or unauthorized"
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
if (!response.ok) {
|
|
249
|
+
const error = await response.json().catch(() => ({}));
|
|
250
|
+
throw new Error(
|
|
251
|
+
error.message || `HTTP error! status: ${response.status}`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
const data = await response.json();
|
|
255
|
+
this.sessionManager.updateSessionFromResponse(data);
|
|
256
|
+
return data.messages || [];
|
|
257
|
+
} catch (error) {
|
|
258
|
+
console.error("Error loading message history:", error);
|
|
259
|
+
throw new Error(error.message || "Failed to load message history");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Connect to WebSocket
|
|
264
|
+
*/
|
|
265
|
+
connectWebSocket(chatId, sessionId, onMessage, onConnectionChange, onClose) {
|
|
266
|
+
if (this.reconnectTimeout) {
|
|
267
|
+
clearTimeout(this.reconnectTimeout);
|
|
268
|
+
this.reconnectTimeout = null;
|
|
269
|
+
}
|
|
270
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
271
|
+
if (this.debug) {
|
|
272
|
+
console.log("WebSocket already connected");
|
|
273
|
+
}
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.currentChatId = chatId;
|
|
277
|
+
this.currentSessionId = sessionId;
|
|
278
|
+
if (onMessage) {
|
|
279
|
+
this.messageHandlers.add(onMessage);
|
|
280
|
+
}
|
|
281
|
+
if (onConnectionChange) {
|
|
282
|
+
this.connectionHandlers.add(onConnectionChange);
|
|
283
|
+
}
|
|
284
|
+
const sessionIdToUse = sessionId || this.sessionManager.getSessionId() || "";
|
|
285
|
+
const wsUrl = `${this.wsUrl}/ws/support/${chatId}?X-Session-ID=${encodeURIComponent(sessionIdToUse)}`;
|
|
286
|
+
try {
|
|
287
|
+
this.ws = new WebSocket(wsUrl);
|
|
288
|
+
this.ws.onopen = () => {
|
|
289
|
+
if (this.debug) {
|
|
290
|
+
console.log("WebSocket connected to:", wsUrl);
|
|
291
|
+
}
|
|
292
|
+
console.log("✅ Customer WebSocket connected:", { chatId, sessionId, wsUrl });
|
|
293
|
+
this.wsReconnectAttempts = 0;
|
|
294
|
+
this.connectionHandlers.forEach((handler) => handler(true));
|
|
295
|
+
this.startPingInterval();
|
|
296
|
+
};
|
|
297
|
+
this.ws.onmessage = (event) => {
|
|
298
|
+
try {
|
|
299
|
+
const message = JSON.parse(event.data);
|
|
300
|
+
if (this.debug) {
|
|
301
|
+
console.log("WebSocket raw message received:", event.data);
|
|
302
|
+
console.log("WebSocket parsed message:", message);
|
|
303
|
+
}
|
|
304
|
+
if (message.session_id) {
|
|
305
|
+
this.sessionManager.updateSessionFromResponse({ session_id: message.session_id });
|
|
306
|
+
}
|
|
307
|
+
if (message.type === "agent_accepted" || message.type === "chat_resolved" || message.type === "chat_ended") {
|
|
308
|
+
console.log("🔔 Received notification message:", {
|
|
309
|
+
type: message.type,
|
|
310
|
+
chat_id: message.chat_id,
|
|
311
|
+
timestamp: message.timestamp,
|
|
312
|
+
to_agent: message.to_agent,
|
|
313
|
+
to_agent_id: message.to_agent_id
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
if (message.type === "pong") {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (this.debug && message.type === "message") {
|
|
320
|
+
console.log("Processing message type:", {
|
|
321
|
+
type: message.type,
|
|
322
|
+
sender_type: message.sender_type,
|
|
323
|
+
content: message.content?.substring(0, 50) + "...",
|
|
324
|
+
id: message.id
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
this.messageHandlers.forEach((handler) => handler(message));
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error("Error parsing WebSocket message:", error);
|
|
330
|
+
if (this.debug) {
|
|
331
|
+
console.error("Raw message data:", event.data);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
this.ws.onerror = (error) => {
|
|
336
|
+
console.error("❌ WebSocket error:", error);
|
|
337
|
+
this.connectionHandlers.forEach((handler) => handler(false));
|
|
338
|
+
};
|
|
339
|
+
this.ws.onclose = (event) => {
|
|
340
|
+
if (this.debug) {
|
|
341
|
+
console.log("WebSocket closed:", event.code, event.reason);
|
|
342
|
+
}
|
|
343
|
+
console.log("🔌 Customer WebSocket closed:", { code: event.code, reason: event.reason, chatId });
|
|
344
|
+
this.stopPingInterval();
|
|
345
|
+
this.connectionHandlers.forEach((handler) => handler(false));
|
|
346
|
+
this.ws = null;
|
|
347
|
+
onClose?.(event);
|
|
348
|
+
if (event.code === 4e3) {
|
|
349
|
+
this.wsReconnectAttempts = this.maxReconnectAttempts;
|
|
350
|
+
this.currentChatId = null;
|
|
351
|
+
this.currentSessionId = null;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (this.wsReconnectAttempts < this.maxReconnectAttempts && this.currentChatId && this.currentSessionId) {
|
|
355
|
+
this.wsReconnectAttempts++;
|
|
356
|
+
const delay = Math.min(1e3 * Math.pow(2, this.wsReconnectAttempts), 3e4);
|
|
357
|
+
if (this.debug) {
|
|
358
|
+
console.log(`Reconnecting in ${delay}ms (attempt ${this.wsReconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
359
|
+
}
|
|
360
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
361
|
+
if (this.currentChatId && this.currentSessionId) {
|
|
362
|
+
this.connectWebSocket(this.currentChatId, this.currentSessionId, onMessage, onConnectionChange, onClose);
|
|
363
|
+
}
|
|
364
|
+
}, delay);
|
|
365
|
+
} else if (this.debug) {
|
|
366
|
+
console.error("Max reconnection attempts reached");
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
} catch (error) {
|
|
370
|
+
console.error("Error creating WebSocket connection:", error);
|
|
371
|
+
this.connectionHandlers.forEach((handler) => handler(false));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Send message via WebSocket
|
|
376
|
+
*/
|
|
377
|
+
sendMessageViaWebSocket(message) {
|
|
378
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
this.ws.send(
|
|
383
|
+
JSON.stringify({
|
|
384
|
+
type: "message",
|
|
385
|
+
content: message
|
|
386
|
+
})
|
|
387
|
+
);
|
|
388
|
+
return true;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
console.error("Error sending message via WebSocket:", error);
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Send typing indicator via WebSocket
|
|
396
|
+
*/
|
|
397
|
+
sendTypingIndicator(type) {
|
|
398
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
this.ws.send(
|
|
403
|
+
JSON.stringify({
|
|
404
|
+
type
|
|
405
|
+
})
|
|
406
|
+
);
|
|
407
|
+
return true;
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.error(`Error sending ${type} via WebSocket:`, error);
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Start ping interval to keep connection alive
|
|
415
|
+
*/
|
|
416
|
+
startPingInterval() {
|
|
417
|
+
this.stopPingInterval();
|
|
418
|
+
this.pingInterval = setInterval(() => {
|
|
419
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
420
|
+
try {
|
|
421
|
+
this.ws.send(JSON.stringify({ type: "ping" }));
|
|
422
|
+
} catch (error) {
|
|
423
|
+
console.error("Error sending ping:", error);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}, 3e4);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Stop ping interval
|
|
430
|
+
*/
|
|
431
|
+
stopPingInterval() {
|
|
432
|
+
if (this.pingInterval) {
|
|
433
|
+
clearInterval(this.pingInterval);
|
|
434
|
+
this.pingInterval = null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Disconnect WebSocket
|
|
439
|
+
*/
|
|
440
|
+
disconnectWebSocket() {
|
|
441
|
+
if (this.reconnectTimeout) {
|
|
442
|
+
clearTimeout(this.reconnectTimeout);
|
|
443
|
+
this.reconnectTimeout = null;
|
|
444
|
+
}
|
|
445
|
+
this.stopPingInterval();
|
|
446
|
+
if (this.ws) {
|
|
447
|
+
this.ws.close();
|
|
448
|
+
this.ws = null;
|
|
449
|
+
}
|
|
450
|
+
this.messageHandlers.clear();
|
|
451
|
+
this.connectionHandlers.clear();
|
|
452
|
+
this.wsReconnectAttempts = 0;
|
|
453
|
+
this.currentChatId = null;
|
|
454
|
+
this.currentSessionId = null;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Check if WebSocket is connected
|
|
458
|
+
*/
|
|
459
|
+
isWebSocketConnected() {
|
|
460
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Remove message handler
|
|
464
|
+
*/
|
|
465
|
+
removeMessageHandler(handler) {
|
|
466
|
+
this.messageHandlers.delete(handler);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Remove connection handler
|
|
470
|
+
*/
|
|
471
|
+
removeConnectionHandler(handler) {
|
|
472
|
+
this.connectionHandlers.delete(handler);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function createChatService(config) {
|
|
476
|
+
return new ChatService(config);
|
|
477
|
+
}
|
|
478
|
+
export {
|
|
479
|
+
ChatResolvedError,
|
|
480
|
+
createChatService
|
|
481
|
+
};
|
|
482
|
+
//# sourceMappingURL=chatService.esm.js.map
|