@sentientui/core 0.22.0 → 0.24.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.
Files changed (52) hide show
  1. package/dist/chunk-2NVSFI4V.mjs +2 -0
  2. package/dist/chunk-2NVSFI4V.mjs.map +1 -0
  3. package/dist/chunk-EWP6FTHE.mjs +2 -0
  4. package/dist/chunk-EWP6FTHE.mjs.map +1 -0
  5. package/dist/chunk-KIP52DUJ.mjs +2 -0
  6. package/dist/chunk-KIP52DUJ.mjs.map +1 -0
  7. package/dist/chunk-RL5B6M4G.mjs +2 -0
  8. package/dist/chunk-RL5B6M4G.mjs.map +1 -0
  9. package/dist/classify-DYlSjkFP.d.cts +47 -0
  10. package/dist/classify-DYlSjkFP.d.ts +47 -0
  11. package/dist/{index-BbrtAtrY.d.ts → index-BjVvN7cU.d.ts} +1 -1
  12. package/dist/{index-CXxvWxCB.d.cts → index-Cd0gMdJv.d.cts} +1 -1
  13. package/dist/index-engagement.d.cts +3 -28
  14. package/dist/index-engagement.d.ts +3 -28
  15. package/dist/index-engagement.js +1 -1
  16. package/dist/index-engagement.js.map +1 -1
  17. package/dist/index-engagement.mjs +1 -1
  18. package/dist/index-engagement.mjs.map +1 -1
  19. package/dist/index-graph.d.cts +14 -4
  20. package/dist/index-graph.d.ts +14 -4
  21. package/dist/index-graph.js +1 -1
  22. package/dist/index-graph.js.map +1 -1
  23. package/dist/index-graph.mjs +1 -1
  24. package/dist/index-graph.mjs.map +1 -1
  25. package/dist/index-local.d.cts +2 -2
  26. package/dist/index-local.d.ts +2 -2
  27. package/dist/index-server.d.cts +10 -2
  28. package/dist/index-server.d.ts +10 -2
  29. package/dist/index-server.js +1 -1
  30. package/dist/index-server.js.map +1 -1
  31. package/dist/index-server.mjs +1 -1
  32. package/dist/index-server.mjs.map +1 -1
  33. package/dist/index-topics.d.cts +21 -0
  34. package/dist/index-topics.d.ts +21 -0
  35. package/dist/index-topics.js +2 -0
  36. package/dist/index-topics.js.map +1 -0
  37. package/dist/index-topics.mjs +2 -0
  38. package/dist/index-topics.mjs.map +1 -0
  39. package/dist/index.d.cts +2 -2
  40. package/dist/index.d.ts +2 -2
  41. package/dist/index.js +1 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +1 -1
  44. package/dist/{session-meta-BVvq5RBB.d.cts → session-meta-C-bMqVeq.d.cts} +32 -1
  45. package/dist/{session-meta-BVvq5RBB.d.ts → session-meta-C-bMqVeq.d.ts} +32 -1
  46. package/package.json +7 -2
  47. package/dist/chunk-2RH7I6AP.mjs +0 -2
  48. package/dist/chunk-2RH7I6AP.mjs.map +0 -1
  49. package/dist/chunk-CD2A55US.mjs +0 -2
  50. package/dist/chunk-CD2A55US.mjs.map +0 -1
  51. package/dist/chunk-QNEYUJJJ.mjs +0 -2
  52. package/dist/chunk-QNEYUJJJ.mjs.map +0 -1
@@ -0,0 +1,2 @@
1
+ import{a}from"./chunk-TMCGHANO.mjs";function x(t){return t?`_${t.slice(0,12)}`:""}var S="_snt_uid";function _(t){return`${S}${x(t)}`}var c=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function y(t){return b(t)!==null}function b(t){var r;if(!t)return null;let e=t.toLowerCase();return(r=c.find(i=>e.includes(i.toLowerCase())))!=null?r:null}var h={GPTBot:"training","ChatGPT-User":"user","OAI-SearchBot":"search",ClaudeBot:"training","Claude-User":"user","Claude-SearchBot":"search",PerplexityBot:"search","Perplexity-User":"user","Google-Extended":"training","Applebot-Extended":"training","Meta-ExternalAgent":"training",Bytespider:"training",CCBot:"training",Amazonbot:"other","cohere-ai":"training",Diffbot:"other"};function L(t){if(!t)return"other";let e=c.find(r=>r.toLowerCase()===t.toLowerCase());return e&&h[e]||"other"}function E(){var e;let t={user:[],search:[],training:[],other:[]};for(let r of c)t[(e=h[r])!=null?e:"other"].push(r);return t}function p(t){let e=t.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(e)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(e)?"mobile":"desktop"}function R(t,e){if(!t)return"direct";try{let r=new URL(t);if(e)try{if(new URL(e).host===r.host)return"direct"}catch(n){}let i=r.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(i)?"search":/(^|\.)(twitter\.com|x\.com|facebook\.com|linkedin\.com|reddit\.com|t\.co)$/.test(i)?"social":"referral"}catch(r){return"direct"}}function C(t){if(!t)return null;try{return new URL(t).hostname}catch(e){return null}}var A=["gclid","gbraid","wbraid","fbclid","ttclid","msclkid","twclid","li_fat_id"];function T(t){let e={},r={};try{let i=typeof t=="string"||t instanceof URLSearchParams?new URLSearchParams(t):Object.entries(t).flatMap(([n,o])=>{let s=Array.isArray(o)?o[0]:o;return s===void 0?[]:[[n,s]]});for(let[n,o]of i)n.startsWith("utm_")?n in e||(e[n]=o):A.includes(n)&&(n in r||(r[n]=o))}catch(i){}return{utmParams:e,clickIds:r}}function I(t){let e=t.getHours();return e<6?"night":e<12?"morning":e<18?"afternoon":"evening"}function G(t){let e=k("__segment__",t);return`${e.deviceClass}:${e.trafficSource}`}function k(t,e){var o,s,l,u,g,d,f,m;let r=(s=(o=e==null?void 0:e.userAgent)==null?void 0:o.trim())!=null?s:"",i=(u=(l=e==null?void 0:e.referer)==null?void 0:l.trim())!=null?u:"",n=(g=e==null?void 0:e.now)!=null?g:new Date;return{sessionId:t,ephemeral:!1,utmParams:(d=e==null?void 0:e.utmParams)!=null?d:{},clickIds:(f=e==null?void 0:e.clickIds)!=null?f:{},deviceClass:r?p(r):"desktop",trafficSource:i?R(i,e==null?void 0:e.appOrigin):"direct",referrerDomain:C(i),timeOfDay:I(n),dayOfWeek:(m=["sun","mon","tue","wed","thu","fri","sat"][n.getDay()])!=null?m:"sun",automation:(e==null?void 0:e.webdriver)===!0||y(r)}}import{canonicalArm as P,slotBaselineArm as w,slotResultFor as D}from"@sentientui/policy";function U(t){return a(a(a({id:t.id},t.arms?{arms:[...t.arms]}:{}),t.dims?{dims:Object.fromEntries(Object.entries(t.dims).map(([e,r])=>[e,[...r]]))}:{}),t.baseline!==void 0?{baseline:t.baseline}:{})}function O(t){let e=U(t);return D(e,w(e))}function M(t){let e={};for(let r of t)e[r.id]=O(r);return e}function N(t){return typeof t=="string"?t:P(t)}export{x as a,S as b,_ as c,c as d,y as e,b as f,h as g,L as h,E as i,p as j,R as k,C as l,A as m,T as n,I as o,G as p,k as q,U as r,O as s,M as t,N as u};
2
+ //# sourceMappingURL=chunk-2NVSFI4V.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage-key.ts","../src/session-meta.ts","../src/slots.ts"],"sourcesContent":["/**\n * Per-project browser-storage namespace suffix, derived from the public apiKey.\n *\n * Multiple SentientUI projects (different `pk_` keys) can run on the same exact\n * origin. Storage keyed only by name (`_snt_uid`, `_snt_asgn_*`,\n * `_snt_graph_nodes`) would then collide across projects — the visitor id in\n * particular, whose session row is keyed globally server-side, would let one\n * project's traffic land on another's session. Suffixing every browser key with\n * the apiKey prefix isolates projects, matching the queue's existing\n * `_snt_retry_${apiKey.slice(0,12)}` convention.\n *\n * Returns `''` when no apiKey is available (local mode) so keys stay stable\n * there.\n */\nexport function storageSuffix(apiKey?: string): string {\n return apiKey ? `_${apiKey.slice(0, 12)}` : '';\n}\n\n/**\n * The bare, pre-namespacing session cookie name. Still read as a FALLBACK\n * everywhere the suffixed name is read, so visitors who got their identity\n * before per-project namespacing keep it instead of being minted a fresh one.\n */\nexport const LEGACY_SESSION_COOKIE_NAME = '_snt_uid';\n\n/**\n * The one place the session cookie's name is decided. The writer (session.ts)\n * and every reader (core/server.ts SSR helper, graph sync, react devtools) must\n * call THIS — when namespacing landed, the writer moved to the suffixed name\n * while three readers kept the bare `_snt_uid`, so every SSR request for a\n * returning visitor missed the cookie and minted a fresh orphan session (quota\n * inflation, broken sticky assignments and persona continuity), and graph sync\n * sent `sessionId: undefined`. Deriving both sides from one function makes that\n * drift impossible, and index.test.ts pins the reader against the writer.\n */\nexport function sessionCookieName(apiKey?: string): string {\n return `${LEGACY_SESSION_COOKIE_NAME}${storageSuffix(apiKey)}`;\n}\n","/** Session metadata helpers (browser + Node). No DOM APIs. */\n\n/**\n * Known AI-agent / crawler user-agent tokens. Matched case-insensitively as\n * substrings. This is maintained data — bot lists move monthly. Used both to\n * flag automation on sessions (agentic browsers that leak a token) and by the\n * server middleware / agent-feed route to identify crawler HTTP reads.\n */\nexport const agentUaList: readonly string[] = [\n 'GPTBot',\n 'ChatGPT-User',\n 'OAI-SearchBot',\n 'ClaudeBot',\n 'Claude-User',\n 'Claude-SearchBot',\n 'PerplexityBot',\n 'Perplexity-User',\n 'Google-Extended',\n 'Applebot-Extended',\n 'Meta-ExternalAgent',\n 'Bytespider',\n 'CCBot',\n 'Amazonbot',\n 'cohere-ai',\n 'Diffbot',\n];\n\n/** True when the user-agent contains a known AI-agent / crawler token. */\nexport function uaTokenMatch(userAgent: string): boolean {\n return matchedAgentToken(userAgent) !== null;\n}\n\n/** The first known agent token found in the user-agent, or null. */\nexport function matchedAgentToken(userAgent: string): string | null {\n if (!userAgent) return null;\n const s = userAgent.toLowerCase();\n return agentUaList.find((token) => s.includes(token.toLowerCase())) ?? null;\n}\n\n/**\n * Purpose category for an agent fetch, inferred from its published user-agent:\n * - `user` — a person asked an assistant to read the page, live (…-User UAs)\n * - `search` — indexing for an AI answer engine (…-SearchBot / SearchBot)\n * - `training` — model-training crawl (GPTBot, ClaudeBot, CCBot, …)\n * - `other` — not clearly AI, or an unknown/new token\n */\nexport type AgentIntent = 'user' | 'search' | 'training' | 'other';\n\n/** Intent per agent token. Maintained beside `agentUaList` — when you add or\n * rename a token above, set its intent here (a unit test enforces coverage). */\nexport const AGENT_INTENTS: Record<string, AgentIntent> = {\n 'GPTBot': 'training',\n 'ChatGPT-User': 'user',\n 'OAI-SearchBot': 'search',\n 'ClaudeBot': 'training',\n 'Claude-User': 'user',\n 'Claude-SearchBot': 'search',\n 'PerplexityBot': 'search',\n 'Perplexity-User': 'user',\n 'Google-Extended': 'training',\n 'Applebot-Extended': 'training',\n 'Meta-ExternalAgent': 'training',\n 'Bytespider': 'training',\n 'CCBot': 'training',\n 'Amazonbot': 'other',\n 'cohere-ai': 'training',\n 'Diffbot': 'other',\n};\n\n/** Intent for a matched bot token (case-insensitive); `other` for null/unknown. */\nexport function agentIntent(botName: string | null): AgentIntent {\n if (!botName) return 'other';\n const hit = agentUaList.find((t) => t.toLowerCase() === botName.toLowerCase());\n return (hit && AGENT_INTENTS[hit]) || 'other';\n}\n\n/** `agentUaList` grouped by intent — the \"which crawlers do you classify?\" reference. */\nexport function classifiedAgents(): Record<AgentIntent, string[]> {\n const out: Record<AgentIntent, string[]> = { user: [], search: [], training: [], other: [] };\n for (const t of agentUaList) out[AGENT_INTENTS[t] ?? 'other'].push(t);\n return out;\n}\n\nexport function detectDeviceClass(userAgent: string): string {\n const s = userAgent.toLowerCase();\n if (/ipad|tablet|playbook|kindle|silk/.test(s)) return 'tablet';\n if (/mobi|iphone|ipod|android.*mobile|phone/.test(s)) return 'mobile';\n return 'desktop';\n}\n\nexport function detectTrafficSource(referrer: string, appOrigin?: string): string {\n if (!referrer) return 'direct';\n try {\n const refUrl = new URL(referrer);\n if (appOrigin) {\n try {\n if (new URL(appOrigin).host === refUrl.host) return 'direct';\n } catch {\n /* ignore invalid appOrigin */\n }\n }\n const host = refUrl.hostname.toLowerCase();\n if (/(^|\\.)(google|bing|duckduckgo|yahoo)\\./.test(host)) return 'search';\n // Anchor to the registrable domain (exact host or a subdomain of it) so\n // hosts like `x.company.com`, `t.company.io` or `linkedinsights.com` are not\n // misclassified as social by an unbounded substring match.\n if (/(^|\\.)(twitter\\.com|x\\.com|facebook\\.com|linkedin\\.com|reddit\\.com|t\\.co)$/.test(host)) return 'social';\n return 'referral';\n } catch {\n return 'direct';\n }\n}\n\nexport function referrerDomainFromReferer(referrer: string): string | null {\n if (!referrer) return null;\n try {\n return new URL(referrer).hostname;\n } catch {\n return null;\n }\n}\n\n/**\n * Ad-platform click-ID query params worth keeping. An ALLOWLIST, unlike the\n * `utm_` prefix match: unknown query keys here are unbounded-cardinality junk\n * (session tokens, cache busters) that would bloat the sessions table, so only\n * the IDs the major ad platforms actually append survive.\n *\n * gclid / gbraid / wbraid — Google Ads auto-tagging (search, YouTube, Display;\n * gbraid/wbraid are the iOS-14 privacy variants)\n * fbclid — Meta (Facebook + Instagram). Appended to EVERY outbound Meta\n * click, paid and organic alike — it identifies the platform, never spend.\n * ttclid — TikTok Ads\n * msclkid — Microsoft Ads (Bing)\n * twclid — X/Twitter Ads\n * li_fat_id — LinkedIn Ads\n */\nexport const CLICK_ID_KEYS: readonly string[] = [\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'fbclid',\n 'ttclid',\n 'msclkid',\n 'twclid',\n 'li_fat_id',\n];\n\n/**\n * Splits a URL query into the attribution params the session upsert carries:\n * every `utm_`-prefixed key, plus allowlisted ad click IDs (CLICK_ID_KEYS).\n * Accepts a raw search string (\"?a=b\" or \"a=b\"), a URLSearchParams, or a\n * Next.js `searchParams` object (whose values may be string arrays — the\n * first occurrence wins, matching URLSearchParams iteration order).\n * Node-safe: no DOM APIs.\n */\nexport function extractTrackedParams(\n search: string | URLSearchParams | Record<string, string | string[] | undefined>,\n): { utmParams: Record<string, string>; clickIds: Record<string, string> } {\n const utmParams: Record<string, string> = {};\n const clickIds: Record<string, string> = {};\n try {\n const entries: Iterable<[string, string]> =\n typeof search === 'string' || search instanceof URLSearchParams\n ? new URLSearchParams(search)\n : Object.entries(search).flatMap(([k, v]): Array<[string, string]> => {\n const first = Array.isArray(v) ? v[0] : v;\n return first === undefined ? [] : [[k, first]];\n });\n for (const [k, v] of entries) {\n // First occurrence wins for duplicates — a repeated gclid in a mangled\n // URL must not let the later value silently replace the real one.\n if (k.startsWith('utm_')) {\n if (!(k in utmParams)) utmParams[k] = v;\n } else if (CLICK_ID_KEYS.includes(k)) {\n if (!(k in clickIds)) clickIds[k] = v;\n }\n }\n } catch {\n /* malformed input → empty attribution, never a throw at init() */\n }\n return { utmParams, clickIds };\n}\n\nexport function detectTimeOfDay(d: Date): string {\n const h = d.getHours();\n if (h < 6) return 'night';\n if (h < 12) return 'morning';\n if (h < 18) return 'afternoon';\n return 'evening';\n}\n\nexport type SessionUpsertPayload = {\n sessionId: string;\n ephemeral: boolean;\n utmParams: Record<string, string>;\n /** Allowlisted ad-platform click IDs from the landing URL (CLICK_ID_KEYS). */\n clickIds: Record<string, string>;\n deviceClass: string;\n trafficSource: string;\n referrerDomain: string | null;\n timeOfDay: string;\n dayOfWeek: string;\n /**\n * True when this session is likely driven by automation — either\n * `navigator.webdriver` was set, or the user-agent carried a known agent\n * token. Probabilistic: a flag for metrics + bandit exclusion, never a gate.\n */\n automation: boolean;\n};\n\n/** Bandit segment key: `<device_class>:<traffic_source>`. */\nexport function deriveSessionSegment(opts?: {\n userAgent?: string;\n referer?: string;\n appOrigin?: string;\n}): string {\n const body = buildSessionUpsertPayload('__segment__', opts);\n return `${body.deviceClass}:${body.trafficSource}`;\n}\n\n/**\n * Builds a session upsert body aligned with the browser SDK so SSR assign uses\n * the same segment key (`device:source`) as the client after hydration.\n */\nexport function buildSessionUpsertPayload(\n sessionId: string,\n opts?: {\n userAgent?: string;\n referer?: string;\n appOrigin?: string;\n utmParams?: Record<string, string>;\n clickIds?: Record<string, string>;\n now?: Date;\n /** `navigator.webdriver` value from the browser, when available. */\n webdriver?: boolean;\n },\n): SessionUpsertPayload {\n const ua = opts?.userAgent?.trim() ?? '';\n const referer = opts?.referer?.trim() ?? '';\n const now = opts?.now ?? new Date();\n return {\n sessionId,\n ephemeral: false,\n utmParams: opts?.utmParams ?? {},\n clickIds: opts?.clickIds ?? {},\n deviceClass: ua ? detectDeviceClass(ua) : 'desktop',\n trafficSource: referer\n ? detectTrafficSource(referer, opts?.appOrigin)\n : 'direct',\n referrerDomain: referrerDomainFromReferer(referer),\n timeOfDay: detectTimeOfDay(now),\n dayOfWeek: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][now.getDay()] ?? 'sun',\n automation: opts?.webdriver === true || uaTokenMatch(ua),\n };\n}\n","/**\n * Slot declaration helpers shared by the browser client (decide) and the\n * server preload path. Pure wrappers over @sentientui/policy.\n */\nimport {\n canonicalArm,\n slotBaselineArm,\n slotResultFor,\n type SlotDecl,\n type SlotResult,\n} from '@sentientui/policy';\n\n/** SDK-facing slot declaration. `dims` accepts readonly arrays (`as const`). */\nexport type SlotDeclInput = {\n id: string;\n arms?: string[];\n dims?: Record<string, readonly string[]>;\n baseline?: string | Record<string, string>;\n};\n\nexport type { SlotResult };\n\n/**\n * Whitelists the wire fields of a slot declaration. Anything an SDK layer\n * attached (goal configs, refs, …) is stripped so it never reaches the zod\n * schema on the API. Also normalizes readonly arrays to mutable ones.\n */\nexport function toWireSlot(d: SlotDeclInput): SlotDecl {\n return {\n id: d.id,\n ...(d.arms ? { arms: [...d.arms] } : {}),\n ...(d.dims\n ? {\n dims: Object.fromEntries(\n Object.entries(d.dims).map(([dim, values]) => [dim, [...values]]),\n ),\n }\n : {}),\n ...(d.baseline !== undefined ? { baseline: d.baseline } : {}),\n };\n}\n\n/** The declared (or default first-declared) baseline result for a slot. */\nexport function baselineResultFor(d: SlotDeclInput): SlotResult {\n const decl = toWireSlot(d);\n return slotResultFor(decl, slotBaselineArm(decl));\n}\n\n/** Baseline results for a whole declaration list, keyed by slot id. */\nexport function baselineSlots(decls: SlotDeclInput[]): Record<string, SlotResult> {\n const out: Record<string, SlotResult> = {};\n for (const d of decls) out[d.id] = baselineResultFor(d);\n return out;\n}\n\n/**\n * Canonical arm string of a slot result: dims results encode as sorted\n * `dim=value` pairs joined with '|'; arms results are the arm id verbatim.\n */\nexport function armOfResult(result: SlotResult): string {\n return typeof result === 'string' ? result : canonicalArm(result);\n}\n"],"mappings":"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","names":["storageSuffix","apiKey","LEGACY_SESSION_COOKIE_NAME","sessionCookieName","agentUaList","uaTokenMatch","userAgent","matchedAgentToken","_a","s","token","AGENT_INTENTS","agentIntent","botName","hit","t","classifiedAgents","out","detectDeviceClass","detectTrafficSource","referrer","appOrigin","refUrl","e","host","referrerDomainFromReferer","CLICK_ID_KEYS","extractTrackedParams","search","utmParams","clickIds","entries","k","v","first","detectTimeOfDay","d","h","deriveSessionSegment","opts","body","buildSessionUpsertPayload","sessionId","_b","_c","_d","_e","_f","_g","_h","ua","referer","now","canonicalArm","slotBaselineArm","slotResultFor","toWireSlot","d","__spreadValues","dim","values","baselineResultFor","decl","slotResultFor","slotBaselineArm","baselineSlots","decls","out","armOfResult","result","canonicalArm"]}
@@ -0,0 +1,2 @@
1
+ import{a as c}from"./chunk-TMCGHANO.mjs";var d=["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"],p={banner:"hero",navigation:"navigation",contentinfo:"footer"};function g(t){let e=t.ariaRole?p[t.ariaRole.toLowerCase()]:void 0;if(e)return e;if(t.tag==="nav")return"navigation";if(t.tag==="footer")return"footer";if(t.tag==="header")return"hero";let r=`${t.idClass} ${t.headingText}`.toLowerCase();return/\b(navbar|nav-bar|navigation|site-nav|main-nav|topbar|footer)\b/.test(r)?/footer/.test(r)?"footer":"navigation":/\b(hero|masthead|jumbotron)\b/i.test(t.idClass)?"hero":null}function b(t){return t.actionCount>=1&&t.textLength>0&&t.textLength<200?"cta":"generic"}var l=[["pricing",/\b(pricing|price list|per month|\/mo|subscriptions?)\b|\bplans?\b(?=[^.]{0,40}(from|start|month|year|[$€£]))/i],["faq",/\bfaq\b|frequently asked|common questions?/i],["comparison",/\b(compare|comparison|versus)\b|\bvs\./i],["social_proof",/\b(reviews?|ratings?|testimonial|brands?|galler(y|ies)|logos)\b|trusted by|loved by|case stud|what our customers say/i],["trust",/\b(insurance|warrant(y|ies)|guarantees?|certifi|accredit|security|privacy|compliance|gdpr|encrypt)\b|why choose|about us|our team/i],["cta",/\b(book|booking|reserve|appointments?|newsletter|subscribe)\b|contact us|get in touch|opening hours/i],["features",/\b(features?|benefits?|capabilit|services?|repairs?|menus?|products?)\b|how it works|our process|what we (do|offer)|what you get/i]],m=[["pricing",/(?:[$€£]\s?\d[\d,.]*\s*(?:\/|per\s)\s*(?:mo|month|yr|year|seat|user))|(?:\b(?:starter|basic|pro|growth|premium|enterprise)\b[^.]{0,60}[$€£]\s?\d)/i],["social_proof",/(?:★{2,})|(?:\b\d(?:\.\d)?\s*(?:out of|\/)\s*5\b)|(?:\brated\b)|(?:["“][^"”]{20,160}["”]\s*[—–-]\s*[A-Z][a-z]+)/],["trust",/\b(?:money[- ]back guarantee|free returns?|returns? within|refund(?:s)? within|encrypted|soc ?2|iso ?27001|gdpr[- ]compliant|cancel anytime)\b/i],["comparison",/\b(?:vs|versus)\b\.?[^.!?]{0,80}\b(?:compare|comparison|plans?|features?|alternative)\b|\bhow (?:we|it) compares?\b/i]],u={navigation:"navigation",footer:"navigation",hero:"hero",cta:"cta",generic:"generic"};function y(t){var r;let e=t.querySelector("h1, h2, h3");return((r=e==null?void 0:e.textContent)!=null?r:"").slice(0,160)}function f(t){var n,s;let e=g(t);if(e)return{type:(n=u[e])!=null?n:"generic",strength:"strong"};let r=`${t.idClass} ${t.headingText}`.toLowerCase();for(let[i,a]of l)if(a.test(r))return{type:i,strength:"strong"};for(let[i,a]of m)if(a.test(t.bodyText))return{type:i,strength:"strong"};let o=b(t);return{type:(s=u[o])!=null?s:"generic",strength:"weak"}}function h(t){var o,n;let e=((o=t.textContent)!=null?o:"").replace(/\s+/g," ").trim(),r=t.getAttribute("role");return c({tag:t.tagName.toLowerCase(),idClass:`${t.id} ${String((n=t.className)!=null?n:"")}`,headingText:y(t),bodyText:e.slice(0,2e3),actionCount:t.querySelectorAll('a, button, [role="button"]').length,textLength:e.length},r?{ariaRole:r}:{})}function T(t){return f(h(t)).type}export{d as a,g as b,b as c,f as d,h as e,T as f};
2
+ //# sourceMappingURL=chunk-EWP6FTHE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engagement/classify.ts"],"sourcesContent":["// Semantic section classification for no-code section capture (Phase 3 §2.4).\n// Pure heuristic: element → one of the graph_nodes semantic_type enum. Mirrors\n// the SDK graph scanner's vocabulary so the persona × section matrix consumes\n// snippet-captured sections unchanged.\n//\n// SPLIT (Phase 2b, spec 2026-09-04). This module is the BROWSER-SAFE core:\n// structural rules, the small parent-level keyword table, and the fallbacks.\n// The rich ~40-topic vocabulary lives in ./topics.ts, which only the server\n// imports — shipping it here cost 1.5 KB gzip in every bundle (7% of the\n// always-on snippet) for a layer the browser never reads, since classifySection\n// returns only the parent.\n//\n// Both paths share structuralTopicOf/fallbackTopicOf, so the three fixes below\n// apply identically on client and server; only vocabulary richness differs.\n//\n// Fixes, each reproduced against the shipped classifier before being changed:\n// 1. structural before the converter fallback — `<div class=\"navbar\">` used\n// to become `cta`, because `navigation` was reachable only via tag\n// nav/footer.\n// 2. hero before the converter fallback — the cta rule sat above both hero\n// rules, so a `<header>` with a button and <200 chars could never be hero.\n// 3. tightened pricing/social keywords — `plans?` and `customers?` fired on\n// unrelated copy AND were `strong`, so they auto-applied at confidence 0.9\n// and were never sent to the LLM fallback.\n\nexport type SemanticType =\n | 'pricing' | 'hero' | 'social_proof' | 'cta' | 'features'\n | 'faq' | 'comparison' | 'trust' | 'navigation' | 'generic';\n\nexport type SectionRole = 'converter' | 'persuader' | 'structural';\n\n/** Canonical vocabulary — mirrors the graph_nodes semantic_type CHECK enum. */\nexport const SEMANTIC_TYPES: readonly SemanticType[] = [\n 'pricing', 'hero', 'social_proof', 'cta', 'features',\n 'faq', 'comparison', 'trust', 'navigation', 'generic',\n] as const;\n\nexport type TopicRule = { topic: string; parent: SemanticType; role: SectionRole };\n\n/** Environment-agnostic section features — buildable from a browser Element or\n * a server-parsed node (node-html-parser). */\nexport type SectionFeatures = {\n tag: string; // lowercase tag name\n idClass: string; // `${id} ${className}`\n headingText: string;\n bodyText: string; // normalized text content, first 2000 chars\n actionCount: number;\n textLength: number;\n /** ARIA landmark role, when the element declares one. Optional so every\n * existing caller keeps compiling; a page that uses landmarks gives a\n * high-precision signal for free, which the old classifier ignored — it\n * tested membership of SEMANTIC_TYPES, so only role=\"navigation\" ever hit\n * and role=\"banner\"/\"contentinfo\" were discarded. */\n ariaRole?: string;\n /** schema.org `@type` values found in `<script type=\"application/ld+json\">`\n * INSIDE this section. Highest-precision signal available and free to\n * collect — the crawler already has the HTML. Type-only here; the\n * `@type` → topic table is server-side in ./topics.ts, since the browser\n * never reads the topic layer and the snippet has ~200 bytes of margin. */\n structuredTypes?: string[];\n};\n\n// ARIA landmark → topic. Structural facts, not guesses.\nconst ARIA_TOPIC: Record<string, string> = {\n banner: 'hero',\n navigation: 'navigation',\n contentinfo: 'footer',\n};\n\n/**\n * Structural identification, shared by the browser and server classifiers.\n * Returns a topic name, or null when the section is not structural furniture.\n * Everything matched here is definitive (tag or authored marker), so callers\n * treat it as `strong`.\n */\nexport function structuralTopicOf(f: SectionFeatures): string | null {\n const aria = f.ariaRole ? ARIA_TOPIC[f.ariaRole.toLowerCase()] : undefined;\n if (aria) return aria;\n if (f.tag === 'nav') return 'navigation';\n if (f.tag === 'footer') return 'footer';\n // A page-level <header> IS the banner landmark (HTML-AAM maps it to\n // role=\"banner\", which this function already treats as hero), so it is a\n // structural fact rather than a keyword guess. Without this, a header whose\n // headline happens to contain a content word loses to the keyword table:\n // \"We build brands that move\" scored social_proof and \"Winter collection\"\n // scored features, purely on words inside the hero copy.\n if (f.tag === 'header') return 'hero';\n const hay = `${f.idClass} ${f.headingText}`.toLowerCase();\n if (/\\b(navbar|nav-bar|navigation|site-nav|main-nav|topbar|footer)\\b/.test(hay)) {\n return /footer/.test(hay) ? 'footer' : 'navigation';\n }\n // Explicit authoring marker beats any inferred keyword, and is matched on\n // idClass ONLY: a `<header class=\"hero\">` headlined \"Expert Car Repair\" is a\n // hero, not a services section — but matching \"hero\" in heading text would\n // also catch \"Hero of the story\".\n if (/\\b(hero|masthead|jumbotron)\\b/i.test(f.idClass)) return 'hero';\n return null;\n}\n\n/**\n * Last-resort classification once no keyword or content evidence matched.\n * Hero is checked BEFORE the converter fallback — fix 2 above.\n */\nexport function fallbackTopicOf(f: SectionFeatures): string {\n // `tag === 'header'` is handled in structuralTopicOf, which runs first.\n if (f.actionCount >= 1 && f.textLength > 0 && f.textLength < 200) return 'cta';\n return 'generic';\n}\n\n// Parent-level keyword table for the BROWSER path. Deliberately close to the\n// original size — the rich topic vocabulary is in ./topics.ts. `plans?` now\n// requires adjacent pricing context, and bare `customers?` is gone (it fired on\n// navigation furniture like a \"Customer Service\" footer block).\nconst KEYWORDS: Array<[SemanticType, RegExp]> = [\n ['pricing', /\\b(pricing|price list|per month|\\/mo|subscriptions?)\\b|\\bplans?\\b(?=[^.]{0,40}(from|start|month|year|[$€£]))/i],\n ['faq', /\\bfaq\\b|frequently asked|common questions?/i],\n ['comparison', /\\b(compare|comparison|versus)\\b|\\bvs\\./i],\n ['social_proof', /\\b(reviews?|ratings?|testimonial|brands?|galler(y|ies)|logos)\\b|trusted by|loved by|case stud|what our customers say/i],\n ['trust', /\\b(insurance|warrant(y|ies)|guarantees?|certifi|accredit|security|privacy|compliance|gdpr|encrypt)\\b|why choose|about us|our team/i],\n ['cta', /\\b(book|booking|reserve|appointments?|newsletter|subscribe)\\b|contact us|get in touch|opening hours/i],\n ['features', /\\b(features?|benefits?|capabilit|services?|repairs?|menus?|products?)\\b|how it works|our process|what we (do|offer)|what you get/i],\n];\n\n// Content-evidence patterns — run against bodyText when the heading gave us\n// nothing. Deliberately conservative: pricing needs per-period/plan context next\n// to money so an article mentioning \"$5 million\" stays generic.\nexport const CONTENT_PATTERNS: Array<[SemanticType, RegExp]> = [\n ['pricing', /(?:[$€£]\\s?\\d[\\d,.]*\\s*(?:\\/|per\\s)\\s*(?:mo|month|yr|year|seat|user))|(?:\\b(?:starter|basic|pro|growth|premium|enterprise)\\b[^.]{0,60}[$€£]\\s?\\d)/i],\n ['social_proof', /(?:★{2,})|(?:\\b\\d(?:\\.\\d)?\\s*(?:out of|\\/)\\s*5\\b)|(?:\\brated\\b)|(?:[\"“][^\"”]{20,160}[\"”]\\s*[—–-]\\s*[A-Z][a-z]+)/],\n ['trust', /\\b(?:money[- ]back guarantee|free returns?|returns? within|refund(?:s)? within|encrypted|soc ?2|iso ?27001|gdpr[- ]compliant|cancel anytime)\\b/i],\n ['comparison', /\\b(?:vs|versus)\\b\\.?[^.!?]{0,80}\\b(?:compare|comparison|plans?|features?|alternative)\\b|\\bhow (?:we|it) compares?\\b/i],\n];\n\n/** Parent for the handful of topics the shared structural/fallback helpers\n * emit. The server maps the full vocabulary via CLASSIFIER_TOPICS instead. */\nconst SHARED_TOPIC_PARENT: Record<string, SemanticType> = {\n navigation: 'navigation',\n footer: 'navigation',\n hero: 'hero',\n cta: 'cta',\n generic: 'generic',\n};\n\nfunction headingText(el: Element): string {\n const h = el.querySelector('h1, h2, h3');\n return (h?.textContent ?? '').slice(0, 160);\n}\n\n/**\n * Pure classification over extracted features. `strong` = keyword, content, or\n * structural evidence (trustable enough to auto-apply); `weak` = a fallback\n * guess (hero/cta/generic — capture-worthy but not persona evidence).\n */\nexport function classifyFeatures(f: SectionFeatures): { type: SemanticType; strength: 'strong' | 'weak' } {\n const structural = structuralTopicOf(f);\n if (structural) return { type: SHARED_TOPIC_PARENT[structural] ?? 'generic', strength: 'strong' };\n\n const hay = `${f.idClass} ${f.headingText}`.toLowerCase();\n for (const [type, re] of KEYWORDS) if (re.test(hay)) return { type, strength: 'strong' };\n for (const [type, re] of CONTENT_PATTERNS) if (re.test(f.bodyText)) return { type, strength: 'strong' };\n\n const fb = fallbackTopicOf(f);\n return { type: SHARED_TOPIC_PARENT[fb] ?? 'generic', strength: 'weak' };\n}\n\n/** Feature extraction from a live DOM element (browser paths). */\nexport function featuresFromElement(el: Element): SectionFeatures {\n const text = (el.textContent ?? '').replace(/\\s+/g, ' ').trim();\n const role = el.getAttribute('role');\n return {\n tag: el.tagName.toLowerCase(),\n idClass: `${el.id} ${String(el.className ?? '')}`,\n headingText: headingText(el),\n bodyText: text.slice(0, 2000),\n actionCount: el.querySelectorAll('a, button, [role=\"button\"]').length,\n textLength: text.length,\n ...(role ? { ariaRole: role } : {}),\n };\n}\n\n/** Classify a page section into a semantic type (never null — falls back to\n * 'generic' so the caller can still capture attention on it). */\nexport function classifySection(el: Element): SemanticType {\n return classifyFeatures(featuresFromElement(el)).type;\n}\n"],"mappings":"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","names":["SEMANTIC_TYPES","ARIA_TOPIC","structuralTopicOf","f","aria","hay","fallbackTopicOf","KEYWORDS","CONTENT_PATTERNS","SHARED_TOPIC_PARENT","headingText","el","_a","h","classifyFeatures","_b","structural","type","re","fb","featuresFromElement","text","role","__spreadValues","classifySection"]}
@@ -0,0 +1,2 @@
1
+ var E=["data-testid","data-test","data-id","data-name","data-cy"];function f(t){var n;return((n=t.textContent)!=null?n:"").replace(/\s+/g," ").trim()}function $(t){return{tag:t.tagName.toLowerCase(),text:f(t).slice(0,40)}}function m(t){return t.replace(/["\\\]]/g,"\\$&")}function u(t,n){try{return t.querySelectorAll(n).length===1}catch(e){return!1}}function p(t,n){var a;let e=t.tagName.toLowerCase();if(!e)return null;let i=((a=t.getAttribute("class"))!=null?a:"").split(/\s+/).filter(r=>/^[a-zA-Z][\w-]*$/.test(r)),c=[e,...i.map(r=>`${e}.${r}`)];for(let r of c)if(u(n,r))return r;let s=t.parentElement;if(s&&s!==n){let r=p(s,n);if(r){for(let o of c){let g=`${r} > ${o}`;if(u(n,g))return g}let l=Array.from(s.children).filter(o=>o.tagName.toLowerCase()===e),d=l.indexOf(t),A=l.some(o=>o!==t&&f(o)!==f(t));if(d>=0&&A){let o=`${r} > ${e}:nth-of-type(${d+1})`;if(u(n,o))return o}}}return null}function N(t,n){let e=$(t),i=t.getAttribute("id");if(i&&u(n,`#${m(i)}`))return{v:1,id:i,fingerprint:e};for(let s of E){let a=t.getAttribute(s);if(a&&u(n,`[${s}="${m(a)}"]`))return{v:1,dataAttr:{name:s,value:a},fingerprint:e}}let c=p(t,n);return c?{v:1,selector:c,fingerprint:e}:null}export{N as a};
2
+ //# sourceMappingURL=chunk-KIP52DUJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/locator-from-dom.ts"],"sourcesContent":["import type { CompoundLocator } from './snapshot.js';\n\n// Live-DOM twin of apps/api/src/domain/locator-from-html.ts. The two MUST stay\n// in step: section_key is a hash of this object, so any divergence silently\n// splits one physical section into two identities — a crawl-derived one and a\n// client-derived one — and every per-section number downstream halves.\n// Cross-implementation parity is locked by apps/api/src/domain/locator-parity.test.ts.\nconst STABLE_DATA_ATTRS = ['data-testid', 'data-test', 'data-id', 'data-name', 'data-cy'];\nconst FINGERPRINT_TEXT_MAX = 40;\n\nfunction normalizedText(el: Element): string {\n return (el.textContent ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction fingerprintOf(el: Element): { tag: string; text: string } {\n return {\n tag: el.tagName.toLowerCase(),\n text: normalizedText(el).slice(0, FINGERPRINT_TEXT_MAX),\n };\n}\n\nfunction cssEscape(v: string): string {\n return v.replace(/[\"\\\\\\]]/g, '\\\\$&');\n}\n\nfunction unique(root: ParentNode, selector: string): boolean {\n try {\n return root.querySelectorAll(selector).length === 1;\n } catch {\n return false;\n }\n}\n\n/** Shortest unique selector: tag, tag.class, then parent-qualified, then nth-of-type chain. */\nfunction uniqueSelector(el: Element, root: ParentNode): string | null {\n const tag = el.tagName.toLowerCase();\n if (!tag) return null;\n const classes = (el.getAttribute('class') ?? '').split(/\\s+/).filter((c) => /^[a-zA-Z][\\w-]*$/.test(c));\n const candidates = [tag, ...classes.map((c) => `${tag}.${c}`)];\n for (const c of candidates) if (unique(root, c)) return c;\n const parent = el.parentElement;\n if (parent && (parent as ParentNode) !== root) {\n const parentSel = uniqueSelector(parent, root);\n if (parentSel) {\n for (const c of candidates) {\n const combined = `${parentSel} > ${c}`;\n if (unique(root, combined)) return combined;\n }\n // Element-only children: matches the server's rawTagName filter over\n // childNodes, which excludes text nodes.\n const siblings = Array.from(parent.children).filter((n) => n.tagName.toLowerCase() === tag);\n const idx = siblings.indexOf(el);\n // An nth-of-type selector is only trustworthy when it pairs with a\n // fingerprint that could actually catch drift: if every same-tag sibling\n // has identical text, the node is a true duplicate and the {tag, text}\n // check can never distinguish \"still the right one\" from \"DOM reordered,\n // now pointing at the wrong duplicate\". Refuse it rather than return a\n // false sense of precision.\n const distinguishable = siblings.some((s) => s !== el && normalizedText(s) !== normalizedText(el));\n if (idx >= 0 && distinguishable) {\n const nth = `${parentSel} > ${tag}:nth-of-type(${idx + 1})`;\n if (unique(root, nth)) return nth;\n }\n }\n }\n return null;\n}\n\n/** Build a compound locator for a live DOM element. Returns null when nothing\n * resolves uniquely — the runtime never guesses an identity. */\nexport function locatorFromElement(el: Element, root: ParentNode): CompoundLocator | null {\n const fingerprint = fingerprintOf(el);\n const id = el.getAttribute('id');\n if (id && unique(root, `#${cssEscape(id)}`)) return { v: 1, id, fingerprint };\n for (const name of STABLE_DATA_ATTRS) {\n const value = el.getAttribute(name);\n if (value && unique(root, `[${name}=\"${cssEscape(value)}\"]`)) {\n return { v: 1, dataAttr: { name, value }, fingerprint };\n }\n }\n const selector = uniqueSelector(el, root);\n if (selector) return { v: 1, selector, fingerprint };\n return null;\n}\n"],"mappings":"AAOA,IAAMA,EAAoB,CAAC,cAAe,YAAa,UAAW,YAAa,SAAS,EAGxF,SAASC,EAAeC,EAAqB,CAV7C,IAAAC,EAWE,QAAQA,EAAAD,EAAG,cAAH,KAAAC,EAAkB,IAAI,QAAQ,OAAQ,GAAG,EAAE,KAAK,CAC1D,CAEA,SAASC,EAAcF,EAA4C,CACjE,MAAO,CACL,IAAKA,EAAG,QAAQ,YAAY,EAC5B,KAAMD,EAAeC,CAAE,EAAE,MAAM,EAAG,EAAoB,CACxD,CACF,CAEA,SAASG,EAAUC,EAAmB,CACpC,OAAOA,EAAE,QAAQ,WAAY,MAAM,CACrC,CAEA,SAASC,EAAOC,EAAkBC,EAA2B,CAC3D,GAAI,CACF,OAAOD,EAAK,iBAAiBC,CAAQ,EAAE,SAAW,CACpD,OAAQ,GACN,MAAO,EACT,CACF,CAGA,SAASC,EAAeR,EAAaM,EAAiC,CAlCtE,IAAAL,EAmCE,IAAMQ,EAAMT,EAAG,QAAQ,YAAY,EACnC,GAAI,CAACS,EAAK,OAAO,KACjB,IAAMC,IAAWT,EAAAD,EAAG,aAAa,OAAO,IAAvB,KAAAC,EAA4B,IAAI,MAAM,KAAK,EAAE,OAAQU,GAAM,mBAAmB,KAAKA,CAAC,CAAC,EAChGC,EAAa,CAACH,EAAK,GAAGC,EAAQ,IAAKC,GAAM,GAAGF,CAAG,IAAIE,CAAC,EAAE,CAAC,EAC7D,QAAWA,KAAKC,EAAY,GAAIP,EAAOC,EAAMK,CAAC,EAAG,OAAOA,EACxD,IAAME,EAASb,EAAG,cAClB,GAAIa,GAAWA,IAA0BP,EAAM,CAC7C,IAAMQ,EAAYN,EAAeK,EAAQP,CAAI,EAC7C,GAAIQ,EAAW,CACb,QAAWH,KAAKC,EAAY,CAC1B,IAAMG,EAAW,GAAGD,CAAS,MAAMH,CAAC,GACpC,GAAIN,EAAOC,EAAMS,CAAQ,EAAG,OAAOA,CACrC,CAGA,IAAMC,EAAW,MAAM,KAAKH,EAAO,QAAQ,EAAE,OAAQI,GAAMA,EAAE,QAAQ,YAAY,IAAMR,CAAG,EACpFS,EAAMF,EAAS,QAAQhB,CAAE,EAOzBmB,EAAkBH,EAAS,KAAMI,GAAMA,IAAMpB,GAAMD,EAAeqB,CAAC,IAAMrB,EAAeC,CAAE,CAAC,EACjG,GAAIkB,GAAO,GAAKC,EAAiB,CAC/B,IAAME,EAAM,GAAGP,CAAS,MAAML,CAAG,gBAAgBS,EAAM,CAAC,IACxD,GAAIb,EAAOC,EAAMe,CAAG,EAAG,OAAOA,CAChC,CACF,CACF,CACA,OAAO,IACT,CAIO,SAASC,EAAmBtB,EAAaM,EAA0C,CACxF,IAAMiB,EAAcrB,EAAcF,CAAE,EAC9BwB,EAAKxB,EAAG,aAAa,IAAI,EAC/B,GAAIwB,GAAMnB,EAAOC,EAAM,IAAIH,EAAUqB,CAAE,CAAC,EAAE,EAAG,MAAO,CAAE,EAAG,EAAG,GAAAA,EAAI,YAAAD,CAAY,EAC5E,QAAWE,KAAQC,EAAmB,CACpC,IAAMC,EAAQ3B,EAAG,aAAayB,CAAI,EAClC,GAAIE,GAAStB,EAAOC,EAAM,IAAImB,CAAI,KAAKtB,EAAUwB,CAAK,CAAC,IAAI,EACzD,MAAO,CAAE,EAAG,EAAG,SAAU,CAAE,KAAAF,EAAM,MAAAE,CAAM,EAAG,YAAAJ,CAAY,CAE1D,CACA,IAAMhB,EAAWC,EAAeR,EAAIM,CAAI,EACxC,OAAIC,EAAiB,CAAE,EAAG,EAAG,SAAAA,EAAU,YAAAgB,CAAY,EAC5C,IACT","names":["STABLE_DATA_ATTRS","normalizedText","el","_a","fingerprintOf","cssEscape","v","unique","root","selector","uniqueSelector","tag","classes","c","candidates","parent","parentSel","combined","siblings","n","idx","distinguishable","s","nth","locatorFromElement","fingerprint","id","name","STABLE_DATA_ATTRS","value"]}
@@ -0,0 +1,2 @@
1
+ import{a as fe,c as Ee,e as Ie,j as _e,k as Ce,l as Te,n as Ae,o as Oe,r as Re,s as me,u as Be}from"./chunk-2NVSFI4V.mjs";import{a as I,b as se}from"./chunk-TMCGHANO.mjs";function ye(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}try{if(typeof crypto!="undefined"&&typeof crypto.getRandomValues=="function"){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let n="";for(let s=0;s<16;s++)n+=e[s].toString(16).padStart(2,"0"),(s===3||s===5||s===7||s===9)&&(n+="-");return n}}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let n=Math.random()*16|0;return(e==="x"?n:n&3|8).toString(16)})}var st="_snt_uid",rt=365,he="_snt_uid";function it(){return ye()}function We(e){try{let n=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return n?decodeURIComponent(n[1]):null}catch(n){return null}}function at(e,n,s){try{document.cookie=`${e}=${encodeURIComponent(n)}; max-age=${s}; SameSite=strict; path=/`}catch(u){}}function Le(e){try{return localStorage.getItem(e)}catch(n){return null}}function je(e,n){try{return localStorage.setItem(e,n),!0}catch(s){return!1}}function He(e){try{return sessionStorage.getItem(e)}catch(n){return null}}function lt(e,n){try{return sessionStorage.setItem(e,n),!0}catch(s){return!1}}function ct(e){try{sessionStorage.removeItem(e)}catch(n){}}function dt(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(n){return!1}}function ut(e){try{localStorage.removeItem(e)}catch(n){}}function pt(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(n){}}var gt={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Se(e){var b,A,R,E,G,F,_;if(typeof window=="undefined")return gt;let n=fe(e==null?void 0:e.apiKey),s=(b=e==null?void 0:e.cookieName)!=null?b:Ee(e==null?void 0:e.apiKey),u=`${he}${n}`,f=`${he}_tomb${n}`,l=((A=e==null?void 0:e.cookieTTLDays)!=null?A:rt)*24*60*60,i=w=>w&&w.length>0?w:null,d=()=>{var w,L;return n&&!(e!=null&&e.cookieName)&&Le(f)===null?(L=(w=i(We(st)))!=null?w:i(Le(he)))!=null?L:i(He(he)):null},r=(_=(F=(G=(E=(R=i(We(s)))!=null?R:i(Le(u)))!=null?E:i(He(u)))!=null?G:d())!=null?F:i(e==null?void 0:e.ssrSessionId))!=null?_:it();at(s,r,l);let t=je(u,r),o=dt(s),y=t?!1:lt(u,r),S=!t&&!o&&!y;return{getSessionId:()=>r,isEphemeral:()=>S,destroy:()=>{r=null,pt(s),ut(u),ct(u),n&&!(e!=null&&e.cookieName)&&je(f,"1")}}}function X(e){return Math.min(6e4,1e3*2**Math.min(e,6))}function re(e){if(e.ok===!0)return"delivered";let{status:n}=e;return typeof n!="number"?"retry":n>=200&&n<300?"delivered":n>=400&&n<500&&n!==429?"dropped":"retry"}function ve(e,n){try{let s=localStorage.getItem(e);if(!s)return[];let u=JSON.parse(s);return Array.isArray(u)?(localStorage.removeItem(e),u.slice(-n)):[]}catch(s){return[]}}function Y(e,n,s){try{let u=(()=>{try{let a=localStorage.getItem(s);if(!a)return[];let l=JSON.parse(a);return Array.isArray(l)?l:[]}catch(a){return[]}})(),f=new Map;for(let a of u)f.set(a.id,a);for(let a of e)f.set(a.id,a);localStorage.setItem(s,JSON.stringify([...f.values()].slice(-n)))}catch(u){}}function we(e,n){try{let s=localStorage.getItem(n);if(!s)return;let u=JSON.parse(s);if(!Array.isArray(u))return;let f=new Set(e),a=u.filter(l=>!f.has(l.id));if(a.length===u.length)return;a.length===0?localStorage.removeItem(n):localStorage.setItem(n,JSON.stringify(a))}catch(s){}}var ft=500,mt=56*1024;function Pe(e){return`_snt_retry_${e.slice(0,12)}`}var yt={push:()=>{},flush:()=>{},destroy:()=>{}};function Qe(e){var q,K,te;if(typeof window=="undefined")return yt;let n=(q=e.flushIntervalMs)!=null?q:5e3,s=(K=e.maxBatchSize)!=null?K:20,u=(te=e.maxRetrySize)!=null?te:100,f=e.ingestUrl,a=e.apiKey,l=Pe(a),i=[],d=new Set,r=[],t=g=>{for(let k of g)o.delete(k),!d.has(k)&&(d.add(k),r.push(k));for(;r.length>ft;){let k=r.shift();k&&d.delete(k)}we(g,l)},o=new Set,y=()=>{for(;i.length>u;){let g=i.shift();g&&o.delete(g.id)}},S=g=>{d.has(g.id)||o.has(g.id)||(o.add(g.id),i.push(g),y())},b=g=>{for(let k of g)d.has(k.id)||(o.add(k.id),i.push(k));y()},A=ve(l,u);for(let g of A)S(g);let R=0,E=0,G=(g,k=!0)=>{if(g.length===0)return;let j=JSON.stringify(g),Z=g.map(Q=>Q.id),$;try{$=fetch(f,{method:"POST",keepalive:!0,body:j,headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`}})}catch(Q){Y(g,u,l),b(g),E++,R=Date.now()+X(E);return}let ae=Q=>{if(re(Q)!=="retry"){if(!Q.ok&&k){let ne=g.filter(z=>z.eventType!=="pageview");if(ne.length>0&&ne.length<g.length){t(g.filter(z=>z.eventType==="pageview").map(z=>z.id)),G(ne,!1);return}}t(Z),E=0,R=0;return}Y(g,u,l),b(g),E++,R=Date.now()+X(E)};$ instanceof Promise?$.then(ae).catch(()=>{Y(g,u,l),b(g),E++,R=Date.now()+X(E)}):ae($)},F=typeof TextEncoder!="undefined"?new TextEncoder:null,_=g=>F?F.encode(g).length:g.length,w=g=>{let k=[],j=2;for(let Z of g){let $=_(JSON.stringify(Z))+1;if(k.length>0&&j+$>mt||k.length>=s)break;k.push(Z),j+=$}return k},L=()=>{try{if(Date.now()<R)return;for(;i.length>0&&!(Date.now()<R);){let g=i.filter(j=>!d.has(j.id));if(i.length=0,g.length===0)break;let k=w(g);if(k.length===0)break;k.length<g.length&&i.push(...g.slice(k.length)),G(k)}}catch(g){}},m=!0,T=null;T=setInterval(()=>{m&&L()},n);let M=()=>{document.visibilityState==="hidden"&&L()},W=()=>{L()};return document.addEventListener("visibilitychange",M),window.addEventListener("pagehide",W),{push(g){S(g),i.length>=s&&L()},flush:L,destroy(){m=!1,T!==null&&(clearInterval(T),T=null),document.removeEventListener("visibilitychange",M),window.removeEventListener("pagehide",W),L()}}}var ht=200;function De(e){return`_snt_goal_retry_${e.slice(0,12)}`}var St={send:()=>{},flush:()=>{},destroy:()=>{}};function ze(e){var _,w,L;if(typeof window=="undefined")return St;let n=(_=e.flushIntervalMs)!=null?_:5e3,s=(w=e.maxRetrySize)!=null?w:100,u=(L=e.maxPerFlush)!=null?L:5,f=De(e.apiKey),a=[],l=new Set,i=new Set,d=[],r=0,t=0,o=!1,y=m=>{for(l.delete(m.id),i.has(m.id)||(i.add(m.id),d.push(m.id));d.length>ht;){let T=d.shift();T&&i.delete(T)}we([m.id],f)},S=m=>{Y([m],s,f),!i.has(m.id)&&!l.has(m.id)&&(l.add(m.id),a.push(m)),Date.now()>=r&&(t++,r=Date.now()+X(t))},b=m=>{let T;try{T=fetch(e.url,{method:"POST",keepalive:!0,body:m.body,headers:e.headers})}catch(W){S(m);return}let M=W=>{var K;let q=re(W);if(q==="retry"){S(m);return}q==="dropped"&&((K=e.onDrop)==null||K.call(e,m,W.status)),y(m),t=0,r=0};T instanceof Promise?T.then(M).catch(()=>S(m)):M(T)},A=()=>{try{if(o||Date.now()<r)return;let m=0;for(;a.length>0&&m<u&&!(Date.now()<r);){let T=a.shift();l.delete(T.id),!i.has(T.id)&&(m++,b(T))}}catch(m){}},R=ve(f,s);for(let m of R)l.has(m.id)||(l.add(m.id),a.push(m));R.length>0&&Y(R,s,f);let E=setInterval(A,n),G=()=>{document.visibilityState==="hidden"&&A()},F=()=>A();return document.addEventListener("visibilitychange",G),window.addEventListener("pagehide",F),{send(m){if(!o&&!(i.has(m.id)||l.has(m.id))){if(Date.now()<r){Y([m],s,f),l.add(m.id),a.push(m);return}b(m)}},flush:A,destroy(){clearInterval(E),document.removeEventListener("visibilitychange",G),window.removeEventListener("pagehide",F),A(),o=!0}}}var vt=1800*1e3;function ke(e,n){return`${encodeURIComponent(e)}:${encodeURIComponent(n)}`}function Je(e=vt,n){let s=new Map,u=`_snt_asgn${fe(n)}_`,f=(r,t)=>`${u}${encodeURIComponent(r)}:${encodeURIComponent(t)}`,a=r=>{let t=r.slice(u.length),o=t.indexOf(":");if(o<0)return null;try{return{componentId:decodeURIComponent(t.slice(0,o)),segment:decodeURIComponent(t.slice(o+1))}}catch(y){return null}},l=()=>{try{let r=[];for(let t=0;t<localStorage.length;t++){let o=localStorage.key(t);o!=null&&o.startsWith(u)&&r.push(o)}return r}catch(r){return[]}},i=r=>r.assignedAt+(r.ttlMs&&r.ttlMs>0?r.ttlMs:e)<Date.now();return typeof window!="undefined"&&(()=>{for(let r of l())try{let t=localStorage.getItem(r);if(!t)continue;let o=JSON.parse(t);if(i(o)){localStorage.removeItem(r);continue}let y=a(r);if(!y)continue;s.set(ke(y.componentId,y.segment),o)}catch(t){}})(),{get(r,t){let o=s.get(ke(r,t));return o?i(o)?(s.delete(ke(r,t)),null):o:null},set(r,t,o){let y=ke(r,t);s.set(y,o);try{localStorage.setItem(f(r,t),JSON.stringify(o))}catch(S){}},clear(){s.clear();for(let r of l())try{localStorage.removeItem(r)}catch(t){}}}}var ie="_snt_snap:",wt=["low","medium","high"];function de(e){try{let n=localStorage.getItem(ie+e);if(!n)return null;let s=JSON.parse(n);return!s||typeof s!="object"||s.v!==1||typeof s.persona!="string"||typeof s.band!="string"||!wt.includes(s.band)||typeof s.slots!="object"||s.slots===null||Array.isArray(s.slots)||!(s.layoutOrder===null||Array.isArray(s.layoutOrder))||typeof s.savedAt!="number"||!(s.slotConfig===void 0||typeof s.slotConfig=="object"&&s.slotConfig!==null&&!Array.isArray(s.slotConfig))?null:s}catch(n){return null}}function ue(e,n){try{localStorage.setItem(ie+e,JSON.stringify(n))}catch(s){}}function kt(e){return"(function(){try{var r=localStorage.getItem("+JSON.stringify(ie+e).replace(/</g,"\\u003c")+');if(!r)return;var s=JSON.parse(r);if(!s||s.v!==1||typeof s.persona!=="string"||typeof s.band!=="string")return;var d=document.documentElement;if(d.hasAttribute("data-sentient-persona"))return;d.setAttribute("data-sentient-persona",s.persona);d.setAttribute("data-sentient-confidence",s.band);}catch(e){}})();'}import{confidenceBand as qe}from"@sentientui/policy";import{confidenceBand as Me}from"@sentientui/policy";var Ke="[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.",Xe="[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.",Ve=!1,xe=!1;function xt(){var e;try{return(e=new URLSearchParams(window.location.search).get("sentient_persona"))!=null?e:void 0}catch(n){return}}function Ye(e){var r;let n=Se({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),s=(r=n.getSessionId())!=null?r:"local",u=xt(),f=import("@sentientui/core/local").then(t=>{let o=t;return o.LOCAL_ENGINE_AVAILABLE?(Ve||(Ve=!0,console.info(Xe)),o):(xe||(xe=!0,console.error(Ke)),null)}).catch(()=>(xe||(xe=!0,console.error(Ke)),null)),a=null,l={low:.15,medium:.5,high:.85},i=(()=>{var o;if(e.initialPersona)return I({},e.initialPersona);let t=de(e.apiKey||"local");return t?{persona:t.persona,confidence:(o=l[t.band])!=null?o:.15}:null})();function d(t){let o=document.documentElement;o.dataset.sentientPersona===void 0&&(o.dataset.sentientPersona=t.persona,o.dataset.sentientConfidence=Me(t.confidence))}return{isLocal:!0,async decide(t){var S,b,A;let o=await f;if(!o)return null;let y=o.createLocalEngine({sessionId:s,forcedPersona:u}).decide(t);return a=se(I({},y),{layoutOrder:(b=(S=y.layoutOrder)!=null?S:a==null?void 0:a.layoutOrder)!=null?b:null,slots:I(I({},(A=a==null?void 0:a.slots)!=null?A:{}),y.slots)}),ue(e.apiKey||"local",{v:1,persona:a.persona,band:Me(a.confidence),slots:a.slots,layoutOrder:a.layoutOrder,savedAt:Date.now()}),d(y),y},getSlotResult(t){var o,y,S;return(S=(y=a==null?void 0:a.slots[t])!=null?y:(o=e.initialSlots)==null?void 0:o[t])!=null?S:null},getPersona(){let t=a!=null?a:i;return t?{persona:t.persona,confidence:t.confidence,band:Me(t.confidence)}:null},async assign(t,o){var b;let y=await f;return!y||!o||o.length===0?o!=null&&o[0]?{variantId:o[0],assignmentTtlMs:0}:null:{variantId:(b=y.createLocalEngine({sessionId:s,forcedPersona:u}).decide({components:[{id:t,variantIds:o}]}).assignments[t])!=null?b:o[0],assignmentTtlMs:0}},track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>n.destroy()}}var Jt=["none","sm","md","lg"],Vt=["start","center","end","stretch"],Xt=["start","center","end","between"],Yt=["sm","md","lg"],qt=["normal","medium","bold"],Zt=["default","muted","accent"],en=["primary","secondary","ghost"],tn=["left","center","right"],nn=["auto","square","landscape","wide"],on=["cover","contain"],sn=[2,3,4],rn=[2,3,4],an=64,ln=5,cn=12,dn=4,un=500;function bt(e,n,s,u){let f=[];{let i=!1,d=[],r=()=>{if(i)return;let t=Date.now();for(d.push(t);d.length>0&&t-d[0]>500;)d.shift();d.length>=3&&(i=!0,e("rage_click"))};n.addEventListener("click",r),f.push(()=>n.removeEventListener("click",r))}{let a=!1,l=i=>{if(a||!(i.target instanceof Node)||!n.contains(i.target)&&n!==i.target)return;a=!0;let d=typeof window!="undefined"?window.getSelection():null,r=d?d.toString().length:0;e("text_copy",{selectionLength:r})};document.addEventListener("copy",l),f.push(()=>document.removeEventListener("copy",l))}{let a=!1,l=!1,i=null,d=()=>{i!==null&&(clearTimeout(i),i=null)},r=()=>{a||!l||(d(),i=setTimeout(()=>{!a&&l&&(a=!0,e("scroll_hesitation"))},3e3))},t=()=>{d(),r()},o=S=>{for(let b of S)l=b.intersectionRatio>.3,l?r():d()},y=new IntersectionObserver(o,{threshold:[.3]});y.observe(n),window.addEventListener("scroll",t,{passive:!0}),f.push(()=>{y.disconnect(),window.removeEventListener("scroll",t),d()})}if((u==null?void 0:u.tabLoss)!==!1){let a=!1,l=s!=null?s:Date.now(),i=()=>{if(a||document.visibilityState!=="hidden")return;let d=Date.now()-l;d<15e3&&(a=!0,e("tab_loss",{timeOnPage:d}))};document.addEventListener("visibilitychange",i),f.push(()=>document.removeEventListener("visibilitychange",i))}return()=>{for(let a of f)a()}}var Ze="https://api.sentient-ui.com/v1/events",N=new Map,et=null;function Pn(e,n){let s=N.get(e);s&&s.upgrade&&(s.reinit=n)}function Et(e){return"value"in e||"currency"in e||"externalId"in e||"metadata"in e||"weight"in e||"stepIndex"in e}var It=3;function Ne(){return ye()}function be(){var e;if(typeof window!="undefined")return((e=window.location)==null?void 0:e.pathname)||void 0}function _t(){let e=new WeakMap,n=new Map,s=!1,u=(i,d,r)=>{let t=i.get(d);return r===null?t?!0:(i.set(d,new Set),!1):t?t.has(r)?!0:(t.add(r),!1):(i.set(d,new Set([r])),!1)},f=typeof window!="undefined"&&"event"in window,a=()=>{if(!f)return;let i=window.event;return typeof Event=="function"&&i instanceof Event?i:void 0},l=()=>{if(f){Promise.resolve().then(()=>{s=!1,n.clear()});return}let i=!1,d=()=>{i||(i=!0,s=!1,n.clear())};if(setTimeout(d,0),typeof MessageChannel=="function"){let r=new MessageChannel;r.port1.onmessage=()=>{r.port1.close(),r.port2.close(),d()},r.port2.postMessage(0)}};return{firedBefore(i,d){let r=a();if(r){let o=e.get(r);return o||(o=new Map,e.set(r,o)),u(o,i,d)}let t=u(n,i,d);return!t&&!s&&(s=!0,l()),t}}}var tt=new Set;function Ct(e,n,s){let u=typeof window=="undefined"?null:window.history;if(!u)return()=>{};let f=!1,a,l=()=>{if(f)return;let r=be();!r||r===a||(a=r,e.track({projectId:n,componentId:"__page__",eventType:"pageview",payload:{}}),s(`${n}:${r}`))},i=[];for(let r of["pushState","replaceState"]){let t=u[r],o=function(...y){let S=t.apply(this,y);return l(),S};u[r]=o,i.push([r,t,o])}window.addEventListener("popstate",l);let d=be();return d&&tt.has(`${n}:${d}`)?a=d:l(),()=>{if(!f){f=!0,window.removeEventListener("popstate",l);for(let[r,t,o]of i)u[r]===o&&(u[r]=t)}}}var pe={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}};function Tt(){try{return Ae(window.location.search)}catch(e){return{utmParams:{},clickIds:{}}}}function nt(e){return e.replace(/\/events\/?$/,"")}function ot(){return typeof navigator!="undefined"&&navigator.globalPrivacyControl===!0?!0:[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(n=>n==="1"||n==="yes")}function Dn(e){var d;if(typeof window=="undefined")return;let n=e!=null?e:et;if(!n){console.warn("[sentient] grantConsent() called before init()");return}let s=N.get(n);if(!s){console.warn("[sentient] grantConsent() called before init()");return}let{config:u,upgrade:f,reinit:a}=s;if(!f){s.upgradeBlockedReason&&console.warn(s.upgradeBlockedReason);return}if(u.respectDoNotTrack!==!1&&ot())return;let l=(a!=null?a:Ot)(se(I({},u),{consent:!0}));f(l);let i=(d=N.get(n))==null?void 0:d.dispose;N.set(n,{config:se(I({},u),{consent:!0}),upgrade:null,dispose:i})}function At(e){var r;let n=e.preConsentBehavior==="statistical_winner",s=nt((r=e.ingestUrl)!=null?r:Ze),u={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},f=new Map,a=new Map,l={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),assign(t,o,y){if(!n)return Promise.resolve(null);let S=f.get(t);return S?Promise.resolve(S):Ge(a,t,async()=>{try{let b=new URLSearchParams({componentId:t});for(let G of o!=null?o:[])b.append("variantIds[]",G);let A=await fetch(`${s}/winner?${b.toString()}`,{headers:u});if(!A.ok)return o!=null&&o[0]?{variantId:o[0],assignmentTtlMs:0}:null;let E={variantId:(await A.json()).variantId,assignmentTtlMs:0};return f.set(t,E),E}catch(b){return o!=null&&o[0]?{variantId:o[0],assignmentTtlMs:0}:null}})},decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,getGraph:()=>({pageNodes:[],capturedAt:0}),dispose:()=>{},destroy:()=>{}},i={track:t=>l.track(t),goal:((t,o,y,S)=>l.goal(t,o,y,S)),componentGoal:(t,o,y)=>l.componentGoal(t,o,y),identify:t=>l.identify(t),getAssignment:(t,o)=>l.getAssignment(t,o),assign:(t,o,y,S)=>l.assign(t,o,y,S),decide:t=>l.decide(t),getSlotResult:t=>l.getSlotResult(t),getPersona:()=>l.getPersona(),fetchWeights:()=>l.fetchWeights(),getGraph:()=>l.getGraph(),dispose:()=>l.dispose(),destroy:()=>l.destroy()};function d(t){l=t}return{proxy:i,setInner:d}}function Ge(e,n,s){let u=e.get(n);if(u)return u;let f=(async()=>{try{return await s()}finally{e.delete(n)}})();return e.set(n,f),f}function Ot(e){var k,j,Z,$,ae,Q,ne,z,Ue;if(typeof window=="undefined")return pe;et=e.apiKey||"local";let n=N.get(e.apiKey||"local");if(n!=null&&n.dispose)try{n.dispose()}catch(c){}let s=e.respectDoNotTrack!==!1&&ot(),u=e.consent===!1||s,f=typeof e.apiKey=="string"&&e.apiKey.startsWith("pk_");if(e.localMode===!0||!f&&e.localMode!==!1)return N.set(e.apiKey||"local",{config:e,upgrade:null,upgradeBlockedReason:"[sentient] grantConsent(): this client is keyless/local \u2014 there is no hosted client to upgrade to. Configure a pk_ API key to enable tracking."}),u?pe:Ye(e);if(u){if(!e.apiKey||!e.apiKey.startsWith("pk_"))return e.preConsentBehavior==="statistical_winner"&&console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),N.set(e.apiKey||"local",{config:e,upgrade:null,upgradeBlockedReason:"[sentient] grantConsent(): the client was initialized with an invalid apiKey (expected a pk_ public key) \u2014 consent cannot enable tracking."}),pe;let{proxy:c,setInner:p}=At(e);return N.set(e.apiKey,{config:e,upgrade:s?null:p}),c}if(!e.apiKey||!e.apiKey.startsWith("pk_"))return console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),pe;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),pe;let a=(k=e.ingestUrl)!=null?k:Ze,l=Date.now(),i=Se({ssrSessionId:e.ssrSessionId,apiKey:e.apiKey}),d=Je(void 0,e.apiKey),r=Qe({ingestUrl:a,apiKey:e.apiKey}),t=nt(a),o={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},y=new Set,S=ze({url:`${t}/goals`,apiKey:e.apiKey,headers:o,onDrop:(c,p)=>{if(!e.debug){if(y.has(p))return;y.add(p)}console.warn(`[sentient] goal dropped (HTTP ${p}) \u2014 this will not be retried. `+(p===400?"The session was not found: call init() and let the session upsert complete before firing goals.":p===401||p===403?"Check the API key and that this origin is on the project allowlist.":"See the response status for the cause."),c)}}),b=_e((j=navigator.userAgent)!=null?j:""),A=window.location.origin,R=Ce((Z=document.referrer)!=null?Z:"",A),E=($=e.sessionSegment)!=null?$:`${b}:${R}`,G=new Map,F=new Map,_=new Map,w=null,L=c=>{for(let p of c)_.has(p.id)||_.set(p.id,me(p))};if(e.initialSlots)for(let[c,p]of Object.entries(e.initialSlots))_.set(c,p);let m=de(e.apiKey);if(m)for(let[c,p]of Object.entries(m.slots))_.has(c)||_.set(c,p);let T={low:.15,medium:.5,high:.85};if(e.initialPersona)w=I({},e.initialPersona);else{let c=document.documentElement.dataset;c.sentientPersona?w={persona:c.sentientPersona,confidence:(Q=T[(ae=c.sentientConfidence)!=null?ae:"low"])!=null?Q:.15}:m&&(w={persona:m.persona,confidence:(ne=T[m.band])!=null?ne:.15})}if(e.initialAssignments)for(let[c,p]of Object.entries(e.initialAssignments))d.set(c,E,{variantId:p,assignedAt:Date.now(),segment:E,confidence:1});let M=Promise.resolve(),W=i.getSessionId();if(W){let c=Te((z=document.referrer)!=null?z:""),{utmParams:p,clickIds:v}=Tt(),O=I(I(I({sessionId:W,deviceClass:b,trafficSource:R,referrerDomain:c,utmParams:p,clickIds:v,timeOfDay:Oe(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:i.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||Ie((Ue=navigator.userAgent)!=null?Ue:"")},e.userId?{userId:e.userId}:{}),e.persona?{persona:e.persona}:{}),e.country?{country:e.country}:{}),P=async()=>{for(let h=0;;h++){try{let C=await fetch(`${t}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(O),headers:o});if(C.status===402){console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing");return}if(C.ok||re(C)==="dropped")return}catch(C){}if(h>=It){console.warn("[SentientUI] Could not register the session after retries. Conversions in this visit may not be recorded.");return}await new Promise(C=>setTimeout(C,X(h+1)))}};try{M=P()}catch(h){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:r});let q=_t(),K=null,te=!1,g={goal(c,p={},v=1,O=0){var le,ce,oe,x,H,ge,B;let P=i.getSessionId();if(!P)return;let h=Et(p)?p:{metadata:p},C=[c,(le=h.externalId)!=null?le:"",(ce=h.stepIndex)!=null?ce:O,(oe=h.weight)!=null?oe:v].join("\0"),U=h.value!==void 0?`${h.value}\0${(x=h.currency)!=null?x:""}`:null;if(q.firedBefore(C,U)){e.debug&&console.log(`[sentient] goal("${c}") already recorded for this action \u2014 not sent twice`);return}let D=Ne(),J={sessionId:P,name:c,metadata:(H=h.metadata)!=null?H:{},weight:(ge=h.weight)!=null?ge:v,stepIndex:(B=h.stepIndex)!=null?B:O,goalId:D,value:h.value,currency:h.currency,externalId:h.externalId};e.debug&&console.log("[sentient] goal",J);let ee={id:D,body:JSON.stringify(J)};M.then(()=>S.send(ee))},componentGoal(c,p,v){var D,J,ee;let O=i.getSessionId();if(!O)return;let P=d.get(c,E),h=P?null:(D=_.get(c))!=null?D:null;if(!P&&h===null){e.debug&&console.warn(`[sentient] componentGoal("${c}"): no assignment or slot decision yet \u2014 render its <Adaptive>/adaptive hook or call assign()/decide() before recording a goal.`);return}let C=P?P.variantId:Be(h),U={id:Ne(),sessionId:O,projectId:e.apiKey,componentId:c,variantId:C,eventType:"goal_achieved",goalType:p,payload:I({reward:(J=v==null?void 0:v.reward)!=null?J:1,goalValue:v==null?void 0:v.value,currency:v==null?void 0:v.currency},(ee=v==null?void 0:v.metadata)!=null?ee:{}),timestamp:Date.now(),timeInSession:Date.now()-l,path:be()};e.debug&&console.log("[sentient] componentGoal",U),M.then(()=>r.push(U))},identify(c){let p=i.getSessionId();p&&M.then(()=>{fetch(`${t}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:p,userId:c,ephemeral:i.isEphemeral()}),headers:o}).catch(()=>{})})},track(c){let p=i.getSessionId();if(!p)return;let v=se(I({path:be()},c),{id:Ne(),sessionId:p,timestamp:Date.now(),timeInSession:Date.now()-l});e.debug&&console.log("[sentient] track",v),M.then(()=>r.push(v))},getAssignment(c,p){return d.get(c,p)},async assign(c,p,v,O){let P=i.getSessionId();if(!P)return null;let h=d.get(c,E);if(h&&(p!=null&&p.length||h.content!==void 0)){let C=h.ttlMs&&h.ttlMs>0?Math.max(0,h.assignedAt+h.ttlMs-Date.now()):0;return{variantId:h.variantId,assignmentTtlMs:C,content:h.content}}return Ge(G,c,async()=>{await M;try{let C={sessionId:P,componentId:c,variantIds:p};O!==void 0?C.agentDataByVariant=O:v!==void 0&&(C.agentData=v);let U=await fetch(`${t}/assign`,{method:"POST",body:JSON.stringify(C),headers:o});if(!U.ok)return null;let D=await U.json();return d.set(c,E,I({variantId:D.variantId,assignedAt:Date.now(),segment:E,confidence:1,content:D.content},D.assignmentTtlMs&&D.assignmentTtlMs>0?{ttlMs:D.assignmentTtlMs}:{})),D}catch(C){return null}})},async decide(c){var h,C;let p=i.getSessionId();if(!p)return null;let v=(h=c.slots)!=null?h:[],O={sessionId:p};c.sections&&c.sections.length>0&&(O.sections=c.sections.map(U=>({id:U}))),O.components=(C=c.components)!=null?C:[],v.length>0&&(O.slots=v.map(Re)),c.slotsFrom==="registry"&&(O.slotsFrom="registry"),c.v&&(O.v=c.v),e.persona&&(O.persona=e.persona);let P=JSON.stringify(O);return Ge(F,P,async()=>{var U,D,J,ee,le,ce;await M;try{let oe=await fetch(`${t}/decide`,{method:"POST",body:P,headers:o});if(!oe.ok)return L(v),null;let x=await oe.json(),H={};for(let B of v){let V=(U=x.slots)==null?void 0:U[B.id];if(V!==void 0){H[B.id]=V,_.set(B.id,V);continue}let Fe=_.get(B.id);if(Fe!==void 0)H[B.id]=Fe;else{let $e=me(B);H[B.id]=$e,_.set(B.id,$e)}}if(x.slots)for(let[B,V]of Object.entries(x.slots))B in H||(H[B]=V,_.set(B,V));let ge=w!=null&&w.persona!=="unknown";x.persona&&!(x.persona==="unknown"&&ge)?w={persona:x.persona,confidence:(D=x.confidence)!=null?D:0}:w||(w={persona:"unknown",confidence:0});for(let[B,V]of Object.entries((J=x.assignments)!=null?J:{}))d.set(B,E,{variantId:V,assignedAt:Date.now(),segment:E,confidence:1});return ue(e.apiKey,I(I({v:1,persona:w.persona,band:qe(w.confidence),slots:Object.fromEntries(_),layoutOrder:(ee=x.layoutOrder)!=null?ee:null,savedAt:Date.now()},x.slotConfig?{slotConfig:x.slotConfig}:{}),x.palette?{palette:x.palette}:{})),I(I(I(I({layoutOrder:(le=x.layoutOrder)!=null?le:null,assignments:(ce=x.assignments)!=null?ce:{},slots:H,persona:w.persona,confidence:w.confidence},x.slotConfig?{slotConfig:x.slotConfig}:{}),x.goals?{goals:x.goals}:{}),x.sectionMap?{sectionMap:x.sectionMap}:{}),x.palette?{palette:x.palette}:{})}catch(oe){return L(v),null}})},getSlotResult(c){var p;return(p=_.get(c))!=null?p:null},getPersona(){return w?{persona:w.persona,confidence:w.confidence,band:qe(w.confidence)}:null},async fetchWeights(){var c;try{let p=await fetch(`${t}/weights`,{headers:o});return p.ok?(c=(await p.json()).components)!=null?c:[]:[]}catch(p){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},dispose(){var c;K==null||K(),te=!0,r.destroy(),S.destroy(),((c=N.get(e.apiKey))==null?void 0:c.dispose)===g.dispose&&N.delete(e.apiKey),e.debug&&console.log("[sentient] disposed")},destroy(){var c;K==null||K(),te=!0,r.destroy(),S.destroy(),i.destroy(),d.clear(),((c=N.get(e.apiKey))==null?void 0:c.dispose)===g.dispose&&N.delete(e.apiKey);try{localStorage.removeItem(ie+e.apiKey),localStorage.removeItem(Pe(e.apiKey)),localStorage.removeItem(De(e.apiKey))}catch(p){}e.debug&&console.log("[sentient] destroyed")}};if(N.set(e.apiKey,{config:e,upgrade:null,dispose:g.dispose}),K=Ct(g,e.apiKey,c=>{M.then(()=>{te||tt.add(c)})}),e.debug){let c=window;c.__sentient&&(c.__sentient.client=g)}return g}export{ie as a,de as b,ue as c,kt as d,Ke as e,Xe as f,Jt as g,Vt as h,Xt as i,Yt as j,qt as k,Zt as l,en as m,tn as n,nn as o,on as p,sn as q,rn as r,an as s,ln as t,cn as u,dn as v,un as w,bt as x,Pn as y,ot as z,Dn as A,Ot as B};
2
+ //# sourceMappingURL=chunk-RL5B6M4G.mjs.map