@opencx/widget 3.0.9 → 3.0.12
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/{basic.cjs → designs.cjs} +41 -41
- package/dist/designs.cjs.map +1 -0
- package/dist/designs.d.ts +2 -0
- package/dist/{basic.js → designs.js} +3044 -3036
- package/dist/designs.js.map +1 -0
- 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/index.d.ts +5 -8
- package/dist/src/designs/react/{basic/utils → utils}/group-messages-by-type.d.ts +1 -1
- package/dist/src/embedded/index.d.ts +11 -0
- package/dist/src/headless/core/api.d.ts +42 -16
- 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.ctx.d.ts +56 -0
- 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 +80 -4
- package/dist/src/headless/core/types/WidgetConfig.d.ts +22 -9
- 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 +7 -1
- package/dist/src/headless/react/hooks/useWidgetRouter.d.ts +7 -0
- package/dist/src/headless/react/index.d.ts +1 -1
- package/dist/{useUploadFiles-BsYBWtZE.js → useUploadFiles-BQkTgy3Z.js} +243 -237
- package/dist/useUploadFiles-BQkTgy3Z.js.map +1 -0
- package/dist/useUploadFiles-CgV45e1z.cjs +18 -0
- package/dist/useUploadFiles-CgV45e1z.cjs.map +1 -0
- package/dist/widget.ctx-BFXSWWWZ.cjs +2 -0
- package/dist/widget.ctx-BFXSWWWZ.cjs.map +1 -0
- package/dist/{widget-BeNOCqB5.js → widget.ctx-CKrjZfxE.js} +179 -89
- package/dist/widget.ctx-CKrjZfxE.js.map +1 -0
- package/dist-embed/script.js +118 -118
- package/dist-embed/script.js.map +1 -1
- package/package.json +5 -5
- package/dist/basic.cjs.map +0 -1
- package/dist/basic.d.ts +0 -2
- package/dist/basic.js.map +0 -1
- package/dist/src/designs/react/basic/index.d.ts +0 -10
- package/dist/src/designs/react/render.d.ts +0 -2
- package/dist/src/headless/core/context/message.d.ts +0 -42
- package/dist/src/headless/core/context/session.d.ts +0 -74
- package/dist/src/headless/core/utils/PubSub.test.d.ts +0 -1
- package/dist/src/headless/react/hooks/usePubsub.d.ts +0 -2
- package/dist/style.css +0 -1
- package/dist/useUploadFiles-BsYBWtZE.js.map +0 -1
- package/dist/useUploadFiles-CVNyTftw.cjs +0 -18
- package/dist/useUploadFiles-CVNyTftw.cjs.map +0 -1
- package/dist/widget-BeNOCqB5.js.map +0 -1
- package/dist/widget-DlAUwHzU.cjs +0 -2
- package/dist/widget-DlAUwHzU.cjs.map +0 -1
- /package/dist/src/designs/react/{basic/WidgetPopoverTrigger.d.ts → WidgetPopoverTrigger.d.ts} +0 -0
- /package/dist/src/designs/react/{basic/screens/chat-screen → screens/chat}/ChatFooter.d.ts +0 -0
- /package/dist/src/designs/react/{basic/screens/chat-screen → screens/chat}/ChatHeader.d.ts +0 -0
- /package/dist/src/designs/react/{basic/screens/chat-screen → screens/chat}/ChatMain.d.ts +0 -0
- /package/dist/src/designs/react/{basic/screens/chat-screen/ChatScreen.d.ts → screens/chat/index.d.ts} +0 -0
- /package/dist/src/designs/react/{basic/screens/root-screen.d.ts → screens/index.d.ts} +0 -0
- /package/dist/src/designs/react/{basic/screens/welcome-screen/WelcomeScreen.d.ts → screens/welcome/index.d.ts} +0 -0
- /package/dist/src/{designs/react/basic/widget-interaction-tests/widget.test.d.ts → headless/core/utils/PrimitiveState.test.d.ts} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var
|
|
1
|
+
var R = Object.defineProperty;
|
|
2
2
|
var A = (a) => {
|
|
3
3
|
throw TypeError(a);
|
|
4
4
|
};
|
|
5
|
-
var
|
|
6
|
-
var s = (a, t, e) =>
|
|
7
|
-
var
|
|
8
|
-
import
|
|
5
|
+
var T = (a, t, e) => t in a ? R(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
|
|
6
|
+
var s = (a, t, e) => T(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), S = (a, t, e, i) => (M(a, t, "write to private field"), i ? i.call(a, e) : t.set(a, e), e);
|
|
8
|
+
import I from "axios";
|
|
9
9
|
import E from "openapi-fetch";
|
|
10
10
|
import F 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
15
|
const t = E({
|
|
16
16
|
baseUrl: a.baseUrl
|
|
17
17
|
}), e = {
|
|
@@ -21,7 +21,7 @@ const D = (a) => {
|
|
|
21
21
|
};
|
|
22
22
|
return t.use(e), t;
|
|
23
23
|
};
|
|
24
|
-
class
|
|
24
|
+
class q {
|
|
25
25
|
constructor({
|
|
26
26
|
config: t
|
|
27
27
|
}) {
|
|
@@ -40,7 +40,7 @@ class B {
|
|
|
40
40
|
s(this, "createOpenAPIClient", ({
|
|
41
41
|
baseUrl: t,
|
|
42
42
|
headers: e
|
|
43
|
-
}) =>
|
|
43
|
+
}) => _({
|
|
44
44
|
baseUrl: t,
|
|
45
45
|
onRequest: ({ request: i }) => {
|
|
46
46
|
Object.entries(e).forEach(([n, r]) => {
|
|
@@ -51,7 +51,7 @@ class B {
|
|
|
51
51
|
s(this, "createAxiosUploadClient", ({
|
|
52
52
|
baseUrl: t,
|
|
53
53
|
headers: e
|
|
54
|
-
}) =>
|
|
54
|
+
}) => I.create({
|
|
55
55
|
baseURL: `${t}/backend/widget/v2/upload`,
|
|
56
56
|
headers: e
|
|
57
57
|
}));
|
|
@@ -84,7 +84,9 @@ class B {
|
|
|
84
84
|
body: t
|
|
85
85
|
}
|
|
86
86
|
));
|
|
87
|
-
s(this, "createSession", async () => await this.client.POST("/backend/widget/v2/create-session"
|
|
87
|
+
s(this, "createSession", async (t) => await this.client.POST("/backend/widget/v2/create-session", {
|
|
88
|
+
body: t
|
|
89
|
+
}));
|
|
88
90
|
s(this, "getSession", async ({
|
|
89
91
|
sessionId: t,
|
|
90
92
|
abortSignal: e
|
|
@@ -92,6 +94,14 @@ class B {
|
|
|
92
94
|
params: { path: { sessionId: t } },
|
|
93
95
|
signal: e
|
|
94
96
|
}));
|
|
97
|
+
s(this, "getSessions", async ({
|
|
98
|
+
cursor: t,
|
|
99
|
+
filters: e,
|
|
100
|
+
abortSignal: i
|
|
101
|
+
}) => await this.client.GET("/backend/widget/v2/sessions", {
|
|
102
|
+
params: { query: { cursor: t, filters: JSON.stringify(e) } },
|
|
103
|
+
signal: i
|
|
104
|
+
}));
|
|
95
105
|
s(this, "uploadFile", async (t, e = {}) => {
|
|
96
106
|
const i = new FormData();
|
|
97
107
|
i.append("file", t.file);
|
|
@@ -104,20 +114,21 @@ class B {
|
|
|
104
114
|
return n;
|
|
105
115
|
});
|
|
106
116
|
s(this, "vote", async (t) => await this.client.POST("/backend/widget/v2/chat/vote", { body: t }));
|
|
117
|
+
var n;
|
|
107
118
|
this.config = t;
|
|
108
119
|
const { baseUrl: e, headers: i } = this.constructClientOptions(
|
|
109
|
-
t.
|
|
120
|
+
(n = t.user) == null ? void 0 : n.token
|
|
110
121
|
);
|
|
111
122
|
this.client = this.createOpenAPIClient({ baseUrl: e, headers: i }), this.uploadFileClient = this.createAxiosUploadClient({ baseUrl: e, headers: i });
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
|
-
var l,
|
|
115
|
-
class
|
|
125
|
+
var l, C;
|
|
126
|
+
class m {
|
|
116
127
|
constructor(t) {
|
|
117
128
|
s(this, "subscribers", /* @__PURE__ */ new Set());
|
|
118
|
-
|
|
129
|
+
P(this, l);
|
|
119
130
|
s(this, "initialState");
|
|
120
|
-
|
|
131
|
+
P(this, C);
|
|
121
132
|
s(this, "lifecycleListeners", /* @__PURE__ */ new Map());
|
|
122
133
|
s(this, "emitLifecycle", (t, e) => {
|
|
123
134
|
const i = this.lifecycleListeners.get(t);
|
|
@@ -160,7 +171,7 @@ class P {
|
|
|
160
171
|
};
|
|
161
172
|
});
|
|
162
173
|
/** Get the current state */
|
|
163
|
-
s(this, "get", () =>
|
|
174
|
+
s(this, "get", () => h(this, l));
|
|
164
175
|
// TODO make this provide prev state
|
|
165
176
|
/**
|
|
166
177
|
* Set the state and notify subscribers if the state changes
|
|
@@ -168,14 +179,14 @@ class P {
|
|
|
168
179
|
*/
|
|
169
180
|
s(this, "set", (t) => {
|
|
170
181
|
this.emitLifecycle("beforeUpdate", {
|
|
171
|
-
previousState:
|
|
182
|
+
previousState: h(this, l),
|
|
172
183
|
nextState: t
|
|
173
|
-
}), F(
|
|
184
|
+
}), F(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 });
|
|
174
185
|
});
|
|
175
186
|
// TODO make this provide prev state
|
|
176
187
|
s(this, "setPartial", (t) => {
|
|
177
188
|
if (t == null) return;
|
|
178
|
-
const e = { ...
|
|
189
|
+
const e = { ...h(this, l), ...t };
|
|
179
190
|
this.set(e);
|
|
180
191
|
});
|
|
181
192
|
/**
|
|
@@ -190,12 +201,12 @@ class P {
|
|
|
190
201
|
s(this, "reset", () => {
|
|
191
202
|
this.set(this.initialState);
|
|
192
203
|
});
|
|
193
|
-
s(this, "lastUpdated", () =>
|
|
194
|
-
|
|
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) });
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
|
-
l = new WeakMap(),
|
|
198
|
-
class
|
|
208
|
+
l = new WeakMap(), C = new WeakMap();
|
|
209
|
+
class B {
|
|
199
210
|
constructor({
|
|
200
211
|
config: t,
|
|
201
212
|
api: e
|
|
@@ -208,10 +219,10 @@ class q {
|
|
|
208
219
|
return !!(!((e = this.state.get().contact) != null && e.token) && this.config.collectUserData);
|
|
209
220
|
});
|
|
210
221
|
s(this, "autoCreateUnverifiedUser", async () => {
|
|
211
|
-
var t, e;
|
|
222
|
+
var t, e, i, n;
|
|
212
223
|
await this.createUnverifiedContact({
|
|
213
|
-
name: ((t = this.config.user) == null ? void 0 : t.name) || "Anonymous",
|
|
214
|
-
email: (
|
|
224
|
+
name: ((e = (t = this.config.user) == null ? void 0 : t.data) == null ? void 0 : e.name) || "Anonymous",
|
|
225
|
+
email: (n = (i = this.config.user) == null ? void 0 : i.data) == null ? void 0 : n.email
|
|
215
226
|
});
|
|
216
227
|
});
|
|
217
228
|
s(this, "createUnverifiedContact", async (t) => {
|
|
@@ -221,21 +232,22 @@ class q {
|
|
|
221
232
|
isErrorCreatingUnverifiedContact: !1
|
|
222
233
|
});
|
|
223
234
|
const { data: e } = await this.api.createUnverifiedContact(t);
|
|
224
|
-
e != null && e.token ? (this.state.setPartial({ contact: { token: e.token } })
|
|
235
|
+
e != null && e.token ? (this.api.setAuthToken(e.token), this.state.setPartial({ contact: { token: e.token } })) : this.state.setPartial({ isErrorCreatingUnverifiedContact: !0 });
|
|
225
236
|
} finally {
|
|
226
237
|
this.state.setPartial({ isCreatingUnverifiedContact: !1 });
|
|
227
238
|
}
|
|
228
239
|
});
|
|
229
|
-
|
|
230
|
-
|
|
240
|
+
var i, n, r;
|
|
241
|
+
this.config = t, this.api = e, this.state = new m({
|
|
242
|
+
contact: (i = t.user) != null && i.token ? { token: (n = t.user) == null ? void 0 : n.token } : null,
|
|
231
243
|
isCreatingUnverifiedContact: !1,
|
|
232
244
|
isErrorCreatingUnverifiedContact: !1
|
|
233
|
-
}), !t.
|
|
245
|
+
}), !((r = t.user) != null && r.token) && !t.collectUserData && this.autoCreateUnverifiedUser();
|
|
234
246
|
}
|
|
235
247
|
}
|
|
236
|
-
class
|
|
248
|
+
class U {
|
|
237
249
|
constructor() {
|
|
238
|
-
s(this, "state", new
|
|
250
|
+
s(this, "state", new m({
|
|
239
251
|
isPolling: !1,
|
|
240
252
|
isError: !1
|
|
241
253
|
}));
|
|
@@ -266,48 +278,83 @@ class M {
|
|
|
266
278
|
});
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
|
-
function
|
|
281
|
+
function y() {
|
|
270
282
|
return L();
|
|
271
283
|
}
|
|
272
|
-
class
|
|
273
|
-
constructor(
|
|
284
|
+
class H {
|
|
285
|
+
constructor({
|
|
286
|
+
config: t,
|
|
287
|
+
api: e,
|
|
288
|
+
contactCtx: i
|
|
289
|
+
}) {
|
|
290
|
+
s(this, "config");
|
|
274
291
|
s(this, "api");
|
|
275
|
-
s(this, "
|
|
276
|
-
s(this, "
|
|
292
|
+
s(this, "contactCtx");
|
|
293
|
+
s(this, "poller", new U());
|
|
294
|
+
s(this, "sessionState", new m({
|
|
277
295
|
session: null,
|
|
278
296
|
isCreatingSession: !1
|
|
279
297
|
}));
|
|
298
|
+
s(this, "sessionsState", new m({
|
|
299
|
+
data: [],
|
|
300
|
+
cursor: void 0,
|
|
301
|
+
isLastPage: !1,
|
|
302
|
+
didInitialFetch: !1
|
|
303
|
+
}));
|
|
280
304
|
/** Clears the session and stops polling */
|
|
281
305
|
s(this, "reset", async () => {
|
|
282
|
-
this.
|
|
306
|
+
this.sessionState.reset(), this.poller.reset();
|
|
283
307
|
});
|
|
284
308
|
s(this, "registerPolling", () => {
|
|
285
|
-
this.
|
|
309
|
+
this.sessionState.subscribe(({ session: t }) => {
|
|
286
310
|
t != null && t.id ? this.poller.startPolling(async (e) => {
|
|
287
|
-
const { data: i } = await this.
|
|
288
|
-
|
|
311
|
+
const { data: i } = await this.api.getSession({
|
|
312
|
+
sessionId: t.id,
|
|
313
|
+
abortSignal: e
|
|
314
|
+
});
|
|
315
|
+
i && this.sessionState.setPartial({ session: i });
|
|
289
316
|
}, 1e3) : this.poller.reset();
|
|
290
317
|
});
|
|
291
318
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
319
|
+
s(this, "registerInitialSessionsFetch", () => {
|
|
320
|
+
this.contactCtx.state.subscribe(({ contact: t }) => {
|
|
321
|
+
t != null && t.token && !this.sessionsState.get().didInitialFetch && (this.sessionsState.setPartial({ didInitialFetch: !0 }), this.loadMoreSessions());
|
|
322
|
+
});
|
|
323
|
+
});
|
|
296
324
|
s(this, "createSession", async () => {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
325
|
+
var i, n;
|
|
326
|
+
this.sessionState.setPartial({ session: null, isCreatingSession: !0 });
|
|
327
|
+
const { data: t, error: e } = await this.api.createSession({
|
|
328
|
+
customData: (i = this.config.user) != null && i.externalId ? {
|
|
329
|
+
external_id: (n = this.config.user) == null ? void 0 : n.externalId
|
|
330
|
+
} : void 0
|
|
331
|
+
});
|
|
332
|
+
return t ? (this.sessionState.setPartial({ session: t, isCreatingSession: !1 }), t) : (console.error("Failed to create session:", e), null);
|
|
300
333
|
});
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
334
|
+
s(this, "loadMoreSessions", async () => {
|
|
335
|
+
var e, i;
|
|
336
|
+
if (this.sessionsState.get().isLastPage || !((e = this.contactCtx.state.get().contact) != null && e.token)) return;
|
|
337
|
+
const { data: t } = await this.api.getSessions({
|
|
338
|
+
cursor: this.sessionsState.get().cursor,
|
|
339
|
+
filters: (i = this.config.user) != null && i.externalId ? {
|
|
340
|
+
external_id: this.config.user.externalId
|
|
341
|
+
} : {}
|
|
342
|
+
});
|
|
343
|
+
if (t) {
|
|
344
|
+
const r = [...this.sessionsState.get().data, ...t.items].filter(
|
|
345
|
+
(c, d, g) => d === g.findIndex((u) => c.id === u.id)
|
|
346
|
+
);
|
|
347
|
+
this.sessionsState.setPartial({
|
|
348
|
+
data: r,
|
|
349
|
+
cursor: t.next || void 0,
|
|
350
|
+
isLastPage: t.next === null
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
this.config = t, this.api = e, this.contactCtx = i, this.registerPolling(), this.registerInitialSessionsFetch();
|
|
308
355
|
}
|
|
309
356
|
}
|
|
310
|
-
class
|
|
357
|
+
class p {
|
|
311
358
|
constructor({
|
|
312
359
|
config: t,
|
|
313
360
|
api: e,
|
|
@@ -316,8 +363,8 @@ class d {
|
|
|
316
363
|
s(this, "config");
|
|
317
364
|
s(this, "api");
|
|
318
365
|
s(this, "sessionCtx");
|
|
319
|
-
s(this, "poller", new
|
|
320
|
-
s(this, "state", new
|
|
366
|
+
s(this, "poller", new U());
|
|
367
|
+
s(this, "state", new m({
|
|
321
368
|
messages: [],
|
|
322
369
|
isSendingMessage: !1,
|
|
323
370
|
suggestedReplies: null
|
|
@@ -327,16 +374,16 @@ class d {
|
|
|
327
374
|
this.sendMessageAbortController.abort("Resetting chat"), this.state.reset(), this.poller.reset();
|
|
328
375
|
});
|
|
329
376
|
s(this, "registerPolling", () => {
|
|
330
|
-
this.sessionCtx.
|
|
377
|
+
this.sessionCtx.sessionState.subscribe(({ session: t }) => {
|
|
331
378
|
t != null && t.id ? this.poller.startPolling(async (e) => {
|
|
332
379
|
await this.fetchAndSetHistory(t.id, e);
|
|
333
380
|
}, 1e3) : this.poller.reset();
|
|
334
381
|
});
|
|
335
382
|
});
|
|
336
383
|
s(this, "sendMessage", async (t) => {
|
|
337
|
-
var n, r,
|
|
384
|
+
var n, r, c, d, g, u, x;
|
|
338
385
|
this.sendMessageAbortController = new AbortController();
|
|
339
|
-
const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.
|
|
386
|
+
const e = this.state.get().isSendingMessage, i = ((n = this.sessionCtx.sessionState.get().session) == null ? void 0 : n.assignee.kind) === "ai";
|
|
340
387
|
if (e && i) {
|
|
341
388
|
console.warn("Cannot send messages while awaiting AI response");
|
|
342
389
|
return;
|
|
@@ -344,17 +391,17 @@ class d {
|
|
|
344
391
|
this.state.setPartial({ suggestedReplies: null });
|
|
345
392
|
try {
|
|
346
393
|
this.state.setPartial({ isSendingMessage: !0 });
|
|
347
|
-
const b =
|
|
394
|
+
const b = p.toUserMessage(
|
|
348
395
|
t.content,
|
|
349
396
|
t.attachments || void 0
|
|
350
397
|
), k = this.state.get().messages;
|
|
351
398
|
if (this.state.setPartial({
|
|
352
399
|
messages: [...k, b]
|
|
353
|
-
}), !((r = this.sessionCtx.
|
|
400
|
+
}), !((r = this.sessionCtx.sessionState.get().session) != null && r.id) && !await this.sessionCtx.createSession()) {
|
|
354
401
|
console.error("Failed to create session");
|
|
355
402
|
return;
|
|
356
403
|
}
|
|
357
|
-
const v = (
|
|
404
|
+
const v = (c = this.sessionCtx.sessionState.get().session) == null ? void 0 : c.id;
|
|
358
405
|
if (!v) return;
|
|
359
406
|
const { data: o } = await this.api.sendMessage(
|
|
360
407
|
{
|
|
@@ -363,27 +410,27 @@ class d {
|
|
|
363
410
|
headers: this.config.headers,
|
|
364
411
|
query_params: this.config.queryParams,
|
|
365
412
|
session_id: v,
|
|
366
|
-
user: this.config.user,
|
|
413
|
+
user: (d = this.config.user) == null ? void 0 : d.data,
|
|
367
414
|
...t
|
|
368
415
|
},
|
|
369
416
|
this.sendMessageAbortController.signal
|
|
370
417
|
);
|
|
371
418
|
if (o != null && o.success) {
|
|
372
|
-
const
|
|
373
|
-
if (
|
|
374
|
-
const
|
|
375
|
-
if (!!
|
|
376
|
-
(
|
|
419
|
+
const f = p.toBotMessage(o);
|
|
420
|
+
if (f) {
|
|
421
|
+
const w = this.state.get().messages;
|
|
422
|
+
if (!!w.some(
|
|
423
|
+
(O) => O.id === f.id
|
|
377
424
|
)) return;
|
|
378
|
-
this.state.setPartial({ messages: [...
|
|
425
|
+
this.state.setPartial({ messages: [...w, f] });
|
|
379
426
|
} else
|
|
380
|
-
(
|
|
427
|
+
(g = o.options) != null && g.value && ((u = o.options) == null ? void 0 : u.value.length) > 0 && this.state.setPartial({ suggestedReplies: o.options.value });
|
|
381
428
|
} else {
|
|
382
|
-
const
|
|
383
|
-
((
|
|
384
|
-
),
|
|
429
|
+
const f = p.toErrorMessage(
|
|
430
|
+
((x = o == null ? void 0 : o.error) == null ? void 0 : x.message) || "Unknown error occurred"
|
|
431
|
+
), w = this.state.get().messages;
|
|
385
432
|
this.state.setPartial({
|
|
386
|
-
messages: [...
|
|
433
|
+
messages: [...w, f]
|
|
387
434
|
});
|
|
388
435
|
}
|
|
389
436
|
} catch (b) {
|
|
@@ -400,11 +447,11 @@ class d {
|
|
|
400
447
|
abortSignal: e
|
|
401
448
|
});
|
|
402
449
|
if (n && n.length > 0) {
|
|
403
|
-
const
|
|
404
|
-
(
|
|
450
|
+
const c = this.state.get().messages, d = n.map(p.mapHistoryToMessage).filter(
|
|
451
|
+
(g) => !c.some((u) => u.id === g.id)
|
|
405
452
|
);
|
|
406
453
|
this.state.setPartial({
|
|
407
|
-
messages: [...
|
|
454
|
+
messages: [...c, ...d]
|
|
408
455
|
});
|
|
409
456
|
}
|
|
410
457
|
});
|
|
@@ -446,7 +493,7 @@ class d {
|
|
|
446
493
|
}
|
|
447
494
|
static toUserMessage(t, e) {
|
|
448
495
|
return {
|
|
449
|
-
id:
|
|
496
|
+
id: y(),
|
|
450
497
|
type: "FROM_USER",
|
|
451
498
|
content: t,
|
|
452
499
|
deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -458,7 +505,7 @@ class d {
|
|
|
458
505
|
if (t.success && t.autopilotResponse)
|
|
459
506
|
return {
|
|
460
507
|
type: "FROM_BOT",
|
|
461
|
-
id: t.autopilotResponse.id ||
|
|
508
|
+
id: t.autopilotResponse.id || y(),
|
|
462
509
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
463
510
|
component: "bot_message",
|
|
464
511
|
data: {
|
|
@@ -469,7 +516,7 @@ class d {
|
|
|
469
516
|
const e = t.uiResponse.value;
|
|
470
517
|
return {
|
|
471
518
|
type: "FROM_BOT",
|
|
472
|
-
id:
|
|
519
|
+
id: y(),
|
|
473
520
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
474
521
|
component: e.name,
|
|
475
522
|
data: e.request_response
|
|
@@ -480,7 +527,7 @@ class d {
|
|
|
480
527
|
static toErrorMessage(t) {
|
|
481
528
|
return {
|
|
482
529
|
type: "FROM_BOT",
|
|
483
|
-
id:
|
|
530
|
+
id: y(),
|
|
484
531
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
485
532
|
component: "TEXT",
|
|
486
533
|
data: {
|
|
@@ -490,28 +537,71 @@ class d {
|
|
|
490
537
|
};
|
|
491
538
|
}
|
|
492
539
|
}
|
|
493
|
-
class
|
|
540
|
+
class G {
|
|
541
|
+
constructor({
|
|
542
|
+
contactCtx: t,
|
|
543
|
+
sessionCtx: e,
|
|
544
|
+
resetChat: i
|
|
545
|
+
}) {
|
|
546
|
+
s(this, "state");
|
|
547
|
+
s(this, "contactCtx");
|
|
548
|
+
s(this, "sessionCtx");
|
|
549
|
+
s(this, "resetChat");
|
|
550
|
+
s(this, "registerRoutingListener", () => {
|
|
551
|
+
this.contactCtx.state.subscribe(({ contact: t }) => {
|
|
552
|
+
t != null && t.token && this.state.get().screen === "welcome" && this.state.setPartial({ screen: "sessions" });
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
s(this, "toSessionsScreen", () => {
|
|
556
|
+
this.resetChat(), this.state.setPartial({ screen: "sessions" });
|
|
557
|
+
});
|
|
558
|
+
/**
|
|
559
|
+
* @param sessionId The ID of the session to open, or `undefined` if it is a new chat session
|
|
560
|
+
*/
|
|
561
|
+
s(this, "toChatScreen", (t) => {
|
|
562
|
+
if (this.resetChat(), t) {
|
|
563
|
+
const e = this.sessionCtx.sessionsState.get().data.find((i) => i.id === t);
|
|
564
|
+
if (!e) return;
|
|
565
|
+
this.sessionCtx.sessionState.setPartial({ session: e });
|
|
566
|
+
}
|
|
567
|
+
this.state.setPartial({ screen: "chat" });
|
|
568
|
+
});
|
|
569
|
+
this.state = new m({
|
|
570
|
+
screen: t.shouldCollectData() ? "welcome" : "sessions"
|
|
571
|
+
}), this.contactCtx = t, this.sessionCtx = e, this.resetChat = i, this.registerRoutingListener();
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
class J {
|
|
494
575
|
constructor({ config: t }) {
|
|
495
576
|
s(this, "config");
|
|
496
577
|
s(this, "api");
|
|
497
578
|
s(this, "contactCtx");
|
|
498
579
|
s(this, "sessionCtx");
|
|
499
580
|
s(this, "messageCtx");
|
|
581
|
+
s(this, "routerCtx");
|
|
500
582
|
s(this, "resetChat", () => {
|
|
501
583
|
this.sessionCtx.reset(), this.messageCtx.reset();
|
|
502
584
|
});
|
|
503
|
-
this.config = t, this.api = new
|
|
585
|
+
this.config = t, this.api = new q({ config: t }), this.contactCtx = new B({
|
|
504
586
|
api: this.api,
|
|
505
587
|
config: this.config
|
|
506
|
-
}), this.sessionCtx = new
|
|
588
|
+
}), this.sessionCtx = new H({
|
|
589
|
+
config: this.config,
|
|
590
|
+
api: this.api,
|
|
591
|
+
contactCtx: this.contactCtx
|
|
592
|
+
}), this.messageCtx = new p({
|
|
507
593
|
config: this.config,
|
|
508
594
|
api: this.api,
|
|
509
595
|
sessionCtx: this.sessionCtx
|
|
596
|
+
}), this.routerCtx = new G({
|
|
597
|
+
contactCtx: this.contactCtx,
|
|
598
|
+
sessionCtx: this.sessionCtx,
|
|
599
|
+
resetChat: this.resetChat
|
|
510
600
|
});
|
|
511
601
|
}
|
|
512
602
|
}
|
|
513
603
|
export {
|
|
514
|
-
P,
|
|
515
|
-
W
|
|
604
|
+
m as P,
|
|
605
|
+
J as W
|
|
516
606
|
};
|
|
517
|
-
//# sourceMappingURL=widget-
|
|
607
|
+
//# sourceMappingURL=widget.ctx-CKrjZfxE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.ctx-CKrjZfxE.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 didInitialFetch: 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 didInitialFetch: false,\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(({ contact }) => {\n if (contact?.token && !this.sessionsState.get().didInitialFetch) {\n this.sessionsState.setPartial({ didInitialFetch: true });\n // Call this for the first time to get the first page of sessions\n this.loadMoreSessions();\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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"}
|