@gengage/assistant-fe 0.6.10 → 0.6.12

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.
@@ -17,3 +17,4 @@ export { createDiagnosticsTool, createReadPageTool, installBrowserTools } from '
17
17
  export { startLazyRuntimeLoader } from './util/lazy-runtime-loader.js';
18
18
  export { requestText } from './util/request-text.js';
19
19
  export { elapsedMs, nowIso } from './util/time.js';
20
+ export type { AdapterStep, FlowAdapterFn, FlowAdapterMap } from './types.js';
@@ -1,4 +1,4 @@
1
- import { A as B, C as Ae, D as I, E as Pe, F as Re, I as Ue, M as k, O as ve, P as F, R as G, S as Te, T as xe, _ as _e, a as Le, b as je, c as Ce, d as Me, f as $e, g as De, h as Oe, i as qe, j as Be, k as Ie, l as ke, m as Fe, n as Ge, o as Ne, p as He, r as Je, s as ze, t as We, u as Ke, v as N, w as Qe, x as Ye, y as H, z as J } from "../similarity-XEVfAN-6.js";
1
+ import { A as B, C as Ae, D as I, E as Pe, F as Re, I as Ue, M as k, O as ve, P as F, R as G, S as Te, T as xe, _ as _e, a as Le, b as je, c as Ce, d as Me, f as $e, g as De, h as Oe, i as qe, j as Be, k as Ie, l as ke, m as Fe, n as Ge, o as Ne, p as He, r as Je, s as ze, t as We, u as Ke, v as N, w as Qe, x as Ye, y as H, z as J } from "../similarity-qMH5-do-.js";
2
2
  var z = 512, W = 0.74;
3
3
  function K({ accountId: e, worker: t, beUrl: r, devJwtSecret: n, tokenBrokerUrl: o, tokenBrokerAudience: s, defaultLocale: i, tools: d = {}, beacon: w }) {
4
4
  let m = 1;
@@ -43,6 +43,8 @@ export interface FlowStepCtx {
43
43
  }
44
44
  export type FlowValue<T> = T | ((ctx: FlowStepCtx) => T);
45
45
  export type FlowPatch = (ctx: ChatContext, result: unknown, snapshot: FlowStepCtx) => Partial<ChatContext> | null | undefined;
46
+ export type FlowAdapterFn = (input: unknown, ctx: FlowStepCtx) => unknown | Promise<unknown>;
47
+ export type FlowAdapterMap = Record<string, FlowAdapterFn>;
46
48
  export interface BeOpStep {
47
49
  kind: 'be_op';
48
50
  op: string;
@@ -59,6 +61,13 @@ export interface ToolStep {
59
61
  out?: string;
60
62
  patch?: FlowPatch;
61
63
  }
64
+ export interface AdapterStep {
65
+ kind: 'adapter';
66
+ name: string;
67
+ input: FlowValue<unknown>;
68
+ out?: string;
69
+ patch?: FlowPatch;
70
+ }
62
71
  export interface EmitStep {
63
72
  kind: 'emit';
64
73
  build: (ctx: FlowStepCtx) => StreamEvent;
@@ -79,7 +88,7 @@ export interface RefusalStep {
79
88
  export interface CommitStep {
80
89
  kind: 'commit';
81
90
  }
82
- export type FlowStep = BeOpStep | ToolStep | EmitStep | BranchStep | ParallelStep | RefusalStep | CommitStep;
91
+ export type FlowStep = BeOpStep | ToolStep | AdapterStep | EmitStep | BranchStep | ParallelStep | RefusalStep | CommitStep;
83
92
  export type Flow = readonly FlowStep[];
84
93
  export type ToolFn = (input: unknown) => unknown | Promise<unknown>;
85
94
  export type ToolMap = Record<string, ToolFn>;
@@ -88,6 +97,7 @@ export interface AccountModule {
88
97
  defaultLocale?: string;
89
98
  flows: Record<string, Flow>;
90
99
  tools?: ToolMap;
100
+ adapters?: FlowAdapterMap;
91
101
  accountConfig?: Record<string, unknown>;
92
102
  }
93
103
  export interface AgentOpBeacon {
@@ -15,3 +15,4 @@ export { runTurn } from './worker/flow-runner.js';
15
15
  export { createJwtProvider, mintDevJwt } from './worker/jwt-mint.js';
16
16
  export { createWorkerRpc, handleMainRpc, runMainRpc } from './worker/rpc.js';
17
17
  export { createToolBridge } from './worker/tool-bridge.js';
18
+ export type { AdapterStep, FlowAdapterFn, FlowAdapterMap } from './types.js';
@@ -1,4 +1,4 @@
1
- import { A as P, C as m, D as B, E as J, F as M, I as F, L as I, M as C, N as g, O as j, P as T, R as L, S as h, T as z, _ as R, a as q, b as D, c as K, d as O, f as W, g as G, h as N, i as Q, j as _, k as H, l as V, m as X, n as Y, o as Z, p as $, r as tt, s as et, t as rt, u as ot, v as x, w as at, x as nt, y as A, z as it } from "../similarity-XEVfAN-6.js";
1
+ import { A as P, C as m, D as B, E as J, F as M, I as F, L as I, M as C, N as g, O as j, P as T, R as L, S as h, T as z, _ as R, a as q, b as D, c as K, d as O, f as W, g as G, h as N, i as Q, j as _, k as H, l as V, m as X, n as Y, o as Z, p as $, r as tt, s as et, t as rt, u as ot, v as x, w as at, x as nt, y as A, z as it } from "../similarity-qMH5-do-.js";
2
2
  function ct(i) {
3
3
  const a = self, n = /* @__PURE__ */ new Map(), c = I(a), S = x(c);
4
4
  let e = null, u = null, l = null, p = "";
@@ -1,5 +1,5 @@
1
- (function(m){Object.defineProperty(m,Symbol.toStringTag,{value:"Module"});function qe(e){return!!e&&typeof e=="object"&&e.type==="rpc.req"}function ze({worker:e,tools:t={},beacon:n,memory:r=sessionStorage}){e.addEventListener("message",o=>{const i=o.data;qe(i)&&Ge(e,i,{tools:t,beacon:n,memory:r})})}async function Ge(e,t,n){try{const r=await te(t.method,t.payload,n);e.postMessage({type:"rpc.result",rpcId:t.rpcId,ok:!0,value:r})}catch(r){e.postMessage({type:"rpc.result",rpcId:t.rpcId,ok:!1,error:{message:r instanceof Error?r.message:String(r)}})}}function Je(e){if(e&&typeof e=="object"&&typeof e.name=="string")return e;throw new Error("tool.invoke requires { name, input }")}function He(e){if(e&&typeof e=="object"&&e.key!==void 0)return e;throw new Error("memory.get requires { key }")}function Ke(e){if(e&&typeof e=="object"&&e.key!==void 0)return e;throw new Error("memory.set requires { key }")}async function te(e,t,{tools:n,beacon:r,memory:o}){if(e==="tool.invoke"){const{name:i,input:a}=Je(t),s=n[i];if(typeof s!="function")throw new Error(`Unknown tool: ${i}`);return s(a)}if(e==="beacon.send")return r?.(t),{sent:!0};if(e==="memory.get"){const{key:i}=He(t),a=o.getItem(String(i));return a?JSON.parse(a):null}if(e==="memory.set"){const{key:i,value:a}=Ke(t);return o.setItem(String(i),JSON.stringify(a??null)),{ok:!0}}throw new Error(`Unknown RPC method: ${e}`)}function ne(){return new Date().toISOString()}function U(e){return Math.max(0,Math.round(performance.now()-e))}function v(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function We(e){const{accountId:t,locale:n="en-GB",parentUrl:r="",threadId:o,incomingContext:i}=e,a=v(i)?i:{},s=v(a.thread)?a.thread:{},f=v(a.panel)?a.panel:{},p=v(a.meta)?a.meta:{},d=re(a.messages),u={id:String(o||s.id||self.crypto.randomUUID()),started_at:String(s.started_at||ne()),extensions:v(s.extensions)?{...s.extensions}:{}},c=String(p.locale||n),l=String(p.parentUrl||r||typeof self<"u"&&self.location?.href||"");return{panel:{...f},messages:d,thread:u,meta:{locale:c,parentUrl:l,accountId:t}}}function Ve(e,t){const n=re([t])[0];return n?{...e,messages:[...e.messages,n].slice(-50)}:e}function re(e){return Array.isArray(e)?e.map(t=>{const n=t?.role;return{role:n==="model"?"assistant":typeof n=="string"?n:"",content:String(t?.content||"")}}).filter(t=>(t.role==="user"||t.role==="assistant")&&!!t.content).slice(-50):[]}var Qe="gengage:agent:context:";async function Ye({accountId:e,threadId:t,rpc:n}){const r=await n("memory.get",{tier:"session",key:oe(e,t)});return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}async function Xe({accountId:e,threadId:t,extensions:n,rpc:r}){await r("memory.set",{tier:"session",key:oe(e,t),value:{thread:{extensions:n}}})}function oe(e,t){return`${Qe}${e}:${t}`}function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var ie=class{#e=new Map;#t;#r;#o;#n;constructor({accountId:e,locale:t,parentUrl:n,rpc:r}){this.#t=e,this.#r=t,this.#o=n,this.#n=r}async load(e){const t=e?.meta?.threadId||e?.session_id||e?.sessionId,n=String(t||"default"),r=this.#e.get(n);if(r)return r;const o=await Ye({accountId:this.#t,threadId:n,rpc:this.#n}),i=We({accountId:this.#t,locale:e?.locale||this.#r,parentUrl:this.#o,threadId:n,incomingContext:Ze(o,e?.context)});return this.#e.set(n,i),i}patch(e,t){const n=String(e||"default"),r=this.#e.get(n);if(!r)return null;const o=ae(r,typeof t=="function"?t(r):t);return this.#e.set(n,o),o}appendUserMessage(e,t){const n=String(e||"default");if(!t)return this.#e.get(n)??null;const r=this.#e.get(n);if(!r)return null;const o=Ve(r,{role:"user",content:t});return this.#e.set(n,o),o}async commit(e){const t=String(e||"default"),n=this.#e.get(t);return n?(await Xe({accountId:this.#t,threadId:t,extensions:n.thread.extensions,rpc:this.#n}),n):null}};function Ze(e,t){return!S(e)&&!S(t)?{}:ae(S(e)?e:{},S(t)?t:{})}function ae(e,t){if(!S(t))return e;const n=e,r=t,o=S(n.panel)?n.panel:{},i=S(r.panel)?r.panel:{},a=S(n.thread)?n.thread:{},s=S(r.thread)?r.thread:{},f=S(a.extensions)?a.extensions:{},p=S(s.extensions)?s.extensions:{},d=S(n.meta)?n.meta:{},u=S(r.meta)?r.meta:{};return{...e,...t,panel:{...o,...i},thread:{...a,...s,extensions:{...f,...p}},meta:{...d,...u},messages:Array.isArray(r.messages)?r.messages.slice(-50):e.messages??[]}}function se(e){const t=String.fromCharCode(...e);return btoa(t).replace(/\+/gu,"-").replace(/\//gu,"_").replace(/=+$/u,"")}function ce(e){return se(new TextEncoder().encode(JSON.stringify(e)))}async function et({accountId:e,devJwtSecret:t,ttlS:n=300}){if(!t)throw new Error("devJwtSecret is required for local agent mode.");const r=Math.floor(Date.now()/1e3),o=`${ce({alg:"HS256",typ:"JWT"})}.${ce({sub:e,iat:r,exp:r+n,scope:"invoke",jti:crypto.randomUUID?.()||`${r}-${Math.random()}`})}`,i=await crypto.subtle.importKey("raw",new TextEncoder().encode(t),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",i,new TextEncoder().encode(o));return`${o}.${se(new Uint8Array(a))}`}function ue({accountId:e,devJwtSecret:t,tokenBrokerUrl:n,tokenBrokerAudience:r,refreshSkewS:o=30,fetchImpl:i=fetch}){let a=null;return async({signal:s,parentUrl:f}={})=>{if(t)return et({accountId:e,devJwtSecret:t});if(!n)throw new Error("tokenBrokerUrl is required for production agent mode.");const p=Math.floor(Date.now()/1e3);return a?.token&&a.expiresAtS-o>p||(a=await tt({accountId:e,tokenBrokerUrl:n,tokenBrokerAudience:r,parentUrl:f,signal:s,fetchImpl:i})),a.token}}async function tt({accountId:e,tokenBrokerUrl:t,tokenBrokerAudience:n,parentUrl:r,signal:o,fetchImpl:i}){const a=await i(t,{method:"POST",credentials:"include",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({accountId:e,scope:"invoke",audience:n||void 0,parentUrl:r||void 0}),...o?{signal:o}:{}});if(!a.ok)throw new Error(`Token broker request failed (${a.status}).`);const s=await a.json(),f=s?.token||s?.jwt||s?.access_token;if(!f||typeof f!="string")throw new Error("Token broker response did not include a JWT.");return{token:f,expiresAtS:nt(s)||rt(f)||Math.floor(Date.now()/1e3)+300}}function nt(e){const t=e?.expiresAtS??e?.expires_at_s??e?.expiresInS??e?.expires_in_s;if(Number.isFinite(t))return Number(t);const n=e?.expiresIn??e?.expires_in;if(Number.isFinite(n))return Math.floor(Date.now()/1e3)+Number(n);const r=e?.expiresAt??e?.expires_at;if(typeof r=="string"){const o=Date.parse(r);if(Number.isFinite(o))return Math.floor(o/1e3)}return null}function rt(e){try{const[,t]=e.split(".");if(!t)return null;const n=t.replace(/-/gu,"+").replace(/_/gu,"/"),r=atob(n.padEnd(Math.ceil(n.length/4)*4,"=")),o=JSON.parse(r);return Number.isFinite(o?.exp)?Number(o.exp):null}catch{return null}}var le={unauthorized:{code:"auth",message:"Assistant authentication failed. Please retry."},forbidden:{code:"auth",message:"Assistant authentication failed. Please retry."},unknown_op:{code:"op_unavailable",message:"This assistant action is not available yet."},invalid_input:{code:"invalid_request",message:"The assistant request was not valid."},account_config:{code:"account_config",message:"Assistant configuration is unavailable."},upstream_llm:{code:"op_failed",message:"The assistant could not complete that request."},upstream_timeout:{code:"op_timeout",message:"The assistant took too long to respond."},schema_mismatch:{code:"op_failed",message:"The assistant could not complete that request."},rate_limited:{code:"rate_limited",message:"The assistant is receiving too many requests. Please retry shortly."},internal:{code:"op_failed",message:"The assistant could not complete that request."},payload_too_large:{code:"invalid_request",message:"The assistant request was too large."}},$=class extends Error{constructor(e,t,n={}){super(t),this.name="AgentError",this.code=e,this.source=n.source||"agent",n.sourceCode&&(this.sourceCode=n.sourceCode),n.detail!==void 0&&(this.detail=n.detail)}};function L(e){const t=String(e?.code||"upstream_llm"),n=le[t]||le.upstream_llm;return new $(n.code,n.message,{source:"be",sourceCode:t,detail:e?.detail})}function de(e,t){const n=t?.error&&typeof t.error=="object"?t.error:{};return L({code:String(n.code||ot(e)),detail:n.detail})}function fe(e){return e instanceof $?{type:"error",code:e.code,message:e.message}:{type:"error",code:"agent_invoke_failed",message:"The assistant could not complete that request."}}function ot(e){return e===401?"unauthorized":e===403?"forbidden":e===413?"payload_too_large":e===429?"rate_limited":"internal"}async function it({beUrl:e,accountId:t,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o,jwtProvider:i,parentUrl:a,op:s,input:f,cacheTtlS:p,cacheKey:d,signal:u}){const c=await(i||ue({accountId:t,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o}))({...u?{signal:u}:{},...a?{parentUrl:a}:{}}),{opDomain:l,opName:y}=at(s),g={method:"POST",headers:{authorization:`Bearer ${c}`,"content-type":"application/json",accept:"application/x-ndjson"},body:JSON.stringify({op_domain:l,op_name:y,op_payload:f,...p!==void 0?{cache_ttl_s:p}:{},...d!==void 0?{cache_key:d}:{}}),...u?{signal:u}:{}},h=await fetch(`${String(e).replace(/\/+$/u,"")}/v1/execute`,g);if(!h.ok)throw de(h.status,await st(h));return ct(h)}function at(e){const t=e.indexOf("-");if(t<=0||t===e.length-1)throw new Error(`Invalid BE op name: ${e}`);return{opDomain:e.slice(0,t),opName:e.slice(t+1)}}async function st(e){try{return await e.json()}catch{return{error:{code:e.statusText||"internal"}}}}async function ct(e){const t=e.body?.getReader();if(!t)throw new Error("BE response body is not readable.");const n=new TextDecoder;let r="";const o={};for(;;){const{value:a,done:s}=await t.read();if(s)break;r+=n.decode(a,{stream:!0});let f=r.indexOf(`
2
- `);for(;f>=0;){const p=r.slice(0,f).trim();r=r.slice(f+1),p&&pe(JSON.parse(p),o),f=r.indexOf(`
3
- `)}}const i=r.trim();return i&&pe(JSON.parse(i),o),o}function pe(e,t){if(e._error)throw L(e._error);e._end||Object.assign(t,e)}function ut(e={}){return{type:"metadata",...e}}function C(e,t=!1,n={}){return{type:"text_chunk",content:e,final:t,...n}}function me(e){return{type:"ui_spec",...e}}function lt(e){return{type:"action",action:e}}function ye(e,t){return{type:"error",code:e,message:t}}function D(){return{type:"done"}}function ge(e,t){return e[t?.type||t?.action?.type||"inputText"]||e.inputText}async function dt({request:e,accountModule:t,contextStore:n,beClient:r,toolBridge:o,emit:i,rpc:a,signal:s}){const f=performance.now(),p=await n.load(e),d=p.thread.id,u=St(e);n.appendUserMessage(d,u);const c=ge(t.flows,e);if(!c)return i(ye("unknown_action",`No agent flow for request type ${e?.type||"inputText"}`)),i(D()),{steps:0,productSkusEmitted:[]};const l={request:e,context:n.patch(d,{})||p,bag:{},accountConfig:t.accountConfig||{},threadId:d,steps:0,productSkusEmitted:new Set,committed:!1},y={contextStore:n,beClient:r,toolBridge:o,emit:i,rpc:a,...s?{signal:s}:{}};return await F(c,l,y),l.committed||await q(l,y),await a("beacon.send",{type:"turnSummary",threadId:d,sessionId:e?.session_id||e?.sessionId||d,accountId:t.accountId||l.context.meta.accountId,steps:l.steps,totalLatencyMs:U(f),productSkusEmitted:[...l.productSkusEmitted]}),{steps:l.steps,productSkusEmitted:[...l.productSkusEmitted]}}async function F(e,t,n){for(const r of e){if(n.signal?.aborted)return;t.steps+=1,await ft(r,t,n),t.context=n.contextStore.patch(t.threadId,{})||t.context}}async function ft(e,t,n){const r=z(t);if(e.kind==="be_op"){await pt(e,t,n,r);return}if(e.kind==="tool"){await mt(e,t,n,r);return}if(e.kind==="emit"){yt(e,t,n);return}if(e.kind==="branch"){await gt(e,t,n,r);return}if(e.kind==="parallel"){await ht(e,t,n);return}if(e.kind==="refusal"){await wt(e,t,n,r);return}e.kind==="commit"&&await bt(e,t,n)}async function pt(e,t,n,r){const o=performance.now();let i;const a=x(e.cacheTtlS,r),s=x(e.cacheKey,r);try{i=await n.beClient.invoke({op:e.op,input:x(e.input,r),...a!==void 0?{cacheTtlS:a}:{},...s!==void 0?{cacheKey:s}:{},...n.signal?{signal:n.signal}:{}})}catch(p){const d=p,u=String(d?.sourceCode||d?.code||"unknown"),c={type:"agentOp",threadId:t.threadId,sessionId:t.request?.session_id||t.request?.sessionId||t.threadId,accountId:t.context.meta.accountId,op:e.op,status:"error",latencyMs:U(o),errorCode:u};throw await n.rpc("beacon.send",c),p}e.out&&(t.bag[e.out]=i),he(e,i,t,n.contextStore);const f={type:"agentOp",threadId:t.threadId,sessionId:t.request?.session_id||t.request?.sessionId||t.threadId,accountId:t.context.meta.accountId,op:e.op,status:"ok",latencyMs:U(o)};await n.rpc("beacon.send",f)}async function mt(e,t,n,r){const o=await n.toolBridge.invoke(e.name,x(e.input,r));e.out&&(t.bag[e.out]=o),he(e,o,t,n.contextStore)}function yt(e,t,n){const r=e.build(z(t));_t(r,t.productSkusEmitted),n.emit(r)}async function gt(e,t,n,r){const o=String(x(e.on,r)||"default");await F(e.cases[o]||e.cases.default||[],t,n)}async function ht(e,t,n){await Promise.all(e.steps.map(r=>F(r,t,n)))}async function wt(e,t,n,r){n.emit(C(x(e.message,r),!0)),await q(t,n)}async function bt(e,t,n){await q(t,n)}async function q(e,{contextStore:t,emit:n}){e.committed||(e.context=await t.commit(e.threadId)||e.context,e.committed=!0,n(D()))}function he(e,t,n,r){if(typeof e.patch!="function")return;const o=e.patch(n.context,t,z(n));o&&(n.context=r.patch(n.threadId,o)||n.context)}function z(e){return{request:e.request,context:e.context,bag:e.bag,accountConfig:e.accountConfig}}function x(e,t){return typeof e=="function"?e(t):e}function St(e){const t=e?.payload;if(typeof t=="string")return t;if(t&&typeof t=="object"&&"text"in t){const n=t.text;if(typeof n=="string")return n}return typeof e?.action?.payload=="string"?e.action.payload:typeof e?.action?.title=="string"?e.action.title:""}function _t(e,t){const n=e,r=n.spec,o=Array.isArray(r?.items)?r.items:void 0,i=Array.isArray(n.items)?n.items:void 0,a=o||i;if(Array.isArray(a)){for(const s of a)if(s&&typeof s=="object"){const f=s.sku;typeof f=="string"&&t.add(f)}}}function kt(e){return{invoke(t,n){return e("tool.invoke",{name:t,input:n})}}}var At=512,Tt=.74;function we({accountId:e,worker:t,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,tools:s={},beacon:f}){let p=1;const d=new Map;return ze({worker:t,tools:s,beacon:u=>f?.({...u,accountId:u.accountId||e}),memory:sessionStorage}),t.addEventListener("message",u=>{const c=u.data||{},l=typeof c.id=="number"?c.id:null;if(l==null)return;const y=d.get(l);if(y){if(c.type==="event"&&c.event){G(y,c.event);return}if(c.type==="error"){y.onError(new Error(c.message||"Agent worker failed")),d.delete(l);return}c.type==="end"&&d.delete(l)}}),(u,c,l,y)=>{const g=p++;d.set(g,c);const h=()=>{d.delete(g),t.postMessage({id:g,type:"abort"})},E=w=>{if(l.aborted){h();return}t.postMessage({id:g,type:"invoke",accountId:e,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,request:w,parentUrl:window.location.href})};if(l.aborted){h();return}if(l.addEventListener("abort",h,{once:!0}),y){Se(u,y).then(E).catch(w=>{d.delete(g),c.onError(w instanceof Error?w:new Error("Failed to read image attachment"))});return}E(u)}}function be({accountId:e,accountModule:t,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,tools:s={},beacon:f}){let p=null;const d=Et({accountId:e,tools:s,beacon:f}),u=kt(d),c=ue({accountId:e,...r?{devJwtSecret:r}:{},...o?{tokenBrokerUrl:o}:{},...i?{tokenBrokerAudience:i}:{}});return async(l,y,g,h)=>{const E=await Se(l||{},h);p||=new ie({accountId:e,locale:E?.locale||a,parentUrl:window.location.href,rpc:d});try{await dt({request:E,accountModule:{...t,accountId:e},contextStore:p,beClient:{invoke({op:w,input:ee,signal:Fe,cacheTtlS:En,cacheKey:Pn}){return it({beUrl:n,accountId:e,jwtProvider:c,parentUrl:window.location.href,op:w,input:ee,cacheTtlS:En,cacheKey:Pn,...Fe?{signal:Fe}:{}})}},toolBridge:u,emit:w=>G(y,w),rpc:d,signal:g})}catch(w){g?.aborted||(G(y,fe(w)),y.onDone())}}}function Et({accountId:e,tools:t,beacon:n}){const r=o=>n?.({...o,accountId:o.accountId||e});return((o,i)=>te(o,i,{tools:t,beacon:r,memory:sessionStorage}))}async function Se(e,t){if(!t||!t.type?.startsWith("image/"))return e;const n=await jt(t),r={...Pt(e.payload??e.action?.payload),image_data_url:n.dataUrl,image_mime:n.mime};return{...e,payload:r,...e.action?{action:{...e.action,payload:r}}:{}}}function Pt(e){return xt(e)?{...e}:typeof e=="string"?{text:e}:{}}function xt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}async function jt(e){const t=await It(e);return t||{dataUrl:await _e(e),mime:e.type}}async function It(e){if(typeof createImageBitmap!="function"||typeof document>"u")return null;let t=null;try{t=await createImageBitmap(e);const n=Math.min(1,At/Math.max(t.width,t.height)),r=Math.max(1,Math.round(t.width*n)),o=Math.max(1,Math.round(t.height*n)),i=document.createElement("canvas");i.width=r,i.height=o;const a=i.getContext("2d");if(!a)return null;a.drawImage(t,0,0,r,o);const s=await new Promise(f=>i.toBlob(f,"image/jpeg",Tt));return s?{dataUrl:await _e(s),mime:s.type||"image/jpeg"}:null}catch{return null}finally{t?.close()}}async function _e(e){const t=new Uint8Array(await e.arrayBuffer());let n="";const r=32768;for(let o=0;o<t.length;o+=r)n+=String.fromCharCode(...t.subarray(o,o+r));return`data:${e.type};base64,${btoa(n)}`}function G(e,t){switch(t?.type){case"text_chunk":{const n=t;e.onTextChunk(n.content||"",n.final===!0,n);break}case"ui_spec":{const n=t;e.onUISpec(n.spec,n.widget,n.panelHint,n.clearPanel===!0);break}case"action":e.onAction(t);break;case"metadata":e.onMetadata(t);break;case"error":e.onError(vt(t));break;case"done":e.onDone();break;default:break}}function vt(e){const t=new Error(e.message||e.code||"Agent error");return e.code&&(t.code=e.code),t}var ke="__gengageAgentFetchBridge";function Ct({accountId:e,streamTransport:t,endpoints:n={}}){if(!e)throw new Error("accountId is required.");if(typeof t!="function")throw new Error("streamTransport is required.");const r=Mt(),o=`https://gengage-injector.invalid/${encodeURIComponent(e)}`,i=new Set,a=s=>{const f=`${o}/chat/${s}`;i.add(f);const p=n[s],d={streamTransport:t,endpoint:s};p&&(d.endpointHandler=p),r.routes.set(f,d)};a("process_action");for(const s of Object.keys(n))s!=="process_action"&&a(s);return{middlewareUrl:o,stop(){for(const s of i)r.routes.delete(s)}}}function Mt(){const e=window,t=e[ke];if(t)return t;const n=e.fetch.bind(e),r={routes:new Map,originalFetch:n};return e.fetch=(o,i)=>{const a=Ae(o),s=r.routes.get(a);return s?Ut(s,o,i):n(o,i)},e[ke]=r,r}function Ae(e){return typeof e=="string"?e:e instanceof URL?e.href:e?.url||""}function Te(e,t){if(t?.signal)return t.signal;if(typeof Request<"u"&&e instanceof Request)return e.signal}function Ee(e,t){return t?.body!==void 0&&t?.body!==null?t.body:typeof Request<"u"&&e instanceof Request?e.clone().text():null}async function Rt(e,t){const n=Ee(e,t);if(n instanceof FormData){const o=n.get("request"),i=n.get("attachment");return{request:JSON.parse(String(o||"{}")),...i instanceof File?{attachment:i}:{}}}const r=await Promise.resolve(n);return typeof r=="string"?{request:JSON.parse(r||"{}")}:{request:{}}}async function Ut(e,t,n){if(e.endpoint&&e.endpoint!=="process_action"&&e.endpointHandler){const p=new AbortController,d=Te(t,n);let u=null;if(d){const c=()=>p.abort();d.aborted&&c(),d.addEventListener("abort",c,{once:!0}),u=()=>d.removeEventListener("abort",c)}try{const c=await Ot(t,n);return await e.endpointHandler(c,{accountId:Bt(t),endpoint:e.endpoint,signal:p.signal})}finally{u?.()}}const r=new TextEncoder,o=new AbortController,i=Te(t,n);let a=!1,s=null;const f=new ReadableStream({async start(p){const d=l=>{a||p.enqueue(r.encode(`${JSON.stringify(l)}
4
- `))},u=()=>{a||(a=!0,s?.(),p.close())},c=l=>{d({type:"error",code:l?.code||"agent_bridge_error",message:l instanceof Error?l.message:String(l)}),d({type:"done"}),u()};if(i){const l=()=>{o.abort(),a||(a=!0,s?.(),p.error(new DOMException("Aborted","AbortError")))};if(i.aborted){l();return}i.addEventListener("abort",l,{once:!0}),s=()=>i.removeEventListener("abort",l)}try{const{request:l,attachment:y}=await Rt(t,n),g=e.streamTransport(l,{onTextChunk:(h,E,w={})=>d({type:"text_chunk",content:h,final:E===!0,...w}),onUISpec:(h,E,w,ee)=>d({type:"ui_spec",spec:h,widget:E,...w?{panelHint:w}:{},...ee?{clearPanel:!0}:{}}),onAction:h=>{d(h?.type==="action"?h:{type:"action",action:h})},onMetadata:h=>{d(h?.type==="metadata"?h:{type:"metadata",...h})},onError:c,onDone:()=>{d({type:"done"}),u()}},o.signal,y);Nt(g)&&(await g,o.signal.aborted||(d({type:"done"}),u()))}catch(l){o.signal.aborted||c(l)}},cancel(){o.abort(),s?.(),a=!0}});return new Response(f,{status:200,headers:{"Content-Type":"application/x-ndjson"}})}async function Ot(e,t){const n=await Promise.resolve(Ee(e,t));return typeof n!="string"||n.trim()===""?{}:JSON.parse(n)}function Bt(e){try{const[t]=new URL(Ae(e)).pathname.split("/").filter(Boolean);return decodeURIComponent(t||"")}catch{return""}}function Nt(e){return e!==null&&(typeof e=="object"||typeof e=="function")&&typeof e.then=="function"}function $t({accountId:e,beUrl:t,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o,workerUrl:i,defaultLocale:a="en-GB",accountModule:s,tools:f={},beacon:p,allowBlobWorker:d=!1}){if(!e)throw new Error("accountId is required.");if(!t)throw new Error("beUrl is required. The injector owns backend URLs; the SDK has no default.");if(!i)throw new Error("workerUrl is required.");const u=window,c=u.GengageAssistantInjector||(u.GengageAssistantInjector={}),l=c[e]||(c[e]={});if(l.agentController)return l.agentController;const y=J(i)||d?Pe(i,`gengage-${e}-agent`,{allowBlobWorker:d}):null;l.streamTransport=y?we({accountId:e,worker:y.worker,beUrl:t,...n?{devJwtSecret:n}:{},...r?{tokenBrokerUrl:r}:{},...o?{tokenBrokerAudience:o}:{},defaultLocale:a,tools:f,...p?{beacon:p}:{}}):be({accountId:e,accountModule:s,beUrl:t,...n?{devJwtSecret:n}:{},...r?{tokenBrokerUrl:r}:{},...o?{tokenBrokerAudience:o}:{},defaultLocale:a,tools:f,...p?{beacon:p}:{}});const g={type:"agent",stop(){delete l.streamTransport,y?.worker.terminate(),y?.cleanup(),delete l.agentController},diagnostics(){return{accountId:e,beUrl:t,workerUrl:i,mounted:!0,transport:y?"worker":"main-thread",flows:Object.keys(s?.flows||{})}}};return l.agentController=g,g}function J(e){const t=new URL(e,window.location.href);return t.origin===window.location.origin||t.protocol==="blob:"}function Pe(e,t,n={}){const r=new URL(e,window.location.href);if(J(e))return{worker:new Worker(r.href,{type:"module",name:t}),cleanup(){}};if(!n.allowBlobWorker)throw new Error("Cross-origin agent workers require allowBlobWorker=true or a same-origin workerUrl.");const o=new Blob([`import ${JSON.stringify(r.href)};
5
- `],{type:"text/javascript"}),i=URL.createObjectURL(o);try{return{worker:new Worker(i,{type:"module",name:t}),cleanup(){URL.revokeObjectURL(i)}}}catch(a){throw URL.revokeObjectURL(i),a}}function xe(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function O(e){const t=xe(e);if(!t)return null;const n=j(t.sku,t.SKU);if(!n)return null;const r={sku:n,name:j(t.name,t.title,t.short_name,n)||n,url:j(t.url)||""},o=Array.isArray(t.images)?t.images:void 0,i=j(t.imageUrl,t.image_url,t.image,o?.[0]);i&&(r.imageUrl=i),o&&o.length>1&&(r.images=o.filter(g=>!!g).map(String));const a=M(t.price_discounted),s=M(t.price),f=a||s;f>0&&(r.price=String(f));const p=a>0?s:0;p>0&&(r.originalPrice=String(p));const d=j(t.brand);d&&(r.brand=d);const u=M(t.rating);u>0&&(r.rating=u);const c=M(t.review_count)||M(t.reviewCount);c>0&&(r.reviewCount=c);const l=j(t.cart_code,t.cartCode);l&&(r.cartCode=l),typeof t.in_stock=="boolean"&&(r.inStock=t.in_stock),typeof t.inStock=="boolean"&&(r.inStock=t.inStock);const y=t.category_names;return Array.isArray(y)&&(r.categoryNames=y.map(String)),r}function je(e){const t=xe(e);if(!t)return e;const n=t.category_names,r=Array.isArray(n)?n:void 0,o=t.images,i=Array.isArray(o)?o:void 0,a={sku:t.sku,name:t.name||t.title,url:t.url,price:t.price,currency:t.price_currency||t.currency,category:r?.[r.length-1]??void 0,category_names:r?r.slice(0,4):void 0,image:i?i[0]:t.image,in_stock:t.in_stock,rating:t.rating,review_count:t.review_count};for(const s of Object.keys(a))a[s]===void 0&&delete a[s];return a}function H(e){return Array.isArray(e)?e.map(je).filter(t=>!!t):[]}function j(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function M(e){const t=Number(e);return Number.isFinite(t)?t:0}function Ie(e){return Array.isArray(e)?e.map(String).filter(Boolean):typeof e=="string"&&e?[e]:[]}function ve(e=[]){const t={},n=[];return(Array.isArray(e)?e.map(O).filter(r=>!!r):[]).forEach((r,o)=>{const i=`product-${o.toString()}`;n.push(i);const a={sku:r.sku,product:r};t[i]={type:"ProductCard",props:{product:r,index:o,action:{title:r.name,type:"launchSingleProduct",payload:a}}}}),t.root={type:"ProductGrid",props:{layout:"grid"},children:n},{widget:"chat",panelHint:"panel",spec:{root:"root",elements:t}}}function Lt(e){return{widget:"chat",panelHint:"panel",spec:{root:"root",elements:{root:{type:"ProductDetailsPanel",props:{product:O(e)||e||{}}}}}}}function Dt(e={}){const t=(e.multiple_product_details||e.products||[]).map(O).filter(r=>!!r),n=e.table||{};return{widget:"chat",panelHint:"panel",spec:{root:"root",elements:{root:{type:"ComparisonTable",props:{products:t,recommended:t.find(r=>r.sku===e.recommended_choice_sku)||t[0],attributes:Object.entries(n).map(([r,o])=>({label:r,values:Array.isArray(o)?o.map(String):[String(o??"")]})),highlights:Ie(e.key_differences),specialCases:Ie(e.special_considerations),recommendedText:e.recommended_choice,productActions:Object.fromEntries(t.map(r=>[r.sku,{title:r.name,type:"launchSingleProduct",payload:{sku:r.sku,product:r}}]))}}}}}}function Ft(e=[]){return{widget:"chat",panelHint:"inline",spec:{root:"root",elements:{root:{type:"ActionButtons",props:{buttons:(Array.isArray(e)?e:[]).map(t=>{const n=t.label||t.title||t.shortName||"",r=t.action||t.requestDetails||t.request_details;return!n||!r?.type?null:{label:n,action:{title:n,type:r.type,...r.payload!==void 0?{payload:r.payload}:{}}}}).filter(t=>!!t)}}}}}}function B(e){const t=e?.payload;if(typeof t=="string")return t;if(t&&typeof t=="object"&&"text"in t){const r=t.text;if(typeof r=="string")return r}const n=e?.action;return n&&typeof n.payload=="string"?n.payload:n&&typeof n.title=="string"?n.title:""}function Ce(e){return Object.freeze([...e])}function P(e){return e&&typeof e=="object"?e:{}}function K(e){return e&&typeof e=="object"?e:{}}function Me(e){return e.thread.extensions.beauty_profile}var qt=Ce([{kind:"be_op",op:"beauty-consulting-turn",input:({request:e,context:t})=>({utterance:B(e),prior_messages:t.messages.slice(-10),profile:Me(t),candidate_products:Gt(e),locale:t.meta.locale}),out:"consultation",patch:Re},{kind:"branch",on:({bag:e})=>P(e.consultation).consultation_state?.stage||"answer",cases:{refuse:[{kind:"refusal",message:({bag:e})=>{const t=P(e.consultation);return t.refusal?.message||t.plain_text||"I cannot help with that request."}}],needs_more_info:[{kind:"emit",build:({bag:e})=>C(V(P(e.consultation)),!0)},{kind:"commit"}],search:[{kind:"tool",name:"search",input:({request:e,bag:t,context:n})=>{const r=P(t.consultation);return{query:r.search_params?.query||B(e),facets:r.search_params?.facets||{},limit:12,locale:n.meta.locale}},out:"products",patch:(e,t)=>{const n=K(t);return{panel:{...e.panel,screen_sku_list:W(n).map(r=>zt(r)).filter(r=>!!r),last_search:{query:n.query||""}}}}},{kind:"emit",build:({bag:e})=>me(ve(W(K(e.products))))},{kind:"be_op",op:"beauty-consulting-turn",input:({request:e,context:t,bag:n})=>({utterance:B(e),prior_messages:t.messages.slice(-10),profile:Me(t),candidate_products:H(W(K(n.products)).slice(0,12)),locale:t.meta.locale}),out:"answer",patch:(e,t)=>{const n=Re(e,t),r=(P(t).product_mentions||[]).map(o=>o.sku).filter(o=>!!o);return{...n||{},panel:{...e.panel,chat_mentioned_skus:r}}}},{kind:"emit",build:({bag:e})=>{const t=P(e.answer);return C(V(t),!0,{productMentions:t.product_mentions||[]})}},{kind:"commit"}],default:[{kind:"emit",build:({bag:e})=>{const t=P(e.consultation);return C(V(t),!0,{productMentions:t.product_mentions||[]})}},{kind:"commit"}]}}]);function Re(e,t){const n=P(t).consultation_state?.captured_profile;if(!n)return null;const r=e.thread.extensions.beauty_profile&&typeof e.thread.extensions.beauty_profile=="object"?e.thread.extensions.beauty_profile:{};return{thread:{...e.thread,extensions:{...e.thread.extensions,beauty_profile:{...r,...n}}}}}function W(e){return Array.isArray(e?.products)?e.products:[]}function zt(e){if(e&&typeof e=="object"&&"sku"in e){const t=e.sku;if(typeof t=="string")return t}}function Gt(e){const t=e?.payload&&typeof e.payload=="object"?e.payload.products:void 0,n=e?.action?.payload&&typeof e.action.payload=="object"?e.action.payload.products:void 0,r=t||n;return Array.isArray(r)?H(r.slice(0,12)):void 0}function V(e){return e?.answer_html||e?.plain_text||e?.refusal?.message||"I can help with beauty shopping."}var Ue=new Set(["and","are","box","for","from","gift","gifts","the","with"]),Jt={token:.26,keyword:.22,category:.18,facet:.16,color:.08,attribute:.06,price:.08,retrieval:.08},Ht=["amber","beige","black","blue","blush","bronze","brown","cream","gold","green","grey","ivory","lilac","mixed","orange","pastel","pink","purple","red","silver","white","yellow"];function A(e){return String(e??"").normalize("NFKD").replace(new RegExp("\\p{Diacritic}","gu"),"").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function _(e,t=Ue){const n=t instanceof Set?t:new Set([...Ue,...t]),r=new Set,o=[];for(const i of A(e).split(/\s+/u))i.length<3||n.has(i)||r.has(i)||(r.add(i),o.push(i));return o}function R(e,t={}){if(Qt(e))return e;const n=t.facetKeys,r=b(e.category_names??e.category),o=b(e.category_ids),i=Yt(e.facet_hits),a=Object.entries(i).filter(([g])=>!n||n.some(h=>A(h)===A(g))).map(([,g])=>g),s=k(e.name,e.title),f=k(e.brand),p=t.sourceKeywords??[],d=[s,f,...r,...a,...b(e.promotions),k(e.description),...p].join(" "),u=_(d,t.stopWords),c=k(t.sourceProductType,en(r,s,u),u[0]),l=T([...Zt(d,Ht),...Object.entries(i).filter(([g])=>/colou?r/iu.test(g)).flatMap(([,g])=>_(g,t.stopWords))]),y=T([...a.flatMap(g=>_(g,t.stopWords)),...b(e.promotions).flatMap(g=>_(g,t.stopWords))]).slice(0,24);return{sku:k(e.sku),title:s,brand:f,productType:c,categoryNames:r,categoryIds:o,facets:i,keywords:T([...p.flatMap(g=>_(g,t.stopWords)),...u]).slice(0,12),tokens:u,colors:l,attributes:y,price:Xt(e)}}function Kt(e,t={}){const n=k(e.product_type,e.productType),r=k(e.title,n,b(e.keywords).join(" ")),o=T([...b(e.keywords),...b(e.colors),...b(e.materials),...b(e.styles),...b(e.attributes)]);return R({sku:"__photo__",name:r,category_names:n?[n]:[],facet_hits:{colors:b(e.colors).join(", "),materials:b(e.materials).join(", "),styles:b(e.styles).join(", "),attributes:b(e.attributes).join(", ")},promotions:o},{...t,sourceProductType:n,sourceKeywords:o})}function Wt(e,t={}){const n=R(e,t);return T([...t.sourceQueries??[],N([n.productType,...n.colors.slice(0,1),...n.attributes.slice(0,2)]),N([n.productType,...n.keywords.slice(0,3)]),N([n.categoryNames[n.categoryNames.length-1],...n.keywords.slice(0,2)]),N(n.title.split(/\s+/u).slice(0,6)),n.productType].map(r=>r.trim()).filter(Boolean)).slice(0,t.queryLimit??6)}function Oe(e,t,n={}){const r={...Jt,...n.weights},o=R(t,n),i=[],a=I(e.tokens,o.tokens),s=I(e.keywords,o.tokens),f=tn(e.categoryNames,o.categoryNames)||I(Be(e.categoryNames),Be(o.categoryNames)),p=I(e.attributes,o.attributes),d=I(e.colors,o.colors),u=I(e.attributes,o.tokens),c=nn(e.price,o.price),l=rn(o.sku,n.hitCounts)>0?1:0,y=on(e,o),g=a*r.token+s*r.keyword+f*r.category+p*r.facet+d*r.color+u*r.attribute+c*r.price+l*r.retrieval,h=an(y?g:g*.35);return y&&e.productType&&e.productType===o.productType&&i.push("same product type"),f>.4&&i.push("similar category"),p>.2&&i.push("matching product attributes"),d>0&&i.push("matching colour"),c>.8&&i.push("similar price"),y||i.push("weaker product-type match"),{score:Number(h.toFixed(4)),reasons:i}}function Vt(e,t,n={}){const r=R(e,n),o=new Set([r.sku,...n.ignoreSkus??[]].filter(Boolean));return t.filter(i=>{const a=k(i.sku);return a&&!o.has(a)}).map(i=>{const a=Oe(r,i,n);return{...i,similarity_score:a.score,similarity_reasons:a.reasons}}).sort((i,a)=>a.similarity_score-i.similarity_score).slice(0,Math.max(1,Math.min(n.limit??12,100)))}function Qt(e){return!!(e&&typeof e=="object"&&Array.isArray(e.tokens))}function k(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function b(e){return Array.isArray(e)?e.map(t=>k(t)).filter(Boolean):typeof e=="string"&&e.trim()?e.split(/[,;/|]+/u).map(t=>t.trim()).filter(Boolean):[]}function Yt(e){return!e||typeof e!="object"||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).map(([t,n])=>[t,k(n)]).filter(([,t])=>t))}function Xt(e){const t=Number(e.price_discounted);if(Number.isFinite(t)&&t>0)return t;const n=Number(e.price);return Number.isFinite(n)&&n>0?n:0}function T(e){const t=new Set,n=[];for(const r of e){const o=A(r);!o||t.has(o)||(t.add(o),n.push(o))}return n}function Zt(e,t){const n=` ${A(e)} `;return t.filter(r=>n.includes(` ${A(r)} `))}function en(e,t,n){const r=A(e[e.length-1]??e[0]??"");if(r){const o=_(r),i=new Set(_(t));return o.find(a=>i.has(a))??o[0]??r}return n[0]??""}function N(e){return e.map(t=>A(t)).filter(Boolean).join(" ").replace(/\s+/gu," ").trim().slice(0,120)}function Be(e){return e.flatMap(t=>_(t))}function I(e,t){const n=T(e),r=new Set(T(t));return n.length===0||r.size===0?0:n.filter(o=>r.has(o)).length/n.length}function tn(e,t){const n=T(e),r=new Set(T(t));return n.length===0||r.size===0?0:n.filter(o=>r.has(o)).length/n.length}function nn(e,t){return e<=0||t<=0?0:Math.min(e,t)/Math.max(e,t)}function rn(e,t){return!e||!t?0:typeof t.get=="function"?t.get(e)??0:t[e]??0}function on(e,t){if(!e.productType||!t.productType||e.productType===t.productType)return!0;const n=new Set(_(e.productType)),r=new Set([..._(t.productType),...t.tokens]);return[...n].some(o=>r.has(o))}function an(e){return Math.max(0,Math.min(1,e))}function sn(e){const t=(e?.chat||e?._chat)?.root||e?._chat?.root;return t?t.getRootNode?.()?.host||t:Array.from(document.querySelectorAll("*")).find(n=>n.shadowRoot?.querySelector?.(".gengage-chat-root, .gengage-chat-launcher-container"))}function cn(e,t){const n=sn(e);n?.style&&(t?n.style.removeProperty("display"):n.style.setProperty("display","none","important")),t||(e?.chat||e?._chat)?.close?.()}var un="nd_be_url";function ln(e,t){const n=dn()||e.beUrl||t;if(!n)throw new Error("resolveBeUrl: backend URL is required. The injector must supply a fallback URL; the SDK has no default.");return n}function dn(){try{const e=new URLSearchParams(window.location.search).get(un)?.trim();if(!e)return null;const t=new URL(e);return t.protocol!=="https:"&&t.protocol!=="http:"?null:t.toString().replace(/\/+$/u,"")}catch{return null}}var fn="entries",pn=1,mn={volatile:"Hot per-page state and sensitive request context.",session:"Current-visit tool context without raw tokens or PII-heavy payloads.",local:"Small, non-sensitive capability facts or user preferences.",indexedDb:"Larger product/search payload caches with short TTLs."},Ne=new Map;function Q(){return Date.now()}function Y(e){return e?.expiresAt!=null&&e.expiresAt<=Q()}function X(e,t){return{value:e,createdAt:Q(),expiresAt:t?Q()+t:null}}function yn(e,t,n){try{const r=e.getItem(`${t}${n}`);if(!r)return null;const o=JSON.parse(r);return Y(o)?(e.removeItem(`${t}${n}`),null):o.value}catch{return null}}function gn(e,t,n,r,o){try{return e.setItem(`${t}${n}`,JSON.stringify(X(r,o))),!0}catch{return!1}}function hn(e,t,n){try{e.removeItem(`${t}${n}`)}catch{}}function $e(e){try{return window[e]}catch{return null}}function Le(e,t){return e?{get:n=>yn(e,t,n),set:(n,r,o={})=>gn(e,t,n,r,o.ttlMs),remove:n=>hn(e,t,n)}:{get:()=>null,set:()=>!1,remove:()=>{}}}function Z(e){if(Array.isArray(e))return`[${e.map(Z).join(",")}]`;if(e&&typeof e=="object"){const t=e;return`{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${Z(t[n])}`).join(",")}}`}return JSON.stringify(e)}function De(e){let t=2166136261;const n=Z(e);for(let r=0;r<n.length;r+=1)t^=n.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0).toString(36)}function wn(e,t){const n=t.dbName||`gengage-${e}`,r=t.dbStore||fn,o=t.dbVersion||pn,i=new Map;let a=null;const s=()=>"indexedDB"in window?a||(a=new Promise(u=>{const c=indexedDB.open(n,o);c.onupgradeneeded=()=>{c.result.createObjectStore(r,{keyPath:"key"})},c.onsuccess=()=>u(c.result),c.onerror=()=>u(null),c.onblocked=()=>u(null)}),a):Promise.resolve(null);return{volatileEntries:i,idbGet:async u=>{const c=await s();return c?new Promise(l=>{const y=c.transaction(r,"readwrite").objectStore(r),g=y.get(u);g.onsuccess=()=>{const h=g.result;if(!h||Y(h)){h&&y.delete(u),l(null);return}l(h.value)},g.onerror=()=>l(null)}):null},idbSet:async(u,c,l={})=>{const y=await s();return y?new Promise(g=>{const h=y.transaction(r,"readwrite");h.oncomplete=()=>g(!0),h.onerror=()=>g(!1),h.objectStore(r).put({key:u,...X(c,l.ttlMs)})}):!1},idbRemove:async u=>{const c=await s();c&&c.transaction(r,"readwrite").objectStore(r).delete(u)}}}function bn(e,t={}){const n=window,r=n.gengage||(n.gengage={}),o=r.memory||(r.memory={}),i=o[e];if(i)return i;const a=Ne.get(e)||wn(e,t);Ne.set(e,a);const s=t.sessionPrefix||`gengage:${e}:session:`,f=t.localPrefix||`gengage:${e}:local:`,d={get:l=>{const y=a.volatileEntries.get(l);return y?Y(y)?(a.volatileEntries.delete(l),null):y.value:null},set:(l,y,g={})=>(a.volatileEntries.set(l,X(y,g.ttlMs)),!0),remove:l=>{a.volatileEntries.delete(l)},clear:()=>a.volatileEntries.clear()},u={get:a.idbGet,set:a.idbSet,remove:a.idbRemove},c={accountId:e,volatile:d,session:Le($e("sessionStorage"),s),local:Le($e("localStorage"),f),indexedDb:u,stableKey:De,policy:{...mn,...t.policy||{}}};o[e]=c;for(const l of t.aliases||[])o[l]=c;return c}var Sn=["addToCart","search","searchKeyword","facetedSearch","searchGiftOptions","similaritySearch"];function _n(e,t,n={}){const r=window,o=r.gengage||(r.gengage={}),i=o.tools||(o.tools={});i[e]=t;for(const a of n.accountAliases||[])i[a]=t;if(n.exposeStandardAliases!==!1)for(const a of n.standardAliases||Sn){const s=t[a];typeof s=="function"&&(i[a]=i[a]||s)}return t}function kn({getPageType:e,getProduct:t}){return()=>({url:window.location.href,title:document.title,pageType:e(),product:t()})}function An({accountId:e,getPageType:t,getProduct:n,getToolNames:r,getSearchCapabilities:o,getMemory:i}){return async()=>({accountId:e,url:window.location.href,pageType:t(),productSku:n()?.sku??null,toolNames:r(),...o?{searchCapabilities:o()}:{},...i?{memoryPolicy:i().policy}:{},timestamp:new Date().toISOString()})}function Tn({accountId:e,runtimeFile:t="runtime.js",startExport:n="start",globalBaseUrlKey:r,errorLabel:o}={}){if(!e)throw new Error("accountId is required.");const i=o||e,a=window,s=()=>{const u=a.GengageInjectorConfig||{},c=u[e]||{};return{...u,...c}},f=()=>{const u=s();if(u.runtimeUrl)return u.runtimeUrl;const c=u.assetBaseUrl||u.baseUrl||document.currentScript?.getAttribute("src")||(r?a[r]:null);if(!c)throw new Error(`${i} runtime URL cannot be resolved.`);return new URL(t,c).href},p=a.GengageAssistantInjector||(a.GengageAssistantInjector={}),d=p[e]||(p[e]={});return d.loaderPromise||(d.loaderPromise=import(f()).then(u=>{const c=u[n];if(typeof c!="function")throw new Error(`${i} runtime export ${n} is unavailable.`);return c()}).catch(u=>{throw delete d.loaderPromise,console.error(`[Gengage][${e}] runtime load failed`,u),u})),d.loaderPromise}m.AgentError=$,m.ContextStore=ie,m.action=lt,m.actionButtonsUiSpec=Ft,m.beErrorToAgentError=L,m.beautyConsultingTurnFlow=qt,m.buildPhotoSimilarityProfile=Kt,m.buildProductSimilarityProfile=R,m.buildSimilarityQueries=Wt,m.canUseModuleWorker=J,m.caughtToStreamError=fe,m.comparisonUiSpec=Dt,m.createBrowserMemory=bn,m.createDiagnosticsTool=An,m.createFlow=Ce,m.createInjectorAdapter=we,m.createMainThreadInjectorAdapter=be,m.createModuleWorker=Pe,m.createReadPageTool=kn,m.done=D,m.elapsedMs=U,m.error=ye,m.httpErrorToAgentError=de,m.installBrowserTools=_n,m.installFetchTransportBridge=Ct,m.metadata=ut,m.mountAccount=$t,m.normalizeProduct=O,m.normalizeSimilarityText=A,m.nowIso=ne,m.productDetailsUiSpec=Lt,m.productsUiSpec=ve,m.rankSimilarProducts=Vt,m.requestText=B,m.resolveBeUrl=ln,m.resolveFlow=ge,m.scoreSimilarityCandidate=Oe,m.setAssistantHostVisible=cn,m.stableKey=De,m.startLazyRuntimeLoader=Tn,m.textChunk=C,m.tokenizeSimilarityText=_,m.trimProductFactsCore=je,m.trimProductFactsListCore=H,m.uiSpec=me})(this.Gengage=this.Gengage||{});
1
+ (function(m){Object.defineProperty(m,Symbol.toStringTag,{value:"Module"});function qt(t){return!!t&&typeof t=="object"&&t.type==="rpc.req"}function zt({worker:t,tools:e={},beacon:n,memory:r=sessionStorage}){t.addEventListener("message",o=>{const i=o.data;qt(i)&&Gt(t,i,{tools:e,beacon:n,memory:r})})}async function Gt(t,e,n){try{const r=await nt(e.method,e.payload,n);t.postMessage({type:"rpc.result",rpcId:e.rpcId,ok:!0,value:r})}catch(r){t.postMessage({type:"rpc.result",rpcId:e.rpcId,ok:!1,error:{message:r instanceof Error?r.message:String(r)}})}}function Jt(t){if(t&&typeof t=="object"&&typeof t.name=="string")return t;throw new Error("tool.invoke requires { name, input }")}function Ht(t){if(t&&typeof t=="object"&&t.key!==void 0)return t;throw new Error("memory.get requires { key }")}function Wt(t){if(t&&typeof t=="object"&&t.key!==void 0)return t;throw new Error("memory.set requires { key }")}async function nt(t,e,{tools:n,beacon:r,memory:o}){if(t==="tool.invoke"){const{name:i,input:a}=Jt(e),s=n[i];if(typeof s!="function")throw new Error(`Unknown tool: ${i}`);return s(a)}if(t==="beacon.send")return r?.(e),{sent:!0};if(t==="memory.get"){const{key:i}=Ht(e),a=o.getItem(String(i));return a?JSON.parse(a):null}if(t==="memory.set"){const{key:i,value:a}=Wt(e);return o.setItem(String(i),JSON.stringify(a??null)),{ok:!0}}throw new Error(`Unknown RPC method: ${t}`)}function rt(){return new Date().toISOString()}function U(t){return Math.max(0,Math.round(performance.now()-t))}function v(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Kt(t){const{accountId:e,locale:n="en-GB",parentUrl:r="",threadId:o,incomingContext:i}=t,a=v(i)?i:{},s=v(a.thread)?a.thread:{},f=v(a.panel)?a.panel:{},p=v(a.meta)?a.meta:{},d=ot(a.messages),u={id:String(o||s.id||self.crypto.randomUUID()),started_at:String(s.started_at||rt()),extensions:v(s.extensions)?{...s.extensions}:{}},c=String(p.locale||n),l=String(p.parentUrl||r||typeof self<"u"&&self.location?.href||"");return{panel:{...f},messages:d,thread:u,meta:{locale:c,parentUrl:l,accountId:e}}}function Vt(t,e){const n=ot([e])[0];return n?{...t,messages:[...t.messages,n].slice(-50)}:t}function ot(t){return Array.isArray(t)?t.map(e=>{const n=e?.role;return{role:n==="model"?"assistant":typeof n=="string"?n:"",content:String(e?.content||"")}}).filter(e=>(e.role==="user"||e.role==="assistant")&&!!e.content).slice(-50):[]}var Qt="gengage:agent:context:";async function Yt({accountId:t,threadId:e,rpc:n}){const r=await n("memory.get",{tier:"session",key:it(t,e)});return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}async function Xt({accountId:t,threadId:e,extensions:n,rpc:r}){await r("memory.set",{tier:"session",key:it(t,e),value:{thread:{extensions:n}}})}function it(t,e){return`${Qt}${t}:${e}`}function S(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}var at=class{#t=new Map;#e;#r;#o;#n;constructor({accountId:t,locale:e,parentUrl:n,rpc:r}){this.#e=t,this.#r=e,this.#o=n,this.#n=r}async load(t){const e=t?.meta?.threadId||t?.session_id||t?.sessionId,n=String(e||"default"),r=this.#t.get(n);if(r)return r;const o=await Yt({accountId:this.#e,threadId:n,rpc:this.#n}),i=Kt({accountId:this.#e,locale:t?.locale||this.#r,parentUrl:this.#o,threadId:n,incomingContext:Zt(o,t?.context)});return this.#t.set(n,i),i}patch(t,e){const n=String(t||"default"),r=this.#t.get(n);if(!r)return null;const o=st(r,typeof e=="function"?e(r):e);return this.#t.set(n,o),o}appendUserMessage(t,e){const n=String(t||"default");if(!e)return this.#t.get(n)??null;const r=this.#t.get(n);if(!r)return null;const o=Vt(r,{role:"user",content:e});return this.#t.set(n,o),o}async commit(t){const e=String(t||"default"),n=this.#t.get(e);return n?(await Xt({accountId:this.#e,threadId:e,extensions:n.thread.extensions,rpc:this.#n}),n):null}};function Zt(t,e){return!S(t)&&!S(e)?{}:st(S(t)?t:{},S(e)?e:{})}function st(t,e){if(!S(e))return t;const n=t,r=e,o=S(n.panel)?n.panel:{},i=S(r.panel)?r.panel:{},a=S(n.thread)?n.thread:{},s=S(r.thread)?r.thread:{},f=S(a.extensions)?a.extensions:{},p=S(s.extensions)?s.extensions:{},d=S(n.meta)?n.meta:{},u=S(r.meta)?r.meta:{};return{...t,...e,panel:{...o,...i},thread:{...a,...s,extensions:{...f,...p}},meta:{...d,...u},messages:Array.isArray(r.messages)?r.messages.slice(-50):t.messages??[]}}function ct(t){const e=String.fromCharCode(...t);return btoa(e).replace(/\+/gu,"-").replace(/\//gu,"_").replace(/=+$/u,"")}function ut(t){return ct(new TextEncoder().encode(JSON.stringify(t)))}async function te({accountId:t,devJwtSecret:e,ttlS:n=300}){if(!e)throw new Error("devJwtSecret is required for local agent mode.");const r=Math.floor(Date.now()/1e3),o=`${ut({alg:"HS256",typ:"JWT"})}.${ut({sub:t,iat:r,exp:r+n,scope:"invoke",jti:crypto.randomUUID?.()||`${r}-${Math.random()}`})}`,i=await crypto.subtle.importKey("raw",new TextEncoder().encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await crypto.subtle.sign("HMAC",i,new TextEncoder().encode(o));return`${o}.${ct(new Uint8Array(a))}`}function lt({accountId:t,devJwtSecret:e,tokenBrokerUrl:n,tokenBrokerAudience:r,refreshSkewS:o=30,fetchImpl:i=fetch}){let a=null;return async({signal:s,parentUrl:f}={})=>{if(e)return te({accountId:t,devJwtSecret:e});if(!n)throw new Error("tokenBrokerUrl is required for production agent mode.");const p=Math.floor(Date.now()/1e3);return a?.token&&a.expiresAtS-o>p||(a=await ee({accountId:t,tokenBrokerUrl:n,tokenBrokerAudience:r,parentUrl:f,signal:s,fetchImpl:i})),a.token}}async function ee({accountId:t,tokenBrokerUrl:e,tokenBrokerAudience:n,parentUrl:r,signal:o,fetchImpl:i}){const a=await i(e,{method:"POST",credentials:"include",headers:{accept:"application/json","content-type":"application/json"},body:JSON.stringify({accountId:t,scope:"invoke",audience:n||void 0,parentUrl:r||void 0}),...o?{signal:o}:{}});if(!a.ok)throw new Error(`Token broker request failed (${a.status}).`);const s=await a.json(),f=s?.token||s?.jwt||s?.access_token;if(!f||typeof f!="string")throw new Error("Token broker response did not include a JWT.");return{token:f,expiresAtS:ne(s)||re(f)||Math.floor(Date.now()/1e3)+300}}function ne(t){const e=t?.expiresAtS??t?.expires_at_s??t?.expiresInS??t?.expires_in_s;if(Number.isFinite(e))return Number(e);const n=t?.expiresIn??t?.expires_in;if(Number.isFinite(n))return Math.floor(Date.now()/1e3)+Number(n);const r=t?.expiresAt??t?.expires_at;if(typeof r=="string"){const o=Date.parse(r);if(Number.isFinite(o))return Math.floor(o/1e3)}return null}function re(t){try{const[,e]=t.split(".");if(!e)return null;const n=e.replace(/-/gu,"+").replace(/_/gu,"/"),r=atob(n.padEnd(Math.ceil(n.length/4)*4,"=")),o=JSON.parse(r);return Number.isFinite(o?.exp)?Number(o.exp):null}catch{return null}}var dt={unauthorized:{code:"auth",message:"Assistant authentication failed. Please retry."},forbidden:{code:"auth",message:"Assistant authentication failed. Please retry."},unknown_op:{code:"op_unavailable",message:"This assistant action is not available yet."},invalid_input:{code:"invalid_request",message:"The assistant request was not valid."},account_config:{code:"account_config",message:"Assistant configuration is unavailable."},upstream_llm:{code:"op_failed",message:"The assistant could not complete that request."},upstream_timeout:{code:"op_timeout",message:"The assistant took too long to respond."},schema_mismatch:{code:"op_failed",message:"The assistant could not complete that request."},rate_limited:{code:"rate_limited",message:"The assistant is receiving too many requests. Please retry shortly."},internal:{code:"op_failed",message:"The assistant could not complete that request."},payload_too_large:{code:"invalid_request",message:"The assistant request was too large."}},$=class extends Error{constructor(t,e,n={}){super(e),this.name="AgentError",this.code=t,this.source=n.source||"agent",n.sourceCode&&(this.sourceCode=n.sourceCode),n.detail!==void 0&&(this.detail=n.detail)}};function L(t){const e=String(t?.code||"upstream_llm"),n=dt[e]||dt.upstream_llm;return new $(n.code,n.message,{source:"be",sourceCode:e,detail:t?.detail})}function ft(t,e){const n=e?.error&&typeof e.error=="object"?e.error:{};return L({code:String(n.code||oe(t)),detail:n.detail})}function pt(t){return t instanceof $?{type:"error",code:t.code,message:t.message}:{type:"error",code:"agent_invoke_failed",message:"The assistant could not complete that request."}}function oe(t){return t===401?"unauthorized":t===403?"forbidden":t===413?"payload_too_large":t===429?"rate_limited":"internal"}async function ie({beUrl:t,accountId:e,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o,jwtProvider:i,parentUrl:a,op:s,input:f,cacheTtlS:p,cacheKey:d,signal:u}){const c=await(i||lt({accountId:e,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o}))({...u?{signal:u}:{},...a?{parentUrl:a}:{}}),{opDomain:l,opName:y}=ae(s,e),g={method:"POST",headers:{authorization:`Bearer ${c}`,"content-type":"application/json",accept:"application/x-ndjson"},body:JSON.stringify({op_domain:l,op_name:y,op_payload:f,...p!==void 0?{cache_ttl_s:p}:{},...d!==void 0?{cache_key:d}:{}}),...u?{signal:u}:{}},h=await fetch(`${String(t).replace(/\/+$/u,"")}/v1/execute`,g);if(!h.ok)throw ft(h.status,await ce(h));return ue(h)}function ae(t,e){if(!t||t.startsWith("-")||t.endsWith("-"))throw new Error(`Invalid BE op name: ${t}`);return{opDomain:se(e),opName:t}}function se(t){return t.replace(/-agentic$/u,"")}async function ce(t){try{return await t.json()}catch{return{error:{code:t.statusText||"internal"}}}}async function ue(t){const e=t.body?.getReader();if(!e)throw new Error("BE response body is not readable.");const n=new TextDecoder;let r="";const o={};for(;;){const{value:a,done:s}=await e.read();if(s)break;r+=n.decode(a,{stream:!0});let f=r.indexOf(`
2
+ `);for(;f>=0;){const p=r.slice(0,f).trim();r=r.slice(f+1),p&&mt(JSON.parse(p),o),f=r.indexOf(`
3
+ `)}}const i=r.trim();return i&&mt(JSON.parse(i),o),o}function mt(t,e){if(t._error)throw L(t._error);t._end||Object.assign(e,t)}function le(t={}){return{type:"metadata",...t}}function C(t,e=!1,n={}){return{type:"text_chunk",content:t,final:e,...n}}function yt(t){return{type:"ui_spec",...t}}function de(t){return{type:"action",action:t}}function gt(t,e){return{type:"error",code:t,message:e}}function D(){return{type:"done"}}function ht(t,e){return t[e?.type||e?.action?.type||"inputText"]||t.inputText}async function fe({request:t,accountModule:e,contextStore:n,beClient:r,toolBridge:o,emit:i,rpc:a,signal:s}){const f=performance.now(),p=await n.load(t),d=p.thread.id,u=_e(t);n.appendUserMessage(d,u);const c=ht(e.flows,t);if(!c)return i(gt("unknown_action",`No agent flow for request type ${t?.type||"inputText"}`)),i(D()),{steps:0,productSkusEmitted:[]};const l={request:t,context:n.patch(d,{})||p,bag:{},accountConfig:e.accountConfig||{},threadId:d,steps:0,productSkusEmitted:new Set,committed:!1},y={contextStore:n,beClient:r,toolBridge:o,emit:i,rpc:a,adapters:e.adapters||{},...s?{signal:s}:{}};return await F(c,l,y),l.committed||await q(l,y),await a("beacon.send",{type:"turnSummary",threadId:d,sessionId:t?.session_id||t?.sessionId||d,accountId:e.accountId||l.context.meta.accountId,steps:l.steps,totalLatencyMs:U(f),productSkusEmitted:[...l.productSkusEmitted]}),{steps:l.steps,productSkusEmitted:[...l.productSkusEmitted]}}async function F(t,e,n){for(const r of t){if(n.signal?.aborted)return;e.steps+=1,await pe(r,e,n),e.context=n.contextStore.patch(e.threadId,{})||e.context}}async function pe(t,e,n){const r=G(e);if(t.kind==="be_op"){await me(t,e,n,r);return}if(t.kind==="tool"){await ye(t,e,n,r);return}if(t.kind==="adapter"){await ge(t,e,n,r);return}if(t.kind==="emit"){he(t,e,n);return}if(t.kind==="branch"){await we(t,e,n,r);return}if(t.kind==="parallel"){await be(t,e,n);return}if(t.kind==="refusal"){await Se(t,e,n,r);return}t.kind==="commit"&&await ke(t,e,n)}async function me(t,e,n,r){const o=performance.now();let i;const a=j(t.cacheTtlS,r),s=j(t.cacheKey,r);try{i=await n.beClient.invoke({op:t.op,input:j(t.input,r),...a!==void 0?{cacheTtlS:a}:{},...s!==void 0?{cacheKey:s}:{},...n.signal?{signal:n.signal}:{}})}catch(p){const d=p,u=String(d?.sourceCode||d?.code||"unknown"),c={type:"agentOp",threadId:e.threadId,sessionId:e.request?.session_id||e.request?.sessionId||e.threadId,accountId:e.context.meta.accountId,op:t.op,status:"error",latencyMs:U(o),errorCode:u};throw await n.rpc("beacon.send",c),p}t.out&&(e.bag[t.out]=i),z(t,i,e,n.contextStore);const f={type:"agentOp",threadId:e.threadId,sessionId:e.request?.session_id||e.request?.sessionId||e.threadId,accountId:e.context.meta.accountId,op:t.op,status:"ok",latencyMs:U(o)};await n.rpc("beacon.send",f)}async function ye(t,e,n,r){const o=await n.toolBridge.invoke(t.name,j(t.input,r));t.out&&(e.bag[t.out]=o),z(t,o,e,n.contextStore)}async function ge(t,e,n,r){const o=n.adapters?.[t.name];if(typeof o!="function")throw new Error(`Unknown flow adapter: ${t.name}`);const i=await o(j(t.input,r),r);t.out&&(e.bag[t.out]=i),z(t,i,e,n.contextStore)}function he(t,e,n){const r=t.build(G(e));Ae(r,e.productSkusEmitted),n.emit(r)}async function we(t,e,n,r){const o=String(j(t.on,r)||"default");await F(t.cases[o]||t.cases.default||[],e,n)}async function be(t,e,n){await Promise.all(t.steps.map(r=>F(r,e,n)))}async function Se(t,e,n,r){n.emit(C(j(t.message,r),!0)),await q(e,n)}async function ke(t,e,n){await q(e,n)}async function q(t,{contextStore:e,emit:n}){t.committed||(t.context=await e.commit(t.threadId)||t.context,t.committed=!0,n(D()))}function z(t,e,n,r){if(typeof t.patch!="function")return;const o=t.patch(n.context,e,G(n));o&&(n.context=r.patch(n.threadId,o)||n.context)}function G(t){return{request:t.request,context:t.context,bag:t.bag,accountConfig:t.accountConfig}}function j(t,e){return typeof t=="function"?t(e):t}function _e(t){const e=t?.payload;if(typeof e=="string")return e;if(e&&typeof e=="object"&&"text"in e){const n=e.text;if(typeof n=="string")return n}return typeof t?.action?.payload=="string"?t.action.payload:typeof t?.action?.title=="string"?t.action.title:""}function Ae(t,e){const n=t,r=n.spec,o=Array.isArray(r?.items)?r.items:void 0,i=Array.isArray(n.items)?n.items:void 0,a=o||i;if(Array.isArray(a)){for(const s of a)if(s&&typeof s=="object"){const f=s.sku;typeof f=="string"&&e.add(f)}}}function Te(t){return{invoke(e,n){return t("tool.invoke",{name:e,input:n})}}}var Ee=512,Pe=.74;function wt({accountId:t,worker:e,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,tools:s={},beacon:f}){let p=1;const d=new Map;return zt({worker:e,tools:s,beacon:u=>f?.({...u,accountId:u.accountId||t}),memory:sessionStorage}),e.addEventListener("message",u=>{const c=u.data||{},l=typeof c.id=="number"?c.id:null;if(l==null)return;const y=d.get(l);if(y){if(c.type==="event"&&c.event){J(y,c.event);return}if(c.type==="error"){y.onError(new Error(c.message||"Agent worker failed")),d.delete(l);return}c.type==="end"&&d.delete(l)}}),(u,c,l,y)=>{const g=p++;d.set(g,c);const h=()=>{d.delete(g),e.postMessage({id:g,type:"abort"})},E=w=>{if(l.aborted){h();return}e.postMessage({id:g,type:"invoke",accountId:t,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,request:w,parentUrl:window.location.href})};if(l.aborted){h();return}if(l.addEventListener("abort",h,{once:!0}),y){St(u,y).then(E).catch(w=>{d.delete(g),c.onError(w instanceof Error?w:new Error("Failed to read image attachment"))});return}E(u)}}function bt({accountId:t,accountModule:e,beUrl:n,devJwtSecret:r,tokenBrokerUrl:o,tokenBrokerAudience:i,defaultLocale:a,tools:s={},beacon:f}){let p=null;const d=je({accountId:t,tools:s,beacon:f}),u=Te(d),c=lt({accountId:t,...r?{devJwtSecret:r}:{},...o?{tokenBrokerUrl:o}:{},...i?{tokenBrokerAudience:i}:{}});return async(l,y,g,h)=>{const E=await St(l||{},h);p||=new at({accountId:t,locale:E?.locale||a,parentUrl:window.location.href,rpc:d});try{await fe({request:E,accountModule:{...e,accountId:t},contextStore:p,beClient:{invoke({op:w,input:et,signal:Ft,cacheTtlS:jn,cacheKey:xn}){return ie({beUrl:n,accountId:t,jwtProvider:c,parentUrl:window.location.href,op:w,input:et,cacheTtlS:jn,cacheKey:xn,...Ft?{signal:Ft}:{}})}},toolBridge:u,emit:w=>J(y,w),rpc:d,signal:g})}catch(w){g?.aborted||(J(y,pt(w)),y.onDone())}}}function je({accountId:t,tools:e,beacon:n}){const r=o=>n?.({...o,accountId:o.accountId||t});return((o,i)=>nt(o,i,{tools:e,beacon:r,memory:sessionStorage}))}async function St(t,e){if(!e||!e.type?.startsWith("image/"))return t;const n=await ve(e),r={...xe(t.payload??t.action?.payload),image_data_url:n.dataUrl,image_mime:n.mime};return{...t,payload:r,...t.action?{action:{...t.action,payload:r}}:{}}}function xe(t){return Ie(t)?{...t}:typeof t=="string"?{text:t}:{}}function Ie(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}async function ve(t){const e=await Ce(t);return e||{dataUrl:await kt(t),mime:t.type}}async function Ce(t){if(typeof createImageBitmap!="function"||typeof document>"u")return null;let e=null;try{e=await createImageBitmap(t);const n=Math.min(1,Ee/Math.max(e.width,e.height)),r=Math.max(1,Math.round(e.width*n)),o=Math.max(1,Math.round(e.height*n)),i=document.createElement("canvas");i.width=r,i.height=o;const a=i.getContext("2d");if(!a)return null;a.drawImage(e,0,0,r,o);const s=await new Promise(f=>i.toBlob(f,"image/jpeg",Pe));return s?{dataUrl:await kt(s),mime:s.type||"image/jpeg"}:null}catch{return null}finally{e?.close()}}async function kt(t){const e=new Uint8Array(await t.arrayBuffer());let n="";const r=32768;for(let o=0;o<e.length;o+=r)n+=String.fromCharCode(...e.subarray(o,o+r));return`data:${t.type};base64,${btoa(n)}`}function J(t,e){switch(e?.type){case"text_chunk":{const n=e;t.onTextChunk(n.content||"",n.final===!0,n);break}case"ui_spec":{const n=e;t.onUISpec(n.spec,n.widget,n.panelHint,n.clearPanel===!0);break}case"action":t.onAction(e);break;case"metadata":t.onMetadata(e);break;case"error":t.onError(Me(e));break;case"done":t.onDone();break;default:break}}function Me(t){const e=new Error(t.message||t.code||"Agent error");return t.code&&(e.code=t.code),e}var _t="__gengageAgentFetchBridge";function Re({accountId:t,streamTransport:e,endpoints:n={}}){if(!t)throw new Error("accountId is required.");if(typeof e!="function")throw new Error("streamTransport is required.");const r=Ue(),o=`https://gengage-injector.invalid/${encodeURIComponent(t)}`,i=new Set,a=s=>{const f=`${o}/chat/${s}`;i.add(f);const p=n[s],d={streamTransport:e,endpoint:s};p&&(d.endpointHandler=p),r.routes.set(f,d)};a("process_action");for(const s of Object.keys(n))s!=="process_action"&&a(s);return{middlewareUrl:o,stop(){for(const s of i)r.routes.delete(s)}}}function Ue(){const t=window,e=t[_t];if(e)return e;const n=t.fetch.bind(t),r={routes:new Map,originalFetch:n};return t.fetch=(o,i)=>{const a=At(o),s=r.routes.get(a);return s?Be(s,o,i):n(o,i)},t[_t]=r,r}function At(t){return typeof t=="string"?t:t instanceof URL?t.href:t?.url||""}function Tt(t,e){if(e?.signal)return e.signal;if(typeof Request<"u"&&t instanceof Request)return t.signal}function Et(t,e){return e?.body!==void 0&&e?.body!==null?e.body:typeof Request<"u"&&t instanceof Request?t.clone().text():null}async function Oe(t,e){const n=Et(t,e);if(n instanceof FormData){const o=n.get("request"),i=n.get("attachment");return{request:JSON.parse(String(o||"{}")),...i instanceof File?{attachment:i}:{}}}const r=await Promise.resolve(n);return typeof r=="string"?{request:JSON.parse(r||"{}")}:{request:{}}}async function Be(t,e,n){if(t.endpoint&&t.endpoint!=="process_action"&&t.endpointHandler){const p=new AbortController,d=Tt(e,n);let u=null;if(d){const c=()=>p.abort();d.aborted&&c(),d.addEventListener("abort",c,{once:!0}),u=()=>d.removeEventListener("abort",c)}try{const c=await Ne(e,n);return await t.endpointHandler(c,{accountId:$e(e),endpoint:t.endpoint,signal:p.signal})}finally{u?.()}}const r=new TextEncoder,o=new AbortController,i=Tt(e,n);let a=!1,s=null;const f=new ReadableStream({async start(p){const d=l=>{a||p.enqueue(r.encode(`${JSON.stringify(l)}
4
+ `))},u=()=>{a||(a=!0,s?.(),p.close())},c=l=>{d({type:"error",code:l?.code||"agent_bridge_error",message:l instanceof Error?l.message:String(l)}),d({type:"done"}),u()};if(i){const l=()=>{o.abort(),a||(a=!0,s?.(),p.error(new DOMException("Aborted","AbortError")))};if(i.aborted){l();return}i.addEventListener("abort",l,{once:!0}),s=()=>i.removeEventListener("abort",l)}try{const{request:l,attachment:y}=await Oe(e,n),g=t.streamTransport(l,{onTextChunk:(h,E,w={})=>d({type:"text_chunk",content:h,final:E===!0,...w}),onUISpec:(h,E,w,et)=>d({type:"ui_spec",spec:h,widget:E,...w?{panelHint:w}:{},...et?{clearPanel:!0}:{}}),onAction:h=>{d(h?.type==="action"?h:{type:"action",action:h})},onMetadata:h=>{d(h?.type==="metadata"?h:{type:"metadata",...h})},onError:c,onDone:()=>{d({type:"done"}),u()}},o.signal,y);Le(g)&&(await g,o.signal.aborted||(d({type:"done"}),u()))}catch(l){o.signal.aborted||c(l)}},cancel(){o.abort(),s?.(),a=!0}});return new Response(f,{status:200,headers:{"Content-Type":"application/x-ndjson"}})}async function Ne(t,e){const n=await Promise.resolve(Et(t,e));return typeof n!="string"||n.trim()===""?{}:JSON.parse(n)}function $e(t){try{const[e]=new URL(At(t)).pathname.split("/").filter(Boolean);return decodeURIComponent(e||"")}catch{return""}}function Le(t){return t!==null&&(typeof t=="object"||typeof t=="function")&&typeof t.then=="function"}function De({accountId:t,beUrl:e,devJwtSecret:n,tokenBrokerUrl:r,tokenBrokerAudience:o,workerUrl:i,defaultLocale:a="en-GB",accountModule:s,tools:f={},beacon:p,allowBlobWorker:d=!1}){if(!t)throw new Error("accountId is required.");if(!e)throw new Error("beUrl is required. The injector owns backend URLs; the SDK has no default.");if(!i)throw new Error("workerUrl is required.");const u=window,c=u.GengageAssistantInjector||(u.GengageAssistantInjector={}),l=c[t]||(c[t]={});if(l.agentController)return l.agentController;const y=H(i)||d?Pt(i,`gengage-${t}-agent`,{allowBlobWorker:d}):null;l.streamTransport=y?wt({accountId:t,worker:y.worker,beUrl:e,...n?{devJwtSecret:n}:{},...r?{tokenBrokerUrl:r}:{},...o?{tokenBrokerAudience:o}:{},defaultLocale:a,tools:f,...p?{beacon:p}:{}}):bt({accountId:t,accountModule:s,beUrl:e,...n?{devJwtSecret:n}:{},...r?{tokenBrokerUrl:r}:{},...o?{tokenBrokerAudience:o}:{},defaultLocale:a,tools:f,...p?{beacon:p}:{}});const g={type:"agent",stop(){delete l.streamTransport,y?.worker.terminate(),y?.cleanup(),delete l.agentController},diagnostics(){return{accountId:t,beUrl:e,workerUrl:i,mounted:!0,transport:y?"worker":"main-thread",flows:Object.keys(s?.flows||{})}}};return l.agentController=g,g}function H(t){const e=new URL(t,window.location.href);return e.origin===window.location.origin||e.protocol==="blob:"}function Pt(t,e,n={}){const r=new URL(t,window.location.href);if(H(t))return{worker:new Worker(r.href,{type:"module",name:e}),cleanup(){}};if(!n.allowBlobWorker)throw new Error("Cross-origin agent workers require allowBlobWorker=true or a same-origin workerUrl.");const o=new Blob([`import ${JSON.stringify(r.href)};
5
+ `],{type:"text/javascript"}),i=URL.createObjectURL(o);try{return{worker:new Worker(i,{type:"module",name:e}),cleanup(){URL.revokeObjectURL(i)}}}catch(a){throw URL.revokeObjectURL(i),a}}function jt(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function O(t){const e=jt(t);if(!e)return null;const n=x(e.sku,e.SKU);if(!n)return null;const r={sku:n,name:x(e.name,e.title,e.short_name,n)||n,url:x(e.url)||""},o=Array.isArray(e.images)?e.images:void 0,i=x(e.imageUrl,e.image_url,e.image,o?.[0]);i&&(r.imageUrl=i),o&&o.length>1&&(r.images=o.filter(g=>!!g).map(String));const a=M(e.price_discounted),s=M(e.price),f=a||s;f>0&&(r.price=String(f));const p=a>0?s:0;p>0&&(r.originalPrice=String(p));const d=x(e.brand);d&&(r.brand=d);const u=M(e.rating);u>0&&(r.rating=u);const c=M(e.review_count)||M(e.reviewCount);c>0&&(r.reviewCount=c);const l=x(e.cart_code,e.cartCode);l&&(r.cartCode=l),typeof e.in_stock=="boolean"&&(r.inStock=e.in_stock),typeof e.inStock=="boolean"&&(r.inStock=e.inStock);const y=e.category_names;return Array.isArray(y)&&(r.categoryNames=y.map(String)),r}function xt(t){const e=jt(t);if(!e)return t;const n=e.category_names,r=Array.isArray(n)?n:void 0,o=e.images,i=Array.isArray(o)?o:void 0,a={sku:e.sku,name:e.name||e.title,url:e.url,price:e.price,currency:e.price_currency||e.currency,category:r?.[r.length-1]??void 0,category_names:r?r.slice(0,4):void 0,image:i?i[0]:e.image,in_stock:e.in_stock,rating:e.rating,review_count:e.review_count};for(const s of Object.keys(a))a[s]===void 0&&delete a[s];return a}function W(t){return Array.isArray(t)?t.map(xt).filter(e=>!!e):[]}function x(...t){for(const e of t)if(typeof e=="string"&&e.trim())return e.trim();return""}function M(t){const e=Number(t);return Number.isFinite(e)?e:0}function It(t){return Array.isArray(t)?t.map(String).filter(Boolean):typeof t=="string"&&t?[t]:[]}function vt(t=[]){const e={},n=[];return(Array.isArray(t)?t.map(O).filter(r=>!!r):[]).forEach((r,o)=>{const i=`product-${o.toString()}`;n.push(i);const a={sku:r.sku,product:r};e[i]={type:"ProductCard",props:{product:r,index:o,action:{title:r.name,type:"launchSingleProduct",payload:a}}}}),e.root={type:"ProductGrid",props:{layout:"grid"},children:n},{widget:"chat",panelHint:"panel",spec:{root:"root",elements:e}}}function Fe(t){return{widget:"chat",panelHint:"panel",spec:{root:"root",elements:{root:{type:"ProductDetailsPanel",props:{product:O(t)||t||{}}}}}}}function qe(t={}){const e=(t.multiple_product_details||t.products||[]).map(O).filter(r=>!!r),n=t.table||{};return{widget:"chat",panelHint:"panel",spec:{root:"root",elements:{root:{type:"ComparisonTable",props:{products:e,recommended:e.find(r=>r.sku===t.recommended_choice_sku)||e[0],attributes:Object.entries(n).map(([r,o])=>({label:r,values:Array.isArray(o)?o.map(String):[String(o??"")]})),highlights:It(t.key_differences),specialCases:It(t.special_considerations),recommendedText:t.recommended_choice,productActions:Object.fromEntries(e.map(r=>[r.sku,{title:r.name,type:"launchSingleProduct",payload:{sku:r.sku,product:r}}]))}}}}}}function ze(t=[]){return{widget:"chat",panelHint:"inline",spec:{root:"root",elements:{root:{type:"ActionButtons",props:{buttons:(Array.isArray(t)?t:[]).map(e=>{const n=e.label||e.title||e.shortName||"",r=e.action||e.requestDetails||e.request_details;return!n||!r?.type?null:{label:n,action:{title:n,type:r.type,...r.payload!==void 0?{payload:r.payload}:{}}}}).filter(e=>!!e)}}}}}}function B(t){const e=t?.payload;if(typeof e=="string")return e;if(e&&typeof e=="object"&&"text"in e){const r=e.text;if(typeof r=="string")return r}const n=t?.action;return n&&typeof n.payload=="string"?n.payload:n&&typeof n.title=="string"?n.title:""}function Ct(t){return Object.freeze([...t])}function P(t){return t&&typeof t=="object"?t:{}}function K(t){return t&&typeof t=="object"?t:{}}function Mt(t){return t.thread.extensions.beauty_profile}var Ge=Ct([{kind:"be_op",op:"beauty-consulting-turn",input:({request:t,context:e})=>({utterance:B(t),prior_messages:e.messages.slice(-10),profile:Mt(e),candidate_products:He(t),locale:e.meta.locale}),out:"consultation",patch:Rt},{kind:"branch",on:({bag:t})=>P(t.consultation).consultation_state?.stage||"answer",cases:{refuse:[{kind:"refusal",message:({bag:t})=>{const e=P(t.consultation);return e.refusal?.message||e.plain_text||"I cannot help with that request."}}],needs_more_info:[{kind:"emit",build:({bag:t})=>C(Q(P(t.consultation)),!0)},{kind:"commit"}],search:[{kind:"tool",name:"search",input:({request:t,bag:e,context:n})=>{const r=P(e.consultation);return{query:r.search_params?.query||B(t),facets:r.search_params?.facets||{},limit:12,locale:n.meta.locale}},out:"products",patch:(t,e)=>{const n=K(e);return{panel:{...t.panel,screen_sku_list:V(n).map(r=>Je(r)).filter(r=>!!r),last_search:{query:n.query||""}}}}},{kind:"emit",build:({bag:t})=>yt(vt(V(K(t.products))))},{kind:"be_op",op:"beauty-consulting-turn",input:({request:t,context:e,bag:n})=>({utterance:B(t),prior_messages:e.messages.slice(-10),profile:Mt(e),candidate_products:W(V(K(n.products)).slice(0,12)),locale:e.meta.locale}),out:"answer",patch:(t,e)=>{const n=Rt(t,e),r=(P(e).product_mentions||[]).map(o=>o.sku).filter(o=>!!o);return{...n||{},panel:{...t.panel,chat_mentioned_skus:r}}}},{kind:"emit",build:({bag:t})=>{const e=P(t.answer);return C(Q(e),!0,{productMentions:e.product_mentions||[]})}},{kind:"commit"}],default:[{kind:"emit",build:({bag:t})=>{const e=P(t.consultation);return C(Q(e),!0,{productMentions:e.product_mentions||[]})}},{kind:"commit"}]}}]);function Rt(t,e){const n=P(e).consultation_state?.captured_profile;if(!n)return null;const r=t.thread.extensions.beauty_profile&&typeof t.thread.extensions.beauty_profile=="object"?t.thread.extensions.beauty_profile:{};return{thread:{...t.thread,extensions:{...t.thread.extensions,beauty_profile:{...r,...n}}}}}function V(t){return Array.isArray(t?.products)?t.products:[]}function Je(t){if(t&&typeof t=="object"&&"sku"in t){const e=t.sku;if(typeof e=="string")return e}}function He(t){const e=t?.payload&&typeof t.payload=="object"?t.payload.products:void 0,n=t?.action?.payload&&typeof t.action.payload=="object"?t.action.payload.products:void 0,r=e||n;return Array.isArray(r)?W(r.slice(0,12)):void 0}function Q(t){return t?.answer_html||t?.plain_text||t?.refusal?.message||"I can help with beauty shopping."}var Ut=new Set(["and","are","box","for","from","gift","gifts","the","with"]),We={token:.26,keyword:.22,category:.18,facet:.16,color:.08,attribute:.06,price:.08,retrieval:.08},Ke=["amber","beige","black","blue","blush","bronze","brown","cream","gold","green","grey","ivory","lilac","mixed","orange","pastel","pink","purple","red","silver","white","yellow"];function A(t){return String(t??"").normalize("NFKD").replace(new RegExp("\\p{Diacritic}","gu"),"").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function k(t,e=Ut){const n=e instanceof Set?e:new Set([...Ut,...e]),r=new Set,o=[];for(const i of A(t).split(/\s+/u))i.length<3||n.has(i)||r.has(i)||(r.add(i),o.push(i));return o}function R(t,e={}){if(Xe(t))return t;const n=e.facetKeys,r=b(t.category_names??t.category),o=b(t.category_ids),i=Ze(t.facet_hits),a=Object.entries(i).filter(([g])=>!n||n.some(h=>A(h)===A(g))).map(([,g])=>g),s=_(t.name,t.title),f=_(t.brand),p=e.sourceKeywords??[],d=[s,f,...r,...a,...b(t.promotions),_(t.description),...p].join(" "),u=k(d,e.stopWords),c=_(e.sourceProductType,nn(r,s,u),u[0]),l=T([...en(d,Ke),...Object.entries(i).filter(([g])=>/colou?r/iu.test(g)).flatMap(([,g])=>k(g,e.stopWords))]),y=T([...a.flatMap(g=>k(g,e.stopWords)),...b(t.promotions).flatMap(g=>k(g,e.stopWords))]).slice(0,24);return{sku:_(t.sku),title:s,brand:f,productType:c,categoryNames:r,categoryIds:o,facets:i,keywords:T([...p.flatMap(g=>k(g,e.stopWords)),...u]).slice(0,12),tokens:u,colors:l,attributes:y,price:tn(t)}}function Ve(t,e={}){const n=_(t.product_type,t.productType),r=_(t.title,n,b(t.keywords).join(" ")),o=T([...b(t.keywords),...b(t.colors),...b(t.materials),...b(t.styles),...b(t.attributes)]);return R({sku:"__photo__",name:r,category_names:n?[n]:[],facet_hits:{colors:b(t.colors).join(", "),materials:b(t.materials).join(", "),styles:b(t.styles).join(", "),attributes:b(t.attributes).join(", ")},promotions:o},{...e,sourceProductType:n,sourceKeywords:o})}function Qe(t,e={}){const n=R(t,e);return T([...e.sourceQueries??[],N([n.productType,...n.colors.slice(0,1),...n.attributes.slice(0,2)]),N([n.productType,...n.keywords.slice(0,3)]),N([n.categoryNames[n.categoryNames.length-1],...n.keywords.slice(0,2)]),N(n.title.split(/\s+/u).slice(0,6)),n.productType].map(r=>r.trim()).filter(Boolean)).slice(0,e.queryLimit??6)}function Ot(t,e,n={}){const r={...We,...n.weights},o=R(e,n),i=[],a=I(t.tokens,o.tokens),s=I(t.keywords,o.tokens),f=rn(t.categoryNames,o.categoryNames)||I(Bt(t.categoryNames),Bt(o.categoryNames)),p=I(t.attributes,o.attributes),d=I(t.colors,o.colors),u=I(t.attributes,o.tokens),c=on(t.price,o.price),l=an(o.sku,n.hitCounts)>0?1:0,y=sn(t,o),g=a*r.token+s*r.keyword+f*r.category+p*r.facet+d*r.color+u*r.attribute+c*r.price+l*r.retrieval,h=cn(y?g:g*.35);return y&&t.productType&&t.productType===o.productType&&i.push("same product type"),f>.4&&i.push("similar category"),p>.2&&i.push("matching product attributes"),d>0&&i.push("matching colour"),c>.8&&i.push("similar price"),y||i.push("weaker product-type match"),{score:Number(h.toFixed(4)),reasons:i}}function Ye(t,e,n={}){const r=R(t,n),o=new Set([r.sku,...n.ignoreSkus??[]].filter(Boolean));return e.filter(i=>{const a=_(i.sku);return a&&!o.has(a)}).map(i=>{const a=Ot(r,i,n);return{...i,similarity_score:a.score,similarity_reasons:a.reasons}}).sort((i,a)=>a.similarity_score-i.similarity_score).slice(0,Math.max(1,Math.min(n.limit??12,100)))}function Xe(t){return!!(t&&typeof t=="object"&&Array.isArray(t.tokens))}function _(...t){for(const e of t)if(typeof e=="string"&&e.trim())return e.trim();return""}function b(t){return Array.isArray(t)?t.map(e=>_(e)).filter(Boolean):typeof t=="string"&&t.trim()?t.split(/[,;/|]+/u).map(e=>e.trim()).filter(Boolean):[]}function Ze(t){return!t||typeof t!="object"||Array.isArray(t)?{}:Object.fromEntries(Object.entries(t).map(([e,n])=>[e,_(n)]).filter(([,e])=>e))}function tn(t){const e=Number(t.price_discounted);if(Number.isFinite(e)&&e>0)return e;const n=Number(t.price);return Number.isFinite(n)&&n>0?n:0}function T(t){const e=new Set,n=[];for(const r of t){const o=A(r);!o||e.has(o)||(e.add(o),n.push(o))}return n}function en(t,e){const n=` ${A(t)} `;return e.filter(r=>n.includes(` ${A(r)} `))}function nn(t,e,n){const r=A(t[t.length-1]??t[0]??"");if(r){const o=k(r),i=new Set(k(e));return o.find(a=>i.has(a))??o[0]??r}return n[0]??""}function N(t){return t.map(e=>A(e)).filter(Boolean).join(" ").replace(/\s+/gu," ").trim().slice(0,120)}function Bt(t){return t.flatMap(e=>k(e))}function I(t,e){const n=T(t),r=new Set(T(e));return n.length===0||r.size===0?0:n.filter(o=>r.has(o)).length/n.length}function rn(t,e){const n=T(t),r=new Set(T(e));return n.length===0||r.size===0?0:n.filter(o=>r.has(o)).length/n.length}function on(t,e){return t<=0||e<=0?0:Math.min(t,e)/Math.max(t,e)}function an(t,e){return!t||!e?0:typeof e.get=="function"?e.get(t)??0:e[t]??0}function sn(t,e){if(!t.productType||!e.productType||t.productType===e.productType)return!0;const n=new Set(k(t.productType)),r=new Set([...k(e.productType),...e.tokens]);return[...n].some(o=>r.has(o))}function cn(t){return Math.max(0,Math.min(1,t))}function un(t){const e=(t?.chat||t?._chat)?.root||t?._chat?.root;return e?e.getRootNode?.()?.host||e:Array.from(document.querySelectorAll("*")).find(n=>n.shadowRoot?.querySelector?.(".gengage-chat-root, .gengage-chat-launcher-container"))}function ln(t,e){const n=un(t);n?.style&&(e?n.style.removeProperty("display"):n.style.setProperty("display","none","important")),e||(t?.chat||t?._chat)?.close?.()}var dn="nd_be_url";function fn(t,e){const n=pn()||t.beUrl||e;if(!n)throw new Error("resolveBeUrl: backend URL is required. The injector must supply a fallback URL; the SDK has no default.");return n}function pn(){try{const t=new URLSearchParams(window.location.search).get(dn)?.trim();if(!t)return null;const e=new URL(t);return e.protocol!=="https:"&&e.protocol!=="http:"?null:e.toString().replace(/\/+$/u,"")}catch{return null}}var mn="entries",yn=1,gn={volatile:"Hot per-page state and sensitive request context.",session:"Current-visit tool context without raw tokens or PII-heavy payloads.",local:"Small, non-sensitive capability facts or user preferences.",indexedDb:"Larger product/search payload caches with short TTLs."},Nt=new Map;function Y(){return Date.now()}function X(t){return t?.expiresAt!=null&&t.expiresAt<=Y()}function Z(t,e){return{value:t,createdAt:Y(),expiresAt:e?Y()+e:null}}function hn(t,e,n){try{const r=t.getItem(`${e}${n}`);if(!r)return null;const o=JSON.parse(r);return X(o)?(t.removeItem(`${e}${n}`),null):o.value}catch{return null}}function wn(t,e,n,r,o){try{return t.setItem(`${e}${n}`,JSON.stringify(Z(r,o))),!0}catch{return!1}}function bn(t,e,n){try{t.removeItem(`${e}${n}`)}catch{}}function $t(t){try{return window[t]}catch{return null}}function Lt(t,e){return t?{get:n=>hn(t,e,n),set:(n,r,o={})=>wn(t,e,n,r,o.ttlMs),remove:n=>bn(t,e,n)}:{get:()=>null,set:()=>!1,remove:()=>{}}}function tt(t){if(Array.isArray(t))return`[${t.map(tt).join(",")}]`;if(t&&typeof t=="object"){const e=t;return`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${tt(e[n])}`).join(",")}}`}return JSON.stringify(t)}function Dt(t){let e=2166136261;const n=tt(t);for(let r=0;r<n.length;r+=1)e^=n.charCodeAt(r),e=Math.imul(e,16777619);return(e>>>0).toString(36)}function Sn(t,e){const n=e.dbName||`gengage-${t}`,r=e.dbStore||mn,o=e.dbVersion||yn,i=new Map;let a=null;const s=()=>"indexedDB"in window?a||(a=new Promise(u=>{const c=indexedDB.open(n,o);c.onupgradeneeded=()=>{c.result.createObjectStore(r,{keyPath:"key"})},c.onsuccess=()=>u(c.result),c.onerror=()=>u(null),c.onblocked=()=>u(null)}),a):Promise.resolve(null);return{volatileEntries:i,idbGet:async u=>{const c=await s();return c?new Promise(l=>{const y=c.transaction(r,"readwrite").objectStore(r),g=y.get(u);g.onsuccess=()=>{const h=g.result;if(!h||X(h)){h&&y.delete(u),l(null);return}l(h.value)},g.onerror=()=>l(null)}):null},idbSet:async(u,c,l={})=>{const y=await s();return y?new Promise(g=>{const h=y.transaction(r,"readwrite");h.oncomplete=()=>g(!0),h.onerror=()=>g(!1),h.objectStore(r).put({key:u,...Z(c,l.ttlMs)})}):!1},idbRemove:async u=>{const c=await s();c&&c.transaction(r,"readwrite").objectStore(r).delete(u)}}}function kn(t,e={}){const n=window,r=n.gengage||(n.gengage={}),o=r.memory||(r.memory={}),i=o[t];if(i)return i;const a=Nt.get(t)||Sn(t,e);Nt.set(t,a);const s=e.sessionPrefix||`gengage:${t}:session:`,f=e.localPrefix||`gengage:${t}:local:`,d={get:l=>{const y=a.volatileEntries.get(l);return y?X(y)?(a.volatileEntries.delete(l),null):y.value:null},set:(l,y,g={})=>(a.volatileEntries.set(l,Z(y,g.ttlMs)),!0),remove:l=>{a.volatileEntries.delete(l)},clear:()=>a.volatileEntries.clear()},u={get:a.idbGet,set:a.idbSet,remove:a.idbRemove},c={accountId:t,volatile:d,session:Lt($t("sessionStorage"),s),local:Lt($t("localStorage"),f),indexedDb:u,stableKey:Dt,policy:{...gn,...e.policy||{}}};o[t]=c;for(const l of e.aliases||[])o[l]=c;return c}var _n=["addToCart","search","searchKeyword","facetedSearch","searchGiftOptions","similaritySearch"];function An(t,e,n={}){const r=window,o=r.gengage||(r.gengage={}),i=o.tools||(o.tools={});i[t]=e;for(const a of n.accountAliases||[])i[a]=e;if(n.exposeStandardAliases!==!1)for(const a of n.standardAliases||_n){const s=e[a];typeof s=="function"&&(i[a]=i[a]||s)}return e}function Tn({getPageType:t,getProduct:e}){return()=>({url:window.location.href,title:document.title,pageType:t(),product:e()})}function En({accountId:t,getPageType:e,getProduct:n,getToolNames:r,getSearchCapabilities:o,getMemory:i}){return async()=>({accountId:t,url:window.location.href,pageType:e(),productSku:n()?.sku??null,toolNames:r(),...o?{searchCapabilities:o()}:{},...i?{memoryPolicy:i().policy}:{},timestamp:new Date().toISOString()})}function Pn({accountId:t,runtimeFile:e="runtime.js",startExport:n="start",globalBaseUrlKey:r,errorLabel:o}={}){if(!t)throw new Error("accountId is required.");const i=o||t,a=window,s=()=>{const u=a.GengageInjectorConfig||{},c=u[t]||{};return{...u,...c}},f=()=>{const u=s();if(u.runtimeUrl)return u.runtimeUrl;const c=u.assetBaseUrl||u.baseUrl||document.currentScript?.getAttribute("src")||(r?a[r]:null);if(!c)throw new Error(`${i} runtime URL cannot be resolved.`);return new URL(e,c).href},p=a.GengageAssistantInjector||(a.GengageAssistantInjector={}),d=p[t]||(p[t]={});return d.loaderPromise||(d.loaderPromise=import(f()).then(u=>{const c=u[n];if(typeof c!="function")throw new Error(`${i} runtime export ${n} is unavailable.`);return c()}).catch(u=>{throw delete d.loaderPromise,console.error(`[Gengage][${t}] runtime load failed`,u),u})),d.loaderPromise}m.AgentError=$,m.ContextStore=at,m.action=de,m.actionButtonsUiSpec=ze,m.beErrorToAgentError=L,m.beautyConsultingTurnFlow=Ge,m.buildPhotoSimilarityProfile=Ve,m.buildProductSimilarityProfile=R,m.buildSimilarityQueries=Qe,m.canUseModuleWorker=H,m.caughtToStreamError=pt,m.comparisonUiSpec=qe,m.createBrowserMemory=kn,m.createDiagnosticsTool=En,m.createFlow=Ct,m.createInjectorAdapter=wt,m.createMainThreadInjectorAdapter=bt,m.createModuleWorker=Pt,m.createReadPageTool=Tn,m.done=D,m.elapsedMs=U,m.error=gt,m.httpErrorToAgentError=ft,m.installBrowserTools=An,m.installFetchTransportBridge=Re,m.metadata=le,m.mountAccount=De,m.normalizeProduct=O,m.normalizeSimilarityText=A,m.nowIso=rt,m.productDetailsUiSpec=Fe,m.productsUiSpec=vt,m.rankSimilarProducts=Ye,m.requestText=B,m.resolveBeUrl=fn,m.resolveFlow=ht,m.scoreSimilarityCandidate=Ot,m.setAssistantHostVisible=ln,m.stableKey=Dt,m.startLazyRuntimeLoader=Pn,m.textChunk=C,m.tokenizeSimilarityText=k,m.trimProductFactsCore=xt,m.trimProductFactsListCore=W,m.uiSpec=yt})(this.Gengage=this.Gengage||{});
@@ -1,4 +1,4 @@
1
- import { i as U } from "./widget-base-Dmu5iLyV.js";
1
+ import { i as U } from "./widget-base-C6H3cDSW.js";
2
2
  var z = ({ element: e, renderElement: t }) => {
3
3
  if (!e.children || e.children.length === 0) return null;
4
4
  const r = document.createElement("div");
@@ -1,4 +1,4 @@
1
- import { c as e, d as t, i as r, l as s, n, o as i, r as l, s as C, t as c, u as d } from "./runtime-DOsQNOP3.js";
1
+ import { c as e, d as t, i as r, l as s, n, o as i, r as l, s as C, t as c, u as d } from "./runtime-B0v76aJ5.js";
2
2
  export {
3
3
  s as CHAT_SCROLL_ELEMENT_ID,
4
4
  r as ChatPresentationState,