@opencx/widget 3.0.33 → 3.0.35

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.
@@ -1,23 +1,23 @@
1
- var y = Object.defineProperty;
2
- var A = (o, t, e) => t in o ? y(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
3
- var s = (o, t, e) => A(o, typeof t != "symbol" ? t + "" : t, e);
1
+ var A = Object.defineProperty;
2
+ var U = (o, t, e) => t in o ? A(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
3
+ var s = (o, t, e) => U(o, typeof t != "symbol" ? t + "" : t, e);
4
4
  import k from "axios";
5
- import U from "openapi-fetch";
6
- import M from "lodash.isequal";
7
- import { v4 as R } from "uuid";
8
- const E = (o) => {
5
+ import M from "openapi-fetch";
6
+ import R from "lodash.isequal";
7
+ import { v4 as P } from "uuid";
8
+ const T = (o) => {
9
9
  console.log(o.error);
10
- }, F = (o) => {
11
- const t = U({
10
+ }, E = (o) => {
11
+ const t = M({
12
12
  baseUrl: o.baseUrl
13
13
  }), e = {
14
14
  onRequest: o.onRequest,
15
15
  onResponse: o.onResponse,
16
- onError: o.onError || E
16
+ onError: o.onError || T
17
17
  };
18
18
  return t.use(e), t;
19
19
  };
20
- class T {
20
+ class F {
21
21
  constructor({
22
22
  config: t
23
23
  }) {
@@ -36,7 +36,7 @@ class T {
36
36
  s(this, "createOpenAPIClient", ({
37
37
  baseUrl: t,
38
38
  headers: e
39
- }) => F({
39
+ }) => E({
40
40
  baseUrl: t,
41
41
  onRequest: ({ request: i }) => {
42
42
  Object.entries(e).forEach(([a, n]) => {
@@ -118,14 +118,14 @@ class T {
118
118
  this.client = this.createOpenAPIClient({ baseUrl: e, headers: i }), this.uploadFileClient = this.createAxiosUploadClient({ baseUrl: e, headers: i });
119
119
  }
120
120
  }
121
- class g {
121
+ class f {
122
122
  constructor(t) {
123
123
  s(this, "subscribers", /* @__PURE__ */ new Set());
124
124
  s(this, "state");
125
125
  s(this, "initialState");
126
126
  s(this, "get", () => this.state);
127
127
  s(this, "set", (t) => {
128
- M(this.state, t) || (this.state = t, this.notifySubscribers(t));
128
+ R(this.state, t) || (this.state = t, this.notifySubscribers(t));
129
129
  });
130
130
  s(this, "setPartial", (t) => {
131
131
  if (t == null) return;
@@ -161,15 +161,29 @@ class O {
161
161
  s(this, "api");
162
162
  s(this, "state");
163
163
  s(this, "shouldCollectData", () => {
164
- var e;
165
- return !!(!((e = this.state.get().contact) != null && e.token) && this.config.collectUserData);
164
+ var t;
165
+ return !!(!((t = this.state.get().contact) != null && t.token) && this.config.collectUserData);
166
166
  });
167
167
  s(this, "autoCreateUnverifiedUserIfNotExists", async () => {
168
- var t, e, i, a, n;
169
- (t = this.config.user) != null && t.token || this.config.collectUserData || await this.createUnverifiedContact({
170
- name: ((i = (e = this.config.user) == null ? void 0 : e.data) == null ? void 0 : i.name) || "Anonymous",
171
- email: (n = (a = this.config.user) == null ? void 0 : a.data) == null ? void 0 : n.email
172
- });
168
+ var t, e, i, a, n, r, c, g, d, C, p;
169
+ if (!((t = this.config.user) != null && t.token)) {
170
+ if (this.config.collectUserData && !((i = (e = this.config.user) == null ? void 0 : e.data) != null && i.email)) {
171
+ const h = await ((a = this.storageCtx) == null ? void 0 : a.getContactToken());
172
+ h && await this.setUnverifiedContact(h);
173
+ return;
174
+ }
175
+ if (!((r = (n = this.config.user) == null ? void 0 : n.data) != null && r.email)) {
176
+ const h = await ((c = this.storageCtx) == null ? void 0 : c.getContactToken());
177
+ if (h) {
178
+ await this.setUnverifiedContact(h);
179
+ return;
180
+ }
181
+ }
182
+ await this.createUnverifiedContact({
183
+ name: ((d = (g = this.config.user) == null ? void 0 : g.data) == null ? void 0 : d.name) || "Anonymous",
184
+ email: (p = (C = this.config.user) == null ? void 0 : C.data) == null ? void 0 : p.email
185
+ });
186
+ }
173
187
  });
174
188
  s(this, "createUnverifiedContact", async (t) => {
175
189
  try {
@@ -178,22 +192,31 @@ class O {
178
192
  isErrorCreatingUnverifiedContact: !1
179
193
  });
180
194
  const { data: e } = await this.api.createUnverifiedContact(t);
181
- e != null && e.token ? (this.api.setAuthToken(e.token), this.state.setPartial({ contact: { token: e.token } })) : this.state.setPartial({ isErrorCreatingUnverifiedContact: !0 });
195
+ e != null && e.token ? await this.setUnverifiedContact(e.token) : this.state.setPartial({ isErrorCreatingUnverifiedContact: !0 });
182
196
  } finally {
183
197
  this.state.setPartial({ isCreatingUnverifiedContact: !1 });
184
198
  }
185
199
  });
186
- var a, n;
187
- this.config = t, this.storageCtx = i, this.api = e, this.state = new g({
188
- contact: (a = t.user) != null && a.token ? { token: (n = t.user) == null ? void 0 : n.token } : null,
200
+ s(this, "setUnverifiedContact", async (t) => {
201
+ var a, n, r, c;
202
+ const e = await ((a = this.storageCtx) == null ? void 0 : a.getExternalContactId()), i = ((n = this.config.user) == null ? void 0 : n.externalId) || e || P();
203
+ this.api.setAuthToken(t), await ((r = this.storageCtx) == null ? void 0 : r.setContactToken(t)), await ((c = this.storageCtx) == null ? void 0 : c.setExternalContactId(i)), this.state.setPartial({ contact: { token: t, externalId: i } });
204
+ });
205
+ var a;
206
+ this.config = t, this.storageCtx = i, this.api = e, this.state = new f({
207
+ contact: (a = t.user) != null && a.token ? {
208
+ token: t.user.token,
209
+ // Set optional externalId from config... not local storage
210
+ externalId: t.user.externalId
211
+ } : null,
189
212
  isCreatingUnverifiedContact: !1,
190
213
  isErrorCreatingUnverifiedContact: !1
191
214
  }), this.autoCreateUnverifiedUserIfNotExists();
192
215
  }
193
216
  }
194
- class S {
217
+ class w {
195
218
  constructor() {
196
- s(this, "state", new g({
219
+ s(this, "state", new f({
197
220
  isPolling: !1,
198
221
  isError: !1
199
222
  }));
@@ -224,25 +247,20 @@ class S {
224
247
  });
225
248
  }
226
249
  }
227
- function p() {
228
- return R();
250
+ function x() {
251
+ return P();
229
252
  }
230
253
  class _ {
231
- constructor({
232
- config: t,
233
- api: e,
234
- contactCtx: i
235
- }) {
236
- s(this, "config");
254
+ constructor({ api: t, contactCtx: e }) {
237
255
  s(this, "api");
238
256
  s(this, "contactCtx");
239
- s(this, "activeSessionPoller", new S());
240
- s(this, "sessionsRefresher", new S());
241
- s(this, "sessionState", new g({
257
+ s(this, "activeSessionPoller", new w());
258
+ s(this, "sessionsRefresher", new w());
259
+ s(this, "sessionState", new f({
242
260
  session: null,
243
261
  isCreatingSession: !1
244
262
  }));
245
- s(this, "sessionsState", new g({
263
+ s(this, "sessionsState", new f({
246
264
  data: [],
247
265
  cursor: void 0,
248
266
  isLastPage: !1,
@@ -286,14 +304,14 @@ class _ {
286
304
  }, 1e4);
287
305
  });
288
306
  s(this, "createSession", async () => {
289
- var i, a;
307
+ var a;
290
308
  this.sessionState.setPartial({ session: null, isCreatingSession: !0 });
291
- const { data: t, error: e } = await this.api.createSession({
292
- customData: (i = this.config.user) != null && i.externalId ? {
293
- external_id: (a = this.config.user) == null ? void 0 : a.externalId
309
+ const t = (a = this.contactCtx.state.get().contact) == null ? void 0 : a.externalId, { data: e, error: i } = await this.api.createSession({
310
+ customData: t ? {
311
+ external_id: t
294
312
  } : void 0
295
313
  });
296
- return t ? (this.sessionState.setPartial({ session: t, isCreatingSession: !1 }), t) : (console.error("Failed to create session:", e), null);
314
+ return e ? (this.sessionState.setPartial({ session: e, isCreatingSession: !1 }), e) : (console.error("Failed to create session:", i), null);
297
315
  });
298
316
  s(this, "loadMoreSessions", async () => {
299
317
  if (this.sessionsState.get().isLastPage) return;
@@ -312,15 +330,17 @@ class _ {
312
330
  }
313
331
  });
314
332
  s(this, "getSessions", async ({ cursor: t }) => {
315
- var e, i;
316
- return (e = this.contactCtx.state.get().contact) != null && e.token ? await this.api.getSessions({
333
+ var i, a;
334
+ if (!((i = this.contactCtx.state.get().contact) != null && i.token)) return { data: null };
335
+ const e = (a = this.contactCtx.state.get().contact) == null ? void 0 : a.externalId;
336
+ return await this.api.getSessions({
317
337
  cursor: t,
318
- filters: (i = this.config.user) != null && i.externalId ? {
319
- external_id: this.config.user.externalId
338
+ filters: e ? {
339
+ external_id: e
320
340
  } : {}
321
- }) : { data: null };
341
+ });
322
342
  });
323
- this.config = t, this.api = e, this.contactCtx = i, this.registerActiveSessionPolling(), this.registerInitialSessionsFetch();
343
+ this.api = t, this.contactCtx = e, this.registerActiveSessionPolling(), this.registerInitialSessionsFetch();
324
344
  }
325
345
  }
326
346
  class L {
@@ -332,8 +352,8 @@ class L {
332
352
  s(this, "config");
333
353
  s(this, "api");
334
354
  s(this, "sessionCtx");
335
- s(this, "poller", new S());
336
- s(this, "state", new g({
355
+ s(this, "poller", new w());
356
+ s(this, "state", new f({
337
357
  messages: [],
338
358
  isSendingMessage: !1,
339
359
  lastAIResMightSolveUserIssue: !1,
@@ -351,7 +371,7 @@ class L {
351
371
  });
352
372
  });
353
373
  s(this, "sendMessage", async (t) => {
354
- var n, r, c, d, u, m, x, b, v;
374
+ var n, r, c, g, d, C, p, h, b;
355
375
  if (!t.content.trim() && (!t.attachments || t.attachments.length === 0)) {
356
376
  console.warn("Cannot send an empty message of no content or attachments");
357
377
  return;
@@ -365,57 +385,57 @@ class L {
365
385
  this.sendMessageAbortController = new AbortController(), this.state.setPartial({ lastAIResMightSolveUserIssue: !1 });
366
386
  try {
367
387
  this.state.setPartial({ isSendingMessage: !0 });
368
- const f = this.toUserMessage(
388
+ const S = this.toUserMessage(
369
389
  t.content.trim(),
370
390
  t.attachments || void 0
371
- ), P = this.state.get().messages;
391
+ ), I = this.state.get().messages;
372
392
  if (this.state.setPartial({
373
- messages: [...P, f]
393
+ messages: [...I, S]
374
394
  }), !((r = this.sessionCtx.sessionState.get().session) != null && r.id) && !await this.sessionCtx.createSession()) {
375
395
  console.error("Failed to create session");
376
396
  return;
377
397
  }
378
- const w = (c = this.sessionCtx.sessionState.get().session) == null ? void 0 : c.id;
379
- if (!w) return;
398
+ const v = (c = this.sessionCtx.sessionState.get().session) == null ? void 0 : c.id;
399
+ if (!v) return;
380
400
  const { data: l } = await this.api.sendMessage(
381
401
  {
382
- uuid: f.id,
402
+ uuid: S.id,
383
403
  bot_token: this.config.token,
384
404
  headers: this.config.headers,
385
405
  query_params: this.config.queryParams,
386
- session_id: w,
387
- user: (d = this.config.user) == null ? void 0 : d.data,
406
+ session_id: v,
407
+ user: (g = this.config.user) == null ? void 0 : g.data,
388
408
  ...t
389
409
  },
390
410
  this.sendMessageAbortController.signal
391
411
  );
392
412
  if (l != null && l.success) {
393
- const h = this.toBotMessage(l);
394
- if (h) {
395
- const C = this.state.get().messages;
396
- if (!!C.some(
397
- (I) => I.id === h.id
413
+ const u = this.toBotMessage(l);
414
+ if (u) {
415
+ const m = this.state.get().messages;
416
+ if (!!m.some(
417
+ (y) => y.id === u.id
398
418
  )) {
399
419
  this.state.setPartial({
400
- lastAIResMightSolveUserIssue: ((u = l.autopilotResponse) == null ? void 0 : u.mightSolveUserIssue) || ((m = l.uiResponse) == null ? void 0 : m.mightSolveUserIssue)
420
+ lastAIResMightSolveUserIssue: ((d = l.autopilotResponse) == null ? void 0 : d.mightSolveUserIssue) || ((C = l.uiResponse) == null ? void 0 : C.mightSolveUserIssue)
401
421
  });
402
422
  return;
403
423
  }
404
424
  this.state.setPartial({
405
- messages: [...C, h],
406
- lastAIResMightSolveUserIssue: ((x = l.autopilotResponse) == null ? void 0 : x.mightSolveUserIssue) || ((b = l.uiResponse) == null ? void 0 : b.mightSolveUserIssue)
425
+ messages: [...m, u],
426
+ lastAIResMightSolveUserIssue: ((p = l.autopilotResponse) == null ? void 0 : p.mightSolveUserIssue) || ((h = l.uiResponse) == null ? void 0 : h.mightSolveUserIssue)
407
427
  });
408
428
  }
409
429
  } else {
410
- const h = this.toBotErrorMessage(
411
- ((v = l == null ? void 0 : l.error) == null ? void 0 : v.message) || "Unknown error occurred"
412
- ), C = this.state.get().messages;
430
+ const u = this.toBotErrorMessage(
431
+ ((b = l == null ? void 0 : l.error) == null ? void 0 : b.message) || "Unknown error occurred"
432
+ ), m = this.state.get().messages;
413
433
  this.state.setPartial({
414
- messages: [...C, h]
434
+ messages: [...m, u]
415
435
  });
416
436
  }
417
- } catch (f) {
418
- this.sendMessageAbortController.signal.aborted || console.error("Failed to send message:", f);
437
+ } catch (S) {
438
+ this.sendMessageAbortController.signal.aborted || console.error("Failed to send message:", S);
419
439
  } finally {
420
440
  this.state.setPartial({ isSendingMessage: !1 });
421
441
  }
@@ -430,7 +450,7 @@ class L {
430
450
  });
431
451
  if (a && a.length > 0) {
432
452
  const r = this.state.get().messages, c = a.map(this.mapHistoryToMessage).filter(
433
- (d) => !r.some((u) => u.id === d.id)
453
+ (g) => !r.some((d) => d.id === g.id)
434
454
  );
435
455
  this.state.setPartial({
436
456
  messages: [...r, ...c]
@@ -486,7 +506,7 @@ class L {
486
506
  };
487
507
  });
488
508
  s(this, "toUserMessage", (t, e) => ({
489
- id: p(),
509
+ id: x(),
490
510
  type: "FROM_USER",
491
511
  content: t,
492
512
  deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -497,7 +517,7 @@ class L {
497
517
  var e;
498
518
  return t.success && t.autopilotResponse ? {
499
519
  type: "FROM_BOT",
500
- id: t.autopilotResponse.id || p(),
520
+ id: t.autopilotResponse.id || x(),
501
521
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
502
522
  component: "bot_message",
503
523
  agent: this.config.bot ? {
@@ -517,7 +537,7 @@ class L {
517
537
  });
518
538
  s(this, "toBotErrorMessage", (t) => ({
519
539
  type: "FROM_BOT",
520
- id: p(),
540
+ id: x(),
521
541
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
522
542
  component: "TEXT",
523
543
  data: {
@@ -558,7 +578,7 @@ class D {
558
578
  }
559
579
  this.state.setPartial({ screen: "chat" });
560
580
  });
561
- this.state = new g({
581
+ this.state = new f({
562
582
  screen: t.shouldCollectData() ? "welcome" : "sessions"
563
583
  }), this.contactCtx = t, this.sessionCtx = e, this.resetChat = i, this.registerRoutingListener();
564
584
  }
@@ -596,12 +616,11 @@ class j {
596
616
  s(this, "resetChat", () => {
597
617
  this.sessionCtx.reset(), this.messageCtx.reset();
598
618
  });
599
- this.config = t, this.api = new T({ config: t }), this.storageCtx = e ? new B({ storage: e }) : void 0, this.contactCtx = new O({
619
+ this.config = t, this.api = new F({ config: t }), this.storageCtx = e ? new B({ storage: e }) : void 0, this.contactCtx = new O({
600
620
  api: this.api,
601
621
  config: this.config,
602
622
  storageCtx: this.storageCtx
603
623
  }), this.sessionCtx = new _({
604
- config: this.config,
605
624
  api: this.api,
606
625
  contactCtx: this.contactCtx
607
626
  }), this.messageCtx = new L({
@@ -616,7 +635,7 @@ class j {
616
635
  }
617
636
  }
618
637
  export {
619
- g as P,
638
+ f as P,
620
639
  j as W
621
640
  };
622
- //# sourceMappingURL=widget.ctx-D0ExFLNH.js.map
641
+ //# sourceMappingURL=widget.ctx-CplVbjtp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.ctx-CplVbjtp.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/storage.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/widget-config\";\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 class PrimitiveState<S> {\n private subscribers = new Set<Subscriber<S>>();\n private state: S;\n private initialState: S;\n\n constructor(state: S) {\n this.state = state;\n this.initialState = state;\n }\n\n get = (): S => this.state;\n\n set = (newState: S): void => {\n if (!isEqual(this.state, newState)) {\n this.state = newState;\n this.notifySubscribers(newState);\n }\n };\n\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 reset = (): void => {\n this.set(this.initialState);\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 if (import.meta.env.MODE !== \"test\") {\n console.error(error);\n }\n }\n });\n };\n\n subscribe = (callback: Subscriber<S>): (() => void) => {\n this.subscribers.add(callback);\n\n return () => {\n this.subscribers.delete(callback);\n };\n };\n}\n","import { PrimitiveState } from \"../utils/PrimitiveState\";\nimport { ApiCaller } from \"../api\";\nimport { type WidgetConfig } from \"../types/widget-config\";\nimport { type Dto } from \"../sdk\";\nimport type { StorageCtx } from \"./storage.ctx\";\nimport { v4 } from \"uuid\";\n\ntype ContactState = {\n contact: {\n token: string;\n externalId: string | undefined;\n } | null;\n isCreatingUnverifiedContact: boolean;\n isErrorCreatingUnverifiedContact: boolean;\n};\n\nexport class ContactCtx {\n private config: WidgetConfig;\n private storageCtx?: StorageCtx;\n private api: ApiCaller;\n state: PrimitiveState<ContactState>;\n\n constructor({\n config,\n api,\n storageCtx,\n }: {\n api: ApiCaller;\n config: WidgetConfig;\n storageCtx?: StorageCtx;\n }) {\n this.config = config;\n this.storageCtx = storageCtx;\n this.api = api;\n\n this.state = new PrimitiveState<ContactState>({\n contact: config.user?.token\n ? {\n token: config.user.token,\n // Set optional externalId from config... not local storage\n externalId: config.user.externalId,\n }\n : null,\n isCreatingUnverifiedContact: false,\n isErrorCreatingUnverifiedContact: false,\n });\n\n this.autoCreateUnverifiedUserIfNotExists();\n }\n\n shouldCollectData = (): boolean => {\n if (!this.state.get().contact?.token && this.config.collectUserData) {\n return true;\n }\n return false;\n };\n\n private autoCreateUnverifiedUserIfNotExists = async () => {\n /**\n * If token is passed in config... we consider it as a verified user and do nothing (we don't force generate an externalId)\n * If a non-verified user take their token and place it in the config... the backend will refuse their requests saying that a non-verified token must have an externalId to create and get sessions\n */\n if (this.config.user?.token) return;\n\n /**\n * If collectUserData is true... we check if the user entered their credentials before, otherwise, show them the welcome screen so they can enter their credentials\n */\n if (this.config.collectUserData && !this.config.user?.data?.email) {\n const persistedToken = await this.storageCtx?.getContactToken();\n if (persistedToken) {\n await this.setUnverifiedContact(persistedToken);\n }\n // return early whether there is a persisted token or not\n return;\n }\n\n /**\n * If there is no email, then it is an anonymous contact, we check if the contact is persisted or we create a new one\n */\n if (!this.config.user?.data?.email) {\n const persistedToken = await this.storageCtx?.getContactToken();\n if (persistedToken) {\n await this.setUnverifiedContact(persistedToken);\n // return early only if there is a persisted token\n return;\n }\n }\n\n /**\n * If we reach here... then it is one of two \n * 1. There is an email passed in the config, let's just upsert the unverified contact without checking for persistence; maybe the email in the config did change.\n * 2. It is an anonymous contact (without an email) using this device for the first time.\n * \n * This is still safe even if the email in the config is tampered with by the contact, because there is a client-side externalId that will be generated for the current device...\n * So, only sessions created on this device will be accessible.\n */\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 await this.setUnverifiedContact(data.token);\n } else {\n this.state.setPartial({ isErrorCreatingUnverifiedContact: true });\n }\n } finally {\n this.state.setPartial({ isCreatingUnverifiedContact: false });\n }\n };\n\n setUnverifiedContact = async (token: string) => {\n const persistedExternalId = await this.storageCtx?.getExternalContactId();\n /** Give priority to `externalId` from the config */\n const externalId: string =\n this.config.user?.externalId || persistedExternalId || v4();\n this.api.setAuthToken(token);\n // Set token in state after setting the token in the api handler\n await this.storageCtx?.setContactToken(token);\n await this.storageCtx?.setExternalContactId(externalId);\n this.state.setPartial({ contact: { token, externalId } });\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 private 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 }\n console.error(\"Failed to poll:\", error);\n this.state.setPartial({ isError: true });\n } finally {\n this.state.setPartial({ isPolling: false });\n }\n\n // Another check to stop scheduling polls in case someone removes the early return in the catch above\n if (this.abortController.signal.aborted) {\n console.log(\"Poller aborted, not scheduling anymore\");\n } else {\n timeouts.push(setTimeout(poll, interval));\n }\n };\n\n poll();\n\n this.stopPolling = () => {\n timeouts.forEach(clearTimeout);\n this.state.reset();\n };\n };\n}\n","import { v4 as uuidv4 } from \"uuid\";\n\nexport function genUuid() {\n return uuidv4();\n}\n","import type { ApiCaller } from \"../api\";\nimport type { SessionDto } from \"../types/schemas\";\nimport { 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 api: ApiCaller;\n private contactCtx: ContactCtx;\n private activeSessionPoller = new Poller();\n private sessionsRefresher = new Poller();\n\n public sessionState = new PrimitiveState<SessionState>({\n session: null,\n isCreatingSession: false,\n });\n public sessionsState = new PrimitiveState<SessionsState>({\n data: [],\n cursor: undefined,\n isLastPage: false,\n didStartInitialFetch: false,\n /**\n * Initialize this as `true` so it always starts loading until the first fetch is done\n */\n isInitialFetchLoading: true,\n });\n\n constructor({ api, contactCtx }: { api: ApiCaller; contactCtx: ContactCtx }) {\n this.api = api;\n this.contactCtx = contactCtx;\n\n this.registerActiveSessionPolling();\n this.registerInitialSessionsFetch();\n }\n\n /** Clears the session and stops polling */\n reset = async () => {\n // Reset the session only, leave sessions as-is\n this.sessionState.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.activeSessionPoller.reset();\n };\n\n private registerActiveSessionPolling = () => {\n this.sessionState.subscribe(({ session }) => {\n if (session?.id) {\n this.activeSessionPoller.startPolling(async (abortSignal) => {\n const { data } = await this.api.getSession({\n sessionId: session.id,\n abortSignal,\n });\n data && this.sessionState.setPartial({ session: data });\n }, 1000);\n } else {\n this.activeSessionPoller.reset();\n }\n });\n };\n\n private registerInitialSessionsFetch = () => {\n if (\n // If the widget config was initially provided with a contact token, no state change would be triggered, so we just fetch\n this.contactCtx.state.get().contact?.token &&\n !this.sessionsState.get().didStartInitialFetch\n ) {\n this.registerSessionsRefresher();\n } else {\n // In other cases where auto authenticate is fired, the token would be eventually set in state, so we wait for it\n this.contactCtx.state.subscribe(({ contact }) => {\n if (contact?.token && !this.sessionsState.get().didStartInitialFetch) {\n this.registerSessionsRefresher();\n }\n });\n }\n };\n\n private registerSessionsRefresher = () => {\n this.sessionsRefresher.startPolling(async () => {\n if (this.sessionsState.get().didStartInitialFetch === false) {\n this.sessionsState.setPartial({ didStartInitialFetch: true });\n }\n\n // Get the first page only (pass no `cursor`)\n const { data } = await this.getSessions({ cursor: undefined });\n if (!data) return;\n const sessions = [...data.items, ...this.sessionsState.get().data].filter(\n (s, i, self) => i === self.findIndex((_s) => s.id === _s.id),\n );\n this.sessionsState.setPartial({ data: sessions });\n\n if (this.sessionsState.get().isInitialFetchLoading === true) {\n this.sessionsState.setPartial({ isInitialFetchLoading: false });\n }\n }, 10000);\n };\n\n createSession = async () => {\n this.sessionState.setPartial({ session: null, isCreatingSession: true });\n\n const externalId = this.contactCtx.state.get().contact?.externalId;\n const { data: session, error } = await this.api.createSession({\n customData: externalId\n ? {\n external_id: 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\n const { data } = await this.getSessions({\n cursor: this.sessionsState.get().cursor,\n });\n\n if (data) {\n const allSessions = [...this.sessionsState.get().data, ...data.items];\n // TODO sort by updated at\n const deduped = allSessions.filter(\n (s, i, self) => i === self.findIndex((_s) => s.id === _s.id),\n );\n\n this.sessionsState.setPartial({\n data: deduped,\n cursor: data.next || undefined,\n isLastPage: data.next === null,\n });\n }\n };\n\n private getSessions = async ({ cursor }: { cursor: string | undefined }) => {\n if (!this.contactCtx.state.get().contact?.token) return { data: null };\n\n const externalId = this.contactCtx.state.get().contact?.externalId;\n return await this.api.getSessions({\n cursor,\n filters: externalId\n ? {\n external_id: externalId,\n }\n : {},\n });\n };\n}\n","import { ApiCaller } from \"../api\";\nimport type { WidgetConfig } from \"../types/widget-config\";\nimport type { SafeOmit, SomeOptional } from \"../types/helpers\";\nimport type {\n BotMessageType,\n MessageType,\n UserMessageType,\n} from \"../types/messages\";\nimport type {\n MessageAttachmentType,\n MessageDto,\n SendMessageDto,\n SendMessageOutputDto,\n} from \"../types/schemas\";\nimport { Poller } from \"../utils/Poller\";\nimport { PrimitiveState } from \"../utils/PrimitiveState\";\nimport { genUuid } from \"../utils/uuid\";\nimport { SessionCtx } from \"./session.ctx\";\n\ntype MessageCtxState = {\n messages: MessageType[];\n isSendingMessage: boolean;\n lastAIResMightSolveUserIssue: boolean;\n isInitialFetchLoading: boolean;\n};\n\nexport class MessageCtx {\n private config: WidgetConfig;\n private api: ApiCaller;\n private sessionCtx: SessionCtx;\n private poller = new Poller();\n\n public state = new PrimitiveState<MessageCtxState>({\n messages: [],\n isSendingMessage: false,\n lastAIResMightSolveUserIssue: false,\n isInitialFetchLoading: false,\n });\n\n private sendMessageAbortController = new AbortController();\n\n constructor({\n config,\n api,\n sessionCtx,\n }: { config: WidgetConfig; api: ApiCaller; sessionCtx: SessionCtx }) {\n this.config = config;\n this.api = api;\n this.sessionCtx = sessionCtx;\n\n this.registerPolling();\n }\n\n reset = () => {\n this.sendMessageAbortController.abort(\"Resetting chat\");\n this.state.reset();\n // The poller should automatically reset, since we're subscribed to the session state, and whenever it's null, the poller resets... but just in case, let's reset it here as well\n this.poller.reset();\n };\n\n private registerPolling = () => {\n this.sessionCtx.sessionState.subscribe(({ session }) => {\n if (session?.id) {\n this.poller.startPolling(async (abortSignal) => {\n await this.fetchAndSetHistory(session.id, abortSignal);\n }, 1000);\n } else {\n this.poller.reset();\n }\n });\n };\n\n sendMessage = async (\n input: SomeOptional<\n SafeOmit<SendMessageDto, \"bot_token\" | \"uuid\">,\n \"session_id\" | \"user\"\n >,\n ): Promise<void> => {\n /* ------------------------------------------------------ */\n /* Prevent sending if there is no content */\n /* ------------------------------------------------------ */\n if (\n !input.content.trim() &&\n (!input.attachments || input.attachments.length === 0)\n ) {\n console.warn(\"Cannot send an empty message of no content or attachments\");\n return;\n }\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 const lastMessage = this.state.get().messages.at(-1);\n if (\n (isAssignedToAI && isSending) ||\n // If last message is from user, then bot response did not arrive yet\n (isAssignedToAI && lastMessage?.type === \"FROM_USER\")\n ) {\n console.warn(\"Cannot send messages while awaiting AI response\");\n return;\n }\n\n this.sendMessageAbortController = new AbortController();\n\n /* ------------------------------------------------------ */\n /* Clear last AI response might solve user issue */\n /* ------------------------------------------------------ */\n this.state.setPartial({ lastAIResMightSolveUserIssue: false });\n\n try {\n this.state.setPartial({ isSendingMessage: true });\n /* ------------------------------------------------------ */\n /* Optimistically add message to rendered messages */\n /* ------------------------------------------------------ */\n const userMessage = this.toUserMessage(\n input.content.trim(),\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 = this.toBotMessage(data);\n if (botMessage) {\n const prevMessages = this.state.get().messages;\n const shouldAppend = !prevMessages.some(\n (m) => m.id === botMessage.id,\n );\n if (!shouldAppend) {\n this.state.setPartial({\n lastAIResMightSolveUserIssue:\n data.autopilotResponse?.mightSolveUserIssue ||\n data.uiResponse?.mightSolveUserIssue,\n });\n return;\n }\n this.state.setPartial({\n messages: [...prevMessages, botMessage],\n lastAIResMightSolveUserIssue:\n data.autopilotResponse?.mightSolveUserIssue ||\n data.uiResponse?.mightSolveUserIssue,\n });\n }\n } else {\n const errorMessage = this.toBotErrorMessage(\n data?.error?.message || \"Unknown error occurred\",\n );\n const currentMessages = this.state.get().messages;\n this.state.setPartial({\n messages: [...currentMessages, errorMessage],\n });\n }\n } catch (error) {\n if (!this.sendMessageAbortController.signal.aborted) {\n console.error(\"Failed to send message:\", error);\n }\n } finally {\n this.state.setPartial({ isSendingMessage: false });\n }\n };\n\n private fetchAndSetHistory = async (\n sessionId: string,\n abortSignal: AbortSignal,\n ): Promise<void> => {\n /**\n * This is a bit of an implicit contract... there are two cases here\n * 1. If there are no messages in state, it means the user selected a previous session from the sessions screen and got routed to the chat,\n * in this case, we want to show a loading indicator until the initial fetch is done\n * 2. There is a single message in state, which is the optimistically rendered user message,\n * in this case, we don't want to show a loading indicator\n */\n if (this.state.get().messages.length === 0) {\n this.state.setPartial({ isInitialFetchLoading: true });\n }\n\n const lastMessageTimestamp = this.state.get().messages.at(-1)?.timestamp;\n\n const { data: response } = await this.api.getSessionHistory({\n sessionId,\n lastMessageTimestamp,\n abortSignal,\n });\n\n if (response && response.length > 0) {\n // Get a fresh reference to current messages after the poll is done\n const prevMessages = this.state.get().messages;\n const newMessages = response\n .map(this.mapHistoryToMessage)\n .filter(\n (newMsg) =>\n !prevMessages.some((existingMsg) => existingMsg.id === newMsg.id),\n );\n this.state.setPartial({\n messages: [...prevMessages, ...newMessages],\n });\n }\n\n if (this.state.get().isInitialFetchLoading) {\n this.state.setPartial({ isInitialFetchLoading: false });\n }\n };\n\n /** Not the best name but whatever */\n private 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 agent: {\n name: history.sender.name || \"\",\n avatar: history.sender.avatar || \"\",\n id: null,\n isAi: false,\n },\n };\n }\n\n const action = history.actionCalls?.at(-1);\n return {\n ...commonFields,\n type: \"FROM_BOT\",\n component: \"bot_message\",\n agent: {\n id: null,\n name: this.config.bot?.name || \"\",\n isAi: true,\n avatar: this.config.bot?.avatar || \"\",\n },\n data: {\n message: history.content.text || \"\",\n action: action\n ? { name: action.actionName, data: action.result }\n : undefined,\n },\n };\n };\n\n private 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 toBotMessage = (\n response: SendMessageOutputDto,\n ): 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 agent: this.config.bot\n ? {\n name: this.config.bot.name || \"\",\n isAi: true,\n avatar: this.config.bot.avatar || \"\",\n id: null,\n }\n : undefined,\n data: {\n message: response.autopilotResponse.value.content,\n action: response.uiResponse?.value.name\n ? {\n name: response.uiResponse.value.name,\n data: response.uiResponse.value.request_response,\n }\n : undefined,\n },\n };\n }\n\n return null;\n };\n\n private toBotErrorMessage = (message: string): BotMessageType => {\n return {\n type: \"FROM_BOT\",\n id: genUuid(),\n timestamp: new Date().toISOString(),\n component: \"TEXT\",\n data: {\n message,\n variant: \"error\",\n action: undefined,\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 type { ExternalStorage } from \"../types/external-storage\";\n\nexport class StorageCtx {\n private storage: ExternalStorage;\n private KEYS = {\n contactToken: \"opencx__widget__contactToken\",\n externalContactId: \"opencx__widget__externalContactId\",\n };\n\n constructor({ storage }: { storage: ExternalStorage }) {\n this.storage = storage;\n }\n\n setContactToken = async (token: string) => {\n await this.storage.set(this.KEYS.contactToken, token);\n };\n getContactToken = async () => {\n return this.storage.get(this.KEYS.contactToken);\n };\n\n setExternalContactId = async (id: string) => {\n await this.storage.set(this.KEYS.externalContactId, id);\n };\n getExternalContactId = async () => {\n return this.storage.get(this.KEYS.externalContactId);\n };\n}\n","import { ApiCaller } from \"../api\";\nimport type { ExternalStorage } from \"../types/external-storage\";\nimport type { WidgetConfig } from \"../types/widget-config\";\nimport { ContactCtx } from \"./contact.ctx\";\nimport { MessageCtx } from \"./message.ctx\";\nimport { RouterCtx } from \"./router.ctx\";\nimport { SessionCtx } from \"./session.ctx\";\nimport { StorageCtx } from \"./storage.ctx\";\n\nexport class WidgetCtx {\n public config: WidgetConfig;\n public api: ApiCaller;\n\n public contactCtx: ContactCtx;\n public sessionCtx: SessionCtx;\n public messageCtx: MessageCtx;\n public routerCtx: RouterCtx;\n public storageCtx?: StorageCtx;\n\n constructor({\n config,\n storage,\n }: { config: WidgetConfig; storage?: ExternalStorage }) {\n this.config = config;\n this.api = new ApiCaller({ config });\n this.storageCtx = storage ? new StorageCtx({ storage }) : undefined;\n\n this.contactCtx = new ContactCtx({\n api: this.api,\n config: this.config,\n storageCtx: this.storageCtx,\n });\n\n this.sessionCtx = new SessionCtx({\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","newState","isEqual","_s","callback","error","ContactCtx","api","storageCtx","_c","_b","persistedToken","_d","_f","_e","_g","_i","_h","_k","_j","payload","persistedExternalId","externalId","v4","Poller","cb","interval","timeouts","poll","genUuid","uuidv4","SessionCtx","contactCtx","session","contact","sessions","s","i","self","deduped","MessageCtx","sessionCtx","input","isSending","isAssignedToAI","lastMessage","userMessage","currentMessages","botMessage","prevMessages","m","errorMessage","response","newMessages","newMsg","existingMsg","history","commonFields","action","content","attachments","message","RouterCtx","resetChat","StorageCtx","storage","id","WidgetCtx"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";var A=Object.defineProperty;var U=(o,t,e)=>t in o?A(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var s=(o,t,e)=>U(o,typeof t!="symbol"?t+"":t,e);const k=require("axios"),M=require("openapi-fetch"),R=require("lodash.isequal"),P=require("uuid"),T=o=>{console.log(o.error)},E=o=>{const t=M({baseUrl:o.baseUrl}),e={onRequest:o.onRequest,onResponse:o.onResponse,onError:o.onError||T};return t.use(e),t};class F{constructor({config:t}){s(this,"client");s(this,"uploadFileClient");s(this,"config");s(this,"constructClientOptions",t=>{const e=this.config.apiUrl||"https://api.open.cx",i={"X-Bot-Token":this.config.token,"Content-Type":"application/json",Accept:"application/json",Authorization:t?`Bearer ${t}`:void 0};return{baseUrl:e,headers:i}});s(this,"createOpenAPIClient",({baseUrl:t,headers:e})=>E({baseUrl:t,onRequest:({request:i})=>{Object.entries(e).forEach(([a,n])=>{n&&i.headers.set(a,n)})}}));s(this,"createAxiosUploadClient",({baseUrl:t,headers:e})=>k.create({baseURL:`${t}/backend/widget/v2/upload`,headers:e}));s(this,"setAuthToken",t=>{const{baseUrl:e,headers:i}=this.constructClientOptions(t);this.client=this.createOpenAPIClient({baseUrl:e,headers:i}),this.uploadFileClient=this.createAxiosUploadClient({baseUrl:e,headers:i})});s(this,"widgetPrelude",async()=>await this.client.GET("/backend/widget/v2/prelude",{params:{header:{"X-Bot-Token":this.config.token}}}));s(this,"sendMessage",async(t,e)=>await this.client.POST("/backend/widget/v2/chat/send",{body:t,signal:e}));s(this,"getSessionHistory",async({sessionId:t,lastMessageTimestamp:e,abortSignal:i})=>{const a=e?{lastMessageTimestamp:e}:void 0;return await this.client.GET("/backend/widget/v2/session/history/{sessionId}",{params:{path:{sessionId:t},query:a},signal:i})});s(this,"createUnverifiedContact",async t=>await this.client.POST("/backend/widget/v2/contact/create-unverified",{params:{header:{"x-bot-token":this.config.token}},body:t}));s(this,"createSession",async t=>await this.client.POST("/backend/widget/v2/create-session",{body:t}));s(this,"getSession",async({sessionId:t,abortSignal:e})=>await this.client.GET("/backend/widget/v2/session/{sessionId}",{params:{path:{sessionId:t}},signal:e}));s(this,"getSessions",async({cursor:t,filters:e,abortSignal:i})=>await this.client.GET("/backend/widget/v2/sessions",{params:{query:{cursor:t,filters:JSON.stringify(e)}},signal:i}));s(this,"uploadFile",async(t,e={})=>{const i=new FormData;i.append("file",t.file);const{data:a}=await this.uploadFileClient.post("",i,{headers:{"Content-Type":"multipart/form-data"},...e});return a});s(this,"vote",async t=>await this.client.POST("/backend/widget/v2/chat/vote",{body:t}));var a;this.config=t;const{baseUrl:e,headers:i}=this.constructClientOptions((a=t.user)==null?void 0:a.token);this.client=this.createOpenAPIClient({baseUrl:e,headers:i}),this.uploadFileClient=this.createAxiosUploadClient({baseUrl:e,headers:i})}}class u{constructor(t){s(this,"subscribers",new Set);s(this,"state");s(this,"initialState");s(this,"get",()=>this.state);s(this,"set",t=>{R(this.state,t)||(this.state=t,this.notifySubscribers(t))});s(this,"setPartial",t=>{if(t==null)return;const e={...this.state,...t};this.set(e)});s(this,"reset",()=>{this.set(this.initialState)});s(this,"notifySubscribers",t=>{Array.from(this.subscribers).forEach(i=>{try{i(t)}catch(a){console.error(a)}})});s(this,"subscribe",t=>(this.subscribers.add(t),()=>{this.subscribers.delete(t)}));this.state=t,this.initialState=t}}class O{constructor({config:t,api:e,storageCtx:i}){s(this,"config");s(this,"storageCtx");s(this,"api");s(this,"state");s(this,"shouldCollectData",()=>{var t;return!!(!((t=this.state.get().contact)!=null&&t.token)&&this.config.collectUserData)});s(this,"autoCreateUnverifiedUserIfNotExists",async()=>{var t,e,i,a,n,r,c,g,d,C,p;if(!((t=this.config.user)!=null&&t.token)){if(this.config.collectUserData&&!((i=(e=this.config.user)==null?void 0:e.data)!=null&&i.email)){const h=await((a=this.storageCtx)==null?void 0:a.getContactToken());h&&await this.setUnverifiedContact(h);return}if(!((r=(n=this.config.user)==null?void 0:n.data)!=null&&r.email)){const h=await((c=this.storageCtx)==null?void 0:c.getContactToken());if(h){await this.setUnverifiedContact(h);return}}await this.createUnverifiedContact({name:((d=(g=this.config.user)==null?void 0:g.data)==null?void 0:d.name)||"Anonymous",email:(p=(C=this.config.user)==null?void 0:C.data)==null?void 0:p.email})}});s(this,"createUnverifiedContact",async t=>{try{this.state.setPartial({isCreatingUnverifiedContact:!0,isErrorCreatingUnverifiedContact:!1});const{data:e}=await this.api.createUnverifiedContact(t);e!=null&&e.token?await this.setUnverifiedContact(e.token):this.state.setPartial({isErrorCreatingUnverifiedContact:!0})}finally{this.state.setPartial({isCreatingUnverifiedContact:!1})}});s(this,"setUnverifiedContact",async t=>{var a,n,r,c;const e=await((a=this.storageCtx)==null?void 0:a.getExternalContactId()),i=((n=this.config.user)==null?void 0:n.externalId)||e||P.v4();this.api.setAuthToken(t),await((r=this.storageCtx)==null?void 0:r.setContactToken(t)),await((c=this.storageCtx)==null?void 0:c.setExternalContactId(i)),this.state.setPartial({contact:{token:t,externalId:i}})});var a;this.config=t,this.storageCtx=i,this.api=e,this.state=new u({contact:(a=t.user)!=null&&a.token?{token:t.user.token,externalId:t.user.externalId}:null,isCreatingUnverifiedContact:!1,isErrorCreatingUnverifiedContact:!1}),this.autoCreateUnverifiedUserIfNotExists()}}class w{constructor(){s(this,"state",new u({isPolling:!1,isError:!1}));s(this,"abortController",new AbortController);s(this,"reset",()=>{var t;this.abortController.abort("Resetting poller"),(t=this.stopPolling)==null||t.call(this),this.stopPolling=null});s(this,"stopPolling",null);s(this,"startPolling",(t,e)=>{if(this.stopPolling)return;const i=[],a=async()=>{this.abortController=new AbortController,this.state.setPartial({isPolling:!0});try{await t(this.abortController.signal)}catch(n){if(this.abortController.signal.aborted)return;console.error("Failed to poll:",n),this.state.setPartial({isError:!0})}finally{this.state.setPartial({isPolling:!1})}this.abortController.signal.aborted?console.log("Poller aborted, not scheduling anymore"):i.push(setTimeout(a,e))};a(),this.stopPolling=()=>{i.forEach(clearTimeout),this.state.reset()}})}}function x(){return P.v4()}class _{constructor({api:t,contactCtx:e}){s(this,"api");s(this,"contactCtx");s(this,"activeSessionPoller",new w);s(this,"sessionsRefresher",new w);s(this,"sessionState",new u({session:null,isCreatingSession:!1}));s(this,"sessionsState",new u({data:[],cursor:void 0,isLastPage:!1,didStartInitialFetch:!1,isInitialFetchLoading:!0}));s(this,"reset",async()=>{this.sessionState.reset(),this.activeSessionPoller.reset()});s(this,"registerActiveSessionPolling",()=>{this.sessionState.subscribe(({session:t})=>{t!=null&&t.id?this.activeSessionPoller.startPolling(async e=>{const{data:i}=await this.api.getSession({sessionId:t.id,abortSignal:e});i&&this.sessionState.setPartial({session:i})},1e3):this.activeSessionPoller.reset()})});s(this,"registerInitialSessionsFetch",()=>{var t;(t=this.contactCtx.state.get().contact)!=null&&t.token&&!this.sessionsState.get().didStartInitialFetch?this.registerSessionsRefresher():this.contactCtx.state.subscribe(({contact:e})=>{e!=null&&e.token&&!this.sessionsState.get().didStartInitialFetch&&this.registerSessionsRefresher()})});s(this,"registerSessionsRefresher",()=>{this.sessionsRefresher.startPolling(async()=>{this.sessionsState.get().didStartInitialFetch===!1&&this.sessionsState.setPartial({didStartInitialFetch:!0});const{data:t}=await this.getSessions({cursor:void 0});if(!t)return;const e=[...t.items,...this.sessionsState.get().data].filter((i,a,n)=>a===n.findIndex(r=>i.id===r.id));this.sessionsState.setPartial({data:e}),this.sessionsState.get().isInitialFetchLoading===!0&&this.sessionsState.setPartial({isInitialFetchLoading:!1})},1e4)});s(this,"createSession",async()=>{var a;this.sessionState.setPartial({session:null,isCreatingSession:!0});const t=(a=this.contactCtx.state.get().contact)==null?void 0:a.externalId,{data:e,error:i}=await this.api.createSession({customData:t?{external_id:t}:void 0});return e?(this.sessionState.setPartial({session:e,isCreatingSession:!1}),e):(console.error("Failed to create session:",i),null)});s(this,"loadMoreSessions",async()=>{if(this.sessionsState.get().isLastPage)return;const{data:t}=await this.getSessions({cursor:this.sessionsState.get().cursor});if(t){const i=[...this.sessionsState.get().data,...t.items].filter((a,n,r)=>n===r.findIndex(c=>a.id===c.id));this.sessionsState.setPartial({data:i,cursor:t.next||void 0,isLastPage:t.next===null})}});s(this,"getSessions",async({cursor:t})=>{var i,a;if(!((i=this.contactCtx.state.get().contact)!=null&&i.token))return{data:null};const e=(a=this.contactCtx.state.get().contact)==null?void 0:a.externalId;return await this.api.getSessions({cursor:t,filters:e?{external_id:e}:{}})});this.api=t,this.contactCtx=e,this.registerActiveSessionPolling(),this.registerInitialSessionsFetch()}}class q{constructor({config:t,api:e,sessionCtx:i}){s(this,"config");s(this,"api");s(this,"sessionCtx");s(this,"poller",new w);s(this,"state",new u({messages:[],isSendingMessage:!1,lastAIResMightSolveUserIssue:!1,isInitialFetchLoading:!1}));s(this,"sendMessageAbortController",new AbortController);s(this,"reset",()=>{this.sendMessageAbortController.abort("Resetting chat"),this.state.reset(),this.poller.reset()});s(this,"registerPolling",()=>{this.sessionCtx.sessionState.subscribe(({session:t})=>{t!=null&&t.id?this.poller.startPolling(async e=>{await this.fetchAndSetHistory(t.id,e)},1e3):this.poller.reset()})});s(this,"sendMessage",async t=>{var n,r,c,g,d,C,p,h,b;if(!t.content.trim()&&(!t.attachments||t.attachments.length===0)){console.warn("Cannot send an empty message of no content or attachments");return}const e=this.state.get().isSendingMessage,i=((n=this.sessionCtx.sessionState.get().session)==null?void 0:n.assignee.kind)==="ai",a=this.state.get().messages.at(-1);if(i&&e||i&&(a==null?void 0:a.type)==="FROM_USER"){console.warn("Cannot send messages while awaiting AI response");return}this.sendMessageAbortController=new AbortController,this.state.setPartial({lastAIResMightSolveUserIssue:!1});try{this.state.setPartial({isSendingMessage:!0});const S=this.toUserMessage(t.content.trim(),t.attachments||void 0),I=this.state.get().messages;if(this.state.setPartial({messages:[...I,S]}),!((r=this.sessionCtx.sessionState.get().session)!=null&&r.id)&&!await this.sessionCtx.createSession()){console.error("Failed to create session");return}const v=(c=this.sessionCtx.sessionState.get().session)==null?void 0:c.id;if(!v)return;const{data:l}=await this.api.sendMessage({uuid:S.id,bot_token:this.config.token,headers:this.config.headers,query_params:this.config.queryParams,session_id:v,user:(g=this.config.user)==null?void 0:g.data,...t},this.sendMessageAbortController.signal);if(l!=null&&l.success){const f=this.toBotMessage(l);if(f){const m=this.state.get().messages;if(!!m.some(y=>y.id===f.id)){this.state.setPartial({lastAIResMightSolveUserIssue:((d=l.autopilotResponse)==null?void 0:d.mightSolveUserIssue)||((C=l.uiResponse)==null?void 0:C.mightSolveUserIssue)});return}this.state.setPartial({messages:[...m,f],lastAIResMightSolveUserIssue:((p=l.autopilotResponse)==null?void 0:p.mightSolveUserIssue)||((h=l.uiResponse)==null?void 0:h.mightSolveUserIssue)})}}else{const f=this.toBotErrorMessage(((b=l==null?void 0:l.error)==null?void 0:b.message)||"Unknown error occurred"),m=this.state.get().messages;this.state.setPartial({messages:[...m,f]})}}catch(S){this.sendMessageAbortController.signal.aborted||console.error("Failed to send message:",S)}finally{this.state.setPartial({isSendingMessage:!1})}});s(this,"fetchAndSetHistory",async(t,e)=>{var n;this.state.get().messages.length===0&&this.state.setPartial({isInitialFetchLoading:!0});const i=(n=this.state.get().messages.at(-1))==null?void 0:n.timestamp,{data:a}=await this.api.getSessionHistory({sessionId:t,lastMessageTimestamp:i,abortSignal:e});if(a&&a.length>0){const r=this.state.get().messages,c=a.map(this.mapHistoryToMessage).filter(g=>!r.some(d=>d.id===g.id));this.state.setPartial({messages:[...r,...c]})}this.state.get().isInitialFetchLoading&&this.state.setPartial({isInitialFetchLoading:!1})});s(this,"mapHistoryToMessage",t=>{var a,n,r;const e={id:t.publicId,timestamp:t.sentAt||"",attachments:t.attachments||void 0};if(t.sender.kind==="user")return{...e,type:"FROM_USER",content:t.content.text||"",deliveredAt:t.sentAt||""};if(t.sender.kind==="agent")return{...e,type:"FROM_AGENT",component:"agent_message",data:{message:t.content.text||""},agent:{name:t.sender.name||"",avatar:t.sender.avatar||"",id:null,isAi:!1}};const i=(a=t.actionCalls)==null?void 0:a.at(-1);return{...e,type:"FROM_BOT",component:"bot_message",agent:{id:null,name:((n=this.config.bot)==null?void 0:n.name)||"",isAi:!0,avatar:((r=this.config.bot)==null?void 0:r.avatar)||""},data:{message:t.content.text||"",action:i?{name:i.actionName,data:i.result}:void 0}}});s(this,"toUserMessage",(t,e)=>({id:x(),type:"FROM_USER",content:t,deliveredAt:new Date().toISOString(),attachments:e,timestamp:new Date().toISOString()}));s(this,"toBotMessage",t=>{var e;return t.success&&t.autopilotResponse?{type:"FROM_BOT",id:t.autopilotResponse.id||x(),timestamp:new Date().toISOString(),component:"bot_message",agent:this.config.bot?{name:this.config.bot.name||"",isAi:!0,avatar:this.config.bot.avatar||"",id:null}:void 0,data:{message:t.autopilotResponse.value.content,action:(e=t.uiResponse)!=null&&e.value.name?{name:t.uiResponse.value.name,data:t.uiResponse.value.request_response}:void 0}}:null});s(this,"toBotErrorMessage",t=>({type:"FROM_BOT",id:x(),timestamp:new Date().toISOString(),component:"TEXT",data:{message:t,variant:"error",action:void 0}}));this.config=t,this.api=e,this.sessionCtx=i,this.registerPolling()}}class L{constructor({contactCtx:t,sessionCtx:e,resetChat:i}){s(this,"state");s(this,"contactCtx");s(this,"sessionCtx");s(this,"resetChat");s(this,"registerRoutingListener",()=>{this.contactCtx.state.subscribe(({contact:t})=>{t!=null&&t.token&&this.state.get().screen==="welcome"&&this.state.setPartial({screen:"sessions"})})});s(this,"toSessionsScreen",()=>{this.resetChat(),this.state.setPartial({screen:"sessions"})});s(this,"toChatScreen",t=>{if(this.resetChat(),t){const e=this.sessionCtx.sessionsState.get().data.find(i=>i.id===t);if(!e)return;this.sessionCtx.sessionState.setPartial({session:e})}this.state.setPartial({screen:"chat"})});this.state=new u({screen:t.shouldCollectData()?"welcome":"sessions"}),this.contactCtx=t,this.sessionCtx=e,this.resetChat=i,this.registerRoutingListener()}}class D{constructor({storage:t}){s(this,"storage");s(this,"KEYS",{contactToken:"opencx__widget__contactToken",externalContactId:"opencx__widget__externalContactId"});s(this,"setContactToken",async t=>{await this.storage.set(this.KEYS.contactToken,t)});s(this,"getContactToken",async()=>this.storage.get(this.KEYS.contactToken));s(this,"setExternalContactId",async t=>{await this.storage.set(this.KEYS.externalContactId,t)});s(this,"getExternalContactId",async()=>this.storage.get(this.KEYS.externalContactId));this.storage=t}}class B{constructor({config:t,storage:e}){s(this,"config");s(this,"api");s(this,"contactCtx");s(this,"sessionCtx");s(this,"messageCtx");s(this,"routerCtx");s(this,"storageCtx");s(this,"resetChat",()=>{this.sessionCtx.reset(),this.messageCtx.reset()});this.config=t,this.api=new F({config:t}),this.storageCtx=e?new D({storage:e}):void 0,this.contactCtx=new O({api:this.api,config:this.config,storageCtx:this.storageCtx}),this.sessionCtx=new _({api:this.api,contactCtx:this.contactCtx}),this.messageCtx=new q({config:this.config,api:this.api,sessionCtx:this.sessionCtx}),this.routerCtx=new L({contactCtx:this.contactCtx,sessionCtx:this.sessionCtx,resetChat:this.resetChat})}}exports.PrimitiveState=u;exports.WidgetCtx=B;
2
+ //# sourceMappingURL=widget.ctx-D_AFA5p3.cjs.map