@deway-ai/web-sdk 0.45.0 → 0.46.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 CHANGED
@@ -30,11 +30,19 @@ class S {
30
30
  getThinkingMessages() {
31
31
  return this.loadConfig()?.thinkingMessages ?? p;
32
32
  }
33
- getTalkToHumanBtnTxt() {
34
- return this.loadConfig()?.talkToHumanBtnTxt ?? "talk to Support";
33
+ /**
34
+ * Get the support handoff configuration
35
+ * @returns SupportHandoff config or null if not configured
36
+ */
37
+ getSupportHandoff() {
38
+ return this.loadConfig()?.supportHandoff ?? null;
35
39
  }
36
- getHumanHandoffUrl() {
37
- return this.loadConfig()?.humanHandoffUrl;
40
+ /**
41
+ * Get the support handoff button text
42
+ * @returns Custom button text or default "talk to Support"
43
+ */
44
+ getSupportHandoffButtonText() {
45
+ return this.getSupportHandoff()?.button_text ?? "talk to Support";
38
46
  }
39
47
  getFeatureFlags() {
40
48
  return this.loadConfig()?.featureFlags ?? {};
@@ -66,33 +74,42 @@ class S {
66
74
  const t = this.getTenantTheme();
67
75
  return t ? e === "dark" ? t.dark : t.light : null;
68
76
  }
77
+ getCustomIcons() {
78
+ return this.loadConfig()?.customIcons ?? null;
79
+ }
80
+ getBookmarkIconInlineSvg() {
81
+ return this.getCustomIcons()?.bookmark_icon_inline_svg ?? void 0;
82
+ }
83
+ getEmptyChatStateIconInlineSvg() {
84
+ return this.getCustomIcons()?.empty_chat_state_icon_inline_svg ?? void 0;
85
+ }
69
86
  }
70
87
  class s {
71
88
  static CACHE_KEY = "deway-sdk-cache";
72
89
  static DB_NAME = "DewaySdk";
73
90
  static DB_VERSION = 1;
74
91
  static STORE_NAME = "sdk";
75
- async cacheSDK(e, t, i, n) {
92
+ async cacheSDK(e, t, n, i) {
76
93
  try {
77
94
  const d = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readwrite").objectStore(s.STORE_NAME);
78
- await new Promise((h, m) => {
95
+ await new Promise((f, m) => {
79
96
  const l = d.put({
80
97
  id: "latest",
81
98
  code: e,
82
99
  version: t,
83
- checksum: i,
84
- signature: n,
100
+ checksum: n,
101
+ signature: i,
85
102
  timestamp: Date.now()
86
103
  });
87
- l.onsuccess = () => h(l.result), l.onerror = () => m(l.error);
104
+ l.onsuccess = () => f(l.result), l.onerror = () => m(l.error);
88
105
  });
89
106
  } catch {
90
107
  try {
91
108
  const a = JSON.stringify({
92
109
  code: e,
93
110
  version: t,
94
- checksum: i,
95
- signature: n,
111
+ checksum: n,
112
+ signature: i,
96
113
  timestamp: Date.now()
97
114
  });
98
115
  localStorage.setItem(s.CACHE_KEY, a);
@@ -102,12 +119,12 @@ class s {
102
119
  }
103
120
  async getCachedSDK() {
104
121
  try {
105
- const i = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readonly").objectStore(s.STORE_NAME), n = await new Promise((o, a) => {
106
- const d = i.get("latest");
107
- d.onsuccess = () => o(d.result || null), d.onerror = () => a(d.error);
122
+ const n = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readonly").objectStore(s.STORE_NAME), i = await new Promise((r, a) => {
123
+ const d = n.get("latest");
124
+ d.onsuccess = () => r(d.result || null), d.onerror = () => a(d.error);
108
125
  });
109
- if (n)
110
- return n;
126
+ if (i)
127
+ return i;
111
128
  } catch {
112
129
  }
113
130
  try {
@@ -120,53 +137,53 @@ class s {
120
137
  }
121
138
  openIndexedDB() {
122
139
  return new Promise((e, t) => {
123
- const i = indexedDB.open(s.DB_NAME, s.DB_VERSION);
124
- i.onerror = () => t(i.error), i.onsuccess = () => e(i.result), i.onupgradeneeded = (n) => {
125
- const o = n.target.result;
126
- o.objectStoreNames.contains(s.STORE_NAME) || o.createObjectStore(s.STORE_NAME, { keyPath: "id" });
140
+ const n = indexedDB.open(s.DB_NAME, s.DB_VERSION);
141
+ n.onerror = () => t(n.error), n.onsuccess = () => e(n.result), n.onupgradeneeded = (i) => {
142
+ const r = i.target.result;
143
+ r.objectStoreNames.contains(s.STORE_NAME) || r.createObjectStore(s.STORE_NAME, { keyPath: "id" });
127
144
  };
128
145
  });
129
146
  }
130
147
  }
131
- async function C(r) {
132
- const t = new TextEncoder().encode(r), i = await crypto.subtle.digest("SHA-256", t);
133
- return Array.from(new Uint8Array(i)).map((o) => o.toString(16).padStart(2, "0")).join("");
148
+ async function C(o) {
149
+ const t = new TextEncoder().encode(o), n = await crypto.subtle.digest("SHA-256", t);
150
+ return Array.from(new Uint8Array(n)).map((r) => r.toString(16).padStart(2, "0")).join("");
134
151
  }
135
- function w(r) {
136
- const e = atob(r), t = new Uint8Array(e.length);
137
- for (let i = 0; i < e.length; i++)
138
- t[i] = e.charCodeAt(i);
152
+ function w(o) {
153
+ const e = atob(o), t = new Uint8Array(e.length);
154
+ for (let n = 0; n < e.length; n++)
155
+ t[n] = e.charCodeAt(n);
139
156
  return t;
140
157
  }
141
- function E(r) {
142
- const e = new Uint8Array(r.length / 2);
143
- for (let t = 0; t < r.length; t += 2)
144
- e[t / 2] = Number.parseInt(r.substr(t, 2), 16);
158
+ function E(o) {
159
+ const e = new Uint8Array(o.length / 2);
160
+ for (let t = 0; t < o.length; t += 2)
161
+ e[t / 2] = Number.parseInt(o.substr(t, 2), 16);
145
162
  return e;
146
163
  }
147
- async function D(r, e, t) {
164
+ async function D(o, e, t) {
148
165
  try {
149
- const i = w(r), n = E(e), o = w(t), a = await crypto.subtle.importKey("raw", i, { name: "Ed25519" }, !1, ["verify"]);
150
- return await crypto.subtle.verify("Ed25519", a, o, n);
166
+ const n = w(o), i = E(e), r = w(t), a = await crypto.subtle.importKey("raw", n, { name: "Ed25519" }, !1, ["verify"]);
167
+ return await crypto.subtle.verify("Ed25519", a, r, i);
151
168
  } catch {
152
169
  return !1;
153
170
  }
154
171
  }
155
- async function A(r, e, t, i) {
172
+ async function v(o, e, t, n) {
156
173
  if (!e || !t)
157
174
  throw new Error("SDK verification failed: Missing security headers");
158
- if (await C(r) !== e)
175
+ if (await C(o) !== e)
159
176
  throw new Error("SDK verification failed: Checksum mismatch - content tampered");
160
- if (!await D(i, e, t))
177
+ if (!await D(n, e, t))
161
178
  throw new Error("SDK verification failed: Invalid signature - content tampered");
162
179
  }
163
- class b {
180
+ class A {
164
181
  cleanApiEndpoint(e) {
165
182
  return e.trim().replace(/\/+$/, "");
166
183
  }
167
- async fetchSDK(e, t, i) {
184
+ async fetchSDK(e, t, n) {
168
185
  try {
169
- const n = this.cleanApiEndpoint(t), o = await fetch(`${n}/sdk-serve/sdk/v0`, {
186
+ const i = this.cleanApiEndpoint(t), r = await fetch(`${i}/sdk-serve/sdk/v0`, {
170
187
  method: "GET",
171
188
  headers: {
172
189
  Accept: "application/javascript",
@@ -174,16 +191,16 @@ class b {
174
191
  Origin: window?.location?.origin || ""
175
192
  }
176
193
  });
177
- return o.ok ? this.handleSuccessfulFetch(o, i) : null;
194
+ return r.ok ? this.handleSuccessfulFetch(r, n) : null;
178
195
  } catch {
179
196
  return null;
180
197
  }
181
198
  }
182
199
  async handleSuccessfulFetch(e, t) {
183
- const i = e.headers.get("x-sdk-checksum"), n = e.headers.get("x-sdk-version"), o = e.headers.get("x-sdk-signature"), a = await e.text();
184
- if (!n || !a || !i)
200
+ 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();
201
+ if (!i || !a || !n)
185
202
  throw Object.fromEntries(e.headers.entries()), new Error("Invalid SDK response: missing version, code, or checksum");
186
- return await A(a, i, o, t), { code: a, version: n, checksum: i, signature: o || "" };
203
+ return await v(a, n, r, t), { code: a, version: i, checksum: n, signature: r || "" };
187
204
  }
188
205
  }
189
206
  class g {
@@ -208,8 +225,8 @@ class g {
208
225
  }
209
226
  replayCommand(e) {
210
227
  try {
211
- const t = window.Deway, i = t?.[e.method];
212
- typeof i == "function" && i.apply(t, e.args);
228
+ const t = window.Deway, n = t?.[e.method];
229
+ typeof n == "function" && n.apply(t, e.args);
213
230
  } catch {
214
231
  }
215
232
  }
@@ -225,12 +242,12 @@ class u {
225
242
  */
226
243
  async cacheRemoteConfig(e, t) {
227
244
  try {
228
- const i = {
245
+ const n = {
229
246
  config: e,
230
247
  ttl_seconds: t,
231
248
  timestamp: Date.now()
232
249
  };
233
- localStorage.setItem(u.CACHE_KEY, JSON.stringify(i));
250
+ localStorage.setItem(u.CACHE_KEY, JSON.stringify(n));
234
251
  } catch {
235
252
  }
236
253
  }
@@ -257,11 +274,11 @@ class u {
257
274
  * @returns true if cache is still valid
258
275
  */
259
276
  isCacheValid(e, t) {
260
- const i = Date.now(), n = e + t * 1e3;
261
- return i < n;
277
+ const n = Date.now(), i = e + t * 1e3;
278
+ return n < i;
262
279
  }
263
280
  }
264
- class v {
281
+ class b {
265
282
  cleanApiEndpoint(e) {
266
283
  return e.trim().replace(/\/+$/, "");
267
284
  }
@@ -275,7 +292,7 @@ class v {
275
292
  */
276
293
  async fetchRemoteConfig(e, t) {
277
294
  try {
278
- const i = this.cleanApiEndpoint(t), n = await fetch(`${i}/sdk-remote-config-serve/`, {
295
+ const n = this.cleanApiEndpoint(t), i = await fetch(`${n}/sdk-remote-config-serve/`, {
279
296
  method: "GET",
280
297
  headers: {
281
298
  Accept: "application/json",
@@ -283,13 +300,13 @@ class v {
283
300
  Origin: window?.location?.origin || ""
284
301
  }
285
302
  });
286
- return n.ok ? await n.json() : null;
303
+ return i.ok ? await i.json() : null;
287
304
  } catch {
288
305
  return null;
289
306
  }
290
307
  }
291
308
  }
292
- class K {
309
+ class I {
293
310
  async executeSDK(e) {
294
311
  return new Promise((t) => {
295
312
  try {
@@ -297,16 +314,16 @@ class K {
297
314
  t(!1);
298
315
  return;
299
316
  }
300
- const i = document.createElement("script");
301
- i.textContent = e, i.type = "text/javascript";
302
- let n = !1;
303
- const o = (a) => {
304
- n || (n = !0, this.cleanupScript(i), t(a));
317
+ const n = document.createElement("script");
318
+ n.textContent = e, n.type = "text/javascript";
319
+ let i = !1;
320
+ const r = (a) => {
321
+ i || (i = !0, this.cleanupScript(n), t(a));
305
322
  };
306
- i.onerror = () => {
307
- o(!1);
308
- }, i.onload = () => o(!0), document.head.appendChild(i), setTimeout(() => {
309
- !n && this.verifySDKLoaded() ? o(!0) : n || o(!1);
323
+ n.onerror = () => {
324
+ r(!1);
325
+ }, n.onload = () => r(!0), document.head.appendChild(n), setTimeout(() => {
326
+ !i && this.verifySDKLoaded() ? r(!0) : i || r(!1);
310
327
  }, 100);
311
328
  } catch {
312
329
  t(!1);
@@ -326,7 +343,7 @@ class K {
326
343
  }
327
344
  }
328
345
  }
329
- class k {
346
+ class K {
330
347
  validateConfig(e) {
331
348
  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);
332
349
  }
@@ -338,11 +355,11 @@ class k {
338
355
  }
339
356
  }
340
357
  }
341
- const f = {
358
+ const h = {
342
359
  apiEndpoint: "https://service.deway.app",
343
360
  publicKey: "9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY="
344
361
  };
345
- class I {
362
+ class k {
346
363
  isLoaded = !1;
347
364
  isLoading = !1;
348
365
  cacheManager;
@@ -354,7 +371,7 @@ class I {
354
371
  remoteConfigCache;
355
372
  sdkConfigStore;
356
373
  constructor() {
357
- this.cacheManager = new s(), this.scriptExecutor = new K(), this.commandQueue = new g(), this.sdkFetcher = new b(), this.configValidator = new k(), this.sdkConfigStore = new S(), this.remoteConfigFetcher = new v(), this.remoteConfigCache = new u();
374
+ this.cacheManager = new s(), this.scriptExecutor = new I(), this.commandQueue = new g(), this.sdkFetcher = new A(), this.configValidator = new K(), this.sdkConfigStore = new S(), this.remoteConfigFetcher = new b(), this.remoteConfigCache = new u();
358
375
  }
359
376
  init(e) {
360
377
  this.performInit(e).catch((t) => {
@@ -364,15 +381,15 @@ class I {
364
381
  try {
365
382
  if (!this.canInitialize())
366
383
  return;
367
- const t = this.isInitializationPayload(e), i = t ? e.localConfig : e;
368
- if (!this.configValidator.validateConfig(i))
384
+ const t = this.isInitializationPayload(e), n = t ? e.localConfig : e;
385
+ if (!this.configValidator.validateConfig(n))
369
386
  return;
370
387
  this.isLoading = !0;
371
- const n = i.apiEndpoint || f.apiEndpoint, o = i.publicKey || f.publicKey, [a, d] = await Promise.all([this.fetchOrLoadSDK(i.appKey, n, o), this.fetchRemoteConfigWithCache(i, n)]);
388
+ const i = n.apiEndpoint || h.apiEndpoint, r = n.publicKey || h.publicKey, [a, d] = await Promise.all([this.fetchOrLoadSDK(n.appKey, i, r), this.fetchRemoteConfigWithCache(n, i)]);
372
389
  if (!a)
373
390
  return;
374
- const h = t ? e : this.createInitializationPayload(d, i);
375
- if (!await this.scriptExecutor.executeSDK(a.code) || !this.initializeSDK(h))
391
+ const f = t ? e : this.createInitializationPayload(d, n);
392
+ if (!await this.scriptExecutor.executeSDK(a.code) || !this.initializeSDK(f))
376
393
  return;
377
394
  this.commandQueue.replayQueuedCommands(), this.isLoaded = !0;
378
395
  } finally {
@@ -391,13 +408,13 @@ class I {
391
408
  */
392
409
  async fetchRemoteConfigWithCache(e, t) {
393
410
  this.sdkConfigStore.saveConfig(e);
394
- const i = await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey, t);
395
- if (i)
396
- return await this.remoteConfigCache.cacheRemoteConfig(i.config, i.ttl_seconds), i;
397
- const n = await this.remoteConfigCache.getCachedRemoteConfig();
398
- return n ? {
399
- config: n.config,
400
- ttl_seconds: n.ttl_seconds
411
+ const n = await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey, t);
412
+ if (n)
413
+ return await this.remoteConfigCache.cacheRemoteConfig(n.config, n.ttl_seconds), n;
414
+ const i = await this.remoteConfigCache.getCachedRemoteConfig();
415
+ return i ? {
416
+ config: i.config,
417
+ ttl_seconds: i.ttl_seconds
401
418
  } : null;
402
419
  }
403
420
  /**
@@ -409,12 +426,12 @@ class I {
409
426
  return {
410
427
  localConfig: t,
411
428
  remoteConfig: e?.config ?? null,
412
- defaults: f
429
+ defaults: h
413
430
  };
414
431
  }
415
- async fetchOrLoadSDK(e, t, i) {
416
- const n = await this.sdkFetcher.fetchSDK(e, t, i);
417
- return n ? (await this.cacheManager.cacheSDK(n.code, n.version, n.checksum, n.signature), n) : this.loadFromCache();
432
+ async fetchOrLoadSDK(e, t, n) {
433
+ const i = await this.sdkFetcher.fetchSDK(e, t, n);
434
+ return i ? (await this.cacheManager.cacheSDK(i.code, i.version, i.checksum, i.signature), i) : this.loadFromCache();
418
435
  }
419
436
  async loadFromCache() {
420
437
  const e = await this.cacheManager.getCachedSDK();
@@ -483,18 +500,18 @@ class I {
483
500
  return typeof window < "u" && "Deway" in window && !!window.Deway;
484
501
  }
485
502
  }
486
- const c = new I(), T = {
487
- init: (r) => c.init(r),
488
- identify: (r) => c.identify(r),
489
- reportEvent: (r, e) => c.reportEvent(r, e),
490
- setUserProfile: (r) => c.setUserProfile(r),
491
- show: (r) => c.show(r),
503
+ const c = new k(), x = {
504
+ init: (o) => c.init(o),
505
+ identify: (o) => c.identify(o),
506
+ reportEvent: (o, e) => c.reportEvent(o, e),
507
+ setUserProfile: (o) => c.setUserProfile(o),
508
+ show: (o) => c.show(o),
492
509
  hide: () => c.hide(),
493
510
  isVisible: () => c.isVisible(),
494
511
  isInitialized: () => c.isInitialized(),
495
512
  destroy: () => c.destroy()
496
513
  };
497
- typeof window < "u" && (window.Deway = T);
514
+ typeof window < "u" && (window.Deway = x);
498
515
  export {
499
- T as default
516
+ x as default
500
517
  };
@@ -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}getTalkToHumanBtnTxt(){return this.loadConfig()?.talkToHumanBtnTxt??"talk to Support"}getHumanHandoffUrl(){return this.loadConfig()?.humanHandoffUrl}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."}getBookmarkAppearanceMode(){return this.loadConfig()?.bookmarkAppearanceMode??"bookmark"}getTenantTheme(){return this.loadConfig()?.tenantTheme??null}getTenantThemeForMode(e){const t=this.getTenantTheme();return t?e==="dark"?t.dark:t.light:null}}class s{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,i,n){try{const d=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readwrite").objectStore(s.STORE_NAME);await new Promise((y,S)=>{const f=d.put({id:"latest",code:e,version:t,checksum:i,signature:n,timestamp:Date.now()});f.onsuccess=()=>y(f.result),f.onerror=()=>S(f.error)})}catch{try{const a=JSON.stringify({code:e,version:t,checksum:i,signature:n,timestamp:Date.now()});localStorage.setItem(s.CACHE_KEY,a)}catch{}}}async getCachedSDK(){try{const i=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readonly").objectStore(s.STORE_NAME),n=await new Promise((o,a)=>{const d=i.get("latest");d.onsuccess=()=>o(d.result||null),d.onerror=()=>a(d.error)});if(n)return n}catch{}try{const e=localStorage.getItem(s.CACHE_KEY);if(e)return JSON.parse(e)}catch{}return null}openIndexedDB(){return new Promise((e,t)=>{const i=indexedDB.open(s.DB_NAME,s.DB_VERSION);i.onerror=()=>t(i.error),i.onsuccess=()=>e(i.result),i.onupgradeneeded=n=>{const o=n.target.result;o.objectStoreNames.contains(s.STORE_NAME)||o.createObjectStore(s.STORE_NAME,{keyPath:"id"})}})}}async function E(r){const t=new TextEncoder().encode(r),i=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(i)).map(o=>o.toString(16).padStart(2,"0")).join("")}function w(r){const e=atob(r),t=new Uint8Array(e.length);for(let i=0;i<e.length;i++)t[i]=e.charCodeAt(i);return t}function D(r){const e=new Uint8Array(r.length/2);for(let t=0;t<r.length;t+=2)e[t/2]=Number.parseInt(r.substr(t,2),16);return e}async function A(r,e,t){try{const i=w(r),n=D(e),o=w(t),a=await crypto.subtle.importKey("raw",i,{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",a,o,n)}catch{return!1}}async function b(r,e,t,i){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await E(r)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await A(i,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class v{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchSDK(e,t,i){try{const n=this.cleanApiEndpoint(t),o=await fetch(`${n}/sdk-serve/sdk/v0`,{method:"GET",headers:{Accept:"application/javascript","deway-app-key":e,Origin:window?.location?.origin||""}});return o.ok?this.handleSuccessfulFetch(o,i):null}catch{return null}}async handleSuccessfulFetch(e,t){const i=e.headers.get("x-sdk-checksum"),n=e.headers.get("x-sdk-version"),o=e.headers.get("x-sdk-signature"),a=await e.text();if(!n||!a||!i)throw Object.fromEntries(e.headers.entries()),new Error("Invalid SDK response: missing version, code, or checksum");return await b(a,i,o,t),{code:a,version:n,checksum:i,signature:o||""}}}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,i=t?.[e.method];typeof i=="function"&&i.apply(t,e.args)}catch{}}}class h{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const i={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(h.CACHE_KEY,JSON.stringify(i))}catch{}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(h.CACHE_KEY);return e?JSON.parse(e):null}catch{return null}}isCacheValid(e,t){const i=Date.now(),n=e+t*1e3;return i<n}}class K{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchRemoteConfig(e,t){try{const i=this.cleanApiEndpoint(t),n=await fetch(`${i}/sdk-remote-config-serve/`,{method:"GET",headers:{Accept:"application/json","deway-app-key":e,Origin:window?.location?.origin||""}});return n.ok?await n.json():null}catch{return null}}}class k{async executeSDK(e){return new Promise(t=>{try{if(!this.isDocumentReady()){t(!1);return}const i=document.createElement("script");i.textContent=e,i.type="text/javascript";let n=!1;const o=a=>{n||(n=!0,this.cleanupScript(i),t(a))};i.onerror=()=>{o(!1)},i.onload=()=>o(!0),document.head.appendChild(i),setTimeout(()=>{!n&&this.verifySDKLoaded()?o(!0):n||o(!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 T{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 I{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new s,this.scriptExecutor=new k,this.commandQueue=new g,this.sdkFetcher=new v,this.configValidator=new T,this.sdkConfigStore=new C,this.remoteConfigFetcher=new K,this.remoteConfigCache=new h}init(e){this.performInit(e).catch(t=>{})}async performInit(e){try{if(!this.canInitialize())return;const t=this.isInitializationPayload(e),i=t?e.localConfig:e;if(!this.configValidator.validateConfig(i))return;this.isLoading=!0;const n=i.apiEndpoint||m.apiEndpoint,o=i.publicKey||m.publicKey,[a,d]=await Promise.all([this.fetchOrLoadSDK(i.appKey,n,o),this.fetchRemoteConfigWithCache(i,n)]);if(!a)return;const y=t?e:this.createInitializationPayload(d,i);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 i=await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey,t);if(i)return await this.remoteConfigCache.cacheRemoteConfig(i.config,i.ttl_seconds),i;const n=await this.remoteConfigCache.getCachedRemoteConfig();return n?{config:n.config,ttl_seconds:n.ttl_seconds}:null}createInitializationPayload(e,t){return{localConfig:t,remoteConfig:e?.config??null,defaults:m}}async fetchOrLoadSDK(e,t,i){const n=await this.sdkFetcher.fetchSDK(e,t,i);return n?(await this.cacheManager.cacheSDK(n.code,n.version,n.checksum,n.signature),n):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{}}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}}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 c=new I,p={init:r=>c.init(r),identify:r=>c.identify(r),reportEvent:(r,e)=>c.reportEvent(r,e),setUserProfile:r=>c.setUserProfile(r),show:r=>c.show(r),hide:()=>c.hide(),isVisible:()=>c.isVisible(),isInitialized:()=>c.isInitialized(),destroy:()=>c.destroy()};return typeof window<"u"&&(window.Deway=p),p}));
1
+ (function(u,l){typeof exports=="object"&&typeof module<"u"?module.exports=l():typeof define=="function"&&define.amd?define(l):(u=typeof globalThis<"u"?globalThis:u||self,u.Deway=l())})(this,(function(){"use strict";const u="deway-sdk-config",l=["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(u,t)}catch{}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(u);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??l}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."}getBookmarkAppearanceMode(){return this.loadConfig()?.bookmarkAppearanceMode??"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}getBookmarkIconInlineSvg(){return this.getCustomIcons()?.bookmark_icon_inline_svg??void 0}getEmptyChatStateIconInlineSvg(){return this.getCustomIcons()?.empty_chat_state_icon_inline_svg??void 0}}class s{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([s.STORE_NAME],"readwrite").objectStore(s.STORE_NAME);await new Promise((y,S)=>{const f=d.put({id:"latest",code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});f.onsuccess=()=>y(f.result),f.onerror=()=>S(f.error)})}catch{try{const a=JSON.stringify({code:e,version:t,checksum:n,signature:i,timestamp:Date.now()});localStorage.setItem(s.CACHE_KEY,a)}catch{}}}async getCachedSDK(){try{const n=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readonly").objectStore(s.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(s.CACHE_KEY);if(e)return JSON.parse(e)}catch{}return null}openIndexedDB(){return new Promise((e,t)=>{const n=indexedDB.open(s.DB_NAME,s.DB_VERSION);n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result),n.onupgradeneeded=i=>{const r=i.target.result;r.objectStoreNames.contains(s.STORE_NAME)||r.createObjectStore(s.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 w(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 v(o,e,t){try{const n=w(o),i=D(e),r=w(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 A(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 v(n,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class b{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 A(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 h{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const n={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(h.CACHE_KEY,JSON.stringify(n))}catch{}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(h.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 x{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new s,this.scriptExecutor=new K,this.commandQueue=new g,this.sdkFetcher=new b,this.configValidator=new k,this.sdkConfigStore=new C,this.remoteConfigFetcher=new I,this.remoteConfigCache=new h}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{}}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}}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 c=new x,p={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(),isVisible:()=>c.isVisible(),isInitialized:()=>c.isInitialized(),destroy:()=>c.destroy()};return typeof window<"u"&&(window.Deway=p),p}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deway-ai/web-sdk",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "type": "module",
5
5
  "description": "Deway's Web SDK",
6
6
  "main": "dist/loader.umd.js",