@opencx/widget 3.0.11 → 3.0.13
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 +59 -59
- package/dist/designs.cjs.map +1 -1
- package/dist/designs.js +8642 -8522
- package/dist/designs.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/dist/react.cjs +1 -1
- package/dist/react.js +12 -12
- package/dist/src/designs/react/components/lib/button.d.ts +1 -1
- package/dist/src/designs/react/components/lib/loading.d.ts +4 -0
- package/dist/src/designs/react/screens/sessions/index.d.ts +2 -0
- package/dist/src/headless/core/context/{contact.d.ts → contact.ctx.d.ts} +3 -3
- package/dist/src/headless/core/context/message.ctx.d.ts +33 -0
- package/dist/src/headless/core/context/router.ctx.d.ts +29 -0
- package/dist/src/headless/core/context/{session.d.ts → session.ctx.d.ts} +23 -17
- package/dist/src/headless/core/context/{widget.d.ts → widget.ctx.d.ts} +5 -3
- package/dist/src/headless/core/index.d.ts +6 -5
- package/dist/src/headless/core/sdk/schema.d.ts +2 -0
- package/dist/src/headless/core/utils/Poller.d.ts +2 -2
- package/dist/src/headless/core/utils/{PubSub.d.ts → PrimitiveState.d.ts} +1 -1
- package/dist/src/headless/react/hooks/useContact.d.ts +1 -1
- package/dist/src/headless/react/hooks/useMessages.d.ts +1 -1
- package/dist/src/headless/react/hooks/usePreludeData.d.ts +3 -1
- package/dist/src/headless/react/hooks/usePrimitiveState.d.ts +2 -0
- package/dist/src/headless/react/hooks/useSession.d.ts +8 -7
- package/dist/src/headless/react/hooks/useWidgetRouter.d.ts +7 -0
- package/dist/src/headless/react/index.d.ts +1 -1
- package/dist/useUploadFiles-CiUgziil.cjs +18 -0
- package/dist/useUploadFiles-CiUgziil.cjs.map +1 -0
- package/dist/{useUploadFiles-B-HZXbPR.js → useUploadFiles-ClUXwfKK.js} +243 -237
- package/dist/useUploadFiles-ClUXwfKK.js.map +1 -0
- package/dist/widget.ctx-C7UzbSii.cjs +2 -0
- package/dist/widget.ctx-C7UzbSii.cjs.map +1 -0
- package/dist/{widget-BOaF1U-p.js → widget.ctx-DkDwIMJZ.js} +108 -73
- package/dist/widget.ctx-DkDwIMJZ.js.map +1 -0
- package/dist-embed/script.js +112 -102
- package/dist-embed/script.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/designs/react/components/lib/dialog.d.ts +0 -276
- package/dist/src/headless/core/context/message.d.ts +0 -42
- package/dist/src/headless/react/hooks/usePubsub.d.ts +0 -2
- package/dist/useUploadFiles-B-HZXbPR.js.map +0 -1
- package/dist/useUploadFiles-WylOvupS.cjs +0 -18
- package/dist/useUploadFiles-WylOvupS.cjs.map +0 -1
- package/dist/widget-6i5ISSQC.cjs +0 -2
- package/dist/widget-6i5ISSQC.cjs.map +0 -1
- package/dist/widget-BOaF1U-p.js.map +0 -1
- /package/dist/src/designs/react/screens/{chat-screen → chat}/ChatFooter.d.ts +0 -0
- /package/dist/src/designs/react/screens/{chat-screen → chat}/ChatHeader.d.ts +0 -0
- /package/dist/src/designs/react/screens/{chat-screen → chat}/ChatMain.d.ts +0 -0
- /package/dist/src/designs/react/screens/{chat-screen/ChatScreen.d.ts → chat/index.d.ts} +0 -0
- /package/dist/src/designs/react/screens/{root-screen.d.ts → index.d.ts} +0 -0
- /package/dist/src/designs/react/screens/{welcome-screen/WelcomeScreen.d.ts → welcome/index.d.ts} +0 -0
- /package/dist/src/headless/core/utils/{PubSub.test.d.ts → PrimitiveState.test.d.ts} +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
var
|
|
1
|
+
var R = Object.defineProperty;
|
|
2
2
|
var A = (a) => {
|
|
3
3
|
throw TypeError(a);
|
|
4
4
|
};
|
|
5
|
-
var I = (a, t, e) => t in a ?
|
|
5
|
+
var I = (a, t, e) => t in a ? R(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
|
|
6
6
|
var s = (a, t, e) => I(a, typeof t != "symbol" ? t + "" : t, e), M = (a, t, e) => t.has(a) || A("Cannot " + e);
|
|
7
|
-
var h = (a, t, e) => (M(a, t, "read from private field"), e ? e.call(a) : t.get(a)), P = (a, t, e) => t.has(a) ? A("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(a) : t.set(a, e),
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
7
|
+
var h = (a, t, e) => (M(a, t, "read from private field"), e ? e.call(a) : t.get(a)), P = (a, t, e) => t.has(a) ? A("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(a) : t.set(a, e), S = (a, t, e, i) => (M(a, t, "write to private field"), i ? i.call(a, e) : t.set(a, e), e);
|
|
8
|
+
import T from "axios";
|
|
9
|
+
import F from "openapi-fetch";
|
|
10
|
+
import E from "lodash.isequal";
|
|
11
11
|
import { v4 as L } from "uuid";
|
|
12
12
|
const D = (a) => {
|
|
13
13
|
console.log(a.error);
|
|
14
14
|
}, _ = (a) => {
|
|
15
|
-
const t =
|
|
15
|
+
const t = F({
|
|
16
16
|
baseUrl: a.baseUrl
|
|
17
17
|
}), e = {
|
|
18
18
|
onRequest: a.onRequest,
|
|
@@ -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, C;
|
|
126
|
+
class m {
|
|
127
127
|
constructor(t) {
|
|
128
128
|
s(this, "subscribers", /* @__PURE__ */ new Set());
|
|
129
129
|
P(this, l);
|
|
130
130
|
s(this, "initialState");
|
|
131
|
-
P(this,
|
|
131
|
+
P(this, C);
|
|
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 S {
|
|
|
181
181
|
this.emitLifecycle("beforeUpdate", {
|
|
182
182
|
previousState: h(this, l),
|
|
183
183
|
nextState: t
|
|
184
|
-
}),
|
|
184
|
+
}), E(h(this, l), t) || (S(this, l, t), S(this, C, 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,11 +201,11 @@ class S {
|
|
|
201
201
|
s(this, "reset", () => {
|
|
202
202
|
this.set(this.initialState);
|
|
203
203
|
});
|
|
204
|
-
s(this, "lastUpdated", () => h(this,
|
|
205
|
-
|
|
204
|
+
s(this, "lastUpdated", () => h(this, C));
|
|
205
|
+
S(this, l, t), this.initialState = t, S(this, C, Date.now()), this.emitLifecycle("init", { initialState: h(this, l) });
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
-
l = new WeakMap(),
|
|
208
|
+
l = new WeakMap(), C = new WeakMap();
|
|
209
209
|
class B {
|
|
210
210
|
constructor({
|
|
211
211
|
config: t,
|
|
@@ -238,7 +238,7 @@ 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 m({
|
|
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
|
|
@@ -247,7 +247,7 @@ class B {
|
|
|
247
247
|
}
|
|
248
248
|
class U {
|
|
249
249
|
constructor() {
|
|
250
|
-
s(this, "state", new
|
|
250
|
+
s(this, "state", new m({
|
|
251
251
|
isPolling: !1,
|
|
252
252
|
isError: !1
|
|
253
253
|
}));
|
|
@@ -278,7 +278,7 @@ class U {
|
|
|
278
278
|
});
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
-
function
|
|
281
|
+
function y() {
|
|
282
282
|
return L();
|
|
283
283
|
}
|
|
284
284
|
class H {
|
|
@@ -291,78 +291,74 @@ class H {
|
|
|
291
291
|
s(this, "api");
|
|
292
292
|
s(this, "contactCtx");
|
|
293
293
|
s(this, "poller", new U());
|
|
294
|
-
s(this, "
|
|
294
|
+
s(this, "sessionState", new m({
|
|
295
295
|
session: null,
|
|
296
|
-
sessions: {
|
|
297
|
-
data: [],
|
|
298
|
-
cursor: void 0,
|
|
299
|
-
isLastPage: !1,
|
|
300
|
-
didInitialFetch: !1
|
|
301
|
-
},
|
|
302
296
|
isCreatingSession: !1
|
|
303
297
|
}));
|
|
298
|
+
s(this, "sessionsState", new m({
|
|
299
|
+
data: [],
|
|
300
|
+
cursor: void 0,
|
|
301
|
+
isLastPage: !1,
|
|
302
|
+
didStartInitialFetch: !1,
|
|
303
|
+
/**
|
|
304
|
+
* Initialize this as `true` so it always starts loading until the first fetch is done
|
|
305
|
+
*/
|
|
306
|
+
isInitialFetchLoading: !0
|
|
307
|
+
}));
|
|
304
308
|
/** Clears the session and stops polling */
|
|
305
309
|
s(this, "reset", async () => {
|
|
306
|
-
this.
|
|
310
|
+
this.sessionState.reset(), this.poller.reset();
|
|
307
311
|
});
|
|
308
312
|
s(this, "registerPolling", () => {
|
|
309
|
-
this.
|
|
313
|
+
this.sessionState.subscribe(({ session: t }) => {
|
|
310
314
|
t != null && t.id ? this.poller.startPolling(async (e) => {
|
|
311
315
|
const { data: i } = await this.api.getSession({
|
|
312
316
|
sessionId: t.id,
|
|
313
317
|
abortSignal: e
|
|
314
318
|
});
|
|
315
|
-
i && this.
|
|
319
|
+
i && this.sessionState.setPartial({ session: i });
|
|
316
320
|
}, 1e3) : this.poller.reset();
|
|
317
321
|
});
|
|
318
322
|
});
|
|
319
323
|
s(this, "registerInitialSessionsFetch", () => {
|
|
320
|
-
this.contactCtx.state.subscribe(({ contact: t }) => {
|
|
321
|
-
t != null && t.token && !this.
|
|
322
|
-
sessions: {
|
|
323
|
-
...this.state.get().sessions,
|
|
324
|
-
didInitialFetch: !0
|
|
325
|
-
}
|
|
326
|
-
}), this.loadMoreSessions());
|
|
324
|
+
this.contactCtx.state.subscribe(async ({ contact: t }) => {
|
|
325
|
+
t != null && t.token && !this.sessionsState.get().didStartInitialFetch && (this.sessionsState.setPartial({ didStartInitialFetch: !0 }), await this.loadMoreSessions(), this.sessionsState.setPartial({ isInitialFetchLoading: !1 }));
|
|
327
326
|
});
|
|
328
327
|
});
|
|
329
328
|
s(this, "createSession", async () => {
|
|
330
329
|
var i, n;
|
|
331
|
-
this.
|
|
330
|
+
this.sessionState.setPartial({ session: null, isCreatingSession: !0 });
|
|
332
331
|
const { data: t, error: e } = await this.api.createSession({
|
|
333
332
|
customData: (i = this.config.user) != null && i.externalId ? {
|
|
334
333
|
external_id: (n = this.config.user) == null ? void 0 : n.externalId
|
|
335
334
|
} : void 0
|
|
336
335
|
});
|
|
337
|
-
return t ? (this.
|
|
336
|
+
return t ? (this.sessionState.setPartial({ session: t, isCreatingSession: !1 }), t) : (console.error("Failed to create session:", e), null);
|
|
338
337
|
});
|
|
339
338
|
s(this, "loadMoreSessions", async () => {
|
|
340
339
|
var e, i;
|
|
341
|
-
if (this.
|
|
340
|
+
if (this.sessionsState.get().isLastPage || !((e = this.contactCtx.state.get().contact) != null && e.token)) return;
|
|
342
341
|
const { data: t } = await this.api.getSessions({
|
|
343
|
-
cursor: this.
|
|
342
|
+
cursor: this.sessionsState.get().cursor,
|
|
344
343
|
filters: (i = this.config.user) != null && i.externalId ? {
|
|
345
344
|
external_id: this.config.user.externalId
|
|
346
345
|
} : {}
|
|
347
346
|
});
|
|
348
347
|
if (t) {
|
|
349
|
-
const r = [...this.
|
|
348
|
+
const r = [...this.sessionsState.get().data, ...t.items].filter(
|
|
350
349
|
(c, d, g) => d === g.findIndex((u) => c.id === u.id)
|
|
351
350
|
);
|
|
352
|
-
this.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
cursor: t.next || void 0,
|
|
357
|
-
isLastPage: t.next === null
|
|
358
|
-
}
|
|
351
|
+
this.sessionsState.setPartial({
|
|
352
|
+
data: r,
|
|
353
|
+
cursor: t.next || void 0,
|
|
354
|
+
isLastPage: t.next === null
|
|
359
355
|
});
|
|
360
356
|
}
|
|
361
357
|
});
|
|
362
358
|
this.config = t, this.api = e, this.contactCtx = i, this.registerPolling(), this.registerInitialSessionsFetch();
|
|
363
359
|
}
|
|
364
360
|
}
|
|
365
|
-
class
|
|
361
|
+
class p {
|
|
366
362
|
constructor({
|
|
367
363
|
config: t,
|
|
368
364
|
api: e,
|
|
@@ -372,7 +368,7 @@ class f {
|
|
|
372
368
|
s(this, "api");
|
|
373
369
|
s(this, "sessionCtx");
|
|
374
370
|
s(this, "poller", new U());
|
|
375
|
-
s(this, "state", new
|
|
371
|
+
s(this, "state", new m({
|
|
376
372
|
messages: [],
|
|
377
373
|
isSendingMessage: !1,
|
|
378
374
|
suggestedReplies: null
|
|
@@ -382,7 +378,7 @@ class f {
|
|
|
382
378
|
this.sendMessageAbortController.abort("Resetting chat"), this.state.reset(), this.poller.reset();
|
|
383
379
|
});
|
|
384
380
|
s(this, "registerPolling", () => {
|
|
385
|
-
this.sessionCtx.
|
|
381
|
+
this.sessionCtx.sessionState.subscribe(({ session: t }) => {
|
|
386
382
|
t != null && t.id ? this.poller.startPolling(async (e) => {
|
|
387
383
|
await this.fetchAndSetHistory(t.id, e);
|
|
388
384
|
}, 1e3) : this.poller.reset();
|
|
@@ -391,7 +387,7 @@ class f {
|
|
|
391
387
|
s(this, "sendMessage", async (t) => {
|
|
392
388
|
var n, r, c, d, g, u, x;
|
|
393
389
|
this.sendMessageAbortController = new AbortController();
|
|
394
|
-
const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.
|
|
390
|
+
const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.sessionState.get().session) == null ? void 0 : n.assignee.kind) === "ai";
|
|
395
391
|
if (e && i) {
|
|
396
392
|
console.warn("Cannot send messages while awaiting AI response");
|
|
397
393
|
return;
|
|
@@ -399,17 +395,17 @@ class f {
|
|
|
399
395
|
this.state.setPartial({ suggestedReplies: null });
|
|
400
396
|
try {
|
|
401
397
|
this.state.setPartial({ isSendingMessage: !0 });
|
|
402
|
-
const b =
|
|
398
|
+
const b = p.toUserMessage(
|
|
403
399
|
t.content,
|
|
404
400
|
t.attachments || void 0
|
|
405
401
|
), k = this.state.get().messages;
|
|
406
402
|
if (this.state.setPartial({
|
|
407
403
|
messages: [...k, b]
|
|
408
|
-
}), !((r = this.sessionCtx.
|
|
404
|
+
}), !((r = this.sessionCtx.sessionState.get().session) != null && r.id) && !await this.sessionCtx.createSession()) {
|
|
409
405
|
console.error("Failed to create session");
|
|
410
406
|
return;
|
|
411
407
|
}
|
|
412
|
-
const v = (c = this.sessionCtx.
|
|
408
|
+
const v = (c = this.sessionCtx.sessionState.get().session) == null ? void 0 : c.id;
|
|
413
409
|
if (!v) return;
|
|
414
410
|
const { data: o } = await this.api.sendMessage(
|
|
415
411
|
{
|
|
@@ -424,21 +420,21 @@ class f {
|
|
|
424
420
|
this.sendMessageAbortController.signal
|
|
425
421
|
);
|
|
426
422
|
if (o != null && o.success) {
|
|
427
|
-
const
|
|
428
|
-
if (
|
|
429
|
-
const
|
|
430
|
-
if (!!
|
|
431
|
-
(O) => O.id ===
|
|
423
|
+
const f = p.toBotMessage(o);
|
|
424
|
+
if (f) {
|
|
425
|
+
const w = this.state.get().messages;
|
|
426
|
+
if (!!w.some(
|
|
427
|
+
(O) => O.id === f.id
|
|
432
428
|
)) return;
|
|
433
|
-
this.state.setPartial({ messages: [...
|
|
429
|
+
this.state.setPartial({ messages: [...w, f] });
|
|
434
430
|
} else
|
|
435
431
|
(g = o.options) != null && g.value && ((u = o.options) == null ? void 0 : u.value.length) > 0 && this.state.setPartial({ suggestedReplies: o.options.value });
|
|
436
432
|
} else {
|
|
437
|
-
const
|
|
433
|
+
const f = p.toErrorMessage(
|
|
438
434
|
((x = o == null ? void 0 : o.error) == null ? void 0 : x.message) || "Unknown error occurred"
|
|
439
|
-
),
|
|
435
|
+
), w = this.state.get().messages;
|
|
440
436
|
this.state.setPartial({
|
|
441
|
-
messages: [...
|
|
437
|
+
messages: [...w, f]
|
|
442
438
|
});
|
|
443
439
|
}
|
|
444
440
|
} catch (b) {
|
|
@@ -455,7 +451,7 @@ class f {
|
|
|
455
451
|
abortSignal: e
|
|
456
452
|
});
|
|
457
453
|
if (n && n.length > 0) {
|
|
458
|
-
const c = this.state.get().messages, d = n.map(
|
|
454
|
+
const c = this.state.get().messages, d = n.map(p.mapHistoryToMessage).filter(
|
|
459
455
|
(g) => !c.some((u) => u.id === g.id)
|
|
460
456
|
);
|
|
461
457
|
this.state.setPartial({
|
|
@@ -501,7 +497,7 @@ class f {
|
|
|
501
497
|
}
|
|
502
498
|
static toUserMessage(t, e) {
|
|
503
499
|
return {
|
|
504
|
-
id:
|
|
500
|
+
id: y(),
|
|
505
501
|
type: "FROM_USER",
|
|
506
502
|
content: t,
|
|
507
503
|
deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -513,7 +509,7 @@ class f {
|
|
|
513
509
|
if (t.success && t.autopilotResponse)
|
|
514
510
|
return {
|
|
515
511
|
type: "FROM_BOT",
|
|
516
|
-
id: t.autopilotResponse.id ||
|
|
512
|
+
id: t.autopilotResponse.id || y(),
|
|
517
513
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
518
514
|
component: "bot_message",
|
|
519
515
|
data: {
|
|
@@ -524,7 +520,7 @@ class f {
|
|
|
524
520
|
const e = t.uiResponse.value;
|
|
525
521
|
return {
|
|
526
522
|
type: "FROM_BOT",
|
|
527
|
-
id:
|
|
523
|
+
id: y(),
|
|
528
524
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
529
525
|
component: e.name,
|
|
530
526
|
data: e.request_response
|
|
@@ -535,7 +531,7 @@ class f {
|
|
|
535
531
|
static toErrorMessage(t) {
|
|
536
532
|
return {
|
|
537
533
|
type: "FROM_BOT",
|
|
538
|
-
id:
|
|
534
|
+
id: y(),
|
|
539
535
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
540
536
|
component: "TEXT",
|
|
541
537
|
data: {
|
|
@@ -545,13 +541,48 @@ class f {
|
|
|
545
541
|
};
|
|
546
542
|
}
|
|
547
543
|
}
|
|
548
|
-
class
|
|
544
|
+
class G {
|
|
545
|
+
constructor({
|
|
546
|
+
contactCtx: t,
|
|
547
|
+
sessionCtx: e,
|
|
548
|
+
resetChat: i
|
|
549
|
+
}) {
|
|
550
|
+
s(this, "state");
|
|
551
|
+
s(this, "contactCtx");
|
|
552
|
+
s(this, "sessionCtx");
|
|
553
|
+
s(this, "resetChat");
|
|
554
|
+
s(this, "registerRoutingListener", () => {
|
|
555
|
+
this.contactCtx.state.subscribe(({ contact: t }) => {
|
|
556
|
+
t != null && t.token && this.state.get().screen === "welcome" && this.state.setPartial({ screen: "sessions" });
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
s(this, "toSessionsScreen", () => {
|
|
560
|
+
this.resetChat(), this.state.setPartial({ screen: "sessions" });
|
|
561
|
+
});
|
|
562
|
+
/**
|
|
563
|
+
* @param sessionId The ID of the session to open, or `undefined` if it is a new chat session
|
|
564
|
+
*/
|
|
565
|
+
s(this, "toChatScreen", (t) => {
|
|
566
|
+
if (this.resetChat(), t) {
|
|
567
|
+
const e = this.sessionCtx.sessionsState.get().data.find((i) => i.id === t);
|
|
568
|
+
if (!e) return;
|
|
569
|
+
this.sessionCtx.sessionState.setPartial({ session: e });
|
|
570
|
+
}
|
|
571
|
+
this.state.setPartial({ screen: "chat" });
|
|
572
|
+
});
|
|
573
|
+
this.state = new m({
|
|
574
|
+
screen: t.shouldCollectData() ? "welcome" : "sessions"
|
|
575
|
+
}), this.contactCtx = t, this.sessionCtx = e, this.resetChat = i, this.registerRoutingListener();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
class J {
|
|
549
579
|
constructor({ config: t }) {
|
|
550
580
|
s(this, "config");
|
|
551
581
|
s(this, "api");
|
|
552
582
|
s(this, "contactCtx");
|
|
553
583
|
s(this, "sessionCtx");
|
|
554
584
|
s(this, "messageCtx");
|
|
585
|
+
s(this, "routerCtx");
|
|
555
586
|
s(this, "resetChat", () => {
|
|
556
587
|
this.sessionCtx.reset(), this.messageCtx.reset();
|
|
557
588
|
});
|
|
@@ -562,15 +593,19 @@ class W {
|
|
|
562
593
|
config: this.config,
|
|
563
594
|
api: this.api,
|
|
564
595
|
contactCtx: this.contactCtx
|
|
565
|
-
}), this.messageCtx = new
|
|
596
|
+
}), this.messageCtx = new p({
|
|
566
597
|
config: this.config,
|
|
567
598
|
api: this.api,
|
|
568
599
|
sessionCtx: this.sessionCtx
|
|
600
|
+
}), this.routerCtx = new G({
|
|
601
|
+
contactCtx: this.contactCtx,
|
|
602
|
+
sessionCtx: this.sessionCtx,
|
|
603
|
+
resetChat: this.resetChat
|
|
569
604
|
});
|
|
570
605
|
}
|
|
571
606
|
}
|
|
572
607
|
export {
|
|
573
|
-
|
|
574
|
-
W
|
|
608
|
+
m as P,
|
|
609
|
+
J as W
|
|
575
610
|
};
|
|
576
|
-
//# sourceMappingURL=widget-
|
|
611
|
+
//# sourceMappingURL=widget.ctx-DkDwIMJZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.ctx-DkDwIMJZ.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 { Dto } from \"../sdk\";\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 poller = 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.registerPolling();\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.poller.reset();\n };\n\n private registerPolling = () => {\n this.sessionState.subscribe(({ session }) => {\n if (session?.id) {\n this.poller.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.poller.reset();\n }\n });\n };\n\n private registerInitialSessionsFetch = () => {\n this.contactCtx.state.subscribe(async ({ contact }) => {\n if (contact?.token && !this.sessionsState.get().didStartInitialFetch) {\n this.sessionsState.setPartial({ didStartInitialFetch: true });\n\n // Call this for the first time to get the first page of sessions\n await this.loadMoreSessions();\n\n this.sessionsState.setPartial({ isInitialFetchLoading: false });\n }\n });\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 loadMoreSessions = async () => {\n if (this.sessionsState.get().isLastPage) return;\n if (!this.contactCtx.state.get().contact?.token) return;\n\n const { data } = await this.api.getSessions({\n cursor: this.sessionsState.get().cursor,\n filters: this.config.user?.externalId\n ? {\n external_id: this.config.user.externalId,\n }\n : {},\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","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\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<{\n messages: MessageType[];\n isSendingMessage: boolean;\n suggestedReplies: string[] | null;\n }>({\n messages: [],\n isSendingMessage: false,\n suggestedReplies: null,\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 suggested replies */\n /* ------------------------------------------------------ */\n this.state.setPartial({ suggestedReplies: null });\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) return;\n this.state.setPartial({ messages: [...prevMessages, botMessage] });\n } else {\n /* ------------------------------------------------------ */\n /* Check if bot responded with suggested replies */\n /* ------------------------------------------------------ */\n if (data.options?.value && data.options?.value.length > 0) {\n this.state.setPartial({ suggestedReplies: data.options.value });\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 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 // if (newMessages.length > 0) {\n // // const playSoundEffects = config?.settings?.playSoundEffects;\n // // Play notification sound for new messages if enabled\n // // if (\n // // playSoundEffects &&\n // // platform?.audio &&\n // // isAudioAvailable(platform.audio)\n // // ) {\n // // const botMessages = newMessages.filter(\n // // (msg) => msg.type === \"FROM_BOT\",\n // // );\n // // if (botMessages.length > 0) {\n // // await safeAudioOperation(\n // // () => platform.audio!.playNotification(),\n // // \"Failed to play notification sound for new messages\",\n // // );\n // // }\n // // }\n\n // }\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(response: SendMessageOutputDto): BotMessageType | null {\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","contact","deduped","s","i","self","MessageCtx","sessionCtx","input","isSending","isAssignedToAI","userMessage","currentMessages","botMessage","prevMessages","m","_e","_f","errorMessage","_g","response","newMessages","newMsg","existingMsg","history","commonFields","content","attachments","uiVal","message","RouterCtx","resetChat","WidgetCtx"],"mappings":"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"}
|