@sentientui/core 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @sentientui/core
2
2
 
3
- Framework-agnostic JavaScript SDK for [SentientUI](https://sentientui.dev) — an adaptive UI platform that uses a contextual bandit to automatically surface the best-performing variant for each visitor.
3
+ Framework-agnostic JavaScript SDK for [SentientUI](https://sentient-ui.com) — a Thompson Sampling bandit + persona/portrait engine that automatically surfaces the best-performing variant for each visitor. Learning runs on the SentientUI hosted API.
4
+
5
+ > Most users should install **`@sentientui/react`** instead — it bundles this package and adds the SSR-safe `<AdaptiveRoot>`, `<Adaptive>`, and hooks. Use `@sentientui/core` directly only if you are not building with React.
4
6
 
5
7
  ## Installation
6
8
 
@@ -14,69 +16,133 @@ npm install @sentientui/core
14
16
  import { init } from '@sentientui/core';
15
17
 
16
18
  const client = init({
17
- apiKey: 'pk_your_key',
18
- context: 'saas', // 'landing' | 'ecommerce' | 'saas' | 'marketplace'
19
+ apiKey: 'pk_your_key', // from app.sentient-ui.com → Settings
20
+ context: 'saas', // 'landing' | 'ecommerce' | 'saas' | 'marketplace'
19
21
  });
20
22
 
21
- // Get a variant assignment for a component
22
- const result = await client.assign('hero-headline');
23
- console.log(result?.variantId); // e.g. 'variant-b'
23
+ // Get a variant assignment for a component (returns null during SSR)
24
+ const result = await client.assign('hero_headline', ['control', 'variant_b']);
25
+ console.log(result?.variantId); // e.g. 'variant_b'
26
+ console.log(result?.content); // managed text content if the variant is WYSIWYG-managed
27
+
28
+ // Fire a goal (reward) when the visitor converts
29
+ client.goal('trial_started', { plan: 'pro' });
24
30
 
25
- // Track a conversion event
31
+ // Or record a custom event
26
32
  client.track({
27
- projectId: 'your-project-id',
28
- componentId: 'hero-headline',
33
+ componentId: 'hero_headline',
29
34
  variantId: result?.variantId ?? 'control',
30
35
  eventType: 'click',
31
36
  });
32
37
  ```
33
38
 
34
- ## API
39
+ `init()` returns a no-op client during SSR (`typeof window === 'undefined'`), when `consent` is `false`, or when `apiKey` does not start with `pk_`. The hosted ingest URL (`https://sentient-api.fly.dev/v1/events`) is built in — no URL configuration required.
35
40
 
36
- ### `init(config)`
41
+ ## API
37
42
 
38
- Initializes the client. Returns a no-op client during SSR and when `consent` is `false`.
43
+ ### `init(config)` `SentientClient`
39
44
 
40
45
  | Option | Type | Description |
41
46
  |--------|------|-------------|
42
- | `apiKey` | `string` | Your public API key (`pk_…`) |
43
- | `context` | `string` | Site context — `'landing'`, `'ecommerce'`, `'saas'`, or `'marketplace'` |
44
- | `initialAssignments` | `Record<string, string>` | SSR-preloaded assignments to seed the cache (prevents variant flash on hydration) |
45
- | `sessionSegment` | `string` | Segment from SSR (`device:source`) must match the value used in `preloadAssignments` |
46
- | `consent` | `boolean` | Set to `false` to disable tracking (e.g. before cookie consent). Defaults to `true` |
47
- | `debug` | `boolean` | Logs events to the console and exposes `window.__sentient` |
47
+ | `apiKey` | `string` | Public API key (`pk_…`) from the SentientUI dashboard. |
48
+ | `context` | `'landing' \| 'ecommerce' \| 'saas' \| 'marketplace'` | Type of product. Used for segment weighting and analytics grouping. |
49
+ | `consent` | `boolean` *(default `true`)* | When `false`, returns a no-op client (no cookies, no events). |
50
+ | `initialAssignments` | `Record<string, string>` | SSR-preloaded assignments. Seeds the cache so `assign()` returns immediately for listed components. |
51
+ | `sessionSegment` | `string` | Segment from SSR (`device:source`). Must match the value used in `preloadAssignments`. |
52
+ | `userId` | `string` | Optional cross-session identity. Persists portraits across sessions for the same user. |
53
+ | `debug` | `boolean` | Logs events to the console and exposes `window.__sentient`. |
48
54
 
49
- ### `client.assign(componentId, variantIds?)`
55
+ ### `client.assign(componentId, variantIds?)` → `Promise<AssignResult | null>`
50
56
 
51
- Fetches a variant assignment from the bandit. Returns a cached result immediately if one exists. Returns `null` during SSR.
57
+ Asks the hosted bandit for a variant. Cached locally per `(componentId, segment)` repeat calls hit the cache. Returns `null` during SSR or when the session has no ID.
58
+
59
+ ```ts
60
+ type AssignResult = {
61
+ variantId: string;
62
+ assignmentTtlMs: number;
63
+ content?: string; // populated when the variant is dashboard-managed (WYSIWYG)
64
+ };
65
+ ```
52
66
 
53
67
  ### `client.track(event)`
54
68
 
55
- Queues an event for ingest. Batched and sent automatically.
69
+ Queues an event for batched ingest. Events flush every 5 s and on `visibilitychange` / page unload (via `fetch` with `keepalive: true`).
70
+
71
+ ### `client.goal(name, metadata?)`
72
+
73
+ Fires a named goal for the current session. Used for cross-component conversions (e.g. `'trial_started'`, `'purchase_completed'`) where you cannot scope the reward to a single `<Adaptive>`.
74
+
75
+ ### `client.identify(userId)`
76
+
77
+ Attaches a stable user ID to the session. Portraits and cluster assignment carry forward across future sessions for the same `userId`.
56
78
 
57
79
  ### `client.getAssignment(componentId, segment)`
58
80
 
59
- Synchronously returns the cached assignment for a component/segment pair, or `null` if not yet assigned.
81
+ Synchronously returns the cached assignment, or `null` if not yet assigned. Use when you need a non-async lookup.
82
+
83
+ ### `client.getGraph()`
84
+
85
+ Returns the current `GraphSnapshot` (page nodes captured by the optional graph scanner — see `@sentientui/core/graph`).
60
86
 
61
87
  ### `client.destroy()`
62
88
 
63
- Flushes the event queue and clears the session. Call on page unload if needed.
89
+ Flushes the event queue and clears session state. Call on page unload if you need a synchronous teardown (the SDK already handles `visibilitychange` automatically).
64
90
 
65
91
  ## SSR helpers
66
92
 
67
93
  ```ts
68
94
  import { preloadAssignments, readSessionCookie } from '@sentientui/core';
69
95
 
70
- // In your server loader / getServerSideProps / Server Component:
71
- const sessionSegment = readSessionCookie(request.headers.get('cookie'));
72
- const initialAssignments = await preloadAssignments({
73
- apiKey: 'pk_your_key',
74
- componentIds: ['hero-headline', 'pricing-cta'],
75
- sessionSegment,
76
- });
96
+ // In your server loader / getServerSideProps / Server Component.
97
+ // `cookies` must expose `get(name)` — Next.js `req.cookies`, `headers().cookies()`, or any
98
+ // object with the same shape.
99
+ const sessionId = readSessionCookie(cookies) ?? crypto.randomUUID();
100
+
101
+ const initialAssignments = await preloadAssignments(
102
+ [
103
+ { id: 'hero_headline', variantIds: ['control', 'variant_b'] },
104
+ { id: 'pricing_cta', variantIds: ['monthly', 'annual_first'] },
105
+ ],
106
+ sessionId,
107
+ {
108
+ apiKey: process.env.SENTIENT_API_KEY!,
109
+ baseUrl: 'https://sentient-api.fly.dev/v1',
110
+ origin: process.env.APP_ORIGIN, // must be in the project's allowed origins
111
+ userAgent, // from request headers, aligns segment with the client
112
+ referer,
113
+ },
114
+ );
77
115
  ```
78
116
 
79
- Pass `initialAssignments` and `sessionSegment` to `init()` on the client to prevent hydration mismatches.
117
+ Pass `initialAssignments` and the same `sessionSegment` to `init()` on the client to prevent hydration mismatches.
118
+
119
+ For pages with a section layout, use `preloadDecisions` instead — same options, plus a `sections: string[]` request field. The return value carries both `assignments` and `layoutOrder`.
120
+
121
+ ## Optional: graph mode
122
+
123
+ `@sentientui/core/graph` is a separate, tree-shakable entry that activates the DOM scanner and graph sync (component-to-component edges + 2-hop reward propagation). Import it once, on the client, after `init()`:
124
+
125
+ ```ts
126
+ import('@sentientui/core/graph');
127
+ ```
128
+
129
+ The lean bundle stays under 8 KB gzip; graph adds roughly another 8 KB.
130
+
131
+ ## Local overrides (development)
132
+
133
+ ```
134
+ # URL parameter (stackable)
135
+ https://yourapp.com?sentient_variant=hero_cta:variant_a
136
+
137
+ # Or before SDK init:
138
+ window.__sentient_overrides = { hero_cta: 'variant_a' };
139
+ ```
140
+
141
+ Overrides bypass the bandit entirely — no events recorded.
142
+
143
+ ## Docs
144
+
145
+ Full reference: [sentient-ui.com/docs](https://sentient-ui.com/docs).
80
146
 
81
147
  ## License
82
148
 
@@ -0,0 +1 @@
1
+ var ie=Object.defineProperty,oe=Object.defineProperties;var ae=Object.getOwnPropertyDescriptors;var H=Object.getOwnPropertySymbols;var ce=Object.prototype.hasOwnProperty,de=Object.prototype.propertyIsEnumerable;var X=(e,t,n)=>t in e?ie(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,_=(e,t)=>{for(var n in t||(t={}))ce.call(t,n)&&X(e,n,t[n]);if(H)for(var n of H(t))de.call(t,n)&&X(e,n,t[n]);return e},U=(e,t)=>oe(e,ae(t));var ue="_snt_uid";var k="_snt_uid";function le(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function ge(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function fe(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(o){}}function me(e){try{return localStorage.getItem(e)}catch(t){return null}}function pe(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function ye(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function he(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Se(e){try{sessionStorage.removeItem(e)}catch(t){}}function ve(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function we(e){try{localStorage.removeItem(e)}catch(t){}}function xe(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Ae={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Z(e){var u,g,p,h,S;if(typeof window=="undefined")return Ae;let t=(u=e==null?void 0:e.cookieName)!=null?u:ue,o=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,s=(S=(h=(p=ge(t))!=null?p:me(k))!=null?h:ye(k))!=null?S:le();fe(t,s,o);let i=pe(k,s),r=ve(t),a=i?!1:he(k,s),c=!i&&!r&&!a;return{getSessionId:()=>s,isEphemeral:()=>c,destroy:()=>{s=null,xe(t),we(k),Se(k)}}}var L="_snt_retry";var be={push:()=>{},flush:()=>{},destroy:()=>{}};function Ie(e){try{let t=localStorage.getItem(L);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(L),n.slice(-e)):[]}catch(t){return[]}}function W(e,t){try{let o=[...(()=>{try{let s=localStorage.getItem(L);if(!s)return[];let i=JSON.parse(s);return Array.isArray(i)?i:[]}catch(s){return[]}})(),...e].slice(-t);localStorage.setItem(L,JSON.stringify(o))}catch(n){}}function ee(e){var D,E,b;if(typeof window=="undefined")return be;let t=(D=e.flushIntervalMs)!=null?D:5e3,n=(E=e.maxBatchSize)!=null?E:20,o=(b=e.maxRetrySize)!=null?b:100,s=e.ingestUrl,i=e.apiKey,r=[],a=new Set,c=[],u=d=>{for(let l of d)g.delete(l),!a.has(l)&&(a.add(l),c.push(l));for(;c.length>500;){let l=c.shift();l&&a.delete(l)}},g=new Set,p=d=>{a.has(d.id)||g.has(d.id)||(g.add(d.id),r.push(d))},h=Ie(o);for(let d of h)p(d);let S=0,v=0,P=d=>{if(d.length===0)return;let l=JSON.stringify(d),x=d.map(A=>A.id),I;try{I=fetch(s,{method:"POST",keepalive:!0,body:l,headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}})}catch(A){W(d,o);for(let z of x)g.delete(z);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6));return}let O=A=>{if(A.ok||A.status>=400&&A.status<500&&A.status!==429){u(x),v=0,S=0;return}W(d,o);for(let z of x)g.delete(z);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};I instanceof Promise?I.then(O).catch(()=>{W(d,o);for(let A of x)g.delete(A);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):O(I)},C=typeof TextEncoder!="undefined"?new TextEncoder:null,M=d=>C?C.encode(d).length:d.length,$=d=>{let l=[],x=2;for(let I of d){let O=M(JSON.stringify(I))+1;if(l.length>0&&x+O>57344||l.length>=n)break;l.push(I),x+=O}return l},w=()=>{try{if(Date.now()<S)return;for(;r.length>0;){let d=r.filter(x=>!a.has(x.id));if(r.length=0,d.length===0)break;let l=$(d);if(l.length===0)break;l.length<d.length&&r.push(...d.slice(l.length)),P(l)}}catch(d){}},f=!0,m=null;m=setInterval(()=>{f&&w()},t);let y=()=>{document.visibilityState==="hidden"&&w()},T=()=>{w()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",T),{push(d){p(d),r.length>=n&&w()},flush:w,destroy(){f=!1,m!==null&&(clearInterval(m),m=null),document.removeEventListener("visibilitychange",y),window.removeEventListener("beforeunload",T),w()}}}var N="_snt_asgn_";function K(e,t){return`${e}:${t}`}function Ee(e,t){return`${N}${e}_${t}`}function Y(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(N)&&e.push(n)}return e}catch(e){return[]}}function te(e=18e5){let t=new Map,n=s=>s.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let s of Y())try{let i=localStorage.getItem(s);if(!i)continue;let r=JSON.parse(i);if(n(r)){localStorage.removeItem(s);continue}let a=s.slice(N.length),c=a.lastIndexOf("_");if(c<0)continue;let u=a.slice(0,c),g=a.slice(c+1);t.set(K(u,g),r)}catch(i){}})(),{get(s,i){let r=t.get(K(s,i));return r?n(r)?(t.delete(K(s,i)),null):r:null},set(s,i,r){let a=K(s,i);t.set(a,r);try{localStorage.setItem(Ee(s,i),JSON.stringify(r))}catch(c){}},invalidate(s){let i=`${s}:`;for(let r of[...t.keys()])r.startsWith(i)&&t.delete(r);for(let r of Y()){let a=r.slice(N.length),c=a.lastIndexOf("_");if(c<0)continue;if(a.slice(0,c)===s)try{localStorage.removeItem(r)}catch(g){}}},clear(){t.clear();for(let s of Y())try{localStorage.removeItem(s)}catch(i){}}}}function B(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function G(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(s){}let o=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(o)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(o)?"social":"referral"}catch(n){return"direct"}}function Q(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function J(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function _e(e){let t=j("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function j(e,t){var i,r,a,c,u,g,p;let n=(r=(i=t==null?void 0:t.userAgent)==null?void 0:i.trim())!=null?r:"",o=(c=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?c:"",s=(u=t==null?void 0:t.now)!=null?u:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?B(n):"desktop",trafficSource:o?G(o,t==null?void 0:t.appOrigin):"direct",referrerDomain:Q(o),timeOfDay:J(s),dayOfWeek:(p=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?p:"sun"}}var ne=1500;function F(e,t,n){let o=new AbortController,s=setTimeout(()=>o.abort(),n);return fetch(e,U(_({},t),{signal:o.signal})).finally(()=>clearTimeout(s))}async function ke(e,t,n){var c;let o=(c=n.timeoutMs)!=null?c:ne,s={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(s.Origin=n.origin);let i=j(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await F(`${n.baseUrl}/sessions`,{method:"POST",headers:s,body:JSON.stringify(i)},o)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(u){}let r=await Promise.allSettled(e.map(async({id:u,variantIds:g})=>{let p=await F(`${n.baseUrl}/assign`,{method:"POST",headers:s,body:JSON.stringify({sessionId:t,componentId:u,variantIds:g})},o);if(!p.ok)return null;let h=await p.json();return{id:u,variantId:h.variantId}})),a={};for(let u of r)u.status==="fulfilled"&&u.value&&(a[u.value.id]=u.value.variantId);return a}function Ce(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}async function Te(e,t,n){var a;let o=(a=n.timeoutMs)!=null?a:ne,s={layoutOrder:e.sections,assignments:{},persona:"unknown",confidence:0},i={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(i.Origin=n.origin);let r=j(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{await F(`${n.baseUrl}/sessions`,{method:"POST",headers:i,body:JSON.stringify(r)},o)}catch(c){}try{let c=await F(`${n.baseUrl}/decide`,{method:"POST",headers:i,body:JSON.stringify({sessionId:t,sections:e.sections.map(u=>({id:u})),components:e.components})},o);return c.ok?await c.json():s}catch(c){return s}}var re="https://sentient-api.fly.dev/v1/events",q=null,V=null;function De(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var R={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Oe(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,o]of t)n.startsWith("utm_")&&(e[n]=o);return e}catch(e){return{}}}function se(e){return e.replace(/\/events\/?$/,"")}function ze(){if(typeof window=="undefined")return;if(!q){console.warn("[sentient] grantConsent() called before init()");return}let e=V;V=null;let t=Re(U(_({},q),{consent:!0}));e==null||e(t)}function Ue(e){var s;let t=se((s=e.ingestUrl)!=null?s:re),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},o={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(i,r,a){try{let c=new URLSearchParams({componentId:i});for(let p of r!=null?r:[])c.append("variantIds[]",p);let u=await fetch(`${t}/winner?${c.toString()}`,{headers:n});return u.ok?{variantId:(await u.json()).variantId,assignmentTtlMs:0}:r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}catch(c){return r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return V=i=>{o=i},{track:i=>o.track(i),goal:(i,r)=>o.goal(i,r),identify:i=>o.identify(i),getAssignment:(i,r)=>o.getAssignment(i,r),assign:(i,r,a,c)=>o.assign(i,r,a,c),getGraph:()=>o.getGraph(),destroy:()=>o.destroy()}}function Re(e){var P,C,M,$,w;if(typeof window=="undefined")return R;if(q=e,e.consent===!1)return e.preConsentBehavior==="statistical_winner"?!e.apiKey||!e.apiKey.startsWith("pk_")?(console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),R):Ue(e):R;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."),R;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),R;let t=(P=e.ingestUrl)!=null?P:re,n=Date.now(),o=Z(),s=te(),i=ee({ingestUrl:t,apiKey:e.apiKey}),r=se(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=B((C=navigator.userAgent)!=null?C:""),u=typeof window!="undefined"?window.location.origin:void 0,g=G((M=document.referrer)!=null?M:"",u),p=($=e.sessionSegment)!=null?$:`${c}:${g}`;if(e.initialAssignments)for(let[f,m]of Object.entries(e.initialAssignments))s.set(f,p,{variantId:m,assignedAt:Date.now(),segment:p,confidence:1});let h=Promise.resolve(),S=o.getSessionId();if(S){let f=Q((w=document.referrer)!=null?w:""),m=_({sessionId:S,deviceClass:c,trafficSource:g,referrerDomain:f,utmParams:Oe(),timeOfDay:J(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:o.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(m),headers:a}).then(y=>{y.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(y){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:i});let v={goal(f,m={}){let y=o.getSessionId();y&&h.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:f,metadata:m}),headers:a}).catch(()=>{})})},identify(f){let m=o.getSessionId();m&&h.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:f,ephemeral:o.isEphemeral()}),headers:a}).catch(()=>{})})},track(f){let m=o.getSessionId();if(!m)return;let y=U(_({},f),{id:De(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});i.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(f,m){return s.get(f,m)},async assign(f,m,y,T){let D=o.getSessionId();if(!D)return null;let E=s.get(f,p);if(E)return{variantId:E.variantId,assignmentTtlMs:0,content:E.content};await h;try{let b={sessionId:D,componentId:f,variantIds:m};T!==void 0?b.agentDataByVariant=T:y!==void 0&&(b.agentData=y);let d=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(b),headers:a});if(!d.ok)return null;let l=await d.json();return s.set(f,p,{variantId:l.variantId,assignedAt:Date.now(),segment:p,confidence:1,content:l.content}),l}catch(b){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){i.destroy(),o.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let f=window;f.__sentient&&(f.__sentient.client=v)}return v}export{_ as a,U as b,B as c,G as d,Q as e,J as f,_e as g,ke as h,Ce as i,Te as j,ze as k,Re as l};
@@ -1 +1 @@
1
- "use strict";var K=Object.defineProperty,pe=Object.defineProperties,me=Object.getOwnPropertyDescriptor,fe=Object.getOwnPropertyDescriptors,he=Object.getOwnPropertyNames,te=Object.getOwnPropertySymbols;var re=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var ne=(e,t,n)=>t in e?K(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,C=(e,t)=>{for(var n in t||(t={}))re.call(t,n)&&ne(e,n,t[n]);if(te)for(var n of te(t))ye.call(t,n)&&ne(e,n,t[n]);return e},N=(e,t)=>pe(e,fe(t));var Se=(e,t)=>{for(var n in t)K(e,n,{get:t[n],enumerable:!0})},ve=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of he(t))!re.call(e,s)&&s!==n&&K(e,s,{get:()=>t[s],enumerable:!(a=me(t,s))||a.enumerable});return e};var Ie=e=>ve(K({},"__esModule",{value:!0}),e);var at={};Se(at,{deriveSessionSegment:()=>q,detectDeviceClass:()=>R,detectTimeOfDay:()=>M,detectTrafficSource:()=>U,init:()=>it,preloadAssignments:()=>Y,readSessionCookie:()=>H,referrerDomainFromReferer:()=>P});module.exports=Ie(at);var Ee="_snt_uid";var D="_snt_uid";function we(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function be(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Ae(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(a){}}function Ce(e){try{return localStorage.getItem(e)}catch(t){return null}}function xe(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function Te(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function _e(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Oe(e){try{sessionStorage.removeItem(e)}catch(t){}}function ke(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function Ne(e){try{localStorage.removeItem(e)}catch(t){}}function De(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Re={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function se(e){var d,g,l,p,u;if(typeof window=="undefined")return Re;let t=(d=e==null?void 0:e.cookieName)!=null?d:Ee,a=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,s=(u=(p=(l=be(t))!=null?l:Ce(D))!=null?p:Te(D))!=null?u:we();Ae(t,s,a);let i=xe(D,s),r=ke(t),o=i?!1:_e(D,s),c=!i&&!r&&!o;return{getSessionId:()=>s,isEphemeral:()=>c,destroy:()=>{s=null,De(t),Ne(D),Oe(D)}}}var G="_snt_retry";var Ue={push:()=>{},flush:()=>{},destroy:()=>{}};function Pe(e){try{let t=localStorage.getItem(G);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(G),n.slice(-e)):[]}catch(t){return[]}}function z(e,t){try{let a=[...(()=>{try{let s=localStorage.getItem(G);if(!s)return[];let i=JSON.parse(s);return Array.isArray(i)?i:[]}catch(s){return[]}})(),...e].slice(-t);localStorage.setItem(G,JSON.stringify(a))}catch(n){}}function oe(e){var O,k,ee;if(typeof window=="undefined")return Ue;let t=(O=e.flushIntervalMs)!=null?O:5e3,n=(k=e.maxBatchSize)!=null?k:20,a=(ee=e.maxRetrySize)!=null?ee:100,s=e.ingestUrl,i=e.apiKey,r=[],o=new Set,c=[],d=m=>{for(let S of m)g.delete(S),!o.has(S)&&(o.add(S),c.push(S));for(;c.length>500;){let S=c.shift();S&&o.delete(S)}},g=new Set,l=m=>{o.has(m.id)||g.has(m.id)||(g.add(m.id),r.push(m))},p=Pe(a);for(let m of p)l(m);let u=0,f=0,I=m=>{if(m.length===0)return;let S=JSON.stringify(m),b=m.map(A=>A.id),T;try{T=fetch(s,{method:"POST",keepalive:!0,body:S,headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}})}catch(A){z(m,a);for(let J of b)g.delete(J);f++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6));return}let $=A=>{if(A.ok||A.status>=400&&A.status<500&&A.status!==429){d(b),f=0,u=0;return}z(m,a);for(let J of b)g.delete(J);f++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6))};T instanceof Promise?T.then($).catch(()=>{z(m,a);for(let A of b)g.delete(A);f++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6))}):$(T)},E=typeof TextEncoder!="undefined"?new TextEncoder:null,x=m=>E?E.encode(m).length:m.length,L=m=>{let S=[],b=2;for(let T of m){let $=x(JSON.stringify(T))+1;if(S.length>0&&b+$>57344||S.length>=n)break;S.push(T),b+=$}return S},w=()=>{try{if(Date.now()<u)return;for(;r.length>0;){let m=r.filter(b=>!o.has(b.id));if(r.length=0,m.length===0)break;let S=L(m);if(S.length===0)break;S.length<m.length&&r.push(...m.slice(S.length)),I(S)}}catch(m){}},h=!0,y=null;y=setInterval(()=>{h&&w()},t);let v=()=>{document.visibilityState==="hidden"&&w()},_=()=>{w()};return document.addEventListener("visibilitychange",v),window.addEventListener("beforeunload",_),{push(m){l(m),r.length>=n&&w()},flush:w,destroy(){h=!1,y!==null&&(clearInterval(y),y=null),document.removeEventListener("visibilitychange",v),window.removeEventListener("beforeunload",_),w()}}}var F="_snt_asgn_";function B(e,t){return`${e}:${t}`}function Me(e,t){return`${F}${e}_${t}`}function Q(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(F)&&e.push(n)}return e}catch(e){return[]}}function ie(e=18e5){let t=new Map,n=s=>s.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let s of Q())try{let i=localStorage.getItem(s);if(!i)continue;let r=JSON.parse(i);if(n(r)){localStorage.removeItem(s);continue}let o=s.slice(F.length),c=o.lastIndexOf("_");if(c<0)continue;let d=o.slice(0,c),g=o.slice(c+1);t.set(B(d,g),r)}catch(i){}})(),{get(s,i){let r=t.get(B(s,i));return r?n(r)?(t.delete(B(s,i)),null):r:null},set(s,i,r){let o=B(s,i);t.set(o,r);try{localStorage.setItem(Me(s,i),JSON.stringify(r))}catch(c){}},invalidate(s){let i=`${s}:`;for(let r of[...t.keys()])r.startsWith(i)&&t.delete(r);for(let r of Q()){let o=r.slice(F.length),c=o.lastIndexOf("_");if(c<0)continue;if(o.slice(0,c)===s)try{localStorage.removeItem(r)}catch(g){}}},clear(){t.clear();for(let s of Q())try{localStorage.removeItem(s)}catch(i){}}}}function R(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function U(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(s){}let a=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(a)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(a)?"social":"referral"}catch(n){return"direct"}}function P(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function M(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function q(e){let t=W("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function W(e,t){var i,r,o,c,d,g,l;let n=(r=(i=t==null?void 0:t.userAgent)==null?void 0:i.trim())!=null?r:"",a=(c=(o=t==null?void 0:t.referer)==null?void 0:o.trim())!=null?c:"",s=(d=t==null?void 0:t.now)!=null?d:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?R(n):"desktop",trafficSource:a?U(a,t==null?void 0:t.appOrigin):"direct",referrerDomain:P(a),timeOfDay:M(s),dayOfWeek:(l=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?l:"sun"}}var $e=1500;function ae(e,t,n){let a=new AbortController,s=setTimeout(()=>a.abort(),n);return fetch(e,N(C({},t),{signal:a.signal})).finally(()=>clearTimeout(s))}async function Y(e,t,n){var c;let a=(c=n.timeoutMs)!=null?c:$e,s={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(s.Origin=n.origin);let i=W(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await ae(`${n.baseUrl}/sessions`,{method:"POST",headers:s,body:JSON.stringify(i)},a)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(d){}let r=await Promise.allSettled(e.map(async({id:d,variantIds:g})=>{let l=await ae(`${n.baseUrl}/assign`,{method:"POST",headers:s,body:JSON.stringify({sessionId:t,componentId:d,variantIds:g})},a);if(!l.ok)return null;let p=await l.json();return{id:d,variantId:p.variantId}})),o={};for(let d of r)d.status==="fulfilled"&&d.value&&(o[d.value.id]=d.value.variantId);return o}function H(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}var Le="https://sentient-api.fly.dev/v1/events";function Ke(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var j={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Ge(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,a]of t)n.startsWith("utm_")&&(e[n]=a);return e}catch(e){return{}}}function Be(e){return e.replace(/\/events\/?$/,"")}function ce(e){var I,E,x,L,w;if(typeof window=="undefined"||e.consent===!1)return j;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."),j;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),j;let t=(I=e.ingestUrl)!=null?I:Le,n=Date.now(),a=se(),s=ie(),i=oe({ingestUrl:t,apiKey:e.apiKey}),r=Be(t),o={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=R((E=navigator.userAgent)!=null?E:""),d=typeof window!="undefined"?window.location.origin:void 0,g=U((x=document.referrer)!=null?x:"",d),l=(L=e.sessionSegment)!=null?L:`${c}:${g}`;if(e.initialAssignments)for(let[h,y]of Object.entries(e.initialAssignments))s.set(h,l,{variantId:y,assignedAt:Date.now(),segment:l,confidence:1});let p=Promise.resolve(),u=a.getSessionId();if(u){let h=P((w=document.referrer)!=null?w:""),y=C({sessionId:u,deviceClass:c,trafficSource:g,referrerDomain:h,utmParams:Ge(),timeOfDay:M(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:a.isEphemeral()},e.userId?{userId:e.userId}:{});try{p=fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(y),headers:o}).then(v=>{v.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(v){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:i});let f={goal(h,y={}){let v=a.getSessionId();v&&p.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:v,name:h,metadata:y}),headers:o}).catch(()=>{})})},identify(h){let y=a.getSessionId();y&&p.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,userId:h,ephemeral:a.isEphemeral()}),headers:o}).catch(()=>{})})},track(h){let y=a.getSessionId();if(!y)return;let v=N(C({},h),{id:Ke(),sessionId:y,timestamp:Date.now(),timeInSession:Date.now()-n});i.push(v),e.debug&&console.log("[sentient] track",v)},getAssignment(h,y){return s.get(h,y)},async assign(h,y){let v=a.getSessionId();if(!v)return null;let _=s.get(h,l);if(_)return{variantId:_.variantId,assignmentTtlMs:0,content:_.content};await p;try{let O=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify({sessionId:v,componentId:h,variantIds:y}),headers:o});if(!O.ok)return null;let k=await O.json();return s.set(h,l,{variantId:k.variantId,assignedAt:Date.now(),segment:l,confidence:1,content:k.content}),k}catch(O){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){i.destroy(),a.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let h=window;h.__sentient&&(h.__sentient.client=f)}return f}var Fe=new Set(["SECTION","ARTICLE","MAIN","DIV"]),je="h1, h2, h3",Je={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function V(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function ze(e){var t,n,a;try{let s=e;for(let i of Object.keys(s)){if(!i.startsWith("__reactFiber")&&!i.startsWith("__reactInternalInstance"))continue;let r=s[i],o=(a=(t=r==null?void 0:r.type)==null?void 0:t.displayName)!=null?a:(n=r==null?void 0:r.type)==null?void 0:n.name;if(o&&o.length>1)return o}}catch(s){}}function Qe(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}function qe(e){let t=e.getAttribute("data-sentient-type");if(t)return t;let n=e.getAttribute("role");return n||"generic"}function We(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function Ye(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function X(e,t){var a,s,i;let n=e.querySelector(je);return{componentId:We(e),semanticType:qe(e),ariaLabel:(a=e.getAttribute("aria-label"))!=null?a:void 0,headingText:(i=(s=n==null?void 0:n.textContent)==null?void 0:s.trim())!=null?i:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:Ye(e),reactComponentName:ze(e),dataAttributes:Qe(e)}}function de(e){var i;let t=[],n=new Set,a="__root__",s=new Map;for(let[r,o]of e){let c=r.parentElement,d=a;for(;c;){if(e.has(c)){d=e.get(c);let l=e.get(r),p=`${d}->${l}`;!n.has(p)&&d!==l&&(n.add(p),t.push({fromComponentId:d,toComponentId:l,weight:.6}));break}c=c.parentElement}let g=(i=s.get(d))!=null?i:[];g.push(r),s.set(d,g)}for(let r of s.values())if(!(r.length<2))for(let o=0;o<r.length;o++)for(let c=o+1;c<r.length;c++){let d=e.get(r[o]),g=e.get(r[c]);if(d===g)continue;let l=`${d}->${g}::sib`,p=`${g}->${d}::sib`;n.has(l)||(n.add(l),t.push({fromComponentId:d,toComponentId:g,weight:.3})),n.has(p)||(n.add(p),t.push({fromComponentId:g,toComponentId:d,weight:.3}))}return t}function He(e){let t=[],n=new Set,a=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(r=>{if(r instanceof Element&&!n.has(r)){n.add(r);let o=X(r,e);t.push(o),a.set(r,o.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(r=>{if(!(r instanceof Element)||n.has(r))return;let o=r.hasAttribute("aria-label"),c=r.hasAttribute("data-sentient-id");if(!o&&!c)return;n.add(r);let d=X(r,e);t.push(d),a.set(r,d.componentId)}),{nodes:t,edges:de(a)}}function ue(){if(typeof window=="undefined")return Je;let e=null,t=0,n=null,a=o=>{try{let c=window.getComputedStyle(o),d=parseFloat(c.fontSize)||12,g=parseFloat(c.zIndex)||0,l=o.getBoundingClientRect(),p=Math.max(l.top,0),u=window.innerHeight||1,f=1/(p/u+1),I=V(d,12,48)*.4+V(f,0,1)*.4+V(g,0,100)*.2;return Math.max(0,Math.min(1,I))}catch(c){return .5}};return{scan:()=>new Promise(o=>{let c=()=>{let{nodes:d,edges:g}=He(a);o({nodes:d,edges:g,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(c,{timeout:100}):c()}catch(d){c()}}),observe:o=>{n=o;try{e=new MutationObserver(c=>{let d=[],g=new Map;for(let l of c)l.type==="childList"&&l.addedNodes.forEach(p=>{if(!(p instanceof Element)||!Fe.has(p.tagName))return;let u=p.hasAttribute("data-sentient-id"),f=p.hasAttribute("aria-label");if(!u&&!f)return;let I=X(p,a);d.push(I),g.set(p,I.componentId)});d.length>0&&n&&n({nodes:d,edges:de(g),addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(c){}},getProminenceScore:a,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(o){}t=0,n=null}}}var Z="_snt_graph_nodes",ge="_snt_graph_edges",Ve={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function Xe(e){var t;return(t=Ve[e])!=null?t:[]}function Ze(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function et(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var tt=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function nt(e){return tt.has(e)?e:"generic"}function rt(e,t,n){let a=`${e}:${t}:${n.join(",")}`,s=5381;for(let i=0;i<a.length;i++)s=(s<<5)+s+a.charCodeAt(i)&4294967295;return(s>>>0).toString(16).padStart(8,"0")}function le(e){let t=new Map,n=new Map,a=()=>{typeof window!="undefined"&&et(Z,[...t.values()])},s=i=>{var r;try{let o=JSON.parse(i);t.clear();for(let c of(r=o.pageNodes)!=null?r:[])t.set(c.componentId,c)}catch(o){}};if(typeof window!="undefined"){let i=Ze(Z,[]);for(let r of i)t.set(r.componentId,r);try{localStorage.removeItem(ge)}catch(r){}}return{addPageNode(i){t.set(i.componentId,i),a()},addStructuralEdge(i){let r=`${i.fromComponentId}->${i.toComponentId}`;n.set(r,i)},syncOnce(){var r,o;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let i=[...t.values()];if(i.length!==0)try{let c=new Map;for(let u of i){let f=(r=c.get(u.semanticType))!=null?r:[];f.push(u),c.set(u.semanticType,f)}let d=[],g=new Set;for(let u of i)for(let f of Xe(u.semanticType)){let I=(o=c.get(f))!=null?o:[];for(let E of I){if(E.componentId===u.componentId)continue;let x=`semantic:${u.componentId}->${E.componentId}`;g.has(x)||(g.add(x),d.push({fromComponentId:u.componentId,toComponentId:E.componentId,type:"semantic",weight:.4,confidence:.9}))}}let l=new Set(i.map(u=>u.componentId));for(let u of n.values()){if(!l.has(u.fromComponentId)||!l.has(u.toComponentId))continue;let f=`structural:${u.fromComponentId}->${u.toComponentId}`;g.has(f)||(g.add(f),d.push({fromComponentId:u.fromComponentId,toComponentId:u.toComponentId,type:"structural",weight:u.weight,confidence:1}))}let p={pageUrl:window.location.href,nodes:i.map(u=>{let f=nt(u.semanticType);return{componentId:u.componentId,semanticType:f,answers:u.answers,contentHash:rt(u.componentId,f,u.answers),prominenceScore:u.prominenceScore,depthInPage:u.depth}}),edges:d};fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:C({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(p)}).catch(()=>{})}catch(c){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},serialize(){return JSON.stringify({pageNodes:[...t.values()]})},restore:s,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(Z),localStorage.removeItem(ge)}catch(i){}}}}var st="https://sentient-api.fly.dev/v1/events";function ot(){try{let e=document.cookie.match(/(?:^|; )_snt_uid=([^;]*)/);return e?decodeURIComponent(e[1]):void 0}catch(e){return}}function it(e){var i;let t=ce(e);if(!e.graph||typeof window=="undefined")return t;let n=ue(),a=(i=e.ingestUrl)!=null?i:st,s=le({syncUrl:a.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:ot()});try{let r=localStorage.getItem("_snt_graph_nodes");r&&s.restore(JSON.stringify({pageNodes:JSON.parse(r)}))}catch(r){}return n.scan().then(r=>{for(let o of r.nodes)s.addPageNode({id:o.componentId,componentId:o.componentId,semanticType:o.semanticType,answers:o.headingText?[o.headingText]:[],prominenceScore:o.prominenceScore,depth:o.depth});for(let o of r.edges)s.addStructuralEdge(o);s.syncOnce()}),n.observe(r=>{for(let o of r.nodes)s.addPageNode({id:o.componentId,componentId:o.componentId,semanticType:o.semanticType,answers:o.headingText?[o.headingText]:[],prominenceScore:o.prominenceScore,depth:o.depth});for(let o of r.edges)s.addStructuralEdge(o)}),N(C({},t),{getGraph:()=>s.snapshot(),destroy:()=>{n.destroy(),s.destroy(),t.destroy()}})}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,init,preloadAssignments,readSessionCookie,referrerDomainFromReferer});
1
+ "use strict";var B=Object.defineProperty,fe=Object.defineProperties,he=Object.getOwnPropertyDescriptor,ye=Object.getOwnPropertyDescriptors,Se=Object.getOwnPropertyNames,te=Object.getOwnPropertySymbols;var re=Object.prototype.hasOwnProperty,ve=Object.prototype.propertyIsEnumerable;var ne=(e,t,n)=>t in e?B(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,A=(e,t)=>{for(var n in t||(t={}))re.call(t,n)&&ne(e,n,t[n]);if(te)for(var n of te(t))ve.call(t,n)&&ne(e,n,t[n]);return e},O=(e,t)=>fe(e,ye(t));var Ie=(e,t)=>{for(var n in t)B(e,n,{get:t[n],enumerable:!0})},we=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Se(t))!re.call(e,s)&&s!==n&&B(e,s,{get:()=>t[s],enumerable:!(a=he(t,s))||a.enumerable});return e};var Ee=e=>we(B({},"__esModule",{value:!0}),e);var ut={};Ie(ut,{deriveSessionSegment:()=>W,detectDeviceClass:()=>N,detectTimeOfDay:()=>P,detectTrafficSource:()=>R,init:()=>dt,preloadAssignments:()=>H,readSessionCookie:()=>V,referrerDomainFromReferer:()=>U});module.exports=Ee(ut);var be="_snt_uid";var D="_snt_uid";function Ce(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function Ae(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function xe(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(a){}}function Te(e){try{return localStorage.getItem(e)}catch(t){return null}}function _e(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function ke(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function Oe(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function De(e){try{sessionStorage.removeItem(e)}catch(t){}}function Ne(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function Re(e){try{localStorage.removeItem(e)}catch(t){}}function Ue(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Pe={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function se(e){var d,u,g,m,l;if(typeof window=="undefined")return Pe;let t=(d=e==null?void 0:e.cookieName)!=null?d:be,a=((u=e==null?void 0:e.cookieTTLDays)!=null?u:365)*24*60*60,s=(l=(m=(g=Ae(t))!=null?g:Te(D))!=null?m:ke(D))!=null?l:Ce();xe(t,s,a);let o=_e(D,s),r=Ne(t),i=o?!1:Oe(D,s),c=!o&&!r&&!i;return{getSessionId:()=>s,isEphemeral:()=>c,destroy:()=>{s=null,Ue(t),Re(D),De(D)}}}var j="_snt_retry";var Me={push:()=>{},flush:()=>{},destroy:()=>{}};function $e(e){try{let t=localStorage.getItem(j);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(j),n.slice(-e)):[]}catch(t){return[]}}function Q(e,t){try{let a=[...(()=>{try{let s=localStorage.getItem(j);if(!s)return[];let o=JSON.parse(s);return Array.isArray(o)?o:[]}catch(s){return[]}})(),...e].slice(-t);localStorage.setItem(j,JSON.stringify(a))}catch(n){}}function oe(e){var $,k,T;if(typeof window=="undefined")return Me;let t=($=e.flushIntervalMs)!=null?$:5e3,n=(k=e.maxBatchSize)!=null?k:20,a=(T=e.maxRetrySize)!=null?T:100,s=e.ingestUrl,o=e.apiKey,r=[],i=new Set,c=[],d=p=>{for(let h of p)u.delete(h),!i.has(h)&&(i.add(h),c.push(h));for(;c.length>500;){let h=c.shift();h&&i.delete(h)}},u=new Set,g=p=>{i.has(p.id)||u.has(p.id)||(u.add(p.id),r.push(p))},m=$e(a);for(let p of m)g(p);let l=0,f=0,I=p=>{if(p.length===0)return;let h=JSON.stringify(p),b=p.map(C=>C.id),_;try{_=fetch(s,{method:"POST",keepalive:!0,body:h,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(C){Q(p,a);for(let z of b)u.delete(z);f++,l=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6));return}let L=C=>{if(C.ok||C.status>=400&&C.status<500&&C.status!==429){d(b),f=0,l=0;return}Q(p,a);for(let z of b)u.delete(z);f++,l=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6))};_ instanceof Promise?_.then(L).catch(()=>{Q(p,a);for(let C of b)u.delete(C);f++,l=Date.now()+Math.min(6e4,1e3*2**Math.min(f,6))}):L(_)},w=typeof TextEncoder!="undefined"?new TextEncoder:null,x=p=>w?w.encode(p).length:p.length,G=p=>{let h=[],b=2;for(let _ of p){let L=x(JSON.stringify(_))+1;if(h.length>0&&b+L>57344||h.length>=n)break;h.push(_),b+=L}return h},E=()=>{try{if(Date.now()<l)return;for(;r.length>0;){let p=r.filter(b=>!i.has(b.id));if(r.length=0,p.length===0)break;let h=G(p);if(h.length===0)break;h.length<p.length&&r.push(...p.slice(h.length)),I(h)}}catch(p){}},y=!0,S=null;S=setInterval(()=>{y&&E()},t);let v=()=>{document.visibilityState==="hidden"&&E()},M=()=>{E()};return document.addEventListener("visibilitychange",v),window.addEventListener("beforeunload",M),{push(p){g(p),r.length>=n&&E()},flush:E,destroy(){y=!1,S!==null&&(clearInterval(S),S=null),document.removeEventListener("visibilitychange",v),window.removeEventListener("beforeunload",M),E()}}}var J="_snt_asgn_";function F(e,t){return`${e}:${t}`}function Le(e,t){return`${J}${e}_${t}`}function q(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(J)&&e.push(n)}return e}catch(e){return[]}}function ie(e=18e5){let t=new Map,n=s=>s.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let s of q())try{let o=localStorage.getItem(s);if(!o)continue;let r=JSON.parse(o);if(n(r)){localStorage.removeItem(s);continue}let i=s.slice(J.length),c=i.lastIndexOf("_");if(c<0)continue;let d=i.slice(0,c),u=i.slice(c+1);t.set(F(d,u),r)}catch(o){}})(),{get(s,o){let r=t.get(F(s,o));return r?n(r)?(t.delete(F(s,o)),null):r:null},set(s,o,r){let i=F(s,o);t.set(i,r);try{localStorage.setItem(Le(s,o),JSON.stringify(r))}catch(c){}},invalidate(s){let o=`${s}:`;for(let r of[...t.keys()])r.startsWith(o)&&t.delete(r);for(let r of q()){let i=r.slice(J.length),c=i.lastIndexOf("_");if(c<0)continue;if(i.slice(0,c)===s)try{localStorage.removeItem(r)}catch(u){}}},clear(){t.clear();for(let s of q())try{localStorage.removeItem(s)}catch(o){}}}}function N(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function R(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(s){}let a=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(a)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(a)?"social":"referral"}catch(n){return"direct"}}function U(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function P(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function W(e){let t=Y("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function Y(e,t){var o,r,i,c,d,u,g;let n=(r=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?r:"",a=(c=(i=t==null?void 0:t.referer)==null?void 0:i.trim())!=null?c:"",s=(d=t==null?void 0:t.now)!=null?d:new Date;return{sessionId:e,ephemeral:!1,utmParams:(u=t==null?void 0:t.utmParams)!=null?u:{},deviceClass:n?N(n):"desktop",trafficSource:a?R(a,t==null?void 0:t.appOrigin):"direct",referrerDomain:U(a),timeOfDay:P(s),dayOfWeek:(g=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?g:"sun"}}var Ke=1500;function ae(e,t,n){let a=new AbortController,s=setTimeout(()=>a.abort(),n);return fetch(e,O(A({},t),{signal:a.signal})).finally(()=>clearTimeout(s))}async function H(e,t,n){var c;let a=(c=n.timeoutMs)!=null?c:Ke,s={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(s.Origin=n.origin);let o=Y(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await ae(`${n.baseUrl}/sessions`,{method:"POST",headers:s,body:JSON.stringify(o)},a)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(d){}let r=await Promise.allSettled(e.map(async({id:d,variantIds:u})=>{let g=await ae(`${n.baseUrl}/assign`,{method:"POST",headers:s,body:JSON.stringify({sessionId:t,componentId:d,variantIds:u})},a);if(!g.ok)return null;let m=await g.json();return{id:d,variantId:m.variantId}})),i={};for(let d of r)d.status==="fulfilled"&&d.value&&(i[d.value.id]=d.value.variantId);return i}function V(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}var ce="https://sentient-api.fly.dev/v1/events",Ge=null,Be=null;function je(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var K={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Fe(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,a]of t)n.startsWith("utm_")&&(e[n]=a);return e}catch(e){return{}}}function de(e){return e.replace(/\/events\/?$/,"")}function Je(e){var s;let t=de((s=e.ingestUrl)!=null?s:ce),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},a={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(o,r,i){try{let c=new URLSearchParams({componentId:o});for(let g of r!=null?r:[])c.append("variantIds[]",g);let d=await fetch(`${t}/winner?${c.toString()}`,{headers:n});return d.ok?{variantId:(await d.json()).variantId,assignmentTtlMs:0}:r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}catch(c){return r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return Be=o=>{a=o},{track:o=>a.track(o),goal:(o,r)=>a.goal(o,r),identify:o=>a.identify(o),getAssignment:(o,r)=>a.getAssignment(o,r),assign:(o,r,i,c)=>a.assign(o,r,i,c),getGraph:()=>a.getGraph(),destroy:()=>a.destroy()}}function ue(e){var I,w,x,G,E;if(typeof window=="undefined")return K;if(Ge=e,e.consent===!1)return e.preConsentBehavior==="statistical_winner"?!e.apiKey||!e.apiKey.startsWith("pk_")?(console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),K):Je(e):K;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."),K;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),K;let t=(I=e.ingestUrl)!=null?I:ce,n=Date.now(),a=se(),s=ie(),o=oe({ingestUrl:t,apiKey:e.apiKey}),r=de(t),i={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=N((w=navigator.userAgent)!=null?w:""),d=typeof window!="undefined"?window.location.origin:void 0,u=R((x=document.referrer)!=null?x:"",d),g=(G=e.sessionSegment)!=null?G:`${c}:${u}`;if(e.initialAssignments)for(let[y,S]of Object.entries(e.initialAssignments))s.set(y,g,{variantId:S,assignedAt:Date.now(),segment:g,confidence:1});let m=Promise.resolve(),l=a.getSessionId();if(l){let y=U((E=document.referrer)!=null?E:""),S=A({sessionId:l,deviceClass:c,trafficSource:u,referrerDomain:y,utmParams:Fe(),timeOfDay:P(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:a.isEphemeral()},e.userId?{userId:e.userId}:{});try{m=fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(S),headers:i}).then(v=>{v.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(v){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:o});let f={goal(y,S={}){let v=a.getSessionId();v&&m.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:v,name:y,metadata:S}),headers:i}).catch(()=>{})})},identify(y){let S=a.getSessionId();S&&m.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:S,userId:y,ephemeral:a.isEphemeral()}),headers:i}).catch(()=>{})})},track(y){let S=a.getSessionId();if(!S)return;let v=O(A({},y),{id:je(),sessionId:S,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(v),e.debug&&console.log("[sentient] track",v)},getAssignment(y,S){return s.get(y,S)},async assign(y,S,v,M){let $=a.getSessionId();if(!$)return null;let k=s.get(y,g);if(k)return{variantId:k.variantId,assignmentTtlMs:0,content:k.content};await m;try{let T={sessionId:$,componentId:y,variantIds:S};M!==void 0?T.agentDataByVariant=M:v!==void 0&&(T.agentData=v);let p=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(T),headers:i});if(!p.ok)return null;let h=await p.json();return s.set(y,g,{variantId:h.variantId,assignedAt:Date.now(),segment:g,confidence:1,content:h.content}),h}catch(T){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),a.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let y=window;y.__sentient&&(y.__sentient.client=f)}return f}var ze=new Set(["SECTION","ARTICLE","MAIN","DIV"]),Qe="h1, h2, h3",qe={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function X(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function We(e){var t,n,a;try{let s=e;for(let o of Object.keys(s)){if(!o.startsWith("__reactFiber")&&!o.startsWith("__reactInternalInstance"))continue;let r=s[o],i=(a=(t=r==null?void 0:r.type)==null?void 0:t.displayName)!=null?a:(n=r==null?void 0:r.type)==null?void 0:n.name;if(i&&i.length>1)return i}}catch(s){}}function Ye(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}function He(e){let t=e.getAttribute("data-sentient-type");if(t)return t;let n=e.getAttribute("role");return n||"generic"}function Ve(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function Xe(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function Z(e,t){var a,s,o;let n=e.querySelector(Qe);return{componentId:Ve(e),semanticType:He(e),ariaLabel:(a=e.getAttribute("aria-label"))!=null?a:void 0,headingText:(o=(s=n==null?void 0:n.textContent)==null?void 0:s.trim())!=null?o:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:Xe(e),reactComponentName:We(e),dataAttributes:Ye(e)}}function le(e){var o;let t=[],n=new Set,a="__root__",s=new Map;for(let[r,i]of e){let c=r.parentElement,d=a;for(;c;){if(e.has(c)){d=e.get(c);let g=e.get(r),m=`${d}->${g}`;!n.has(m)&&d!==g&&(n.add(m),t.push({fromComponentId:d,toComponentId:g,weight:.6}));break}c=c.parentElement}let u=(o=s.get(d))!=null?o:[];u.push(r),s.set(d,u)}for(let r of s.values())if(!(r.length<2))for(let i=0;i<r.length;i++)for(let c=i+1;c<r.length;c++){let d=e.get(r[i]),u=e.get(r[c]);if(d===u)continue;let g=`${d}->${u}::sib`,m=`${u}->${d}::sib`;n.has(g)||(n.add(g),t.push({fromComponentId:d,toComponentId:u,weight:.3})),n.has(m)||(n.add(m),t.push({fromComponentId:u,toComponentId:d,weight:.3}))}return t}function Ze(e){let t=[],n=new Set,a=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(r=>{if(r instanceof Element&&!n.has(r)){n.add(r);let i=Z(r,e);t.push(i),a.set(r,i.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(r=>{if(!(r instanceof Element)||n.has(r))return;let i=r.hasAttribute("aria-label"),c=r.hasAttribute("data-sentient-id");if(!i&&!c)return;n.add(r);let d=Z(r,e);t.push(d),a.set(r,d.componentId)}),{nodes:t,edges:le(a)}}function ge(){if(typeof window=="undefined")return qe;let e=null,t=0,n=null,a=i=>{try{let c=window.getComputedStyle(i),d=parseFloat(c.fontSize)||12,u=parseFloat(c.zIndex)||0,g=i.getBoundingClientRect(),m=Math.max(g.top,0),l=window.innerHeight||1,f=1/(m/l+1),I=X(d,12,48)*.4+X(f,0,1)*.4+X(u,0,100)*.2;return Math.max(0,Math.min(1,I))}catch(c){return .5}};return{scan:()=>new Promise(i=>{let c=()=>{let{nodes:d,edges:u}=Ze(a);i({nodes:d,edges:u,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(c,{timeout:100}):c()}catch(d){c()}}),observe:i=>{n=i;try{e=new MutationObserver(c=>{let d=[],u=new Map;for(let g of c)g.type==="childList"&&g.addedNodes.forEach(m=>{if(!(m instanceof Element)||!ze.has(m.tagName))return;let l=m.hasAttribute("data-sentient-id"),f=m.hasAttribute("aria-label");if(!l&&!f)return;let I=Z(m,a);d.push(I),u.set(m,I.componentId)});d.length>0&&n&&n({nodes:d,edges:le(u),addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(c){}},getProminenceScore:a,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(i){}t=0,n=null}}}var ee="_snt_graph_nodes",pe="_snt_graph_edges",et={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function tt(e){var t;return(t=et[e])!=null?t:[]}function nt(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function rt(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var st=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function ot(e){return st.has(e)?e:"generic"}function it(e,t,n){let a=`${e}:${t}:${n.join(",")}`,s=5381;for(let o=0;o<a.length;o++)s=(s<<5)+s+a.charCodeAt(o)&4294967295;return(s>>>0).toString(16).padStart(8,"0")}function me(e){let t=new Map,n=new Map,a=()=>{typeof window!="undefined"&&rt(ee,[...t.values()])},s=o=>{var r;try{let i=JSON.parse(o);t.clear();for(let c of(r=i.pageNodes)!=null?r:[])t.set(c.componentId,c)}catch(i){}};if(typeof window!="undefined"){let o=nt(ee,[]);for(let r of o)t.set(r.componentId,r);try{localStorage.removeItem(pe)}catch(r){}}return{addPageNode(o){t.set(o.componentId,o),a()},addStructuralEdge(o){let r=`${o.fromComponentId}->${o.toComponentId}`;n.set(r,o)},syncOnce(){var r,i;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let o=[...t.values()];if(o.length!==0)try{let c=new Map;for(let l of o){let f=(r=c.get(l.semanticType))!=null?r:[];f.push(l),c.set(l.semanticType,f)}let d=[],u=new Set;for(let l of o)for(let f of tt(l.semanticType)){let I=(i=c.get(f))!=null?i:[];for(let w of I){if(w.componentId===l.componentId)continue;let x=`semantic:${l.componentId}->${w.componentId}`;u.has(x)||(u.add(x),d.push({fromComponentId:l.componentId,toComponentId:w.componentId,type:"semantic",weight:.4,confidence:.9}))}}let g=new Set(o.map(l=>l.componentId));for(let l of n.values()){if(!g.has(l.fromComponentId)||!g.has(l.toComponentId))continue;let f=`structural:${l.fromComponentId}->${l.toComponentId}`;u.has(f)||(u.add(f),d.push({fromComponentId:l.fromComponentId,toComponentId:l.toComponentId,type:"structural",weight:l.weight,confidence:1}))}let m={pageUrl:window.location.href,nodes:o.map(l=>{let f=ot(l.semanticType);return{componentId:l.componentId,semanticType:f,answers:l.answers,contentHash:it(l.componentId,f,l.answers),prominenceScore:l.prominenceScore,depthInPage:l.depth}}),edges:d};fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:A({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(m)}).catch(()=>{})}catch(c){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},serialize(){return JSON.stringify({pageNodes:[...t.values()]})},restore:s,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(ee),localStorage.removeItem(pe)}catch(o){}}}}var at="https://sentient-api.fly.dev/v1/events";function ct(){try{let e=document.cookie.match(/(?:^|; )_snt_uid=([^;]*)/);return e?decodeURIComponent(e[1]):void 0}catch(e){return}}function dt(e){var o;let t=ue(e);if(!e.graph||typeof window=="undefined")return t;let n=ge(),a=(o=e.ingestUrl)!=null?o:at,s=me({syncUrl:a.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:ct()});try{let r=localStorage.getItem("_snt_graph_nodes");r&&s.restore(JSON.stringify({pageNodes:JSON.parse(r)}))}catch(r){}return n.scan().then(r=>{for(let i of r.nodes)s.addPageNode({id:i.componentId,componentId:i.componentId,semanticType:i.semanticType,answers:i.headingText?[i.headingText]:[],prominenceScore:i.prominenceScore,depth:i.depth});for(let i of r.edges)s.addStructuralEdge(i);s.syncOnce()}),n.observe(r=>{for(let i of r.nodes)s.addPageNode({id:i.componentId,componentId:i.componentId,semanticType:i.semanticType,answers:i.headingText?[i.headingText]:[],prominenceScore:i.prominenceScore,depth:i.depth});for(let i of r.edges)s.addStructuralEdge(i)}),O(A({},t),{getGraph:()=>s.snapshot(),destroy:()=>{n.destroy(),s.destroy(),t.destroy()}})}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,init,preloadAssignments,readSessionCookie,referrerDomainFromReferer});
@@ -1 +1 @@
1
- import{a as h,b,c as x,d as _,e as O,f as M,g as R,h as P,i as D,k as v}from"./chunk-6B5JZHAF.mjs";var G=new Set(["SECTION","ARTICLE","MAIN","DIV"]),k="h1, h2, h3",$={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function S(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function L(e){var t,n,p;try{let d=e;for(let s of Object.keys(d)){if(!s.startsWith("__reactFiber")&&!s.startsWith("__reactInternalInstance"))continue;let o=d[s],r=(p=(t=o==null?void 0:o.type)==null?void 0:t.displayName)!=null?p:(n=o==null?void 0:o.type)==null?void 0:n.name;if(r&&r.length>1)return r}}catch(d){}}function U(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}function j(e){let t=e.getAttribute("data-sentient-type");if(t)return t;let n=e.getAttribute("role");return n||"generic"}function F(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function K(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function I(e,t){var p,d,s;let n=e.querySelector(k);return{componentId:F(e),semanticType:j(e),ariaLabel:(p=e.getAttribute("aria-label"))!=null?p:void 0,headingText:(s=(d=n==null?void 0:n.textContent)==null?void 0:d.trim())!=null?s:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:K(e),reactComponentName:L(e),dataAttributes:U(e)}}function w(e){var s;let t=[],n=new Set,p="__root__",d=new Map;for(let[o,r]of e){let a=o.parentElement,c=p;for(;a;){if(e.has(a)){c=e.get(a);let m=e.get(o),g=`${c}->${m}`;!n.has(g)&&c!==m&&(n.add(g),t.push({fromComponentId:c,toComponentId:m,weight:.6}));break}a=a.parentElement}let u=(s=d.get(c))!=null?s:[];u.push(o),d.set(c,u)}for(let o of d.values())if(!(o.length<2))for(let r=0;r<o.length;r++)for(let a=r+1;a<o.length;a++){let c=e.get(o[r]),u=e.get(o[a]);if(c===u)continue;let m=`${c}->${u}::sib`,g=`${u}->${c}::sib`;n.has(m)||(n.add(m),t.push({fromComponentId:c,toComponentId:u,weight:.3})),n.has(g)||(n.add(g),t.push({fromComponentId:u,toComponentId:c,weight:.3}))}return t}function q(e){let t=[],n=new Set,p=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(o=>{if(o instanceof Element&&!n.has(o)){n.add(o);let r=I(o,e);t.push(r),p.set(o,r.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(o=>{if(!(o instanceof Element)||n.has(o))return;let r=o.hasAttribute("aria-label"),a=o.hasAttribute("data-sentient-id");if(!r&&!a)return;n.add(o);let c=I(o,e);t.push(c),p.set(o,c.componentId)}),{nodes:t,edges:w(p)}}function N(){if(typeof window=="undefined")return $;let e=null,t=0,n=null,p=r=>{try{let a=window.getComputedStyle(r),c=parseFloat(a.fontSize)||12,u=parseFloat(a.zIndex)||0,m=r.getBoundingClientRect(),g=Math.max(m.top,0),i=window.innerHeight||1,f=1/(g/i+1),l=S(c,12,48)*.4+S(f,0,1)*.4+S(u,0,100)*.2;return Math.max(0,Math.min(1,l))}catch(a){return .5}};return{scan:()=>new Promise(r=>{let a=()=>{let{nodes:c,edges:u}=q(p);r({nodes:c,edges:u,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(a,{timeout:100}):a()}catch(c){a()}}),observe:r=>{n=r;try{e=new MutationObserver(a=>{let c=[],u=new Map;for(let m of a)m.type==="childList"&&m.addedNodes.forEach(g=>{if(!(g instanceof Element)||!G.has(g.tagName))return;let i=g.hasAttribute("data-sentient-id"),f=g.hasAttribute("aria-label");if(!i&&!f)return;let l=I(g,p);c.push(l),u.set(g,l.componentId)});c.length>0&&n&&n({nodes:c,edges:w(u),addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(a){}},getProminenceScore:p,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(r){}t=0,n=null}}}var C="_snt_graph_nodes",A="_snt_graph_edges",z={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function H(e){var t;return(t=z[e])!=null?t:[]}function J(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function B(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var V=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function W(e){return V.has(e)?e:"generic"}function Y(e,t,n){let p=`${e}:${t}:${n.join(",")}`,d=5381;for(let s=0;s<p.length;s++)d=(d<<5)+d+p.charCodeAt(s)&4294967295;return(d>>>0).toString(16).padStart(8,"0")}function T(e){let t=new Map,n=new Map,p=()=>{typeof window!="undefined"&&B(C,[...t.values()])},d=s=>{var o;try{let r=JSON.parse(s);t.clear();for(let a of(o=r.pageNodes)!=null?o:[])t.set(a.componentId,a)}catch(r){}};if(typeof window!="undefined"){let s=J(C,[]);for(let o of s)t.set(o.componentId,o);try{localStorage.removeItem(A)}catch(o){}}return{addPageNode(s){t.set(s.componentId,s),p()},addStructuralEdge(s){let o=`${s.fromComponentId}->${s.toComponentId}`;n.set(o,s)},syncOnce(){var o,r;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let s=[...t.values()];if(s.length!==0)try{let a=new Map;for(let i of s){let f=(o=a.get(i.semanticType))!=null?o:[];f.push(i),a.set(i.semanticType,f)}let c=[],u=new Set;for(let i of s)for(let f of H(i.semanticType)){let l=(r=a.get(f))!=null?r:[];for(let y of l){if(y.componentId===i.componentId)continue;let E=`semantic:${i.componentId}->${y.componentId}`;u.has(E)||(u.add(E),c.push({fromComponentId:i.componentId,toComponentId:y.componentId,type:"semantic",weight:.4,confidence:.9}))}}let m=new Set(s.map(i=>i.componentId));for(let i of n.values()){if(!m.has(i.fromComponentId)||!m.has(i.toComponentId))continue;let f=`structural:${i.fromComponentId}->${i.toComponentId}`;u.has(f)||(u.add(f),c.push({fromComponentId:i.fromComponentId,toComponentId:i.toComponentId,type:"structural",weight:i.weight,confidence:1}))}let g={pageUrl:window.location.href,nodes:s.map(i=>{let f=W(i.semanticType);return{componentId:i.componentId,semanticType:f,answers:i.answers,contentHash:Y(i.componentId,f,i.answers),prominenceScore:i.prominenceScore,depthInPage:i.depth}}),edges:c};fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:h({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(g)}).catch(()=>{})}catch(a){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},serialize(){return JSON.stringify({pageNodes:[...t.values()]})},restore:d,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(C),localStorage.removeItem(A)}catch(s){}}}}var Q="https://sentient-api.fly.dev/v1/events";function X(){try{let e=document.cookie.match(/(?:^|; )_snt_uid=([^;]*)/);return e?decodeURIComponent(e[1]):void 0}catch(e){return}}function se(e){var s;let t=v(e);if(!e.graph||typeof window=="undefined")return t;let n=N(),p=(s=e.ingestUrl)!=null?s:Q,d=T({syncUrl:p.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:X()});try{let o=localStorage.getItem("_snt_graph_nodes");o&&d.restore(JSON.stringify({pageNodes:JSON.parse(o)}))}catch(o){}return n.scan().then(o=>{for(let r of o.nodes)d.addPageNode({id:r.componentId,componentId:r.componentId,semanticType:r.semanticType,answers:r.headingText?[r.headingText]:[],prominenceScore:r.prominenceScore,depth:r.depth});for(let r of o.edges)d.addStructuralEdge(r);d.syncOnce()}),n.observe(o=>{for(let r of o.nodes)d.addPageNode({id:r.componentId,componentId:r.componentId,semanticType:r.semanticType,answers:r.headingText?[r.headingText]:[],prominenceScore:r.prominenceScore,depth:r.depth});for(let r of o.edges)d.addStructuralEdge(r)}),b(h({},t),{getGraph:()=>d.snapshot(),destroy:()=>{n.destroy(),d.destroy(),t.destroy()}})}export{R as deriveSessionSegment,x as detectDeviceClass,M as detectTimeOfDay,_ as detectTrafficSource,se as init,P as preloadAssignments,D as readSessionCookie,O as referrerDomainFromReferer};
1
+ import{a as h,b,c as x,d as _,e as O,f as M,g as R,h as P,i as D,l as v}from"./chunk-SAUXPAW5.mjs";var G=new Set(["SECTION","ARTICLE","MAIN","DIV"]),k="h1, h2, h3",$={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function S(e,t,n){return n<=t?0:Math.max(0,Math.min(1,(e-t)/(n-t)))}function L(e){var t,n,p;try{let d=e;for(let s of Object.keys(d)){if(!s.startsWith("__reactFiber")&&!s.startsWith("__reactInternalInstance"))continue;let o=d[s],r=(p=(t=o==null?void 0:o.type)==null?void 0:t.displayName)!=null?p:(n=o==null?void 0:o.type)==null?void 0:n.name;if(r&&r.length>1)return r}}catch(d){}}function U(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}function j(e){let t=e.getAttribute("data-sentient-type");if(t)return t;let n=e.getAttribute("role");return n||"generic"}function F(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function K(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function I(e,t){var p,d,s;let n=e.querySelector(k);return{componentId:F(e),semanticType:j(e),ariaLabel:(p=e.getAttribute("aria-label"))!=null?p:void 0,headingText:(s=(d=n==null?void 0:n.textContent)==null?void 0:d.trim())!=null?s:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:K(e),reactComponentName:L(e),dataAttributes:U(e)}}function w(e){var s;let t=[],n=new Set,p="__root__",d=new Map;for(let[o,r]of e){let a=o.parentElement,c=p;for(;a;){if(e.has(a)){c=e.get(a);let m=e.get(o),g=`${c}->${m}`;!n.has(g)&&c!==m&&(n.add(g),t.push({fromComponentId:c,toComponentId:m,weight:.6}));break}a=a.parentElement}let u=(s=d.get(c))!=null?s:[];u.push(o),d.set(c,u)}for(let o of d.values())if(!(o.length<2))for(let r=0;r<o.length;r++)for(let a=r+1;a<o.length;a++){let c=e.get(o[r]),u=e.get(o[a]);if(c===u)continue;let m=`${c}->${u}::sib`,g=`${u}->${c}::sib`;n.has(m)||(n.add(m),t.push({fromComponentId:c,toComponentId:u,weight:.3})),n.has(g)||(n.add(g),t.push({fromComponentId:u,toComponentId:c,weight:.3}))}return t}function q(e){let t=[],n=new Set,p=new Map;return document.querySelectorAll("[data-sentient-id]").forEach(o=>{if(o instanceof Element&&!n.has(o)){n.add(o);let r=I(o,e);t.push(r),p.set(o,r.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(o=>{if(!(o instanceof Element)||n.has(o))return;let r=o.hasAttribute("aria-label"),a=o.hasAttribute("data-sentient-id");if(!r&&!a)return;n.add(o);let c=I(o,e);t.push(c),p.set(o,c.componentId)}),{nodes:t,edges:w(p)}}function N(){if(typeof window=="undefined")return $;let e=null,t=0,n=null,p=r=>{try{let a=window.getComputedStyle(r),c=parseFloat(a.fontSize)||12,u=parseFloat(a.zIndex)||0,m=r.getBoundingClientRect(),g=Math.max(m.top,0),i=window.innerHeight||1,f=1/(g/i+1),l=S(c,12,48)*.4+S(f,0,1)*.4+S(u,0,100)*.2;return Math.max(0,Math.min(1,l))}catch(a){return .5}};return{scan:()=>new Promise(r=>{let a=()=>{let{nodes:c,edges:u}=q(p);r({nodes:c,edges:u,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(a,{timeout:100}):a()}catch(c){a()}}),observe:r=>{n=r;try{e=new MutationObserver(a=>{let c=[],u=new Map;for(let m of a)m.type==="childList"&&m.addedNodes.forEach(g=>{if(!(g instanceof Element)||!G.has(g.tagName))return;let i=g.hasAttribute("data-sentient-id"),f=g.hasAttribute("aria-label");if(!i&&!f)return;let l=I(g,p);c.push(l),u.set(g,l.componentId)});c.length>0&&n&&n({nodes:c,edges:w(u),addedAt:Date.now()})}),e.observe(document.body,{childList:!0,subtree:!0})}catch(a){}},getProminenceScore:p,destroy:()=>{if(e&&(e.disconnect(),e=null),t&&typeof cancelIdleCallback=="function")try{cancelIdleCallback(t)}catch(r){}t=0,n=null}}}var C="_snt_graph_nodes",A="_snt_graph_edges",z={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function H(e){var t;return(t=z[e])!=null?t:[]}function J(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function B(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var V=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function W(e){return V.has(e)?e:"generic"}function Y(e,t,n){let p=`${e}:${t}:${n.join(",")}`,d=5381;for(let s=0;s<p.length;s++)d=(d<<5)+d+p.charCodeAt(s)&4294967295;return(d>>>0).toString(16).padStart(8,"0")}function T(e){let t=new Map,n=new Map,p=()=>{typeof window!="undefined"&&B(C,[...t.values()])},d=s=>{var o;try{let r=JSON.parse(s);t.clear();for(let a of(o=r.pageNodes)!=null?o:[])t.set(a.componentId,a)}catch(r){}};if(typeof window!="undefined"){let s=J(C,[]);for(let o of s)t.set(o.componentId,o);try{localStorage.removeItem(A)}catch(o){}}return{addPageNode(s){t.set(s.componentId,s),p()},addStructuralEdge(s){let o=`${s.fromComponentId}->${s.toComponentId}`;n.set(o,s)},syncOnce(){var o,r;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let s=[...t.values()];if(s.length!==0)try{let a=new Map;for(let i of s){let f=(o=a.get(i.semanticType))!=null?o:[];f.push(i),a.set(i.semanticType,f)}let c=[],u=new Set;for(let i of s)for(let f of H(i.semanticType)){let l=(r=a.get(f))!=null?r:[];for(let y of l){if(y.componentId===i.componentId)continue;let E=`semantic:${i.componentId}->${y.componentId}`;u.has(E)||(u.add(E),c.push({fromComponentId:i.componentId,toComponentId:y.componentId,type:"semantic",weight:.4,confidence:.9}))}}let m=new Set(s.map(i=>i.componentId));for(let i of n.values()){if(!m.has(i.fromComponentId)||!m.has(i.toComponentId))continue;let f=`structural:${i.fromComponentId}->${i.toComponentId}`;u.has(f)||(u.add(f),c.push({fromComponentId:i.fromComponentId,toComponentId:i.toComponentId,type:"structural",weight:i.weight,confidence:1}))}let g={pageUrl:window.location.href,nodes:s.map(i=>{let f=W(i.semanticType);return{componentId:i.componentId,semanticType:f,answers:i.answers,contentHash:Y(i.componentId,f,i.answers),prominenceScore:i.prominenceScore,depthInPage:i.depth}}),edges:c};fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:h({"Content-Type":"application/json"},e.apiKey?{Authorization:`Bearer ${e.apiKey}`}:{}),body:JSON.stringify(g)}).catch(()=>{})}catch(a){}},snapshot(){return{pageNodes:[...t.values()],capturedAt:Date.now()}},serialize(){return JSON.stringify({pageNodes:[...t.values()]})},restore:d,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(C),localStorage.removeItem(A)}catch(s){}}}}var Q="https://sentient-api.fly.dev/v1/events";function X(){try{let e=document.cookie.match(/(?:^|; )_snt_uid=([^;]*)/);return e?decodeURIComponent(e[1]):void 0}catch(e){return}}function se(e){var s;let t=v(e);if(!e.graph||typeof window=="undefined")return t;let n=N(),p=(s=e.ingestUrl)!=null?s:Q,d=T({syncUrl:p.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:X()});try{let o=localStorage.getItem("_snt_graph_nodes");o&&d.restore(JSON.stringify({pageNodes:JSON.parse(o)}))}catch(o){}return n.scan().then(o=>{for(let r of o.nodes)d.addPageNode({id:r.componentId,componentId:r.componentId,semanticType:r.semanticType,answers:r.headingText?[r.headingText]:[],prominenceScore:r.prominenceScore,depth:r.depth});for(let r of o.edges)d.addStructuralEdge(r);d.syncOnce()}),n.observe(o=>{for(let r of o.nodes)d.addPageNode({id:r.componentId,componentId:r.componentId,semanticType:r.semanticType,answers:r.headingText?[r.headingText]:[],prominenceScore:r.prominenceScore,depth:r.depth});for(let r of o.edges)d.addStructuralEdge(r)}),b(h({},t),{getGraph:()=>d.snapshot(),destroy:()=>{n.destroy(),d.destroy(),t.destroy()}})}export{R as deriveSessionSegment,x as detectDeviceClass,M as detectTimeOfDay,_ as detectTrafficSource,se as init,P as preloadAssignments,D as readSessionCookie,O as referrerDomainFromReferer};
package/dist/index.d.cts CHANGED
@@ -236,6 +236,13 @@ type SentientConfig = {
236
236
  * the user grants or revokes consent mid-session.
237
237
  */
238
238
  consent?: boolean;
239
+ /**
240
+ * Behavior before consent is granted. `'statistical_winner'` fetches the
241
+ * best-performing variant via `GET /v1/winner` — no session or tracking data
242
+ * is stored. `'control'` (default) shows `variantIds[0]` with no API call.
243
+ * Only applies when `consent: false`.
244
+ */
245
+ preConsentBehavior?: 'statistical_winner' | 'control';
239
246
  userId?: string;
240
247
  };
241
248
  type AssignResult = {
@@ -249,14 +256,20 @@ type SentientClient = {
249
256
  identify(userId: string): void;
250
257
  getAssignment(componentId: string, segment: string): Assignment | null;
251
258
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
252
- assign(componentId: string, variantIds?: string[]): Promise<AssignResult | null>;
259
+ assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
253
260
  getGraph(): GraphSnapshot;
254
261
  destroy(): void;
255
262
  };
256
263
 
264
+ /**
265
+ * Upgrades a pre-consent client (created with `consent: false, preConsentBehavior: 'statistical_winner'`)
266
+ * to a fully-tracking client. Call this from your consent management platform callback.
267
+ * For React apps, prefer updating the `consent` prop on `<AdaptiveProvider>`.
268
+ */
269
+ declare function grantConsent(): void;
257
270
  /**
258
271
  * Initializes the Sentient client. Returns a no-op client during SSR.
259
272
  */
260
273
  declare function init(config: SentientConfig): SentientClient;
261
274
 
262
- export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type DecideResult, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type ServerAssignConfig, type ServerAssignments, type SessionConfig, type SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, init, preloadAssignments, preloadDecisions, readSessionCookie, referrerDomainFromReferer };
275
+ export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type DecideResult, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type ServerAssignConfig, type ServerAssignments, type SessionConfig, type SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, grantConsent, init, preloadAssignments, preloadDecisions, readSessionCookie, referrerDomainFromReferer };
package/dist/index.d.ts CHANGED
@@ -236,6 +236,13 @@ type SentientConfig = {
236
236
  * the user grants or revokes consent mid-session.
237
237
  */
238
238
  consent?: boolean;
239
+ /**
240
+ * Behavior before consent is granted. `'statistical_winner'` fetches the
241
+ * best-performing variant via `GET /v1/winner` — no session or tracking data
242
+ * is stored. `'control'` (default) shows `variantIds[0]` with no API call.
243
+ * Only applies when `consent: false`.
244
+ */
245
+ preConsentBehavior?: 'statistical_winner' | 'control';
239
246
  userId?: string;
240
247
  };
241
248
  type AssignResult = {
@@ -249,14 +256,20 @@ type SentientClient = {
249
256
  identify(userId: string): void;
250
257
  getAssignment(componentId: string, segment: string): Assignment | null;
251
258
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
252
- assign(componentId: string, variantIds?: string[]): Promise<AssignResult | null>;
259
+ assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
253
260
  getGraph(): GraphSnapshot;
254
261
  destroy(): void;
255
262
  };
256
263
 
264
+ /**
265
+ * Upgrades a pre-consent client (created with `consent: false, preConsentBehavior: 'statistical_winner'`)
266
+ * to a fully-tracking client. Call this from your consent management platform callback.
267
+ * For React apps, prefer updating the `consent` prop on `<AdaptiveProvider>`.
268
+ */
269
+ declare function grantConsent(): void;
257
270
  /**
258
271
  * Initializes the Sentient client. Returns a no-op client during SSR.
259
272
  */
260
273
  declare function init(config: SentientConfig): SentientClient;
261
274
 
262
- export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type DecideResult, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type ServerAssignConfig, type ServerAssignments, type SessionConfig, type SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, init, preloadAssignments, preloadDecisions, readSessionCookie, referrerDomainFromReferer };
275
+ export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type DecideResult, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type ServerAssignConfig, type ServerAssignments, type SessionConfig, type SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, grantConsent, init, preloadAssignments, preloadDecisions, readSessionCookie, referrerDomainFromReferer };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var N=Object.defineProperty,ae=Object.defineProperties,ce=Object.getOwnPropertyDescriptor,de=Object.getOwnPropertyDescriptors,ue=Object.getOwnPropertyNames,V=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,le=Object.prototype.propertyIsEnumerable;var X=(e,t,n)=>t in e?N(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,C=(e,t)=>{for(var n in t||(t={}))H.call(t,n)&&X(e,n,t[n]);if(V)for(var n of V(t))le.call(t,n)&&X(e,n,t[n]);return e},K=(e,t)=>ae(e,de(t));var ge=(e,t)=>{for(var n in t)N(e,n,{get:t[n],enumerable:!0})},me=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ue(t))!H.call(e,r)&&r!==n&&N(e,r,{get:()=>t[r],enumerable:!(s=ce(t,r))||s.enumerable});return e};var fe=e=>me(N({},"__esModule",{value:!0}),e);var $e={};ge($e,{deriveSessionSegment:()=>ne,detectDeviceClass:()=>O,detectTimeOfDay:()=>P,detectTrafficSource:()=>U,init:()=>Me,preloadAssignments:()=>se,preloadDecisions:()=>oe,readSessionCookie:()=>ie,referrerDomainFromReferer:()=>R});module.exports=fe($e);var pe="_snt_uid";var T="_snt_uid";function ye(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function he(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Se(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(s){}}function ve(e){try{return localStorage.getItem(e)}catch(t){return null}}function xe(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function Ie(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function we(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Ae(e){try{sessionStorage.removeItem(e)}catch(t){}}function be(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function Ee(e){try{localStorage.removeItem(e)}catch(t){}}function _e(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Te={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Z(e){var u,g,p,h,S;if(typeof window=="undefined")return Te;let t=(u=e==null?void 0:e.cookieName)!=null?u:pe,s=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,r=(S=(h=(p=he(t))!=null?p:ve(T))!=null?h:Ie(T))!=null?S:ye();Se(t,r,s);let o=xe(T,r),i=be(t),a=o?!1:we(T,r),d=!o&&!i&&!a;return{getSessionId:()=>r,isEphemeral:()=>d,destroy:()=>{r=null,_e(t),Ee(T),Ae(T)}}}var B="_snt_retry";var ke={push:()=>{},flush:()=>{},destroy:()=>{}};function De(e){try{let t=localStorage.getItem(B);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(B),n.slice(-e)):[]}catch(t){return[]}}function W(e,t){try{let s=[...(()=>{try{let r=localStorage.getItem(B);if(!r)return[];let o=JSON.parse(r);return Array.isArray(o)?o:[]}catch(r){return[]}})(),...e].slice(-t);localStorage.setItem(B,JSON.stringify(s))}catch(n){}}function ee(e){var E,_,q;if(typeof window=="undefined")return ke;let t=(E=e.flushIntervalMs)!=null?E:5e3,n=(_=e.maxBatchSize)!=null?_:20,s=(q=e.maxRetrySize)!=null?q:100,r=e.ingestUrl,o=e.apiKey,i=[],a=new Set,d=[],u=c=>{for(let f of c)g.delete(f),!a.has(f)&&(a.add(f),d.push(f));for(;d.length>500;){let f=d.shift();f&&a.delete(f)}},g=new Set,p=c=>{a.has(c.id)||g.has(c.id)||(g.add(c.id),i.push(c))},h=De(s);for(let c of h)p(c);let S=0,v=0,M=c=>{if(c.length===0)return;let f=JSON.stringify(c),I=c.map(w=>w.id),A;try{A=fetch(r,{method:"POST",keepalive:!0,body:f,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(w){W(c,s);for(let z of I)g.delete(z);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6));return}let D=w=>{if(w.ok||w.status>=400&&w.status<500&&w.status!==429){u(I),v=0,S=0;return}W(c,s);for(let z of I)g.delete(z);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};A instanceof Promise?A.then(D).catch(()=>{W(c,s);for(let w of I)g.delete(w);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):D(A)},k=typeof TextEncoder!="undefined"?new TextEncoder:null,$=c=>k?k.encode(c).length:c.length,L=c=>{let f=[],I=2;for(let A of c){let D=$(JSON.stringify(A))+1;if(f.length>0&&I+D>57344||f.length>=n)break;f.push(A),I+=D}return f},x=()=>{try{if(Date.now()<S)return;for(;i.length>0;){let c=i.filter(I=>!a.has(I.id));if(i.length=0,c.length===0)break;let f=L(c);if(f.length===0)break;f.length<c.length&&i.push(...c.slice(f.length)),M(f)}}catch(c){}},l=!0,m=null;m=setInterval(()=>{l&&x()},t);let y=()=>{document.visibilityState==="hidden"&&x()},b=()=>{x()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",b),{push(c){p(c),i.length>=n&&x()},flush:x,destroy(){l=!1,m!==null&&(clearInterval(m),m=null),document.removeEventListener("visibilitychange",y),window.removeEventListener("beforeunload",b),x()}}}var G="_snt_asgn_";function Q(e,t){return`${e}:${t}`}function Ce(e,t){return`${G}${e}_${t}`}function Y(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(G)&&e.push(n)}return e}catch(e){return[]}}function te(e=18e5){let t=new Map,n=r=>r.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let r of Y())try{let o=localStorage.getItem(r);if(!o)continue;let i=JSON.parse(o);if(n(i)){localStorage.removeItem(r);continue}let a=r.slice(G.length),d=a.lastIndexOf("_");if(d<0)continue;let u=a.slice(0,d),g=a.slice(d+1);t.set(Q(u,g),i)}catch(o){}})(),{get(r,o){let i=t.get(Q(r,o));return i?n(i)?(t.delete(Q(r,o)),null):i:null},set(r,o,i){let a=Q(r,o);t.set(a,i);try{localStorage.setItem(Ce(r,o),JSON.stringify(i))}catch(d){}},invalidate(r){let o=`${r}:`;for(let i of[...t.keys()])i.startsWith(o)&&t.delete(i);for(let i of Y()){let a=i.slice(G.length),d=a.lastIndexOf("_");if(d<0)continue;if(a.slice(0,d)===r)try{localStorage.removeItem(i)}catch(g){}}},clear(){t.clear();for(let r of Y())try{localStorage.removeItem(r)}catch(o){}}}}function O(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function U(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(r){}let s=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(s)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(s)?"social":"referral"}catch(n){return"direct"}}function R(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function P(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function ne(e){let t=J("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function J(e,t){var o,i,a,d,u,g,p;let n=(i=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?i:"",s=(d=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?d:"",r=(u=t==null?void 0:t.now)!=null?u:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?O(n):"desktop",trafficSource:s?U(s,t==null?void 0:t.appOrigin):"direct",referrerDomain:R(s),timeOfDay:P(r),dayOfWeek:(p=["sun","mon","tue","wed","thu","fri","sat"][r.getDay()])!=null?p:"sun"}}var re=1500;function F(e,t,n){let s=new AbortController,r=setTimeout(()=>s.abort(),n);return fetch(e,K(C({},t),{signal:s.signal})).finally(()=>clearTimeout(r))}async function se(e,t,n){var d;let s=(d=n.timeoutMs)!=null?d:re,r={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(r.Origin=n.origin);let o=J(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await F(`${n.baseUrl}/sessions`,{method:"POST",headers:r,body:JSON.stringify(o)},s)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(u){}let i=await Promise.allSettled(e.map(async({id:u,variantIds:g})=>{let p=await F(`${n.baseUrl}/assign`,{method:"POST",headers:r,body:JSON.stringify({sessionId:t,componentId:u,variantIds:g})},s);if(!p.ok)return null;let h=await p.json();return{id:u,variantId:h.variantId}})),a={};for(let u of i)u.status==="fulfilled"&&u.value&&(a[u.value.id]=u.value.variantId);return a}function ie(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}async function oe(e,t,n){var a;let s=(a=n.timeoutMs)!=null?a:re,r={layoutOrder:e.sections,assignments:{},persona:"unknown",confidence:0},o={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(o.Origin=n.origin);let i=J(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{await F(`${n.baseUrl}/sessions`,{method:"POST",headers:o,body:JSON.stringify(i)},s)}catch(d){}try{let d=await F(`${n.baseUrl}/decide`,{method:"POST",headers:o,body:JSON.stringify({sessionId:t,sections:e.sections.map(u=>({id:u})),components:e.components})},s);return d.ok?await d.json():r}catch(d){return r}}var Oe="https://sentient-api.fly.dev/v1/events";function Ue(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var j={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Re(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,s]of t)n.startsWith("utm_")&&(e[n]=s);return e}catch(e){return{}}}function Pe(e){return e.replace(/\/events\/?$/,"")}function Me(e){var M,k,$,L,x;if(typeof window=="undefined"||e.consent===!1)return j;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."),j;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),j;let t=(M=e.ingestUrl)!=null?M:Oe,n=Date.now(),s=Z(),r=te(),o=ee({ingestUrl:t,apiKey:e.apiKey}),i=Pe(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},d=O((k=navigator.userAgent)!=null?k:""),u=typeof window!="undefined"?window.location.origin:void 0,g=U(($=document.referrer)!=null?$:"",u),p=(L=e.sessionSegment)!=null?L:`${d}:${g}`;if(e.initialAssignments)for(let[l,m]of Object.entries(e.initialAssignments))r.set(l,p,{variantId:m,assignedAt:Date.now(),segment:p,confidence:1});let h=Promise.resolve(),S=s.getSessionId();if(S){let l=R((x=document.referrer)!=null?x:""),m=C({sessionId:S,deviceClass:d,trafficSource:g,referrerDomain:l,utmParams:Re(),timeOfDay:P(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:s.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(m),headers:a}).then(y=>{y.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(y){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:o});let v={goal(l,m={}){let y=s.getSessionId();y&&h.then(()=>{fetch(`${i}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:l,metadata:m}),headers:a}).catch(()=>{})})},identify(l){let m=s.getSessionId();m&&h.then(()=>{fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:l,ephemeral:s.isEphemeral()}),headers:a}).catch(()=>{})})},track(l){let m=s.getSessionId();if(!m)return;let y=K(C({},l),{id:Ue(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(l,m){return r.get(l,m)},async assign(l,m){let y=s.getSessionId();if(!y)return null;let b=r.get(l,p);if(b)return{variantId:b.variantId,assignmentTtlMs:0,content:b.content};await h;try{let E=await fetch(`${i}/assign`,{method:"POST",body:JSON.stringify({sessionId:y,componentId:l,variantIds:m}),headers:a});if(!E.ok)return null;let _=await E.json();return r.set(l,p,{variantId:_.variantId,assignedAt:Date.now(),segment:p,confidence:1,content:_.content}),_}catch(E){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),s.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let l=window;l.__sentient&&(l.__sentient.client=v)}return v}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,init,preloadAssignments,preloadDecisions,readSessionCookie,referrerDomainFromReferer});
1
+ "use strict";var G=Object.defineProperty,ge=Object.defineProperties,fe=Object.getOwnPropertyDescriptor,me=Object.getOwnPropertyDescriptors,pe=Object.getOwnPropertyNames,X=Object.getOwnPropertySymbols;var ee=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var Z=(e,t,n)=>t in e?G(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,_=(e,t)=>{for(var n in t||(t={}))ee.call(t,n)&&Z(e,n,t[n]);if(X)for(var n of X(t))ye.call(t,n)&&Z(e,n,t[n]);return e},U=(e,t)=>ge(e,me(t));var he=(e,t)=>{for(var n in t)G(e,n,{get:t[n],enumerable:!0})},Se=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of pe(t))!ee.call(e,r)&&r!==n&&G(e,r,{get:()=>t[r],enumerable:!(i=fe(t,r))||i.enumerable});return e};var ve=e=>Se(G({},"__esModule",{value:!0}),e);var Be={};he(Be,{deriveSessionSegment:()=>se,detectDeviceClass:()=>R,detectTimeOfDay:()=>$,detectTrafficSource:()=>P,grantConsent:()=>Ke,init:()=>le,preloadAssignments:()=>oe,preloadDecisions:()=>ce,readSessionCookie:()=>ae,referrerDomainFromReferer:()=>M});module.exports=ve(Be);var we="_snt_uid";var k="_snt_uid";function xe(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function Ae(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function be(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(i){}}function Ie(e){try{return localStorage.getItem(e)}catch(t){return null}}function Ee(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function _e(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function ke(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function Ce(e){try{sessionStorage.removeItem(e)}catch(t){}}function Te(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function De(e){try{localStorage.removeItem(e)}catch(t){}}function Oe(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Ue={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function te(e){var u,g,p,h,S;if(typeof window=="undefined")return Ue;let t=(u=e==null?void 0:e.cookieName)!=null?u:we,i=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,r=(S=(h=(p=Ae(t))!=null?p:Ie(k))!=null?h:_e(k))!=null?S:xe();be(t,r,i);let o=Ee(k,r),s=Te(t),a=o?!1:ke(k,r),c=!o&&!s&&!a;return{getSessionId:()=>r,isEphemeral:()=>c,destroy:()=>{r=null,Oe(t),De(k),Ce(k)}}}var Q="_snt_retry";var Re={push:()=>{},flush:()=>{},destroy:()=>{}};function Pe(e){try{let t=localStorage.getItem(Q);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(Q),n.slice(-e)):[]}catch(t){return[]}}function Y(e,t){try{let i=[...(()=>{try{let r=localStorage.getItem(Q);if(!r)return[];let o=JSON.parse(r);return Array.isArray(o)?o:[]}catch(r){return[]}})(),...e].slice(-t);localStorage.setItem(Q,JSON.stringify(i))}catch(n){}}function ne(e){var D,E,b;if(typeof window=="undefined")return Re;let t=(D=e.flushIntervalMs)!=null?D:5e3,n=(E=e.maxBatchSize)!=null?E:20,i=(b=e.maxRetrySize)!=null?b:100,r=e.ingestUrl,o=e.apiKey,s=[],a=new Set,c=[],u=d=>{for(let l of d)g.delete(l),!a.has(l)&&(a.add(l),c.push(l));for(;c.length>500;){let l=c.shift();l&&a.delete(l)}},g=new Set,p=d=>{a.has(d.id)||g.has(d.id)||(g.add(d.id),s.push(d))},h=Pe(i);for(let d of h)p(d);let S=0,v=0,K=d=>{if(d.length===0)return;let l=JSON.stringify(d),x=d.map(A=>A.id),I;try{I=fetch(r,{method:"POST",keepalive:!0,body:l,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(A){Y(d,i);for(let W of x)g.delete(W);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6));return}let O=A=>{if(A.ok||A.status>=400&&A.status<500&&A.status!==429){u(x),v=0,S=0;return}Y(d,i);for(let W of x)g.delete(W);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};I instanceof Promise?I.then(O).catch(()=>{Y(d,i);for(let A of x)g.delete(A);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):O(I)},C=typeof TextEncoder!="undefined"?new TextEncoder:null,N=d=>C?C.encode(d).length:d.length,B=d=>{let l=[],x=2;for(let I of d){let O=N(JSON.stringify(I))+1;if(l.length>0&&x+O>57344||l.length>=n)break;l.push(I),x+=O}return l},w=()=>{try{if(Date.now()<S)return;for(;s.length>0;){let d=s.filter(x=>!a.has(x.id));if(s.length=0,d.length===0)break;let l=B(d);if(l.length===0)break;l.length<d.length&&s.push(...d.slice(l.length)),K(l)}}catch(d){}},f=!0,m=null;m=setInterval(()=>{f&&w()},t);let y=()=>{document.visibilityState==="hidden"&&w()},T=()=>{w()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",T),{push(d){p(d),s.length>=n&&w()},flush:w,destroy(){f=!1,m!==null&&(clearInterval(m),m=null),document.removeEventListener("visibilitychange",y),window.removeEventListener("beforeunload",T),w()}}}var j="_snt_asgn_";function J(e,t){return`${e}:${t}`}function Me(e,t){return`${j}${e}_${t}`}function q(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(j)&&e.push(n)}return e}catch(e){return[]}}function re(e=18e5){let t=new Map,n=r=>r.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let r of q())try{let o=localStorage.getItem(r);if(!o)continue;let s=JSON.parse(o);if(n(s)){localStorage.removeItem(r);continue}let a=r.slice(j.length),c=a.lastIndexOf("_");if(c<0)continue;let u=a.slice(0,c),g=a.slice(c+1);t.set(J(u,g),s)}catch(o){}})(),{get(r,o){let s=t.get(J(r,o));return s?n(s)?(t.delete(J(r,o)),null):s:null},set(r,o,s){let a=J(r,o);t.set(a,s);try{localStorage.setItem(Me(r,o),JSON.stringify(s))}catch(c){}},invalidate(r){let o=`${r}:`;for(let s of[...t.keys()])s.startsWith(o)&&t.delete(s);for(let s of q()){let a=s.slice(j.length),c=a.lastIndexOf("_");if(c<0)continue;if(a.slice(0,c)===r)try{localStorage.removeItem(s)}catch(g){}}},clear(){t.clear();for(let r of q())try{localStorage.removeItem(r)}catch(o){}}}}function R(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function P(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(r){}let i=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(i)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(i)?"social":"referral"}catch(n){return"direct"}}function M(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function $(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function se(e){let t=F("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function F(e,t){var o,s,a,c,u,g,p;let n=(s=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?s:"",i=(c=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?c:"",r=(u=t==null?void 0:t.now)!=null?u:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?R(n):"desktop",trafficSource:i?P(i,t==null?void 0:t.appOrigin):"direct",referrerDomain:M(i),timeOfDay:$(r),dayOfWeek:(p=["sun","mon","tue","wed","thu","fri","sat"][r.getDay()])!=null?p:"sun"}}var ie=1500;function z(e,t,n){let i=new AbortController,r=setTimeout(()=>i.abort(),n);return fetch(e,U(_({},t),{signal:i.signal})).finally(()=>clearTimeout(r))}async function oe(e,t,n){var c;let i=(c=n.timeoutMs)!=null?c:ie,r={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(r.Origin=n.origin);let o=F(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await z(`${n.baseUrl}/sessions`,{method:"POST",headers:r,body:JSON.stringify(o)},i)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(u){}let s=await Promise.allSettled(e.map(async({id:u,variantIds:g})=>{let p=await z(`${n.baseUrl}/assign`,{method:"POST",headers:r,body:JSON.stringify({sessionId:t,componentId:u,variantIds:g})},i);if(!p.ok)return null;let h=await p.json();return{id:u,variantId:h.variantId}})),a={};for(let u of s)u.status==="fulfilled"&&u.value&&(a[u.value.id]=u.value.variantId);return a}function ae(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}async function ce(e,t,n){var a;let i=(a=n.timeoutMs)!=null?a:ie,r={layoutOrder:e.sections,assignments:{},persona:"unknown",confidence:0},o={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(o.Origin=n.origin);let s=F(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{await z(`${n.baseUrl}/sessions`,{method:"POST",headers:o,body:JSON.stringify(s)},i)}catch(c){}try{let c=await z(`${n.baseUrl}/decide`,{method:"POST",headers:o,body:JSON.stringify({sessionId:t,sections:e.sections.map(u=>({id:u})),components:e.components})},i);return c.ok?await c.json():r}catch(c){return r}}var de="https://sentient-api.fly.dev/v1/events",V=null,H=null;function $e(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var L={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Le(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,i]of t)n.startsWith("utm_")&&(e[n]=i);return e}catch(e){return{}}}function ue(e){return e.replace(/\/events\/?$/,"")}function Ke(){if(typeof window=="undefined")return;if(!V){console.warn("[sentient] grantConsent() called before init()");return}let e=H;H=null;let t=le(U(_({},V),{consent:!0}));e==null||e(t)}function Ne(e){var r;let t=ue((r=e.ingestUrl)!=null?r:de),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},i={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(o,s,a){try{let c=new URLSearchParams({componentId:o});for(let p of s!=null?s:[])c.append("variantIds[]",p);let u=await fetch(`${t}/winner?${c.toString()}`,{headers:n});return u.ok?{variantId:(await u.json()).variantId,assignmentTtlMs:0}:s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}catch(c){return s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return H=o=>{i=o},{track:o=>i.track(o),goal:(o,s)=>i.goal(o,s),identify:o=>i.identify(o),getAssignment:(o,s)=>i.getAssignment(o,s),assign:(o,s,a,c)=>i.assign(o,s,a,c),getGraph:()=>i.getGraph(),destroy:()=>i.destroy()}}function le(e){var K,C,N,B,w;if(typeof window=="undefined")return L;if(V=e,e.consent===!1)return e.preConsentBehavior==="statistical_winner"?!e.apiKey||!e.apiKey.startsWith("pk_")?(console.warn("[sentient] init() called with an invalid apiKey \u2014 expected a pk_ public key. SDK disabled."),L):Ne(e):L;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."),L;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),L;let t=(K=e.ingestUrl)!=null?K:de,n=Date.now(),i=te(),r=re(),o=ne({ingestUrl:t,apiKey:e.apiKey}),s=ue(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=R((C=navigator.userAgent)!=null?C:""),u=typeof window!="undefined"?window.location.origin:void 0,g=P((N=document.referrer)!=null?N:"",u),p=(B=e.sessionSegment)!=null?B:`${c}:${g}`;if(e.initialAssignments)for(let[f,m]of Object.entries(e.initialAssignments))r.set(f,p,{variantId:m,assignedAt:Date.now(),segment:p,confidence:1});let h=Promise.resolve(),S=i.getSessionId();if(S){let f=M((w=document.referrer)!=null?w:""),m=_({sessionId:S,deviceClass:c,trafficSource:g,referrerDomain:f,utmParams:Le(),timeOfDay:$(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:i.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${s}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(m),headers:a}).then(y=>{y.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(y){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:o});let v={goal(f,m={}){let y=i.getSessionId();y&&h.then(()=>{fetch(`${s}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:f,metadata:m}),headers:a}).catch(()=>{})})},identify(f){let m=i.getSessionId();m&&h.then(()=>{fetch(`${s}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:f,ephemeral:i.isEphemeral()}),headers:a}).catch(()=>{})})},track(f){let m=i.getSessionId();if(!m)return;let y=U(_({},f),{id:$e(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(f,m){return r.get(f,m)},async assign(f,m,y,T){let D=i.getSessionId();if(!D)return null;let E=r.get(f,p);if(E)return{variantId:E.variantId,assignmentTtlMs:0,content:E.content};await h;try{let b={sessionId:D,componentId:f,variantIds:m};T!==void 0?b.agentDataByVariant=T:y!==void 0&&(b.agentData=y);let d=await fetch(`${s}/assign`,{method:"POST",body:JSON.stringify(b),headers:a});if(!d.ok)return null;let l=await d.json();return r.set(f,p,{variantId:l.variantId,assignedAt:Date.now(),segment:p,confidence:1,content:l.content}),l}catch(b){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),i.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let f=window;f.__sentient&&(f.__sentient.client=v)}return v}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,preloadAssignments,preloadDecisions,readSessionCookie,referrerDomainFromReferer});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{c as a,d as b,e as c,f as d,g as e,h as f,i as g,j as h,k as i}from"./chunk-6B5JZHAF.mjs";export{e as deriveSessionSegment,a as detectDeviceClass,d as detectTimeOfDay,b as detectTrafficSource,i as init,f as preloadAssignments,h as preloadDecisions,g as readSessionCookie,c as referrerDomainFromReferer};
1
+ import{c as a,d as b,e as c,f as d,g as e,h as f,i as g,j as h,k as i,l as j}from"./chunk-SAUXPAW5.mjs";export{e as deriveSessionSegment,a as detectDeviceClass,d as detectTimeOfDay,b as detectTrafficSource,i as grantConsent,j as init,f as preloadAssignments,h as preloadDecisions,g as readSessionCookie,c as referrerDomainFromReferer};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/core",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- var te=Object.defineProperty,ne=Object.defineProperties;var re=Object.getOwnPropertyDescriptors;var q=Object.getOwnPropertySymbols;var se=Object.prototype.hasOwnProperty,ie=Object.prototype.propertyIsEnumerable;var V=(e,t,n)=>t in e?te(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,C=(e,t)=>{for(var n in t||(t={}))se.call(t,n)&&V(e,n,t[n]);if(q)for(var n of q(t))ie.call(t,n)&&V(e,n,t[n]);return e},P=(e,t)=>ne(e,re(t));var oe="_snt_uid";var T="_snt_uid";function ae(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function ce(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function de(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(s){}}function ue(e){try{return localStorage.getItem(e)}catch(t){return null}}function le(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function ge(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function me(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function fe(e){try{sessionStorage.removeItem(e)}catch(t){}}function pe(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function ye(e){try{localStorage.removeItem(e)}catch(t){}}function he(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Se={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function X(e){var u,g,p,h,S;if(typeof window=="undefined")return Se;let t=(u=e==null?void 0:e.cookieName)!=null?u:oe,s=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,r=(S=(h=(p=ce(t))!=null?p:ue(T))!=null?h:ge(T))!=null?S:ae();de(t,r,s);let o=le(T,r),i=pe(t),a=o?!1:me(T,r),d=!o&&!i&&!a;return{getSessionId:()=>r,isEphemeral:()=>d,destroy:()=>{r=null,he(t),ye(T),fe(T)}}}var M="_snt_retry";var ve={push:()=>{},flush:()=>{},destroy:()=>{}};function xe(e){try{let t=localStorage.getItem(M);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(M),n.slice(-e)):[]}catch(t){return[]}}function z(e,t){try{let s=[...(()=>{try{let r=localStorage.getItem(M);if(!r)return[];let o=JSON.parse(r);return Array.isArray(o)?o:[]}catch(r){return[]}})(),...e].slice(-t);localStorage.setItem(M,JSON.stringify(s))}catch(n){}}function H(e){var E,_,Y;if(typeof window=="undefined")return ve;let t=(E=e.flushIntervalMs)!=null?E:5e3,n=(_=e.maxBatchSize)!=null?_:20,s=(Y=e.maxRetrySize)!=null?Y:100,r=e.ingestUrl,o=e.apiKey,i=[],a=new Set,d=[],u=c=>{for(let f of c)g.delete(f),!a.has(f)&&(a.add(f),d.push(f));for(;d.length>500;){let f=d.shift();f&&a.delete(f)}},g=new Set,p=c=>{a.has(c.id)||g.has(c.id)||(g.add(c.id),i.push(c))},h=xe(s);for(let c of h)p(c);let S=0,v=0,O=c=>{if(c.length===0)return;let f=JSON.stringify(c),I=c.map(w=>w.id),A;try{A=fetch(r,{method:"POST",keepalive:!0,body:f,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(w){z(c,s);for(let j of I)g.delete(j);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6));return}let D=w=>{if(w.ok||w.status>=400&&w.status<500&&w.status!==429){u(I),v=0,S=0;return}z(c,s);for(let j of I)g.delete(j);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};A instanceof Promise?A.then(D).catch(()=>{z(c,s);for(let w of I)g.delete(w);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):D(A)},k=typeof TextEncoder!="undefined"?new TextEncoder:null,U=c=>k?k.encode(c).length:c.length,R=c=>{let f=[],I=2;for(let A of c){let D=U(JSON.stringify(A))+1;if(f.length>0&&I+D>57344||f.length>=n)break;f.push(A),I+=D}return f},x=()=>{try{if(Date.now()<S)return;for(;i.length>0;){let c=i.filter(I=>!a.has(I.id));if(i.length=0,c.length===0)break;let f=R(c);if(f.length===0)break;f.length<c.length&&i.push(...c.slice(f.length)),O(f)}}catch(c){}},l=!0,m=null;m=setInterval(()=>{l&&x()},t);let y=()=>{document.visibilityState==="hidden"&&x()},b=()=>{x()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",b),{push(c){p(c),i.length>=n&&x()},flush:x,destroy(){l=!1,m!==null&&(clearInterval(m),m=null),document.removeEventListener("visibilitychange",y),window.removeEventListener("beforeunload",b),x()}}}var L="_snt_asgn_";function $(e,t){return`${e}:${t}`}function Ie(e,t){return`${L}${e}_${t}`}function W(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(L)&&e.push(n)}return e}catch(e){return[]}}function Z(e=18e5){let t=new Map,n=r=>r.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let r of W())try{let o=localStorage.getItem(r);if(!o)continue;let i=JSON.parse(o);if(n(i)){localStorage.removeItem(r);continue}let a=r.slice(L.length),d=a.lastIndexOf("_");if(d<0)continue;let u=a.slice(0,d),g=a.slice(d+1);t.set($(u,g),i)}catch(o){}})(),{get(r,o){let i=t.get($(r,o));return i?n(i)?(t.delete($(r,o)),null):i:null},set(r,o,i){let a=$(r,o);t.set(a,i);try{localStorage.setItem(Ie(r,o),JSON.stringify(i))}catch(d){}},invalidate(r){let o=`${r}:`;for(let i of[...t.keys()])i.startsWith(o)&&t.delete(i);for(let i of W()){let a=i.slice(L.length),d=a.lastIndexOf("_");if(d<0)continue;if(a.slice(0,d)===r)try{localStorage.removeItem(i)}catch(g){}}},clear(){t.clear();for(let r of W())try{localStorage.removeItem(r)}catch(o){}}}}function N(e){let t=e.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(t)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(t)?"mobile":"desktop"}function K(e,t){if(!e)return"direct";try{let n=new URL(e);if(t)try{if(new URL(t).host===n.host)return"direct"}catch(r){}let s=n.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(s)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(s)?"social":"referral"}catch(n){return"direct"}}function B(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function Q(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function we(e){let t=G("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function G(e,t){var o,i,a,d,u,g,p;let n=(i=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?i:"",s=(d=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?d:"",r=(u=t==null?void 0:t.now)!=null?u:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?N(n):"desktop",trafficSource:s?K(s,t==null?void 0:t.appOrigin):"direct",referrerDomain:B(s),timeOfDay:Q(r),dayOfWeek:(p=["sun","mon","tue","wed","thu","fri","sat"][r.getDay()])!=null?p:"sun"}}var ee=1500;function J(e,t,n){let s=new AbortController,r=setTimeout(()=>s.abort(),n);return fetch(e,P(C({},t),{signal:s.signal})).finally(()=>clearTimeout(r))}async function Ae(e,t,n){var d;let s=(d=n.timeoutMs)!=null?d:ee,r={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(r.Origin=n.origin);let o=G(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{(await J(`${n.baseUrl}/sessions`,{method:"POST",headers:r,body:JSON.stringify(o)},s)).status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}catch(u){}let i=await Promise.allSettled(e.map(async({id:u,variantIds:g})=>{let p=await J(`${n.baseUrl}/assign`,{method:"POST",headers:r,body:JSON.stringify({sessionId:t,componentId:u,variantIds:g})},s);if(!p.ok)return null;let h=await p.json();return{id:u,variantId:h.variantId}})),a={};for(let u of i)u.status==="fulfilled"&&u.value&&(a[u.value.id]=u.value.variantId);return a}function be(e){var t,n;return(n=(t=e.get("_snt_uid"))==null?void 0:t.value)!=null?n:null}async function Ee(e,t,n){var a;let s=(a=n.timeoutMs)!=null?a:ee,r={layoutOrder:e.sections,assignments:{},persona:"unknown",confidence:0},o={"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`};n.origin&&(o.Origin=n.origin);let i=G(t,{userAgent:n.userAgent,referer:n.referer,utmParams:n.utmParams,appOrigin:n.origin});try{await J(`${n.baseUrl}/sessions`,{method:"POST",headers:o,body:JSON.stringify(i)},s)}catch(d){}try{let d=await J(`${n.baseUrl}/decide`,{method:"POST",headers:o,body:JSON.stringify({sessionId:t,sections:e.sections.map(u=>({id:u})),components:e.components})},s);return d.ok?await d.json():r}catch(d){return r}}var _e="https://sentient-api.fly.dev/v1/events";function Te(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}var F={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function ke(){try{let e={},t=new URLSearchParams(window.location.search);for(let[n,s]of t)n.startsWith("utm_")&&(e[n]=s);return e}catch(e){return{}}}function De(e){return e.replace(/\/events\/?$/,"")}function Ge(e){var O,k,U,R,x;if(typeof window=="undefined"||e.consent===!1)return F;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."),F;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),F;let t=(O=e.ingestUrl)!=null?O:_e,n=Date.now(),s=X(),r=Z(),o=H({ingestUrl:t,apiKey:e.apiKey}),i=De(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},d=N((k=navigator.userAgent)!=null?k:""),u=typeof window!="undefined"?window.location.origin:void 0,g=K((U=document.referrer)!=null?U:"",u),p=(R=e.sessionSegment)!=null?R:`${d}:${g}`;if(e.initialAssignments)for(let[l,m]of Object.entries(e.initialAssignments))r.set(l,p,{variantId:m,assignedAt:Date.now(),segment:p,confidence:1});let h=Promise.resolve(),S=s.getSessionId();if(S){let l=B((x=document.referrer)!=null?x:""),m=C({sessionId:S,deviceClass:d,trafficSource:g,referrerDomain:l,utmParams:ke(),timeOfDay:Q(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:s.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(m),headers:a}).then(y=>{y.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentientui.dev/pricing")}).catch(()=>{})}catch(y){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:o});let v={goal(l,m={}){let y=s.getSessionId();y&&h.then(()=>{fetch(`${i}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:l,metadata:m}),headers:a}).catch(()=>{})})},identify(l){let m=s.getSessionId();m&&h.then(()=>{fetch(`${i}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:l,ephemeral:s.isEphemeral()}),headers:a}).catch(()=>{})})},track(l){let m=s.getSessionId();if(!m)return;let y=P(C({},l),{id:Te(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(l,m){return r.get(l,m)},async assign(l,m){let y=s.getSessionId();if(!y)return null;let b=r.get(l,p);if(b)return{variantId:b.variantId,assignmentTtlMs:0,content:b.content};await h;try{let E=await fetch(`${i}/assign`,{method:"POST",body:JSON.stringify({sessionId:y,componentId:l,variantIds:m}),headers:a});if(!E.ok)return null;let _=await E.json();return r.set(l,p,{variantId:_.variantId,assignedAt:Date.now(),segment:p,confidence:1,content:_.content}),_}catch(E){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),s.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let l=window;l.__sentient&&(l.__sentient.client=v)}return v}export{C as a,P as b,N as c,K as d,B as e,Q as f,we as g,Ae as h,be as i,Ee as j,Ge as k};