@deway-ai/web-sdk 0.71.0 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/loader.es.js +264 -156
- package/dist/loader.umd.js +1 -1
- package/package.json +1 -1
package/dist/loader.es.js
CHANGED
|
@@ -1,20 +1,81 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const I = {
|
|
2
|
+
debug: 0,
|
|
3
|
+
info: 1,
|
|
4
|
+
warn: 2,
|
|
5
|
+
error: 3
|
|
6
|
+
}, x = 4;
|
|
7
|
+
function L(o) {
|
|
8
|
+
if (typeof o == "bigint") return `${o}n`;
|
|
9
|
+
if (typeof o == "symbol") return o.toString();
|
|
10
|
+
if (typeof o == "function") return "[Function]";
|
|
11
|
+
}
|
|
12
|
+
function U(o, e) {
|
|
13
|
+
return o instanceof Error ? { name: o.name, message: o.message, stack: o.stack } : e.has(o) ? "[Circular]" : (e.add(o), o);
|
|
14
|
+
}
|
|
15
|
+
function _(o) {
|
|
16
|
+
const e = /* @__PURE__ */ new WeakSet();
|
|
17
|
+
return JSON.stringify(o, (t, n) => {
|
|
18
|
+
const i = L(n);
|
|
19
|
+
return i !== void 0 ? i : typeof n == "object" && n !== null ? U(n, e) : n;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function T(o, e) {
|
|
23
|
+
const t = o !== void 0 && Object.keys(o).length > 0, n = e !== void 0;
|
|
24
|
+
if (!t && !n) return;
|
|
25
|
+
const i = typeof e == "object" && e !== null && !Array.isArray(e) ? e : n ? { value: e } : {};
|
|
26
|
+
return { ...o, ...i };
|
|
27
|
+
}
|
|
28
|
+
function p(o, e, t, n, i) {
|
|
29
|
+
const r = e;
|
|
30
|
+
if (I[o] < r) return;
|
|
31
|
+
const s = {
|
|
32
|
+
level: o,
|
|
33
|
+
time: Date.now(),
|
|
34
|
+
msg: t
|
|
35
|
+
}, c = T(n, i);
|
|
36
|
+
c !== void 0 && (s.ctx = c), _(s);
|
|
37
|
+
}
|
|
38
|
+
function u(o) {
|
|
39
|
+
const e = o !== void 0 && "minLevel" in o ? o.minLevel : void 0, t = e === void 0 ? x : I[e], n = o?.context;
|
|
40
|
+
return {
|
|
41
|
+
debug(i, r) {
|
|
42
|
+
p("debug", t, i, n, r);
|
|
43
|
+
},
|
|
44
|
+
info(i, r) {
|
|
45
|
+
p("info", t, i, n, r);
|
|
46
|
+
},
|
|
47
|
+
warn(i, r) {
|
|
48
|
+
p("warn", t, i, n, r);
|
|
49
|
+
},
|
|
50
|
+
error(i, r) {
|
|
51
|
+
p("error", t, i, n, r);
|
|
52
|
+
},
|
|
53
|
+
child(i) {
|
|
54
|
+
return u({
|
|
55
|
+
minLevel: e,
|
|
56
|
+
context: { ...n, ...i }
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const k = u({ context: { module: "sdk-config-store" } }), A = "deway-sdk-config", Q = ["Understanding intent", "Reading web page", "Browsing the docs", "Enriching context", "Validating understanding", "Crafting response"], N = 18;
|
|
62
|
+
class R {
|
|
3
63
|
saveConfig(e) {
|
|
4
64
|
if (window?.localStorage)
|
|
5
65
|
try {
|
|
6
66
|
const t = JSON.stringify(e);
|
|
7
|
-
window.localStorage.setItem(
|
|
8
|
-
} catch {
|
|
67
|
+
window.localStorage.setItem(A, t);
|
|
68
|
+
} catch (t) {
|
|
69
|
+
k.warn("Failed to save SDK config to localStorage", t);
|
|
9
70
|
}
|
|
10
71
|
}
|
|
11
72
|
loadConfig() {
|
|
12
73
|
if (window?.localStorage)
|
|
13
74
|
try {
|
|
14
|
-
const e = window.localStorage.getItem(
|
|
75
|
+
const e = window.localStorage.getItem(A);
|
|
15
76
|
return e ? JSON.parse(e) : null;
|
|
16
|
-
} catch {
|
|
17
|
-
return null;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return k.warn("Failed to load SDK config from localStorage", e), null;
|
|
18
79
|
}
|
|
19
80
|
return null;
|
|
20
81
|
}
|
|
@@ -28,7 +89,7 @@ class S {
|
|
|
28
89
|
return this.loadConfig()?.aiDisclaimer;
|
|
29
90
|
}
|
|
30
91
|
getThinkingMessages() {
|
|
31
|
-
return this.loadConfig()?.thinkingMessages ??
|
|
92
|
+
return this.loadConfig()?.thinkingMessages ?? Q;
|
|
32
93
|
}
|
|
33
94
|
/**
|
|
34
95
|
* Get the support handoff configuration
|
|
@@ -84,7 +145,7 @@ class S {
|
|
|
84
145
|
return this.getCustomIcons()?.empty_chat_state_icon_inline_svg ?? void 0;
|
|
85
146
|
}
|
|
86
147
|
getEntrypointWidgetIconSize() {
|
|
87
|
-
return this.loadConfig()?.entrypointWidgetIconSize ??
|
|
148
|
+
return this.loadConfig()?.entrypointWidgetIconSize ?? N;
|
|
88
149
|
}
|
|
89
150
|
getUIAlignment() {
|
|
90
151
|
return this.loadConfig()?.uiAlignment ?? null;
|
|
@@ -96,106 +157,113 @@ class S {
|
|
|
96
157
|
return this.getUIAlignment()?.side ?? "right";
|
|
97
158
|
}
|
|
98
159
|
}
|
|
99
|
-
|
|
160
|
+
const f = u({ context: { module: "sdk-cache-manager" } });
|
|
161
|
+
class l {
|
|
100
162
|
static CACHE_KEY = "deway-sdk-cache";
|
|
101
163
|
static DB_NAME = "DewaySdk";
|
|
102
164
|
static DB_VERSION = 1;
|
|
103
165
|
static STORE_NAME = "sdk";
|
|
104
|
-
async cacheSDK(e, t,
|
|
166
|
+
async cacheSDK(e, t, n, i) {
|
|
105
167
|
try {
|
|
106
|
-
const
|
|
107
|
-
await new Promise((
|
|
108
|
-
const
|
|
168
|
+
const c = (await this.openIndexedDB()).transaction([l.STORE_NAME], "readwrite").objectStore(l.STORE_NAME);
|
|
169
|
+
await new Promise((E, K) => {
|
|
170
|
+
const g = c.put({
|
|
109
171
|
id: "latest",
|
|
110
172
|
code: e,
|
|
111
173
|
version: t,
|
|
112
|
-
checksum:
|
|
113
|
-
signature:
|
|
174
|
+
checksum: n,
|
|
175
|
+
signature: i,
|
|
114
176
|
timestamp: Date.now()
|
|
115
177
|
});
|
|
116
|
-
|
|
117
|
-
});
|
|
178
|
+
g.onsuccess = () => E(g.result), g.onerror = () => K(g.error);
|
|
179
|
+
}), f.debug("SDK cached in IndexedDB");
|
|
118
180
|
} catch {
|
|
119
181
|
try {
|
|
120
|
-
const
|
|
182
|
+
const s = JSON.stringify({
|
|
121
183
|
code: e,
|
|
122
184
|
version: t,
|
|
123
|
-
checksum:
|
|
124
|
-
signature:
|
|
185
|
+
checksum: n,
|
|
186
|
+
signature: i,
|
|
125
187
|
timestamp: Date.now()
|
|
126
188
|
});
|
|
127
|
-
localStorage.setItem(
|
|
128
|
-
} catch {
|
|
189
|
+
localStorage.setItem(l.CACHE_KEY, s), f.debug("SDK cached in localStorage");
|
|
190
|
+
} catch (s) {
|
|
191
|
+
f.warn("Unable to cache SDK", s);
|
|
129
192
|
}
|
|
130
193
|
}
|
|
131
194
|
}
|
|
132
195
|
async getCachedSDK() {
|
|
133
196
|
try {
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
197
|
+
const n = (await this.openIndexedDB()).transaction([l.STORE_NAME], "readonly").objectStore(l.STORE_NAME), i = await new Promise((r, s) => {
|
|
198
|
+
const c = n.get("latest");
|
|
199
|
+
c.onsuccess = () => r(c.result || null), c.onerror = () => s(c.error);
|
|
137
200
|
});
|
|
138
|
-
if (
|
|
139
|
-
return
|
|
201
|
+
if (i)
|
|
202
|
+
return f.debug("Found cached SDK in IndexedDB"), i;
|
|
140
203
|
} catch {
|
|
204
|
+
f.debug("IndexedDB unavailable, trying localStorage");
|
|
141
205
|
}
|
|
142
206
|
try {
|
|
143
|
-
const e = localStorage.getItem(
|
|
207
|
+
const e = localStorage.getItem(l.CACHE_KEY);
|
|
144
208
|
if (e)
|
|
145
|
-
return JSON.parse(e);
|
|
146
|
-
} catch {
|
|
209
|
+
return f.debug("Found cached SDK in localStorage"), JSON.parse(e);
|
|
210
|
+
} catch (e) {
|
|
211
|
+
f.warn("Failed to read from localStorage", e);
|
|
147
212
|
}
|
|
148
213
|
return null;
|
|
149
214
|
}
|
|
150
215
|
openIndexedDB() {
|
|
151
216
|
return new Promise((e, t) => {
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
const r =
|
|
155
|
-
r.objectStoreNames.contains(
|
|
217
|
+
const n = indexedDB.open(l.DB_NAME, l.DB_VERSION);
|
|
218
|
+
n.onerror = () => t(n.error), n.onsuccess = () => e(n.result), n.onupgradeneeded = (i) => {
|
|
219
|
+
const r = i.target.result;
|
|
220
|
+
r.objectStoreNames.contains(l.STORE_NAME) || r.createObjectStore(l.STORE_NAME, { keyPath: "id" });
|
|
156
221
|
};
|
|
157
222
|
});
|
|
158
223
|
}
|
|
159
224
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
225
|
+
const O = u({ context: { module: "sdk-verifier" } });
|
|
226
|
+
async function z(o) {
|
|
227
|
+
const t = new TextEncoder().encode(o), n = await crypto.subtle.digest("SHA-256", t);
|
|
228
|
+
return Array.from(new Uint8Array(n)).map((r) => r.toString(16).padStart(2, "0")).join("");
|
|
163
229
|
}
|
|
164
|
-
function
|
|
230
|
+
function F(o) {
|
|
165
231
|
const e = atob(o), t = new Uint8Array(e.length);
|
|
166
|
-
for (let
|
|
167
|
-
t[
|
|
232
|
+
for (let n = 0; n < e.length; n++)
|
|
233
|
+
t[n] = e.charCodeAt(n);
|
|
168
234
|
return t;
|
|
169
235
|
}
|
|
170
|
-
function
|
|
236
|
+
function $(o) {
|
|
171
237
|
const e = new Uint8Array(o.length / 2);
|
|
172
238
|
for (let t = 0; t < o.length; t += 2)
|
|
173
239
|
e[t / 2] = Number.parseInt(o.substr(t, 2), 16);
|
|
174
240
|
return e;
|
|
175
241
|
}
|
|
176
|
-
async function
|
|
242
|
+
async function q(o, e, t) {
|
|
177
243
|
try {
|
|
178
|
-
const
|
|
179
|
-
return await crypto.subtle.verify("Ed25519",
|
|
180
|
-
} catch {
|
|
181
|
-
return !1;
|
|
244
|
+
const n = F(o), i = $(e), r = F(t), s = await crypto.subtle.importKey("raw", n, { name: "Ed25519" }, !1, ["verify"]);
|
|
245
|
+
return await crypto.subtle.verify("Ed25519", s, r, i);
|
|
246
|
+
} catch (n) {
|
|
247
|
+
return O.error("Ed25519 signature verification failed", n), !1;
|
|
182
248
|
}
|
|
183
249
|
}
|
|
184
|
-
async function
|
|
250
|
+
async function P(o, e, t, n) {
|
|
185
251
|
if (!e || !t)
|
|
186
252
|
throw new Error("SDK verification failed: Missing security headers");
|
|
187
|
-
if (await
|
|
253
|
+
if (await z(o) !== e)
|
|
188
254
|
throw new Error("SDK verification failed: Checksum mismatch - content tampered");
|
|
189
|
-
if (!await
|
|
255
|
+
if (!await q(n, e, t))
|
|
190
256
|
throw new Error("SDK verification failed: Invalid signature - content tampered");
|
|
191
257
|
}
|
|
192
|
-
|
|
258
|
+
const m = u({ context: { module: "sdk-fetcher" } });
|
|
259
|
+
class V {
|
|
193
260
|
cleanApiEndpoint(e) {
|
|
194
261
|
return e.trim().replace(/\/+$/, "");
|
|
195
262
|
}
|
|
196
|
-
async fetchSDK(e, t,
|
|
263
|
+
async fetchSDK(e, t, n) {
|
|
197
264
|
try {
|
|
198
|
-
|
|
265
|
+
m.info("Fetching Deway SDK from backend...");
|
|
266
|
+
const i = this.cleanApiEndpoint(t), r = await fetch(`${i}/sdk-serve/sdk/v0`, {
|
|
199
267
|
method: "GET",
|
|
200
268
|
headers: {
|
|
201
269
|
Accept: "application/javascript",
|
|
@@ -203,31 +271,38 @@ class b {
|
|
|
203
271
|
Origin: window?.location?.origin || ""
|
|
204
272
|
}
|
|
205
273
|
});
|
|
206
|
-
return r.ok ? this.handleSuccessfulFetch(r,
|
|
207
|
-
} catch {
|
|
208
|
-
return null;
|
|
274
|
+
return r.ok ? this.handleSuccessfulFetch(r, n) : (m.warn(`Failed to fetch SDK: HTTP ${r.status}: ${r.statusText}`), null);
|
|
275
|
+
} catch (i) {
|
|
276
|
+
return m.warn("Failed to fetch SDK from server", i), null;
|
|
209
277
|
}
|
|
210
278
|
}
|
|
211
279
|
async handleSuccessfulFetch(e, t) {
|
|
212
|
-
const
|
|
213
|
-
if (!
|
|
214
|
-
|
|
215
|
-
|
|
280
|
+
const n = e.headers.get("x-sdk-checksum"), i = e.headers.get("x-sdk-version"), r = e.headers.get("x-sdk-signature"), s = await e.text();
|
|
281
|
+
if (m.info(`Fetched Deway SDK version ${i}`), !i || !s || !n) {
|
|
282
|
+
const c = Object.fromEntries(e.headers.entries());
|
|
283
|
+
throw m.error("Failed to get required data from sdk fetch", { headers: c }), new Error("Invalid SDK response: missing version, code, or checksum");
|
|
284
|
+
}
|
|
285
|
+
return await P(s, n, r, t), { code: s, version: i, checksum: n, signature: r || "" };
|
|
216
286
|
}
|
|
217
287
|
}
|
|
218
|
-
|
|
288
|
+
const h = u({ context: { module: "command-queue" } });
|
|
289
|
+
class C {
|
|
219
290
|
static MAX_QUEUE_SIZE = 50;
|
|
220
291
|
commandQueue = [];
|
|
221
292
|
queueCommand(e, ...t) {
|
|
222
|
-
this.commandQueue.length >=
|
|
293
|
+
this.commandQueue.length >= C.MAX_QUEUE_SIZE && (h.warn(`Command queue full (${C.MAX_QUEUE_SIZE} commands). Discarding oldest command.`), this.commandQueue.shift()), this.commandQueue.push({ method: e, args: t }), h.debug(`Queued command: ${e} (queue size: ${this.commandQueue.length})`);
|
|
223
294
|
}
|
|
224
295
|
replayQueuedCommands() {
|
|
225
296
|
if (this.commandQueue.length === 0)
|
|
226
297
|
return;
|
|
298
|
+
h.info(`Replaying ${this.commandQueue.length} queued commands`);
|
|
227
299
|
const e = [...this.commandQueue];
|
|
228
|
-
if (this.commandQueue = [],
|
|
229
|
-
|
|
230
|
-
|
|
300
|
+
if (this.commandQueue = [], !this.isSDKAvailable()) {
|
|
301
|
+
h.warn("Deway SDK not available for command replay");
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
for (const t of e)
|
|
305
|
+
this.replayCommand(t);
|
|
231
306
|
}
|
|
232
307
|
clearQueue() {
|
|
233
308
|
this.commandQueue = [];
|
|
@@ -237,13 +312,15 @@ class g {
|
|
|
237
312
|
}
|
|
238
313
|
replayCommand(e) {
|
|
239
314
|
try {
|
|
240
|
-
const t = window.Deway,
|
|
241
|
-
typeof
|
|
242
|
-
} catch {
|
|
315
|
+
const t = window.Deway, n = t?.[e.method];
|
|
316
|
+
typeof n == "function" ? n.apply(t, e.args) : h.warn(`Method ${e.method} not found on Deway SDK`);
|
|
317
|
+
} catch (t) {
|
|
318
|
+
h.error(`Failed to replay command ${e.method}`, t);
|
|
243
319
|
}
|
|
244
320
|
}
|
|
245
321
|
}
|
|
246
|
-
|
|
322
|
+
const w = u({ context: { module: "remote-config-cache" } });
|
|
323
|
+
class b {
|
|
247
324
|
static CACHE_KEY = "deway-remote-config-cache";
|
|
248
325
|
/**
|
|
249
326
|
* Caches remote configuration in localStorage
|
|
@@ -254,13 +331,14 @@ class u {
|
|
|
254
331
|
*/
|
|
255
332
|
async cacheRemoteConfig(e, t) {
|
|
256
333
|
try {
|
|
257
|
-
const
|
|
334
|
+
const n = {
|
|
258
335
|
config: e,
|
|
259
336
|
ttl_seconds: t,
|
|
260
337
|
timestamp: Date.now()
|
|
261
338
|
};
|
|
262
|
-
localStorage.setItem(
|
|
263
|
-
} catch {
|
|
339
|
+
localStorage.setItem(b.CACHE_KEY, JSON.stringify(n)), w.debug("Remote configuration cached in localStorage");
|
|
340
|
+
} catch (n) {
|
|
341
|
+
w.warn("Failed to cache remote config", n);
|
|
264
342
|
}
|
|
265
343
|
}
|
|
266
344
|
/**
|
|
@@ -271,10 +349,13 @@ class u {
|
|
|
271
349
|
*/
|
|
272
350
|
async getCachedRemoteConfig() {
|
|
273
351
|
try {
|
|
274
|
-
const e = localStorage.getItem(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
352
|
+
const e = localStorage.getItem(b.CACHE_KEY);
|
|
353
|
+
if (!e)
|
|
354
|
+
return null;
|
|
355
|
+
const t = JSON.parse(e);
|
|
356
|
+
return w.debug("Found cached remote configuration"), t;
|
|
357
|
+
} catch (e) {
|
|
358
|
+
return w.warn("Failed to read cached remote config", e), null;
|
|
278
359
|
}
|
|
279
360
|
}
|
|
280
361
|
/**
|
|
@@ -286,11 +367,12 @@ class u {
|
|
|
286
367
|
* @returns true if cache is still valid
|
|
287
368
|
*/
|
|
288
369
|
isCacheValid(e, t) {
|
|
289
|
-
const
|
|
290
|
-
return
|
|
370
|
+
const n = Date.now(), i = e + t * 1e3;
|
|
371
|
+
return n < i;
|
|
291
372
|
}
|
|
292
373
|
}
|
|
293
|
-
|
|
374
|
+
const S = u({ context: { module: "remote-config-fetcher" } });
|
|
375
|
+
class j {
|
|
294
376
|
cleanApiEndpoint(e) {
|
|
295
377
|
return e.trim().replace(/\/+$/, "");
|
|
296
378
|
}
|
|
@@ -304,7 +386,8 @@ class v {
|
|
|
304
386
|
*/
|
|
305
387
|
async fetchRemoteConfig(e, t) {
|
|
306
388
|
try {
|
|
307
|
-
|
|
389
|
+
S.info("Fetching remote configuration from backend...");
|
|
390
|
+
const n = this.cleanApiEndpoint(t), i = await fetch(`${n}/sdk-remote-config-serve/`, {
|
|
308
391
|
method: "GET",
|
|
309
392
|
headers: {
|
|
310
393
|
Accept: "application/json",
|
|
@@ -312,33 +395,38 @@ class v {
|
|
|
312
395
|
Origin: window?.location?.origin || ""
|
|
313
396
|
}
|
|
314
397
|
});
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
398
|
+
if (i.ok) {
|
|
399
|
+
const r = await i.json();
|
|
400
|
+
return S.info("Remote configuration fetched successfully"), r;
|
|
401
|
+
}
|
|
402
|
+
return S.warn(`Failed to fetch remote config: HTTP ${i.status}: ${i.statusText}`), null;
|
|
403
|
+
} catch (n) {
|
|
404
|
+
return S.warn("Failed to fetch remote config from server", n), null;
|
|
318
405
|
}
|
|
319
406
|
}
|
|
320
407
|
}
|
|
321
|
-
|
|
408
|
+
const y = u({ context: { module: "script-executor" } });
|
|
409
|
+
class H {
|
|
322
410
|
async executeSDK(e) {
|
|
323
411
|
return new Promise((t) => {
|
|
324
412
|
try {
|
|
325
413
|
if (!this.isDocumentReady()) {
|
|
326
|
-
t(!1);
|
|
414
|
+
y.error("Document is not available for script execution"), t(!1);
|
|
327
415
|
return;
|
|
328
416
|
}
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
let
|
|
332
|
-
const r = (
|
|
333
|
-
|
|
417
|
+
const n = document.createElement("script");
|
|
418
|
+
n.textContent = e, n.type = "text/javascript";
|
|
419
|
+
let i = !1;
|
|
420
|
+
const r = (s) => {
|
|
421
|
+
i || (i = !0, this.cleanupScript(n), t(s));
|
|
334
422
|
};
|
|
335
|
-
|
|
336
|
-
r(!1);
|
|
337
|
-
},
|
|
338
|
-
!
|
|
423
|
+
n.onerror = () => {
|
|
424
|
+
y.error("Script execution failed"), r(!1);
|
|
425
|
+
}, n.onload = () => r(!0), document.head.appendChild(n), setTimeout(() => {
|
|
426
|
+
!i && this.verifySDKLoaded() ? r(!0) : i || (y.error("SDK execution timeout - Deway object not found"), r(!1));
|
|
339
427
|
}, 100);
|
|
340
|
-
} catch {
|
|
341
|
-
t(!1);
|
|
428
|
+
} catch (n) {
|
|
429
|
+
y.error("Failed to execute SDK script", n), t(!1);
|
|
342
430
|
}
|
|
343
431
|
});
|
|
344
432
|
}
|
|
@@ -351,13 +439,15 @@ class I {
|
|
|
351
439
|
cleanupScript(e) {
|
|
352
440
|
try {
|
|
353
441
|
e.parentNode && e.parentNode.removeChild(e);
|
|
354
|
-
} catch {
|
|
442
|
+
} catch (t) {
|
|
443
|
+
y.debug("Failed to cleanup script element", t);
|
|
355
444
|
}
|
|
356
445
|
}
|
|
357
446
|
}
|
|
358
|
-
|
|
447
|
+
const D = u({ context: { module: "config-validator" } });
|
|
448
|
+
class M {
|
|
359
449
|
validateConfig(e) {
|
|
360
|
-
return
|
|
450
|
+
return e ? !e.appKey || e.appKey.trim().length === 0 ? (D.error("Config.appKey is required and must be a non-empty string"), !1) : e.apiEndpoint !== void 0 && !this.isValidUrl(e.apiEndpoint) ? (D.error("Config.apiEndpoint must be a valid URL"), !1) : e.publicKey !== void 0 && e.publicKey.trim().length === 0 ? (D.error("Config.publicKey must be a non-empty string if provided"), !1) : !0 : (D.error("Config is required"), !1);
|
|
361
451
|
}
|
|
362
452
|
isValidUrl(e) {
|
|
363
453
|
try {
|
|
@@ -367,11 +457,11 @@ class K {
|
|
|
367
457
|
}
|
|
368
458
|
}
|
|
369
459
|
}
|
|
370
|
-
const
|
|
460
|
+
const a = u({ context: { module: "sdk-loader" } }), v = {
|
|
371
461
|
apiEndpoint: "https://service.deway.app",
|
|
372
462
|
publicKey: "9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY="
|
|
373
463
|
};
|
|
374
|
-
class
|
|
464
|
+
class B {
|
|
375
465
|
isLoaded = !1;
|
|
376
466
|
isLoading = !1;
|
|
377
467
|
cacheManager;
|
|
@@ -383,25 +473,32 @@ class k {
|
|
|
383
473
|
remoteConfigCache;
|
|
384
474
|
sdkConfigStore;
|
|
385
475
|
constructor() {
|
|
386
|
-
this.cacheManager = new
|
|
476
|
+
this.cacheManager = new l(), this.scriptExecutor = new H(), this.commandQueue = new C(), this.sdkFetcher = new V(), this.configValidator = new M(), this.sdkConfigStore = new R(), this.remoteConfigFetcher = new j(), this.remoteConfigCache = new b();
|
|
387
477
|
}
|
|
388
478
|
init(e) {
|
|
389
479
|
this.performInit(e).catch((t) => {
|
|
480
|
+
a.error("Failed to initialize Deway SDK", t);
|
|
390
481
|
});
|
|
391
482
|
}
|
|
392
483
|
async performInit(e) {
|
|
393
484
|
try {
|
|
394
485
|
if (!this.canInitialize())
|
|
395
486
|
return;
|
|
396
|
-
const t = this.isInitializationPayload(e),
|
|
397
|
-
if (!this.configValidator.validateConfig(
|
|
487
|
+
const t = this.isInitializationPayload(e), n = t ? e.localConfig : e;
|
|
488
|
+
if (!this.configValidator.validateConfig(n)) {
|
|
489
|
+
a.error("Invalid config provided to Deway SDK");
|
|
398
490
|
return;
|
|
491
|
+
}
|
|
399
492
|
this.isLoading = !0;
|
|
400
|
-
const
|
|
401
|
-
if (!
|
|
493
|
+
const i = n.apiEndpoint || v.apiEndpoint, r = n.publicKey || v.publicKey, [s, c] = await Promise.all([this.fetchOrLoadSDK(n.appKey, i, r), this.fetchRemoteConfigWithCache(n, i)]);
|
|
494
|
+
if (!s)
|
|
402
495
|
return;
|
|
403
|
-
const
|
|
404
|
-
if (!await this.scriptExecutor.executeSDK(
|
|
496
|
+
const E = t ? e : this.createInitializationPayload(c, n);
|
|
497
|
+
if (!await this.scriptExecutor.executeSDK(s.code)) {
|
|
498
|
+
a.error("SDK execution failed");
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
if (!this.initializeSDK(E))
|
|
405
502
|
return;
|
|
406
503
|
this.commandQueue.replayQueuedCommands(), this.isLoaded = !0;
|
|
407
504
|
} finally {
|
|
@@ -412,7 +509,7 @@ class k {
|
|
|
412
509
|
return "localConfig" in e && "remoteConfig" in e && "defaults" in e;
|
|
413
510
|
}
|
|
414
511
|
canInitialize() {
|
|
415
|
-
return
|
|
512
|
+
return this.isLoaded ? (a.warn("Deway SDK already initialized"), !1) : this.isLoading ? (a.warn("Deway SDK initialization already in progress"), !1) : !0;
|
|
416
513
|
}
|
|
417
514
|
/**
|
|
418
515
|
* Fetches remote config from backend with cache fallback
|
|
@@ -420,14 +517,15 @@ class k {
|
|
|
420
517
|
*/
|
|
421
518
|
async fetchRemoteConfigWithCache(e, t) {
|
|
422
519
|
this.sdkConfigStore.saveConfig(e);
|
|
423
|
-
const
|
|
424
|
-
if (
|
|
425
|
-
return await this.remoteConfigCache.cacheRemoteConfig(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
520
|
+
const n = await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey, t);
|
|
521
|
+
if (n)
|
|
522
|
+
return await this.remoteConfigCache.cacheRemoteConfig(n.config, n.ttl_seconds), n;
|
|
523
|
+
a.info("Using cached remote config as fallback");
|
|
524
|
+
const i = await this.remoteConfigCache.getCachedRemoteConfig();
|
|
525
|
+
return i ? {
|
|
526
|
+
config: i.config,
|
|
527
|
+
ttl_seconds: i.ttl_seconds
|
|
528
|
+
} : (a.warn("No remote config available (fetch failed and no cache)"), null);
|
|
431
529
|
}
|
|
432
530
|
/**
|
|
433
531
|
* Creates initialization payload for backend SDK (NEW LOADER v0.29.0+)
|
|
@@ -438,120 +536,130 @@ class k {
|
|
|
438
536
|
return {
|
|
439
537
|
localConfig: t,
|
|
440
538
|
remoteConfig: e?.config ?? null,
|
|
441
|
-
defaults:
|
|
539
|
+
defaults: v
|
|
442
540
|
};
|
|
443
541
|
}
|
|
444
|
-
async fetchOrLoadSDK(e, t,
|
|
445
|
-
const
|
|
446
|
-
return
|
|
542
|
+
async fetchOrLoadSDK(e, t, n) {
|
|
543
|
+
const i = await this.sdkFetcher.fetchSDK(e, t, n);
|
|
544
|
+
return i ? (await this.cacheManager.cacheSDK(i.code, i.version, i.checksum, i.signature), i) : (a.warn("Failed to fetch SDK from server, attempting cache fallback"), this.loadFromCache());
|
|
447
545
|
}
|
|
448
546
|
async loadFromCache() {
|
|
449
547
|
const e = await this.cacheManager.getCachedSDK();
|
|
450
|
-
return e ? { code: e.code, version: e.version } : null;
|
|
548
|
+
return e ? (a.info(`Loading cached Deway SDK version ${e.version}`), { code: e.code, version: e.version }) : (a.error("SDK unavailable: Network error and no cached version found"), null);
|
|
451
549
|
}
|
|
452
550
|
initializeSDK(e) {
|
|
453
551
|
if (!this.isSDKAvailable())
|
|
454
|
-
return !1;
|
|
552
|
+
return a.error("SDK execution failed: Deway object not found after loading"), !1;
|
|
455
553
|
try {
|
|
456
|
-
return window.Deway?.init(e), !0;
|
|
457
|
-
} catch {
|
|
458
|
-
return !1;
|
|
554
|
+
return window.Deway?.init(e), a.info("Deway SDK initialized successfully with payload"), !0;
|
|
555
|
+
} catch (t) {
|
|
556
|
+
return a.error("Failed to initialize SDK with payload", t), !1;
|
|
459
557
|
}
|
|
460
558
|
}
|
|
461
559
|
identify(e) {
|
|
462
560
|
try {
|
|
463
561
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.identify(e) : this.commandQueue.queueCommand("identify", e);
|
|
464
|
-
} catch {
|
|
562
|
+
} catch (t) {
|
|
563
|
+
a.error("Failed to identify user", t);
|
|
465
564
|
}
|
|
466
565
|
}
|
|
467
566
|
reportEvent(e, t) {
|
|
468
567
|
try {
|
|
469
568
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.reportEvent(e, t) : this.commandQueue.queueCommand("reportEvent", e, t);
|
|
470
|
-
} catch {
|
|
569
|
+
} catch (n) {
|
|
570
|
+
a.error("Failed to report event", n);
|
|
471
571
|
}
|
|
472
572
|
}
|
|
473
573
|
setUserProfile(e) {
|
|
474
574
|
try {
|
|
475
575
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.setUserProfile(e) : this.commandQueue.queueCommand("setUserProfile", e);
|
|
476
|
-
} catch {
|
|
576
|
+
} catch (t) {
|
|
577
|
+
a.error("Failed to set user profile", t);
|
|
477
578
|
}
|
|
478
579
|
}
|
|
479
580
|
show(e) {
|
|
480
581
|
try {
|
|
481
582
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.show(e) : this.commandQueue.queueCommand("show", e);
|
|
482
|
-
} catch {
|
|
583
|
+
} catch (t) {
|
|
584
|
+
a.error("Failed to show bookmark", t);
|
|
483
585
|
}
|
|
484
586
|
}
|
|
485
587
|
hide() {
|
|
486
588
|
try {
|
|
487
589
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.hide() : this.commandQueue.queueCommand("hide");
|
|
488
|
-
} catch {
|
|
590
|
+
} catch (e) {
|
|
591
|
+
a.error("Failed to hide bookmark", e);
|
|
489
592
|
}
|
|
490
593
|
}
|
|
491
594
|
openChat() {
|
|
492
595
|
try {
|
|
493
596
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.openChat() : this.commandQueue.queueCommand("openChat");
|
|
494
|
-
} catch {
|
|
597
|
+
} catch (e) {
|
|
598
|
+
a.error("Failed to open chat", e);
|
|
495
599
|
}
|
|
496
600
|
}
|
|
497
601
|
resetUserLocally() {
|
|
498
602
|
try {
|
|
499
603
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.resetUserLocally() : this.commandQueue.queueCommand("resetUserLocally");
|
|
500
|
-
} catch {
|
|
604
|
+
} catch (e) {
|
|
605
|
+
a.error("Failed to reset user locally", e);
|
|
501
606
|
}
|
|
502
607
|
}
|
|
503
608
|
isVisible() {
|
|
504
609
|
try {
|
|
505
610
|
return this.isLoaded && this.isSDKAvailable() ? window.Deway?.isVisible() ?? !1 : !1;
|
|
506
|
-
} catch {
|
|
507
|
-
return !1;
|
|
611
|
+
} catch (e) {
|
|
612
|
+
return a.error("Failed to check bookmark visibility", e), !1;
|
|
508
613
|
}
|
|
509
614
|
}
|
|
510
615
|
isInitialized() {
|
|
511
616
|
try {
|
|
512
617
|
return this.isLoaded && this.isSDKAvailable() ? window.Deway?.isInitialized() ?? !1 : !1;
|
|
513
|
-
} catch {
|
|
514
|
-
return !1;
|
|
618
|
+
} catch (e) {
|
|
619
|
+
return a.error("Failed to check initialization status", e), !1;
|
|
515
620
|
}
|
|
516
621
|
}
|
|
517
622
|
registerSupportCallback(e) {
|
|
518
623
|
try {
|
|
519
624
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.registerSupportCallback(e) : this.commandQueue.queueCommand("registerSupportCallback", e);
|
|
520
|
-
} catch {
|
|
625
|
+
} catch (t) {
|
|
626
|
+
a.error("Failed to register support callback", t);
|
|
521
627
|
}
|
|
522
628
|
}
|
|
523
629
|
unregisterSupportCallback() {
|
|
524
630
|
try {
|
|
525
631
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.unregisterSupportCallback() : this.commandQueue.queueCommand("unregisterSupportCallback");
|
|
526
|
-
} catch {
|
|
632
|
+
} catch (e) {
|
|
633
|
+
a.error("Failed to unregister support callback", e);
|
|
527
634
|
}
|
|
528
635
|
}
|
|
529
636
|
destroy() {
|
|
530
637
|
try {
|
|
531
638
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.destroy() : this.commandQueue.queueCommand("destroy"), this.commandQueue.clearQueue();
|
|
532
|
-
} catch {
|
|
639
|
+
} catch (e) {
|
|
640
|
+
a.error("Failed to destroy SDK", e);
|
|
533
641
|
}
|
|
534
642
|
}
|
|
535
643
|
isSDKAvailable() {
|
|
536
644
|
return typeof window < "u" && "Deway" in window && !!window.Deway;
|
|
537
645
|
}
|
|
538
646
|
}
|
|
539
|
-
const
|
|
540
|
-
init: (o) =>
|
|
541
|
-
identify: (o) =>
|
|
542
|
-
reportEvent: (o, e) =>
|
|
543
|
-
setUserProfile: (o) =>
|
|
544
|
-
show: (o) =>
|
|
545
|
-
hide: () =>
|
|
546
|
-
openChat: () =>
|
|
547
|
-
resetUserLocally: () =>
|
|
548
|
-
registerSupportCallback: (o) =>
|
|
549
|
-
unregisterSupportCallback: () =>
|
|
550
|
-
isVisible: () =>
|
|
551
|
-
isInitialized: () =>
|
|
552
|
-
destroy: () =>
|
|
647
|
+
const d = new B(), W = {
|
|
648
|
+
init: (o) => d.init(o),
|
|
649
|
+
identify: (o) => d.identify(o),
|
|
650
|
+
reportEvent: (o, e) => d.reportEvent(o, e),
|
|
651
|
+
setUserProfile: (o) => d.setUserProfile(o),
|
|
652
|
+
show: (o) => d.show(o),
|
|
653
|
+
hide: () => d.hide(),
|
|
654
|
+
openChat: () => d.openChat(),
|
|
655
|
+
resetUserLocally: () => d.resetUserLocally(),
|
|
656
|
+
registerSupportCallback: (o) => d.registerSupportCallback(o),
|
|
657
|
+
unregisterSupportCallback: () => d.unregisterSupportCallback(),
|
|
658
|
+
isVisible: () => d.isVisible(),
|
|
659
|
+
isInitialized: () => d.isInitialized(),
|
|
660
|
+
destroy: () => d.destroy()
|
|
553
661
|
};
|
|
554
|
-
typeof window < "u" && (window.Deway =
|
|
662
|
+
typeof window < "u" && (window.Deway = W);
|
|
555
663
|
export {
|
|
556
|
-
|
|
664
|
+
W as default
|
|
557
665
|
};
|
package/dist/loader.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(l,u){typeof exports=="object"&&typeof module<"u"?module.exports=u():typeof define=="function"&&define.amd?define(u):(l=typeof globalThis<"u"?globalThis:l||self,l.Deway=u())})(this,(function(){"use strict";const l="deway-sdk-config",u=["Understanding intent","Reading web page","Browsing the docs","Enriching context","Validating understanding","Crafting response"];class C{saveConfig(e){if(window?.localStorage)try{const t=JSON.stringify(e);window.localStorage.setItem(l,t)}catch{}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(l);return e?JSON.parse(e):null}catch{return null}return null}getExcludedVendors(){return this.loadConfig()?.excludedVendors??[]}getAssistantName(){return this.loadConfig()?.assistantName??"Assistant"}getAiDisclaimer(){return this.loadConfig()?.aiDisclaimer}getThinkingMessages(){return this.loadConfig()?.thinkingMessages??u}getSupportHandoff(){return this.loadConfig()?.supportHandoff??null}getSupportHandoffButtonText(){return this.getSupportHandoff()?.button_text??"talk to Support"}getFeatureFlags(){return this.loadConfig()?.featureFlags??{}}getFeatureFlag(e){return this.getFeatureFlags()[e]??!1}getPromptSuggestions(){return this.loadConfig()?.promptSuggestions}getWelcomeTitle(){return this.loadConfig()?.welcomeTitle??"How can I help you today?"}getWelcomeSubtitle(){return this.loadConfig()?.welcomeSubtitle??"I'm ready to help you navigate, learn, and get things done."}getEntrypointWidgetAppearanceMode(){return this.loadConfig()?.entrypointWidgetAppearanceMode??"bookmark"}getTenantTheme(){return this.loadConfig()?.tenantTheme??null}getTenantThemeForMode(e){const t=this.getTenantTheme();return t?e==="dark"?t.dark:t.light:null}getCustomIcons(){return this.loadConfig()?.customIcons??null}getEntrypointWidgetIconInlineSvg(){return this.getCustomIcons()?.entrypoint_widget_icon_inline_svg??void 0}getEmptyChatStateIconInlineSvg(){return this.getCustomIcons()?.empty_chat_state_icon_inline_svg??void 0}getEntrypointWidgetIconSize(){return this.loadConfig()?.entrypointWidgetIconSize??18}getUIAlignment(){return this.loadConfig()?.uiAlignment??null}getUIAlignmentAnchorSelector(){return this.getUIAlignment()?.anchor_selector??null}getUIAlignmentSide(){return this.getUIAlignment()?.side??"right"}}class c{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,n,i){try{const d=(await this.openIndexedDB()).transaction([c.STORE_NAME],"readwrite").objectStore(c.STORE_NAME);await new Promise((y,S)=>{const h=d.put({id:"latest",code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});h.onsuccess=()=>y(h.result),h.onerror=()=>S(h.error)})}catch{try{const a=JSON.stringify({code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});localStorage.setItem(c.CACHE_KEY,a)}catch{}}}async getCachedSDK(){try{const n=(await this.openIndexedDB()).transaction([c.STORE_NAME],"readonly").objectStore(c.STORE_NAME),i=await new Promise((r,a)=>{const d=n.get("latest");d.onsuccess=()=>r(d.result||null),d.onerror=()=>a(d.error)});if(i)return i}catch{}try{const e=localStorage.getItem(c.CACHE_KEY);if(e)return JSON.parse(e)}catch{}return null}openIndexedDB(){return new Promise((e,t)=>{const n=indexedDB.open(c.DB_NAME,c.DB_VERSION);n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result),n.onupgradeneeded=i=>{const r=i.target.result;r.objectStoreNames.contains(c.STORE_NAME)||r.createObjectStore(c.STORE_NAME,{keyPath:"id"})}})}}async function E(o){const t=new TextEncoder().encode(o),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map(r=>r.toString(16).padStart(2,"0")).join("")}function p(o){const e=atob(o),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function D(o){const e=new Uint8Array(o.length/2);for(let t=0;t<o.length;t+=2)e[t/2]=Number.parseInt(o.substr(t,2),16);return e}async function A(o,e,t){try{const n=p(o),i=D(e),r=p(t),a=await crypto.subtle.importKey("raw",n,{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",a,r,i)}catch{return!1}}async function b(o,e,t,n){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await E(o)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await A(n,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class v{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchSDK(e,t,n){try{const i=this.cleanApiEndpoint(t),r=await fetch(`${i}/sdk-serve/sdk/v0`,{method:"GET",headers:{Accept:"application/javascript","deway-app-key":e,Origin:window?.location?.origin||""}});return r.ok?this.handleSuccessfulFetch(r,n):null}catch{return null}}async handleSuccessfulFetch(e,t){const n=e.headers.get("x-sdk-checksum"),i=e.headers.get("x-sdk-version"),r=e.headers.get("x-sdk-signature"),a=await e.text();if(!i||!a||!n)throw Object.fromEntries(e.headers.entries()),new Error("Invalid SDK response: missing version, code, or checksum");return await b(a,n,r,t),{code:a,version:i,checksum:n,signature:r||""}}}class g{static MAX_QUEUE_SIZE=50;commandQueue=[];queueCommand(e,...t){this.commandQueue.length>=g.MAX_QUEUE_SIZE&&this.commandQueue.shift(),this.commandQueue.push({method:e,args:t})}replayQueuedCommands(){if(this.commandQueue.length===0)return;const e=[...this.commandQueue];if(this.commandQueue=[],!!this.isSDKAvailable())for(const t of e)this.replayCommand(t)}clearQueue(){this.commandQueue=[]}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}replayCommand(e){try{const t=window.Deway,n=t?.[e.method];typeof n=="function"&&n.apply(t,e.args)}catch{}}}class f{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const n={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(f.CACHE_KEY,JSON.stringify(n))}catch{}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(f.CACHE_KEY);return e?JSON.parse(e):null}catch{return null}}isCacheValid(e,t){const n=Date.now(),i=e+t*1e3;return n<i}}class I{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchRemoteConfig(e,t){try{const n=this.cleanApiEndpoint(t),i=await fetch(`${n}/sdk-remote-config-serve/`,{method:"GET",headers:{Accept:"application/json","deway-app-key":e,Origin:window?.location?.origin||""}});return i.ok?await i.json():null}catch{return null}}}class K{async executeSDK(e){return new Promise(t=>{try{if(!this.isDocumentReady()){t(!1);return}const n=document.createElement("script");n.textContent=e,n.type="text/javascript";let i=!1;const r=a=>{i||(i=!0,this.cleanupScript(n),t(a))};n.onerror=()=>{r(!1)},n.onload=()=>r(!0),document.head.appendChild(n),setTimeout(()=>{!i&&this.verifySDKLoaded()?r(!0):i||r(!1)},100)}catch{t(!1)}})}isDocumentReady(){return typeof document<"u"&&document.head!=null}verifySDKLoaded(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}cleanupScript(e){try{e.parentNode&&e.parentNode.removeChild(e)}catch{}}}class k{validateConfig(e){return!(!e||!e.appKey||e.appKey.trim().length===0||e.apiEndpoint!==void 0&&!this.isValidUrl(e.apiEndpoint)||e.publicKey!==void 0&&e.publicKey.trim().length===0)}isValidUrl(e){try{return new URL(e),!0}catch{return!1}}}const m={apiEndpoint:"https://service.deway.app",publicKey:"9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY="};class _{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new c,this.scriptExecutor=new K,this.commandQueue=new g,this.sdkFetcher=new v,this.configValidator=new k,this.sdkConfigStore=new C,this.remoteConfigFetcher=new I,this.remoteConfigCache=new f}init(e){this.performInit(e).catch(t=>{})}async performInit(e){try{if(!this.canInitialize())return;const t=this.isInitializationPayload(e),n=t?e.localConfig:e;if(!this.configValidator.validateConfig(n))return;this.isLoading=!0;const i=n.apiEndpoint||m.apiEndpoint,r=n.publicKey||m.publicKey,[a,d]=await Promise.all([this.fetchOrLoadSDK(n.appKey,i,r),this.fetchRemoteConfigWithCache(n,i)]);if(!a)return;const y=t?e:this.createInitializationPayload(d,n);if(!await this.scriptExecutor.executeSDK(a.code)||!this.initializeSDK(y))return;this.commandQueue.replayQueuedCommands(),this.isLoaded=!0}finally{this.isLoading=!1}}isInitializationPayload(e){return"localConfig"in e&&"remoteConfig"in e&&"defaults"in e}canInitialize(){return!(this.isLoaded||this.isLoading)}async fetchRemoteConfigWithCache(e,t){this.sdkConfigStore.saveConfig(e);const n=await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey,t);if(n)return await this.remoteConfigCache.cacheRemoteConfig(n.config,n.ttl_seconds),n;const i=await this.remoteConfigCache.getCachedRemoteConfig();return i?{config:i.config,ttl_seconds:i.ttl_seconds}:null}createInitializationPayload(e,t){return{localConfig:t,remoteConfig:e?.config??null,defaults:m}}async fetchOrLoadSDK(e,t,n){const i=await this.sdkFetcher.fetchSDK(e,t,n);return i?(await this.cacheManager.cacheSDK(i.code,i.version,i.checksum,i.signature),i):this.loadFromCache()}async loadFromCache(){const e=await this.cacheManager.getCachedSDK();return e?{code:e.code,version:e.version}:null}initializeSDK(e){if(!this.isSDKAvailable())return!1;try{return window.Deway?.init(e),!0}catch{return!1}}identify(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.identify(e):this.commandQueue.queueCommand("identify",e)}catch{}}reportEvent(e,t){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.reportEvent(e,t):this.commandQueue.queueCommand("reportEvent",e,t)}catch{}}setUserProfile(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.setUserProfile(e):this.commandQueue.queueCommand("setUserProfile",e)}catch{}}show(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.show(e):this.commandQueue.queueCommand("show",e)}catch{}}hide(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.hide():this.commandQueue.queueCommand("hide")}catch{}}openChat(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.openChat():this.commandQueue.queueCommand("openChat")}catch{}}resetUserLocally(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.resetUserLocally():this.commandQueue.queueCommand("resetUserLocally")}catch{}}isVisible(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isVisible()??!1:!1}catch{return!1}}isInitialized(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isInitialized()??!1:!1}catch{return!1}}registerSupportCallback(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.registerSupportCallback(e):this.commandQueue.queueCommand("registerSupportCallback",e)}catch{}}unregisterSupportCallback(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.unregisterSupportCallback():this.commandQueue.queueCommand("unregisterSupportCallback")}catch{}}destroy(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.destroy():this.commandQueue.queueCommand("destroy"),this.commandQueue.clearQueue()}catch{}}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}}const s=new _,w={init:o=>s.init(o),identify:o=>s.identify(o),reportEvent:(o,e)=>s.reportEvent(o,e),setUserProfile:o=>s.setUserProfile(o),show:o=>s.show(o),hide:()=>s.hide(),openChat:()=>s.openChat(),resetUserLocally:()=>s.resetUserLocally(),registerSupportCallback:o=>s.registerSupportCallback(o),unregisterSupportCallback:()=>s.unregisterSupportCallback(),isVisible:()=>s.isVisible(),isInitialized:()=>s.isInitialized(),destroy:()=>s.destroy()};return typeof window<"u"&&(window.Deway=w),w}));
|
|
1
|
+
(function(h,m){typeof exports=="object"&&typeof module<"u"?module.exports=m():typeof define=="function"&&define.amd?define(m):(h=typeof globalThis<"u"?globalThis:h||self,h.Deway=m())})(this,(function(){"use strict";const h={debug:0,info:1,warn:2,error:3},m=4;function U(o){if(typeof o=="bigint")return`${o}n`;if(typeof o=="symbol")return o.toString();if(typeof o=="function")return"[Function]"}function T(o,e){return o instanceof Error?{name:o.name,message:o.message,stack:o.stack}:e.has(o)?"[Circular]":(e.add(o),o)}function _(o){const e=new WeakSet;return JSON.stringify(o,(t,n)=>{const i=U(n);return i!==void 0?i:typeof n=="object"&&n!==null?T(n,e):n})}function Q(o,e){const t=o!==void 0&&Object.keys(o).length>0,n=e!==void 0;if(!t&&!n)return;const i=typeof e=="object"&&e!==null&&!Array.isArray(e)?e:n?{value:e}:{};return{...o,...i}}function S(o,e,t,n,i){const r=e;if(h[o]<r)return;const s={level:o,time:Date.now(),msg:t},d=Q(n,i);d!==void 0&&(s.ctx=d),_(s)}function u(o){const e=o!==void 0&&"minLevel"in o?o.minLevel:void 0,t=e===void 0?m:h[e],n=o?.context;return{debug(i,r){S("debug",t,i,n,r)},info(i,r){S("info",t,i,n,r)},warn(i,r){S("warn",t,i,n,r)},error(i,r){S("error",t,i,n,r)},child(i){return u({minLevel:e,context:{...n,...i}})}}}const A=u({context:{module:"sdk-config-store"}}),F="deway-sdk-config",N=["Understanding intent","Reading web page","Browsing the docs","Enriching context","Validating understanding","Crafting response"],R=18;class O{saveConfig(e){if(window?.localStorage)try{const t=JSON.stringify(e);window.localStorage.setItem(F,t)}catch(t){A.warn("Failed to save SDK config to localStorage",t)}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(F);return e?JSON.parse(e):null}catch(e){return A.warn("Failed to load SDK config from localStorage",e),null}return null}getExcludedVendors(){return this.loadConfig()?.excludedVendors??[]}getAssistantName(){return this.loadConfig()?.assistantName??"Assistant"}getAiDisclaimer(){return this.loadConfig()?.aiDisclaimer}getThinkingMessages(){return this.loadConfig()?.thinkingMessages??N}getSupportHandoff(){return this.loadConfig()?.supportHandoff??null}getSupportHandoffButtonText(){return this.getSupportHandoff()?.button_text??"talk to Support"}getFeatureFlags(){return this.loadConfig()?.featureFlags??{}}getFeatureFlag(e){return this.getFeatureFlags()[e]??!1}getPromptSuggestions(){return this.loadConfig()?.promptSuggestions}getWelcomeTitle(){return this.loadConfig()?.welcomeTitle??"How can I help you today?"}getWelcomeSubtitle(){return this.loadConfig()?.welcomeSubtitle??"I'm ready to help you navigate, learn, and get things done."}getEntrypointWidgetAppearanceMode(){return this.loadConfig()?.entrypointWidgetAppearanceMode??"bookmark"}getTenantTheme(){return this.loadConfig()?.tenantTheme??null}getTenantThemeForMode(e){const t=this.getTenantTheme();return t?e==="dark"?t.dark:t.light:null}getCustomIcons(){return this.loadConfig()?.customIcons??null}getEntrypointWidgetIconInlineSvg(){return this.getCustomIcons()?.entrypoint_widget_icon_inline_svg??void 0}getEmptyChatStateIconInlineSvg(){return this.getCustomIcons()?.empty_chat_state_icon_inline_svg??void 0}getEntrypointWidgetIconSize(){return this.loadConfig()?.entrypointWidgetIconSize??R}getUIAlignment(){return this.loadConfig()?.uiAlignment??null}getUIAlignmentAnchorSelector(){return this.getUIAlignment()?.anchor_selector??null}getUIAlignmentSide(){return this.getUIAlignment()?.side??"right"}}const f=u({context:{module:"sdk-cache-manager"}});class l{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,n,i){try{const d=(await this.openIndexedDB()).transaction([l.STORE_NAME],"readwrite").objectStore(l.STORE_NAME);await new Promise((k,L)=>{const w=d.put({id:"latest",code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});w.onsuccess=()=>k(w.result),w.onerror=()=>L(w.error)}),f.debug("SDK cached in IndexedDB")}catch{try{const s=JSON.stringify({code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});localStorage.setItem(l.CACHE_KEY,s),f.debug("SDK cached in localStorage")}catch(s){f.warn("Unable to cache SDK",s)}}}async getCachedSDK(){try{const n=(await this.openIndexedDB()).transaction([l.STORE_NAME],"readonly").objectStore(l.STORE_NAME),i=await new Promise((r,s)=>{const d=n.get("latest");d.onsuccess=()=>r(d.result||null),d.onerror=()=>s(d.error)});if(i)return f.debug("Found cached SDK in IndexedDB"),i}catch{f.debug("IndexedDB unavailable, trying localStorage")}try{const e=localStorage.getItem(l.CACHE_KEY);if(e)return f.debug("Found cached SDK in localStorage"),JSON.parse(e)}catch(e){f.warn("Failed to read from localStorage",e)}return null}openIndexedDB(){return new Promise((e,t)=>{const n=indexedDB.open(l.DB_NAME,l.DB_VERSION);n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result),n.onupgradeneeded=i=>{const r=i.target.result;r.objectStoreNames.contains(l.STORE_NAME)||r.createObjectStore(l.STORE_NAME,{keyPath:"id"})}})}}const z=u({context:{module:"sdk-verifier"}});async function $(o){const t=new TextEncoder().encode(o),n=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(n)).map(r=>r.toString(16).padStart(2,"0")).join("")}function I(o){const e=atob(o),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function q(o){const e=new Uint8Array(o.length/2);for(let t=0;t<o.length;t+=2)e[t/2]=Number.parseInt(o.substr(t,2),16);return e}async function P(o,e,t){try{const n=I(o),i=q(e),r=I(t),s=await crypto.subtle.importKey("raw",n,{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",s,r,i)}catch(n){return z.error("Ed25519 signature verification failed",n),!1}}async function j(o,e,t,n){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await $(o)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await P(n,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}const y=u({context:{module:"sdk-fetcher"}});class V{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchSDK(e,t,n){try{y.info("Fetching Deway SDK from backend...");const i=this.cleanApiEndpoint(t),r=await fetch(`${i}/sdk-serve/sdk/v0`,{method:"GET",headers:{Accept:"application/javascript","deway-app-key":e,Origin:window?.location?.origin||""}});return r.ok?this.handleSuccessfulFetch(r,n):(y.warn(`Failed to fetch SDK: HTTP ${r.status}: ${r.statusText}`),null)}catch(i){return y.warn("Failed to fetch SDK from server",i),null}}async handleSuccessfulFetch(e,t){const n=e.headers.get("x-sdk-checksum"),i=e.headers.get("x-sdk-version"),r=e.headers.get("x-sdk-signature"),s=await e.text();if(y.info(`Fetched Deway SDK version ${i}`),!i||!s||!n){const d=Object.fromEntries(e.headers.entries());throw y.error("Failed to get required data from sdk fetch",{headers:d}),new Error("Invalid SDK response: missing version, code, or checksum")}return await j(s,n,r,t),{code:s,version:i,checksum:n,signature:r||""}}}const g=u({context:{module:"command-queue"}});class D{static MAX_QUEUE_SIZE=50;commandQueue=[];queueCommand(e,...t){this.commandQueue.length>=D.MAX_QUEUE_SIZE&&(g.warn(`Command queue full (${D.MAX_QUEUE_SIZE} commands). Discarding oldest command.`),this.commandQueue.shift()),this.commandQueue.push({method:e,args:t}),g.debug(`Queued command: ${e} (queue size: ${this.commandQueue.length})`)}replayQueuedCommands(){if(this.commandQueue.length===0)return;g.info(`Replaying ${this.commandQueue.length} queued commands`);const e=[...this.commandQueue];if(this.commandQueue=[],!this.isSDKAvailable()){g.warn("Deway SDK not available for command replay");return}for(const t of e)this.replayCommand(t)}clearQueue(){this.commandQueue=[]}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}replayCommand(e){try{const t=window.Deway,n=t?.[e.method];typeof n=="function"?n.apply(t,e.args):g.warn(`Method ${e.method} not found on Deway SDK`)}catch(t){g.error(`Failed to replay command ${e.method}`,t)}}}const C=u({context:{module:"remote-config-cache"}});class b{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const n={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(b.CACHE_KEY,JSON.stringify(n)),C.debug("Remote configuration cached in localStorage")}catch(n){C.warn("Failed to cache remote config",n)}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(b.CACHE_KEY);if(!e)return null;const t=JSON.parse(e);return C.debug("Found cached remote configuration"),t}catch(e){return C.warn("Failed to read cached remote config",e),null}}isCacheValid(e,t){const n=Date.now(),i=e+t*1e3;return n<i}}const E=u({context:{module:"remote-config-fetcher"}});class H{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchRemoteConfig(e,t){try{E.info("Fetching remote configuration from backend...");const n=this.cleanApiEndpoint(t),i=await fetch(`${n}/sdk-remote-config-serve/`,{method:"GET",headers:{Accept:"application/json","deway-app-key":e,Origin:window?.location?.origin||""}});if(i.ok){const r=await i.json();return E.info("Remote configuration fetched successfully"),r}return E.warn(`Failed to fetch remote config: HTTP ${i.status}: ${i.statusText}`),null}catch(n){return E.warn("Failed to fetch remote config from server",n),null}}}const p=u({context:{module:"script-executor"}});class M{async executeSDK(e){return new Promise(t=>{try{if(!this.isDocumentReady()){p.error("Document is not available for script execution"),t(!1);return}const n=document.createElement("script");n.textContent=e,n.type="text/javascript";let i=!1;const r=s=>{i||(i=!0,this.cleanupScript(n),t(s))};n.onerror=()=>{p.error("Script execution failed"),r(!1)},n.onload=()=>r(!0),document.head.appendChild(n),setTimeout(()=>{!i&&this.verifySDKLoaded()?r(!0):i||(p.error("SDK execution timeout - Deway object not found"),r(!1))},100)}catch(n){p.error("Failed to execute SDK script",n),t(!1)}})}isDocumentReady(){return typeof document<"u"&&document.head!=null}verifySDKLoaded(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}cleanupScript(e){try{e.parentNode&&e.parentNode.removeChild(e)}catch(t){p.debug("Failed to cleanup script element",t)}}}const v=u({context:{module:"config-validator"}});class B{validateConfig(e){return e?!e.appKey||e.appKey.trim().length===0?(v.error("Config.appKey is required and must be a non-empty string"),!1):e.apiEndpoint!==void 0&&!this.isValidUrl(e.apiEndpoint)?(v.error("Config.apiEndpoint must be a valid URL"),!1):e.publicKey!==void 0&&e.publicKey.trim().length===0?(v.error("Config.publicKey must be a non-empty string if provided"),!1):!0:(v.error("Config is required"),!1)}isValidUrl(e){try{return new URL(e),!0}catch{return!1}}}const a=u({context:{module:"sdk-loader"}}),K={apiEndpoint:"https://service.deway.app",publicKey:"9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY="};class W{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new l,this.scriptExecutor=new M,this.commandQueue=new D,this.sdkFetcher=new V,this.configValidator=new B,this.sdkConfigStore=new O,this.remoteConfigFetcher=new H,this.remoteConfigCache=new b}init(e){this.performInit(e).catch(t=>{a.error("Failed to initialize Deway SDK",t)})}async performInit(e){try{if(!this.canInitialize())return;const t=this.isInitializationPayload(e),n=t?e.localConfig:e;if(!this.configValidator.validateConfig(n)){a.error("Invalid config provided to Deway SDK");return}this.isLoading=!0;const i=n.apiEndpoint||K.apiEndpoint,r=n.publicKey||K.publicKey,[s,d]=await Promise.all([this.fetchOrLoadSDK(n.appKey,i,r),this.fetchRemoteConfigWithCache(n,i)]);if(!s)return;const k=t?e:this.createInitializationPayload(d,n);if(!await this.scriptExecutor.executeSDK(s.code)){a.error("SDK execution failed");return}if(!this.initializeSDK(k))return;this.commandQueue.replayQueuedCommands(),this.isLoaded=!0}finally{this.isLoading=!1}}isInitializationPayload(e){return"localConfig"in e&&"remoteConfig"in e&&"defaults"in e}canInitialize(){return this.isLoaded?(a.warn("Deway SDK already initialized"),!1):this.isLoading?(a.warn("Deway SDK initialization already in progress"),!1):!0}async fetchRemoteConfigWithCache(e,t){this.sdkConfigStore.saveConfig(e);const n=await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey,t);if(n)return await this.remoteConfigCache.cacheRemoteConfig(n.config,n.ttl_seconds),n;a.info("Using cached remote config as fallback");const i=await this.remoteConfigCache.getCachedRemoteConfig();return i?{config:i.config,ttl_seconds:i.ttl_seconds}:(a.warn("No remote config available (fetch failed and no cache)"),null)}createInitializationPayload(e,t){return{localConfig:t,remoteConfig:e?.config??null,defaults:K}}async fetchOrLoadSDK(e,t,n){const i=await this.sdkFetcher.fetchSDK(e,t,n);return i?(await this.cacheManager.cacheSDK(i.code,i.version,i.checksum,i.signature),i):(a.warn("Failed to fetch SDK from server, attempting cache fallback"),this.loadFromCache())}async loadFromCache(){const e=await this.cacheManager.getCachedSDK();return e?(a.info(`Loading cached Deway SDK version ${e.version}`),{code:e.code,version:e.version}):(a.error("SDK unavailable: Network error and no cached version found"),null)}initializeSDK(e){if(!this.isSDKAvailable())return a.error("SDK execution failed: Deway object not found after loading"),!1;try{return window.Deway?.init(e),a.info("Deway SDK initialized successfully with payload"),!0}catch(t){return a.error("Failed to initialize SDK with payload",t),!1}}identify(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.identify(e):this.commandQueue.queueCommand("identify",e)}catch(t){a.error("Failed to identify user",t)}}reportEvent(e,t){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.reportEvent(e,t):this.commandQueue.queueCommand("reportEvent",e,t)}catch(n){a.error("Failed to report event",n)}}setUserProfile(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.setUserProfile(e):this.commandQueue.queueCommand("setUserProfile",e)}catch(t){a.error("Failed to set user profile",t)}}show(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.show(e):this.commandQueue.queueCommand("show",e)}catch(t){a.error("Failed to show bookmark",t)}}hide(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.hide():this.commandQueue.queueCommand("hide")}catch(e){a.error("Failed to hide bookmark",e)}}openChat(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.openChat():this.commandQueue.queueCommand("openChat")}catch(e){a.error("Failed to open chat",e)}}resetUserLocally(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.resetUserLocally():this.commandQueue.queueCommand("resetUserLocally")}catch(e){a.error("Failed to reset user locally",e)}}isVisible(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isVisible()??!1:!1}catch(e){return a.error("Failed to check bookmark visibility",e),!1}}isInitialized(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isInitialized()??!1:!1}catch(e){return a.error("Failed to check initialization status",e),!1}}registerSupportCallback(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.registerSupportCallback(e):this.commandQueue.queueCommand("registerSupportCallback",e)}catch(t){a.error("Failed to register support callback",t)}}unregisterSupportCallback(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.unregisterSupportCallback():this.commandQueue.queueCommand("unregisterSupportCallback")}catch(e){a.error("Failed to unregister support callback",e)}}destroy(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.destroy():this.commandQueue.queueCommand("destroy"),this.commandQueue.clearQueue()}catch(e){a.error("Failed to destroy SDK",e)}}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}}const c=new W,x={init:o=>c.init(o),identify:o=>c.identify(o),reportEvent:(o,e)=>c.reportEvent(o,e),setUserProfile:o=>c.setUserProfile(o),show:o=>c.show(o),hide:()=>c.hide(),openChat:()=>c.openChat(),resetUserLocally:()=>c.resetUserLocally(),registerSupportCallback:o=>c.registerSupportCallback(o),unregisterSupportCallback:()=>c.unregisterSupportCallback(),isVisible:()=>c.isVisible(),isInitialized:()=>c.isInitialized(),destroy:()=>c.destroy()};return typeof window<"u"&&(window.Deway=x),x}));
|