@origonai/web-chat-sdk 1.0.8 → 1.0.9
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/origon-chat-sdk.js +198 -197
- package/dist/origon-chat-sdk.js.map +1 -1
- package/package.json +1 -1
- package/src/chat.js +4 -3
package/dist/origon-chat-sdk.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fetchEventSource as
|
|
2
|
-
function
|
|
1
|
+
import { fetchEventSource as ge } from "@microsoft/fetch-event-source";
|
|
2
|
+
function j() {
|
|
3
3
|
const e = Date.now(), n = new Uint8Array(16);
|
|
4
4
|
crypto.getRandomValues(n), n[0] = e >> 40 & 255, n[1] = e >> 32 & 255, n[2] = e >> 24 & 255, n[3] = e >> 16 & 255, n[4] = e >> 8 & 255, n[5] = e & 255, n[6] = n[6] & 15 | 112, n[8] = n[8] & 63 | 128;
|
|
5
5
|
const o = [...n].map((r) => r.toString(16).padStart(2, "0")).join("");
|
|
@@ -8,16 +8,16 @@ function Z() {
|
|
|
8
8
|
20
|
|
9
9
|
)}-${o.slice(20)}`;
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function fe() {
|
|
12
12
|
if (localStorage.getItem("chatDeviceId"))
|
|
13
13
|
return localStorage.getItem("chatDeviceId");
|
|
14
|
-
const e =
|
|
14
|
+
const e = j();
|
|
15
15
|
return localStorage.setItem("chatDeviceId", e), e;
|
|
16
16
|
}
|
|
17
|
-
async function
|
|
17
|
+
async function pe(e) {
|
|
18
18
|
return new Promise((n) => setTimeout(n, e));
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function me(e) {
|
|
21
21
|
let n;
|
|
22
22
|
try {
|
|
23
23
|
const o = new URL(e);
|
|
@@ -26,7 +26,7 @@ function pe(e) {
|
|
|
26
26
|
}
|
|
27
27
|
return n;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function Se(e) {
|
|
30
30
|
let n;
|
|
31
31
|
try {
|
|
32
32
|
const o = new URL(e);
|
|
@@ -35,7 +35,7 @@ function me(e) {
|
|
|
35
35
|
}
|
|
36
36
|
return n;
|
|
37
37
|
}
|
|
38
|
-
function
|
|
38
|
+
function ke(e) {
|
|
39
39
|
let n;
|
|
40
40
|
try {
|
|
41
41
|
const o = new URL(e);
|
|
@@ -53,13 +53,13 @@ const y = {
|
|
|
53
53
|
// this is human supervisor (ex. Samespace Dock agent, or Resolve human agent)
|
|
54
54
|
SYSTEM: "system"
|
|
55
55
|
// this is system message, for ex "Agent joined" / "Agent left"
|
|
56
|
-
},
|
|
56
|
+
}, ee = 1e4, Ie = 5e3, R = {
|
|
57
57
|
MESSAGE: "message",
|
|
58
58
|
TYPING: "typing",
|
|
59
59
|
TYPING_STOP: "typingOff",
|
|
60
60
|
END: "end"
|
|
61
61
|
};
|
|
62
|
-
function
|
|
62
|
+
function he() {
|
|
63
63
|
return {
|
|
64
64
|
socket: null,
|
|
65
65
|
previouslyConnected: !1,
|
|
@@ -69,25 +69,25 @@ function Ie() {
|
|
|
69
69
|
socketConnectionTimeout: null
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
-
let a =
|
|
73
|
-
function
|
|
72
|
+
let a = he();
|
|
73
|
+
function x() {
|
|
74
74
|
a.pingInterval && (clearInterval(a.pingInterval), a.pingInterval = null);
|
|
75
75
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
a.socket && a.socket.readyState === WebSocket.OPEN ?
|
|
79
|
-
},
|
|
80
|
-
}
|
|
81
|
-
function ee() {
|
|
82
|
-
M(), a.socketDisconnectedTimeout && (clearTimeout(a.socketDisconnectedTimeout), a.socketDisconnectedTimeout = null), a.socketConnectionTimeout && (clearTimeout(a.socketConnectionTimeout), a.socketConnectionTimeout = null);
|
|
76
|
+
function we() {
|
|
77
|
+
x(), a.pingInterval = setInterval(() => {
|
|
78
|
+
a.socket && a.socket.readyState === WebSocket.OPEN ? q({ type: "ping" }) : x();
|
|
79
|
+
}, ee);
|
|
83
80
|
}
|
|
84
81
|
function ne() {
|
|
85
|
-
a.
|
|
82
|
+
x(), a.socketDisconnectedTimeout && (clearTimeout(a.socketDisconnectedTimeout), a.socketDisconnectedTimeout = null), a.socketConnectionTimeout && (clearTimeout(a.socketConnectionTimeout), a.socketConnectionTimeout = null);
|
|
86
83
|
}
|
|
87
84
|
function te() {
|
|
88
|
-
a.socketDisconnected = !
|
|
85
|
+
a.socketDisconnected = !1, N("socket");
|
|
86
|
+
}
|
|
87
|
+
function oe() {
|
|
88
|
+
a.socketDisconnected = !0, N("sse");
|
|
89
89
|
}
|
|
90
|
-
function
|
|
90
|
+
function Ce(e) {
|
|
91
91
|
return new Promise((n, o) => {
|
|
92
92
|
if (a.socket && (a.socket.readyState === WebSocket.CONNECTING || a.socket.readyState === WebSocket.OPEN)) {
|
|
93
93
|
n(a.socket.readyState === WebSocket.OPEN);
|
|
@@ -98,7 +98,7 @@ function we(e) {
|
|
|
98
98
|
o(new Error("SDK not initialized. Please initialize SDK first."));
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
|
-
const l =
|
|
101
|
+
const l = Se(r.endpoint);
|
|
102
102
|
if (!l) {
|
|
103
103
|
o(
|
|
104
104
|
new Error(
|
|
@@ -107,53 +107,53 @@ function we(e) {
|
|
|
107
107
|
);
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
|
-
const d =
|
|
110
|
+
const d = O(), c = new URLSearchParams({
|
|
111
111
|
externalId: d
|
|
112
112
|
});
|
|
113
113
|
e.sessionId && c.set("sessionId", e.sessionId), e.requestId && c.set("requestId", e.requestId), r.token && c.set("token", r.token);
|
|
114
114
|
const u = `${l}?${c.toString()}`;
|
|
115
115
|
a.socket = new WebSocket(u), a.socket.onopen = () => {
|
|
116
|
-
a.previouslyConnected = !0,
|
|
117
|
-
}, a.socket.onmessage = (
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
}, a.socket.onerror = (
|
|
121
|
-
|
|
122
|
-
}, a.socket.onclose = (
|
|
123
|
-
|
|
116
|
+
a.previouslyConnected = !0, te(), q({ type: "ping" }), clearTimeout(a.socketConnectionTimeout), we(), n(!0);
|
|
117
|
+
}, a.socket.onmessage = (g) => {
|
|
118
|
+
const f = JSON.parse(g.data);
|
|
119
|
+
Ee(f);
|
|
120
|
+
}, a.socket.onerror = (g) => {
|
|
121
|
+
N("sse"), o(g);
|
|
122
|
+
}, a.socket.onclose = (g) => {
|
|
123
|
+
g.target === a.socket && (g.code === 1006 && (a.previouslyConnected ? oe() : h({
|
|
124
124
|
errorText: "Unable to establish connection",
|
|
125
125
|
done: !0,
|
|
126
126
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
127
|
-
}), clearTimeout(a.socketConnectionTimeout)), a.socket = null,
|
|
127
|
+
}), clearTimeout(a.socketConnectionTimeout)), a.socket = null, ne());
|
|
128
128
|
}, a.previouslyConnected || (a.socketConnectionTimeout = setTimeout(() => {
|
|
129
129
|
h({
|
|
130
130
|
errorText: "Unable to establish connection",
|
|
131
131
|
done: !0,
|
|
132
132
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
133
133
|
}), o(new Error("Socket connection timed out"));
|
|
134
|
-
},
|
|
134
|
+
}, Ie));
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
|
-
function
|
|
138
|
-
a.socketDisconnected || !a.socket || a.socket.send(JSON.stringify({ ...e, eventId: e.eventId ||
|
|
137
|
+
function q(e) {
|
|
138
|
+
a.socketDisconnected || !a.socket || a.socket.send(JSON.stringify({ ...e, eventId: e.eventId || j() }));
|
|
139
139
|
}
|
|
140
|
-
function
|
|
140
|
+
function Ee(e) {
|
|
141
141
|
switch (e.type) {
|
|
142
142
|
case "pong": {
|
|
143
|
-
a.socketDisconnected &&
|
|
144
|
-
|
|
145
|
-
},
|
|
143
|
+
a.socketDisconnected && te(), a.socketDisconnectedTimeout && clearTimeout(a.socketDisconnectedTimeout), a.socketDisconnectedTimeout = setTimeout(() => {
|
|
144
|
+
oe();
|
|
145
|
+
}, ee + 1e3);
|
|
146
146
|
break;
|
|
147
147
|
}
|
|
148
|
-
case
|
|
149
|
-
|
|
148
|
+
case R.TYPING: {
|
|
149
|
+
Z(!0);
|
|
150
150
|
break;
|
|
151
151
|
}
|
|
152
|
-
case
|
|
153
|
-
|
|
152
|
+
case R.TYPING_STOP: {
|
|
153
|
+
Z(!1);
|
|
154
154
|
break;
|
|
155
155
|
}
|
|
156
|
-
case
|
|
156
|
+
case R.MESSAGE: {
|
|
157
157
|
const { eventId: n, data: o } = e;
|
|
158
158
|
n || h({
|
|
159
159
|
...o,
|
|
@@ -162,19 +162,19 @@ function Ce(e) {
|
|
|
162
162
|
});
|
|
163
163
|
break;
|
|
164
164
|
}
|
|
165
|
-
case
|
|
166
|
-
|
|
165
|
+
case R.END: {
|
|
166
|
+
se();
|
|
167
167
|
break;
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
function
|
|
172
|
-
a.socket && a.socket.close(1e3), a.previouslyConnected = !1,
|
|
171
|
+
function se() {
|
|
172
|
+
a.socket && a.socket.close(1e3), a.previouslyConnected = !1, ne(), a.socket = null, N("sse");
|
|
173
173
|
}
|
|
174
|
-
function
|
|
174
|
+
function ye() {
|
|
175
175
|
return a.socket !== null && a.socket.readyState === WebSocket.OPEN && !a.socketDisconnected;
|
|
176
176
|
}
|
|
177
|
-
function
|
|
177
|
+
function re(e = {}) {
|
|
178
178
|
return {
|
|
179
179
|
credentials: void 0,
|
|
180
180
|
authenticated: !1,
|
|
@@ -190,33 +190,33 @@ function se(e = {}) {
|
|
|
190
190
|
control: "agent"
|
|
191
191
|
};
|
|
192
192
|
}
|
|
193
|
-
let s =
|
|
194
|
-
function
|
|
193
|
+
let s = re();
|
|
194
|
+
function Ge(e) {
|
|
195
195
|
s.callbacks = { ...s.callbacks, ...e };
|
|
196
196
|
}
|
|
197
|
-
function
|
|
197
|
+
function Je(e) {
|
|
198
198
|
s.credentials = e, e.token && (s.authenticated = !0);
|
|
199
199
|
}
|
|
200
200
|
function b() {
|
|
201
201
|
return s.credentials;
|
|
202
202
|
}
|
|
203
|
-
function
|
|
203
|
+
function be(e) {
|
|
204
204
|
var n, o;
|
|
205
205
|
e && e !== s.sessionId && (s.sessionId = e, (o = (n = s.callbacks).onSessionUpdate) == null || o.call(n, e));
|
|
206
206
|
}
|
|
207
|
-
async function
|
|
207
|
+
async function We(e = {}) {
|
|
208
208
|
try {
|
|
209
209
|
let n = null;
|
|
210
|
-
s.authenticated ? n = s.configData : (n = await
|
|
210
|
+
s.authenticated ? n = s.configData : (n = await $e(s.credentials), s.authenticated = !0, s.configData = n);
|
|
211
211
|
let o = [], r = "agent";
|
|
212
212
|
if (e.sessionId) {
|
|
213
|
-
const d = await
|
|
213
|
+
const d = await De(e.sessionId);
|
|
214
214
|
o = d.messages, r = d.control || "agent";
|
|
215
215
|
}
|
|
216
216
|
const l = new URLSearchParams();
|
|
217
|
-
return s.credentials.token || l.set("externalId",
|
|
217
|
+
return s.credentials.token || l.set("externalId", O()), s.sseUrl = `${me(
|
|
218
218
|
s.credentials.endpoint
|
|
219
|
-
)}?${l.toString()}`, s.sessionId = e.sessionId, s.messages = o, s.control = r, r === "human" &&
|
|
219
|
+
)}?${l.toString()}`, s.sessionId = e.sessionId, s.messages = o, s.control = r, r === "human" && Te({ text: "", html: "" }).catch(() => {
|
|
220
220
|
}), {
|
|
221
221
|
sessionId: s.sessionId,
|
|
222
222
|
messages: o,
|
|
@@ -224,57 +224,58 @@ async function Je(e = {}) {
|
|
|
224
224
|
configData: n
|
|
225
225
|
};
|
|
226
226
|
} catch (n) {
|
|
227
|
-
throw
|
|
227
|
+
throw ae(), n;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
-
function
|
|
231
|
-
|
|
230
|
+
function _e() {
|
|
231
|
+
ae();
|
|
232
232
|
}
|
|
233
|
-
function
|
|
234
|
-
s.abortController && s.abortController.abort(),
|
|
233
|
+
function ae() {
|
|
234
|
+
s.abortController && s.abortController.abort(), se();
|
|
235
235
|
const { callbacks: e, credentials: n } = s;
|
|
236
|
-
s =
|
|
236
|
+
s = re(e), s.credentials = n;
|
|
237
237
|
}
|
|
238
|
-
function
|
|
238
|
+
function O() {
|
|
239
239
|
var e;
|
|
240
|
-
return (e = s.credentials) != null && e.externalId ? s.credentials.externalId :
|
|
240
|
+
return (e = s.credentials) != null && e.externalId ? s.credentials.externalId : fe();
|
|
241
241
|
}
|
|
242
242
|
function h(e) {
|
|
243
243
|
var n, o;
|
|
244
244
|
s.messages = [...s.messages, e], (o = (n = s.callbacks).onMessageAdd) == null || o.call(n, e);
|
|
245
245
|
}
|
|
246
|
-
function
|
|
246
|
+
function Z(e) {
|
|
247
247
|
var n, o;
|
|
248
248
|
(o = (n = s.callbacks).onTyping) == null || o.call(n, e);
|
|
249
249
|
}
|
|
250
|
-
function
|
|
250
|
+
function N(e) {
|
|
251
251
|
var n, o;
|
|
252
252
|
s.transport = e, (o = (n = s.callbacks).onTransportUpdate) == null || o.call(n, e);
|
|
253
253
|
}
|
|
254
|
-
function
|
|
255
|
-
return new Promise((
|
|
254
|
+
function Te({ text: e, html: n, context: o, attachments: r, meta: l }) {
|
|
255
|
+
return new Promise((d, c) => {
|
|
256
256
|
(async () => {
|
|
257
|
-
var
|
|
257
|
+
var u, g, f;
|
|
258
258
|
try {
|
|
259
|
-
const
|
|
260
|
-
if (!
|
|
259
|
+
const I = !e && !n && !(r != null && r.length);
|
|
260
|
+
if (!I) {
|
|
261
261
|
const p = {
|
|
262
262
|
role: y.USER,
|
|
263
263
|
text: e,
|
|
264
264
|
html: n,
|
|
265
265
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
266
|
-
attachments: r
|
|
266
|
+
attachments: r,
|
|
267
|
+
meta: l
|
|
267
268
|
};
|
|
268
|
-
h(p), await
|
|
269
|
+
h(p), await pe(200);
|
|
269
270
|
}
|
|
270
|
-
if (s.transport === "socket" &&
|
|
271
|
-
|
|
271
|
+
if (s.transport === "socket" && ye()) {
|
|
272
|
+
q({
|
|
272
273
|
type: "message",
|
|
273
274
|
data: {
|
|
274
275
|
text: e,
|
|
275
276
|
html: n
|
|
276
277
|
}
|
|
277
|
-
}),
|
|
278
|
+
}), d(s.sessionId);
|
|
278
279
|
return;
|
|
279
280
|
}
|
|
280
281
|
if (s.control === "agent") {
|
|
@@ -285,15 +286,15 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
285
286
|
};
|
|
286
287
|
h(p);
|
|
287
288
|
}
|
|
288
|
-
const
|
|
289
|
-
s.sessionId &&
|
|
289
|
+
const v = new URL(s.sseUrl);
|
|
290
|
+
s.sessionId && v.searchParams.set("sessionId", s.sessionId), s.requestId && v.searchParams.set("requestId", s.requestId), s.lastStreamId = void 0, s.abortController = new AbortController();
|
|
290
291
|
const C = {
|
|
291
292
|
"Content-Type": "application/json"
|
|
292
293
|
};
|
|
293
|
-
(
|
|
294
|
+
(u = s.credentials) != null && u.token && (C.Authorization = `Bearer ${s.credentials.token}`), await ge(v.toString(), {
|
|
294
295
|
method: "POST",
|
|
295
296
|
headers: C,
|
|
296
|
-
body:
|
|
297
|
+
body: I ? l : JSON.stringify({
|
|
297
298
|
message: e,
|
|
298
299
|
html: n,
|
|
299
300
|
context: o,
|
|
@@ -306,17 +307,17 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
306
307
|
throw new Error("Failed to send message");
|
|
307
308
|
},
|
|
308
309
|
onmessage: (p) => {
|
|
309
|
-
var
|
|
310
|
+
var D, A, L, z, F, G, J, W, _, K, H, V, B, Y, Q, X;
|
|
310
311
|
const i = JSON.parse(p.data);
|
|
311
312
|
if (p.event === "connected")
|
|
312
|
-
s.sessionId = i.sessionId, s.requestId = i.requestId, i.control && (s.control = i.control, (
|
|
313
|
+
s.sessionId = i.sessionId, s.requestId = i.requestId, i.control && (s.control = i.control, (A = (D = s.callbacks).onControlUpdate) == null || A.call(D, i.control));
|
|
313
314
|
else if (p.event === "upgrade_to_websocket")
|
|
314
|
-
|
|
315
|
+
Ce({
|
|
315
316
|
sessionId: s.sessionId,
|
|
316
317
|
requestId: i.requestId
|
|
317
318
|
});
|
|
318
319
|
else if (p.event === "update")
|
|
319
|
-
i.control && (s.control = i.control, (
|
|
320
|
+
i.control && (s.control = i.control, (z = (L = s.callbacks).onControlUpdate) == null || z.call(L, i.control));
|
|
320
321
|
else if (i.error) {
|
|
321
322
|
const m = i.error && typeof i.error == "string" ? i.error : "Failed to connect to the system", k = s.messages.length - 1, S = {
|
|
322
323
|
...s.messages[k],
|
|
@@ -324,8 +325,8 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
324
325
|
errorText: m
|
|
325
326
|
};
|
|
326
327
|
s.messages = s.messages.map(
|
|
327
|
-
(
|
|
328
|
-
), (
|
|
328
|
+
($, ue) => ue === k ? S : $
|
|
329
|
+
), (G = (F = s.callbacks).onMessageUpdate) == null || G.call(F, k, S), c(new Error(m));
|
|
329
330
|
} else if (p.event === "done") {
|
|
330
331
|
const m = s.messages.length - 1, E = {
|
|
331
332
|
...s.messages[m],
|
|
@@ -333,9 +334,9 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
333
334
|
done: !0
|
|
334
335
|
};
|
|
335
336
|
s.messages = s.messages.map(
|
|
336
|
-
(S,
|
|
337
|
-
), (
|
|
338
|
-
} else if (i.message !== void 0 || ((
|
|
337
|
+
(S, $) => $ === m ? E : S
|
|
338
|
+
), (W = (J = s.callbacks).onMessageUpdate) == null || W.call(J, m, E), d(s.sessionId);
|
|
339
|
+
} else if (i.message !== void 0 || ((_ = i.attachments) == null ? void 0 : _.length) > 0) {
|
|
339
340
|
if (i.role === y.SUPERVISOR) {
|
|
340
341
|
const S = {
|
|
341
342
|
role: y.SUPERVISOR,
|
|
@@ -344,7 +345,7 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
344
345
|
sources: i.sources,
|
|
345
346
|
done: !0
|
|
346
347
|
};
|
|
347
|
-
h(S),
|
|
348
|
+
h(S), d(s.sessionId), s.sessionId = (K = i.sessionId) != null ? K : s.sessionId, s.requestId = (H = i.requestId) != null ? H : s.requestId;
|
|
348
349
|
return;
|
|
349
350
|
}
|
|
350
351
|
if (i.streamId !== void 0) {
|
|
@@ -366,11 +367,11 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
366
367
|
text: (k.text || "") + i.message,
|
|
367
368
|
sources: i.sources,
|
|
368
369
|
attachments: i.attachments,
|
|
369
|
-
done: (
|
|
370
|
+
done: (V = i.done) != null ? V : k.done
|
|
370
371
|
};
|
|
371
372
|
s.messages = s.messages.map(
|
|
372
|
-
(S,
|
|
373
|
-
), (
|
|
373
|
+
(S, $) => $ === m ? E : S
|
|
374
|
+
), (Y = (B = s.callbacks).onMessageUpdate) == null || Y.call(B, m, E), s.sessionId = (Q = i.sessionId) != null ? Q : s.sessionId, s.requestId = (X = i.requestId) != null ? X : s.requestId;
|
|
374
375
|
}
|
|
375
376
|
},
|
|
376
377
|
onerror: (p) => {
|
|
@@ -378,22 +379,22 @@ function be({ text: e, html: n, context: o, attachments: r }) {
|
|
|
378
379
|
},
|
|
379
380
|
openWhenHidden: !0
|
|
380
381
|
});
|
|
381
|
-
} catch (
|
|
382
|
-
const
|
|
382
|
+
} catch (I) {
|
|
383
|
+
const v = "Failed to connect to the system", C = s.messages.length - 1, p = s.messages[C], i = {
|
|
383
384
|
...p,
|
|
384
385
|
loading: !1,
|
|
385
|
-
errorText: p.done ? void 0 :
|
|
386
|
+
errorText: p.done ? void 0 : I.message || v,
|
|
386
387
|
done: !0
|
|
387
388
|
};
|
|
388
389
|
s.messages = s.messages.map(
|
|
389
|
-
(
|
|
390
|
-
), (f = (
|
|
390
|
+
(D, A) => A === C ? i : D
|
|
391
|
+
), (f = (g = s.callbacks).onMessageUpdate) == null || f.call(g, C, i), c(I);
|
|
391
392
|
}
|
|
392
393
|
})();
|
|
393
394
|
});
|
|
394
395
|
}
|
|
395
|
-
const
|
|
396
|
-
async function
|
|
396
|
+
const ve = "Something went wrong initializing the chat", M = "Chat SDK not initialized";
|
|
397
|
+
async function $e(e) {
|
|
397
398
|
const { endpoint: n } = e, o = `${n}/config`, r = await fetch(o, {
|
|
398
399
|
method: "GET",
|
|
399
400
|
headers: {
|
|
@@ -402,23 +403,23 @@ async function ve(e) {
|
|
|
402
403
|
});
|
|
403
404
|
if (!r.ok) {
|
|
404
405
|
const c = await r.json();
|
|
405
|
-
throw new Error((c == null ? void 0 : c.error) ||
|
|
406
|
+
throw new Error((c == null ? void 0 : c.error) || ve);
|
|
406
407
|
}
|
|
407
408
|
return (await r.json()).data;
|
|
408
409
|
}
|
|
409
|
-
async function
|
|
410
|
+
async function Ke() {
|
|
410
411
|
const e = new URLSearchParams({
|
|
411
|
-
externalId:
|
|
412
|
-
}), n = await
|
|
412
|
+
externalId: O()
|
|
413
|
+
}), n = await ce(`/sessions?${e.toString()}`, "GET");
|
|
413
414
|
if (!n.ok)
|
|
414
415
|
throw new Error("Unable to load history, please try again later");
|
|
415
416
|
return n.json();
|
|
416
417
|
}
|
|
417
|
-
async function
|
|
418
|
+
async function De(e) {
|
|
418
419
|
var c;
|
|
419
420
|
const n = new URLSearchParams({
|
|
420
421
|
sessionId: e
|
|
421
|
-
}), o = await
|
|
422
|
+
}), o = await ce(`/session?${n.toString()}`, "GET");
|
|
422
423
|
if (!o.ok)
|
|
423
424
|
throw new Error("Unable to load messages, please try again later");
|
|
424
425
|
const r = await o.json(), l = r == null ? void 0 : r.control, d = ((c = r == null ? void 0 : r.history) != null ? c : []).map((u) => ({
|
|
@@ -433,26 +434,26 @@ async function $e(e) {
|
|
|
433
434
|
}));
|
|
434
435
|
return { control: l, messages: d };
|
|
435
436
|
}
|
|
436
|
-
function
|
|
437
|
+
function He(e, n, o) {
|
|
437
438
|
const r = b(), { endpoint: l, token: d } = r || {};
|
|
438
439
|
if (!l) {
|
|
439
|
-
const
|
|
440
|
-
return o && o(
|
|
440
|
+
const f = new Error(M);
|
|
441
|
+
return o && o(f, null), null;
|
|
441
442
|
}
|
|
442
443
|
const c = new XMLHttpRequest(), u = new FormData();
|
|
443
444
|
u.append("file", e);
|
|
444
|
-
const
|
|
445
|
-
return c.open("POST",
|
|
446
|
-
if (
|
|
447
|
-
const I =
|
|
448
|
-
n(I,
|
|
445
|
+
const g = `${l}/upload`;
|
|
446
|
+
return c.open("POST", g), d && c.setRequestHeader("Authorization", `Bearer ${d}`), n && c.upload.addEventListener("progress", (f) => {
|
|
447
|
+
if (f.lengthComputable) {
|
|
448
|
+
const I = f.loaded / f.total * 100;
|
|
449
|
+
n(I, f.loaded, f.total);
|
|
449
450
|
}
|
|
450
451
|
}), c.addEventListener("load", () => {
|
|
451
452
|
if (c.status >= 200 && c.status < 300)
|
|
452
453
|
try {
|
|
453
|
-
const
|
|
454
|
-
o && o(null,
|
|
455
|
-
} catch (
|
|
454
|
+
const f = JSON.parse(c.responseText);
|
|
455
|
+
o && o(null, f);
|
|
456
|
+
} catch (f) {
|
|
456
457
|
o && o(new Error("Failed to parse response"), null);
|
|
457
458
|
}
|
|
458
459
|
else
|
|
@@ -463,10 +464,10 @@ function Ke(e, n, o) {
|
|
|
463
464
|
o && o(new Error("Upload aborted"), null);
|
|
464
465
|
}), c.send(u), c;
|
|
465
466
|
}
|
|
466
|
-
async function
|
|
467
|
+
async function Ve(e) {
|
|
467
468
|
const n = b(), { endpoint: o, token: r } = n || {};
|
|
468
469
|
if (!o)
|
|
469
|
-
throw new Error(
|
|
470
|
+
throw new Error(M);
|
|
470
471
|
const l = `${o}/delete/${e}`, d = {};
|
|
471
472
|
r && (d.Authorization = `Bearer ${r}`);
|
|
472
473
|
const c = await fetch(l, {
|
|
@@ -477,16 +478,16 @@ async function He(e) {
|
|
|
477
478
|
throw new Error(`Delete failed with status ${c.status}`);
|
|
478
479
|
return { success: !0 };
|
|
479
480
|
}
|
|
480
|
-
function
|
|
481
|
+
function Be(e) {
|
|
481
482
|
const n = b(), { endpoint: o } = n || {};
|
|
482
483
|
if (!o)
|
|
483
|
-
throw new Error(
|
|
484
|
+
throw new Error(M);
|
|
484
485
|
return `${o}/upload/${e}`;
|
|
485
486
|
}
|
|
486
|
-
async function
|
|
487
|
+
async function ce(e, n = "GET", o = null) {
|
|
487
488
|
const r = b(), { endpoint: l, token: d } = r || {};
|
|
488
489
|
if (!l)
|
|
489
|
-
throw new Error(
|
|
490
|
+
throw new Error(M);
|
|
490
491
|
const c = `${l}${e}`, u = {
|
|
491
492
|
"Content-Type": "application/json"
|
|
492
493
|
};
|
|
@@ -496,7 +497,7 @@ async function ae(e, n = "GET", o = null) {
|
|
|
496
497
|
body: o ? JSON.stringify(o) : null
|
|
497
498
|
});
|
|
498
499
|
}
|
|
499
|
-
function
|
|
500
|
+
function ie(e = {}) {
|
|
500
501
|
return {
|
|
501
502
|
sessionId: void 0,
|
|
502
503
|
socket: null,
|
|
@@ -514,31 +515,31 @@ function ce(e = {}) {
|
|
|
514
515
|
pendingRemoteIceCandidates: []
|
|
515
516
|
};
|
|
516
517
|
}
|
|
517
|
-
let t =
|
|
518
|
-
const
|
|
518
|
+
let t = ie();
|
|
519
|
+
const Ae = {
|
|
519
520
|
iceServers: [{ urls: "stun:stun.l.google.com:19302" }, { urls: "stun:stun1.l.google.com:19302" }]
|
|
520
521
|
};
|
|
521
|
-
function
|
|
522
|
+
function Ye(e) {
|
|
522
523
|
t.callbacks = { ...t.callbacks, ...e };
|
|
523
524
|
}
|
|
524
|
-
function
|
|
525
|
-
t.peerConnection && (t.peerConnection.close(), t.peerConnection = null), t.localStream && (t.localStream.getTracks().forEach((n) => n.stop()), t.localStream = null), t.remoteStream && (t.remoteStream = null), t.remoteAudio && (t.remoteAudio.srcObject = null, t.remoteAudio.parentNode && t.remoteAudio.parentNode.removeChild(t.remoteAudio), t.remoteAudio = null), t.socket && (t.socket.close(), t.socket = null),
|
|
525
|
+
function le() {
|
|
526
|
+
t.peerConnection && (t.peerConnection.close(), t.peerConnection = null), t.localStream && (t.localStream.getTracks().forEach((n) => n.stop()), t.localStream = null), t.remoteStream && (t.remoteStream = null), t.remoteAudio && (t.remoteAudio.srcObject = null, t.remoteAudio.parentNode && t.remoteAudio.parentNode.removeChild(t.remoteAudio), t.remoteAudio = null), t.socket && (t.socket.close(), t.socket = null), P();
|
|
526
527
|
const e = t.callbacks;
|
|
527
|
-
t =
|
|
528
|
+
t = ie(e);
|
|
528
529
|
}
|
|
529
530
|
function w(e) {
|
|
530
531
|
var n, o;
|
|
531
532
|
t.callStatus = e, (o = (n = t.callbacks).onCallStatus) == null || o.call(n, e);
|
|
532
533
|
}
|
|
533
|
-
function
|
|
534
|
+
function U(e) {
|
|
534
535
|
var n, o;
|
|
535
536
|
(o = (n = t.callbacks).onCallError) == null || o.call(n, e);
|
|
536
537
|
}
|
|
537
|
-
function
|
|
538
|
+
function P() {
|
|
538
539
|
t.pingInterval && (clearInterval(t.pingInterval), t.pingInterval = null);
|
|
539
540
|
}
|
|
540
|
-
function
|
|
541
|
-
|
|
541
|
+
function Re() {
|
|
542
|
+
P(), t.pingInterval = setInterval(() => {
|
|
542
543
|
if (t.socket && t.socket.readyState === WebSocket.OPEN) {
|
|
543
544
|
t.pingCount++;
|
|
544
545
|
const e = {
|
|
@@ -548,16 +549,16 @@ function Ae() {
|
|
|
548
549
|
};
|
|
549
550
|
T(e);
|
|
550
551
|
} else
|
|
551
|
-
|
|
552
|
+
P();
|
|
552
553
|
}, 1e4);
|
|
553
554
|
}
|
|
554
|
-
function
|
|
555
|
+
function Ue() {
|
|
555
556
|
t.lastPongTime = Date.now();
|
|
556
557
|
}
|
|
557
558
|
function T(e) {
|
|
558
559
|
t.socket && t.socket.readyState === WebSocket.OPEN && t.socket.send(JSON.stringify(e));
|
|
559
560
|
}
|
|
560
|
-
async function
|
|
561
|
+
async function Pe() {
|
|
561
562
|
try {
|
|
562
563
|
t.localStream = await navigator.mediaDevices.getUserMedia({
|
|
563
564
|
audio: !0,
|
|
@@ -567,8 +568,8 @@ async function Ue() {
|
|
|
567
568
|
throw e;
|
|
568
569
|
}
|
|
569
570
|
}
|
|
570
|
-
function
|
|
571
|
-
t.peerConnection = new RTCPeerConnection(
|
|
571
|
+
function Oe() {
|
|
572
|
+
t.peerConnection = new RTCPeerConnection(Ae), t.peerConnection.onicecandidate = (e) => {
|
|
572
573
|
if (e.candidate) {
|
|
573
574
|
const n = JSON.stringify(e.candidate);
|
|
574
575
|
t.peerConnection && t.peerConnection.remoteDescription ? T({
|
|
@@ -584,11 +585,11 @@ function Pe() {
|
|
|
584
585
|
});
|
|
585
586
|
}, t.peerConnection.onconnectionstatechange = () => {
|
|
586
587
|
const e = t.peerConnection.connectionState;
|
|
587
|
-
e === "connected" ? w("connected") : (e === "disconnected" || e === "closed") && (w("disconnected"),
|
|
588
|
+
e === "connected" ? w("connected") : (e === "disconnected" || e === "closed") && (w("disconnected"), de());
|
|
588
589
|
}, t.peerConnection.oniceconnectionstatechange = () => {
|
|
589
590
|
};
|
|
590
591
|
}
|
|
591
|
-
function
|
|
592
|
+
function Ne(e) {
|
|
592
593
|
return new Promise((n, o) => {
|
|
593
594
|
if (t.socket && (t.socket.readyState === WebSocket.CONNECTING || t.socket.readyState === WebSocket.OPEN)) {
|
|
594
595
|
n(t.socket.readyState === WebSocket.OPEN);
|
|
@@ -599,7 +600,7 @@ function Oe(e) {
|
|
|
599
600
|
o(new Error("SDK not initialized. Please initialize SDK first."));
|
|
600
601
|
return;
|
|
601
602
|
}
|
|
602
|
-
const l =
|
|
603
|
+
const l = ke(r.endpoint);
|
|
603
604
|
if (!l) {
|
|
604
605
|
o(
|
|
605
606
|
new Error(
|
|
@@ -608,54 +609,54 @@ function Oe(e) {
|
|
|
608
609
|
);
|
|
609
610
|
return;
|
|
610
611
|
}
|
|
611
|
-
const d =
|
|
612
|
+
const d = O(), c = new URLSearchParams({
|
|
612
613
|
externalId: d
|
|
613
614
|
});
|
|
614
615
|
e.sessionId && c.set("sessionId", e.sessionId), r.token && c.set("token", r.token);
|
|
615
616
|
const u = `${l}?${c.toString()}`;
|
|
616
|
-
t.socket = new WebSocket(u), t.socket.onopen = (
|
|
617
|
-
|
|
618
|
-
}, t.socket.onmessage = (
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
}, t.socket.onerror = (
|
|
622
|
-
w("error"),
|
|
623
|
-
}, t.socket.onclose = (
|
|
624
|
-
|
|
617
|
+
t.socket = new WebSocket(u), t.socket.onopen = (g) => {
|
|
618
|
+
Re(), n(!0);
|
|
619
|
+
}, t.socket.onmessage = (g) => {
|
|
620
|
+
const f = JSON.parse(g.data);
|
|
621
|
+
Me(f);
|
|
622
|
+
}, t.socket.onerror = (g) => {
|
|
623
|
+
w("error"), U(g.message || "Unable to connect voice"), o(g);
|
|
624
|
+
}, t.socket.onclose = (g) => {
|
|
625
|
+
P();
|
|
625
626
|
};
|
|
626
627
|
});
|
|
627
628
|
}
|
|
628
|
-
function
|
|
629
|
+
function Me(e) {
|
|
629
630
|
switch (e.type) {
|
|
630
631
|
case "pong":
|
|
631
|
-
|
|
632
|
+
Ue();
|
|
632
633
|
break;
|
|
633
634
|
case "answer":
|
|
634
|
-
|
|
635
|
+
qe(e.data);
|
|
635
636
|
break;
|
|
636
637
|
case "connected":
|
|
637
|
-
|
|
638
|
+
xe(e.data);
|
|
638
639
|
break;
|
|
639
640
|
case "ice":
|
|
640
|
-
|
|
641
|
+
Le(e.data);
|
|
641
642
|
break;
|
|
642
643
|
case "renegotiationOffer":
|
|
643
|
-
|
|
644
|
+
ze(e.data);
|
|
644
645
|
break;
|
|
645
646
|
case "end":
|
|
646
|
-
|
|
647
|
+
de();
|
|
647
648
|
break;
|
|
648
649
|
case "error":
|
|
649
|
-
w("error"),
|
|
650
|
+
w("error"), U(e.error || "Unable to connect voice");
|
|
650
651
|
break;
|
|
651
652
|
default:
|
|
652
653
|
break;
|
|
653
654
|
}
|
|
654
655
|
}
|
|
655
|
-
function
|
|
656
|
-
t.sessionId = e.sessionId,
|
|
656
|
+
function xe(e) {
|
|
657
|
+
t.sessionId = e.sessionId, be(e.sessionId);
|
|
657
658
|
}
|
|
658
|
-
async function
|
|
659
|
+
async function qe(e) {
|
|
659
660
|
try {
|
|
660
661
|
if (t.peerConnection) {
|
|
661
662
|
const n = new RTCSessionDescription({
|
|
@@ -682,7 +683,7 @@ async function xe(e) {
|
|
|
682
683
|
} catch (n) {
|
|
683
684
|
}
|
|
684
685
|
}
|
|
685
|
-
async function
|
|
686
|
+
async function Le(e) {
|
|
686
687
|
try {
|
|
687
688
|
if (t.peerConnection) {
|
|
688
689
|
if (!t.peerConnection.remoteDescription) {
|
|
@@ -695,7 +696,7 @@ async function qe(e) {
|
|
|
695
696
|
} catch (n) {
|
|
696
697
|
}
|
|
697
698
|
}
|
|
698
|
-
async function
|
|
699
|
+
async function ze(e) {
|
|
699
700
|
try {
|
|
700
701
|
if (t.peerConnection) {
|
|
701
702
|
const n = new RTCSessionDescription({
|
|
@@ -714,13 +715,13 @@ async function Le(e) {
|
|
|
714
715
|
} catch (n) {
|
|
715
716
|
}
|
|
716
717
|
}
|
|
717
|
-
async function
|
|
718
|
+
async function Qe(e = {}) {
|
|
718
719
|
try {
|
|
719
720
|
if (t.callStatus === "connecting" || t.callStatus === "connected")
|
|
720
721
|
return;
|
|
721
|
-
w("connecting"),
|
|
722
|
+
w("connecting"), U(null), t.sessionId = e.sessionId, await Pe(), Oe(), t.localStream.getTracks().forEach((o) => {
|
|
722
723
|
t.peerConnection.addTrack(o, t.localStream);
|
|
723
|
-
}), await
|
|
724
|
+
}), await Ne(e);
|
|
724
725
|
const n = await t.peerConnection.createOffer();
|
|
725
726
|
await t.peerConnection.setLocalDescription(n), T({
|
|
726
727
|
type: "offer",
|
|
@@ -729,15 +730,15 @@ async function Ye(e = {}) {
|
|
|
729
730
|
}
|
|
730
731
|
});
|
|
731
732
|
} catch (n) {
|
|
732
|
-
w("error"),
|
|
733
|
+
w("error"), U(n.message || "Unable to connect voice"), le();
|
|
733
734
|
}
|
|
734
735
|
}
|
|
735
|
-
function
|
|
736
|
+
function de() {
|
|
736
737
|
T({
|
|
737
738
|
type: "end"
|
|
738
|
-
}), t.socket && (t.socket.close(), t.socket = null), w("disconnected"), t.peerConnection && (t.peerConnection.close(), t.peerConnection = null), t.localStream && (t.localStream.getTracks().forEach((e) => e.stop()), t.localStream = null),
|
|
739
|
+
}), t.socket && (t.socket.close(), t.socket = null), w("disconnected"), t.peerConnection && (t.peerConnection.close(), t.peerConnection = null), t.localStream && (t.localStream.getTracks().forEach((e) => e.stop()), t.localStream = null), le();
|
|
739
740
|
}
|
|
740
|
-
function
|
|
741
|
+
function Xe() {
|
|
741
742
|
if (t.localStream) {
|
|
742
743
|
const e = t.localStream.getAudioTracks()[0];
|
|
743
744
|
if (e)
|
|
@@ -745,10 +746,10 @@ function Qe() {
|
|
|
745
746
|
}
|
|
746
747
|
return !1;
|
|
747
748
|
}
|
|
748
|
-
function
|
|
749
|
+
function Ze() {
|
|
749
750
|
return t.localStream;
|
|
750
751
|
}
|
|
751
|
-
function
|
|
752
|
+
function je() {
|
|
752
753
|
return new Promise((e, n) => {
|
|
753
754
|
if (!t.peerConnection) {
|
|
754
755
|
n(new Error("no peer connection"));
|
|
@@ -763,7 +764,7 @@ function Ze() {
|
|
|
763
764
|
});
|
|
764
765
|
});
|
|
765
766
|
}
|
|
766
|
-
function
|
|
767
|
+
function en() {
|
|
767
768
|
return new Promise((e, n) => {
|
|
768
769
|
if (!t.peerConnection) {
|
|
769
770
|
n(new Error("no peer connection"));
|
|
@@ -780,23 +781,23 @@ function je() {
|
|
|
780
781
|
}
|
|
781
782
|
export {
|
|
782
783
|
y as MESSAGE_ROLES,
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
784
|
+
$e as authenticate,
|
|
785
|
+
Ve as deleteAttachment,
|
|
786
|
+
_e as disconnect,
|
|
787
|
+
de as disconnectCall,
|
|
788
|
+
Be as getAttachment,
|
|
789
|
+
Ke as getHistory,
|
|
790
|
+
je as getInboundAudioEnergy,
|
|
791
|
+
Ze as getLocalStream,
|
|
792
|
+
en as getOutboundAudioEnergy,
|
|
793
|
+
De as getSession,
|
|
794
|
+
Je as initialize,
|
|
795
|
+
Te as sendMessage,
|
|
796
|
+
Ye as setCallCallbacks,
|
|
797
|
+
Ge as setCallbacks,
|
|
798
|
+
Qe as startCall,
|
|
799
|
+
We as startChat,
|
|
800
|
+
Xe as toggleMute,
|
|
801
|
+
He as uploadAttachment
|
|
801
802
|
};
|
|
802
803
|
//# sourceMappingURL=origon-chat-sdk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origon-chat-sdk.js","sources":["../src/utils.js","../src/constants.js","../src/socket.js","../src/chat.js","../src/http.js","../src/call.js"],"sourcesContent":["/**\n * Utility functions for the Chat SDK\n */\n\nexport function uuidv7() {\n const timestamp = Date.now()\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n\n // Set timestamp (48 bits)\n bytes[0] = (timestamp >> 40) & 0xff\n bytes[1] = (timestamp >> 32) & 0xff\n bytes[2] = (timestamp >> 24) & 0xff\n bytes[3] = (timestamp >> 16) & 0xff\n bytes[4] = (timestamp >> 8) & 0xff\n bytes[5] = timestamp & 0xff\n\n // Set version 7 (0111)\n bytes[6] = (bytes[6] & 0x0f) | 0x70\n\n // Set variant (10xx)\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(\n 16,\n 20\n )}-${hex.slice(20)}`\n}\n\nexport function getDeviceId() {\n if (localStorage.getItem('chatDeviceId')) {\n return localStorage.getItem('chatDeviceId')\n }\n\n const deviceId = uuidv7()\n localStorage.setItem('chatDeviceId', deviceId)\n return deviceId\n}\n\nexport function parseJwt(token) {\n try {\n const base64Url = token.split('.')[1]\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map(function (c) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)\n })\n .join('')\n )\n\n return JSON.parse(jsonPayload)\n } catch {\n return null\n }\n}\n\nexport async function sleep(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function getSseEndpoint(baseUrl) {\n let sseEndpoint\n try {\n const url = new URL(baseUrl)\n sseEndpoint = `https://${url.hostname}${url.pathname}/sse`\n } catch {\n console.error('SSE Invalid base URL: ', baseUrl)\n }\n return sseEndpoint\n}\n\nexport function getSocketEndpoint(baseUrl) {\n let socketEndpoint\n try {\n const url = new URL(baseUrl)\n socketEndpoint = `wss://${url.hostname}${url.pathname}/wss`\n } catch {\n console.error('Socket Invalid base URL: ', baseUrl)\n }\n return socketEndpoint\n}\n\nexport function getCallServerEndpoint(baseUrl) {\n let socketEndpoint\n try {\n const url = new URL(baseUrl)\n socketEndpoint = `wss://${url.hostname}${url.pathname}/audio`\n } catch {\n console.error('getCallServerEndpoint: Invalid base URL: ', baseUrl)\n }\n return socketEndpoint\n}\n","/**\n * Constants for the Chat SDK\n */\n\nexport const MESSAGE_ROLES = {\n ASSISTANT: 'assistant', // this can be automated or LLM AI Agent response\n USER: 'user', // this is widget user\n SUPERVISOR: 'supervisor', // this is human supervisor (ex. Samespace Dock agent, or Resolve human agent)\n SYSTEM: 'system' // this is system message, for ex \"Agent joined\" / \"Agent left\"\n}\n","/**\n * Socket Service for Chat SDK\n * Handles WebSocket connection for real-time chat functionality\n */\n\nimport { getSocketEndpoint, uuidv7 } from './utils.js'\nimport {\n getCredentials,\n getExternalId,\n addMessage,\n toggleTypingStatus,\n setTransport\n} from './chat.js'\n\nconst PING_INTERVAL = 10000\nconst SOCKET_TIMEOUT = 5000\n\n/**\n * @typedef {Object} SocketSession\n * @property {WebSocket} [socket]\n * @property {boolean} previouslyConnected\n * @property {boolean} socketDisconnected\n * @property {NodeJS.Timeout} [pingInterval]\n * @property {NodeJS.Timeout} [socketDisconnectedTimeout]\n * @property {NodeJS.Timeout} [socketConnectionTimeout]\n */\n\n/**\n * Socket Events\n */\nexport const SocketEvents = {\n MESSAGE: 'message',\n TYPING: 'typing',\n TYPING_STOP: 'typingOff',\n END: 'end'\n}\n\n/**\n * Create a new socket session\n * @returns {SocketSession}\n */\nfunction createSession() {\n return {\n socket: null,\n previouslyConnected: false,\n socketDisconnected: false,\n pingInterval: null,\n socketDisconnectedTimeout: null,\n socketConnectionTimeout: null\n }\n}\n\n/** @type {SocketSession} */\nlet currentSession = createSession()\n\n/**\n * Stop ping interval\n */\nfunction stopPingInterval() {\n if (currentSession.pingInterval) {\n clearInterval(currentSession.pingInterval)\n currentSession.pingInterval = null\n }\n}\n\n/**\n * Start ping interval\n */\nfunction startPingInterval() {\n stopPingInterval()\n\n currentSession.pingInterval = setInterval(() => {\n if (currentSession.socket && currentSession.socket.readyState === WebSocket.OPEN) {\n send({ type: 'ping' })\n console.log('Sending keep-alive ping')\n } else {\n console.log('Socket not open, stopping ping interval')\n stopPingInterval()\n }\n }, PING_INTERVAL)\n}\n\n/**\n * Clear all timeouts\n */\nfunction clearAllTimeouts() {\n stopPingInterval()\n if (currentSession.socketDisconnectedTimeout) {\n clearTimeout(currentSession.socketDisconnectedTimeout)\n currentSession.socketDisconnectedTimeout = null\n }\n if (currentSession.socketConnectionTimeout) {\n clearTimeout(currentSession.socketConnectionTimeout)\n currentSession.socketConnectionTimeout = null\n }\n}\n\n/**\n * Handle socket connected state\n */\nfunction handleSocketConnected() {\n console.log('handleSocketConnected')\n currentSession.socketDisconnected = false\n setTransport('socket')\n}\n\n/**\n * Handle socket disconnected state\n */\nfunction handleSocketDisconnected() {\n console.log('handleSocketDisconnected')\n currentSession.socketDisconnected = true\n setTransport('sse')\n}\n\n/**\n * Connect to socket\n * @param {{ token: string, sessionId?: string }} payload\n * @returns {Promise<boolean>}\n */\nexport function connectSocket(payload) {\n return new Promise((fulfill, reject) => {\n if (\n currentSession.socket &&\n (currentSession.socket.readyState === WebSocket.CONNECTING ||\n currentSession.socket.readyState === WebSocket.OPEN)\n ) {\n console.log('Socket in connecting/open state, returning.')\n fulfill(currentSession.socket.readyState === WebSocket.OPEN)\n return\n }\n\n console.log('Initializing socket connection..')\n const credentials = getCredentials()\n if (!credentials || !credentials.endpoint) {\n reject(new Error('SDK not initialized. Please initialize SDK first.'))\n return\n }\n\n const socketEndpoint = getSocketEndpoint(credentials.endpoint)\n if (!socketEndpoint) {\n reject(\n new Error(\n 'Invalid endpoint while initializing SDK. Please check the endpoint and try again.'\n )\n )\n return\n }\n\n const externalId = getExternalId()\n const queryParams = new URLSearchParams({\n externalId\n })\n\n if (payload.sessionId) {\n queryParams.set('sessionId', payload.sessionId)\n }\n if (payload.requestId) {\n queryParams.set('requestId', payload.requestId)\n }\n if (credentials.token) {\n queryParams.set('token', credentials.token)\n }\n\n const socketUrl = `${socketEndpoint}?${queryParams.toString()}`\n currentSession.socket = new WebSocket(socketUrl)\n\n currentSession.socket.onopen = () => {\n console.log('-------- socket connected --------')\n currentSession.previouslyConnected = true\n handleSocketConnected()\n send({ type: 'ping' })\n clearTimeout(currentSession.socketConnectionTimeout)\n startPingInterval()\n fulfill(true)\n }\n\n currentSession.socket.onmessage = (event) => {\n const message = JSON.parse(event.data)\n handleSocketEvent(message)\n }\n\n currentSession.socket.onerror = (error) => {\n console.error('Socket error:', error)\n setTransport('sse')\n reject(error)\n }\n\n currentSession.socket.onclose = (ws) => {\n console.log('-------- socket disconnected --------: ', ws.code, ws.reason)\n\n if (ws.target === currentSession.socket) {\n if (ws.code === 1006) {\n // abnormal closure\n if (currentSession.previouslyConnected) {\n handleSocketDisconnected()\n } else {\n addMessage({\n errorText: 'Unable to establish connection',\n done: true,\n timestamp: new Date().toISOString()\n })\n }\n clearTimeout(currentSession.socketConnectionTimeout)\n }\n\n currentSession.socket = null\n clearAllTimeouts()\n }\n }\n\n if (!currentSession.previouslyConnected) {\n currentSession.socketConnectionTimeout = setTimeout(() => {\n console.error('Socket connection timed out')\n addMessage({\n errorText: 'Unable to establish connection',\n done: true,\n timestamp: new Date().toISOString()\n })\n reject(new Error('Socket connection timed out'))\n }, SOCKET_TIMEOUT)\n }\n })\n}\n\n/**\n * Send data through socket\n * @param {Object} data\n */\nexport function send(data) {\n console.log('sending socket event: ', data.type)\n if (currentSession.socketDisconnected || !currentSession.socket) {\n return\n }\n currentSession.socket.send(JSON.stringify({ ...data, eventId: data.eventId || uuidv7() }))\n}\n\n/**\n * Send data through socket and wait for acknowledgment\n * @param {Object} data\n * @returns {Promise<Object>}\n */\nexport function sendWithAck(data) {\n return new Promise((resolve, reject) => {\n if (!currentSession.socket) {\n console.error('sendWithAck: socket instance not found or not connected')\n reject(new Error('Socket instance not found or not connected'))\n return\n }\n\n const autoRejectTimeout = setTimeout(() => {\n reject(new Error('Timeout'))\n }, 5000)\n\n const eventId = data.eventId || uuidv7()\n\n const onMessage = (event) => {\n const eventData = JSON.parse(event.data)\n if (eventData.eventId === eventId) {\n clearTimeout(autoRejectTimeout)\n currentSession.socket.removeEventListener('message', onMessage)\n if (eventData.data) {\n resolve(eventData.data)\n } else {\n reject(new Error(eventData.error?.message ?? 'Unknown error'))\n }\n }\n }\n currentSession.socket.addEventListener('message', onMessage)\n currentSession.socket.send(JSON.stringify({ ...data, eventId }))\n })\n}\n\n/**\n * Handle socket event\n * @param {Object} event\n */\nfunction handleSocketEvent(event) {\n console.log('received socket event: ', event.type)\n\n switch (event.type) {\n case 'pong': {\n if (currentSession.socketDisconnected) {\n handleSocketConnected()\n }\n if (currentSession.socketDisconnectedTimeout) {\n clearTimeout(currentSession.socketDisconnectedTimeout)\n }\n currentSession.socketDisconnectedTimeout = setTimeout(() => {\n console.log('---- socket ping timeout ----')\n handleSocketDisconnected()\n }, PING_INTERVAL + 1000)\n break\n }\n case SocketEvents.TYPING: {\n toggleTypingStatus(true)\n break\n }\n case SocketEvents.TYPING_STOP: {\n toggleTypingStatus(false)\n break\n }\n case SocketEvents.MESSAGE: {\n const { eventId, data } = event\n if (!eventId) {\n addMessage({\n ...data,\n done: true,\n timestamp: new Date().toISOString()\n })\n }\n break\n }\n case SocketEvents.END: {\n disconnect()\n break\n }\n default:\n break\n }\n}\n\n/**\n * Reconnect to socket\n */\nexport function reconnect() {\n if (currentSession.socket) {\n send({ type: 'ping' })\n }\n}\n\n/**\n * Disconnect socket\n */\nexport function disconnect() {\n console.log('Disconnecting socket')\n if (currentSession.socket) {\n currentSession.socket.close(1000)\n }\n currentSession.previouslyConnected = false\n clearAllTimeouts()\n currentSession.socket = null\n setTransport('sse')\n}\n\n/**\n * Check if socket is connected\n * @returns {boolean}\n */\nexport function isConnected() {\n return (\n currentSession.socket !== null &&\n currentSession.socket.readyState === WebSocket.OPEN &&\n !currentSession.socketDisconnected\n )\n}\n\n/**\n * Check if socket is disconnected\n * @returns {boolean}\n */\nexport function isDisconnected() {\n return currentSession.socketDisconnected\n}\n","/**\n * Chat Service for Chat SDK\n * Handles real-time chat functionality without depending on external state\n * Uses callbacks to communicate state changes to the consumer\n */\n\nimport { fetchEventSource } from '@microsoft/fetch-event-source'\nimport { getSession, authenticate } from './http.js'\nimport { getDeviceId, getSseEndpoint, sleep } from './utils.js'\nimport { MESSAGE_ROLES } from './constants.js'\nimport {\n connectSocket,\n send as socketSend,\n disconnect as disconnectSocket,\n isConnected as isSocketConnected\n} from './socket.js'\n\n/**\n * @typedef {Object} ChatCallbacks\n * @property {(message: Object) => void} [onMessageAdd] - Called when a new message is added\n * @property {(index: number, updatedMsg: Object) => void} [onMessageUpdate] - Called when an existing message is updated\n * @property {(sessionId: string) => void} [onSessionUpdate] - Called when session ID is updated\n * @property {(transport: TransportType) => void} [onTransportUpdate] - Called when transport type changes\n * @property {(control: 'agent' | 'human') => void} [onControlUpdate] - Called when control changes between agent and human\n */\n\n/**\n * @typedef {'sse' | 'socket'} TransportType\n */\n\n/**\n * @typedef {Object} ChatSession\n * @property {string} sessionId\n * @property {string} sseUrl\n * @property {string} [requestId]\n * @property {AbortController} [abortController]\n * @property {string} [lastStreamId]\n * @property {Array} messages\n * @property {ChatCallbacks} callbacks\n * @property {TransportType} transport\n */\n\n/**\n * Create a new chat session\n * @param {ChatCallbacks} [callbacks={}]\n * @returns {ChatSession}\n */\nfunction createSession(callbacks = {}) {\n return {\n credentials: undefined,\n authenticated: false,\n configData: undefined,\n sessionId: undefined,\n requestId: undefined,\n sseUrl: undefined,\n abortController: undefined,\n lastStreamId: undefined,\n messages: [],\n callbacks,\n transport: 'sse',\n control: 'agent'\n }\n}\n\n/** @type {ChatSession} */\nlet currentSession = createSession()\n\n/**\n * Set callbacks for the current session\n * @param {ChatCallbacks} callbacks\n */\nexport function setCallbacks(callbacks) {\n currentSession.callbacks = { ...currentSession.callbacks, ...callbacks }\n}\n\n/**\n * Initialize the chat session\n * @param {Object} credentials - Credentials for the chat\n */\nexport function initialize(credentials) {\n console.log('Initializing chat...', credentials)\n currentSession.credentials = credentials\n if (credentials.token) {\n currentSession.authenticated = true\n }\n}\n\n/**\n * Get current chat session credentials\n * @returns {{ endpoint: string, apiKey: string } | undefined}\n */\nexport function getCredentials() {\n return currentSession.credentials\n}\n\n/**\n * Update the session ID and notify via callback\n * @param {string} sessionId - The new session ID\n */\nexport function updateSessionId(sessionId) {\n if (sessionId && sessionId !== currentSession.sessionId) {\n currentSession.sessionId = sessionId\n currentSession.callbacks.onSessionUpdate?.(sessionId)\n }\n}\n\n/**\n * Initiate a new chat session or resume an existing one\n * @param {Object} credentials - Credentials for the chat\n * @param {Object} payload - Payload for the chat. It contains sessionId (optional)\n * @param {string} [payload.sessionId] - Optional session ID to resume\n * @returns {Promise<{ sessionId: string, messages: Array }>}\n */\nexport async function startChat(payload = {}) {\n try {\n console.log('startChat: ', payload, currentSession)\n\n let configData = null\n if (!currentSession.authenticated) {\n configData = await authenticate(currentSession.credentials)\n currentSession.authenticated = true\n currentSession.configData = configData\n } else {\n configData = currentSession.configData\n }\n\n let messages = []\n let control = 'agent'\n\n if (payload.sessionId) {\n const session = await getSession(payload.sessionId)\n messages = session.messages\n control = session.control || 'agent'\n }\n\n const searchParams = new URLSearchParams()\n if (!currentSession.credentials.token) {\n searchParams.set('externalId', getExternalId()) // externalId is needed only for public urls, not for internal chat (where token is provided)\n }\n currentSession.sseUrl = `${getSseEndpoint(\n currentSession.credentials.endpoint\n )}?${searchParams.toString()}`\n currentSession.sessionId = payload.sessionId\n currentSession.messages = messages\n currentSession.control = control\n\n if (control === 'human') {\n // Connect to SSE for incoming messages when control is human\n sendMessage({ text: '', html: '' }).catch(() => {})\n }\n\n console.log('Chat initiated successfully')\n\n return {\n sessionId: currentSession.sessionId,\n messages,\n control,\n configData\n }\n } catch (error) {\n console.error(`Failed to start chat: ${error.message}`)\n cleanup()\n throw error\n }\n}\n\n/**\n * Disconnect from the current chat session\n */\nexport function disconnect() {\n cleanup()\n}\n\n/**\n * Clean up the current session\n */\nfunction cleanup() {\n if (currentSession.abortController) {\n currentSession.abortController.abort()\n }\n disconnectSocket()\n\n const { callbacks, credentials } = currentSession\n currentSession = createSession(callbacks)\n currentSession.credentials = credentials\n\n console.log('Chat session cleaned up')\n}\n\nexport function getExternalId() {\n if (currentSession.credentials?.externalId) {\n return currentSession.credentials.externalId\n }\n return getDeviceId()\n}\n\n/**\n * Add a message to the chat\n * @param {Object} message - The message object to add\n */\nexport function addMessage(message) {\n currentSession.messages = [...currentSession.messages, message]\n currentSession.callbacks.onMessageAdd?.(message)\n}\n\nexport function toggleTypingStatus(isTyping) {\n currentSession.callbacks.onTyping?.(isTyping)\n}\n\n/**\n * Set the transport type\n * @param {TransportType} transport\n */\nexport function setTransport(transport) {\n console.log('Setting transport to:', transport)\n currentSession.transport = transport\n currentSession.callbacks.onTransportUpdate?.(transport)\n}\n\n/**\n * Get current transport type\n * @returns {TransportType}\n */\nexport function getTransport() {\n return currentSession.transport\n}\n\n/**\n * Send a message in the current chat session\n * @param {{ text: string, html?: string }} message\n * @returns {Promise<string>}\n */\nexport function sendMessage({ text, html, context, attachments }) {\n return new Promise((resolve, reject) => {\n ;(async () => {\n try {\n const isEmpty = !text && !html && !attachments?.length\n\n // Add user message only if there's content\n if (!isEmpty) {\n const userMessage = {\n role: MESSAGE_ROLES.USER,\n text,\n html,\n timestamp: new Date().toISOString(),\n attachments\n }\n addMessage(userMessage)\n await sleep(200)\n }\n\n // If transport is socket and socket is connected, use socket\n if (currentSession.transport === 'socket' && isSocketConnected()) {\n socketSend({\n type: 'message',\n data: {\n text,\n html\n }\n })\n resolve(currentSession.sessionId)\n return\n }\n\n if (currentSession.control === 'agent') {\n const loadingMessage = {\n role: MESSAGE_ROLES.ASSISTANT,\n text: '',\n loading: true\n }\n addMessage(loadingMessage)\n }\n\n const url = new URL(currentSession.sseUrl)\n if (currentSession.sessionId) {\n url.searchParams.set('sessionId', currentSession.sessionId)\n }\n if (currentSession.requestId) {\n url.searchParams.set('requestId', currentSession.requestId)\n }\n\n currentSession.lastStreamId = undefined\n\n // Create a new abort controller for this request\n currentSession.abortController = new AbortController()\n\n const headers = {\n 'Content-Type': 'application/json'\n }\n if (currentSession.credentials?.token) {\n headers.Authorization = `Bearer ${currentSession.credentials.token}`\n }\n\n await fetchEventSource(url.toString(), {\n method: 'POST',\n headers,\n body: isEmpty\n ? undefined\n : JSON.stringify({\n message: text,\n html,\n context,\n attachments\n }),\n signal: currentSession.abortController.signal,\n openWhenHidden: true,\n onopen: async (response) => {\n if (!response.ok) {\n console.error('Failed to send message bad response: ', response)\n throw new Error('Failed to send message')\n }\n },\n onmessage: (response) => {\n // console.log('Event: ', response)\n const data = JSON.parse(response.data)\n\n if (response.event === 'connected') {\n currentSession.sessionId = data.sessionId\n currentSession.requestId = data.requestId\n console.log('Connected: ', data)\n if (data.control) {\n currentSession.control = data.control\n currentSession.callbacks.onControlUpdate?.(data.control)\n }\n } else if (response.event === 'upgrade_to_websocket') {\n console.log('Upgrade to websocket: ', data)\n connectSocket({\n sessionId: currentSession.sessionId,\n requestId: data.requestId\n })\n } else if (response.event === 'update') {\n if (data.control) {\n currentSession.control = data.control\n currentSession.callbacks.onControlUpdate?.(data.control)\n }\n } else if (data.error) {\n const errorMessage =\n data.error && typeof data.error === 'string'\n ? data.error\n : 'Failed to connect to the system'\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n errorText: errorMessage\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n reject(new Error(errorMessage))\n } else if (response.event === 'done') {\n console.log('Done: ', data)\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n done: true\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n resolve(currentSession.sessionId)\n } else if (data.message !== undefined || data.attachments?.length > 0) {\n // If role is supervisor, treat it as a new message\n if (data.role === MESSAGE_ROLES.SUPERVISOR) {\n const supervisorMessage = {\n role: MESSAGE_ROLES.SUPERVISOR,\n text: data.message,\n attachments: data.attachments,\n sources: data.sources,\n done: true\n }\n addMessage(supervisorMessage)\n resolve(currentSession.sessionId)\n\n // Store session info for reuse\n currentSession.sessionId = data.sessionId ?? currentSession.sessionId\n currentSession.requestId = data.requestId ?? currentSession.requestId\n return\n }\n\n // If streamId changes, start a new assistant message\n if (data.streamId !== undefined) {\n if (currentSession.lastStreamId === undefined) {\n currentSession.lastStreamId = data.streamId\n } else if (data.streamId !== currentSession.lastStreamId) {\n currentSession.lastStreamId = data.streamId\n const newBotMessage = {\n role: MESSAGE_ROLES.ASSISTANT,\n text: '',\n loading: true\n }\n addMessage(newBotMessage)\n }\n }\n\n // Update the last message with new content\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n text: (lastMsg.text || '') + data.message,\n sources: data.sources,\n attachments: data.attachments,\n done: data.done ?? lastMsg.done\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n\n // Store session info for reuse\n currentSession.sessionId = data.sessionId ?? currentSession.sessionId\n currentSession.requestId = data.requestId ?? currentSession.requestId\n }\n },\n onerror: (error) => {\n throw error // Rethrow to stop retries\n },\n openWhenHidden: true\n })\n } catch (error) {\n console.error('Failed to send message: ', error)\n const errorMessage = 'Failed to connect to the system'\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n errorText: lastMsg.done ? undefined : error.message || errorMessage,\n done: true\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n reject(error)\n }\n })()\n })\n}\n","/**\n * API Service for Chat SDK\n * Handles all HTTP requests without depending on external state\n */\n\nimport { getCredentials, getExternalId } from './chat.js'\nimport { MESSAGE_ROLES } from './constants.js'\n\nconst AUTHENTICATION_ERROR = 'Something went wrong initializing the chat'\nconst INITIALIZATION_ERROR = 'Chat SDK not initialized'\n\n/**\n * Authenticate with the chat service\n * @param {{ endpoint: string }} credentials\n * @returns {Promise<object>} Authentication response data\n */\nexport async function authenticate(payload) {\n const { endpoint } = payload\n const url = `${endpoint}/config`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n\n if (!response.ok) {\n const errorPayload = await response.json()\n throw new Error(errorPayload?.error || AUTHENTICATION_ERROR)\n }\n\n const res = await response.json()\n const data = res.data\n\n return data\n}\n\n/**\n * Get chat history for the current device\n * @returns {Promise<{ sessions: Array }>}\n */\nexport async function getHistory() {\n const queryParams = new URLSearchParams({\n externalId: getExternalId()\n })\n const response = await fetchRequest(`/sessions?${queryParams.toString()}`, 'GET')\n\n if (!response.ok) {\n throw new Error('Unable to load history, please try again later')\n }\n\n return response.json()\n}\n\n/**\n * Get session data (control and history) for a specific session\n * @param {string} sessionId\n * @returns {Promise<{ control: string, messages: Array }>}\n */\nexport async function getSession(sessionId) {\n const queryParams = new URLSearchParams({\n sessionId\n })\n const response = await fetchRequest(`/session?${queryParams.toString()}`, 'GET')\n\n if (!response.ok) {\n throw new Error('Unable to load messages, please try again later')\n }\n\n const data = await response.json()\n const control = data?.control\n const messages = (data?.history ?? []).map((msg) => ({\n id: msg.id,\n text: msg.text,\n role: msg.youtubeVideo\n ? MESSAGE_ROLES.ASSISTANT // for youtube video messages, role is \"system\" from backend, we need to make it \"assistant\"\n : msg.role,\n timestamp: msg.timestamp,\n video: msg.youtubeVideo,\n attachments: msg.attachments,\n channel: msg.channel,\n done: true\n }))\n\n return { control, messages }\n}\n\n/**\n * Upload attachment with progress tracking\n * @param {File} file\n * @param {Function} onProgress - callback (percentComplete, loaded, total)\n * @param {Function} onComplete - callback (error, response)\n * @returns {XMLHttpRequest} xhr object to allow abort\n */\nexport function uploadAttachment(file, onProgress, onComplete) {\n const credentials = getCredentials()\n const { endpoint, token } = credentials || {}\n\n if (!endpoint) {\n const error = new Error(INITIALIZATION_ERROR)\n if (onComplete) {\n onComplete(error, null)\n }\n return null\n }\n\n const xhr = new XMLHttpRequest()\n const formData = new FormData()\n formData.append('file', file)\n\n const uploadUrl = `${endpoint}/upload`\n\n xhr.open('POST', uploadUrl)\n if (token) {\n xhr.setRequestHeader('Authorization', `Bearer ${token}`)\n }\n\n // Upload progress callback\n if (onProgress) {\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable) {\n const percentComplete = (event.loaded / event.total) * 100\n onProgress(percentComplete, event.loaded, event.total)\n }\n })\n }\n\n // Upload complete callback\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText)\n if (onComplete) {\n onComplete(null, response)\n }\n } catch (error) {\n if (onComplete) {\n onComplete(new Error('Failed to parse response'), null)\n }\n }\n } else {\n if (onComplete) {\n onComplete(new Error(`Upload failed with status ${xhr.status}`), null)\n }\n }\n })\n\n xhr.addEventListener('error', () => {\n if (onComplete) {\n onComplete(new Error('Network error during upload'), null)\n }\n })\n\n xhr.addEventListener('abort', () => {\n if (onComplete) {\n onComplete(new Error('Upload aborted'), null)\n }\n })\n\n xhr.send(formData)\n\n return xhr\n}\n\n/**\n * Delete attachment by mediaId\n * @param {string} mediaId\n * @returns {Promise<{ success: boolean }>}\n */\nexport async function deleteAttachment(mediaId) {\n const credentials = getCredentials()\n const { endpoint, token } = credentials || {}\n\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n const deleteUrl = `${endpoint}/delete/${mediaId}`\n\n const headers = {}\n if (token) {\n headers.Authorization = `Bearer ${token}`\n }\n\n const response = await fetch(deleteUrl, {\n method: 'DELETE',\n headers\n })\n\n if (!response.ok) {\n throw new Error(`Delete failed with status ${response.status}`)\n }\n\n return { success: true }\n}\n\n/**\n * Get attachment URL by mediaId\n * @param {string} mediaId\n * @returns {string} Full URL to the attachment\n */\nexport function getAttachment(mediaId) {\n const credentials = getCredentials()\n const { endpoint } = credentials || {}\n\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n return `${endpoint}/upload/${mediaId}`\n}\n\n/**\n * Internal fetch request helper\n * @param {string} pathname\n * @param {string} method\n * @param {object|null} body\n * @returns {Promise<Response>}\n */\nasync function fetchRequest(pathname, method = 'GET', body = null) {\n const credentials = getCredentials()\n\n const { endpoint, token } = credentials || {}\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n const url = `${endpoint}${pathname}`\n\n const headers = {\n 'Content-Type': 'application/json'\n }\n if (token) {\n headers.Authorization = `Bearer ${token}`\n }\n\n return fetch(url, {\n headers,\n method,\n body: body ? JSON.stringify(body) : null\n })\n}\n","/**\n * Socket Service for Call SDK\n * Handles WebRTC call functionality without depending on external state\n * Uses callbacks to communicate state changes to the consumer\n */\n\nimport { getCallServerEndpoint } from './utils.js'\nimport { getCredentials, getExternalId, updateSessionId } from './chat.js'\n\n/**\n * @typedef {Object} CallCallbacks\n * @property {(status: string) => void} [onCallStatus] - Called when call status changes\n * @property {(error: string | null) => void} [onCallError] - Called when call error occurs\n */\n\n/**\n * @typedef {Object} CallSession\n * @property {string} [sessionId]\n * @property {WebSocket} [socket]\n * @property {RTCPeerConnection} [peerConnection]\n * @property {MediaStream} [localStream]\n * @property {MediaStream} [remoteStream]\n * @property {HTMLAudioElement} [remoteAudio]\n * @property {boolean} isMuted\n * @property {string} callStatus\n * @property {NodeJS.Timeout} [pingInterval]\n * @property {number} pingCount\n * @property {number | null} lastPongTime\n * @property {CallCallbacks} callbacks\n * @property {string[]} localIceCandidates - Queued local ICE candidates to send after remote description is set\n * @property {string[]} pendingRemoteIceCandidates - Queued remote ICE candidates to add after remote description is set\n */\n\n/**\n * Create a new call session\n * @param {CallCallbacks} [callbacks={}]\n * @returns {CallSession}\n */\nfunction createSession(callbacks = {}) {\n return {\n sessionId: undefined,\n socket: null,\n peerConnection: null,\n localStream: null,\n remoteStream: null,\n remoteAudio: null,\n isMuted: false,\n callStatus: 'disconnected',\n pingInterval: null,\n pingCount: 0,\n lastPongTime: null,\n callbacks,\n localIceCandidates: [],\n pendingRemoteIceCandidates: []\n }\n}\n\n/** @type {CallSession} */\nlet currentSession = createSession()\n\nconst rtcConfig = {\n iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun1.l.google.com:19302' }]\n}\n\n/**\n * Set callbacks for the current session\n * @param {CallCallbacks} callbacks\n */\nexport function setCallCallbacks(callbacks) {\n currentSession.callbacks = { ...currentSession.callbacks, ...callbacks }\n}\n\n/**\n * Clean up the current session\n */\nfunction cleanup() {\n if (currentSession.peerConnection) {\n currentSession.peerConnection.close()\n currentSession.peerConnection = null\n }\n\n if (currentSession.localStream) {\n currentSession.localStream.getTracks().forEach((track) => track.stop())\n currentSession.localStream = null\n }\n\n if (currentSession.remoteStream) {\n currentSession.remoteStream = null\n }\n\n if (currentSession.remoteAudio) {\n currentSession.remoteAudio.srcObject = null\n if (currentSession.remoteAudio.parentNode) {\n currentSession.remoteAudio.parentNode.removeChild(currentSession.remoteAudio)\n }\n currentSession.remoteAudio = null\n }\n\n if (currentSession.socket) {\n currentSession.socket.close()\n currentSession.socket = null\n }\n\n stopPingInterval()\n\n const callbacks = currentSession.callbacks\n currentSession = createSession(callbacks)\n\n console.log('Call session cleaned up')\n}\n\n/**\n * Update call status and notify callback\n * @param {string} status\n */\nfunction setCallStatus(status) {\n currentSession.callStatus = status\n currentSession.callbacks.onCallStatus?.(status)\n}\n\n/**\n * Update call error and notify callback\n * @param {string | null} error\n */\nfunction setCallError(error) {\n currentSession.callbacks.onCallError?.(error)\n}\n\n/**\n * Stop ping interval\n */\nfunction stopPingInterval() {\n if (currentSession.pingInterval) {\n clearInterval(currentSession.pingInterval)\n currentSession.pingInterval = null\n }\n}\n\n/**\n * Start ping interval\n */\nfunction startPingInterval() {\n stopPingInterval()\n\n currentSession.pingInterval = setInterval(() => {\n if (currentSession.socket && currentSession.socket.readyState === WebSocket.OPEN) {\n currentSession.pingCount++\n const pingMessage = {\n type: 'ping',\n timestamp: Date.now(),\n count: currentSession.pingCount\n }\n sendEvent(pingMessage)\n console.log(`Sending keep-alive ping #${currentSession.pingCount}`)\n } else {\n console.log('Socket not open, stopping ping interval')\n stopPingInterval()\n }\n }, 10000)\n}\n\n/**\n * Handle pong response\n */\nfunction handlePong() {\n currentSession.lastPongTime = Date.now()\n console.log(`Received pong #${currentSession.pingCount}`)\n}\n\n/**\n * Send event through socket\n * @param {Object} payload\n */\nfunction sendEvent(payload) {\n if (!currentSession.socket) {\n console.error('Failed to send event: no socket instance')\n return\n }\n if (currentSession.socket.readyState !== WebSocket.OPEN) {\n console.error('Failed to send event: socket state not open ', payload)\n return\n }\n\n currentSession.socket.send(JSON.stringify(payload))\n}\n\n/**\n * Get user media\n */\nasync function getUserMedia() {\n try {\n currentSession.localStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n video: false\n })\n console.log('Got audio media')\n } catch (error) {\n console.error(`Failed to get audio media: ${error.message}`)\n throw error\n }\n}\n\n/**\n * Create peer connection\n */\nfunction createPeerConnection() {\n currentSession.peerConnection = new RTCPeerConnection(rtcConfig)\n\n currentSession.peerConnection.onicecandidate = (event) => {\n if (event.candidate) {\n const candidateJson = JSON.stringify(event.candidate)\n // Queue local ICE candidates until remote description is set\n if (currentSession.peerConnection && currentSession.peerConnection.remoteDescription) {\n sendEvent({\n type: 'ice',\n data: {\n candidate: candidateJson\n }\n })\n console.log('Sent ICE candidate immediately')\n } else {\n currentSession.localIceCandidates.push(candidateJson)\n console.log('Queued local ICE candidate')\n }\n }\n }\n\n currentSession.peerConnection.ontrack = (event) => {\n console.log('Received remote audio stream')\n currentSession.remoteStream = event.streams[0]\n\n if (!currentSession.remoteAudio) {\n currentSession.remoteAudio = document.createElement('audio')\n currentSession.remoteAudio.autoplay = true\n currentSession.remoteAudio.controls = false\n document.body.appendChild(currentSession.remoteAudio)\n }\n currentSession.remoteAudio.srcObject = currentSession.remoteStream\n // explicitly kick off playback and catch any policy/gesture errors\n currentSession.remoteAudio\n .play()\n .then(() => console.log('🔊 remote audio playing'))\n .catch((err) => console.error('❌ playback error:', err))\n }\n\n currentSession.peerConnection.onconnectionstatechange = () => {\n const newState = currentSession.peerConnection.connectionState\n console.log(`Connection state: ${newState}`)\n\n if (newState === 'connected') {\n setCallStatus('connected')\n } else if (newState === 'disconnected' || newState === 'closed') {\n setCallStatus('disconnected')\n disconnectCall()\n }\n }\n\n currentSession.peerConnection.oniceconnectionstatechange = () => {\n console.log(`ICE connection state: ${currentSession.peerConnection.iceConnectionState}`)\n }\n}\n\n/**\n * Connect socket\n * @param {{ sessionId?: string }} payload\n */\nfunction connectSocket(payload) {\n return new Promise((fulfill, reject) => {\n if (\n currentSession.socket &&\n (currentSession.socket.readyState === WebSocket.CONNECTING ||\n currentSession.socket.readyState === WebSocket.OPEN)\n ) {\n console.log('Socket in connecting/open state, returning.')\n fulfill(currentSession.socket.readyState === WebSocket.OPEN)\n return\n }\n\n console.log('Initializing socket connection..')\n const credentials = getCredentials()\n if (!credentials || !credentials.endpoint) {\n reject(new Error('SDK not initialized. Please initialize SDK first.'))\n return\n }\n\n // Extract hostname from endpoint\n const socketEndpoint = getCallServerEndpoint(credentials.endpoint)\n if (!socketEndpoint) {\n reject(\n new Error(\n 'Invalid endpoint while initializing SDK. Please check the endpoint and try again.'\n )\n )\n return\n }\n\n const externalId = getExternalId()\n const queryParams = new URLSearchParams({\n externalId\n })\n if (payload.sessionId) {\n queryParams.set('sessionId', payload.sessionId)\n }\n if (credentials.token) {\n queryParams.set('token', credentials.token)\n }\n\n const socketUrl = `${socketEndpoint}?${queryParams.toString()}`\n currentSession.socket = new WebSocket(socketUrl)\n\n currentSession.socket.onopen = (event) => {\n console.log('Socket connection established: ', event)\n startPingInterval()\n fulfill(true)\n }\n\n currentSession.socket.onmessage = (event) => {\n const data = JSON.parse(event.data)\n handleCallServerEvent(data)\n }\n\n currentSession.socket.onerror = (error) => {\n console.error('Socket error: ', error)\n setCallStatus('error')\n setCallError(error.message || 'Unable to connect voice')\n reject(error)\n }\n\n currentSession.socket.onclose = (event) => {\n console.log('Socket connection closed: ', event)\n stopPingInterval()\n }\n })\n}\n\n/**\n * Handle call server event\n * @param {Object} action\n */\nfunction handleCallServerEvent(action) {\n console.log('Handling socket server event: ', action)\n\n switch (action.type) {\n case 'pong':\n handlePong()\n break\n\n case 'answer':\n handleAnswer(action.data)\n break\n\n case 'connected':\n handleConnected(action.data)\n break\n\n case 'ice':\n handleIceCandidate(action.data)\n break\n\n case 'renegotiationOffer':\n handleRenegotiationOffer(action.data)\n break\n case 'end':\n disconnectCall()\n break\n case 'error':\n setCallStatus('error')\n setCallError(action.error || 'Unable to connect voice')\n break\n\n default:\n console.log('Unknown call event type: ', action.type)\n break\n }\n}\n\n/**\n * Handle connected event\n * @param {Object} data\n */\nfunction handleConnected(data) {\n console.log('Received connected event')\n currentSession.sessionId = data.sessionId\n // Update chat session with the new sessionId and notify controller\n updateSessionId(data.sessionId)\n}\n\n/**\n * Handle answer\n * @param {Object} data\n */\nasync function handleAnswer(data) {\n try {\n console.log('Received answer')\n\n if (currentSession.peerConnection) {\n const answer = new RTCSessionDescription({\n type: 'answer',\n sdp: data.sdp\n })\n console.log('Setting remote description answer: ', answer)\n await currentSession.peerConnection.setRemoteDescription(answer)\n console.log('Remote description set')\n\n // Send all queued local ICE candidates\n for (const candidateJson of currentSession.localIceCandidates) {\n sendEvent({\n type: 'ice',\n data: {\n candidate: candidateJson\n }\n })\n console.log('Sent queued local ICE candidate')\n }\n currentSession.localIceCandidates = []\n\n // Process any pending remote ICE candidates\n for (const candidateJson of currentSession.pendingRemoteIceCandidates) {\n try {\n const candidate = new RTCIceCandidate(JSON.parse(candidateJson))\n await currentSession.peerConnection.addIceCandidate(candidate)\n console.log('Added pending remote ICE candidate')\n } catch (err) {\n console.error(`Failed to add pending ICE candidate: ${err.message}`)\n }\n }\n currentSession.pendingRemoteIceCandidates = []\n }\n } catch (error) {\n console.error(`Failed to handle answer: ${error.message}`)\n }\n}\n\n/**\n * Handle ICE candidate\n * @param {Object} data\n */\nasync function handleIceCandidate(data) {\n try {\n if (currentSession.peerConnection) {\n // Check if remote description is set\n if (!currentSession.peerConnection.remoteDescription) {\n // Queue the candidate until remote description is set\n currentSession.pendingRemoteIceCandidates.push(data.candidate)\n console.log('Queued remote ICE candidate - remote description not set')\n return\n }\n const candidate = new RTCIceCandidate(JSON.parse(data.candidate))\n await currentSession.peerConnection.addIceCandidate(candidate)\n console.log('Added ICE candidate')\n }\n } catch (error) {\n console.error(`Failed to add ICE candidate: ${error.message}`)\n }\n}\n\n/**\n * Handle renegotiation offer\n * @param {Object} data\n */\nasync function handleRenegotiationOffer(data) {\n try {\n console.log('Received renegotiation offer')\n\n if (currentSession.peerConnection) {\n const offer = new RTCSessionDescription({\n type: 'offer',\n sdp: data.sdp\n })\n console.log('Setting remote description offer: ', offer)\n await currentSession.peerConnection.setRemoteDescription(offer)\n console.log('Remote description set')\n\n const answer = await currentSession.peerConnection.createAnswer()\n await currentSession.peerConnection.setLocalDescription(answer)\n\n sendEvent({\n type: 'renegotiationAnswer',\n data: {\n sdp: answer.sdp\n }\n })\n }\n } catch (error) {\n console.error(`Failed to handle renegotiation offer: ${error.message}`)\n }\n}\n\n/**\n * Start a call\n * @param {{ sessionId?: string }} payload\n */\nexport async function startCall(payload = {}) {\n try {\n if (currentSession.callStatus === 'connecting' || currentSession.callStatus === 'connected') {\n console.log(`Call already in ${currentSession.callStatus} state`)\n return\n }\n\n console.log('Starting audio call...')\n setCallStatus('connecting')\n setCallError(null)\n\n currentSession.sessionId = payload.sessionId\n\n await getUserMedia()\n\n createPeerConnection()\n\n currentSession.localStream.getTracks().forEach((track) => {\n currentSession.peerConnection.addTrack(track, currentSession.localStream)\n console.log(`Added ${track.kind} track`)\n })\n await connectSocket(payload)\n const offer = await currentSession.peerConnection.createOffer()\n await currentSession.peerConnection.setLocalDescription(offer)\n\n sendEvent({\n type: 'offer',\n data: {\n sdp: offer.sdp\n }\n })\n\n console.log('Call initiated successfully')\n } catch (error) {\n console.log('error: ', error)\n console.error(`Failed to start call: ${error.message}`)\n setCallStatus('error')\n setCallError(error.message || 'Unable to connect voice')\n cleanup()\n }\n}\n\n/**\n * Disconnect call\n */\nexport function disconnectCall() {\n sendEvent({\n type: 'end'\n })\n if (currentSession.socket) {\n currentSession.socket.close()\n currentSession.socket = null\n }\n setCallStatus('disconnected')\n if (currentSession.peerConnection) {\n currentSession.peerConnection.close()\n currentSession.peerConnection = null\n }\n if (currentSession.localStream) {\n currentSession.localStream.getTracks().forEach((track) => track.stop())\n currentSession.localStream = null\n }\n cleanup()\n}\n\n/**\n * Toggle mute\n * @returns {boolean}\n */\nexport function toggleMute() {\n if (currentSession.localStream) {\n const audioTrack = currentSession.localStream.getAudioTracks()[0]\n if (audioTrack) {\n audioTrack.enabled = !audioTrack.enabled\n currentSession.isMuted = !audioTrack.enabled\n console.log(`Audio ${currentSession.isMuted ? 'muted' : 'unmuted'}`)\n return currentSession.isMuted\n }\n }\n return false\n}\n\n/**\n * Get local stream\n * @returns {MediaStream | null}\n */\nexport function getLocalStream() {\n return currentSession.localStream\n}\n\n/**\n * Get inbound audio energy\n * @returns {Promise<number>}\n */\nexport function getInboundAudioEnergy() {\n return new Promise((resolve, reject) => {\n if (!currentSession.peerConnection) {\n reject(new Error('no peer connection'))\n return\n }\n currentSession.peerConnection\n .getStats()\n .then((stats) => {\n stats.forEach((report) => {\n if (report.type == 'inbound-rtp') {\n resolve(report.totalAudioEnergy)\n }\n })\n reject(new Error('no inbound-rtp stats found'))\n })\n .catch((err) => {\n reject(err)\n })\n })\n}\n\n/**\n * Get outbound audio energy (not implemented in original, but may be needed)\n * @returns {Promise<number>}\n */\nexport function getOutboundAudioEnergy() {\n return new Promise((resolve, reject) => {\n if (!currentSession.peerConnection) {\n reject(new Error('no peer connection'))\n return\n }\n currentSession.peerConnection\n .getStats()\n .then((stats) => {\n stats.forEach((report) => {\n if (report.type == 'outbound-rtp') {\n resolve(report.totalAudioEnergy)\n }\n })\n reject(new Error('no outbound-rtp stats found'))\n })\n .catch((err) => {\n reject(err)\n })\n })\n}\n"],"names":["uuidv7","timestamp","bytes","hex","b","getDeviceId","deviceId","sleep","ms","resolve","getSseEndpoint","baseUrl","sseEndpoint","url","e","getSocketEndpoint","socketEndpoint","getCallServerEndpoint","MESSAGE_ROLES","PING_INTERVAL","SOCKET_TIMEOUT","SocketEvents","createSession","currentSession","stopPingInterval","startPingInterval","send","clearAllTimeouts","handleSocketConnected","setTransport","handleSocketDisconnected","connectSocket","payload","fulfill","reject","credentials","getCredentials","externalId","getExternalId","queryParams","socketUrl","event","message","handleSocketEvent","error","ws","addMessage","data","toggleTypingStatus","eventId","disconnect","isConnected","callbacks","setCallbacks","initialize","updateSessionId","sessionId","startChat","configData","authenticate","messages","control","session","getSession","searchParams","sendMessage","cleanup","disconnectSocket","isTyping","transport","text","html","context","attachments","isEmpty","userMessage","isSocketConnected","socketSend","loadingMessage","headers","fetchEventSource","response","errorMessage","lastIndex","updatedMsg","msg","index","_i","supervisorMessage","_j","_k","newBotMessage","lastMsg","_l","_o","_p","AUTHENTICATION_ERROR","INITIALIZATION_ERROR","endpoint","errorPayload","getHistory","fetchRequest","_a","uploadAttachment","file","onProgress","onComplete","token","xhr","formData","uploadUrl","percentComplete","deleteAttachment","mediaId","deleteUrl","getAttachment","pathname","method","body","rtcConfig","setCallCallbacks","track","setCallStatus","status","_b","setCallError","pingMessage","sendEvent","handlePong","getUserMedia","createPeerConnection","candidateJson","err","newState","disconnectCall","handleCallServerEvent","action","handleAnswer","handleConnected","handleIceCandidate","handleRenegotiationOffer","answer","candidate","offer","startCall","toggleMute","audioTrack","getLocalStream","getInboundAudioEnergy","stats","report","getOutboundAudioEnergy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"origon-chat-sdk.js","sources":["../src/utils.js","../src/constants.js","../src/socket.js","../src/chat.js","../src/http.js","../src/call.js"],"sourcesContent":["/**\n * Utility functions for the Chat SDK\n */\n\nexport function uuidv7() {\n const timestamp = Date.now()\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n\n // Set timestamp (48 bits)\n bytes[0] = (timestamp >> 40) & 0xff\n bytes[1] = (timestamp >> 32) & 0xff\n bytes[2] = (timestamp >> 24) & 0xff\n bytes[3] = (timestamp >> 16) & 0xff\n bytes[4] = (timestamp >> 8) & 0xff\n bytes[5] = timestamp & 0xff\n\n // Set version 7 (0111)\n bytes[6] = (bytes[6] & 0x0f) | 0x70\n\n // Set variant (10xx)\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(\n 16,\n 20\n )}-${hex.slice(20)}`\n}\n\nexport function getDeviceId() {\n if (localStorage.getItem('chatDeviceId')) {\n return localStorage.getItem('chatDeviceId')\n }\n\n const deviceId = uuidv7()\n localStorage.setItem('chatDeviceId', deviceId)\n return deviceId\n}\n\nexport function parseJwt(token) {\n try {\n const base64Url = token.split('.')[1]\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map(function (c) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)\n })\n .join('')\n )\n\n return JSON.parse(jsonPayload)\n } catch {\n return null\n }\n}\n\nexport async function sleep(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function getSseEndpoint(baseUrl) {\n let sseEndpoint\n try {\n const url = new URL(baseUrl)\n sseEndpoint = `https://${url.hostname}${url.pathname}/sse`\n } catch {\n console.error('SSE Invalid base URL: ', baseUrl)\n }\n return sseEndpoint\n}\n\nexport function getSocketEndpoint(baseUrl) {\n let socketEndpoint\n try {\n const url = new URL(baseUrl)\n socketEndpoint = `wss://${url.hostname}${url.pathname}/wss`\n } catch {\n console.error('Socket Invalid base URL: ', baseUrl)\n }\n return socketEndpoint\n}\n\nexport function getCallServerEndpoint(baseUrl) {\n let socketEndpoint\n try {\n const url = new URL(baseUrl)\n socketEndpoint = `wss://${url.hostname}${url.pathname}/audio`\n } catch {\n console.error('getCallServerEndpoint: Invalid base URL: ', baseUrl)\n }\n return socketEndpoint\n}\n","/**\n * Constants for the Chat SDK\n */\n\nexport const MESSAGE_ROLES = {\n ASSISTANT: 'assistant', // this can be automated or LLM AI Agent response\n USER: 'user', // this is widget user\n SUPERVISOR: 'supervisor', // this is human supervisor (ex. Samespace Dock agent, or Resolve human agent)\n SYSTEM: 'system' // this is system message, for ex \"Agent joined\" / \"Agent left\"\n}\n","/**\n * Socket Service for Chat SDK\n * Handles WebSocket connection for real-time chat functionality\n */\n\nimport { getSocketEndpoint, uuidv7 } from './utils.js'\nimport {\n getCredentials,\n getExternalId,\n addMessage,\n toggleTypingStatus,\n setTransport\n} from './chat.js'\n\nconst PING_INTERVAL = 10000\nconst SOCKET_TIMEOUT = 5000\n\n/**\n * @typedef {Object} SocketSession\n * @property {WebSocket} [socket]\n * @property {boolean} previouslyConnected\n * @property {boolean} socketDisconnected\n * @property {NodeJS.Timeout} [pingInterval]\n * @property {NodeJS.Timeout} [socketDisconnectedTimeout]\n * @property {NodeJS.Timeout} [socketConnectionTimeout]\n */\n\n/**\n * Socket Events\n */\nexport const SocketEvents = {\n MESSAGE: 'message',\n TYPING: 'typing',\n TYPING_STOP: 'typingOff',\n END: 'end'\n}\n\n/**\n * Create a new socket session\n * @returns {SocketSession}\n */\nfunction createSession() {\n return {\n socket: null,\n previouslyConnected: false,\n socketDisconnected: false,\n pingInterval: null,\n socketDisconnectedTimeout: null,\n socketConnectionTimeout: null\n }\n}\n\n/** @type {SocketSession} */\nlet currentSession = createSession()\n\n/**\n * Stop ping interval\n */\nfunction stopPingInterval() {\n if (currentSession.pingInterval) {\n clearInterval(currentSession.pingInterval)\n currentSession.pingInterval = null\n }\n}\n\n/**\n * Start ping interval\n */\nfunction startPingInterval() {\n stopPingInterval()\n\n currentSession.pingInterval = setInterval(() => {\n if (currentSession.socket && currentSession.socket.readyState === WebSocket.OPEN) {\n send({ type: 'ping' })\n console.log('Sending keep-alive ping')\n } else {\n console.log('Socket not open, stopping ping interval')\n stopPingInterval()\n }\n }, PING_INTERVAL)\n}\n\n/**\n * Clear all timeouts\n */\nfunction clearAllTimeouts() {\n stopPingInterval()\n if (currentSession.socketDisconnectedTimeout) {\n clearTimeout(currentSession.socketDisconnectedTimeout)\n currentSession.socketDisconnectedTimeout = null\n }\n if (currentSession.socketConnectionTimeout) {\n clearTimeout(currentSession.socketConnectionTimeout)\n currentSession.socketConnectionTimeout = null\n }\n}\n\n/**\n * Handle socket connected state\n */\nfunction handleSocketConnected() {\n console.log('handleSocketConnected')\n currentSession.socketDisconnected = false\n setTransport('socket')\n}\n\n/**\n * Handle socket disconnected state\n */\nfunction handleSocketDisconnected() {\n console.log('handleSocketDisconnected')\n currentSession.socketDisconnected = true\n setTransport('sse')\n}\n\n/**\n * Connect to socket\n * @param {{ token: string, sessionId?: string }} payload\n * @returns {Promise<boolean>}\n */\nexport function connectSocket(payload) {\n return new Promise((fulfill, reject) => {\n if (\n currentSession.socket &&\n (currentSession.socket.readyState === WebSocket.CONNECTING ||\n currentSession.socket.readyState === WebSocket.OPEN)\n ) {\n console.log('Socket in connecting/open state, returning.')\n fulfill(currentSession.socket.readyState === WebSocket.OPEN)\n return\n }\n\n console.log('Initializing socket connection..')\n const credentials = getCredentials()\n if (!credentials || !credentials.endpoint) {\n reject(new Error('SDK not initialized. Please initialize SDK first.'))\n return\n }\n\n const socketEndpoint = getSocketEndpoint(credentials.endpoint)\n if (!socketEndpoint) {\n reject(\n new Error(\n 'Invalid endpoint while initializing SDK. Please check the endpoint and try again.'\n )\n )\n return\n }\n\n const externalId = getExternalId()\n const queryParams = new URLSearchParams({\n externalId\n })\n\n if (payload.sessionId) {\n queryParams.set('sessionId', payload.sessionId)\n }\n if (payload.requestId) {\n queryParams.set('requestId', payload.requestId)\n }\n if (credentials.token) {\n queryParams.set('token', credentials.token)\n }\n\n const socketUrl = `${socketEndpoint}?${queryParams.toString()}`\n currentSession.socket = new WebSocket(socketUrl)\n\n currentSession.socket.onopen = () => {\n console.log('-------- socket connected --------')\n currentSession.previouslyConnected = true\n handleSocketConnected()\n send({ type: 'ping' })\n clearTimeout(currentSession.socketConnectionTimeout)\n startPingInterval()\n fulfill(true)\n }\n\n currentSession.socket.onmessage = (event) => {\n const message = JSON.parse(event.data)\n handleSocketEvent(message)\n }\n\n currentSession.socket.onerror = (error) => {\n console.error('Socket error:', error)\n setTransport('sse')\n reject(error)\n }\n\n currentSession.socket.onclose = (ws) => {\n console.log('-------- socket disconnected --------: ', ws.code, ws.reason)\n\n if (ws.target === currentSession.socket) {\n if (ws.code === 1006) {\n // abnormal closure\n if (currentSession.previouslyConnected) {\n handleSocketDisconnected()\n } else {\n addMessage({\n errorText: 'Unable to establish connection',\n done: true,\n timestamp: new Date().toISOString()\n })\n }\n clearTimeout(currentSession.socketConnectionTimeout)\n }\n\n currentSession.socket = null\n clearAllTimeouts()\n }\n }\n\n if (!currentSession.previouslyConnected) {\n currentSession.socketConnectionTimeout = setTimeout(() => {\n console.error('Socket connection timed out')\n addMessage({\n errorText: 'Unable to establish connection',\n done: true,\n timestamp: new Date().toISOString()\n })\n reject(new Error('Socket connection timed out'))\n }, SOCKET_TIMEOUT)\n }\n })\n}\n\n/**\n * Send data through socket\n * @param {Object} data\n */\nexport function send(data) {\n console.log('sending socket event: ', data.type)\n if (currentSession.socketDisconnected || !currentSession.socket) {\n return\n }\n currentSession.socket.send(JSON.stringify({ ...data, eventId: data.eventId || uuidv7() }))\n}\n\n/**\n * Send data through socket and wait for acknowledgment\n * @param {Object} data\n * @returns {Promise<Object>}\n */\nexport function sendWithAck(data) {\n return new Promise((resolve, reject) => {\n if (!currentSession.socket) {\n console.error('sendWithAck: socket instance not found or not connected')\n reject(new Error('Socket instance not found or not connected'))\n return\n }\n\n const autoRejectTimeout = setTimeout(() => {\n reject(new Error('Timeout'))\n }, 5000)\n\n const eventId = data.eventId || uuidv7()\n\n const onMessage = (event) => {\n const eventData = JSON.parse(event.data)\n if (eventData.eventId === eventId) {\n clearTimeout(autoRejectTimeout)\n currentSession.socket.removeEventListener('message', onMessage)\n if (eventData.data) {\n resolve(eventData.data)\n } else {\n reject(new Error(eventData.error?.message ?? 'Unknown error'))\n }\n }\n }\n currentSession.socket.addEventListener('message', onMessage)\n currentSession.socket.send(JSON.stringify({ ...data, eventId }))\n })\n}\n\n/**\n * Handle socket event\n * @param {Object} event\n */\nfunction handleSocketEvent(event) {\n console.log('received socket event: ', event.type)\n\n switch (event.type) {\n case 'pong': {\n if (currentSession.socketDisconnected) {\n handleSocketConnected()\n }\n if (currentSession.socketDisconnectedTimeout) {\n clearTimeout(currentSession.socketDisconnectedTimeout)\n }\n currentSession.socketDisconnectedTimeout = setTimeout(() => {\n console.log('---- socket ping timeout ----')\n handleSocketDisconnected()\n }, PING_INTERVAL + 1000)\n break\n }\n case SocketEvents.TYPING: {\n toggleTypingStatus(true)\n break\n }\n case SocketEvents.TYPING_STOP: {\n toggleTypingStatus(false)\n break\n }\n case SocketEvents.MESSAGE: {\n const { eventId, data } = event\n if (!eventId) {\n addMessage({\n ...data,\n done: true,\n timestamp: new Date().toISOString()\n })\n }\n break\n }\n case SocketEvents.END: {\n disconnect()\n break\n }\n default:\n break\n }\n}\n\n/**\n * Reconnect to socket\n */\nexport function reconnect() {\n if (currentSession.socket) {\n send({ type: 'ping' })\n }\n}\n\n/**\n * Disconnect socket\n */\nexport function disconnect() {\n console.log('Disconnecting socket')\n if (currentSession.socket) {\n currentSession.socket.close(1000)\n }\n currentSession.previouslyConnected = false\n clearAllTimeouts()\n currentSession.socket = null\n setTransport('sse')\n}\n\n/**\n * Check if socket is connected\n * @returns {boolean}\n */\nexport function isConnected() {\n return (\n currentSession.socket !== null &&\n currentSession.socket.readyState === WebSocket.OPEN &&\n !currentSession.socketDisconnected\n )\n}\n\n/**\n * Check if socket is disconnected\n * @returns {boolean}\n */\nexport function isDisconnected() {\n return currentSession.socketDisconnected\n}\n","/**\n * Chat Service for Chat SDK\n * Handles real-time chat functionality without depending on external state\n * Uses callbacks to communicate state changes to the consumer\n */\n\nimport { fetchEventSource } from '@microsoft/fetch-event-source'\nimport { getSession, authenticate } from './http.js'\nimport { getDeviceId, getSseEndpoint, sleep } from './utils.js'\nimport { MESSAGE_ROLES } from './constants.js'\nimport {\n connectSocket,\n send as socketSend,\n disconnect as disconnectSocket,\n isConnected as isSocketConnected\n} from './socket.js'\n\n/**\n * @typedef {Object} ChatCallbacks\n * @property {(message: Object) => void} [onMessageAdd] - Called when a new message is added\n * @property {(index: number, updatedMsg: Object) => void} [onMessageUpdate] - Called when an existing message is updated\n * @property {(sessionId: string) => void} [onSessionUpdate] - Called when session ID is updated\n * @property {(transport: TransportType) => void} [onTransportUpdate] - Called when transport type changes\n * @property {(control: 'agent' | 'human') => void} [onControlUpdate] - Called when control changes between agent and human\n */\n\n/**\n * @typedef {'sse' | 'socket'} TransportType\n */\n\n/**\n * @typedef {Object} ChatSession\n * @property {string} sessionId\n * @property {string} sseUrl\n * @property {string} [requestId]\n * @property {AbortController} [abortController]\n * @property {string} [lastStreamId]\n * @property {Array} messages\n * @property {ChatCallbacks} callbacks\n * @property {TransportType} transport\n */\n\n/**\n * Create a new chat session\n * @param {ChatCallbacks} [callbacks={}]\n * @returns {ChatSession}\n */\nfunction createSession(callbacks = {}) {\n return {\n credentials: undefined,\n authenticated: false,\n configData: undefined,\n sessionId: undefined,\n requestId: undefined,\n sseUrl: undefined,\n abortController: undefined,\n lastStreamId: undefined,\n messages: [],\n callbacks,\n transport: 'sse',\n control: 'agent'\n }\n}\n\n/** @type {ChatSession} */\nlet currentSession = createSession()\n\n/**\n * Set callbacks for the current session\n * @param {ChatCallbacks} callbacks\n */\nexport function setCallbacks(callbacks) {\n currentSession.callbacks = { ...currentSession.callbacks, ...callbacks }\n}\n\n/**\n * Initialize the chat session\n * @param {Object} credentials - Credentials for the chat\n */\nexport function initialize(credentials) {\n console.log('Initializing chat...', credentials)\n currentSession.credentials = credentials\n if (credentials.token) {\n currentSession.authenticated = true\n }\n}\n\n/**\n * Get current chat session credentials\n * @returns {{ endpoint: string, apiKey: string } | undefined}\n */\nexport function getCredentials() {\n return currentSession.credentials\n}\n\n/**\n * Update the session ID and notify via callback\n * @param {string} sessionId - The new session ID\n */\nexport function updateSessionId(sessionId) {\n if (sessionId && sessionId !== currentSession.sessionId) {\n currentSession.sessionId = sessionId\n currentSession.callbacks.onSessionUpdate?.(sessionId)\n }\n}\n\n/**\n * Initiate a new chat session or resume an existing one\n * @param {Object} credentials - Credentials for the chat\n * @param {Object} payload - Payload for the chat. It contains sessionId (optional)\n * @param {string} [payload.sessionId] - Optional session ID to resume\n * @returns {Promise<{ sessionId: string, messages: Array }>}\n */\nexport async function startChat(payload = {}) {\n try {\n console.log('startChat: ', payload, currentSession)\n\n let configData = null\n if (!currentSession.authenticated) {\n configData = await authenticate(currentSession.credentials)\n currentSession.authenticated = true\n currentSession.configData = configData\n } else {\n configData = currentSession.configData\n }\n\n let messages = []\n let control = 'agent'\n\n if (payload.sessionId) {\n const session = await getSession(payload.sessionId)\n messages = session.messages\n control = session.control || 'agent'\n }\n\n const searchParams = new URLSearchParams()\n if (!currentSession.credentials.token) {\n searchParams.set('externalId', getExternalId()) // externalId is needed only for public urls, not for internal chat (where token is provided)\n }\n currentSession.sseUrl = `${getSseEndpoint(\n currentSession.credentials.endpoint\n )}?${searchParams.toString()}`\n currentSession.sessionId = payload.sessionId\n currentSession.messages = messages\n currentSession.control = control\n\n if (control === 'human') {\n // Connect to SSE for incoming messages when control is human\n sendMessage({ text: '', html: '' }).catch(() => {})\n }\n\n console.log('Chat initiated successfully')\n\n return {\n sessionId: currentSession.sessionId,\n messages,\n control,\n configData\n }\n } catch (error) {\n console.error(`Failed to start chat: ${error.message}`)\n cleanup()\n throw error\n }\n}\n\n/**\n * Disconnect from the current chat session\n */\nexport function disconnect() {\n cleanup()\n}\n\n/**\n * Clean up the current session\n */\nfunction cleanup() {\n if (currentSession.abortController) {\n currentSession.abortController.abort()\n }\n disconnectSocket()\n\n const { callbacks, credentials } = currentSession\n currentSession = createSession(callbacks)\n currentSession.credentials = credentials\n\n console.log('Chat session cleaned up')\n}\n\nexport function getExternalId() {\n if (currentSession.credentials?.externalId) {\n return currentSession.credentials.externalId\n }\n return getDeviceId()\n}\n\n/**\n * Add a message to the chat\n * @param {Object} message - The message object to add\n */\nexport function addMessage(message) {\n currentSession.messages = [...currentSession.messages, message]\n currentSession.callbacks.onMessageAdd?.(message)\n}\n\nexport function toggleTypingStatus(isTyping) {\n currentSession.callbacks.onTyping?.(isTyping)\n}\n\n/**\n * Set the transport type\n * @param {TransportType} transport\n */\nexport function setTransport(transport) {\n console.log('Setting transport to:', transport)\n currentSession.transport = transport\n currentSession.callbacks.onTransportUpdate?.(transport)\n}\n\n/**\n * Get current transport type\n * @returns {TransportType}\n */\nexport function getTransport() {\n return currentSession.transport\n}\n\n/**\n * Send a message in the current chat session\n * @param {{ text: string, html?: string }} message\n * @returns {Promise<string>}\n */\nexport function sendMessage({ text, html, context, attachments, meta }) {\n return new Promise((resolve, reject) => {\n ;(async () => {\n try {\n const isEmpty = !text && !html && !attachments?.length\n\n // Add user message only if there's content\n if (!isEmpty) {\n const userMessage = {\n role: MESSAGE_ROLES.USER,\n text,\n html,\n timestamp: new Date().toISOString(),\n attachments,\n meta\n }\n addMessage(userMessage)\n await sleep(200)\n }\n\n // If transport is socket and socket is connected, use socket\n if (currentSession.transport === 'socket' && isSocketConnected()) {\n socketSend({\n type: 'message',\n data: {\n text,\n html\n }\n })\n resolve(currentSession.sessionId)\n return\n }\n\n if (currentSession.control === 'agent') {\n const loadingMessage = {\n role: MESSAGE_ROLES.ASSISTANT,\n text: '',\n loading: true\n }\n addMessage(loadingMessage)\n }\n\n const url = new URL(currentSession.sseUrl)\n if (currentSession.sessionId) {\n url.searchParams.set('sessionId', currentSession.sessionId)\n }\n if (currentSession.requestId) {\n url.searchParams.set('requestId', currentSession.requestId)\n }\n\n currentSession.lastStreamId = undefined\n\n // Create a new abort controller for this request\n currentSession.abortController = new AbortController()\n\n const headers = {\n 'Content-Type': 'application/json'\n }\n if (currentSession.credentials?.token) {\n headers.Authorization = `Bearer ${currentSession.credentials.token}`\n }\n\n await fetchEventSource(url.toString(), {\n method: 'POST',\n headers,\n body: isEmpty\n ? meta\n : JSON.stringify({\n message: text,\n html,\n context,\n attachments\n }),\n signal: currentSession.abortController.signal,\n openWhenHidden: true,\n onopen: async (response) => {\n if (!response.ok) {\n console.error('Failed to send message bad response: ', response)\n throw new Error('Failed to send message')\n }\n },\n onmessage: (response) => {\n // console.log('Event: ', response)\n const data = JSON.parse(response.data)\n\n if (response.event === 'connected') {\n currentSession.sessionId = data.sessionId\n currentSession.requestId = data.requestId\n console.log('Connected: ', data)\n if (data.control) {\n currentSession.control = data.control\n currentSession.callbacks.onControlUpdate?.(data.control)\n }\n } else if (response.event === 'upgrade_to_websocket') {\n console.log('Upgrade to websocket: ', data)\n connectSocket({\n sessionId: currentSession.sessionId,\n requestId: data.requestId\n })\n } else if (response.event === 'update') {\n if (data.control) {\n currentSession.control = data.control\n currentSession.callbacks.onControlUpdate?.(data.control)\n }\n } else if (data.error) {\n const errorMessage =\n data.error && typeof data.error === 'string'\n ? data.error\n : 'Failed to connect to the system'\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n errorText: errorMessage\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n reject(new Error(errorMessage))\n } else if (response.event === 'done') {\n console.log('Done: ', data)\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n done: true\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n resolve(currentSession.sessionId)\n } else if (data.message !== undefined || data.attachments?.length > 0) {\n // If role is supervisor, treat it as a new message\n if (data.role === MESSAGE_ROLES.SUPERVISOR) {\n const supervisorMessage = {\n role: MESSAGE_ROLES.SUPERVISOR,\n text: data.message,\n attachments: data.attachments,\n sources: data.sources,\n done: true\n }\n addMessage(supervisorMessage)\n resolve(currentSession.sessionId)\n\n // Store session info for reuse\n currentSession.sessionId = data.sessionId ?? currentSession.sessionId\n currentSession.requestId = data.requestId ?? currentSession.requestId\n return\n }\n\n // If streamId changes, start a new assistant message\n if (data.streamId !== undefined) {\n if (currentSession.lastStreamId === undefined) {\n currentSession.lastStreamId = data.streamId\n } else if (data.streamId !== currentSession.lastStreamId) {\n currentSession.lastStreamId = data.streamId\n const newBotMessage = {\n role: MESSAGE_ROLES.ASSISTANT,\n text: '',\n loading: true\n }\n addMessage(newBotMessage)\n }\n }\n\n // Update the last message with new content\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n text: (lastMsg.text || '') + data.message,\n sources: data.sources,\n attachments: data.attachments,\n done: data.done ?? lastMsg.done\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n\n // Store session info for reuse\n currentSession.sessionId = data.sessionId ?? currentSession.sessionId\n currentSession.requestId = data.requestId ?? currentSession.requestId\n }\n },\n onerror: (error) => {\n throw error // Rethrow to stop retries\n },\n openWhenHidden: true\n })\n } catch (error) {\n console.error('Failed to send message: ', error)\n const errorMessage = 'Failed to connect to the system'\n const lastIndex = currentSession.messages.length - 1\n const lastMsg = currentSession.messages[lastIndex]\n const updatedMsg = {\n ...lastMsg,\n loading: false,\n errorText: lastMsg.done ? undefined : error.message || errorMessage,\n done: true\n }\n currentSession.messages = currentSession.messages.map((msg, index) =>\n index === lastIndex ? updatedMsg : msg\n )\n currentSession.callbacks.onMessageUpdate?.(lastIndex, updatedMsg)\n reject(error)\n }\n })()\n })\n}\n","/**\n * API Service for Chat SDK\n * Handles all HTTP requests without depending on external state\n */\n\nimport { getCredentials, getExternalId } from './chat.js'\nimport { MESSAGE_ROLES } from './constants.js'\n\nconst AUTHENTICATION_ERROR = 'Something went wrong initializing the chat'\nconst INITIALIZATION_ERROR = 'Chat SDK not initialized'\n\n/**\n * Authenticate with the chat service\n * @param {{ endpoint: string }} credentials\n * @returns {Promise<object>} Authentication response data\n */\nexport async function authenticate(payload) {\n const { endpoint } = payload\n const url = `${endpoint}/config`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n\n if (!response.ok) {\n const errorPayload = await response.json()\n throw new Error(errorPayload?.error || AUTHENTICATION_ERROR)\n }\n\n const res = await response.json()\n const data = res.data\n\n return data\n}\n\n/**\n * Get chat history for the current device\n * @returns {Promise<{ sessions: Array }>}\n */\nexport async function getHistory() {\n const queryParams = new URLSearchParams({\n externalId: getExternalId()\n })\n const response = await fetchRequest(`/sessions?${queryParams.toString()}`, 'GET')\n\n if (!response.ok) {\n throw new Error('Unable to load history, please try again later')\n }\n\n return response.json()\n}\n\n/**\n * Get session data (control and history) for a specific session\n * @param {string} sessionId\n * @returns {Promise<{ control: string, messages: Array }>}\n */\nexport async function getSession(sessionId) {\n const queryParams = new URLSearchParams({\n sessionId\n })\n const response = await fetchRequest(`/session?${queryParams.toString()}`, 'GET')\n\n if (!response.ok) {\n throw new Error('Unable to load messages, please try again later')\n }\n\n const data = await response.json()\n const control = data?.control\n const messages = (data?.history ?? []).map((msg) => ({\n id: msg.id,\n text: msg.text,\n role: msg.youtubeVideo\n ? MESSAGE_ROLES.ASSISTANT // for youtube video messages, role is \"system\" from backend, we need to make it \"assistant\"\n : msg.role,\n timestamp: msg.timestamp,\n video: msg.youtubeVideo,\n attachments: msg.attachments,\n channel: msg.channel,\n done: true\n }))\n\n return { control, messages }\n}\n\n/**\n * Upload attachment with progress tracking\n * @param {File} file\n * @param {Function} onProgress - callback (percentComplete, loaded, total)\n * @param {Function} onComplete - callback (error, response)\n * @returns {XMLHttpRequest} xhr object to allow abort\n */\nexport function uploadAttachment(file, onProgress, onComplete) {\n const credentials = getCredentials()\n const { endpoint, token } = credentials || {}\n\n if (!endpoint) {\n const error = new Error(INITIALIZATION_ERROR)\n if (onComplete) {\n onComplete(error, null)\n }\n return null\n }\n\n const xhr = new XMLHttpRequest()\n const formData = new FormData()\n formData.append('file', file)\n\n const uploadUrl = `${endpoint}/upload`\n\n xhr.open('POST', uploadUrl)\n if (token) {\n xhr.setRequestHeader('Authorization', `Bearer ${token}`)\n }\n\n // Upload progress callback\n if (onProgress) {\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable) {\n const percentComplete = (event.loaded / event.total) * 100\n onProgress(percentComplete, event.loaded, event.total)\n }\n })\n }\n\n // Upload complete callback\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText)\n if (onComplete) {\n onComplete(null, response)\n }\n } catch (error) {\n if (onComplete) {\n onComplete(new Error('Failed to parse response'), null)\n }\n }\n } else {\n if (onComplete) {\n onComplete(new Error(`Upload failed with status ${xhr.status}`), null)\n }\n }\n })\n\n xhr.addEventListener('error', () => {\n if (onComplete) {\n onComplete(new Error('Network error during upload'), null)\n }\n })\n\n xhr.addEventListener('abort', () => {\n if (onComplete) {\n onComplete(new Error('Upload aborted'), null)\n }\n })\n\n xhr.send(formData)\n\n return xhr\n}\n\n/**\n * Delete attachment by mediaId\n * @param {string} mediaId\n * @returns {Promise<{ success: boolean }>}\n */\nexport async function deleteAttachment(mediaId) {\n const credentials = getCredentials()\n const { endpoint, token } = credentials || {}\n\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n const deleteUrl = `${endpoint}/delete/${mediaId}`\n\n const headers = {}\n if (token) {\n headers.Authorization = `Bearer ${token}`\n }\n\n const response = await fetch(deleteUrl, {\n method: 'DELETE',\n headers\n })\n\n if (!response.ok) {\n throw new Error(`Delete failed with status ${response.status}`)\n }\n\n return { success: true }\n}\n\n/**\n * Get attachment URL by mediaId\n * @param {string} mediaId\n * @returns {string} Full URL to the attachment\n */\nexport function getAttachment(mediaId) {\n const credentials = getCredentials()\n const { endpoint } = credentials || {}\n\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n return `${endpoint}/upload/${mediaId}`\n}\n\n/**\n * Internal fetch request helper\n * @param {string} pathname\n * @param {string} method\n * @param {object|null} body\n * @returns {Promise<Response>}\n */\nasync function fetchRequest(pathname, method = 'GET', body = null) {\n const credentials = getCredentials()\n\n const { endpoint, token } = credentials || {}\n if (!endpoint) {\n throw new Error(INITIALIZATION_ERROR)\n }\n\n const url = `${endpoint}${pathname}`\n\n const headers = {\n 'Content-Type': 'application/json'\n }\n if (token) {\n headers.Authorization = `Bearer ${token}`\n }\n\n return fetch(url, {\n headers,\n method,\n body: body ? JSON.stringify(body) : null\n })\n}\n","/**\n * Socket Service for Call SDK\n * Handles WebRTC call functionality without depending on external state\n * Uses callbacks to communicate state changes to the consumer\n */\n\nimport { getCallServerEndpoint } from './utils.js'\nimport { getCredentials, getExternalId, updateSessionId } from './chat.js'\n\n/**\n * @typedef {Object} CallCallbacks\n * @property {(status: string) => void} [onCallStatus] - Called when call status changes\n * @property {(error: string | null) => void} [onCallError] - Called when call error occurs\n */\n\n/**\n * @typedef {Object} CallSession\n * @property {string} [sessionId]\n * @property {WebSocket} [socket]\n * @property {RTCPeerConnection} [peerConnection]\n * @property {MediaStream} [localStream]\n * @property {MediaStream} [remoteStream]\n * @property {HTMLAudioElement} [remoteAudio]\n * @property {boolean} isMuted\n * @property {string} callStatus\n * @property {NodeJS.Timeout} [pingInterval]\n * @property {number} pingCount\n * @property {number | null} lastPongTime\n * @property {CallCallbacks} callbacks\n * @property {string[]} localIceCandidates - Queued local ICE candidates to send after remote description is set\n * @property {string[]} pendingRemoteIceCandidates - Queued remote ICE candidates to add after remote description is set\n */\n\n/**\n * Create a new call session\n * @param {CallCallbacks} [callbacks={}]\n * @returns {CallSession}\n */\nfunction createSession(callbacks = {}) {\n return {\n sessionId: undefined,\n socket: null,\n peerConnection: null,\n localStream: null,\n remoteStream: null,\n remoteAudio: null,\n isMuted: false,\n callStatus: 'disconnected',\n pingInterval: null,\n pingCount: 0,\n lastPongTime: null,\n callbacks,\n localIceCandidates: [],\n pendingRemoteIceCandidates: []\n }\n}\n\n/** @type {CallSession} */\nlet currentSession = createSession()\n\nconst rtcConfig = {\n iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun1.l.google.com:19302' }]\n}\n\n/**\n * Set callbacks for the current session\n * @param {CallCallbacks} callbacks\n */\nexport function setCallCallbacks(callbacks) {\n currentSession.callbacks = { ...currentSession.callbacks, ...callbacks }\n}\n\n/**\n * Clean up the current session\n */\nfunction cleanup() {\n if (currentSession.peerConnection) {\n currentSession.peerConnection.close()\n currentSession.peerConnection = null\n }\n\n if (currentSession.localStream) {\n currentSession.localStream.getTracks().forEach((track) => track.stop())\n currentSession.localStream = null\n }\n\n if (currentSession.remoteStream) {\n currentSession.remoteStream = null\n }\n\n if (currentSession.remoteAudio) {\n currentSession.remoteAudio.srcObject = null\n if (currentSession.remoteAudio.parentNode) {\n currentSession.remoteAudio.parentNode.removeChild(currentSession.remoteAudio)\n }\n currentSession.remoteAudio = null\n }\n\n if (currentSession.socket) {\n currentSession.socket.close()\n currentSession.socket = null\n }\n\n stopPingInterval()\n\n const callbacks = currentSession.callbacks\n currentSession = createSession(callbacks)\n\n console.log('Call session cleaned up')\n}\n\n/**\n * Update call status and notify callback\n * @param {string} status\n */\nfunction setCallStatus(status) {\n currentSession.callStatus = status\n currentSession.callbacks.onCallStatus?.(status)\n}\n\n/**\n * Update call error and notify callback\n * @param {string | null} error\n */\nfunction setCallError(error) {\n currentSession.callbacks.onCallError?.(error)\n}\n\n/**\n * Stop ping interval\n */\nfunction stopPingInterval() {\n if (currentSession.pingInterval) {\n clearInterval(currentSession.pingInterval)\n currentSession.pingInterval = null\n }\n}\n\n/**\n * Start ping interval\n */\nfunction startPingInterval() {\n stopPingInterval()\n\n currentSession.pingInterval = setInterval(() => {\n if (currentSession.socket && currentSession.socket.readyState === WebSocket.OPEN) {\n currentSession.pingCount++\n const pingMessage = {\n type: 'ping',\n timestamp: Date.now(),\n count: currentSession.pingCount\n }\n sendEvent(pingMessage)\n console.log(`Sending keep-alive ping #${currentSession.pingCount}`)\n } else {\n console.log('Socket not open, stopping ping interval')\n stopPingInterval()\n }\n }, 10000)\n}\n\n/**\n * Handle pong response\n */\nfunction handlePong() {\n currentSession.lastPongTime = Date.now()\n console.log(`Received pong #${currentSession.pingCount}`)\n}\n\n/**\n * Send event through socket\n * @param {Object} payload\n */\nfunction sendEvent(payload) {\n if (!currentSession.socket) {\n console.error('Failed to send event: no socket instance')\n return\n }\n if (currentSession.socket.readyState !== WebSocket.OPEN) {\n console.error('Failed to send event: socket state not open ', payload)\n return\n }\n\n currentSession.socket.send(JSON.stringify(payload))\n}\n\n/**\n * Get user media\n */\nasync function getUserMedia() {\n try {\n currentSession.localStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n video: false\n })\n console.log('Got audio media')\n } catch (error) {\n console.error(`Failed to get audio media: ${error.message}`)\n throw error\n }\n}\n\n/**\n * Create peer connection\n */\nfunction createPeerConnection() {\n currentSession.peerConnection = new RTCPeerConnection(rtcConfig)\n\n currentSession.peerConnection.onicecandidate = (event) => {\n if (event.candidate) {\n const candidateJson = JSON.stringify(event.candidate)\n // Queue local ICE candidates until remote description is set\n if (currentSession.peerConnection && currentSession.peerConnection.remoteDescription) {\n sendEvent({\n type: 'ice',\n data: {\n candidate: candidateJson\n }\n })\n console.log('Sent ICE candidate immediately')\n } else {\n currentSession.localIceCandidates.push(candidateJson)\n console.log('Queued local ICE candidate')\n }\n }\n }\n\n currentSession.peerConnection.ontrack = (event) => {\n console.log('Received remote audio stream')\n currentSession.remoteStream = event.streams[0]\n\n if (!currentSession.remoteAudio) {\n currentSession.remoteAudio = document.createElement('audio')\n currentSession.remoteAudio.autoplay = true\n currentSession.remoteAudio.controls = false\n document.body.appendChild(currentSession.remoteAudio)\n }\n currentSession.remoteAudio.srcObject = currentSession.remoteStream\n // explicitly kick off playback and catch any policy/gesture errors\n currentSession.remoteAudio\n .play()\n .then(() => console.log('🔊 remote audio playing'))\n .catch((err) => console.error('❌ playback error:', err))\n }\n\n currentSession.peerConnection.onconnectionstatechange = () => {\n const newState = currentSession.peerConnection.connectionState\n console.log(`Connection state: ${newState}`)\n\n if (newState === 'connected') {\n setCallStatus('connected')\n } else if (newState === 'disconnected' || newState === 'closed') {\n setCallStatus('disconnected')\n disconnectCall()\n }\n }\n\n currentSession.peerConnection.oniceconnectionstatechange = () => {\n console.log(`ICE connection state: ${currentSession.peerConnection.iceConnectionState}`)\n }\n}\n\n/**\n * Connect socket\n * @param {{ sessionId?: string }} payload\n */\nfunction connectSocket(payload) {\n return new Promise((fulfill, reject) => {\n if (\n currentSession.socket &&\n (currentSession.socket.readyState === WebSocket.CONNECTING ||\n currentSession.socket.readyState === WebSocket.OPEN)\n ) {\n console.log('Socket in connecting/open state, returning.')\n fulfill(currentSession.socket.readyState === WebSocket.OPEN)\n return\n }\n\n console.log('Initializing socket connection..')\n const credentials = getCredentials()\n if (!credentials || !credentials.endpoint) {\n reject(new Error('SDK not initialized. Please initialize SDK first.'))\n return\n }\n\n // Extract hostname from endpoint\n const socketEndpoint = getCallServerEndpoint(credentials.endpoint)\n if (!socketEndpoint) {\n reject(\n new Error(\n 'Invalid endpoint while initializing SDK. Please check the endpoint and try again.'\n )\n )\n return\n }\n\n const externalId = getExternalId()\n const queryParams = new URLSearchParams({\n externalId\n })\n if (payload.sessionId) {\n queryParams.set('sessionId', payload.sessionId)\n }\n if (credentials.token) {\n queryParams.set('token', credentials.token)\n }\n\n const socketUrl = `${socketEndpoint}?${queryParams.toString()}`\n currentSession.socket = new WebSocket(socketUrl)\n\n currentSession.socket.onopen = (event) => {\n console.log('Socket connection established: ', event)\n startPingInterval()\n fulfill(true)\n }\n\n currentSession.socket.onmessage = (event) => {\n const data = JSON.parse(event.data)\n handleCallServerEvent(data)\n }\n\n currentSession.socket.onerror = (error) => {\n console.error('Socket error: ', error)\n setCallStatus('error')\n setCallError(error.message || 'Unable to connect voice')\n reject(error)\n }\n\n currentSession.socket.onclose = (event) => {\n console.log('Socket connection closed: ', event)\n stopPingInterval()\n }\n })\n}\n\n/**\n * Handle call server event\n * @param {Object} action\n */\nfunction handleCallServerEvent(action) {\n console.log('Handling socket server event: ', action)\n\n switch (action.type) {\n case 'pong':\n handlePong()\n break\n\n case 'answer':\n handleAnswer(action.data)\n break\n\n case 'connected':\n handleConnected(action.data)\n break\n\n case 'ice':\n handleIceCandidate(action.data)\n break\n\n case 'renegotiationOffer':\n handleRenegotiationOffer(action.data)\n break\n case 'end':\n disconnectCall()\n break\n case 'error':\n setCallStatus('error')\n setCallError(action.error || 'Unable to connect voice')\n break\n\n default:\n console.log('Unknown call event type: ', action.type)\n break\n }\n}\n\n/**\n * Handle connected event\n * @param {Object} data\n */\nfunction handleConnected(data) {\n console.log('Received connected event')\n currentSession.sessionId = data.sessionId\n // Update chat session with the new sessionId and notify controller\n updateSessionId(data.sessionId)\n}\n\n/**\n * Handle answer\n * @param {Object} data\n */\nasync function handleAnswer(data) {\n try {\n console.log('Received answer')\n\n if (currentSession.peerConnection) {\n const answer = new RTCSessionDescription({\n type: 'answer',\n sdp: data.sdp\n })\n console.log('Setting remote description answer: ', answer)\n await currentSession.peerConnection.setRemoteDescription(answer)\n console.log('Remote description set')\n\n // Send all queued local ICE candidates\n for (const candidateJson of currentSession.localIceCandidates) {\n sendEvent({\n type: 'ice',\n data: {\n candidate: candidateJson\n }\n })\n console.log('Sent queued local ICE candidate')\n }\n currentSession.localIceCandidates = []\n\n // Process any pending remote ICE candidates\n for (const candidateJson of currentSession.pendingRemoteIceCandidates) {\n try {\n const candidate = new RTCIceCandidate(JSON.parse(candidateJson))\n await currentSession.peerConnection.addIceCandidate(candidate)\n console.log('Added pending remote ICE candidate')\n } catch (err) {\n console.error(`Failed to add pending ICE candidate: ${err.message}`)\n }\n }\n currentSession.pendingRemoteIceCandidates = []\n }\n } catch (error) {\n console.error(`Failed to handle answer: ${error.message}`)\n }\n}\n\n/**\n * Handle ICE candidate\n * @param {Object} data\n */\nasync function handleIceCandidate(data) {\n try {\n if (currentSession.peerConnection) {\n // Check if remote description is set\n if (!currentSession.peerConnection.remoteDescription) {\n // Queue the candidate until remote description is set\n currentSession.pendingRemoteIceCandidates.push(data.candidate)\n console.log('Queued remote ICE candidate - remote description not set')\n return\n }\n const candidate = new RTCIceCandidate(JSON.parse(data.candidate))\n await currentSession.peerConnection.addIceCandidate(candidate)\n console.log('Added ICE candidate')\n }\n } catch (error) {\n console.error(`Failed to add ICE candidate: ${error.message}`)\n }\n}\n\n/**\n * Handle renegotiation offer\n * @param {Object} data\n */\nasync function handleRenegotiationOffer(data) {\n try {\n console.log('Received renegotiation offer')\n\n if (currentSession.peerConnection) {\n const offer = new RTCSessionDescription({\n type: 'offer',\n sdp: data.sdp\n })\n console.log('Setting remote description offer: ', offer)\n await currentSession.peerConnection.setRemoteDescription(offer)\n console.log('Remote description set')\n\n const answer = await currentSession.peerConnection.createAnswer()\n await currentSession.peerConnection.setLocalDescription(answer)\n\n sendEvent({\n type: 'renegotiationAnswer',\n data: {\n sdp: answer.sdp\n }\n })\n }\n } catch (error) {\n console.error(`Failed to handle renegotiation offer: ${error.message}`)\n }\n}\n\n/**\n * Start a call\n * @param {{ sessionId?: string }} payload\n */\nexport async function startCall(payload = {}) {\n try {\n if (currentSession.callStatus === 'connecting' || currentSession.callStatus === 'connected') {\n console.log(`Call already in ${currentSession.callStatus} state`)\n return\n }\n\n console.log('Starting audio call...')\n setCallStatus('connecting')\n setCallError(null)\n\n currentSession.sessionId = payload.sessionId\n\n await getUserMedia()\n\n createPeerConnection()\n\n currentSession.localStream.getTracks().forEach((track) => {\n currentSession.peerConnection.addTrack(track, currentSession.localStream)\n console.log(`Added ${track.kind} track`)\n })\n await connectSocket(payload)\n const offer = await currentSession.peerConnection.createOffer()\n await currentSession.peerConnection.setLocalDescription(offer)\n\n sendEvent({\n type: 'offer',\n data: {\n sdp: offer.sdp\n }\n })\n\n console.log('Call initiated successfully')\n } catch (error) {\n console.log('error: ', error)\n console.error(`Failed to start call: ${error.message}`)\n setCallStatus('error')\n setCallError(error.message || 'Unable to connect voice')\n cleanup()\n }\n}\n\n/**\n * Disconnect call\n */\nexport function disconnectCall() {\n sendEvent({\n type: 'end'\n })\n if (currentSession.socket) {\n currentSession.socket.close()\n currentSession.socket = null\n }\n setCallStatus('disconnected')\n if (currentSession.peerConnection) {\n currentSession.peerConnection.close()\n currentSession.peerConnection = null\n }\n if (currentSession.localStream) {\n currentSession.localStream.getTracks().forEach((track) => track.stop())\n currentSession.localStream = null\n }\n cleanup()\n}\n\n/**\n * Toggle mute\n * @returns {boolean}\n */\nexport function toggleMute() {\n if (currentSession.localStream) {\n const audioTrack = currentSession.localStream.getAudioTracks()[0]\n if (audioTrack) {\n audioTrack.enabled = !audioTrack.enabled\n currentSession.isMuted = !audioTrack.enabled\n console.log(`Audio ${currentSession.isMuted ? 'muted' : 'unmuted'}`)\n return currentSession.isMuted\n }\n }\n return false\n}\n\n/**\n * Get local stream\n * @returns {MediaStream | null}\n */\nexport function getLocalStream() {\n return currentSession.localStream\n}\n\n/**\n * Get inbound audio energy\n * @returns {Promise<number>}\n */\nexport function getInboundAudioEnergy() {\n return new Promise((resolve, reject) => {\n if (!currentSession.peerConnection) {\n reject(new Error('no peer connection'))\n return\n }\n currentSession.peerConnection\n .getStats()\n .then((stats) => {\n stats.forEach((report) => {\n if (report.type == 'inbound-rtp') {\n resolve(report.totalAudioEnergy)\n }\n })\n reject(new Error('no inbound-rtp stats found'))\n })\n .catch((err) => {\n reject(err)\n })\n })\n}\n\n/**\n * Get outbound audio energy (not implemented in original, but may be needed)\n * @returns {Promise<number>}\n */\nexport function getOutboundAudioEnergy() {\n return new Promise((resolve, reject) => {\n if (!currentSession.peerConnection) {\n reject(new Error('no peer connection'))\n return\n }\n currentSession.peerConnection\n .getStats()\n .then((stats) => {\n stats.forEach((report) => {\n if (report.type == 'outbound-rtp') {\n resolve(report.totalAudioEnergy)\n }\n })\n reject(new Error('no outbound-rtp stats found'))\n })\n .catch((err) => {\n reject(err)\n })\n })\n}\n"],"names":["uuidv7","timestamp","bytes","hex","b","getDeviceId","deviceId","sleep","ms","resolve","getSseEndpoint","baseUrl","sseEndpoint","url","e","getSocketEndpoint","socketEndpoint","getCallServerEndpoint","MESSAGE_ROLES","PING_INTERVAL","SOCKET_TIMEOUT","SocketEvents","createSession","currentSession","stopPingInterval","startPingInterval","send","clearAllTimeouts","handleSocketConnected","setTransport","handleSocketDisconnected","connectSocket","payload","fulfill","reject","credentials","getCredentials","externalId","getExternalId","queryParams","socketUrl","event","message","handleSocketEvent","error","ws","addMessage","data","toggleTypingStatus","eventId","disconnect","isConnected","callbacks","setCallbacks","initialize","updateSessionId","sessionId","startChat","configData","authenticate","messages","control","session","getSession","searchParams","sendMessage","cleanup","disconnectSocket","isTyping","transport","text","html","context","attachments","meta","isEmpty","userMessage","isSocketConnected","socketSend","loadingMessage","headers","fetchEventSource","response","errorMessage","lastIndex","updatedMsg","msg","index","_i","supervisorMessage","_j","_k","newBotMessage","lastMsg","_l","_o","_p","AUTHENTICATION_ERROR","INITIALIZATION_ERROR","endpoint","errorPayload","getHistory","fetchRequest","_a","uploadAttachment","file","onProgress","onComplete","token","xhr","formData","uploadUrl","percentComplete","deleteAttachment","mediaId","deleteUrl","getAttachment","pathname","method","body","rtcConfig","setCallCallbacks","track","setCallStatus","status","_b","setCallError","pingMessage","sendEvent","handlePong","getUserMedia","createPeerConnection","candidateJson","err","newState","disconnectCall","handleCallServerEvent","action","handleAnswer","handleConnected","handleIceCandidate","handleRenegotiationOffer","answer","candidate","offer","startCall","toggleMute","audioTrack","getLocalStream","getInboundAudioEnergy","stats","report","getOutboundAudioEnergy"],"mappings":";AAIO,SAASA,IAAS;AACvB,QAAMC,IAAY,KAAK,IAAG,GACpBC,IAAQ,IAAI,WAAW,EAAE;AAC/B,SAAO,gBAAgBA,CAAK,GAG5BA,EAAM,CAAC,IAAKD,KAAa,KAAM,KAC/BC,EAAM,CAAC,IAAKD,KAAa,KAAM,KAC/BC,EAAM,CAAC,IAAKD,KAAa,KAAM,KAC/BC,EAAM,CAAC,IAAKD,KAAa,KAAM,KAC/BC,EAAM,CAAC,IAAKD,KAAa,IAAK,KAC9BC,EAAM,CAAC,IAAID,IAAY,KAGvBC,EAAM,CAAC,IAAKA,EAAM,CAAC,IAAI,KAAQ,KAG/BA,EAAM,CAAC,IAAKA,EAAM,CAAC,IAAI,KAAQ;AAE/B,QAAMC,IAAM,CAAC,GAAGD,CAAK,EAAE,IAAI,CAACE,MAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC1E,SAAO,GAAGD,EAAI,MAAM,GAAG,CAAC,CAAC,IAAIA,EAAI,MAAM,GAAG,EAAE,CAAC,IAAIA,EAAI,MAAM,IAAI,EAAE,CAAC,IAAIA,EAAI;AAAA,IACxE;AAAA,IACA;AAAA,EACJ,CAAG,IAAIA,EAAI,MAAM,EAAE,CAAC;AACpB;AAEO,SAASE,KAAc;AAC5B,MAAI,aAAa,QAAQ,cAAc;AACrC,WAAO,aAAa,QAAQ,cAAc;AAG5C,QAAMC,IAAWN,EAAM;AACvB,sBAAa,QAAQ,gBAAgBM,CAAQ,GACtCA;AACT;AAqBO,eAAeC,GAAMC,GAAI;AAC9B,SAAO,IAAI,QAAQ,CAACC,MAAY,WAAWA,GAASD,CAAE,CAAC;AACzD;AAEO,SAASE,GAAeC,GAAS;AACtC,MAAIC;AACJ,MAAI;AACF,UAAMC,IAAM,IAAI,IAAIF,CAAO;AAC3B,IAAAC,IAAc,WAAWC,EAAI,QAAQ,GAAGA,EAAI,QAAQ;AAAA,EACtD,SAAQC,GAAA;AAAA,EAER;AACA,SAAOF;AACT;AAEO,SAASG,GAAkBJ,GAAS;AACzC,MAAIK;AACJ,MAAI;AACF,UAAMH,IAAM,IAAI,IAAIF,CAAO;AAC3B,IAAAK,IAAiB,SAASH,EAAI,QAAQ,GAAGA,EAAI,QAAQ;AAAA,EACvD,SAAQC,GAAA;AAAA,EAER;AACA,SAAOE;AACT;AAEO,SAASC,GAAsBN,GAAS;AAC7C,MAAIK;AACJ,MAAI;AACF,UAAMH,IAAM,IAAI,IAAIF,CAAO;AAC3B,IAAAK,IAAiB,SAASH,EAAI,QAAQ,GAAGA,EAAI,QAAQ;AAAA,EACvD,SAAQC,GAAA;AAAA,EAER;AACA,SAAOE;AACT;AC1FY,MAACE,IAAgB;AAAA,EAC3B,WAAW;AAAA;AAAA,EACX,MAAM;AAAA;AAAA,EACN,YAAY;AAAA;AAAA,EACZ,QAAQ;AAAA;AACV,GCKMC,KAAgB,KAChBC,KAAiB,KAeVC,IAAe;AAAA,EAC1B,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,KAAK;AACP;AAMA,SAASC,KAAgB;AACvB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,2BAA2B;AAAA,IAC3B,yBAAyB;AAAA,EAC7B;AACA;AAGA,IAAIC,IAAiBD,GAAa;AAKlC,SAASE,IAAmB;AAC1B,EAAID,EAAe,iBACjB,cAAcA,EAAe,YAAY,GACzCA,EAAe,eAAe;AAElC;AAKA,SAASE,KAAoB;AAC3BD,EAAAA,EAAgB,GAEhBD,EAAe,eAAe,YAAY,MAAM;AAC9C,IAAIA,EAAe,UAAUA,EAAe,OAAO,eAAe,UAAU,OAC1EG,EAAK,EAAE,MAAM,OAAM,CAAE,IAIrBF,EAAgB;AAAA,EAEpB,GAAGL,EAAa;AAClB;AAKA,SAASQ,KAAmB;AAC1BH,EAAAA,EAAgB,GACZD,EAAe,8BACjB,aAAaA,EAAe,yBAAyB,GACrDA,EAAe,4BAA4B,OAEzCA,EAAe,4BACjB,aAAaA,EAAe,uBAAuB,GACnDA,EAAe,0BAA0B;AAE7C;AAKA,SAASK,KAAwB;AAE/BL,EAAAA,EAAe,qBAAqB,IACpCM,EAAa,QAAQ;AACvB;AAKA,SAASC,KAA2B;AAElCP,EAAAA,EAAe,qBAAqB,IACpCM,EAAa,KAAK;AACpB;AAOO,SAASE,GAAcC,GAAS;AACrC,SAAO,IAAI,QAAQ,CAACC,GAASC,MAAW;AACtC,QACEX,EAAe,WACdA,EAAe,OAAO,eAAe,UAAU,cAC9CA,EAAe,OAAO,eAAe,UAAU,OACjD;AAEA,MAAAU,EAAQV,EAAe,OAAO,eAAe,UAAU,IAAI;AAC3D;AAAA,IACF;AAGA,UAAMY,IAAcC,EAAc;AAClC,QAAI,CAACD,KAAe,CAACA,EAAY,UAAU;AACzC,MAAAD,EAAO,IAAI,MAAM,mDAAmD,CAAC;AACrE;AAAA,IACF;AAEA,UAAMlB,IAAiBD,GAAkBoB,EAAY,QAAQ;AAC7D,QAAI,CAACnB,GAAgB;AACnB,MAAAkB;AAAA,QACE,IAAI;AAAA,UACF;AAAA,QACV;AAAA,MACA;AACM;AAAA,IACF;AAEA,UAAMG,IAAaC,EAAa,GAC1BC,IAAc,IAAI,gBAAgB;AAAA,MACtC,YAAAF;AAAA,IACN,CAAK;AAED,IAAIL,EAAQ,aACVO,EAAY,IAAI,aAAaP,EAAQ,SAAS,GAE5CA,EAAQ,aACVO,EAAY,IAAI,aAAaP,EAAQ,SAAS,GAE5CG,EAAY,SACdI,EAAY,IAAI,SAASJ,EAAY,KAAK;AAG5C,UAAMK,IAAY,GAAGxB,CAAc,IAAIuB,EAAY,UAAU;AAC7DhB,IAAAA,EAAe,SAAS,IAAI,UAAUiB,CAAS,GAE/CjB,EAAe,OAAO,SAAS,MAAM;AAEnCA,MAAAA,EAAe,sBAAsB,IACrCK,GAAqB,GACrBF,EAAK,EAAE,MAAM,OAAM,CAAE,GACrB,aAAaH,EAAe,uBAAuB,GACnDE,GAAiB,GACjBQ,EAAQ,EAAI;AAAA,IACd,GAEAV,EAAe,OAAO,YAAY,CAACkB,MAAU;AAC3C,YAAMC,IAAU,KAAK,MAAMD,EAAM,IAAI;AACrC,MAAAE,GAAkBD,CAAO;AAAA,IAC3B,GAEAnB,EAAe,OAAO,UAAU,CAACqB,MAAU;AAEzC,MAAAf,EAAa,KAAK,GAClBK,EAAOU,CAAK;AAAA,IACd,GAEArB,EAAe,OAAO,UAAU,CAACsB,MAAO;AAGtC,MAAIA,EAAG,WAAWtB,EAAe,WAC3BsB,EAAG,SAAS,SAEVtB,EAAe,sBACjBO,GAAwB,IAExBgB,EAAW;AAAA,QACT,WAAW;AAAA,QACX,MAAM;AAAA,QACN,YAAW,oBAAI,KAAI,GAAG,YAAW;AAAA,MAC/C,CAAa,GAEH,aAAavB,EAAe,uBAAuB,IAGrDA,EAAe,SAAS,MACxBI,GAAgB;AAAA,IAEpB,GAEKJ,EAAe,wBAClBA,EAAe,0BAA0B,WAAW,MAAM;AAExD,MAAAuB,EAAW;AAAA,QACT,WAAW;AAAA,QACX,MAAM;AAAA,QACN,YAAW,oBAAI,KAAI,GAAG,YAAW;AAAA,MAC3C,CAAS,GACDZ,EAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,IACjD,GAAGd,EAAc;AAAA,EAErB,CAAC;AACH;AAMO,SAASM,EAAKqB,GAAM;AAEzB,EAAIxB,EAAe,sBAAsB,CAACA,EAAe,UAGzDA,EAAe,OAAO,KAAK,KAAK,UAAU,EAAE,GAAGwB,GAAM,SAASA,EAAK,WAAW/C,EAAM,EAAE,CAAE,CAAC;AAC3F;AA0CA,SAAS2C,GAAkBF,GAAO;AAGhC,UAAQA,EAAM,MAAI;AAAA,IAChB,KAAK,QAAQ;AACX,MAAIlB,EAAe,sBACjBK,GAAqB,GAEnBL,EAAe,6BACjB,aAAaA,EAAe,yBAAyB,GAEvDA,EAAe,4BAA4B,WAAW,MAAM;AAE1D,QAAAO,GAAwB;AAAA,MAC1B,GAAGX,KAAgB,GAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAKE,EAAa,QAAQ;AACxB,MAAA2B,EAAmB,EAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK3B,EAAa,aAAa;AAC7B,MAAA2B,EAAmB,EAAK;AACxB;AAAA,IACF;AAAA,IACA,KAAK3B,EAAa,SAAS;AACzB,YAAM,EAAE,SAAA4B,GAAS,MAAAF,MAASN;AAC1B,MAAKQ,KACHH,EAAW;AAAA,QACT,GAAGC;AAAA,QACH,MAAM;AAAA,QACN,YAAW,oBAAI,KAAI,GAAG,YAAW;AAAA,MAC3C,CAAS;AAEH;AAAA,IACF;AAAA,IACA,KAAK1B,EAAa,KAAK;AACrB6B,MAAAA,GAAU;AACV;AAAA,IACF;AAAA,EAGJ;AACA;AAcO,SAASA,KAAa;AAE3B,EAAI3B,EAAe,UACjBA,EAAe,OAAO,MAAM,GAAI,GAElCA,EAAe,sBAAsB,IACrCI,GAAgB,GAChBJ,EAAe,SAAS,MACxBM,EAAa,KAAK;AACpB;AAMO,SAASsB,KAAc;AAC5B,SACE5B,EAAe,WAAW,QAC1BA,EAAe,OAAO,eAAe,UAAU,QAC/C,CAACA,EAAe;AAEpB;ACpTA,SAASD,GAAc8B,IAAY,IAAI;AACrC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,UAAU,CAAA;AAAA,IACV,WAAAA;AAAA,IACA,WAAW;AAAA,IACX,SAAS;AAAA,EACb;AACA;AAGA,IAAI7B,IAAiBD,GAAa;AAM3B,SAAS+B,GAAaD,GAAW;AACtC7B,EAAAA,EAAe,YAAY,EAAE,GAAGA,EAAe,WAAW,GAAG6B,EAAS;AACxE;AAMO,SAASE,GAAWnB,GAAa;AAEtCZ,EAAAA,EAAe,cAAcY,GACzBA,EAAY,UACdZ,EAAe,gBAAgB;AAEnC;AAMO,SAASa,IAAiB;AAC/B,SAAOb,EAAe;AACxB;AAMO,SAASgC,GAAgBC,GAAW;;AACzC,EAAIA,KAAaA,MAAcjC,EAAe,cAC5CA,EAAe,YAAYiC,IAC3BjC,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2CiC;AAE/C;AASO,eAAeC,GAAUzB,IAAU,IAAI;AAC5C,MAAI;AAGF,QAAI0B,IAAa;AACjB,IAAKnC,EAAe,gBAKlBmC,IAAanC,EAAe,cAJ5BmC,IAAa,MAAMC,GAAapC,EAAe,WAAW,GAC1DA,EAAe,gBAAgB,IAC/BA,EAAe,aAAamC;AAK9B,QAAIE,IAAW,CAAA,GACXC,IAAU;AAEd,QAAI7B,EAAQ,WAAW;AACrB,YAAM8B,IAAU,MAAMC,GAAW/B,EAAQ,SAAS;AAClD,MAAA4B,IAAWE,EAAQ,UACnBD,IAAUC,EAAQ,WAAW;AAAA,IAC/B;AAEA,UAAME,IAAe,IAAI,gBAAe;AACxC,WAAKzC,EAAe,YAAY,SAC9ByC,EAAa,IAAI,cAAc1B,GAAe,GAEhDf,EAAe,SAAS,GAAGb;AAAA,MACzBa,EAAe,YAAY;AAAA,IACjC,CAAK,IAAIyC,EAAa,UAAU,IAC5BzC,EAAe,YAAYS,EAAQ,WACnCT,EAAe,WAAWqC,GAC1BrC,EAAe,UAAUsC,GAErBA,MAAY,WAEdI,GAAY,EAAE,MAAM,IAAI,MAAM,IAAI,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC,GAK7C;AAAA,MACL,WAAW1C,EAAe;AAAA,MAC1B,UAAAqC;AAAA,MACA,SAAAC;AAAA,MACA,YAAAH;AAAA,IACN;AAAA,EACE,SAASd,GAAO;AAEdsB,UAAAA,GAAO,GACDtB;AAAA,EACR;AACF;AAKO,SAASM,KAAa;AAC3BgB,EAAAA,GAAO;AACT;AAKA,SAASA,KAAU;AACjB,EAAI3C,EAAe,mBACjBA,EAAe,gBAAgB,MAAK,GAEtC4C,GAAgB;AAEhB,QAAM,EAAE,WAAAf,GAAW,aAAAjB,MAAgBZ;AACnCA,EAAAA,IAAiBD,GAAc8B,CAAS,GACxC7B,EAAe,cAAcY;AAG/B;AAEO,SAASG,IAAgB;;AAC9B,UAAIf,IAAAA,EAAe,gBAAfA,QAAAA,EAA4B,aACvBA,EAAe,YAAY,aAE7BlB,GAAW;AACpB;AAMO,SAASyC,EAAWJ,GAAS;;AAClCnB,EAAAA,EAAe,WAAW,CAAC,GAAGA,EAAe,UAAUmB,CAAO,IAC9DnB,KAAAA,IAAAA,EAAe,WAAU,iBAAzBA,QAAAA,EAAAA,KAAAA,GAAwCmB;AAC1C;AAEO,SAASM,EAAmBoB,GAAU;;AAC3C7C,GAAAA,KAAAA,IAAAA,EAAe,WAAU,aAAzBA,QAAAA,EAAAA,KAAAA,GAAoC6C;AACtC;AAMO,SAASvC,EAAawC,GAAW;;AAEtC9C,EAAAA,EAAe,YAAY8C,IAC3B9C,KAAAA,IAAAA,EAAe,WAAU,sBAAzBA,QAAAA,EAAAA,KAAAA,GAA6C8C;AAC/C;AAeO,SAASJ,GAAY,EAAE,MAAAK,GAAM,MAAAC,GAAM,SAAAC,GAAS,aAAAC,GAAa,MAAAC,KAAQ;AACtE,SAAO,IAAI,QAAQ,CAACjE,GAASyB,MAAW;AACrC,KAAC,YAAY;;AACZ,UAAI;AACF,cAAMyC,IAAU,CAACL,KAAQ,CAACC,KAAQ,EAACE,KAAA,QAAAA,EAAa;AAGhD,YAAI,CAACE,GAAS;AACZ,gBAAMC,IAAc;AAAA,YAClB,MAAM1D,EAAc;AAAA,YACpB,MAAAoD;AAAA,YACA,MAAAC;AAAA,YACA,YAAW,oBAAI,KAAI,GAAG,YAAW;AAAA,YACjC,aAAAE;AAAA,YACA,MAAAC;AAAA,UACZ;AACU,UAAA5B,EAAW8B,CAAW,GACtB,MAAMrE,GAAM,GAAG;AAAA,QACjB;AAGA,YAAIgB,EAAe,cAAc,YAAYsD,GAAiB,GAAI;AAChEC,UAAAA,EAAW;AAAA,YACT,MAAM;AAAA,YACN,MAAM;AAAA,cACJ,MAAAR;AAAA,cACA,MAAAC;AAAA,YACd;AAAA,UACA,CAAW,GACD9D,EAAQc,EAAe,SAAS;AAChC;AAAA,QACF;AAEA,YAAIA,EAAe,YAAY,SAAS;AACtC,gBAAMwD,IAAiB;AAAA,YACrB,MAAM7D,EAAc;AAAA,YACpB,MAAM;AAAA,YACN,SAAS;AAAA,UACrB;AACU,UAAA4B,EAAWiC,CAAc;AAAA,QAC3B;AAEA,cAAMlE,IAAM,IAAI,IAAIU,EAAe,MAAM;AACzC,QAAIA,EAAe,aACjBV,EAAI,aAAa,IAAI,aAAaU,EAAe,SAAS,GAExDA,EAAe,aACjBV,EAAI,aAAa,IAAI,aAAaU,EAAe,SAAS,GAG5DA,EAAe,eAAe,QAG9BA,EAAe,kBAAkB,IAAI,gBAAe;AAEpD,cAAMyD,IAAU;AAAA,UACd,gBAAgB;AAAA,QAC1B;AACQ,SAAIzD,IAAAA,EAAe,gBAAfA,QAAAA,EAA4B,UAC9ByD,EAAQ,gBAAgB,UAAUzD,EAAe,YAAY,KAAK,KAGpE,MAAM0D,GAAiBpE,EAAI,YAAY;AAAA,UACrC,QAAQ;AAAA,UACR,SAAAmE;AAAA,UACA,MAAML,IACFD,IACA,KAAK,UAAU;AAAA,YACb,SAASJ;AAAA,YACT,MAAAC;AAAA,YACA,SAAAC;AAAA,YACA,aAAAC;AAAA,UAChB,CAAe;AAAA,UACL,QAAQlD,EAAe,gBAAgB;AAAA,UACvC,gBAAgB;AAAA,UAChB,QAAQ,OAAO2D,MAAa;AAC1B,gBAAI,CAACA,EAAS;AAEZ,oBAAM,IAAI,MAAM,wBAAwB;AAAA,UAE5C;AAAA,UACA,WAAW,CAACA,MAAa;;AAEvB,kBAAMnC,IAAO,KAAK,MAAMmC,EAAS,IAAI;AAErC,gBAAIA,EAAS,UAAU;AACrB3D,cAAAA,EAAe,YAAYwB,EAAK,WAChCxB,EAAe,YAAYwB,EAAK,WAE5BA,EAAK,YACPxB,EAAe,UAAUwB,EAAK,UAC9BxB,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2CwB,EAAK;AAAA,qBAEzCmC,EAAS,UAAU;AAE5BnD,cAAAA,GAAc;AAAA,gBACZ,WAAWR,EAAe;AAAA,gBAC1B,WAAWwB,EAAK;AAAA,cAChC,CAAe;AAAA,qBACQmC,EAAS,UAAU;AAC5B,cAAInC,EAAK,YACPxB,EAAe,UAAUwB,EAAK,UAC9BxB,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2CwB,EAAK;AAAA,qBAEzCA,EAAK,OAAO;AACrB,oBAAMoC,IACJpC,EAAK,SAAS,OAAOA,EAAK,SAAU,WAChCA,EAAK,QACL,mCACAqC,IAAY7D,EAAe,SAAS,SAAS,GAE7C8D,IAAa;AAAA,gBACjB,GAFc9D,EAAe,SAAS6D,CAAS;AAAA,gBAG/C,SAAS;AAAA,gBACT,WAAWD;AAAA,cAC3B;AACc5D,cAAAA,EAAe,WAAWA,EAAe,SAAS;AAAA,gBAAI,CAAC+D,GAAKC,OAC1DA,OAAUH,IAAYC,IAAaC;AAAA,cACnD,IACc/D,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2C6D,GAAWC,IACtDnD,EAAO,IAAI,MAAMiD,CAAY,CAAC;AAAA,YAChC,WAAWD,EAAS,UAAU,QAAQ;AAEpC,oBAAME,IAAY7D,EAAe,SAAS,SAAS,GAE7C8D,IAAa;AAAA,gBACjB,GAFc9D,EAAe,SAAS6D,CAAS;AAAA,gBAG/C,SAAS;AAAA,gBACT,MAAM;AAAA,cACtB;AACc7D,cAAAA,EAAe,WAAWA,EAAe,SAAS;AAAA,gBAAI,CAAC+D,GAAKC,MAC1DA,MAAUH,IAAYC,IAAaC;AAAA,cACnD,IACc/D,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2C6D,GAAWC,IACtD5E,EAAQc,EAAe,SAAS;AAAA,YAClC,WAAWwB,EAAK,YAAY,YAAayC,IAAAzC,EAAK,gBAAL,gBAAAyC,EAAkB,UAAS,GAAG;AAErE,kBAAIzC,EAAK,SAAS7B,EAAc,YAAY;AAC1C,sBAAMuE,IAAoB;AAAA,kBACxB,MAAMvE,EAAc;AAAA,kBACpB,MAAM6B,EAAK;AAAA,kBACX,aAAaA,EAAK;AAAA,kBAClB,SAASA,EAAK;AAAA,kBACd,MAAM;AAAA,gBACxB;AACgB,gBAAAD,EAAW2C,CAAiB,GAC5BhF,EAAQc,EAAe,SAAS,GAGhCA,EAAe,aAAYmE,IAAA3C,EAAK,cAAL,OAAA2C,IAAkBnE,EAAe,WAC5DA,EAAe,aAAYoE,IAAA5C,EAAK,cAAL,OAAA4C,IAAkBpE,EAAe;AAC5D;AAAA,cACF;AAGA,kBAAIwB,EAAK,aAAa;AACpB,oBAAIxB,EAAe,iBAAiB;AAClCA,kBAAAA,EAAe,eAAewB,EAAK;AAAA,yBAC1BA,EAAK,aAAaxB,EAAe,cAAc;AACxDA,kBAAAA,EAAe,eAAewB,EAAK;AACnC,wBAAM6C,IAAgB;AAAA,oBACpB,MAAM1E,EAAc;AAAA,oBACpB,MAAM;AAAA,oBACN,SAAS;AAAA,kBAC7B;AACkB,kBAAA4B,EAAW8C,CAAa;AAAA,gBAC1B;AAAA;AAIF,oBAAMR,IAAY7D,EAAe,SAAS,SAAS,GAC7CsE,IAAUtE,EAAe,SAAS6D,CAAS,GAC3CC,IAAa;AAAA,gBACjB,GAAGQ;AAAA,gBACH,SAAS;AAAA,gBACT,OAAOA,EAAQ,QAAQ,MAAM9C,EAAK;AAAA,gBAClC,SAASA,EAAK;AAAA,gBACd,aAAaA,EAAK;AAAA,gBAClB,OAAM+C,IAAA/C,EAAK,SAAL,OAAA+C,IAAaD,EAAQ;AAAA,cAC3C;AACctE,cAAAA,EAAe,WAAWA,EAAe,SAAS;AAAA,gBAAI,CAAC+D,GAAKC,MAC1DA,MAAUH,IAAYC,IAAaC;AAAA,cACnD,IAEc/D,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2C6D,GAAWC,IAGtD9D,EAAe,aAAYwE,IAAAhD,EAAK,cAAL,OAAAgD,IAAkBxE,EAAe,WAC5DA,EAAe,aAAYyE,IAAAjD,EAAK,cAAL,OAAAiD,IAAkBzE,EAAe;AAAA,YAC9D;AAAA,UACF;AAAA,UACA,SAAS,CAACqB,MAAU;AAClB,kBAAMA;AAAA,UACR;AAAA,UACA,gBAAgB;AAAA,QAC1B,CAAS;AAAA,MACH,SAASA,GAAO;AAEd,cAAMuC,IAAe,mCACfC,IAAY7D,EAAe,SAAS,SAAS,GAC7CsE,IAAUtE,EAAe,SAAS6D,CAAS,GAC3CC,IAAa;AAAA,UACjB,GAAGQ;AAAA,UACH,SAAS;AAAA,UACT,WAAWA,EAAQ,OAAO,SAAYjD,EAAM,WAAWuC;AAAA,UACvD,MAAM;AAAA,QAChB;AACQ5D,QAAAA,EAAe,WAAWA,EAAe,SAAS;AAAA,UAAI,CAAC+D,GAAKC,MAC1DA,MAAUH,IAAYC,IAAaC;AAAA,QAC7C,IACQ/D,KAAAA,IAAAA,EAAe,WAAU,oBAAzBA,QAAAA,EAAAA,KAAAA,GAA2C6D,GAAWC,IACtDnD,EAAOU,CAAK;AAAA,MACd;AAAA,IACF,GAAC;AAAA,EACH,CAAC;AACH;ACvbA,MAAMqD,KAAuB,8CACvBC,IAAuB;AAOtB,eAAevC,GAAa3B,GAAS;AAC1C,QAAM,EAAE,UAAAmE,EAAQ,IAAKnE,GACfnB,IAAM,GAAGsF,CAAQ,WAEjBjB,IAAW,MAAM,MAAMrE,GAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IACtB;AAAA,EACA,CAAG;AAED,MAAI,CAACqE,EAAS,IAAI;AAChB,UAAMkB,IAAe,MAAMlB,EAAS,KAAI;AACxC,UAAM,IAAI,OAAMkB,KAAA,gBAAAA,EAAc,UAASH,EAAoB;AAAA,EAC7D;AAKA,UAHY,MAAMf,EAAS,KAAI,GACd;AAGnB;AAMO,eAAemB,KAAa;AACjC,QAAM9D,IAAc,IAAI,gBAAgB;AAAA,IACtC,YAAYD,EAAa;AAAA,EAC7B,CAAG,GACK4C,IAAW,MAAMoB,GAAa,aAAa/D,EAAY,SAAQ,CAAE,IAAI,KAAK;AAEhF,MAAI,CAAC2C,EAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAGlE,SAAOA,EAAS,KAAI;AACtB;AAOO,eAAenB,GAAWP,GAAW;;AAC1C,QAAMjB,IAAc,IAAI,gBAAgB;AAAA,IACtC,WAAAiB;AAAA,EACJ,CAAG,GACK0B,IAAW,MAAMoB,GAAa,YAAY/D,EAAY,SAAQ,CAAE,IAAI,KAAK;AAE/E,MAAI,CAAC2C,EAAS;AACZ,UAAM,IAAI,MAAM,iDAAiD;AAGnE,QAAMnC,IAAO,MAAMmC,EAAS,KAAI,GAC1BrB,IAAUd,KAAA,gBAAAA,EAAM,SAChBa,MAAY2C,IAAAxD,KAAA,gBAAAA,EAAM,YAAN,OAAAwD,IAAiB,CAAA,GAAI,IAAI,CAACjB,OAAS;AAAA,IACnD,IAAIA,EAAI;AAAA,IACR,MAAMA,EAAI;AAAA,IACV,MAAMA,EAAI,eACNpE,EAAc,YACdoE,EAAI;AAAA,IACR,WAAWA,EAAI;AAAA,IACf,OAAOA,EAAI;AAAA,IACX,aAAaA,EAAI;AAAA,IACjB,SAASA,EAAI;AAAA,IACb,MAAM;AAAA,EACV,EAAI;AAEF,SAAO,EAAE,SAAAzB,GAAS,UAAAD,EAAQ;AAC5B;AASO,SAAS4C,GAAiBC,GAAMC,GAAYC,GAAY;AAC7D,QAAMxE,IAAcC,EAAc,GAC5B,EAAE,UAAA+D,GAAU,OAAAS,EAAK,IAAKzE,KAAe,CAAA;AAE3C,MAAI,CAACgE,GAAU;AACb,UAAMvD,IAAQ,IAAI,MAAMsD,CAAoB;AAC5C,WAAIS,KACFA,EAAW/D,GAAO,IAAI,GAEjB;AAAA,EACT;AAEA,QAAMiE,IAAM,IAAI,eAAc,GACxBC,IAAW,IAAI,SAAQ;AAC7B,EAAAA,EAAS,OAAO,QAAQL,CAAI;AAE5B,QAAMM,IAAY,GAAGZ,CAAQ;AAE7B,SAAAU,EAAI,KAAK,QAAQE,CAAS,GACtBH,KACFC,EAAI,iBAAiB,iBAAiB,UAAUD,CAAK,EAAE,GAIrDF,KACFG,EAAI,OAAO,iBAAiB,YAAY,CAACpE,MAAU;AACjD,QAAIA,EAAM,kBAAkB;AAC1B,YAAMuE,IAAmBvE,EAAM,SAASA,EAAM,QAAS;AACvD,MAAAiE,EAAWM,GAAiBvE,EAAM,QAAQA,EAAM,KAAK;AAAA,IACvD;AAAA,EACF,CAAC,GAIHoE,EAAI,iBAAiB,QAAQ,MAAM;AACjC,QAAIA,EAAI,UAAU,OAAOA,EAAI,SAAS;AACpC,UAAI;AACF,cAAM3B,IAAW,KAAK,MAAM2B,EAAI,YAAY;AAC5C,QAAIF,KACFA,EAAW,MAAMzB,CAAQ;AAAA,MAE7B,SAAStC,GAAO;AACd,QAAI+D,KACFA,EAAW,IAAI,MAAM,0BAA0B,GAAG,IAAI;AAAA,MAE1D;AAAA;AAEA,MAAIA,KACFA,EAAW,IAAI,MAAM,6BAA6BE,EAAI,MAAM,EAAE,GAAG,IAAI;AAAA,EAG3E,CAAC,GAEDA,EAAI,iBAAiB,SAAS,MAAM;AAClC,IAAIF,KACFA,EAAW,IAAI,MAAM,6BAA6B,GAAG,IAAI;AAAA,EAE7D,CAAC,GAEDE,EAAI,iBAAiB,SAAS,MAAM;AAClC,IAAIF,KACFA,EAAW,IAAI,MAAM,gBAAgB,GAAG,IAAI;AAAA,EAEhD,CAAC,GAEDE,EAAI,KAAKC,CAAQ,GAEVD;AACT;AAOO,eAAeI,GAAiBC,GAAS;AAC9C,QAAM/E,IAAcC,EAAc,GAC5B,EAAE,UAAA+D,GAAU,OAAAS,EAAK,IAAKzE,KAAe,CAAA;AAE3C,MAAI,CAACgE;AACH,UAAM,IAAI,MAAMD,CAAoB;AAGtC,QAAMiB,IAAY,GAAGhB,CAAQ,WAAWe,CAAO,IAEzClC,IAAU,CAAA;AAChB,EAAI4B,MACF5B,EAAQ,gBAAgB,UAAU4B,CAAK;AAGzC,QAAM1B,IAAW,MAAM,MAAMiC,GAAW;AAAA,IACtC,QAAQ;AAAA,IACR,SAAAnC;AAAA,EACJ,CAAG;AAED,MAAI,CAACE,EAAS;AACZ,UAAM,IAAI,MAAM,6BAA6BA,EAAS,MAAM,EAAE;AAGhE,SAAO,EAAE,SAAS,GAAI;AACxB;AAOO,SAASkC,GAAcF,GAAS;AACrC,QAAM/E,IAAcC,EAAc,GAC5B,EAAE,UAAA+D,EAAQ,IAAKhE,KAAe,CAAA;AAEpC,MAAI,CAACgE;AACH,UAAM,IAAI,MAAMD,CAAoB;AAGtC,SAAO,GAAGC,CAAQ,WAAWe,CAAO;AACtC;AASA,eAAeZ,GAAae,GAAUC,IAAS,OAAOC,IAAO,MAAM;AACjE,QAAMpF,IAAcC,EAAc,GAE5B,EAAE,UAAA+D,GAAU,OAAAS,EAAK,IAAKzE,KAAe,CAAA;AAC3C,MAAI,CAACgE;AACH,UAAM,IAAI,MAAMD,CAAoB;AAGtC,QAAMrF,IAAM,GAAGsF,CAAQ,GAAGkB,CAAQ,IAE5BrC,IAAU;AAAA,IACd,gBAAgB;AAAA,EACpB;AACE,SAAI4B,MACF5B,EAAQ,gBAAgB,UAAU4B,CAAK,KAGlC,MAAM/F,GAAK;AAAA,IAChB,SAAAmE;AAAA,IACA,QAAAsC;AAAA,IACA,MAAMC,IAAO,KAAK,UAAUA,CAAI,IAAI;AAAA,EACxC,CAAG;AACH;AC5MA,SAASjG,GAAc8B,IAAY,IAAI;AACrC,SAAO;AAAA,IACL,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,cAAc;AAAA,IACd,WAAAA;AAAA,IACA,oBAAoB,CAAA;AAAA,IACpB,4BAA4B,CAAA;AAAA,EAChC;AACA;AAGA,IAAI7B,IAAiBD,GAAa;AAElC,MAAMkG,KAAY;AAAA,EAChB,YAAY,CAAC,EAAE,MAAM,+BAA8B,GAAI,EAAE,MAAM,gCAA+B,CAAE;AAClG;AAMO,SAASC,GAAiBrE,GAAW;AAC1C,EAAA7B,EAAe,YAAY,EAAE,GAAGA,EAAe,WAAW,GAAG6B,EAAS;AACxE;AAKA,SAASc,KAAU;AACjB,EAAI3C,EAAe,mBACjBA,EAAe,eAAe,MAAK,GACnCA,EAAe,iBAAiB,OAG9BA,EAAe,gBACjBA,EAAe,YAAY,UAAS,EAAG,QAAQ,CAACmG,MAAUA,EAAM,KAAI,CAAE,GACtEnG,EAAe,cAAc,OAG3BA,EAAe,iBACjBA,EAAe,eAAe,OAG5BA,EAAe,gBACjBA,EAAe,YAAY,YAAY,MACnCA,EAAe,YAAY,cAC7BA,EAAe,YAAY,WAAW,YAAYA,EAAe,WAAW,GAE9EA,EAAe,cAAc,OAG3BA,EAAe,WACjBA,EAAe,OAAO,MAAK,GAC3BA,EAAe,SAAS,OAG1BC,EAAgB;AAEhB,QAAM4B,IAAY7B,EAAe;AACjC,EAAAA,IAAiBD,GAAc8B,CAAS;AAG1C;AAMA,SAASuE,EAAcC,GAAQ;;AAC7B,EAAArG,EAAe,aAAaqG,IAC5BC,KAAAtB,IAAAhF,EAAe,WAAU,iBAAzB,QAAAsG,EAAA,KAAAtB,GAAwCqB;AAC1C;AAMA,SAASE,EAAalF,GAAO;;AAC3B,GAAAiF,KAAAtB,IAAAhF,EAAe,WAAU,gBAAzB,QAAAsG,EAAA,KAAAtB,GAAuC3D;AACzC;AAKA,SAASpB,IAAmB;AAC1B,EAAID,EAAe,iBACjB,cAAcA,EAAe,YAAY,GACzCA,EAAe,eAAe;AAElC;AAKA,SAASE,KAAoB;AAC3B,EAAAD,EAAgB,GAEhBD,EAAe,eAAe,YAAY,MAAM;AAC9C,QAAIA,EAAe,UAAUA,EAAe,OAAO,eAAe,UAAU,MAAM;AAChF,MAAAA,EAAe;AACf,YAAMwG,IAAc;AAAA,QAClB,MAAM;AAAA,QACN,WAAW,KAAK,IAAG;AAAA,QACnB,OAAOxG,EAAe;AAAA,MAC9B;AACM,MAAAyG,EAAUD,CAAW;AAAA,IAEvB;AAEE,MAAAvG,EAAgB;AAAA,EAEpB,GAAG,GAAK;AACV;AAKA,SAASyG,KAAa;AACpB,EAAA1G,EAAe,eAAe,KAAK,IAAG;AAExC;AAMA,SAASyG,EAAUhG,GAAS;AAC1B,EAAKT,EAAe,UAIhBA,EAAe,OAAO,eAAe,UAAU,QAKnDA,EAAe,OAAO,KAAK,KAAK,UAAUS,CAAO,CAAC;AACpD;AAKA,eAAekG,KAAe;AAC5B,MAAI;AACF,IAAA3G,EAAe,cAAc,MAAM,UAAU,aAAa,aAAa;AAAA,MACrE,OAAO;AAAA,MACP,OAAO;AAAA,IACb,CAAK;AAAA,EAEH,SAASqB,GAAO;AAEd,UAAMA;AAAA,EACR;AACF;AAKA,SAASuF,KAAuB;AAC9B,EAAA5G,EAAe,iBAAiB,IAAI,kBAAkBiG,EAAS,GAE/DjG,EAAe,eAAe,iBAAiB,CAACkB,MAAU;AACxD,QAAIA,EAAM,WAAW;AACnB,YAAM2F,IAAgB,KAAK,UAAU3F,EAAM,SAAS;AAEpD,MAAIlB,EAAe,kBAAkBA,EAAe,eAAe,oBACjEyG,EAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,WAAWI;AAAA,QACvB;AAAA,MACA,CAAS,IAGD7G,EAAe,mBAAmB,KAAK6G,CAAa;AAAA,IAGxD;AAAA,EACF,GAEA7G,EAAe,eAAe,UAAU,CAACkB,MAAU;AAEjD,IAAAlB,EAAe,eAAekB,EAAM,QAAQ,CAAC,GAExClB,EAAe,gBAClBA,EAAe,cAAc,SAAS,cAAc,OAAO,GAC3DA,EAAe,YAAY,WAAW,IACtCA,EAAe,YAAY,WAAW,IACtC,SAAS,KAAK,YAAYA,EAAe,WAAW,IAEtDA,EAAe,YAAY,YAAYA,EAAe,cAEtDA,EAAe,YACZ,KAAI,EACJ,KAAK,MAAA;AAAA,KAA4C,EACjD,MAAM,CAAC8G,MAAG;AAAA,KAA4C;AAAA,EAC3D,GAEA9G,EAAe,eAAe,0BAA0B,MAAM;AAC5D,UAAM+G,IAAW/G,EAAe,eAAe;AAG/C,IAAI+G,MAAa,cACfX,EAAc,WAAW,KAChBW,MAAa,kBAAkBA,MAAa,cACrDX,EAAc,cAAc,GAC5BY,GAAc;AAAA,EAElB,GAEAhH,EAAe,eAAe,6BAA6B,MAAM;AAAA,EAEjE;AACF;AAMA,SAASQ,GAAcC,GAAS;AAC9B,SAAO,IAAI,QAAQ,CAACC,GAASC,MAAW;AACtC,QACEX,EAAe,WACdA,EAAe,OAAO,eAAe,UAAU,cAC9CA,EAAe,OAAO,eAAe,UAAU,OACjD;AAEA,MAAAU,EAAQV,EAAe,OAAO,eAAe,UAAU,IAAI;AAC3D;AAAA,IACF;AAGA,UAAMY,IAAcC,EAAc;AAClC,QAAI,CAACD,KAAe,CAACA,EAAY,UAAU;AACzC,MAAAD,EAAO,IAAI,MAAM,mDAAmD,CAAC;AACrE;AAAA,IACF;AAGA,UAAMlB,IAAiBC,GAAsBkB,EAAY,QAAQ;AACjE,QAAI,CAACnB,GAAgB;AACnB,MAAAkB;AAAA,QACE,IAAI;AAAA,UACF;AAAA,QACV;AAAA,MACA;AACM;AAAA,IACF;AAEA,UAAMG,IAAaC,EAAa,GAC1BC,IAAc,IAAI,gBAAgB;AAAA,MACtC,YAAAF;AAAA,IACN,CAAK;AACD,IAAIL,EAAQ,aACVO,EAAY,IAAI,aAAaP,EAAQ,SAAS,GAE5CG,EAAY,SACdI,EAAY,IAAI,SAASJ,EAAY,KAAK;AAG5C,UAAMK,IAAY,GAAGxB,CAAc,IAAIuB,EAAY,UAAU;AAC7D,IAAAhB,EAAe,SAAS,IAAI,UAAUiB,CAAS,GAE/CjB,EAAe,OAAO,SAAS,CAACkB,MAAU;AAExC,MAAAhB,GAAiB,GACjBQ,EAAQ,EAAI;AAAA,IACd,GAEAV,EAAe,OAAO,YAAY,CAACkB,MAAU;AAC3C,YAAMM,IAAO,KAAK,MAAMN,EAAM,IAAI;AAClC,MAAA+F,GAAsBzF,CAAI;AAAA,IAC5B,GAEAxB,EAAe,OAAO,UAAU,CAACqB,MAAU;AAEzC,MAAA+E,EAAc,OAAO,GACrBG,EAAalF,EAAM,WAAW,yBAAyB,GACvDV,EAAOU,CAAK;AAAA,IACd,GAEArB,EAAe,OAAO,UAAU,CAACkB,MAAU;AAEzC,MAAAjB,EAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAMA,SAASgH,GAAsBC,GAAQ;AAGrC,UAAQA,EAAO,MAAI;AAAA,IACjB,KAAK;AACH,MAAAR,GAAU;AACV;AAAA,IAEF,KAAK;AACH,MAAAS,GAAaD,EAAO,IAAI;AACxB;AAAA,IAEF,KAAK;AACH,MAAAE,GAAgBF,EAAO,IAAI;AAC3B;AAAA,IAEF,KAAK;AACH,MAAAG,GAAmBH,EAAO,IAAI;AAC9B;AAAA,IAEF,KAAK;AACH,MAAAI,GAAyBJ,EAAO,IAAI;AACpC;AAAA,IACF,KAAK;AACH,MAAAF,GAAc;AACd;AAAA,IACF,KAAK;AACH,MAAAZ,EAAc,OAAO,GACrBG,EAAaW,EAAO,SAAS,yBAAyB;AACtD;AAAA,IAEF;AAEE;AAAA,EACN;AACA;AAMA,SAASE,GAAgB5F,GAAM;AAE7B,EAAAxB,EAAe,YAAYwB,EAAK,WAEhCQ,GAAgBR,EAAK,SAAS;AAChC;AAMA,eAAe2F,GAAa3F,GAAM;AAChC,MAAI;AAGF,QAAIxB,EAAe,gBAAgB;AACjC,YAAMuH,IAAS,IAAI,sBAAsB;AAAA,QACvC,MAAM;AAAA,QACN,KAAK/F,EAAK;AAAA,MAClB,CAAO;AAED,YAAMxB,EAAe,eAAe,qBAAqBuH,CAAM;AAI/D,iBAAWV,KAAiB7G,EAAe;AACzC,QAAAyG,EAAU;AAAA,UACR,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,WAAWI;AAAA,UACvB;AAAA,QACA,CAAS;AAGH,MAAA7G,EAAe,qBAAqB,CAAA;AAGpC,iBAAW6G,KAAiB7G,EAAe;AACzC,YAAI;AACF,gBAAMwH,IAAY,IAAI,gBAAgB,KAAK,MAAMX,CAAa,CAAC;AAC/D,gBAAM7G,EAAe,eAAe,gBAAgBwH,CAAS;AAAA,QAE/D,SAASV,GAAK;AAAA,QAEd;AAEF,MAAA9G,EAAe,6BAA6B,CAAA;AAAA,IAC9C;AAAA,EACF,SAASqB,GAAO;AAAA,EAEhB;AACF;AAMA,eAAegG,GAAmB7F,GAAM;AACtC,MAAI;AACF,QAAIxB,EAAe,gBAAgB;AAEjC,UAAI,CAACA,EAAe,eAAe,mBAAmB;AAEpD,QAAAA,EAAe,2BAA2B,KAAKwB,EAAK,SAAS;AAE7D;AAAA,MACF;AACA,YAAMgG,IAAY,IAAI,gBAAgB,KAAK,MAAMhG,EAAK,SAAS,CAAC;AAChE,YAAMxB,EAAe,eAAe,gBAAgBwH,CAAS;AAAA,IAE/D;AAAA,EACF,SAASnG,GAAO;AAAA,EAEhB;AACF;AAMA,eAAeiG,GAAyB9F,GAAM;AAC5C,MAAI;AAGF,QAAIxB,EAAe,gBAAgB;AACjC,YAAMyH,IAAQ,IAAI,sBAAsB;AAAA,QACtC,MAAM;AAAA,QACN,KAAKjG,EAAK;AAAA,MAClB,CAAO;AAED,YAAMxB,EAAe,eAAe,qBAAqByH,CAAK;AAG9D,YAAMF,IAAS,MAAMvH,EAAe,eAAe,aAAY;AAC/D,YAAMA,EAAe,eAAe,oBAAoBuH,CAAM,GAE9Dd,EAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,KAAKc,EAAO;AAAA,QACtB;AAAA,MACA,CAAO;AAAA,IACH;AAAA,EACF,SAASlG,GAAO;AAAA,EAEhB;AACF;AAMO,eAAeqG,GAAUjH,IAAU,IAAI;AAC5C,MAAI;AACF,QAAIT,EAAe,eAAe,gBAAgBA,EAAe,eAAe;AAE9E;AAIF,IAAAoG,EAAc,YAAY,GAC1BG,EAAa,IAAI,GAEjBvG,EAAe,YAAYS,EAAQ,WAEnC,MAAMkG,GAAY,GAElBC,GAAoB,GAEpB5G,EAAe,YAAY,UAAS,EAAG,QAAQ,CAACmG,MAAU;AACxD,MAAAnG,EAAe,eAAe,SAASmG,GAAOnG,EAAe,WAAW;AAAA,IAE1E,CAAC,GACD,MAAMQ,GAAcC,CAAO;AAC3B,UAAMgH,IAAQ,MAAMzH,EAAe,eAAe,YAAW;AAC7D,UAAMA,EAAe,eAAe,oBAAoByH,CAAK,GAE7DhB,EAAU;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,KAAKgB,EAAM;AAAA,MACnB;AAAA,IACA,CAAK;AAAA,EAGH,SAASpG,GAAO;AAGd,IAAA+E,EAAc,OAAO,GACrBG,EAAalF,EAAM,WAAW,yBAAyB,GACvDsB,GAAO;AAAA,EACT;AACF;AAKO,SAASqE,KAAiB;AAC/B,EAAAP,EAAU;AAAA,IACR,MAAM;AAAA,EACV,CAAG,GACGzG,EAAe,WACjBA,EAAe,OAAO,MAAK,GAC3BA,EAAe,SAAS,OAE1BoG,EAAc,cAAc,GACxBpG,EAAe,mBACjBA,EAAe,eAAe,MAAK,GACnCA,EAAe,iBAAiB,OAE9BA,EAAe,gBACjBA,EAAe,YAAY,UAAS,EAAG,QAAQ,CAACmG,MAAUA,EAAM,KAAI,CAAE,GACtEnG,EAAe,cAAc,OAE/B2C,GAAO;AACT;AAMO,SAASgF,KAAa;AAC3B,MAAI3H,EAAe,aAAa;AAC9B,UAAM4H,IAAa5H,EAAe,YAAY,eAAc,EAAG,CAAC;AAChE,QAAI4H;AACF,aAAAA,EAAW,UAAU,CAACA,EAAW,SACjC5H,EAAe,UAAU,CAAC4H,EAAW,SAE9B5H,EAAe;AAAA,EAE1B;AACA,SAAO;AACT;AAMO,SAAS6H,KAAiB;AAC/B,SAAO7H,EAAe;AACxB;AAMO,SAAS8H,KAAwB;AACtC,SAAO,IAAI,QAAQ,CAAC5I,GAASyB,MAAW;AACtC,QAAI,CAACX,EAAe,gBAAgB;AAClC,MAAAW,EAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC;AAAA,IACF;AACA,IAAAX,EAAe,eACZ,SAAQ,EACR,KAAK,CAAC+H,MAAU;AACf,MAAAA,EAAM,QAAQ,CAACC,MAAW;AACxB,QAAIA,EAAO,QAAQ,iBACjB9I,EAAQ8I,EAAO,gBAAgB;AAAA,MAEnC,CAAC,GACDrH,EAAO,IAAI,MAAM,4BAA4B,CAAC;AAAA,IAChD,CAAC,EACA,MAAM,CAACmG,MAAQ;AACd,MAAAnG,EAAOmG,CAAG;AAAA,IACZ,CAAC;AAAA,EACL,CAAC;AACH;AAMO,SAASmB,KAAyB;AACvC,SAAO,IAAI,QAAQ,CAAC/I,GAASyB,MAAW;AACtC,QAAI,CAACX,EAAe,gBAAgB;AAClC,MAAAW,EAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC;AAAA,IACF;AACA,IAAAX,EAAe,eACZ,SAAQ,EACR,KAAK,CAAC+H,MAAU;AACf,MAAAA,EAAM,QAAQ,CAACC,MAAW;AACxB,QAAIA,EAAO,QAAQ,kBACjB9I,EAAQ8I,EAAO,gBAAgB;AAAA,MAEnC,CAAC,GACDrH,EAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,IACjD,CAAC,EACA,MAAM,CAACmG,MAAQ;AACd,MAAAnG,EAAOmG,CAAG;AAAA,IACZ,CAAC;AAAA,EACL,CAAC;AACH;"}
|
package/package.json
CHANGED
package/src/chat.js
CHANGED
|
@@ -230,7 +230,7 @@ export function getTransport() {
|
|
|
230
230
|
* @param {{ text: string, html?: string }} message
|
|
231
231
|
* @returns {Promise<string>}
|
|
232
232
|
*/
|
|
233
|
-
export function sendMessage({ text, html, context, attachments }) {
|
|
233
|
+
export function sendMessage({ text, html, context, attachments, meta }) {
|
|
234
234
|
return new Promise((resolve, reject) => {
|
|
235
235
|
;(async () => {
|
|
236
236
|
try {
|
|
@@ -243,7 +243,8 @@ export function sendMessage({ text, html, context, attachments }) {
|
|
|
243
243
|
text,
|
|
244
244
|
html,
|
|
245
245
|
timestamp: new Date().toISOString(),
|
|
246
|
-
attachments
|
|
246
|
+
attachments,
|
|
247
|
+
meta
|
|
247
248
|
}
|
|
248
249
|
addMessage(userMessage)
|
|
249
250
|
await sleep(200)
|
|
@@ -295,7 +296,7 @@ export function sendMessage({ text, html, context, attachments }) {
|
|
|
295
296
|
method: 'POST',
|
|
296
297
|
headers,
|
|
297
298
|
body: isEmpty
|
|
298
|
-
?
|
|
299
|
+
? meta
|
|
299
300
|
: JSON.stringify({
|
|
300
301
|
message: text,
|
|
301
302
|
html,
|