@deway-ai/web-sdk 0.78.0 → 0.80.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
@@ -25,7 +25,7 @@ function T(o, e) {
25
25
  const i = typeof e == "object" && e !== null && !Array.isArray(e) ? e : n ? { value: e } : {};
26
26
  return { ...o, ...i };
27
27
  }
28
- function w(o, e, t, n, i) {
28
+ function p(o, e, t, n, i) {
29
29
  const r = e;
30
30
  if (I[o] < r) return;
31
31
  const s = {
@@ -39,16 +39,16 @@ function u(o) {
39
39
  const e = o !== void 0 && "minLevel" in o ? o.minLevel : void 0, t = e === void 0 ? x : I[e], n = o?.context;
40
40
  return {
41
41
  debug(i, r) {
42
- w("debug", t, i, n, r);
42
+ p("debug", t, i, n, r);
43
43
  },
44
44
  info(i, r) {
45
- w("info", t, i, n, r);
45
+ p("info", t, i, n, r);
46
46
  },
47
47
  warn(i, r) {
48
- w("warn", t, i, n, r);
48
+ p("warn", t, i, n, r);
49
49
  },
50
50
  error(i, r) {
51
- w("error", t, i, n, r);
51
+ p("error", t, i, n, r);
52
52
  },
53
53
  child(i) {
54
54
  return u({
@@ -125,6 +125,9 @@ class O {
125
125
  getEntrypointWidgetAppearanceMode() {
126
126
  return this.loadConfig()?.entrypointWidgetAppearanceMode ?? "bookmark";
127
127
  }
128
+ getChatAppearanceMode() {
129
+ return this.loadConfig()?.chatAppearanceMode ?? "floating-window";
130
+ }
128
131
  getTenantTheme() {
129
132
  return this.loadConfig()?.tenantTheme ?? null;
130
133
  }
@@ -258,7 +261,7 @@ async function P(o, e, t, n) {
258
261
  throw new Error("SDK verification failed: Invalid signature - content tampered");
259
262
  }
260
263
  const m = u({ context: { module: "sdk-fetcher" } });
261
- class V {
264
+ class M {
262
265
  cleanApiEndpoint(e) {
263
266
  return e.trim().replace(/\/+$/, "");
264
267
  }
@@ -321,7 +324,7 @@ class C {
321
324
  }
322
325
  }
323
326
  }
324
- const p = u({ context: { module: "remote-config-cache" } });
327
+ const w = u({ context: { module: "remote-config-cache" } });
325
328
  class b {
326
329
  static CACHE_KEY = "deway-remote-config-cache";
327
330
  /**
@@ -338,9 +341,9 @@ class b {
338
341
  ttl_seconds: t,
339
342
  timestamp: Date.now()
340
343
  };
341
- localStorage.setItem(b.CACHE_KEY, JSON.stringify(n)), p.debug("Remote configuration cached in localStorage");
344
+ localStorage.setItem(b.CACHE_KEY, JSON.stringify(n)), w.debug("Remote configuration cached in localStorage");
342
345
  } catch (n) {
343
- p.warn("Failed to cache remote config", n);
346
+ w.warn("Failed to cache remote config", n);
344
347
  }
345
348
  }
346
349
  /**
@@ -355,9 +358,9 @@ class b {
355
358
  if (!e)
356
359
  return null;
357
360
  const t = JSON.parse(e);
358
- return p.debug("Found cached remote configuration"), t;
361
+ return w.debug("Found cached remote configuration"), t;
359
362
  } catch (e) {
360
- return p.warn("Failed to read cached remote config", e), null;
363
+ return w.warn("Failed to read cached remote config", e), null;
361
364
  }
362
365
  }
363
366
  /**
@@ -374,7 +377,7 @@ class b {
374
377
  }
375
378
  }
376
379
  const S = u({ context: { module: "remote-config-fetcher" } });
377
- class j {
380
+ class V {
378
381
  cleanApiEndpoint(e) {
379
382
  return e.trim().replace(/\/+$/, "");
380
383
  }
@@ -408,7 +411,7 @@ class j {
408
411
  }
409
412
  }
410
413
  const y = u({ context: { module: "script-executor" } });
411
- class H {
414
+ class j {
412
415
  async executeSDK(e) {
413
416
  return new Promise((t) => {
414
417
  try {
@@ -447,7 +450,7 @@ class H {
447
450
  }
448
451
  }
449
452
  const D = u({ context: { module: "config-validator" } });
450
- class M {
453
+ class H {
451
454
  validateConfig(e) {
452
455
  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);
453
456
  }
@@ -475,7 +478,7 @@ class B {
475
478
  remoteConfigCache;
476
479
  sdkConfigStore;
477
480
  constructor() {
478
- this.cacheManager = new l(), this.scriptExecutor = new H(), this.commandQueue = new C(), this.sdkFetcher = new V(), this.configValidator = new M(), this.sdkConfigStore = new O(), this.remoteConfigFetcher = new j(), this.remoteConfigCache = new b();
481
+ this.cacheManager = new l(), this.scriptExecutor = new j(), this.commandQueue = new C(), this.sdkFetcher = new M(), this.configValidator = new H(), this.sdkConfigStore = new O(), this.remoteConfigFetcher = new V(), this.remoteConfigCache = new b();
479
482
  }
480
483
  init(e) {
481
484
  this.performInit(e).catch((t) => {
@@ -1 +1 @@
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}})},alwaysOnLog(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"],O=18;class R{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??O}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 R,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}));
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}})},alwaysOnLog(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"],O=18;class R{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"}getChatAppearanceMode(){return this.loadConfig()?.chatAppearanceMode??"floating-window"}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??O}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 M(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 j{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 M(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 V{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 H{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 H,this.commandQueue=new D,this.sdkFetcher=new j,this.configValidator=new B,this.sdkConfigStore=new R,this.remoteConfigFetcher=new V,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}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deway-ai/web-sdk",
3
- "version": "0.78.0",
3
+ "version": "0.80.0",
4
4
  "type": "module",
5
5
  "description": "Deway's Web SDK",
6
6
  "main": "dist/loader.umd.js",