@opencx/widget 2.4.3 → 2.4.4-rn.1

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.
Files changed (49) hide show
  1. package/README.md +30 -30
  2. package/dist/basic.cjs +51 -51
  3. package/dist/basic.cjs.map +1 -1
  4. package/dist/basic.js +1983 -1981
  5. package/dist/basic.js.map +1 -1
  6. package/dist/core/client/api.d.ts +36 -6
  7. package/dist/core/client/chat.d.ts +10 -20
  8. package/dist/core/client/config.d.ts +2 -3
  9. package/dist/core/client/contact.d.ts +13 -12
  10. package/dist/core/client/index.d.ts +1 -0
  11. package/dist/core/index.d.ts +2 -1
  12. package/dist/core/platform/index.d.ts +5 -5
  13. package/dist/core/platform/logger.d.ts +14 -0
  14. package/dist/core/platform/storage.d.ts +46 -0
  15. package/dist/core/types/helpers.d.ts +12 -0
  16. package/dist/core/types/index.d.ts +1 -1
  17. package/dist/core/types/messages.d.ts +2 -2
  18. package/dist/core/types/pub-sub.d.ts +24 -8
  19. package/dist/core/types/schemas-v2.d.ts +22 -25
  20. package/dist/{index-Bb4FAD9K.cjs → index-Bx4hrNc7.cjs} +3 -3
  21. package/dist/index-Bx4hrNc7.cjs.map +1 -0
  22. package/dist/{index-D2ByqkLZ.js → index-ENMg5VOh.js} +92 -87
  23. package/dist/index-ENMg5VOh.js.map +1 -0
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +753 -336
  27. package/dist/index.js.map +1 -1
  28. package/dist/package.json.d.ts +156 -0
  29. package/dist/react.cjs +1 -1
  30. package/dist/react.cjs.map +1 -1
  31. package/dist/react.js +1 -1
  32. package/dist/react.js.map +1 -1
  33. package/dist/schemas-BBAV6Sd_.js.map +1 -1
  34. package/dist/schemas-wky4fpbc.cjs.map +1 -1
  35. package/dist/style.css +1 -1
  36. package/dist-embed/script.js +5 -5
  37. package/dist-embed/script.js.map +1 -1
  38. package/package.json +3 -1
  39. package/dist/core/client/chat.test.d.ts +0 -1
  40. package/dist/core/client/client.d.ts +0 -9
  41. package/dist/core/client/config.test.d.ts +0 -1
  42. package/dist/core/client/contact.test.d.ts +0 -1
  43. package/dist/index-Bb4FAD9K.cjs.map +0 -1
  44. package/dist/index-D2ByqkLZ.js.map +0 -1
  45. package/dist/react-bindings/context/ChatContext.d.ts +0 -127
  46. package/dist/react-bindings/hooks/useContact.d.ts +0 -9
  47. package/dist/react-bindings/hooks/usePubsub.d.ts +0 -3
  48. package/dist/react-bindings/hooks/useSendMessage.d.ts +0 -6
  49. package/dist/react-bindings/index.d.ts +0 -3
package/dist/index.js CHANGED
@@ -1,449 +1,866 @@
1
- var P = Object.defineProperty;
2
- var w = (t) => {
1
+ var x = Object.defineProperty;
2
+ var N = (t) => {
3
3
  throw TypeError(t);
4
4
  };
5
- var v = (t, e, s) => e in t ? P(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
6
- var E = (t, e, s) => v(t, typeof e != "symbol" ? e + "" : e, s), O = (t, e, s) => e.has(t) || w("Cannot " + s);
7
- var d = (t, e, s) => (O(t, e, "read from private field"), s ? s.call(t) : e.get(t)), b = (t, e, s) => e.has(t) ? w("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, s), f = (t, e, s, r) => (O(t, e, "write to private field"), r ? r.call(t, s) : e.set(t, s), s);
8
- import { g as y } from "./schemas-BBAV6Sd_.js";
9
- import { A as V, M as K, b as Q, a as W, S as Y, d as Z, e as ee, c as te, f as se, s as re } from "./schemas-BBAV6Sd_.js";
10
- var h;
11
- class S {
5
+ var q = (t, e, s) => e in t ? x(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
6
+ var S = (t, e, s) => q(t, typeof e != "symbol" ? e + "" : e, s), D = (t, e, s) => e.has(t) || N("Cannot " + s);
7
+ var h = (t, e, s) => (D(t, e, "read from private field"), s ? s.call(t) : e.get(t)), M = (t, e, s) => e.has(t) ? N("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, s), P = (t, e, s, o) => (D(t, e, "write to private field"), o ? o.call(t, s) : e.set(t, s), s);
8
+ import j from "lodash.isequal";
9
+ import { g as _ } from "./schemas-BBAV6Sd_.js";
10
+ import { A as de, M as fe, b as me, a as ge, S as he, d as Se, e as pe, c as Ee, f as ye, s as be } from "./schemas-BBAV6Sd_.js";
11
+ var H = /* @__PURE__ */ ((t) => (t.INIT = "init", t.STATE_CHANGE = "stateChange", t.BEFORE_UPDATE = "beforeUpdate", t.AFTER_UPDATE = "afterUpdate", t.DESTROY = "destroy", t.ERROR = "error", t))(H || {}), y, L;
12
+ class C {
12
13
  constructor(e) {
13
- E(this, "subscribers", /* @__PURE__ */ new Set());
14
- b(this, h);
15
- E(this, "initialState");
16
- f(this, h, e), this.initialState = e;
17
- }
18
- /**
19
- * Subscribe to state changes
20
- * @param callback Function to call when state changes
21
- * @returns Unsubscribe function
22
- */
23
- subscribe(e) {
24
- return this.subscribers.add(e), () => {
14
+ S(this, "subscribers", /* @__PURE__ */ new Set());
15
+ M(this, y);
16
+ S(this, "initialState");
17
+ M(this, L);
18
+ S(this, "lifecycleListeners", /* @__PURE__ */ new Map());
19
+ S(this, "emitLifecycle", (e, s) => {
20
+ const o = this.lifecycleListeners.get(e);
21
+ if (o) {
22
+ const d = {
23
+ type: e,
24
+ timestamp: Date.now(),
25
+ data: s
26
+ };
27
+ o.forEach((n) => n(d));
28
+ }
29
+ });
30
+ /**
31
+ * Subscribe to state changes
32
+ * @param callback Function to call when state changes
33
+ * @returns Unsubscribe function
34
+ */
35
+ S(this, "subscribe", (e) => (this.subscribers.add(e), e(h(this, y)), () => {
25
36
  this.subscribers.delete(e);
26
- };
37
+ }));
38
+ S(this, "onLifecycle", (e, s) => {
39
+ this.lifecycleListeners.has(e) || this.lifecycleListeners.set(e, /* @__PURE__ */ new Set());
40
+ const o = this.lifecycleListeners.get(e);
41
+ return o.add(s), () => {
42
+ o.delete(s), o.size === 0 && this.lifecycleListeners.delete(e);
43
+ };
44
+ });
45
+ /**
46
+ * Get the current state
47
+ */
48
+ S(this, "getState", () => h(this, y));
49
+ /**
50
+ * Set the state and notify subscribers if the state changes
51
+ * @param newState The new state to set
52
+ */
53
+ S(this, "setState", (e) => {
54
+ this.emitLifecycle("beforeUpdate", {
55
+ previousState: h(this, y),
56
+ nextState: e
57
+ }), j(h(this, y), e) || (P(this, y, e), P(this, L, Date.now()), this.emitLifecycle("stateChange", { state: e }), this.subscribers.forEach((s) => {
58
+ try {
59
+ s(e);
60
+ } catch (o) {
61
+ this.emitLifecycle("error", { error: o });
62
+ }
63
+ })), this.emitLifecycle("afterUpdate", { state: e });
64
+ });
65
+ S(this, "setStatePartial", (e) => {
66
+ const s = { ...h(this, y), ...e };
67
+ this.setState(s);
68
+ });
69
+ /**
70
+ * Clear all subscriptions
71
+ */
72
+ S(this, "clear", () => {
73
+ this.emitLifecycle(
74
+ "destroy"
75
+ /* DESTROY */
76
+ ), this.subscribers.clear(), this.lifecycleListeners.clear();
77
+ });
78
+ S(this, "reset", () => {
79
+ this.setState(this.initialState);
80
+ });
81
+ S(this, "lastUpdated", () => h(this, L));
82
+ P(this, y, e), this.initialState = e, P(this, L, Date.now()), this.emitLifecycle("init", { initialState: h(this, y) });
27
83
  }
28
- /**
29
- * Get the current state
30
- */
31
- getState() {
32
- return d(this, h);
84
+ }
85
+ y = new WeakMap(), L = new WeakMap();
86
+ function W(t) {
87
+ return new C(t);
88
+ }
89
+ class v extends Error {
90
+ constructor(e) {
91
+ super(e), this.name = "OpenCXError";
33
92
  }
34
- /**
35
- * Set the state and notify subscribers if the state changes
36
- * @param newState The new state to set
37
- */
38
- setState(e) {
39
- d(this, h) !== e && (f(this, h, e), this.subscribers.forEach((s) => s(e)));
93
+ }
94
+ class Z extends v {
95
+ constructor(e = "Connection failed") {
96
+ super(e), this.name = "ConnectionError";
40
97
  }
41
- setStatePartial(e) {
42
- const s = { ...d(this, h), ...e };
43
- this.setState(s);
98
+ }
99
+ class ee extends v {
100
+ constructor(e = "Authentication failed") {
101
+ super(e), this.name = "AuthenticationError";
44
102
  }
45
- /**
46
- * Clear all subscriptions
47
- */
48
- clear() {
49
- this.subscribers.clear();
103
+ }
104
+ class B extends v {
105
+ constructor(e = "Session error occurred") {
106
+ super(e), this.name = "SessionError";
50
107
  }
51
- reset() {
52
- this.setState(this.initialState);
108
+ }
109
+ class te extends B {
110
+ constructor(e = "Session not defined") {
111
+ super(e), this.name = "SessionNotDefinedError";
53
112
  }
54
- getSnapshot() {
55
- return d(this, h);
113
+ }
114
+ class se extends v {
115
+ constructor(e = "Transport error occurred") {
116
+ super(e), this.name = "TransportError";
56
117
  }
57
- get state() {
58
- return d(this, h);
118
+ }
119
+ class re extends v {
120
+ constructor(e = "File upload failed") {
121
+ super(e), this.name = "FileUploadError";
59
122
  }
60
123
  }
61
- h = new WeakMap();
62
- function $(t) {
63
- return new S(t);
124
+ function T(t) {
125
+ if (!t) return !1;
126
+ try {
127
+ return typeof t.isAvailable == "function" ? t.isAvailable() : !0;
128
+ } catch {
129
+ return !1;
130
+ }
64
131
  }
65
- const I = 1e4, T = 5e3;
66
- function C(t) {
67
- var e, s, r;
132
+ async function O(t, e) {
133
+ try {
134
+ return { success: !0, result: await t() };
135
+ } catch (s) {
136
+ return console.error(e, s), {
137
+ success: !1,
138
+ error: s instanceof Error ? s : new Error(e)
139
+ };
140
+ }
141
+ }
142
+ const R = {
143
+ SESSION: 1e4,
144
+ // every 10 seconds
145
+ MESSAGES: 5e3
146
+ // every 5 seconds
147
+ };
148
+ function k(t) {
149
+ const e = {
150
+ id: t.publicId || _(),
151
+ timestamp: t.sentAt || "",
152
+ attachments: t.attachments || void 0
153
+ };
68
154
  return t.sender.kind === "user" ? {
69
- id: t.publicId || y(),
155
+ ...e,
70
156
  type: "FROM_USER",
71
157
  content: t.content.text || "",
72
- deliveredAt: ((e = t.sentAt) == null ? void 0 : e.toISOString()) || null,
73
- attachments: t.attachments || void 0,
74
- timestamp: (s = t.sentAt) == null ? void 0 : s.toISOString()
158
+ deliveredAt: t.sentAt || ""
75
159
  } : {
76
- id: t.publicId || y(),
160
+ ...e,
77
161
  type: "FROM_BOT",
78
- component: t.type,
79
- data: {
80
- text: t.content.text
162
+ component: "TEXT",
163
+ agent: {
164
+ id: null,
165
+ name: t.sender.name || "",
166
+ is_ai: t.sender.kind === "ai",
167
+ profile_picture: t.sender.avatar
81
168
  },
82
- timestamp: (r = t.sentAt) == null ? void 0 : r.toISOString(),
83
- attachments: t.attachments || void 0
169
+ data: {
170
+ message: t.content.text
171
+ }
84
172
  };
85
173
  }
86
- function A(t, e, s) {
87
- const r = [];
88
- return r.push(
89
- setInterval(async () => {
90
- const n = e.getState();
91
- if (n != null && n.id)
92
- try {
93
- const a = await t.getSession(n.id);
94
- a && e.setState(a);
95
- } catch (a) {
96
- console.error("Error polling session:", a);
97
- }
98
- }, I)
99
- ), r.push(
100
- setInterval(async () => {
101
- const n = e.getState();
102
- if (n != null && n.id)
103
- try {
104
- const a = await t.getSessionHistory(n.id);
105
- if (a) {
106
- const l = a.map(C);
107
- s.setStatePartial({
108
- messages: l,
109
- lastUpdated: Date.now()
110
- });
111
- }
112
- } catch (a) {
113
- console.error("Error polling messages:", a);
174
+ function J(t, e, s) {
175
+ async function o(i) {
176
+ const c = e.getState().messages;
177
+ if (c.length === 0) {
178
+ s == null || s.debug("No messages yet, fetching all history", { sessionId: i.id });
179
+ const g = await t.getSessionHistory(i.id, "");
180
+ g && g.length > 0 && e.setStatePartial({
181
+ messages: g.map(k)
182
+ });
183
+ return;
184
+ }
185
+ const l = c[c.length - 1], r = new Date(l.timestamp);
186
+ r.setSeconds(r.getSeconds() + 1);
187
+ const u = r.toISOString();
188
+ s == null || s.debug("Fetching history messages after timestamp", {
189
+ sessionId: i.id,
190
+ lastMessageTimestamp: u,
191
+ currentMessageCount: c.length
192
+ });
193
+ const E = await t.getSessionHistory(i.id, u);
194
+ if (E && E.length > 0) {
195
+ const g = E.map(k).filter((p) => !c.some((I) => I.id === p.id));
196
+ g.length > 0 && (s == null || s.debug("Adding new messages to state", {
197
+ count: g.length,
198
+ messageIds: g.map((p) => p.id),
199
+ messageTypes: g.map((p) => p.type)
200
+ }), e.setStatePartial({
201
+ messages: [...c, ...g]
202
+ }));
203
+ }
204
+ }
205
+ function d(i, c) {
206
+ return {
207
+ id: _(),
208
+ type: "FROM_USER",
209
+ content: i,
210
+ deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
211
+ attachments: c,
212
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
213
+ };
214
+ }
215
+ function n(i) {
216
+ if (i.success && i.autopilotResponse)
217
+ return {
218
+ type: "FROM_BOT",
219
+ id: i.autopilotResponse.id || _(),
220
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
221
+ component: "TEXT",
222
+ data: {
223
+ message: i.autopilotResponse.value.content
114
224
  }
115
- }, T)
116
- ), () => r.forEach(clearInterval);
225
+ };
226
+ if (i.success && i.uiResponse) {
227
+ const c = i.uiResponse.value;
228
+ return {
229
+ type: "FROM_BOT",
230
+ id: _(),
231
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
232
+ component: c.name,
233
+ data: c.request_response
234
+ };
235
+ }
236
+ return null;
237
+ }
238
+ function a(i) {
239
+ return {
240
+ type: "FROM_BOT",
241
+ id: _(),
242
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
243
+ component: "TEXT",
244
+ data: {
245
+ message: i,
246
+ variant: "error"
247
+ }
248
+ };
249
+ }
250
+ return {
251
+ fetchHistoryMessages: o,
252
+ addUserMessage: d,
253
+ addBotMessage: n,
254
+ addErrorMessage: a
255
+ };
117
256
  }
118
- function L(t) {
119
- const e = new S({
120
- lastUpdated: null,
121
- messages: [],
122
- keyboard: null
123
- }), s = new S(null);
124
- let r = null;
125
- async function n() {
126
- const o = await t.api.createSession();
127
- return s.setState(o), r || (r = A(t.api, s, e)), o;
257
+ function G(t, e, s, o, d, n) {
258
+ var F, U;
259
+ const a = (F = n.platform) == null ? void 0 : F.logger;
260
+ let i = null;
261
+ const c = (U = n.platform) == null ? void 0 : U.storage, l = `${d.getConfig().user.external_id}:${d.getConfig().token}:session`, r = n.config.getSettings().persistSession;
262
+ async function u() {
263
+ if (c)
264
+ try {
265
+ a == null || a.debug("Attempting to restore session from storage");
266
+ const f = await c.getItem(l);
267
+ if (f) {
268
+ const m = JSON.parse(f);
269
+ a == null || a.info("Session restored from storage", { sessionId: m.id }), e.setState(m), await o.fetchHistoryMessages(m), g();
270
+ }
271
+ } catch (f) {
272
+ a == null || a.error("Error restoring session from storage:", f);
273
+ }
128
274
  }
129
- async function a() {
130
- var i;
131
- const o = s.getState();
132
- if (o != null && o.id)
275
+ function E() {
276
+ c && (a == null || a.debug("Setting up session persistence"), e.subscribe(async (f) => {
133
277
  try {
134
- r && (r(), r = null), s.setState(null), e.setState({
135
- lastUpdated: null,
136
- messages: [],
137
- keyboard: null
138
- }), (i = t.onSessionDestroy) == null || i.call(t);
139
- } catch (u) {
140
- throw console.error("Error clearing session:", u), u;
278
+ f ? (await c.setItem(l, JSON.stringify(f)), a == null || a.debug("Session persisted to storage", { sessionId: f.id })) : (await c.removeItem(l), a == null || a.debug("Session removed from storage"));
279
+ } catch (m) {
280
+ a == null || a.error("Error persisting session:", m), s.setStatePartial({
281
+ error: {
282
+ hasError: !0,
283
+ message: m instanceof Error ? m.message : "Failed to persist session",
284
+ code: "SESSION_PERSISTENCE_FAILED"
285
+ }
286
+ });
141
287
  }
288
+ }));
142
289
  }
143
- function l() {
144
- r && (r(), r = null), e.setState({
145
- lastUpdated: null,
146
- messages: [],
147
- keyboard: null
148
- }), s.setState(null), e.clear(), s.clear();
290
+ function g() {
291
+ if (i) return;
292
+ a == null || a.debug("Starting polling");
293
+ const f = [];
294
+ f.push(
295
+ setInterval(async () => {
296
+ const m = e.getState();
297
+ if (m != null && m.id)
298
+ try {
299
+ const w = await t.getSession(m.id);
300
+ w && e.setState(w);
301
+ } catch (w) {
302
+ a == null || a.error("Error polling session:", w);
303
+ }
304
+ }, R.SESSION)
305
+ ), f.push(
306
+ setInterval(async () => {
307
+ const m = e.getState();
308
+ if (m != null && m.id)
309
+ try {
310
+ await o.fetchHistoryMessages(m);
311
+ } catch (w) {
312
+ a == null || a.error("Error polling messages:", w);
313
+ }
314
+ }, R.MESSAGES)
315
+ ), i = () => {
316
+ a == null || a.debug("Stopping polling"), f.forEach(clearInterval);
317
+ };
149
318
  }
150
- return {
151
- chatState: e,
152
- sessionState: s,
153
- sendMessage: async (o) => {
154
- const i = s.getState();
155
- if (!(i != null && i.id))
156
- throw new Error("No active session");
157
- const u = {
158
- ...o,
159
- session_id: i.id
319
+ async function p() {
320
+ try {
321
+ a == null || a.info("Creating new session"), s.setStatePartial({
322
+ loading: { isLoading: !0, reason: "creating_session" },
323
+ error: { hasError: !1 }
324
+ });
325
+ const f = await t.createSession();
326
+ return a == null || a.info("Session created successfully", { sessionId: f.id }), e.setState(f), g(), f;
327
+ } catch (f) {
328
+ a == null || a.error("Failed to create session:", f);
329
+ const m = {
330
+ hasError: !0,
331
+ message: f instanceof Error ? f.message : "Failed to create session",
332
+ code: "SESSION_CREATION_FAILED"
160
333
  };
334
+ return s.setStatePartial({ error: m }), null;
335
+ } finally {
336
+ s.setStatePartial({
337
+ loading: { isLoading: !1, reason: null }
338
+ });
339
+ }
340
+ }
341
+ async function I() {
342
+ var m;
343
+ const f = e.getState();
344
+ if (f != null && f.id)
161
345
  try {
162
- e.setStatePartial({
163
- messages: [
164
- ...e.getState().messages,
165
- {
166
- id: o.id || y(),
167
- type: "FROM_USER",
168
- content: o.content.text,
169
- deliveredAt: (/* @__PURE__ */ new Date()).toISOString(),
170
- attachments: o.attachments,
171
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
172
- }
173
- ]
174
- }), await t.api.handleMessage(u);
175
- } catch (m) {
176
- throw console.error("Error sending message:", m), m;
346
+ i && (i(), i = null), e.setState(null), r && c && T(c) && c.removeItem(l), s.setState({
347
+ messages: [],
348
+ keyboard: null,
349
+ loading: { isLoading: !1 },
350
+ error: { hasError: !1 }
351
+ }), (m = n.onSessionDestroy) == null || m.call(n);
352
+ } catch (w) {
353
+ console.error("Error clearing session:", w), s.setStatePartial({
354
+ error: {
355
+ hasError: !0,
356
+ message: w instanceof Error ? w.message : "Failed to clear session",
357
+ code: "SESSION_CLEAR_FAILED"
358
+ }
359
+ });
177
360
  }
178
- },
179
- createSession: n,
180
- clearSession: a,
181
- cleanup: l
361
+ }
362
+ function A() {
363
+ try {
364
+ i && (i(), i = null), r && c && T(c) && c.removeItem(l), s.setState({
365
+ messages: [],
366
+ keyboard: null,
367
+ loading: { isLoading: !1 },
368
+ error: { hasError: !1 }
369
+ }), e.setState(null), s.clear(), e.clear();
370
+ } catch (f) {
371
+ console.error("Error in cleanup:", f), s.setStatePartial({
372
+ error: {
373
+ hasError: !0,
374
+ message: f instanceof Error ? f.message : "Failed to cleanup",
375
+ code: "SESSION_CLEAR_FAILED"
376
+ }
377
+ });
378
+ }
379
+ }
380
+ return r && T(c) && (u(), E()), {
381
+ createSession: p,
382
+ clearSession: I,
383
+ cleanup: A,
384
+ startPolling: g
182
385
  };
183
386
  }
184
- function N(t) {
185
- var l;
186
- const e = `${t.botToken}:contact:${(l = t.user) == null ? void 0 : l.external_id}`;
187
- let s = null;
188
- if (t.platform.storage) {
189
- const c = t.platform.storage.getItem(e);
190
- if (c)
191
- try {
192
- s = JSON.parse(c);
193
- } catch (o) {
194
- console.error("Error parsing stored contact:", o);
387
+ function ae(t) {
388
+ var i;
389
+ const e = (i = t.platform) == null ? void 0 : i.logger;
390
+ e == null || e.info("Initializing chat");
391
+ const s = new C({
392
+ messages: [],
393
+ keyboard: null,
394
+ loading: { isLoading: !1 },
395
+ error: { hasError: !1 }
396
+ }), o = new C(null), d = J(t.api, s, e), n = G(
397
+ t.api,
398
+ o,
399
+ s,
400
+ d,
401
+ t.config,
402
+ t
403
+ );
404
+ async function a(c) {
405
+ var r;
406
+ let l = o.getState();
407
+ if (!(l != null && l.id) && (e == null || e.debug("No active session, creating new session"), l = await n.createSession(), !l))
408
+ return !1;
409
+ try {
410
+ e == null || e.debug("Sending message", { sessionId: l.id }), s.setStatePartial({
411
+ loading: { isLoading: !0, reason: "sending_message" },
412
+ error: { hasError: !1 }
413
+ });
414
+ const u = d.addUserMessage(c.content, c.attachments || void 0), E = s.getState().messages;
415
+ s.setStatePartial({
416
+ messages: [...E, u]
417
+ });
418
+ const g = t.config.getConfig(), p = await t.api.handleMessage({
419
+ bot_token: g.token,
420
+ headers: g.headers,
421
+ query_params: g.queryParams,
422
+ session_id: l.id,
423
+ ...c
424
+ });
425
+ if (p.success) {
426
+ e == null || e.debug("Message sent successfully");
427
+ const I = d.addBotMessage(p);
428
+ if (I) {
429
+ const A = s.getState().messages;
430
+ s.setStatePartial({
431
+ messages: [...A, I]
432
+ });
433
+ }
434
+ } else {
435
+ e == null || e.warn("Message send failed", p.error);
436
+ const I = d.addErrorMessage(((r = p.error) == null ? void 0 : r.message) || "Unknown error occurred"), A = s.getState().messages;
437
+ s.setStatePartial({
438
+ messages: [...A, I]
439
+ });
195
440
  }
441
+ return !0;
442
+ } catch (u) {
443
+ return e == null || e.error("Error sending message:", u), s.setStatePartial({
444
+ error: {
445
+ hasError: !0,
446
+ message: u instanceof Error ? u.message : "Failed to send message",
447
+ code: "MESSAGE_SEND_FAILED"
448
+ }
449
+ }), !1;
450
+ } finally {
451
+ s.setStatePartial({
452
+ loading: { isLoading: !1, reason: null }
453
+ });
454
+ }
196
455
  }
197
- const r = new S(s);
198
- t.platform.storage && r.subscribe((c) => {
199
- var o, i;
200
- c ? (o = t.platform.storage) == null || o.setItem(e, JSON.stringify(c)) : (i = t.platform.storage) == null || i.removeItem(e);
456
+ return {
457
+ chatState: s,
458
+ sessionState: o,
459
+ sendMessage: a,
460
+ createSession: n.createSession,
461
+ clearSession: n.clearSession,
462
+ cleanup: n.cleanup
463
+ };
464
+ }
465
+ function ne(t) {
466
+ const e = t.config.getConfig();
467
+ t.config.getConfig;
468
+ const s = `${e.token}:contact:${e.user.external_id}`, o = T(t.platform.storage) ? t.platform.storage : void 0;
469
+ let d = null;
470
+ o && O(
471
+ async () => {
472
+ const r = await o.getItem(s);
473
+ return r ? JSON.parse(r) : null;
474
+ },
475
+ "Error loading contact from storage"
476
+ ).then((r) => {
477
+ r.success && (d = r.result);
478
+ });
479
+ const n = new C({
480
+ contact: d,
481
+ loading: { isLoading: !1 },
482
+ error: { hasError: !1 }
201
483
  });
202
- function n() {
203
- const c = r.getState();
204
- return !(c != null && c.id) && t.collectUserData ? {
484
+ T(o) && n.subscribe((r) => {
485
+ O(
486
+ async () => {
487
+ r.contact ? await o.setItem(s, JSON.stringify(r.contact)) : o.removeItem(s);
488
+ },
489
+ "Error persisting contact state"
490
+ ).then((u) => {
491
+ u.success || n.setStatePartial({
492
+ error: {
493
+ hasError: !0,
494
+ message: u.error.message,
495
+ code: "CONTACT_PERSISTENCE_FAILED"
496
+ }
497
+ });
498
+ });
499
+ });
500
+ async function a() {
501
+ try {
502
+ if (n.setStatePartial({
503
+ loading: { isLoading: !0, reason: "loading_contact" },
504
+ error: { hasError: !1 }
505
+ }), o) {
506
+ const r = await O(
507
+ async () => {
508
+ const u = await o.getItem(s);
509
+ return u ? JSON.parse(u) : null;
510
+ },
511
+ "Error loading contact"
512
+ );
513
+ if (!r.success)
514
+ throw r.error;
515
+ return n.setStatePartial({
516
+ contact: r.result,
517
+ error: { hasError: !1 }
518
+ }), r.result;
519
+ }
520
+ return n.getState().contact;
521
+ } catch (r) {
522
+ return n.setStatePartial({
523
+ error: {
524
+ hasError: !0,
525
+ message: r instanceof Error ? r.message : "Failed to load contact",
526
+ code: "CONTACT_LOAD_FAILED"
527
+ }
528
+ }), null;
529
+ } finally {
530
+ n.setStatePartial({
531
+ loading: { isLoading: !1, reason: null }
532
+ });
533
+ }
534
+ }
535
+ async function i(r) {
536
+ try {
537
+ n.setStatePartial({
538
+ loading: { isLoading: !0, reason: "saving_contact" },
539
+ error: { hasError: !1 }
540
+ });
541
+ const u = n.getState().contact, E = {
542
+ id: r.id || (u == null ? void 0 : u.id) || "",
543
+ name: r.name ?? (u == null ? void 0 : u.name) ?? null,
544
+ created_at: r.created_at || (u == null ? void 0 : u.created_at) || (/* @__PURE__ */ new Date()).toISOString(),
545
+ avatar_url: r.avatar_url ?? (u == null ? void 0 : u.avatar_url) ?? null,
546
+ email: r.email ?? (u == null ? void 0 : u.email) ?? null
547
+ };
548
+ if (T(o)) {
549
+ const g = await O(
550
+ () => o.setItem(s, JSON.stringify(E)),
551
+ "Error saving contact"
552
+ );
553
+ if (!g.success)
554
+ throw g.error;
555
+ }
556
+ return n.setStatePartial({
557
+ contact: E,
558
+ error: { hasError: !1 }
559
+ }), E;
560
+ } catch (u) {
561
+ return n.setStatePartial({
562
+ error: {
563
+ hasError: !0,
564
+ message: u instanceof Error ? u.message : "Failed to save contact",
565
+ code: "CONTACT_SAVE_FAILED"
566
+ }
567
+ }), null;
568
+ } finally {
569
+ n.setStatePartial({
570
+ loading: { isLoading: !1, reason: null }
571
+ });
572
+ }
573
+ }
574
+ function c() {
575
+ var u;
576
+ return !((u = n.getState().contact) != null && u.id) && e.collectUserData ? {
205
577
  should: !0,
206
578
  reason: "No contact id and collectUserData is true"
207
579
  } : {
208
580
  should: !1
209
581
  };
210
582
  }
211
- function a() {
212
- r.clear(), r.setState(null);
583
+ async function l() {
584
+ try {
585
+ if (n.setStatePartial({
586
+ loading: { isLoading: !0, reason: "cleaning_up" },
587
+ error: { hasError: !1 }
588
+ }), o) {
589
+ const r = await O(
590
+ () => o.removeItem(s),
591
+ "Error removing contact data"
592
+ );
593
+ if (!r.success)
594
+ throw r.error;
595
+ }
596
+ n.setState({
597
+ contact: null,
598
+ loading: { isLoading: !1 },
599
+ error: { hasError: !1 }
600
+ }), n.clear();
601
+ } catch (r) {
602
+ console.error("Error cleaning up contact:", r), n.setStatePartial({
603
+ error: {
604
+ hasError: !0,
605
+ message: r instanceof Error ? r.message : "Failed to cleanup contact data",
606
+ code: "CONTACT_CLEANUP_FAILED"
607
+ }
608
+ });
609
+ } finally {
610
+ n.setStatePartial({
611
+ loading: { isLoading: !1, reason: null }
612
+ });
613
+ }
213
614
  }
214
615
  return {
215
- shouldCollectData: n,
216
- cleanup: a,
217
- contactState: r
616
+ contactState: n,
617
+ shouldCollectData: c,
618
+ loadContact: a,
619
+ saveContact: i,
620
+ cleanup: l
218
621
  };
219
622
  }
220
- function k(t = {}) {
221
- const e = [], s = [], r = [], n = async (a, l = {}) => {
222
- let c = {
623
+ const X = {
624
+ messageArrived: "https://cloud.opencopilot.so/sfx/notification3.mp3"
625
+ }, $ = {
626
+ primaryColor: "hsl(211,65%,59%)",
627
+ triggerOffset: "20px"
628
+ }, z = 1e3 * 3;
629
+ function oe(t) {
630
+ var s, o, d, n, a, i, c, l, r;
631
+ if (!t.token)
632
+ throw new Error("Token is required");
633
+ if (t.pollingInterval && t.pollingInterval < z)
634
+ throw new Error("Polling interval must be at least 3 seconds");
635
+ const e = {
636
+ ...t,
637
+ collectUserData: t.collectUserData ?? !1,
638
+ apiUrl: t.apiUrl ?? "https://api-v2.opencopilot.so/backend",
639
+ socketUrl: t.socketUrl ?? "https://api-v2.opencopilot.so",
640
+ pollingInterval: t.pollingInterval ?? 3e3,
641
+ headers: t.headers ?? {},
642
+ queryParams: t.queryParams ?? {},
643
+ pathParams: t.pathParams ?? {},
644
+ bot: {
645
+ name: ((s = t.bot) == null ? void 0 : s.name) ?? "Bot",
646
+ avatarUrl: (o = t.bot) == null ? void 0 : o.avatarUrl,
647
+ id: ((d = t.bot) == null ? void 0 : d.id) ?? null,
648
+ is_ai: ((n = t.bot) == null ? void 0 : n.is_ai) ?? !0
649
+ },
650
+ contactToken: t.contactToken,
651
+ debug: t.debug ?? !1,
652
+ language: t.language ?? "en",
653
+ user: t.user ?? {},
654
+ soundEffectFiles: {
655
+ messageArrived: ((a = t.soundEffectFiles) == null ? void 0 : a.messageArrived) ?? X.messageArrived
656
+ },
657
+ theme: {
658
+ primaryColor: ((i = t.theme) == null ? void 0 : i.primaryColor) ?? $.primaryColor,
659
+ triggerOffset: ((c = t.theme) == null ? void 0 : c.triggerOffset) ?? $.triggerOffset
660
+ },
661
+ settings: {
662
+ persistSession: ((l = t.settings) == null ? void 0 : l.persistSession) ?? !1,
663
+ useSoundEffects: ((r = t.settings) == null ? void 0 : r.useSoundEffects) ?? !1
664
+ }
665
+ };
666
+ return {
667
+ getConfig: () => e,
668
+ getApiConfig: () => ({
669
+ apiUrl: e.apiUrl,
670
+ token: e.token,
671
+ headers: e.headers,
672
+ queryParams: e.queryParams,
673
+ pathParams: e.pathParams
674
+ }),
675
+ getBotConfig: () => e.bot,
676
+ getThemeConfig: () => e.theme,
677
+ getSettings: () => e.settings,
678
+ getSoundEffects: () => e.soundEffectFiles,
679
+ getUser: () => e.user,
680
+ getLanguage: () => e.language,
681
+ getDebugMode: () => e.debug
682
+ };
683
+ }
684
+ function V(t = {}) {
685
+ const e = [], s = [], o = [], d = async (n, a = {}) => {
686
+ let i = {
223
687
  ...t,
224
- ...l,
688
+ ...a,
225
689
  headers: {
226
690
  ...t.headers,
227
- ...l.headers
691
+ ...a.headers
228
692
  }
229
693
  };
230
694
  try {
231
- for (const m of e)
232
- c = await m(c);
233
- const o = c.params ? "?" + new URLSearchParams(c.params).toString() : "", i = c.baseURL ? `${c.baseURL}${a}${o}`.replace(/([^:]\/)\/+/g, "$1") : `${a}${o}`;
234
- let u = await fetch(i, c);
235
- for (const m of s)
236
- u = await m(u);
237
- return u;
238
- } catch (o) {
239
- let i = o;
240
- for (const u of r)
695
+ for (const u of e)
241
696
  i = await u(i);
242
- throw i;
697
+ const c = i.params ? "?" + new URLSearchParams(i.params).toString() : "", l = i.baseURL ? `${i.baseURL}${n}${c}`.replace(/([^:]\/)\/+/g, "$1") : `${n}${c}`;
698
+ let r = await fetch(l, i);
699
+ for (const u of s)
700
+ r = await u(r);
701
+ return r;
702
+ } catch (c) {
703
+ let l = c;
704
+ for (const r of o)
705
+ l = await r(l);
706
+ throw l;
243
707
  }
244
708
  };
245
- return n.interceptors = {
709
+ return d.interceptors = {
246
710
  request: {
247
- use: (a) => (e.push(a), e.length - 1),
248
- eject: (a) => {
249
- e.splice(a, 1);
711
+ use: (n) => (e.push(n), e.length - 1),
712
+ eject: (n) => {
713
+ e.splice(n, 1);
250
714
  }
251
715
  },
252
716
  response: {
253
- use: (a, l) => (s.push(a), l && r.push(l), s.length - 1),
254
- eject: (a) => {
255
- s.splice(a, 1), r.splice(a, 1);
717
+ use: (n, a) => (s.push(n), a && o.push(a), s.length - 1),
718
+ eject: (n) => {
719
+ s.splice(n, 1), o.splice(n, 1);
256
720
  }
257
721
  }
258
- }, n;
722
+ }, d;
259
723
  }
260
- var g;
261
- class _ {
724
+ var b;
725
+ class ie {
262
726
  constructor(e) {
263
- b(this, g);
727
+ M(this, b);
264
728
  this.options = e;
265
- const s = this.options.coreOptions.user, r = {
729
+ const s = this.options.config.user, o = {
266
730
  claim: "",
267
731
  value: ""
268
732
  };
269
- s != null && s.email ? (r.claim = "email", r.value = s.email) : s != null && s.phone && (r.claim = "phone", r.value = s.phone);
270
- const n = {
271
- "X-Bot-Token": this.options.token,
272
- "X-Consumer-Id": `${r.claim}:${r.value}`
733
+ s != null && s.email ? (o.claim = "email", o.value = s.email) : s != null && s.phone && (o.claim = "phone", o.value = s.phone);
734
+ const d = {
735
+ "X-Bot-Token": this.options.config.token,
736
+ "X-Consumer-Id": `${o.claim}:${o.value}`,
737
+ "Content-Type": "application/json",
738
+ Accept: "application/json"
273
739
  };
274
- this.options.coreOptions.contactToken && (n.Authorization = `Bearer ${this.options.coreOptions.contactToken}`), f(this, g, k({
275
- baseURL: `${this.options.apiUrl}/widget/v2`,
276
- headers: n
740
+ this.options.config.contactToken && (d.Authorization = `Bearer ${this.options.config.contactToken}`), P(this, b, V({
741
+ baseURL: `${this.options.config.apiUrl}/widget/v2`,
742
+ headers: d
277
743
  }));
278
744
  }
279
745
  async me() {
280
- return (await d(this, g).call(this, "/me")).json();
746
+ return (await h(this, b).call(this, "/me")).json();
281
747
  }
282
748
  async widgetPrelude() {
283
- return (await d(this, g).call(this, "/prelude")).json();
749
+ return (await h(this, b).call(this, "/prelude")).json();
284
750
  }
285
751
  async handleMessage(e) {
286
- return (await d(this, g).call(this, "/chat/send", {
752
+ return (await h(this, b).call(this, "/chat/send", {
287
753
  method: "POST",
288
754
  body: JSON.stringify(e)
289
755
  })).json();
290
756
  }
291
757
  async getSessionHistory(e, s) {
292
- const r = new URLSearchParams({
758
+ const o = new URLSearchParams({
293
759
  lastMessageTimestamp: s || ""
294
- }), n = `/session/history/${e}?${r.toString()}`;
295
- return (await d(this, g).call(this, n, {
760
+ }), d = `/session/history/${e}?${o.toString()}`;
761
+ return (await h(this, b).call(this, d, {
296
762
  method: "GET"
297
763
  })).json();
298
764
  }
299
765
  async createSession() {
300
- return (await d(this, g).call(this, "/create-session", {
766
+ return (await h(this, b).call(this, "/create-session", {
301
767
  method: "POST"
302
768
  })).json();
303
769
  }
304
770
  async getSession(e) {
305
- return (await d(this, g).call(this, `/session/${e}`, {
771
+ return (await h(this, b).call(this, `/session/${e}`, {
306
772
  method: "GET"
307
773
  })).json();
308
774
  }
309
775
  async createContact(e) {
310
- return (await d(this, g).call(this, "/contact/upsert", {
776
+ return (await h(this, b).call(this, "/contact/upsert", {
311
777
  method: "POST",
312
778
  body: JSON.stringify(e)
313
779
  })).json();
314
780
  }
315
781
  }
316
- g = new WeakMap();
317
- class p extends Error {
318
- constructor(e) {
319
- super(e), this.name = "OpenCXError";
320
- }
321
- }
322
- class R extends p {
323
- constructor(e = "Connection failed") {
324
- super(e), this.name = "ConnectionError";
325
- }
326
- }
327
- class j extends p {
328
- constructor(e = "Authentication failed") {
329
- super(e), this.name = "AuthenticationError";
330
- }
331
- }
332
- class x extends p {
333
- constructor(e = "Session error occurred") {
334
- super(e), this.name = "SessionError";
335
- }
336
- }
337
- class q extends x {
338
- constructor(e = "Session not defined") {
339
- super(e), this.name = "SessionNotDefinedError";
782
+ b = new WeakMap();
783
+ function ce(t = {}) {
784
+ const {
785
+ level: e = "info",
786
+ prefix: s = "[openCx]",
787
+ enabled: o = !0
788
+ } = t;
789
+ let d = e;
790
+ const n = {
791
+ debug: 0,
792
+ info: 1,
793
+ warn: 2,
794
+ error: 3
795
+ };
796
+ function a(l) {
797
+ return o && n[l] >= n[d];
340
798
  }
341
- }
342
- class B extends p {
343
- constructor(e = "Transport error occurred") {
344
- super(e), this.name = "TransportError";
799
+ function i(l) {
800
+ return `${s} ${l}`;
345
801
  }
346
- }
347
- class H extends p {
348
- constructor(e = "File upload failed") {
349
- super(e), this.name = "FileUploadError";
802
+ function c(l) {
803
+ return l.map((r) => {
804
+ if (r instanceof Error)
805
+ return {
806
+ name: r.name,
807
+ message: r.message,
808
+ stack: r.stack
809
+ };
810
+ if (typeof r == "object")
811
+ try {
812
+ return JSON.stringify(r, null, 2);
813
+ } catch {
814
+ return r;
815
+ }
816
+ return r;
817
+ });
350
818
  }
351
- }
352
- function G() {
353
819
  return {
354
- env: {
355
- platform: typeof window < "u" ? "browser" : "server"
356
- },
357
- date: {
358
- now: () => Date.now(),
359
- toISOString: (e) => new Date(e).toISOString()
360
- }
361
- };
362
- }
363
- const D = {
364
- messageArrived: "https://cloud.opencopilot.so/sfx/notification3.mp3"
365
- }, U = {
366
- primaryColor: "hsl(211,65%,59%)",
367
- triggerOffset: "20px"
368
- };
369
- function X(t) {
370
- var s, r, n, a, l, c, o, i, u;
371
- const e = {
372
- ...t,
373
- apiUrl: t.apiUrl ?? "https://api-v2.opencopilot.so/backend",
374
- socketUrl: t.socketUrl ?? "https://api-v2.opencopilot.so",
375
- transport: t.transport ?? "socket",
376
- pollingInterval: t.pollingInterval ?? 3e3,
377
- headers: {
378
- ...t.headers ?? {},
379
- "X-Bot-Token": t.token
820
+ debug(l, ...r) {
821
+ a("debug") && console.debug(i(l), ...c(r));
380
822
  },
381
- queryParams: t.queryParams ?? {},
382
- pathParams: t.pathParams ?? {},
383
- bot: {
384
- name: ((s = t.bot) == null ? void 0 : s.name) ?? "Bot",
385
- avatarUrl: (r = t.bot) == null ? void 0 : r.avatarUrl,
386
- id: ((n = t.bot) == null ? void 0 : n.id) ?? null,
387
- is_ai: ((a = t.bot) == null ? void 0 : a.is_ai) ?? !0
823
+ info(l, ...r) {
824
+ a("info") && console.info(i(l), ...c(r));
388
825
  },
389
- contactToken: t.contactToken,
390
- debug: t.debug ?? !1,
391
- language: t.language ?? "en",
392
- user: t.user ?? {},
393
- soundEffectFiles: {
394
- messageArrived: ((l = t.soundEffectFiles) == null ? void 0 : l.messageArrived) ?? D.messageArrived
826
+ warn(l, ...r) {
827
+ a("warn") && console.warn(i(l), ...c(r));
395
828
  },
396
- theme: {
397
- primaryColor: ((c = t.theme) == null ? void 0 : c.primaryColor) ?? U.primaryColor,
398
- triggerOffset: ((o = t.theme) == null ? void 0 : o.triggerOffset) ?? U.triggerOffset
829
+ error(l, ...r) {
830
+ a("error") && console.error(i(l), ...c(r));
399
831
  },
400
- settings: {
401
- persistSession: ((i = t.settings) == null ? void 0 : i.persistSession) ?? !1,
402
- useSoundEffects: ((u = t.settings) == null ? void 0 : u.useSoundEffects) ?? !1
832
+ setLevel(l) {
833
+ d = l;
403
834
  }
404
835
  };
405
- return {
406
- getConfig: () => e,
407
- getApiConfig: () => ({
408
- apiUrl: e.apiUrl,
409
- token: e.token,
410
- headers: e.headers,
411
- queryParams: e.queryParams,
412
- pathParams: e.pathParams
413
- }),
414
- getBotConfig: () => e.bot,
415
- getThemeConfig: () => e.theme,
416
- getSettings: () => e.settings,
417
- getSoundEffects: () => e.soundEffectFiles,
418
- getUser: () => e.user,
419
- getLanguage: () => e.language,
420
- getDebugMode: () => e.debug
421
- };
422
836
  }
423
837
  export {
424
- V as AIClosureType,
425
- _ as ApiCaller,
426
- j as AuthenticationError,
427
- R as ConnectionError,
428
- H as FileUploadError,
429
- K as MessageTypeEnum,
430
- p as OpenCXError,
431
- S as PubSub,
432
- Q as SentimentEnum,
433
- W as SessionChannel,
434
- x as SessionError,
435
- q as SessionNotDefinedError,
436
- Y as SessionStatus,
437
- B as TransportError,
438
- Z as chatAttachmentSchema,
439
- ee as chatHistoryMessageSchema,
440
- te as chatSessionSchema,
441
- se as consumerSchema,
442
- L as createChat,
443
- X as createConfig,
444
- N as createContact,
445
- G as createDefaultPlatform,
446
- $ as createPubSub,
447
- re as structuredSocketMessageSchema
838
+ de as AIClosureType,
839
+ ie as ApiCaller,
840
+ ee as AuthenticationError,
841
+ Z as ConnectionError,
842
+ re as FileUploadError,
843
+ H as LifecycleEvent,
844
+ fe as MessageTypeEnum,
845
+ v as OpenCXError,
846
+ C as PubSub,
847
+ me as SentimentEnum,
848
+ ge as SessionChannel,
849
+ B as SessionError,
850
+ te as SessionNotDefinedError,
851
+ he as SessionStatus,
852
+ se as TransportError,
853
+ Se as chatAttachmentSchema,
854
+ pe as chatHistoryMessageSchema,
855
+ Ee as chatSessionSchema,
856
+ ye as consumerSchema,
857
+ ae as createChat,
858
+ oe as createConfig,
859
+ ne as createContact,
860
+ ce as createLogger,
861
+ W as createPubSub,
862
+ T as isStorageAvailable,
863
+ O as safeStorageOperation,
864
+ be as structuredSocketMessageSchema
448
865
  };
449
866
  //# sourceMappingURL=index.js.map