@opencx/widget 3.0.17 → 3.0.19
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/designs.cjs +48 -48
- package/dist/designs.cjs.map +1 -1
- package/dist/designs.js +3515 -3506
- package/dist/designs.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/react.cjs +1 -1
- package/dist/react.js +2 -2
- package/dist/src/designs/react/components/SuggestedReplies.d.ts +1 -6
- package/dist/src/designs/translation/translation.types.d.ts +1 -1
- package/dist/src/headless/core/context/message.ctx.d.ts +8 -6
- package/dist/src/headless/core/context/session.ctx.d.ts +9 -3
- package/dist/src/headless/core/sdk/schema.d.ts +2 -5
- package/dist/src/headless/react/hooks/useMessages.d.ts +1 -1
- package/dist/src/headless/react/hooks/useSessions.d.ts +0 -1
- package/dist/{useUploadFiles-CPuop4TB.cjs → useUploadFiles-CyBcsF-U.cjs} +2 -2
- package/dist/useUploadFiles-CyBcsF-U.cjs.map +1 -0
- package/dist/{useUploadFiles-LkWYJwRc.js → useUploadFiles-sY8364dS.js} +81 -82
- package/dist/useUploadFiles-sY8364dS.js.map +1 -0
- package/dist/widget.ctx-C4fHGXaH.cjs +2 -0
- package/dist/widget.ctx-C4fHGXaH.cjs.map +1 -0
- package/dist/{widget.ctx-DddwF0U6.js → widget.ctx-DkhYPIAY.js} +115 -89
- package/dist/widget.ctx-DkhYPIAY.js.map +1 -0
- package/dist-embed/script.js +47 -47
- package/dist-embed/script.js.map +1 -1
- package/package.json +1 -1
- package/dist/useUploadFiles-CPuop4TB.cjs.map +0 -1
- package/dist/useUploadFiles-LkWYJwRc.js.map +0 -1
- package/dist/widget.ctx-DddwF0U6.js.map +0 -1
- package/dist/widget.ctx-S-HHGJkM.cjs +0 -2
- package/dist/widget.ctx-S-HHGJkM.cjs.map +0 -1
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
1
|
+
var O = Object.defineProperty;
|
|
2
|
+
var M = (a) => {
|
|
3
3
|
throw TypeError(a);
|
|
4
4
|
};
|
|
5
|
-
var
|
|
6
|
-
var s = (a, t, e) =>
|
|
7
|
-
var h = (a, t, e) => (
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import { v4 as
|
|
12
|
-
const
|
|
5
|
+
var L = (a, t, e) => t in a ? O(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
|
|
6
|
+
var s = (a, t, e) => L(a, typeof t != "symbol" ? t + "" : t, e), R = (a, t, e) => t.has(a) || M("Cannot " + e);
|
|
7
|
+
var h = (a, t, e) => (R(a, t, "read from private field"), e ? e.call(a) : t.get(a)), y = (a, t, e) => t.has(a) ? M("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(a) : t.set(a, e), S = (a, t, e, i) => (R(a, t, "write to private field"), i ? i.call(a, e) : t.set(a, e), e);
|
|
8
|
+
import T from "axios";
|
|
9
|
+
import E from "openapi-fetch";
|
|
10
|
+
import D from "lodash.isequal";
|
|
11
|
+
import { v4 as _ } from "uuid";
|
|
12
|
+
const q = (a) => {
|
|
13
13
|
console.log(a.error);
|
|
14
|
-
},
|
|
15
|
-
const t =
|
|
14
|
+
}, B = (a) => {
|
|
15
|
+
const t = E({
|
|
16
16
|
baseUrl: a.baseUrl
|
|
17
17
|
}), e = {
|
|
18
18
|
onRequest: a.onRequest,
|
|
19
19
|
onResponse: a.onResponse,
|
|
20
|
-
onError: a.onError ||
|
|
20
|
+
onError: a.onError || q
|
|
21
21
|
};
|
|
22
22
|
return t.use(e), t;
|
|
23
23
|
};
|
|
24
|
-
class
|
|
24
|
+
class H {
|
|
25
25
|
constructor({
|
|
26
26
|
config: t
|
|
27
27
|
}) {
|
|
@@ -40,7 +40,7 @@ class q {
|
|
|
40
40
|
s(this, "createOpenAPIClient", ({
|
|
41
41
|
baseUrl: t,
|
|
42
42
|
headers: e
|
|
43
|
-
}) =>
|
|
43
|
+
}) => B({
|
|
44
44
|
baseUrl: t,
|
|
45
45
|
onRequest: ({ request: i }) => {
|
|
46
46
|
Object.entries(e).forEach(([n, r]) => {
|
|
@@ -51,7 +51,7 @@ class q {
|
|
|
51
51
|
s(this, "createAxiosUploadClient", ({
|
|
52
52
|
baseUrl: t,
|
|
53
53
|
headers: e
|
|
54
|
-
}) =>
|
|
54
|
+
}) => T.create({
|
|
55
55
|
baseURL: `${t}/backend/widget/v2/upload`,
|
|
56
56
|
headers: e
|
|
57
57
|
}));
|
|
@@ -122,13 +122,13 @@ class q {
|
|
|
122
122
|
this.client = this.createOpenAPIClient({ baseUrl: e, headers: i }), this.uploadFileClient = this.createAxiosUploadClient({ baseUrl: e, headers: i });
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
var l,
|
|
126
|
-
class
|
|
125
|
+
var l, f;
|
|
126
|
+
class p {
|
|
127
127
|
constructor(t) {
|
|
128
128
|
s(this, "subscribers", /* @__PURE__ */ new Set());
|
|
129
|
-
|
|
129
|
+
y(this, l);
|
|
130
130
|
s(this, "initialState");
|
|
131
|
-
|
|
131
|
+
y(this, f);
|
|
132
132
|
s(this, "lifecycleListeners", /* @__PURE__ */ new Map());
|
|
133
133
|
s(this, "emitLifecycle", (t, e) => {
|
|
134
134
|
const i = this.lifecycleListeners.get(t);
|
|
@@ -181,7 +181,7 @@ class m {
|
|
|
181
181
|
this.emitLifecycle("beforeUpdate", {
|
|
182
182
|
previousState: h(this, l),
|
|
183
183
|
nextState: t
|
|
184
|
-
}),
|
|
184
|
+
}), D(h(this, l), t) || (S(this, l, t), S(this, f, Date.now()), this.emitLifecycle("stateChange", { state: t }), this.notifySubscribers(t)), this.emitLifecycle("afterUpdate", { state: t });
|
|
185
185
|
});
|
|
186
186
|
// TODO make this provide prev state
|
|
187
187
|
s(this, "setPartial", (t) => {
|
|
@@ -201,12 +201,12 @@ class m {
|
|
|
201
201
|
s(this, "reset", () => {
|
|
202
202
|
this.set(this.initialState);
|
|
203
203
|
});
|
|
204
|
-
s(this, "lastUpdated", () => h(this,
|
|
205
|
-
S(this, l, t), this.initialState = t, S(this,
|
|
204
|
+
s(this, "lastUpdated", () => h(this, f));
|
|
205
|
+
S(this, l, t), this.initialState = t, S(this, f, Date.now()), this.emitLifecycle("init", { initialState: h(this, l) });
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
-
l = new WeakMap(),
|
|
209
|
-
class
|
|
208
|
+
l = new WeakMap(), f = new WeakMap();
|
|
209
|
+
class G {
|
|
210
210
|
constructor({
|
|
211
211
|
config: t,
|
|
212
212
|
api: e
|
|
@@ -238,16 +238,16 @@ class B {
|
|
|
238
238
|
}
|
|
239
239
|
});
|
|
240
240
|
var i, n, r;
|
|
241
|
-
this.config = t, this.api = e, this.state = new
|
|
241
|
+
this.config = t, this.api = e, this.state = new p({
|
|
242
242
|
contact: (i = t.user) != null && i.token ? { token: (n = t.user) == null ? void 0 : n.token } : null,
|
|
243
243
|
isCreatingUnverifiedContact: !1,
|
|
244
244
|
isErrorCreatingUnverifiedContact: !1
|
|
245
245
|
}), !((r = t.user) != null && r.token) && !t.collectUserData && this.autoCreateUnverifiedUser();
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
class
|
|
248
|
+
class x {
|
|
249
249
|
constructor() {
|
|
250
|
-
s(this, "state", new
|
|
250
|
+
s(this, "state", new p({
|
|
251
251
|
isPolling: !1,
|
|
252
252
|
isError: !1
|
|
253
253
|
}));
|
|
@@ -278,10 +278,10 @@ class M {
|
|
|
278
278
|
});
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
-
function
|
|
282
|
-
return
|
|
281
|
+
function P() {
|
|
282
|
+
return _();
|
|
283
283
|
}
|
|
284
|
-
class
|
|
284
|
+
class j {
|
|
285
285
|
constructor({
|
|
286
286
|
config: t,
|
|
287
287
|
api: e,
|
|
@@ -290,12 +290,13 @@ class H {
|
|
|
290
290
|
s(this, "config");
|
|
291
291
|
s(this, "api");
|
|
292
292
|
s(this, "contactCtx");
|
|
293
|
-
s(this, "
|
|
294
|
-
s(this, "
|
|
293
|
+
s(this, "activeSessionPoller", new x());
|
|
294
|
+
s(this, "sessionsRefresher", new x());
|
|
295
|
+
s(this, "sessionState", new p({
|
|
295
296
|
session: null,
|
|
296
297
|
isCreatingSession: !1
|
|
297
298
|
}));
|
|
298
|
-
s(this, "sessionsState", new
|
|
299
|
+
s(this, "sessionsState", new p({
|
|
299
300
|
data: [],
|
|
300
301
|
cursor: void 0,
|
|
301
302
|
isLastPage: !1,
|
|
@@ -307,17 +308,17 @@ class H {
|
|
|
307
308
|
}));
|
|
308
309
|
/** Clears the session and stops polling */
|
|
309
310
|
s(this, "reset", async () => {
|
|
310
|
-
this.sessionState.reset(), this.
|
|
311
|
+
this.sessionState.reset(), this.activeSessionPoller.reset();
|
|
311
312
|
});
|
|
312
|
-
s(this, "
|
|
313
|
+
s(this, "registerActiveSessionPolling", () => {
|
|
313
314
|
this.sessionState.subscribe(({ session: t }) => {
|
|
314
|
-
t != null && t.id ? this.
|
|
315
|
+
t != null && t.id ? this.activeSessionPoller.startPolling(async (e) => {
|
|
315
316
|
const { data: i } = await this.api.getSession({
|
|
316
317
|
sessionId: t.id,
|
|
317
318
|
abortSignal: e
|
|
318
319
|
});
|
|
319
320
|
i && this.sessionState.setPartial({ session: i });
|
|
320
|
-
}, 1e3) : this.
|
|
321
|
+
}, 1e3) : this.activeSessionPoller.reset();
|
|
321
322
|
});
|
|
322
323
|
});
|
|
323
324
|
s(this, "registerInitialSessionsFetch", () => {
|
|
@@ -325,10 +326,20 @@ class H {
|
|
|
325
326
|
const t = async () => {
|
|
326
327
|
this.sessionsState.setPartial({ didStartInitialFetch: !0 }), await this.loadMoreSessions(), this.sessionsState.setPartial({ isInitialFetchLoading: !1 });
|
|
327
328
|
};
|
|
328
|
-
(e = this.contactCtx.state.get().contact) != null && e.token && !this.sessionsState.get().didStartInitialFetch && t(), this.contactCtx.state.subscribe(({ contact: i }) => {
|
|
329
|
-
i != null && i.token && !this.sessionsState.get().didStartInitialFetch && t();
|
|
329
|
+
(e = this.contactCtx.state.get().contact) != null && e.token && !this.sessionsState.get().didStartInitialFetch && (t(), this.registerSessionsRefresher()), this.contactCtx.state.subscribe(({ contact: i }) => {
|
|
330
|
+
i != null && i.token && !this.sessionsState.get().didStartInitialFetch && (t(), this.registerSessionsRefresher());
|
|
330
331
|
});
|
|
331
332
|
});
|
|
333
|
+
s(this, "registerSessionsRefresher", () => {
|
|
334
|
+
this.sessionsRefresher.startPolling(async () => {
|
|
335
|
+
const { data: t } = await this.getSessions({ cursor: void 0 });
|
|
336
|
+
if (!t) return;
|
|
337
|
+
const e = [...t.items, ...this.sessionsState.get().data].filter(
|
|
338
|
+
(i, n, r) => n === r.findIndex((c) => i.id === c.id)
|
|
339
|
+
);
|
|
340
|
+
this.sessionsState.setPartial({ data: e });
|
|
341
|
+
}, 1e4);
|
|
342
|
+
});
|
|
332
343
|
s(this, "createSession", async () => {
|
|
333
344
|
var i, n;
|
|
334
345
|
this.sessionState.setPartial({ session: null, isCreatingSession: !0 });
|
|
@@ -339,30 +350,38 @@ class H {
|
|
|
339
350
|
});
|
|
340
351
|
return t ? (this.sessionState.setPartial({ session: t, isCreatingSession: !1 }), t) : (console.error("Failed to create session:", e), null);
|
|
341
352
|
});
|
|
353
|
+
/**
|
|
354
|
+
* Let's keep this private for now until we figure out how to do paginated fetching in tandem with the interval refreshing
|
|
355
|
+
*/
|
|
342
356
|
s(this, "loadMoreSessions", async () => {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
cursor: this.sessionsState.get().cursor,
|
|
347
|
-
filters: (i = this.config.user) != null && i.externalId ? {
|
|
348
|
-
external_id: this.config.user.externalId
|
|
349
|
-
} : {}
|
|
357
|
+
if (this.sessionsState.get().isLastPage) return;
|
|
358
|
+
const { data: t } = await this.getSessions({
|
|
359
|
+
cursor: this.sessionsState.get().cursor
|
|
350
360
|
});
|
|
351
361
|
if (t) {
|
|
352
|
-
const
|
|
353
|
-
(
|
|
362
|
+
const i = [...this.sessionsState.get().data, ...t.items].filter(
|
|
363
|
+
(n, r, c) => r === c.findIndex((d) => n.id === d.id)
|
|
354
364
|
);
|
|
355
365
|
this.sessionsState.setPartial({
|
|
356
|
-
data:
|
|
366
|
+
data: i,
|
|
357
367
|
cursor: t.next || void 0,
|
|
358
368
|
isLastPage: t.next === null
|
|
359
369
|
});
|
|
360
370
|
}
|
|
361
371
|
});
|
|
362
|
-
this
|
|
372
|
+
s(this, "getSessions", async ({ cursor: t }) => {
|
|
373
|
+
var e, i;
|
|
374
|
+
return (e = this.contactCtx.state.get().contact) != null && e.token ? await this.api.getSessions({
|
|
375
|
+
cursor: t,
|
|
376
|
+
filters: (i = this.config.user) != null && i.externalId ? {
|
|
377
|
+
external_id: this.config.user.externalId
|
|
378
|
+
} : {}
|
|
379
|
+
}) : { data: null };
|
|
380
|
+
});
|
|
381
|
+
this.config = t, this.api = e, this.contactCtx = i, this.registerActiveSessionPolling(), this.registerInitialSessionsFetch();
|
|
363
382
|
}
|
|
364
383
|
}
|
|
365
|
-
class
|
|
384
|
+
class u {
|
|
366
385
|
constructor({
|
|
367
386
|
config: t,
|
|
368
387
|
api: e,
|
|
@@ -371,11 +390,11 @@ class p {
|
|
|
371
390
|
s(this, "config");
|
|
372
391
|
s(this, "api");
|
|
373
392
|
s(this, "sessionCtx");
|
|
374
|
-
s(this, "poller", new
|
|
375
|
-
s(this, "state", new
|
|
393
|
+
s(this, "poller", new x());
|
|
394
|
+
s(this, "state", new p({
|
|
376
395
|
messages: [],
|
|
377
396
|
isSendingMessage: !1,
|
|
378
|
-
|
|
397
|
+
lastAIResMightSolveUserIssue: !1,
|
|
379
398
|
isInitialFetchLoading: !1
|
|
380
399
|
}));
|
|
381
400
|
s(this, "sendMessageAbortController", new AbortController());
|
|
@@ -390,56 +409,63 @@ class p {
|
|
|
390
409
|
});
|
|
391
410
|
});
|
|
392
411
|
s(this, "sendMessage", async (t) => {
|
|
393
|
-
var n, r, c, d,
|
|
412
|
+
var n, r, c, d, C, m, v, I, U;
|
|
394
413
|
this.sendMessageAbortController = new AbortController();
|
|
395
414
|
const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.sessionState.get().session) == null ? void 0 : n.assignee.kind) === "ai";
|
|
396
415
|
if (e && i) {
|
|
397
416
|
console.warn("Cannot send messages while awaiting AI response");
|
|
398
417
|
return;
|
|
399
418
|
}
|
|
400
|
-
this.state.setPartial({
|
|
419
|
+
this.state.setPartial({ lastAIResMightSolveUserIssue: !1 });
|
|
401
420
|
try {
|
|
402
421
|
this.state.setPartial({ isSendingMessage: !0 });
|
|
403
|
-
const b =
|
|
422
|
+
const b = u.toUserMessage(
|
|
404
423
|
t.content,
|
|
405
424
|
t.attachments || void 0
|
|
406
|
-
),
|
|
425
|
+
), k = this.state.get().messages;
|
|
407
426
|
if (this.state.setPartial({
|
|
408
|
-
messages: [...
|
|
427
|
+
messages: [...k, b]
|
|
409
428
|
}), !((r = this.sessionCtx.sessionState.get().session) != null && r.id) && !await this.sessionCtx.createSession()) {
|
|
410
429
|
console.error("Failed to create session");
|
|
411
430
|
return;
|
|
412
431
|
}
|
|
413
|
-
const
|
|
414
|
-
if (!
|
|
432
|
+
const A = (c = this.sessionCtx.sessionState.get().session) == null ? void 0 : c.id;
|
|
433
|
+
if (!A) return;
|
|
415
434
|
const { data: o } = await this.api.sendMessage(
|
|
416
435
|
{
|
|
417
436
|
uuid: b.id,
|
|
418
437
|
bot_token: this.config.token,
|
|
419
438
|
headers: this.config.headers,
|
|
420
439
|
query_params: this.config.queryParams,
|
|
421
|
-
session_id:
|
|
440
|
+
session_id: A,
|
|
422
441
|
user: (d = this.config.user) == null ? void 0 : d.data,
|
|
423
442
|
...t
|
|
424
443
|
},
|
|
425
444
|
this.sendMessageAbortController.signal
|
|
426
445
|
);
|
|
427
446
|
if (o != null && o.success) {
|
|
428
|
-
const
|
|
429
|
-
if (
|
|
447
|
+
const g = u.toBotMessage(o);
|
|
448
|
+
if (g) {
|
|
430
449
|
const w = this.state.get().messages;
|
|
431
450
|
if (!!w.some(
|
|
432
|
-
(F) => F.id ===
|
|
433
|
-
))
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
451
|
+
(F) => F.id === g.id
|
|
452
|
+
)) {
|
|
453
|
+
this.state.setPartial({
|
|
454
|
+
lastAIResMightSolveUserIssue: ((C = o.autopilotResponse) == null ? void 0 : C.mightSolveUserIssue) || ((m = o.uiResponse) == null ? void 0 : m.mightSolveUserIssue)
|
|
455
|
+
});
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
this.state.setPartial({
|
|
459
|
+
messages: [...w, g],
|
|
460
|
+
lastAIResMightSolveUserIssue: ((v = o.autopilotResponse) == null ? void 0 : v.mightSolveUserIssue) || ((I = o.uiResponse) == null ? void 0 : I.mightSolveUserIssue)
|
|
461
|
+
});
|
|
462
|
+
}
|
|
437
463
|
} else {
|
|
438
|
-
const
|
|
439
|
-
((
|
|
464
|
+
const g = u.toErrorMessage(
|
|
465
|
+
((U = o == null ? void 0 : o.error) == null ? void 0 : U.message) || "Unknown error occurred"
|
|
440
466
|
), w = this.state.get().messages;
|
|
441
467
|
this.state.setPartial({
|
|
442
|
-
messages: [...w,
|
|
468
|
+
messages: [...w, g]
|
|
443
469
|
});
|
|
444
470
|
}
|
|
445
471
|
} catch (b) {
|
|
@@ -457,8 +483,8 @@ class p {
|
|
|
457
483
|
abortSignal: e
|
|
458
484
|
});
|
|
459
485
|
if (n && n.length > 0) {
|
|
460
|
-
const c = this.state.get().messages, d = n.map(
|
|
461
|
-
(
|
|
486
|
+
const c = this.state.get().messages, d = n.map(u.mapHistoryToMessage).filter(
|
|
487
|
+
(C) => !c.some((m) => m.id === C.id)
|
|
462
488
|
);
|
|
463
489
|
this.state.setPartial({
|
|
464
490
|
messages: [...c, ...d]
|
|
@@ -504,7 +530,7 @@ class p {
|
|
|
504
530
|
}
|
|
505
531
|
static toUserMessage(t, e) {
|
|
506
532
|
return {
|
|
507
|
-
id:
|
|
533
|
+
id: P(),
|
|
508
534
|
type: "FROM_USER",
|
|
509
535
|
content: t,
|
|
510
536
|
deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -516,7 +542,7 @@ class p {
|
|
|
516
542
|
if (t.success && t.autopilotResponse)
|
|
517
543
|
return {
|
|
518
544
|
type: "FROM_BOT",
|
|
519
|
-
id: t.autopilotResponse.id ||
|
|
545
|
+
id: t.autopilotResponse.id || P(),
|
|
520
546
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
521
547
|
component: "bot_message",
|
|
522
548
|
data: {
|
|
@@ -527,7 +553,7 @@ class p {
|
|
|
527
553
|
const e = t.uiResponse.value;
|
|
528
554
|
return {
|
|
529
555
|
type: "FROM_BOT",
|
|
530
|
-
id:
|
|
556
|
+
id: P(),
|
|
531
557
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
532
558
|
component: e.name,
|
|
533
559
|
data: e.request_response
|
|
@@ -538,7 +564,7 @@ class p {
|
|
|
538
564
|
static toErrorMessage(t) {
|
|
539
565
|
return {
|
|
540
566
|
type: "FROM_BOT",
|
|
541
|
-
id:
|
|
567
|
+
id: P(),
|
|
542
568
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
543
569
|
component: "TEXT",
|
|
544
570
|
data: {
|
|
@@ -548,7 +574,7 @@ class p {
|
|
|
548
574
|
};
|
|
549
575
|
}
|
|
550
576
|
}
|
|
551
|
-
class
|
|
577
|
+
class X {
|
|
552
578
|
constructor({
|
|
553
579
|
contactCtx: t,
|
|
554
580
|
sessionCtx: e,
|
|
@@ -577,12 +603,12 @@ class G {
|
|
|
577
603
|
}
|
|
578
604
|
this.state.setPartial({ screen: "chat" });
|
|
579
605
|
});
|
|
580
|
-
this.state = new
|
|
606
|
+
this.state = new p({
|
|
581
607
|
screen: t.shouldCollectData() ? "welcome" : "sessions"
|
|
582
608
|
}), this.contactCtx = t, this.sessionCtx = e, this.resetChat = i, this.registerRoutingListener();
|
|
583
609
|
}
|
|
584
610
|
}
|
|
585
|
-
class
|
|
611
|
+
class K {
|
|
586
612
|
constructor({ config: t }) {
|
|
587
613
|
s(this, "config");
|
|
588
614
|
s(this, "api");
|
|
@@ -593,18 +619,18 @@ class J {
|
|
|
593
619
|
s(this, "resetChat", () => {
|
|
594
620
|
this.sessionCtx.reset(), this.messageCtx.reset();
|
|
595
621
|
});
|
|
596
|
-
this.config = t, this.api = new
|
|
622
|
+
this.config = t, this.api = new H({ config: t }), this.contactCtx = new G({
|
|
597
623
|
api: this.api,
|
|
598
624
|
config: this.config
|
|
599
|
-
}), this.sessionCtx = new
|
|
625
|
+
}), this.sessionCtx = new j({
|
|
600
626
|
config: this.config,
|
|
601
627
|
api: this.api,
|
|
602
628
|
contactCtx: this.contactCtx
|
|
603
|
-
}), this.messageCtx = new
|
|
629
|
+
}), this.messageCtx = new u({
|
|
604
630
|
config: this.config,
|
|
605
631
|
api: this.api,
|
|
606
632
|
sessionCtx: this.sessionCtx
|
|
607
|
-
}), this.routerCtx = new
|
|
633
|
+
}), this.routerCtx = new X({
|
|
608
634
|
contactCtx: this.contactCtx,
|
|
609
635
|
sessionCtx: this.sessionCtx,
|
|
610
636
|
resetChat: this.resetChat
|
|
@@ -612,7 +638,7 @@ class J {
|
|
|
612
638
|
}
|
|
613
639
|
}
|
|
614
640
|
export {
|
|
615
|
-
|
|
616
|
-
|
|
641
|
+
p as P,
|
|
642
|
+
K as W
|
|
617
643
|
};
|
|
618
|
-
//# sourceMappingURL=widget.ctx-
|
|
644
|
+
//# sourceMappingURL=widget.ctx-DkhYPIAY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.ctx-DkhYPIAY.js","sources":["../src/headless/core/sdk/index.ts","../src/headless/core/api.ts","../src/headless/core/utils/PrimitiveState.ts","../src/headless/core/context/contact.ctx.ts","../src/headless/core/utils/Poller.ts","../src/headless/core/utils/uuid.ts","../src/headless/core/context/session.ctx.ts","../src/headless/core/context/message.ctx.ts","../src/headless/core/context/router.ctx.ts","../src/headless/core/context/widget.ctx.ts"],"sourcesContent":["import createClient, { type Middleware } from \"openapi-fetch\";\nimport type { paths } from \"./schema\";\nimport type { components } from \"./schema\";\n\ntype Options = {\n baseUrl: string;\n onRequest?: Middleware[\"onRequest\"];\n onResponse?: Middleware[\"onResponse\"];\n onError?: Middleware[\"onError\"];\n};\n\nconst defaultOnError: Middleware[\"onError\"] = (onErrorOptions) => {\n console.log(onErrorOptions.error);\n};\n\nexport const basicClient = (options: Options) => {\n const client = createClient<paths>({\n baseUrl: options.baseUrl,\n });\n\n const middlewares: Middleware = {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n onError: options.onError || defaultOnError,\n };\n\n client.use(middlewares);\n return client;\n};\n\nexport type Endpoint = keyof paths;\nexport type Dto = components[\"schemas\"];\n","import axios, { type AxiosInstance, type AxiosRequestConfig } from \"axios\";\nimport { type Dto, type Endpoint, basicClient } from \"./sdk\";\nimport type { WidgetConfig } from \"./types/WidgetConfig\";\nimport type { SendMessageDto, VoteInputDto } from \"./types/schemas\";\n\nexport class ApiCaller {\n private client: ReturnType<typeof basicClient>;\n private uploadFileClient: AxiosInstance;\n private config: WidgetConfig;\n\n constructor({\n config,\n }: {\n config: WidgetConfig;\n }) {\n this.config = config;\n const { baseUrl, headers } = this.constructClientOptions(\n config.user?.token,\n );\n this.client = this.createOpenAPIClient({ baseUrl, headers });\n this.uploadFileClient = this.createAxiosUploadClient({ baseUrl, headers });\n }\n\n private constructClientOptions = (token: string | null | undefined) => {\n const baseUrl = this.config.apiUrl || \"https://api.open.cx\";\n const headers = {\n \"X-Bot-Token\": this.config.token,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n Authorization: token ? `Bearer ${token}` : undefined,\n };\n\n return { baseUrl, headers };\n };\n\n private createOpenAPIClient = ({\n baseUrl,\n headers,\n }: ReturnType<typeof this.constructClientOptions>) => {\n return basicClient({\n baseUrl,\n onRequest: ({ request }) => {\n Object.entries(headers).forEach(([key, value]) => {\n if (value) {\n request.headers.set(key, value);\n }\n });\n },\n });\n };\n private createAxiosUploadClient = ({\n baseUrl,\n headers,\n }: ReturnType<typeof this.constructClientOptions>) => {\n const uploadPath = \"/backend/widget/v2/upload\" satisfies Endpoint;\n return axios.create({\n baseURL: `${baseUrl}${uploadPath}`,\n headers,\n });\n };\n\n setAuthToken = (token: string) => {\n const { baseUrl, headers } = this.constructClientOptions(token);\n this.client = this.createOpenAPIClient({ baseUrl, headers });\n this.uploadFileClient = this.createAxiosUploadClient({ baseUrl, headers });\n };\n\n widgetPrelude = async () => {\n return await this.client.GET(\"/backend/widget/v2/prelude\", {\n params: { header: { \"X-Bot-Token\": this.config.token } },\n });\n };\n\n sendMessage = async (body: SendMessageDto, abortSignal?: AbortSignal) => {\n return await this.client.POST(\"/backend/widget/v2/chat/send\", {\n body,\n signal: abortSignal,\n });\n };\n\n getSessionHistory = async ({\n sessionId,\n lastMessageTimestamp,\n abortSignal,\n }: {\n sessionId: string;\n lastMessageTimestamp?: string;\n abortSignal: AbortSignal;\n }) => {\n const query = lastMessageTimestamp ? { lastMessageTimestamp } : undefined;\n return await this.client.GET(\n \"/backend/widget/v2/session/history/{sessionId}\",\n { params: { path: { sessionId }, query }, signal: abortSignal },\n );\n };\n\n createUnverifiedContact = async (body: Dto[\"CreateUnverifiedContactDto\"]) => {\n return await this.client.POST(\n \"/backend/widget/v2/contact/create-unverified\",\n {\n params: { header: { \"x-bot-token\": this.config.token } },\n body,\n },\n );\n };\n\n createSession = async (body: Dto[\"CreateWidgetChatSessionDto\"]) => {\n return await this.client.POST(\"/backend/widget/v2/create-session\", {\n body,\n });\n };\n\n getSession = async ({\n sessionId,\n abortSignal,\n }: { sessionId: string; abortSignal: AbortSignal }) => {\n return await this.client.GET(\"/backend/widget/v2/session/{sessionId}\", {\n params: { path: { sessionId } },\n signal: abortSignal,\n });\n };\n\n getSessions = async ({\n cursor,\n filters,\n abortSignal,\n }: {\n cursor: string | undefined;\n filters: Record<string, string>;\n abortSignal?: AbortSignal;\n }) => {\n return await this.client.GET(\"/backend/widget/v2/sessions\", {\n params: { query: { cursor, filters: JSON.stringify(filters) } },\n signal: abortSignal,\n });\n };\n\n uploadFile = async (\n file: {\n id: string;\n file: File;\n },\n config: Partial<AxiosRequestConfig> = {},\n ) => {\n const formData = new FormData();\n formData.append(\"file\", file.file);\n\n // Couldn't get this to work with the openapi client... dunno why...\n const { data } = await this.uploadFileClient.post<\n Dto[\"UploadWidgetFileResponseDto\"]\n >(\"\", formData, {\n headers: {\n \"Content-Type\": \"multipart/form-data\",\n },\n ...config,\n });\n return data;\n };\n\n vote = async (body: VoteInputDto) => {\n return await this.client.POST(\"/backend/widget/v2/chat/vote\", { body });\n };\n}\n","import isEqual from \"lodash.isequal\";\n\nexport type Subscriber<T> = (data: T) => void;\n\nexport enum LifecycleEvent {\n INIT = \"init\",\n STATE_CHANGE = \"stateChange\",\n BEFORE_UPDATE = \"beforeUpdate\",\n AFTER_UPDATE = \"afterUpdate\",\n DESTROY = \"destroy\",\n ERROR = \"error\",\n}\n\ntype LifecycleListener = (event: {\n type: LifecycleEvent;\n timestamp: number;\n data?: any;\n}) => void;\n\nexport class PrimitiveState<S> {\n private subscribers = new Set<Subscriber<S>>();\n #state: S;\n private initialState: S;\n #lastUpdated: number | null;\n private lifecycleListeners: Map<LifecycleEvent, Set<LifecycleListener>> =\n new Map();\n\n constructor(state: S) {\n this.#state = state;\n this.initialState = state;\n this.#lastUpdated = Date.now();\n this.emitLifecycle(LifecycleEvent.INIT, { initialState: this.#state });\n }\n\n private emitLifecycle = (event: LifecycleEvent, data?: any) => {\n const listeners = this.lifecycleListeners.get(event);\n if (listeners) {\n const eventData = {\n type: event,\n timestamp: Date.now(),\n data,\n };\n listeners.forEach((listener) => {\n try {\n listener(eventData);\n } catch {\n // ignore error\n }\n });\n }\n };\n\n private notifySubscribers = (state: S) => {\n const subscribersArray = Array.from(this.subscribers);\n subscribersArray.forEach((callback) => {\n try {\n callback(state);\n } catch (error) {\n this.emitLifecycle(LifecycleEvent.ERROR, { error });\n }\n });\n };\n\n /**\n * Subscribe to state changes\n * @param callback Function to call when state changes\n * @returns Unsubscribe function\n */\n subscribe = (callback: Subscriber<S>): (() => void) => {\n this.subscribers.add(callback);\n // Don't call the callback immediately with current state\n return () => {\n this.subscribers.delete(callback);\n };\n };\n\n onLifecycle = (\n event: LifecycleEvent,\n listener: LifecycleListener,\n ): (() => void) => {\n if (!this.lifecycleListeners.has(event)) {\n this.lifecycleListeners.set(event, new Set());\n }\n const listeners = this.lifecycleListeners.get(event)!;\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.lifecycleListeners.delete(event);\n }\n };\n };\n\n /** Get the current state */\n get = (): S => {\n return this.#state;\n };\n\n // TODO make this provide prev state\n /**\n * Set the state and notify subscribers if the state changes\n * @param newState The new state to set\n */\n set = (newState: S): void => {\n this.emitLifecycle(LifecycleEvent.BEFORE_UPDATE, {\n previousState: this.#state,\n nextState: newState,\n });\n\n if (!isEqual(this.#state, newState)) {\n this.#state = newState;\n this.#lastUpdated = Date.now();\n this.emitLifecycle(LifecycleEvent.STATE_CHANGE, { state: newState });\n this.notifySubscribers(newState);\n }\n\n this.emitLifecycle(LifecycleEvent.AFTER_UPDATE, { state: newState });\n };\n\n // TODO make this provide prev state\n setPartial = (_s: Partial<S>): void => {\n if (_s === undefined || _s === null) return;\n const newState = { ...this.#state, ..._s };\n this.set(newState);\n };\n\n /**\n * Clear all subscriptions\n */\n clear = (): void => {\n this.emitLifecycle(LifecycleEvent.DESTROY);\n this.subscribers = new Set(); // Create a new Set instead of just clearing\n this.lifecycleListeners = new Map();\n };\n\n reset = (): void => {\n this.set(this.initialState);\n };\n\n lastUpdated = (): number | null => {\n return this.#lastUpdated;\n };\n}\n","import { PrimitiveState } from \"../utils/PrimitiveState\";\nimport { ApiCaller } from \"../api\";\nimport { type WidgetConfig } from \"../types/WidgetConfig\";\nimport { type Dto } from \"../sdk\";\n\ntype ContactState = {\n contact: { token: string } | null;\n isCreatingUnverifiedContact: boolean;\n isErrorCreatingUnverifiedContact: boolean;\n};\n\nexport class ContactCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n state: PrimitiveState<ContactState>;\n\n constructor({\n config,\n api,\n }: {\n api: ApiCaller;\n config: WidgetConfig;\n }) {\n this.config = config;\n this.api = api;\n\n this.state = new PrimitiveState<ContactState>({\n contact: config.user?.token ? { token: config.user?.token } : null,\n isCreatingUnverifiedContact: false,\n isErrorCreatingUnverifiedContact: false,\n });\n\n if (!config.user?.token && !config.collectUserData) {\n this.autoCreateUnverifiedUser();\n }\n }\n\n shouldCollectData = (): boolean => {\n const currentState = this.state.get();\n\n if (!currentState.contact?.token && this.config.collectUserData) {\n return true;\n } else {\n return false;\n }\n };\n\n private autoCreateUnverifiedUser = async () => {\n await this.createUnverifiedContact({\n name: this.config.user?.data?.name || \"Anonymous\",\n email: this.config.user?.data?.email,\n });\n };\n\n createUnverifiedContact = async (\n payload: Dto[\"CreateUnverifiedContactDto\"],\n ): Promise<void> => {\n try {\n this.state.setPartial({\n isCreatingUnverifiedContact: true,\n isErrorCreatingUnverifiedContact: false,\n });\n\n const { data } = await this.api.createUnverifiedContact(payload);\n if (data?.token) {\n this.api.setAuthToken(data.token);\n // Set token in state after setting the token in the api handler\n this.state.setPartial({ contact: { token: data.token } });\n } else {\n this.state.setPartial({ isErrorCreatingUnverifiedContact: true });\n }\n } finally {\n this.state.setPartial({ isCreatingUnverifiedContact: false });\n }\n };\n}\n","import { PrimitiveState } from \"./PrimitiveState\";\n\nexport type PollingState = {\n isPolling: boolean;\n isError: boolean;\n};\n\nexport class Poller {\n state = new PrimitiveState<PollingState>({\n isPolling: false,\n isError: false,\n });\n private abortController = new AbortController();\n\n reset = () => {\n this.abortController.abort(\"Resetting poller\");\n this.stopPolling?.();\n this.stopPolling = null;\n };\n\n stopPolling: (() => void) | null = null;\n\n startPolling = (\n cb: (abortSignal: AbortSignal) => Promise<void>,\n interval: number,\n ) => {\n if (this.stopPolling) return;\n\n const timeouts: NodeJS.Timeout[] = [];\n\n const poll = async () => {\n this.abortController = new AbortController();\n this.state.setPartial({ isPolling: true });\n\n try {\n await cb(this.abortController.signal);\n } catch (error) {\n if (this.abortController.signal.aborted) {\n // If aborted, just return and do not schedule the nest poll\n return;\n } else {\n console.error(\"Failed to poll:\", error);\n this.state.setPartial({ isError: true });\n }\n } finally {\n this.state.setPartial({ isPolling: false });\n }\n\n // Another check to stop scheduling polls in case someone removes the early return in the catch above\n if (this.abortController.signal.aborted) {\n console.log(\"Poller aborted, not scheduling anymore\");\n } else {\n timeouts.push(setTimeout(poll, interval));\n }\n };\n\n poll();\n\n this.stopPolling = () => {\n timeouts.forEach(clearTimeout);\n this.state.reset();\n };\n };\n}\n","import { v4 as uuidv4 } from \"uuid\";\n\nexport function genUuid() {\n return uuidv4();\n}\n","import type { ApiCaller } from \"../api\";\nimport type { SessionDto } from \"../types/schemas\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport { Poller } from \"../utils/Poller\";\nimport { PrimitiveState } from \"../utils/PrimitiveState\";\nimport type { ContactCtx } from \"./contact.ctx\";\n\ntype SessionState = {\n /**\n * The currently selected session.\n * Can be null if no session is selected, or if in chat screen and the session is not created yet.\n */\n session: SessionDto | null;\n isCreatingSession: boolean;\n};\ntype SessionsState = {\n /** List of all user sessions */\n data: SessionDto[];\n /** A cursor to get the next page of sessions */\n cursor: string | undefined;\n /** Indicates if no more pages are left */\n isLastPage: boolean;\n /** Did fetch for the first time */\n didStartInitialFetch: boolean;\n isInitialFetchLoading: boolean;\n};\n\nexport class SessionCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n private contactCtx: ContactCtx;\n private activeSessionPoller = new Poller();\n private sessionsRefresher = new Poller();\n\n public sessionState = new PrimitiveState<SessionState>({\n session: null,\n isCreatingSession: false,\n });\n public sessionsState = new PrimitiveState<SessionsState>({\n data: [],\n cursor: undefined,\n isLastPage: false,\n didStartInitialFetch: false,\n /**\n * Initialize this as `true` so it always starts loading until the first fetch is done\n */\n isInitialFetchLoading: true,\n });\n\n constructor({\n config,\n api,\n contactCtx,\n }: { config: WidgetConfig; api: ApiCaller; contactCtx: ContactCtx }) {\n this.config = config;\n this.api = api;\n this.contactCtx = contactCtx;\n\n this.registerActiveSessionPolling();\n this.registerInitialSessionsFetch();\n }\n\n /** Clears the session and stops polling */\n reset = async () => {\n // Reset the session only, leave sessions as-is\n this.sessionState.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.activeSessionPoller.reset();\n };\n\n private registerActiveSessionPolling = () => {\n this.sessionState.subscribe(({ session }) => {\n if (session?.id) {\n this.activeSessionPoller.startPolling(async (abortSignal) => {\n const { data } = await this.api.getSession({\n sessionId: session.id,\n abortSignal,\n });\n data && this.sessionState.setPartial({ session: data });\n }, 1000);\n } else {\n this.activeSessionPoller.reset();\n }\n });\n };\n\n private registerInitialSessionsFetch = () => {\n const initialFetch = async () => {\n this.sessionsState.setPartial({ didStartInitialFetch: true });\n // Call this for the first time to get the first page of sessions\n await this.loadMoreSessions();\n this.sessionsState.setPartial({ isInitialFetchLoading: false });\n };\n\n // If the widget config was initially provided with a contact token, no state change would be triggered, so we just fetch\n if (\n this.contactCtx.state.get().contact?.token &&\n !this.sessionsState.get().didStartInitialFetch\n ) {\n initialFetch();\n this.registerSessionsRefresher();\n }\n\n // In other cases where auto authenticate is fired, the token would be eventually set in state, so we wait for it\n this.contactCtx.state.subscribe(({ contact }) => {\n if (contact?.token && !this.sessionsState.get().didStartInitialFetch) {\n initialFetch();\n this.registerSessionsRefresher();\n }\n });\n };\n\n private registerSessionsRefresher = () => {\n this.sessionsRefresher.startPolling(async () => {\n // Get the first page only (pass no `cursor`)\n const { data } = await this.getSessions({ cursor: undefined });\n if (!data) return;\n const sessions = [...data.items, ...this.sessionsState.get().data].filter(\n (s, i, self) => i === self.findIndex((_s) => s.id === _s.id),\n );\n this.sessionsState.setPartial({ data: sessions });\n }, 10000);\n };\n\n createSession = async () => {\n this.sessionState.setPartial({ session: null, isCreatingSession: true });\n\n const { data: session, error } = await this.api.createSession({\n customData: this.config.user?.externalId\n ? {\n external_id: this.config.user?.externalId,\n }\n : undefined,\n });\n if (session) {\n this.sessionState.setPartial({ session, isCreatingSession: false });\n return session;\n }\n\n console.error(\"Failed to create session:\", error);\n return null;\n };\n\n /**\n * Let's keep this private for now until we figure out how to do paginated fetching in tandem with the interval refreshing\n */\n private loadMoreSessions = async () => {\n if (this.sessionsState.get().isLastPage) return;\n\n const { data } = await this.getSessions({\n cursor: this.sessionsState.get().cursor,\n });\n\n if (data) {\n const allSessions = [...this.sessionsState.get().data, ...data.items];\n // TODO sort by updated at\n const deduped = allSessions.filter(\n (s, i, self) => i === self.findIndex((_s) => s.id === _s.id),\n );\n\n this.sessionsState.setPartial({\n data: deduped,\n cursor: data.next || undefined,\n isLastPage: data.next === null,\n });\n }\n };\n\n private getSessions = async ({ cursor }: { cursor: string | undefined }) => {\n if (!this.contactCtx.state.get().contact?.token) return { data: null };\n\n return await this.api.getSessions({\n cursor,\n filters: this.config.user?.externalId\n ? {\n external_id: this.config.user.externalId,\n }\n : {},\n });\n };\n}\n","import { ApiCaller } from \"../api\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport type { SafeOmit, SomeOptional } from \"../types/helpers\";\nimport type {\n BotMessageType,\n MessageType,\n UserMessageType,\n} from \"../types/messages\";\nimport type {\n MessageAttachmentType,\n MessageDto,\n SendMessageDto,\n SendMessageOutputDto,\n} from \"../types/schemas\";\nimport { Poller } from \"../utils/Poller\";\nimport { PrimitiveState } from \"../utils/PrimitiveState\";\nimport { genUuid } from \"../utils/uuid\";\nimport { SessionCtx } from \"./session.ctx\";\n\ntype MessageCtxState = {\n messages: MessageType[];\n isSendingMessage: boolean;\n lastAIResMightSolveUserIssue: boolean;\n isInitialFetchLoading: boolean;\n};\n\nexport class MessageCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n private sessionCtx: SessionCtx;\n private poller = new Poller();\n\n public state = new PrimitiveState<MessageCtxState>({\n messages: [],\n isSendingMessage: false,\n lastAIResMightSolveUserIssue: false,\n isInitialFetchLoading: false,\n });\n\n private sendMessageAbortController = new AbortController();\n\n constructor({\n config,\n api,\n sessionCtx,\n }: { config: WidgetConfig; api: ApiCaller; sessionCtx: SessionCtx }) {\n this.config = config;\n this.api = api;\n this.sessionCtx = sessionCtx;\n\n this.registerPolling();\n }\n\n reset = () => {\n this.sendMessageAbortController.abort(\"Resetting chat\");\n this.state.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.poller.reset();\n };\n\n private registerPolling = () => {\n this.sessionCtx.sessionState.subscribe(({ session }) => {\n if (session?.id) {\n this.poller.startPolling(async (abortSignal) => {\n await this.fetchAndSetHistory(session.id, abortSignal);\n }, 1000);\n } else {\n this.poller.reset();\n }\n });\n };\n\n sendMessage = async (\n input: SomeOptional<\n SafeOmit<SendMessageDto, \"bot_token\" | \"uuid\">,\n \"session_id\" | \"user\"\n >,\n ): Promise<void> => {\n this.sendMessageAbortController = new AbortController();\n /* ------------------------------------------------------ */\n /* Prevent sending while waiting for AI res */\n /* ------------------------------------------------------ */\n const isSending = this.state.get().isSendingMessage;\n const isAssignedToAI =\n this.sessionCtx.sessionState.get().session?.assignee.kind === \"ai\";\n if (isSending && isAssignedToAI) {\n console.warn(\"Cannot send messages while awaiting AI response\");\n return;\n }\n\n /* ------------------------------------------------------ */\n /* Clear last AI response might solve user issue */\n /* ------------------------------------------------------ */\n this.state.setPartial({ lastAIResMightSolveUserIssue: false });\n\n try {\n this.state.setPartial({ isSendingMessage: true });\n /* ------------------------------------------------------ */\n /* Optimistically add message to rendered messages */\n /* ------------------------------------------------------ */\n const userMessage = MessageCtx.toUserMessage(\n input.content,\n input.attachments || undefined,\n );\n const currentMessages = this.state.get().messages;\n this.state.setPartial({\n messages: [...currentMessages, userMessage],\n });\n\n /* ------------------------------------------------------ */\n /* Create session if not exists */\n /* ------------------------------------------------------ */\n if (!this.sessionCtx.sessionState.get().session?.id) {\n const createdSession = await this.sessionCtx.createSession();\n\n // TODO: apply some retry logic here\n if (!createdSession) {\n console.error(\"Failed to create session\");\n return;\n }\n }\n const sessionId = this.sessionCtx.sessionState.get().session?.id;\n if (!sessionId) return;\n\n /* ------------------------------------------------------ */\n /* Send and wait for bot response */\n /* ------------------------------------------------------ */\n const { data } = await this.api.sendMessage(\n {\n uuid: userMessage.id,\n bot_token: this.config.token,\n headers: this.config.headers,\n query_params: this.config.queryParams,\n session_id: sessionId,\n user: this.config.user?.data,\n ...input,\n },\n this.sendMessageAbortController.signal,\n );\n\n if (data?.success) {\n /* ------------------------------------------------------ */\n /* Append bot reply if not fetched from polling */\n /* ------------------------------------------------------ */\n const botMessage = MessageCtx.toBotMessage(data);\n if (botMessage) {\n const prevMessages = this.state.get().messages;\n const shouldAppend = !prevMessages.some(\n (m) => m.id === botMessage.id,\n );\n if (!shouldAppend) {\n this.state.setPartial({\n lastAIResMightSolveUserIssue:\n data.autopilotResponse?.mightSolveUserIssue ||\n data.uiResponse?.mightSolveUserIssue,\n });\n return;\n }\n this.state.setPartial({\n messages: [...prevMessages, botMessage],\n lastAIResMightSolveUserIssue:\n data.autopilotResponse?.mightSolveUserIssue ||\n data.uiResponse?.mightSolveUserIssue,\n });\n }\n } else {\n const errorMessage = MessageCtx.toErrorMessage(\n data?.error?.message || \"Unknown error occurred\",\n );\n const currentMessages = this.state.get().messages;\n this.state.setPartial({\n messages: [...currentMessages, errorMessage],\n });\n }\n } catch (error) {\n if (!this.sendMessageAbortController.signal.aborted) {\n console.error(\"Failed to send message:\", error);\n }\n } finally {\n this.state.setPartial({ isSendingMessage: false });\n }\n };\n\n private fetchAndSetHistory = async (\n sessionId: string,\n abortSignal: AbortSignal,\n ): Promise<void> => {\n /**\n * This is a bit of an implicit contract... there are two cases here\n * 1. If there are no messages in state, it means the user selected a previous session from the sessions screen and got routed to the chat,\n * in this case, we want to show a loading indicator until the initial fetch is done\n * 2. There is a single message in state, which is the optimistically rendered user message,\n * in this case, we don't want to show a loading indicator\n */\n if (this.state.get().messages.length === 0) {\n this.state.setPartial({ isInitialFetchLoading: true });\n }\n\n const lastMessageTimestamp = this.state.get().messages.at(-1)?.timestamp;\n\n const { data: response } = await this.api.getSessionHistory({\n sessionId,\n lastMessageTimestamp,\n abortSignal,\n });\n\n if (response && response.length > 0) {\n // Get a fresh reference to current messages after the poll is done\n const prevMessages = this.state.get().messages;\n const newMessages = response\n .map(MessageCtx.mapHistoryToMessage)\n .filter(\n (newMsg) =>\n !prevMessages.some((existingMsg) => existingMsg.id === newMsg.id),\n );\n this.state.setPartial({\n messages: [...prevMessages, ...newMessages],\n });\n }\n\n if (this.state.get().isInitialFetchLoading) {\n this.state.setPartial({ isInitialFetchLoading: false });\n }\n };\n\n /** Not the best name but whatever */\n private static mapHistoryToMessage(history: MessageDto): MessageType {\n const commonFields = {\n id: history.publicId,\n timestamp: history.sentAt || \"\",\n attachments: history.attachments || undefined,\n };\n\n if (history.sender.kind === \"user\") {\n return {\n ...commonFields,\n type: \"FROM_USER\",\n content: history.content.text || \"\",\n deliveredAt: history.sentAt || \"\",\n };\n }\n\n if (history.sender.kind === \"agent\") {\n return {\n ...commonFields,\n type: \"FROM_AGENT\",\n component: \"agent_message\",\n data: {\n message: history.content.text || \"\",\n },\n };\n }\n\n return {\n ...commonFields,\n type: \"FROM_BOT\",\n component: \"bot_message\",\n agent: {\n id: null,\n name: history.sender.name || \"\",\n isAi: history.sender.kind === \"ai\",\n avatar: history.sender.avatar || null,\n },\n data: {\n message: history.content.text,\n },\n };\n }\n\n private static toUserMessage(\n content: string,\n attachments?: MessageAttachmentType[],\n ): UserMessageType {\n return {\n id: genUuid(),\n type: \"FROM_USER\",\n content,\n deliveredAt: new Date().toISOString(),\n attachments,\n timestamp: new Date().toISOString(),\n };\n }\n\n private static toBotMessage(\n response: SendMessageOutputDto,\n ): BotMessageType | null {\n // TODO: sometimes the bot replies with both an autopilotResponse and a uiResponse... handle this case\n\n if (response.success && response.autopilotResponse) {\n return {\n type: \"FROM_BOT\",\n id: response.autopilotResponse.id || genUuid(),\n timestamp: new Date().toISOString(),\n component: \"bot_message\",\n data: {\n message: response.autopilotResponse.value.content,\n },\n };\n }\n\n if (response.success && response.uiResponse) {\n const uiVal = response.uiResponse.value;\n return {\n type: \"FROM_BOT\" as const,\n id: genUuid(),\n timestamp: new Date().toISOString(),\n component: uiVal.name,\n data: uiVal.request_response,\n };\n }\n\n return null;\n }\n\n private static toErrorMessage(message: string) {\n return {\n type: \"FROM_BOT\" as const,\n id: genUuid(),\n timestamp: new Date().toISOString(),\n component: \"TEXT\",\n data: {\n message,\n variant: \"error\",\n },\n };\n }\n}\n","import { PrimitiveState } from \"../utils/PrimitiveState\";\nimport type { ContactCtx } from \"./contact.ctx\";\nimport type { SessionCtx } from \"./session.ctx\";\nimport type { WidgetCtx } from \"./widget.ctx\";\n\ntype RouterState = {\n screen:\n | /** A welcome screen to collect user data. Useful in public non-logged-in environments */\n \"welcome\"\n /** Show a list of the user's previous sessions */\n | \"sessions\"\n /** Self-explanatory */\n | \"chat\";\n};\n\nexport class RouterCtx {\n state: PrimitiveState<RouterState>;\n\n private contactCtx: ContactCtx;\n private sessionCtx: SessionCtx;\n private resetChat: WidgetCtx[\"resetChat\"];\n\n constructor({\n contactCtx,\n sessionCtx,\n resetChat,\n }: {\n contactCtx: ContactCtx;\n sessionCtx: SessionCtx;\n resetChat: WidgetCtx[\"resetChat\"];\n }) {\n this.state = new PrimitiveState<RouterState>({\n screen: contactCtx.shouldCollectData() ? \"welcome\" : \"sessions\",\n });\n this.contactCtx = contactCtx;\n this.sessionCtx = sessionCtx;\n this.resetChat = resetChat;\n\n this.registerRoutingListener();\n }\n\n private registerRoutingListener = () => {\n this.contactCtx.state.subscribe(({ contact }) => {\n // Auto navigate to sessions screen after collecting user data\n if (contact?.token && this.state.get().screen === \"welcome\") {\n this.state.setPartial({ screen: \"sessions\" });\n }\n });\n };\n\n toSessionsScreen = () => {\n this.resetChat();\n this.state.setPartial({ screen: \"sessions\" });\n };\n\n /**\n * @param sessionId The ID of the session to open, or `undefined` if it is a new chat session\n */\n toChatScreen = (sessionId?: string) => {\n this.resetChat();\n\n if (sessionId) {\n const session = this.sessionCtx.sessionsState\n .get()\n .data.find((s) => s.id === sessionId);\n // Do not navigate if session is not found (this shouldn't happen, unless a wrong ID is passed)\n if (!session) return;\n this.sessionCtx.sessionState.setPartial({ session });\n }\n\n this.state.setPartial({ screen: \"chat\" });\n };\n}\n","import { ApiCaller } from \"../api\";\nimport type { WidgetConfig } from \"../types/WidgetConfig\";\nimport { ContactCtx } from \"./contact.ctx\";\nimport { MessageCtx } from \"./message.ctx\";\nimport { RouterCtx } from \"./router.ctx\";\nimport { SessionCtx } from \"./session.ctx\";\n\nexport class WidgetCtx {\n public config: WidgetConfig;\n public api: ApiCaller;\n public contactCtx: ContactCtx;\n public sessionCtx: SessionCtx;\n public messageCtx: MessageCtx;\n public routerCtx: RouterCtx;\n\n constructor({ config }: { config: WidgetConfig }) {\n this.config = config;\n this.api = new ApiCaller({ config });\n\n this.contactCtx = new ContactCtx({\n api: this.api,\n config: this.config,\n });\n\n this.sessionCtx = new SessionCtx({\n config: this.config,\n api: this.api,\n contactCtx: this.contactCtx,\n });\n\n this.messageCtx = new MessageCtx({\n config: this.config,\n api: this.api,\n sessionCtx: this.sessionCtx,\n });\n\n this.routerCtx = new RouterCtx({\n contactCtx: this.contactCtx,\n sessionCtx: this.sessionCtx,\n resetChat: this.resetChat,\n });\n }\n\n resetChat = () => {\n this.sessionCtx.reset();\n this.messageCtx.reset();\n };\n}\n"],"names":["defaultOnError","onErrorOptions","basicClient","options","client","createClient","middlewares","ApiCaller","config","__publicField","token","baseUrl","headers","request","key","value","axios","body","abortSignal","sessionId","lastMessageTimestamp","query","cursor","filters","file","formData","data","_a","PrimitiveState","state","__privateAdd","_state","_lastUpdated","event","listeners","eventData","listener","callback","error","__privateGet","newState","isEqual","__privateSet","_s","ContactCtx","api","_b","_d","_c","payload","Poller","cb","interval","timeouts","poll","genUuid","uuidv4","SessionCtx","contactCtx","session","initialFetch","contact","sessions","s","i","self","deduped","MessageCtx","sessionCtx","input","isSending","isAssignedToAI","userMessage","currentMessages","botMessage","prevMessages","m","_e","_f","_g","_h","errorMessage","_i","response","newMessages","newMsg","existingMsg","history","commonFields","content","attachments","uiVal","message","RouterCtx","resetChat","WidgetCtx"],"mappings":"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"}
|