@sentientui/core 0.4.0 → 0.6.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
@@ -27,13 +27,6 @@ console.log(result?.content); // managed text content if the variant is WYSI
27
27
 
28
28
  // Fire a goal (reward) when the visitor converts
29
29
  client.goal('trial_started', { plan: 'pro' });
30
-
31
- // Or record a custom event
32
- client.track({
33
- componentId: 'hero_headline',
34
- variantId: result?.variantId ?? 'control',
35
- eventType: 'click',
36
- });
37
30
  ```
38
31
 
39
32
  `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.
@@ -68,10 +61,15 @@ type AssignResult = {
68
61
 
69
62
  Queues an event for batched ingest. Events flush every 5 s and on `visibilitychange` / page unload (via `fetch` with `keepalive: true`).
70
63
 
71
- ### `client.goal(name, metadata?)`
64
+ ### `client.goal(name, metadata?, weight?, stepIndex?)`
72
65
 
73
66
  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
67
 
68
+ > **Two reward paths:** `client.goal()` sends a named reward event that the bandit attributes to whatever variant was active at goal time. When using `@sentientui/react`, the `<Adaptive>` component's `onConvert` prop (or the `goal` prop on `<AdaptiveText>`) is the preferred path for rewards scoped to a single component — it ties the reward directly to the assignment without needing the component ID. Use `client.goal()` for funnel steps that span multiple components or occur after navigation.
69
+
70
+ - `weight` (0–1, default `1.0`) — partial reward value. Use values < 1 for funnel steps that precede the final conversion. The bandit learns from each step immediately.
71
+ - `stepIndex` (default `0`) — position in the funnel for analytics grouping.
72
+
75
73
  ### `client.identify(userId)`
76
74
 
77
75
  Attaches a stable user ID to the session. Portraits and cluster assignment carry forward across future sessions for the same `userId`.
@@ -91,7 +89,7 @@ Flushes the event queue and clears session state. Call on page unload if you nee
91
89
  ## SSR helpers
92
90
 
93
91
  ```ts
94
- import { preloadAssignments, readSessionCookie } from '@sentientui/core';
92
+ import { preloadAssignments, readSessionCookie } from '@sentientui/core/server';
95
93
 
96
94
  // In your server loader / getServerSideProps / Server Component.
97
95
  // `cookies` must expose `get(name)` — Next.js `req.cookies`, `headers().cookies()`, or any
@@ -0,0 +1 @@
1
+ import{a as M,b as B,c as G,d as Q,e as F,f as z}from"./chunk-QCYVBCUV.mjs";var ee="_snt_uid";var C="_snt_uid";function te(){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 ne(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function se(e,t,a){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${a}; SameSite=strict; path=/`}catch(o){}}function ie(e){try{return localStorage.getItem(e)}catch(t){return null}}function re(e,t){try{return localStorage.setItem(e,t),!0}catch(a){return!1}}function oe(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function ae(e,t){try{return sessionStorage.setItem(e,t),!0}catch(a){return!1}}function ce(e){try{sessionStorage.removeItem(e)}catch(t){}}function le(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 ue(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var ge={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Y(e){var f,g,p,v,h;if(typeof window=="undefined")return ge;let t=(f=e==null?void 0:e.cookieName)!=null?f:ee,o=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,s=(h=(v=(p=ne(t))!=null?p:ie(C))!=null?v:oe(C))!=null?h:te();se(t,s,o);let i=re(C,s),n=le(t),r=i?!1:ae(C,s),l=!i&&!n&&!r;return{getSessionId:()=>s,isEphemeral:()=>l,destroy:()=>{s=null,ue(t),de(C),ce(C)}}}var K="_snt_retry";var fe={push:()=>{},flush:()=>{},destroy:()=>{}};function me(e){try{let t=localStorage.getItem(K);if(!t)return[];let a=JSON.parse(t);return Array.isArray(a)?(localStorage.removeItem(K),a.slice(-e)):[]}catch(t){return[]}}function J(e,t){try{let o=[...(()=>{try{let s=localStorage.getItem(K);if(!s)return[];let i=JSON.parse(s);return Array.isArray(i)?i:[]}catch(s){return[]}})(),...e].slice(-t);localStorage.setItem(K,JSON.stringify(o))}catch(a){}}function q(e){var k,b,T;if(typeof window=="undefined")return fe;let t=(k=e.flushIntervalMs)!=null?k:5e3,a=(b=e.maxBatchSize)!=null?b:20,o=(T=e.maxRetrySize)!=null?T:100,s=e.ingestUrl,i=e.apiKey,n=[],r=new Set,l=[],f=c=>{for(let u of c)g.delete(u),!r.has(u)&&(r.add(u),l.push(u));for(;l.length>500;){let u=l.shift();u&&r.delete(u)}},g=new Set,p=c=>{r.has(c.id)||g.has(c.id)||(g.add(c.id),n.push(c))},v=me(o);for(let c of v)p(c);let h=0,w=0,R=c=>{if(c.length===0)return;let u=JSON.stringify(c),y=c.map(I=>I.id),E;try{E=fetch(s,{method:"POST",keepalive:!0,body:u,headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}})}catch(I){J(c,o);for(let P of y)g.delete(P);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6));return}let _=I=>{if(I.ok||I.status>=400&&I.status<500&&I.status!==429){f(y),w=0,h=0;return}J(c,o);for(let P of y)g.delete(P);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6))};E instanceof Promise?E.then(_).catch(()=>{J(c,o);for(let I of y)g.delete(I);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6))}):_(E)},A=typeof TextEncoder!="undefined"?new TextEncoder:null,U=c=>A?A.encode(c).length:c.length,L=c=>{let u=[],y=2;for(let E of c){let _=U(JSON.stringify(E))+1;if(u.length>0&&y+_>57344||u.length>=a)break;u.push(E),y+=_}return u},x=()=>{try{if(Date.now()<h)return;for(;n.length>0;){let c=n.filter(y=>!r.has(y.id));if(n.length=0,c.length===0)break;let u=L(c);if(u.length===0)break;u.length<c.length&&n.push(...c.slice(u.length)),R(u)}}catch(c){}},D=!0,d=null;d=setInterval(()=>{D&&x()},t);let m=()=>{document.visibilityState==="hidden"&&x()},S=()=>{x()};return document.addEventListener("visibilitychange",m),window.addEventListener("beforeunload",S),{push(c){p(c),n.length>=a&&x()},flush:x,destroy(){D=!1,d!==null&&(clearInterval(d),d=null),document.removeEventListener("visibilitychange",m),window.removeEventListener("beforeunload",S),x()}}}var $="_snt_asgn_";function N(e,t){return`${e}:${t}`}function pe(e,t){return`${$}${e}_${t}`}function W(){try{let e=[];for(let t=0;t<localStorage.length;t++){let a=localStorage.key(t);a!=null&&a.startsWith($)&&e.push(a)}return e}catch(e){return[]}}function V(e=18e5){let t=new Map,a=s=>s.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let s of W())try{let i=localStorage.getItem(s);if(!i)continue;let n=JSON.parse(i);if(a(n)){localStorage.removeItem(s);continue}let r=s.slice($.length),l=r.lastIndexOf("_");if(l<0)continue;let f=r.slice(0,l),g=r.slice(l+1);t.set(N(f,g),n)}catch(i){}})(),{get(s,i){let n=t.get(N(s,i));return n?a(n)?(t.delete(N(s,i)),null):n:null},set(s,i,n){let r=N(s,i);t.set(r,n);try{localStorage.setItem(pe(s,i),JSON.stringify(n))}catch(l){}},invalidate(s){let i=`${s}:`;for(let n of[...t.keys()])n.startsWith(i)&&t.delete(n);for(let n of W()){let r=n.slice($.length),l=r.lastIndexOf("_");if(l<0)continue;if(r.slice(0,l)===s)try{localStorage.removeItem(n)}catch(g){}}},clear(){t.clear();for(let s of W())try{localStorage.removeItem(s)}catch(i){}}}}function he(e,t,a){let o=[];{let n=!1,r=[],l=()=>{if(n)return;let f=Date.now();for(r.push(f);r.length>0&&f-r[0]>500;)r.shift();r.length>=3&&(n=!0,e("rage_click"))};t.addEventListener("click",l),o.push(()=>t.removeEventListener("click",l))}{let s=!1,i=n=>{if(s||!(n.target instanceof Node)||!t.contains(n.target)&&t!==n.target)return;s=!0;let r=typeof window!="undefined"?window.getSelection():null,l=r?r.toString().length:0;e("text_copy",{selectionLength:l})};document.addEventListener("copy",i),o.push(()=>document.removeEventListener("copy",i))}{let s=!1,i=!1,n=null,r=()=>{n!==null&&(clearTimeout(n),n=null)},l=()=>{s||!i||(r(),n=setTimeout(()=>{!s&&i&&(s=!0,e("scroll_hesitation"))},3e3))},f=()=>{r(),l()},g=v=>{for(let h of v)i=h.intersectionRatio>.3,i?l():r()};window.__lastIOCallback=g;let p=new IntersectionObserver(g,{threshold:[.3]});p.observe(t),window.addEventListener("scroll",f,{passive:!0}),o.push(()=>{p.disconnect(),window.removeEventListener("scroll",f),r()})}{let s=!1,i=a!=null?a:Date.now(),n=()=>{if(s||document.visibilityState!=="hidden")return;let r=Date.now()-i;r<15e3&&(s=!0,e("tab_loss",{timeOnPage:r}))};document.addEventListener("visibilitychange",n),o.push(()=>document.removeEventListener("visibilitychange",n))}return()=>{for(let s of o)s()}}var X="https://sentient-api.fly.dev/v1/events",j=null,H=null;function ye(){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 O={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Se(){try{let e={},t=new URLSearchParams(window.location.search);for(let[a,o]of t)a.startsWith("utm_")&&(e[a]=o);return e}catch(e){return{}}}function Z(e){return e.replace(/\/events\/?$/,"")}function De(){if(typeof window=="undefined")return;if(!j){console.warn("[sentient] grantConsent() called before init()");return}let e=H;H=null;let t=we(B(M({},j),{consent:!0}));e==null||e(t)}function ve(e){var s;let t=Z((s=e.ingestUrl)!=null?s:X),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},o={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(i,n,r){try{let l=new URLSearchParams({componentId:i});for(let p of n!=null?n:[])l.append("variantIds[]",p);let f=await fetch(`${t}/winner?${l.toString()}`,{headers:a});return f.ok?{variantId:(await f.json()).variantId,assignmentTtlMs:0}:n!=null&&n[0]?{variantId:n[0],assignmentTtlMs:0}:null}catch(l){return n!=null&&n[0]?{variantId:n[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return H=i=>{o=i},{track:i=>o.track(i),goal:(i,n)=>o.goal(i,n),identify:i=>o.identify(i),getAssignment:(i,n)=>o.getAssignment(i,n),assign:(i,n,r,l)=>o.assign(i,n,r,l),getGraph:()=>o.getGraph(),destroy:()=>o.destroy()}}function we(e){var A,U,L,x,D;if(typeof window=="undefined")return O;if(j=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."),O):ve(e):O;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."),O;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),O;let t=(A=e.ingestUrl)!=null?A:X,a=Date.now(),o=Y(),s=V(),i=q({ingestUrl:t,apiKey:e.apiKey}),n=Z(t),r={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},l=G((U=navigator.userAgent)!=null?U:""),f=typeof window!="undefined"?window.location.origin:void 0,g=Q((L=document.referrer)!=null?L:"",f),p=(x=e.sessionSegment)!=null?x:`${l}:${g}`,v=new Map;if(e.initialAssignments)for(let[d,m]of Object.entries(e.initialAssignments))s.set(d,p,{variantId:m,assignedAt:Date.now(),segment:p,confidence:1});let h=Promise.resolve(),w=o.getSessionId();if(w){let d=F((D=document.referrer)!=null?D:""),m=M({sessionId:w,deviceClass:l,trafficSource:g,referrerDomain:d,utmParams:Se(),timeOfDay:z(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:o.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(m),headers:r}).then(S=>{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(()=>{})}catch(S){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:i});let R={goal(d,m={},S=1,k=0){let b=o.getSessionId();b&&h.then(()=>{fetch(`${n}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:b,name:d,metadata:m,weight:S,stepIndex:k}),headers:r}).catch(()=>{})})},identify(d){let m=o.getSessionId();m&&h.then(()=>{fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:d,ephemeral:o.isEphemeral()}),headers:r}).catch(()=>{})})},track(d){let m=o.getSessionId();if(!m)return;let S=B(M({},d),{id:ye(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-a});i.push(S),e.debug&&console.log("[sentient] track",S)},getAssignment(d,m){return s.get(d,m)},async assign(d,m,S,k){let b=o.getSessionId();if(!b)return null;let T=s.get(d,p);if(T)return{variantId:T.variantId,assignmentTtlMs:0,content:T.content};let c=v.get(d);if(c)return c;let u=(async()=>{await h;try{let y={sessionId:b,componentId:d,variantIds:m};k!==void 0?y.agentDataByVariant=k:S!==void 0&&(y.agentData=S);let E=await fetch(`${n}/assign`,{method:"POST",body:JSON.stringify(y),headers:r});if(!E.ok)return null;let _=await E.json();return s.set(d,p,{variantId:_.variantId,assignedAt:Date.now(),segment:p,confidence:1,content:_.content}),_}catch(y){return null}finally{v.delete(d)}})();return v.set(d,u),u},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){i.destroy(),o.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let d=window;d.__sentient&&(d.__sentient.client=R)}return R}export{he as a,De as b,we as c};
@@ -0,0 +1 @@
1
+ var m=Object.defineProperty,h=Object.defineProperties;var y=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var b=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var l=(r,e,t)=>e in r?m(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,P=(r,e)=>{for(var t in e||(e={}))b.call(e,t)&&l(r,t,e[t]);if(d)for(var t of d(e))k.call(e,t)&&l(r,t,e[t]);return r},U=(r,e)=>h(r,y(e));function w(r){let e=r.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(e)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(e)?"mobile":"desktop"}function D(r,e){if(!r)return"direct";try{let t=new URL(r);if(e)try{if(new URL(e).host===t.host)return"direct"}catch(i){}let n=t.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(n)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(n)?"social":"referral"}catch(t){return"direct"}}function S(r){if(!r)return null;try{return new URL(r).hostname}catch(e){return null}}function x(r){let e=r.getHours();return e<6?"night":e<12?"morning":e<18?"afternoon":"evening"}function C(r){let e=O("__segment__",r);return`${e.deviceClass}:${e.trafficSource}`}function O(r,e){var s,a,o,c,u,f,g;let t=(a=(s=e==null?void 0:e.userAgent)==null?void 0:s.trim())!=null?a:"",n=(c=(o=e==null?void 0:e.referer)==null?void 0:o.trim())!=null?c:"",i=(u=e==null?void 0:e.now)!=null?u:new Date;return{sessionId:r,ephemeral:!1,utmParams:(f=e==null?void 0:e.utmParams)!=null?f:{},deviceClass:t?w(t):"desktop",trafficSource:n?D(n,e==null?void 0:e.appOrigin):"direct",referrerDomain:S(n),timeOfDay:x(i),dayOfWeek:(g=["sun","mon","tue","wed","thu","fri","sat"][i.getDay()])!=null?g:"sun"}}export{P as a,U as b,w as c,D as d,S as e,x as f,C as g,O as h};
@@ -1,5 +1,6 @@
1
1
  import { SentientConfig, SentientClient } from './index.cjs';
2
- export { AssignResult, Assignment, AssignmentCache, ContentAddedEvent, DOMScanner, EventQueue, EventType, GraphClient, GraphConfig, GraphSnapshot, PageNode, QueueConfig, ScanResult, ScannedNode, SentientEvent, ServerAssignConfig, ServerAssignments, SessionConfig, SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, preloadAssignments, readSessionCookie, referrerDomainFromReferer } from './index.cjs';
2
+ export { AssignResult, Assignment, AssignmentCache, ContentAddedEvent, DOMScanner, EventQueue, EventType, GraphClient, GraphConfig, GraphSnapshot, PageNode, QueueConfig, ScanResult, ScannedNode, SentientEvent, SessionConfig, SessionManager } from './index.cjs';
3
+ export { d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.cjs';
3
4
 
4
5
  /**
5
6
  * Graph-capable entry point for @sentientui/core.
@@ -1,5 +1,6 @@
1
1
  import { SentientConfig, SentientClient } from './index.js';
2
- export { AssignResult, Assignment, AssignmentCache, ContentAddedEvent, DOMScanner, EventQueue, EventType, GraphClient, GraphConfig, GraphSnapshot, PageNode, QueueConfig, ScanResult, ScannedNode, SentientEvent, ServerAssignConfig, ServerAssignments, SessionConfig, SessionManager, deriveSessionSegment, detectDeviceClass, detectTimeOfDay, detectTrafficSource, preloadAssignments, readSessionCookie, referrerDomainFromReferer } from './index.js';
2
+ export { AssignResult, Assignment, AssignmentCache, ContentAddedEvent, DOMScanner, EventQueue, EventType, GraphClient, GraphConfig, GraphSnapshot, PageNode, QueueConfig, ScanResult, ScannedNode, SentientEvent, SessionConfig, SessionManager } from './index.js';
3
+ export { d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.js';
3
4
 
4
5
  /**
5
6
  * Graph-capable entry point for @sentientui/core.
@@ -1 +1 @@
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:()=>D,detectTimeOfDay:()=>P,detectTrafficSource:()=>R,init:()=>dt,preloadAssignments:()=>H,readSessionCookie:()=>V,referrerDomainFromReferer:()=>U});module.exports=Ee(ut);var be="_snt_uid";var N="_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 Ne(e){try{sessionStorage.removeItem(e)}catch(t){}}function De(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(N))!=null?m:ke(N))!=null?l:Ce();xe(t,s,a);let o=_e(N,s),r=De(t),i=o?!1:Oe(N,s),c=!o&&!r&&!i;return{getSessionId:()=>s,isEphemeral:()=>c,destroy:()=>{s=null,Ue(t),Re(N),Ne(N)}}}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,$;if(typeof window=="undefined")return Me;let t=(_=e.flushIntervalMs)!=null?_:5e3,n=(k=e.maxBatchSize)!=null?k:20,a=($=e.maxRetrySize)!=null?$:100,s=e.ingestUrl,o=e.apiKey,r=[],i=new Set,c=[],d=p=>{for(let S of p)u.delete(S),!i.has(S)&&(i.add(S),c.push(S));for(;c.length>500;){let S=c.shift();S&&i.delete(S)}},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 S=JSON.stringify(p),b=p.map(C=>C.id),T;try{T=fetch(s,{method:"POST",keepalive:!0,body:S,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))};T instanceof Promise?T.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(T)},w=typeof TextEncoder!="undefined"?new TextEncoder:null,x=p=>w?w.encode(p).length:p.length,G=p=>{let S=[],b=2;for(let T of p){let L=x(JSON.stringify(T))+1;if(S.length>0&&b+L>57344||S.length>=n)break;S.push(T),b+=L}return S},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 S=G(p);if(S.length===0)break;S.length<p.length&&r.push(...p.slice(S.length)),I(S)}}catch(p){}},h=!0,y=null;y=setInterval(()=>{h&&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(){h=!1,y!==null&&(clearInterval(y),y=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 D(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?D(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)=>a.assign(o,r,i),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=D((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[h,y]of Object.entries(e.initialAssignments))s.set(h,g,{variantId:y,assignedAt:Date.now(),segment:g,confidence:1});let m=Promise.resolve(),l=a.getSessionId();if(l){let h=U((E=document.referrer)!=null?E:""),y=A({sessionId:l,deviceClass:c,trafficSource:u,referrerDomain:h,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(y),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(h,y={}){let v=a.getSessionId();v&&m.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:v,name:h,metadata:y}),headers:i}).catch(()=>{})})},identify(h){let y=a.getSessionId();y&&m.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,userId:h,ephemeral:a.isEphemeral()}),headers:i}).catch(()=>{})})},track(h){let y=a.getSessionId();if(!y)return;let v=O(A({},h),{id:je(),sessionId:y,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(v),e.debug&&console.log("[sentient] track",v)},getAssignment(h,y){return s.get(h,y)},async assign(h,y,v){let M=a.getSessionId();if(!M)return null;let _=s.get(h,g);if(_)return{variantId:_.variantId,assignmentTtlMs:0,content:_.content};await m;try{let k={sessionId:M,componentId:h,variantIds:y};v!==void 0&&(k.agentData=v);let $=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(k),headers:i});if(!$.ok)return null;let p=await $.json();return s.set(h,g,{variantId:p.variantId,assignedAt:Date.now(),segment:g,confidence:1,content:p.content}),p}catch(k){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),a.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let h=window;h.__sentient&&(h.__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
+ "use strict";var G=Object.defineProperty,le=Object.defineProperties,ge=Object.getOwnPropertyDescriptor,pe=Object.getOwnPropertyDescriptors,fe=Object.getOwnPropertyNames,X=Object.getOwnPropertySymbols;var ee=Object.prototype.hasOwnProperty,me=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,D=(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))me.call(t,n)&&Z(e,n,t[n]);return e},B=(e,t)=>le(e,pe(t));var he=(e,t)=>{for(var n in t)G(e,n,{get:t[n],enumerable:!0})},ye=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of fe(t))!ee.call(e,i)&&i!==n&&G(e,i,{get:()=>t[i],enumerable:!(a=ge(t,i))||a.enumerable});return e};var Se=e=>ye(G({},"__esModule",{value:!0}),e);var it={};he(it,{deriveSessionSegment:()=>W,detectDeviceClass:()=>R,detectTimeOfDay:()=>L,detectTrafficSource:()=>M,init:()=>st,referrerDomainFromReferer:()=>U});module.exports=Se(it);var ve="_snt_uid";var N="_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 Ee(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Ie(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(a){}}function be(e){try{return localStorage.getItem(e)}catch(t){return null}}function Ce(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function xe(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 Ae(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 ke(e){try{localStorage.removeItem(e)}catch(t){}}function De(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Oe={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function te(e){var d,l,g,m,u;if(typeof window=="undefined")return Oe;let t=(d=e==null?void 0:e.cookieName)!=null?d:ve,a=((l=e==null?void 0:e.cookieTTLDays)!=null?l:365)*24*60*60,i=(u=(m=(g=Ee(t))!=null?g:be(N))!=null?m:xe(N))!=null?u:we();Ie(t,i,a);let o=Ce(N,i),r=Te(t),s=o?!1:_e(N,i),c=!o&&!r&&!s;return{getSessionId:()=>i,isEphemeral:()=>c,destroy:()=>{i=null,De(t),ke(N),Ae(N)}}}var F="_snt_retry";var Ne={push:()=>{},flush:()=>{},destroy:()=>{}};function Re(e){try{let t=localStorage.getItem(F);if(!t)return[];let n=JSON.parse(t);return Array.isArray(n)?(localStorage.removeItem(F),n.slice(-e)):[]}catch(t){return[]}}function Q(e,t){try{let a=[...(()=>{try{let i=localStorage.getItem(F);if(!i)return[];let o=JSON.parse(i);return Array.isArray(o)?o:[]}catch(i){return[]}})(),...e].slice(-t);localStorage.setItem(F,JSON.stringify(a))}catch(n){}}function ne(e){var k,A,O;if(typeof window=="undefined")return Ne;let t=(k=e.flushIntervalMs)!=null?k:5e3,n=(A=e.maxBatchSize)!=null?A:20,a=(O=e.maxRetrySize)!=null?O:100,i=e.ingestUrl,o=e.apiKey,r=[],s=new Set,c=[],d=p=>{for(let y of p)l.delete(y),!s.has(y)&&(s.add(y),c.push(y));for(;c.length>500;){let y=c.shift();y&&s.delete(y)}},l=new Set,g=p=>{s.has(p.id)||l.has(p.id)||(l.add(p.id),r.push(p))},m=Re(a);for(let p of m)g(p);let u=0,h=0,E=p=>{if(p.length===0)return;let y=JSON.stringify(p),v=p.map(_=>_.id),I;try{I=fetch(i,{method:"POST",keepalive:!0,body:y,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(_){Q(p,a);for(let J of v)l.delete(J);h++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(h,6));return}let x=_=>{if(_.ok||_.status>=400&&_.status<500&&_.status!==429){d(v),h=0,u=0;return}Q(p,a);for(let J of v)l.delete(J);h++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(h,6))};I instanceof Promise?I.then(x).catch(()=>{Q(p,a);for(let _ of v)l.delete(_);h++,u=Date.now()+Math.min(6e4,1e3*2**Math.min(h,6))}):x(I)},b=typeof TextEncoder!="undefined"?new TextEncoder:null,T=p=>b?b.encode(p).length:p.length,K=p=>{let y=[],v=2;for(let I of p){let x=T(JSON.stringify(I))+1;if(y.length>0&&v+x>57344||y.length>=n)break;y.push(I),v+=x}return y},C=()=>{try{if(Date.now()<u)return;for(;r.length>0;){let p=r.filter(v=>!s.has(v.id));if(r.length=0,p.length===0)break;let y=K(p);if(y.length===0)break;y.length<p.length&&r.push(...p.slice(y.length)),E(y)}}catch(p){}},P=!0,f=null;f=setInterval(()=>{P&&C()},t);let S=()=>{document.visibilityState==="hidden"&&C()},w=()=>{C()};return document.addEventListener("visibilitychange",S),window.addEventListener("beforeunload",w),{push(p){g(p),r.length>=n&&C()},flush:C,destroy(){P=!1,f!==null&&(clearInterval(f),f=null),document.removeEventListener("visibilitychange",S),window.removeEventListener("beforeunload",w),C()}}}var z="_snt_asgn_";function j(e,t){return`${e}:${t}`}function Me(e,t){return`${z}${e}_${t}`}function H(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(z)&&e.push(n)}return e}catch(e){return[]}}function re(e=18e5){let t=new Map,n=i=>i.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let i of H())try{let o=localStorage.getItem(i);if(!o)continue;let r=JSON.parse(o);if(n(r)){localStorage.removeItem(i);continue}let s=i.slice(z.length),c=s.lastIndexOf("_");if(c<0)continue;let d=s.slice(0,c),l=s.slice(c+1);t.set(j(d,l),r)}catch(o){}})(),{get(i,o){let r=t.get(j(i,o));return r?n(r)?(t.delete(j(i,o)),null):r:null},set(i,o,r){let s=j(i,o);t.set(s,r);try{localStorage.setItem(Me(i,o),JSON.stringify(r))}catch(c){}},invalidate(i){let o=`${i}:`;for(let r of[...t.keys()])r.startsWith(o)&&t.delete(r);for(let r of H()){let s=r.slice(z.length),c=s.lastIndexOf("_");if(c<0)continue;if(s.slice(0,c)===i)try{localStorage.removeItem(r)}catch(l){}}},clear(){t.clear();for(let i of H())try{localStorage.removeItem(i)}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 M(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(i){}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 L(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function W(e){let t=Ue("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function Ue(e,t){var o,r,s,c,d,l,g;let n=(r=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?r:"",a=(c=(s=t==null?void 0:t.referer)==null?void 0:s.trim())!=null?c:"",i=(d=t==null?void 0:t.now)!=null?d:new Date;return{sessionId:e,ephemeral:!1,utmParams:(l=t==null?void 0:t.utmParams)!=null?l:{},deviceClass:n?R(n):"desktop",trafficSource:a?M(a,t==null?void 0:t.appOrigin):"direct",referrerDomain:U(a),timeOfDay:L(i),dayOfWeek:(g=["sun","mon","tue","wed","thu","fri","sat"][i.getDay()])!=null?g:"sun"}}var oe="https://sentient-api.fly.dev/v1/events",Le=null,Pe=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 $={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,a]of t)n.startsWith("utm_")&&(e[n]=a);return e}catch(e){return{}}}function se(e){return e.replace(/\/events\/?$/,"")}function Ge(e){var i;let t=se((i=e.ingestUrl)!=null?i:oe),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},a={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(o,r,s){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 Pe=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,s,c)=>a.assign(o,r,s,c),getGraph:()=>a.getGraph(),destroy:()=>a.destroy()}}function ie(e){var b,T,K,C,P;if(typeof window=="undefined")return $;if(Le=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."),$):Ge(e):$;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."),$;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),$;let t=(b=e.ingestUrl)!=null?b:oe,n=Date.now(),a=te(),i=re(),o=ne({ingestUrl:t,apiKey:e.apiKey}),r=se(t),s={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=R((T=navigator.userAgent)!=null?T:""),d=typeof window!="undefined"?window.location.origin:void 0,l=M((K=document.referrer)!=null?K:"",d),g=(C=e.sessionSegment)!=null?C:`${c}:${l}`,m=new Map;if(e.initialAssignments)for(let[f,S]of Object.entries(e.initialAssignments))i.set(f,g,{variantId:S,assignedAt:Date.now(),segment:g,confidence:1});let u=Promise.resolve(),h=a.getSessionId();if(h){let f=U((P=document.referrer)!=null?P:""),S=D({sessionId:h,deviceClass:c,trafficSource:l,referrerDomain:f,utmParams:Ke(),timeOfDay:L(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:a.isEphemeral()},e.userId?{userId:e.userId}:{});try{u=fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(S),headers:s}).then(w=>{w.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(w){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:o});let E={goal(f,S={},w=1,k=0){let A=a.getSessionId();A&&u.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:A,name:f,metadata:S,weight:w,stepIndex:k}),headers:s}).catch(()=>{})})},identify(f){let S=a.getSessionId();S&&u.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:S,userId:f,ephemeral:a.isEphemeral()}),headers:s}).catch(()=>{})})},track(f){let S=a.getSessionId();if(!S)return;let w=B(D({},f),{id:$e(),sessionId:S,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(w),e.debug&&console.log("[sentient] track",w)},getAssignment(f,S){return i.get(f,S)},async assign(f,S,w,k){let A=a.getSessionId();if(!A)return null;let O=i.get(f,g);if(O)return{variantId:O.variantId,assignmentTtlMs:0,content:O.content};let p=m.get(f);if(p)return p;let y=(async()=>{await u;try{let v={sessionId:A,componentId:f,variantIds:S};k!==void 0?v.agentDataByVariant=k:w!==void 0&&(v.agentData=w);let I=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(v),headers:s});if(!I.ok)return null;let x=await I.json();return i.set(f,g,{variantId:x.variantId,assignedAt:Date.now(),segment:g,confidence:1,content:x.content}),x}catch(v){return null}finally{m.delete(f)}})();return m.set(f,y),y},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),a.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let f=window;f.__sentient&&(f.__sentient.client=E)}return E}var Be=new Set(["SECTION","ARTICLE","MAIN","DIV"]),Fe="h1, h2, h3",je={scan:async()=>({nodes:[],edges:[],scannedAt:0}),observe:()=>{},getProminenceScore:()=>0,destroy:()=>{}};function q(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 i=e;for(let o of Object.keys(i)){if(!o.startsWith("__reactFiber")&&!o.startsWith("__reactInternalInstance"))continue;let r=i[o],s=(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(s&&s.length>1)return s}}catch(i){}}function Je(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 He(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function We(e){let t=0,n=e.parentElement;for(;n;)t++,n=n.parentElement;return t}function Y(e,t){var a,i,o;let n=e.querySelector(Fe);return{componentId:He(e),semanticType:Qe(e),ariaLabel:(a=e.getAttribute("aria-label"))!=null?a:void 0,headingText:(o=(i=n==null?void 0:n.textContent)==null?void 0:i.trim())!=null?o:void 0,isAboveFold:e.getBoundingClientRect().top<window.innerHeight,prominenceScore:t(e),depth:We(e),reactComponentName:ze(e),dataAttributes:Je(e)}}function ae(e){var o;let t=[],n=new Set,a="__root__",i=new Map;for(let[r,s]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 l=(o=i.get(d))!=null?o:[];l.push(r),i.set(d,l)}for(let r of i.values())if(!(r.length<2))for(let s=0;s<r.length;s++)for(let c=s+1;c<r.length;c++){let d=e.get(r[s]),l=e.get(r[c]);if(d===l)continue;let g=`${d}->${l}::sib`,m=`${l}->${d}::sib`;n.has(g)||(n.add(g),t.push({fromComponentId:d,toComponentId:l,weight:.3})),n.has(m)||(n.add(m),t.push({fromComponentId:l,toComponentId:d,weight:.3}))}return t}function qe(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 s=Y(r,e);t.push(s),a.set(r,s.componentId)}}),document.querySelectorAll("section, article, main, aside").forEach(r=>{if(!(r instanceof Element)||n.has(r))return;let s=r.hasAttribute("aria-label"),c=r.hasAttribute("data-sentient-id");if(!s&&!c)return;n.add(r);let d=Y(r,e);t.push(d),a.set(r,d.componentId)}),{nodes:t,edges:ae(a)}}function ce(){if(typeof window=="undefined")return je;let e=null,t=0,n=null,a=s=>{try{let c=window.getComputedStyle(s),d=parseFloat(c.fontSize)||12,l=parseFloat(c.zIndex)||0,g=s.getBoundingClientRect(),m=Math.max(g.top,0),u=window.innerHeight||1,h=1/(m/u+1),E=q(d,12,48)*.4+q(h,0,1)*.4+q(l,0,100)*.2;return Math.max(0,Math.min(1,E))}catch(c){return .5}};return{scan:()=>new Promise(s=>{let c=()=>{let{nodes:d,edges:l}=qe(a);s({nodes:d,edges:l,scannedAt:Date.now()})};try{typeof requestIdleCallback=="function"?t=requestIdleCallback(c,{timeout:100}):c()}catch(d){c()}}),observe:s=>{n=s;try{e=new MutationObserver(c=>{let d=[],l=new Map;for(let g of c)g.type==="childList"&&g.addedNodes.forEach(m=>{if(!(m instanceof Element)||!Be.has(m.tagName))return;let u=m.hasAttribute("data-sentient-id"),h=m.hasAttribute("aria-label");if(!u&&!h)return;let E=Y(m,a);d.push(E),l.set(m,E.componentId)});d.length>0&&n&&n({nodes:d,edges:ae(l),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(s){}t=0,n=null}}}var V="_snt_graph_nodes",de="_snt_graph_edges",Ye={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function Ve(e){var t;return(t=Ye[e])!=null?t:[]}function Xe(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function Ze(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var et=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function tt(e){return et.has(e)?e:"generic"}function nt(e,t,n){let a=`${e}:${t}:${n.join(",")}`,i=5381;for(let o=0;o<a.length;o++)i=(i<<5)+i+a.charCodeAt(o)&4294967295;return(i>>>0).toString(16).padStart(8,"0")}function ue(e){let t=new Map,n=new Map,a=()=>{typeof window!="undefined"&&Ze(V,[...t.values()])},i=o=>{var r;try{let s=JSON.parse(o);t.clear();for(let c of(r=s.pageNodes)!=null?r:[])t.set(c.componentId,c)}catch(s){}};if(typeof window!="undefined"){let o=Xe(V,[]);for(let r of o)t.set(r.componentId,r);try{localStorage.removeItem(de)}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,s;if(!(e!=null&&e.syncUrl)||typeof window=="undefined")return;let o=[...t.values()];if(o.length!==0)try{let c=new Map;for(let u of o){let h=(r=c.get(u.semanticType))!=null?r:[];h.push(u),c.set(u.semanticType,h)}let d=[],l=new Set;for(let u of o)for(let h of Ve(u.semanticType)){let E=(s=c.get(h))!=null?s:[];for(let b of E){if(b.componentId===u.componentId)continue;let T=`semantic:${u.componentId}->${b.componentId}`;l.has(T)||(l.add(T),d.push({fromComponentId:u.componentId,toComponentId:b.componentId,type:"semantic",weight:.4,confidence:.9}))}}let g=new Set(o.map(u=>u.componentId));for(let u of n.values()){if(!g.has(u.fromComponentId)||!g.has(u.toComponentId))continue;let h=`structural:${u.fromComponentId}->${u.toComponentId}`;l.has(h)||(l.add(h),d.push({fromComponentId:u.fromComponentId,toComponentId:u.toComponentId,type:"structural",weight:u.weight,confidence:1}))}let m={pageUrl:window.location.href,nodes:o.map(u=>{let h=tt(u.semanticType);return{componentId:u.componentId,semanticType:h,answers:u.answers,contentHash:nt(u.componentId,h,u.answers),prominenceScore:u.prominenceScore,depthInPage:u.depth}}),edges:d};fetch(e.syncUrl,{method:"POST",keepalive:!0,headers:D({"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:i,destroy(){if(typeof window!="undefined")try{localStorage.removeItem(V),localStorage.removeItem(de)}catch(o){}}}}var rt="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 st(e){var o;let t=ie(e);if(!e.graph||typeof window=="undefined")return t;let n=ce(),a=(o=e.ingestUrl)!=null?o:rt,i=ue({syncUrl:a.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:ot()});try{let r=localStorage.getItem("_snt_graph_nodes");r&&i.restore(JSON.stringify({pageNodes:JSON.parse(r)}))}catch(r){}return n.scan().then(r=>{for(let s of r.nodes)i.addPageNode({id:s.componentId,componentId:s.componentId,semanticType:s.semanticType,answers:s.headingText?[s.headingText]:[],prominenceScore:s.prominenceScore,depth:s.depth});for(let s of r.edges)i.addStructuralEdge(s);i.syncOnce()}),n.observe(r=>{for(let s of r.nodes)i.addPageNode({id:s.componentId,componentId:s.componentId,semanticType:s.semanticType,answers:s.headingText?[s.headingText]:[],prominenceScore:s.prominenceScore,depth:s.depth});for(let s of r.edges)i.addStructuralEdge(s)}),B(D({},t),{getGraph:()=>i.snapshot(),destroy:()=>{n.destroy(),i.destroy(),t.destroy()}})}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,init,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,l as v}from"./chunk-CJD3GMCD.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{c as v}from"./chunk-GL5EXCWW.mjs";import{a as h,b,c as x,d as _,e as O,f as M,g as R}from"./chunk-QCYVBCUV.mjs";var P=new Set(["SECTION","ARTICLE","MAIN","DIV"]),D="h1, h2, h3",G={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 k(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 $(e){let t={};for(let n of Array.from(e.attributes))n.name.startsWith("data-")&&(t[n.name]=n.value);return t}function L(e){let t=e.getAttribute("data-sentient-type");if(t)return t;let n=e.getAttribute("role");return n||"generic"}function U(e){var t,n;return(n=(t=e.getAttribute("data-sentient-id"))!=null?t:e.getAttribute("id"))!=null?n:e.tagName.toLowerCase()}function j(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(D);return{componentId:U(e),semanticType:L(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:j(e),reactComponentName:k(e),dataAttributes:$(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 F(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 G;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}=F(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)||!P.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",K={pricing:["features","faq"],features:["pricing"],faq:["pricing"],social_proof:["cta"],cta:["social_proof","hero","trust"],hero:["cta"],comparison:["pricing"],trust:["cta"]};function q(e){var t;return(t=K[e])!=null?t:[]}function z(e,t){try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch(n){return t}}function H(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch(n){}}var J=new Set(["pricing","hero","social_proof","cta","features","faq","comparison","trust","navigation","generic"]);function B(e){return J.has(e)?e:"generic"}function V(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"&&H(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=z(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 q(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=B(i.semanticType);return{componentId:i.componentId,semanticType:f,answers:i.answers,contentHash:V(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 W="https://sentient-api.fly.dev/v1/events";function Y(){try{let e=document.cookie.match(/(?:^|; )_snt_uid=([^;]*)/);return e?decodeURIComponent(e[1]):void 0}catch(e){return}}function oe(e){var s;let t=v(e);if(!e.graph||typeof window=="undefined")return t;let n=N(),p=(s=e.ingestUrl)!=null?s:W,d=T({syncUrl:p.replace(/\/events\/?$/,"/graph/sync"),apiKey:e.apiKey,projectId:e.apiKey,sessionId:Y()});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,oe as init,O as referrerDomainFromReferer};
@@ -0,0 +1,81 @@
1
+ export { S as SessionUpsertPayload, b as buildSessionUpsertPayload, d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.cjs';
2
+
3
+ type ServerAssignConfig = {
4
+ /** Public API key (pk_...). */
5
+ apiKey: string;
6
+ /**
7
+ * Base URL of the Sentient API without trailing slash.
8
+ * e.g. 'https://api.yourapp.com/v1'
9
+ */
10
+ baseUrl: string;
11
+ /**
12
+ * Browser origin of your app (e.g. `http://localhost:3001`). Required for `pk_`
13
+ * keys — server-side fetch must send the same `Origin` the API allows.
14
+ */
15
+ origin?: string;
16
+ /** From `User-Agent` request header (Next.js `headers()`). */
17
+ userAgent?: string;
18
+ /** From `Referer` request header. */
19
+ referer?: string;
20
+ utmParams?: Record<string, string>;
21
+ /**
22
+ * Milliseconds to wait for the API before returning default variants.
23
+ * Prevents slow/cold API from blocking SSR. Defaults to 1500.
24
+ */
25
+ timeoutMs?: number;
26
+ };
27
+ /** componentId → assigned variantId */
28
+ type ServerAssignments = Record<string, string>;
29
+ /**
30
+ * Fetches variant assignments server-side for all listed components.
31
+ * Returns a map suitable for passing as `initialAssignments` to `<AdaptiveProvider>`.
32
+ *
33
+ * Call from Next.js layout, Server Component, or getServerSideProps.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * const assignments = await preloadAssignments(
38
+ * [
39
+ * { id: 'hero', variantIds: ['hero-a', 'hero-b'] },
40
+ * { id: 'cta', variantIds: ['cta-short', 'cta-long'] },
41
+ * ],
42
+ * sessionId, // read from cookies() or req.cookies
43
+ * { apiKey: process.env.SENTIENT_API_KEY!, baseUrl: process.env.SENTIENT_API_URL! },
44
+ * );
45
+ * return <AdaptiveProvider ... initialAssignments={assignments}>{children}</AdaptiveProvider>;
46
+ * ```
47
+ */
48
+ declare function preloadAssignments(components: Array<{
49
+ id: string;
50
+ variantIds: string[];
51
+ }>, sessionId: string, config: ServerAssignConfig): Promise<ServerAssignments>;
52
+ /**
53
+ * Reads the Sentient session cookie from a Next.js `ReadonlyRequestCookies` object
54
+ * (the return value of `cookies()` from `next/headers`), or any object with a
55
+ * `get(name: string)` method. Returns null if the cookie is absent.
56
+ */
57
+ declare function readSessionCookie(cookies: {
58
+ get(name: string): {
59
+ value: string;
60
+ } | undefined;
61
+ }): string | null;
62
+ type DecideResult = {
63
+ layoutOrder: string[];
64
+ assignments: Record<string, string>;
65
+ persona: string;
66
+ confidence: number;
67
+ };
68
+ /**
69
+ * Single-roundtrip SSR call returning layout order + all component assignments.
70
+ * Falls back to default section order + empty assignments if the API is unavailable.
71
+ * Use instead of `preloadAssignments` when the page declares a `sections` array.
72
+ */
73
+ declare function preloadDecisions(params: {
74
+ sections: string[];
75
+ components: Array<{
76
+ id: string;
77
+ variantIds?: string[];
78
+ }>;
79
+ }, sessionId: string, config: ServerAssignConfig): Promise<DecideResult>;
80
+
81
+ export { type DecideResult, type ServerAssignConfig, type ServerAssignments, preloadAssignments, preloadDecisions, readSessionCookie };
@@ -0,0 +1,81 @@
1
+ export { S as SessionUpsertPayload, b as buildSessionUpsertPayload, d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.js';
2
+
3
+ type ServerAssignConfig = {
4
+ /** Public API key (pk_...). */
5
+ apiKey: string;
6
+ /**
7
+ * Base URL of the Sentient API without trailing slash.
8
+ * e.g. 'https://api.yourapp.com/v1'
9
+ */
10
+ baseUrl: string;
11
+ /**
12
+ * Browser origin of your app (e.g. `http://localhost:3001`). Required for `pk_`
13
+ * keys — server-side fetch must send the same `Origin` the API allows.
14
+ */
15
+ origin?: string;
16
+ /** From `User-Agent` request header (Next.js `headers()`). */
17
+ userAgent?: string;
18
+ /** From `Referer` request header. */
19
+ referer?: string;
20
+ utmParams?: Record<string, string>;
21
+ /**
22
+ * Milliseconds to wait for the API before returning default variants.
23
+ * Prevents slow/cold API from blocking SSR. Defaults to 1500.
24
+ */
25
+ timeoutMs?: number;
26
+ };
27
+ /** componentId → assigned variantId */
28
+ type ServerAssignments = Record<string, string>;
29
+ /**
30
+ * Fetches variant assignments server-side for all listed components.
31
+ * Returns a map suitable for passing as `initialAssignments` to `<AdaptiveProvider>`.
32
+ *
33
+ * Call from Next.js layout, Server Component, or getServerSideProps.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * const assignments = await preloadAssignments(
38
+ * [
39
+ * { id: 'hero', variantIds: ['hero-a', 'hero-b'] },
40
+ * { id: 'cta', variantIds: ['cta-short', 'cta-long'] },
41
+ * ],
42
+ * sessionId, // read from cookies() or req.cookies
43
+ * { apiKey: process.env.SENTIENT_API_KEY!, baseUrl: process.env.SENTIENT_API_URL! },
44
+ * );
45
+ * return <AdaptiveProvider ... initialAssignments={assignments}>{children}</AdaptiveProvider>;
46
+ * ```
47
+ */
48
+ declare function preloadAssignments(components: Array<{
49
+ id: string;
50
+ variantIds: string[];
51
+ }>, sessionId: string, config: ServerAssignConfig): Promise<ServerAssignments>;
52
+ /**
53
+ * Reads the Sentient session cookie from a Next.js `ReadonlyRequestCookies` object
54
+ * (the return value of `cookies()` from `next/headers`), or any object with a
55
+ * `get(name: string)` method. Returns null if the cookie is absent.
56
+ */
57
+ declare function readSessionCookie(cookies: {
58
+ get(name: string): {
59
+ value: string;
60
+ } | undefined;
61
+ }): string | null;
62
+ type DecideResult = {
63
+ layoutOrder: string[];
64
+ assignments: Record<string, string>;
65
+ persona: string;
66
+ confidence: number;
67
+ };
68
+ /**
69
+ * Single-roundtrip SSR call returning layout order + all component assignments.
70
+ * Falls back to default section order + empty assignments if the API is unavailable.
71
+ * Use instead of `preloadAssignments` when the page declares a `sections` array.
72
+ */
73
+ declare function preloadDecisions(params: {
74
+ sections: string[];
75
+ components: Array<{
76
+ id: string;
77
+ variantIds?: string[];
78
+ }>;
79
+ }, sessionId: string, config: ServerAssignConfig): Promise<DecideResult>;
80
+
81
+ export { type DecideResult, type ServerAssignConfig, type ServerAssignments, preloadAssignments, preloadDecisions, readSessionCookie };
@@ -0,0 +1 @@
1
+ "use strict";var m=Object.defineProperty,k=Object.defineProperties,C=Object.getOwnPropertyDescriptor,I=Object.getOwnPropertyDescriptors,M=Object.getOwnPropertyNames,b=Object.getOwnPropertySymbols;var A=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable;var v=(t,e,r)=>e in t?m(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,O=(t,e)=>{for(var r in e||(e={}))A.call(e,r)&&v(t,r,e[r]);if(b)for(var r of b(e))_.call(e,r)&&v(t,r,e[r]);return t},P=(t,e)=>k(t,I(e));var $=(t,e)=>{for(var r in e)m(t,r,{get:e[r],enumerable:!0})},j=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!A.call(t,s)&&s!==r&&m(t,s,{get:()=>e[s],enumerable:!(n=C(e,s))||n.enumerable});return t};var L=t=>j(m({},"__esModule",{value:!0}),t);var B={};$(B,{buildSessionUpsertPayload:()=>g,deriveSessionSegment:()=>w,detectDeviceClass:()=>y,detectTimeOfDay:()=>h,detectTrafficSource:()=>p,preloadAssignments:()=>R,preloadDecisions:()=>U,readSessionCookie:()=>x,referrerDomainFromReferer:()=>S});module.exports=L(B);function y(t){let e=t.toLowerCase();return/ipad|tablet|playbook|kindle|silk/.test(e)?"tablet":/mobi|iphone|ipod|android.*mobile|phone/.test(e)?"mobile":"desktop"}function p(t,e){if(!t)return"direct";try{let r=new URL(t);if(e)try{if(new URL(e).host===r.host)return"direct"}catch(s){}let n=r.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(n)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(n)?"social":"referral"}catch(r){return"direct"}}function S(t){if(!t)return null;try{return new URL(t).hostname}catch(e){return null}}function h(t){let e=t.getHours();return e<6?"night":e<12?"morning":e<18?"afternoon":"evening"}function w(t){let e=g("__segment__",t);return`${e.deviceClass}:${e.trafficSource}`}function g(t,e){var a,c,u,o,i,d,l;let r=(c=(a=e==null?void 0:e.userAgent)==null?void 0:a.trim())!=null?c:"",n=(o=(u=e==null?void 0:e.referer)==null?void 0:u.trim())!=null?o:"",s=(i=e==null?void 0:e.now)!=null?i:new Date;return{sessionId:t,ephemeral:!1,utmParams:(d=e==null?void 0:e.utmParams)!=null?d:{},deviceClass:r?y(r):"desktop",trafficSource:n?p(n,e==null?void 0:e.appOrigin):"direct",referrerDomain:S(n),timeOfDay:h(s),dayOfWeek:(l=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?l:"sun"}}var D=1500;function f(t,e,r){let n=new AbortController,s=setTimeout(()=>n.abort(),r);return fetch(t,P(O({},e),{signal:n.signal})).finally(()=>clearTimeout(s))}async function R(t,e,r){var o;let n=(o=r.timeoutMs)!=null?o:D,s={"Content-Type":"application/json",Authorization:`Bearer ${r.apiKey}`};r.origin&&(s.Origin=r.origin);let a=g(e,{userAgent:r.userAgent,referer:r.referer,utmParams:r.utmParams,appOrigin:r.origin});try{(await f(`${r.baseUrl}/sessions`,{method:"POST",headers:s,body:JSON.stringify(a)},n)).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(i){}let c=await Promise.allSettled(t.map(async({id:i,variantIds:d})=>{let l=await f(`${r.baseUrl}/assign`,{method:"POST",headers:s,body:JSON.stringify({sessionId:e,componentId:i,variantIds:d})},n);if(!l.ok)return null;let T=await l.json();return{id:i,variantId:T.variantId}})),u={};for(let i of c)i.status==="fulfilled"&&i.value&&(u[i.value.id]=i.value.variantId);return u}function x(t){var e,r;return(r=(e=t.get("_snt_uid"))==null?void 0:e.value)!=null?r:null}async function U(t,e,r){var u;let n=(u=r.timeoutMs)!=null?u:D,s={layoutOrder:t.sections,assignments:{},persona:"unknown",confidence:0},a={"Content-Type":"application/json",Authorization:`Bearer ${r.apiKey}`};r.origin&&(a.Origin=r.origin);let c=g(e,{userAgent:r.userAgent,referer:r.referer,utmParams:r.utmParams,appOrigin:r.origin});try{await f(`${r.baseUrl}/sessions`,{method:"POST",headers:a,body:JSON.stringify(c)},n)}catch(o){}try{let o=await f(`${r.baseUrl}/decide`,{method:"POST",headers:a,body:JSON.stringify({sessionId:e,sections:t.sections.map(i=>({id:i})),components:t.components})},n);return o.ok?await o.json():s}catch(o){return s}}0&&(module.exports={buildSessionUpsertPayload,deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,preloadAssignments,preloadDecisions,readSessionCookie,referrerDomainFromReferer});
@@ -0,0 +1 @@
1
+ import{a as c,b as p,c as v,d as A,e as b,f as h,g as O,h as l}from"./chunk-QCYVBCUV.mjs";var y=1500;function d(r,t,e){let n=new AbortController,i=setTimeout(()=>n.abort(),e);return fetch(r,p(c({},t),{signal:n.signal})).finally(()=>clearTimeout(i))}async function P(r,t,e){var o;let n=(o=e.timeoutMs)!=null?o:y,i={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`};e.origin&&(i.Origin=e.origin);let a=l(t,{userAgent:e.userAgent,referer:e.referer,utmParams:e.utmParams,appOrigin:e.origin});try{(await d(`${e.baseUrl}/sessions`,{method:"POST",headers:i,body:JSON.stringify(a)},n)).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(s){}let g=await Promise.allSettled(r.map(async({id:s,variantIds:S})=>{let m=await d(`${e.baseUrl}/assign`,{method:"POST",headers:i,body:JSON.stringify({sessionId:t,componentId:s,variantIds:S})},n);if(!m.ok)return null;let f=await m.json();return{id:s,variantId:f.variantId}})),u={};for(let s of g)s.status==="fulfilled"&&s.value&&(u[s.value.id]=s.value.variantId);return u}function T(r){var t,e;return(e=(t=r.get("_snt_uid"))==null?void 0:t.value)!=null?e:null}async function R(r,t,e){var u;let n=(u=e.timeoutMs)!=null?u:y,i={layoutOrder:r.sections,assignments:{},persona:"unknown",confidence:0},a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`};e.origin&&(a.Origin=e.origin);let g=l(t,{userAgent:e.userAgent,referer:e.referer,utmParams:e.utmParams,appOrigin:e.origin});try{await d(`${e.baseUrl}/sessions`,{method:"POST",headers:a,body:JSON.stringify(g)},n)}catch(o){}try{let o=await d(`${e.baseUrl}/decide`,{method:"POST",headers:a,body:JSON.stringify({sessionId:t,sections:r.sections.map(s=>({id:s})),components:r.components})},n);return o.ok?await o.json():i}catch(o){return i}}export{l as buildSessionUpsertPayload,O as deriveSessionSegment,v as detectDeviceClass,h as detectTimeOfDay,A as detectTrafficSource,P as preloadAssignments,R as preloadDecisions,T as readSessionCookie,b as referrerDomainFromReferer};
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ export { d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.cjs';
2
+
1
3
  /** Manages anonymous session identity with cookie + localStorage layers. */
2
4
  type SessionConfig = {
3
5
  cookieName?: string;
@@ -11,7 +13,7 @@ type SessionManager = {
11
13
  };
12
14
 
13
15
  /** Batched event queue with reliable transport (fetch + keepalive, localStorage retry). */
14
- type EventType = 'variant_assigned' | 'goal_achieved' | 'scroll_depth' | 'dwell' | 'cursor_signal' | 'component_visible' | 'component_exited';
16
+ type EventType = 'variant_assigned' | 'goal_achieved' | 'scroll_depth' | 'dwell' | 'cursor_signal' | 'component_visible' | 'component_exited' | 'micro_signal';
15
17
  type SentientEvent = {
16
18
  id: string;
17
19
  sessionId: string;
@@ -123,95 +125,13 @@ type GraphClient = {
123
125
  destroy(): void;
124
126
  };
125
127
 
126
- /** Session metadata helpers (browser + Node). No DOM APIs. */
127
- declare function detectDeviceClass(userAgent: string): string;
128
- declare function detectTrafficSource(referrer: string, appOrigin?: string): string;
129
- declare function referrerDomainFromReferer(referrer: string): string | null;
130
- declare function detectTimeOfDay(d: Date): string;
131
- /** Bandit segment key: `<device_class>:<traffic_source>`. */
132
- declare function deriveSessionSegment(opts?: {
133
- userAgent?: string;
134
- referer?: string;
135
- appOrigin?: string;
136
- }): string;
137
-
138
- type ServerAssignConfig = {
139
- /** Public API key (pk_...). */
140
- apiKey: string;
141
- /**
142
- * Base URL of the Sentient API without trailing slash.
143
- * e.g. 'https://api.yourapp.com/v1'
144
- */
145
- baseUrl: string;
146
- /**
147
- * Browser origin of your app (e.g. `http://localhost:3001`). Required for `pk_`
148
- * keys — server-side fetch must send the same `Origin` the API allows.
149
- */
150
- origin?: string;
151
- /** From `User-Agent` request header (Next.js `headers()`). */
152
- userAgent?: string;
153
- /** From `Referer` request header. */
154
- referer?: string;
155
- utmParams?: Record<string, string>;
156
- /**
157
- * Milliseconds to wait for the API before returning default variants.
158
- * Prevents slow/cold API from blocking SSR. Defaults to 1500.
159
- */
160
- timeoutMs?: number;
161
- };
162
- /** componentId → assigned variantId */
163
- type ServerAssignments = Record<string, string>;
164
- /**
165
- * Fetches variant assignments server-side for all listed components.
166
- * Returns a map suitable for passing as `initialAssignments` to `<AdaptiveProvider>`.
167
- *
168
- * Call from Next.js layout, Server Component, or getServerSideProps.
169
- *
170
- * @example
171
- * ```tsx
172
- * const assignments = await preloadAssignments(
173
- * [
174
- * { id: 'hero', variantIds: ['hero-a', 'hero-b'] },
175
- * { id: 'cta', variantIds: ['cta-short', 'cta-long'] },
176
- * ],
177
- * sessionId, // read from cookies() or req.cookies
178
- * { apiKey: process.env.SENTIENT_API_KEY!, baseUrl: process.env.SENTIENT_API_URL! },
179
- * );
180
- * return <AdaptiveProvider ... initialAssignments={assignments}>{children}</AdaptiveProvider>;
181
- * ```
182
- */
183
- declare function preloadAssignments(components: Array<{
184
- id: string;
185
- variantIds: string[];
186
- }>, sessionId: string, config: ServerAssignConfig): Promise<ServerAssignments>;
187
- /**
188
- * Reads the Sentient session cookie from a Next.js `ReadonlyRequestCookies` object
189
- * (the return value of `cookies()` from `next/headers`), or any object with a
190
- * `get(name: string)` method. Returns null if the cookie is absent.
191
- */
192
- declare function readSessionCookie(cookies: {
193
- get(name: string): {
194
- value: string;
195
- } | undefined;
196
- }): string | null;
197
- type DecideResult = {
198
- layoutOrder: string[];
199
- assignments: Record<string, string>;
200
- persona: string;
201
- confidence: number;
202
- };
128
+ type MicroSignalEmitter = (signalType: 'rage_click' | 'text_copy' | 'scroll_hesitation' | 'tab_loss', extra?: Record<string, unknown>) => void;
203
129
  /**
204
- * Single-roundtrip SSR call returning layout order + all component assignments.
205
- * Falls back to default section order + empty assignments if the API is unavailable.
206
- * Use instead of `preloadAssignments` when the page declares a `sections` array.
130
+ * Attaches passive behavioral detectors to `node`. Calls `emit` when a signal
131
+ * fires. Each signal type fires at most once per call to this function.
132
+ * Returns a cleanup function that removes all listeners.
207
133
  */
208
- declare function preloadDecisions(params: {
209
- sections: string[];
210
- components: Array<{
211
- id: string;
212
- variantIds?: string[];
213
- }>;
214
- }, sessionId: string, config: ServerAssignConfig): Promise<DecideResult>;
134
+ declare function attachMicroSignalDetectors(emit: MicroSignalEmitter, node: Element, variantAssignedAt?: number): () => void;
215
135
 
216
136
  type SentientConfig = {
217
137
  apiKey: string;
@@ -252,11 +172,11 @@ type AssignResult = {
252
172
  };
253
173
  type SentientClient = {
254
174
  track(event: Omit<SentientEvent, 'id' | 'sessionId' | 'timestamp' | 'timeInSession'>): void;
255
- goal(name: string, metadata?: Record<string, unknown>): void;
175
+ goal(name: string, metadata?: Record<string, unknown>, weight?: number, stepIndex?: number): void;
256
176
  identify(userId: string): void;
257
177
  getAssignment(componentId: string, segment: string): Assignment | null;
258
178
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
259
- assign(componentId: string, variantIds?: string[], agentData?: unknown): Promise<AssignResult | null>;
179
+ assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
260
180
  getGraph(): GraphSnapshot;
261
181
  destroy(): void;
262
182
  };
@@ -272,4 +192,4 @@ declare function grantConsent(): void;
272
192
  */
273
193
  declare function init(config: SentientConfig): SentientClient;
274
194
 
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 };
195
+ export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type MicroSignalEmitter, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, attachMicroSignalDetectors, grantConsent, init };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { d as deriveSessionSegment, a as detectDeviceClass, c as detectTimeOfDay, e as detectTrafficSource, r as referrerDomainFromReferer } from './session-meta-DCN-QCHQ.js';
2
+
1
3
  /** Manages anonymous session identity with cookie + localStorage layers. */
2
4
  type SessionConfig = {
3
5
  cookieName?: string;
@@ -11,7 +13,7 @@ type SessionManager = {
11
13
  };
12
14
 
13
15
  /** Batched event queue with reliable transport (fetch + keepalive, localStorage retry). */
14
- type EventType = 'variant_assigned' | 'goal_achieved' | 'scroll_depth' | 'dwell' | 'cursor_signal' | 'component_visible' | 'component_exited';
16
+ type EventType = 'variant_assigned' | 'goal_achieved' | 'scroll_depth' | 'dwell' | 'cursor_signal' | 'component_visible' | 'component_exited' | 'micro_signal';
15
17
  type SentientEvent = {
16
18
  id: string;
17
19
  sessionId: string;
@@ -123,95 +125,13 @@ type GraphClient = {
123
125
  destroy(): void;
124
126
  };
125
127
 
126
- /** Session metadata helpers (browser + Node). No DOM APIs. */
127
- declare function detectDeviceClass(userAgent: string): string;
128
- declare function detectTrafficSource(referrer: string, appOrigin?: string): string;
129
- declare function referrerDomainFromReferer(referrer: string): string | null;
130
- declare function detectTimeOfDay(d: Date): string;
131
- /** Bandit segment key: `<device_class>:<traffic_source>`. */
132
- declare function deriveSessionSegment(opts?: {
133
- userAgent?: string;
134
- referer?: string;
135
- appOrigin?: string;
136
- }): string;
137
-
138
- type ServerAssignConfig = {
139
- /** Public API key (pk_...). */
140
- apiKey: string;
141
- /**
142
- * Base URL of the Sentient API without trailing slash.
143
- * e.g. 'https://api.yourapp.com/v1'
144
- */
145
- baseUrl: string;
146
- /**
147
- * Browser origin of your app (e.g. `http://localhost:3001`). Required for `pk_`
148
- * keys — server-side fetch must send the same `Origin` the API allows.
149
- */
150
- origin?: string;
151
- /** From `User-Agent` request header (Next.js `headers()`). */
152
- userAgent?: string;
153
- /** From `Referer` request header. */
154
- referer?: string;
155
- utmParams?: Record<string, string>;
156
- /**
157
- * Milliseconds to wait for the API before returning default variants.
158
- * Prevents slow/cold API from blocking SSR. Defaults to 1500.
159
- */
160
- timeoutMs?: number;
161
- };
162
- /** componentId → assigned variantId */
163
- type ServerAssignments = Record<string, string>;
164
- /**
165
- * Fetches variant assignments server-side for all listed components.
166
- * Returns a map suitable for passing as `initialAssignments` to `<AdaptiveProvider>`.
167
- *
168
- * Call from Next.js layout, Server Component, or getServerSideProps.
169
- *
170
- * @example
171
- * ```tsx
172
- * const assignments = await preloadAssignments(
173
- * [
174
- * { id: 'hero', variantIds: ['hero-a', 'hero-b'] },
175
- * { id: 'cta', variantIds: ['cta-short', 'cta-long'] },
176
- * ],
177
- * sessionId, // read from cookies() or req.cookies
178
- * { apiKey: process.env.SENTIENT_API_KEY!, baseUrl: process.env.SENTIENT_API_URL! },
179
- * );
180
- * return <AdaptiveProvider ... initialAssignments={assignments}>{children}</AdaptiveProvider>;
181
- * ```
182
- */
183
- declare function preloadAssignments(components: Array<{
184
- id: string;
185
- variantIds: string[];
186
- }>, sessionId: string, config: ServerAssignConfig): Promise<ServerAssignments>;
187
- /**
188
- * Reads the Sentient session cookie from a Next.js `ReadonlyRequestCookies` object
189
- * (the return value of `cookies()` from `next/headers`), or any object with a
190
- * `get(name: string)` method. Returns null if the cookie is absent.
191
- */
192
- declare function readSessionCookie(cookies: {
193
- get(name: string): {
194
- value: string;
195
- } | undefined;
196
- }): string | null;
197
- type DecideResult = {
198
- layoutOrder: string[];
199
- assignments: Record<string, string>;
200
- persona: string;
201
- confidence: number;
202
- };
128
+ type MicroSignalEmitter = (signalType: 'rage_click' | 'text_copy' | 'scroll_hesitation' | 'tab_loss', extra?: Record<string, unknown>) => void;
203
129
  /**
204
- * Single-roundtrip SSR call returning layout order + all component assignments.
205
- * Falls back to default section order + empty assignments if the API is unavailable.
206
- * Use instead of `preloadAssignments` when the page declares a `sections` array.
130
+ * Attaches passive behavioral detectors to `node`. Calls `emit` when a signal
131
+ * fires. Each signal type fires at most once per call to this function.
132
+ * Returns a cleanup function that removes all listeners.
207
133
  */
208
- declare function preloadDecisions(params: {
209
- sections: string[];
210
- components: Array<{
211
- id: string;
212
- variantIds?: string[];
213
- }>;
214
- }, sessionId: string, config: ServerAssignConfig): Promise<DecideResult>;
134
+ declare function attachMicroSignalDetectors(emit: MicroSignalEmitter, node: Element, variantAssignedAt?: number): () => void;
215
135
 
216
136
  type SentientConfig = {
217
137
  apiKey: string;
@@ -252,11 +172,11 @@ type AssignResult = {
252
172
  };
253
173
  type SentientClient = {
254
174
  track(event: Omit<SentientEvent, 'id' | 'sessionId' | 'timestamp' | 'timeInSession'>): void;
255
- goal(name: string, metadata?: Record<string, unknown>): void;
175
+ goal(name: string, metadata?: Record<string, unknown>, weight?: number, stepIndex?: number): void;
256
176
  identify(userId: string): void;
257
177
  getAssignment(componentId: string, segment: string): Assignment | null;
258
178
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
259
- assign(componentId: string, variantIds?: string[], agentData?: unknown): Promise<AssignResult | null>;
179
+ assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
260
180
  getGraph(): GraphSnapshot;
261
181
  destroy(): void;
262
182
  };
@@ -272,4 +192,4 @@ declare function grantConsent(): void;
272
192
  */
273
193
  declare function init(config: SentientConfig): SentientClient;
274
194
 
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 };
195
+ export { type AssignResult, type Assignment, type AssignmentCache, type ContentAddedEvent, type DOMScanner, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type MicroSignalEmitter, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, attachMicroSignalDetectors, grantConsent, init };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var G=Object.defineProperty,ge=Object.defineProperties,me=Object.getOwnPropertyDescriptor,fe=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,fe(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=me(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 d,l,f,h,S;if(typeof window=="undefined")return Ue;let t=(d=e==null?void 0:e.cookieName)!=null?d:we,i=((l=e==null?void 0:e.cookieTTLDays)!=null?l:365)*24*60*60,r=(S=(h=(f=Ae(t))!=null?f: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),u=!o&&!s&&!a;return{getSessionId:()=>r,isEphemeral:()=>u,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 I,E,D;if(typeof window=="undefined")return Re;let t=(I=e.flushIntervalMs)!=null?I:5e3,n=(E=e.maxBatchSize)!=null?E:20,i=(D=e.maxRetrySize)!=null?D:100,r=e.ingestUrl,o=e.apiKey,s=[],a=new Set,u=[],d=c=>{for(let p of c)l.delete(p),!a.has(p)&&(a.add(p),u.push(p));for(;u.length>500;){let p=u.shift();p&&a.delete(p)}},l=new Set,f=c=>{a.has(c.id)||l.has(c.id)||(l.add(c.id),s.push(c))},h=Pe(i);for(let c of h)f(c);let S=0,v=0,K=c=>{if(c.length===0)return;let p=JSON.stringify(c),x=c.map(A=>A.id),b;try{b=fetch(r,{method:"POST",keepalive:!0,body:p,headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`}})}catch(A){Y(c,i);for(let W of x)l.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){d(x),v=0,S=0;return}Y(c,i);for(let W of x)l.delete(W);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};b instanceof Promise?b.then(O).catch(()=>{Y(c,i);for(let A of x)l.delete(A);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):O(b)},C=typeof TextEncoder!="undefined"?new TextEncoder:null,N=c=>C?C.encode(c).length:c.length,B=c=>{let p=[],x=2;for(let b of c){let O=N(JSON.stringify(b))+1;if(p.length>0&&x+O>57344||p.length>=n)break;p.push(b),x+=O}return p},w=()=>{try{if(Date.now()<S)return;for(;s.length>0;){let c=s.filter(x=>!a.has(x.id));if(s.length=0,c.length===0)break;let p=B(c);if(p.length===0)break;p.length<c.length&&s.push(...c.slice(p.length)),K(p)}}catch(c){}},g=!0,m=null;m=setInterval(()=>{g&&w()},t);let y=()=>{document.visibilityState==="hidden"&&w()},T=()=>{w()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",T),{push(c){f(c),s.length>=n&&w()},flush:w,destroy(){g=!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),u=a.lastIndexOf("_");if(u<0)continue;let d=a.slice(0,u),l=a.slice(u+1);t.set(J(d,l),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(u){}},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),u=a.lastIndexOf("_");if(u<0)continue;if(a.slice(0,u)===r)try{localStorage.removeItem(s)}catch(l){}}},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,u,d,l,f;let n=(s=(o=t==null?void 0:t.userAgent)==null?void 0:o.trim())!=null?s:"",i=(u=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?u:"",r=(d=t==null?void 0:t.now)!=null?d:new Date;return{sessionId:e,ephemeral:!1,utmParams:(l=t==null?void 0:t.utmParams)!=null?l:{},deviceClass:n?R(n):"desktop",trafficSource:i?P(i,t==null?void 0:t.appOrigin):"direct",referrerDomain:M(i),timeOfDay:$(r),dayOfWeek:(f=["sun","mon","tue","wed","thu","fri","sat"][r.getDay()])!=null?f:"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 u;let i=(u=n.timeoutMs)!=null?u: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(d){}let s=await Promise.allSettled(e.map(async({id:d,variantIds:l})=>{let f=await z(`${n.baseUrl}/assign`,{method:"POST",headers:r,body:JSON.stringify({sessionId:t,componentId:d,variantIds:l})},i);if(!f.ok)return null;let h=await f.json();return{id:d,variantId:h.variantId}})),a={};for(let d of s)d.status==="fulfilled"&&d.value&&(a[d.value.id]=d.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(u){}try{let u=await z(`${n.baseUrl}/decide`,{method:"POST",headers:o,body:JSON.stringify({sessionId:t,sections:e.sections.map(d=>({id:d})),components:e.components})},i);return u.ok?await u.json():r}catch(u){return r}}var ue="https://sentient-api.fly.dev/v1/events",H=null,V=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 de(e){return e.replace(/\/events\/?$/,"")}function Ke(){if(typeof window=="undefined")return;if(!H){console.warn("[sentient] grantConsent() called before init()");return}let e=V;V=null;let t=le(U(_({},H),{consent:!0}));e==null||e(t)}function Ne(e){var r;let t=de((r=e.ingestUrl)!=null?r:ue),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},i={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(o,s,a){try{let u=new URLSearchParams({componentId:o});for(let f of s!=null?s:[])u.append("variantIds[]",f);let d=await fetch(`${t}/winner?${u.toString()}`,{headers:n});return d.ok?{variantId:(await d.json()).variantId,assignmentTtlMs:0}:s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}catch(u){return s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return V=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)=>i.assign(o,s,a),getGraph:()=>i.getGraph(),destroy:()=>i.destroy()}}function le(e){var K,C,N,B,w;if(typeof window=="undefined")return L;if(H=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:ue,n=Date.now(),i=te(),r=re(),o=ne({ingestUrl:t,apiKey:e.apiKey}),s=de(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},u=R((C=navigator.userAgent)!=null?C:""),d=typeof window!="undefined"?window.location.origin:void 0,l=P((N=document.referrer)!=null?N:"",d),f=(B=e.sessionSegment)!=null?B:`${u}:${l}`;if(e.initialAssignments)for(let[g,m]of Object.entries(e.initialAssignments))r.set(g,f,{variantId:m,assignedAt:Date.now(),segment:f,confidence:1});let h=Promise.resolve(),S=i.getSessionId();if(S){let g=M((w=document.referrer)!=null?w:""),m=_({sessionId:S,deviceClass:u,trafficSource:l,referrerDomain:g,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(g,m={}){let y=i.getSessionId();y&&h.then(()=>{fetch(`${s}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:g,metadata:m}),headers:a}).catch(()=>{})})},identify(g){let m=i.getSessionId();m&&h.then(()=>{fetch(`${s}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:g,ephemeral:i.isEphemeral()}),headers:a}).catch(()=>{})})},track(g){let m=i.getSessionId();if(!m)return;let y=U(_({},g),{id:$e(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});o.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(g,m){return r.get(g,m)},async assign(g,m,y){let T=i.getSessionId();if(!T)return null;let I=r.get(g,f);if(I)return{variantId:I.variantId,assignmentTtlMs:0,content:I.content};await h;try{let E={sessionId:T,componentId:g,variantIds:m};y!==void 0&&(E.agentData=y);let D=await fetch(`${s}/assign`,{method:"POST",body:JSON.stringify(E),headers:a});if(!D.ok)return null;let c=await D.json();return r.set(g,f,{variantId:c.variantId,assignedAt:Date.now(),segment:f,confidence:1,content:c.content}),c}catch(E){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){o.destroy(),i.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let g=window;g.__sentient&&(g.__sentient.client=v)}return v}0&&(module.exports={deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,preloadAssignments,preloadDecisions,readSessionCookie,referrerDomainFromReferer});
1
+ "use strict";var N=Object.defineProperty,ae=Object.defineProperties,ce=Object.getOwnPropertyDescriptor,le=Object.getOwnPropertyDescriptors,ue=Object.getOwnPropertyNames,q=Object.getOwnPropertySymbols;var X=Object.prototype.hasOwnProperty,de=Object.prototype.propertyIsEnumerable;var V=(e,t,r)=>t in e?N(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,B=(e,t)=>{for(var r in t||(t={}))X.call(t,r)&&V(e,r,t[r]);if(q)for(var r of q(t))de.call(t,r)&&V(e,r,t[r]);return e},z=(e,t)=>ae(e,le(t));var ge=(e,t)=>{for(var r in t)N(e,r,{get:t[r],enumerable:!0})},fe=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ue(t))!X.call(e,i)&&i!==r&&N(e,i,{get:()=>t[i],enumerable:!(o=ce(t,i))||o.enumerable});return e};var me=e=>fe(N({},"__esModule",{value:!0}),e);var Pe={};ge(Pe,{attachMicroSignalDetectors:()=>ie,deriveSessionSegment:()=>ne,detectDeviceClass:()=>O,detectTimeOfDay:()=>L,detectTrafficSource:()=>R,grantConsent:()=>Le,init:()=>oe,referrerDomainFromReferer:()=>U});module.exports=me(Pe);var pe="_snt_uid";var T="_snt_uid";function he(){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 ye(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function Se(e,t,r){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${r}; SameSite=strict; path=/`}catch(o){}}function ve(e){try{return localStorage.getItem(e)}catch(t){return null}}function we(e,t){try{return localStorage.setItem(e,t),!0}catch(r){return!1}}function xe(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function Ee(e,t){try{return sessionStorage.setItem(e,t),!0}catch(r){return!1}}function _e(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 ke(e){try{localStorage.removeItem(e)}catch(t){}}function Ie(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Ce={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Z(e){var f,d,m,v,h;if(typeof window=="undefined")return Ce;let t=(f=e==null?void 0:e.cookieName)!=null?f:pe,o=((d=e==null?void 0:e.cookieTTLDays)!=null?d:365)*24*60*60,i=(h=(v=(m=ye(t))!=null?m:ve(T))!=null?v:xe(T))!=null?h:he();Se(t,i,o);let s=we(T,i),n=be(t),a=s?!1:Ee(T,i),c=!s&&!n&&!a;return{getSessionId:()=>i,isEphemeral:()=>c,destroy:()=>{i=null,Ie(t),ke(T),_e(T)}}}var G="_snt_retry";var Te={push:()=>{},flush:()=>{},destroy:()=>{}};function De(e){try{let t=localStorage.getItem(G);if(!t)return[];let r=JSON.parse(t);return Array.isArray(r)?(localStorage.removeItem(G),r.slice(-e)):[]}catch(t){return[]}}function J(e,t){try{let o=[...(()=>{try{let i=localStorage.getItem(G);if(!i)return[];let s=JSON.parse(i);return Array.isArray(s)?s:[]}catch(i){return[]}})(),...e].slice(-t);localStorage.setItem(G,JSON.stringify(o))}catch(r){}}function ee(e){var I,k,C;if(typeof window=="undefined")return Te;let t=(I=e.flushIntervalMs)!=null?I:5e3,r=(k=e.maxBatchSize)!=null?k:20,o=(C=e.maxRetrySize)!=null?C:100,i=e.ingestUrl,s=e.apiKey,n=[],a=new Set,c=[],f=l=>{for(let g of l)d.delete(g),!a.has(g)&&(a.add(g),c.push(g));for(;c.length>500;){let g=c.shift();g&&a.delete(g)}},d=new Set,m=l=>{a.has(l.id)||d.has(l.id)||(d.add(l.id),n.push(l))},v=De(o);for(let l of v)m(l);let h=0,w=0,P=l=>{if(l.length===0)return;let g=JSON.stringify(l),y=l.map(b=>b.id),x;try{x=fetch(i,{method:"POST",keepalive:!0,body:g,headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`}})}catch(b){J(l,o);for(let W of y)d.delete(W);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6));return}let _=b=>{if(b.ok||b.status>=400&&b.status<500&&b.status!==429){f(y),w=0,h=0;return}J(l,o);for(let W of y)d.delete(W);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6))};x instanceof Promise?x.then(_).catch(()=>{J(l,o);for(let b of y)d.delete(b);w++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(w,6))}):_(x)},D=typeof TextEncoder!="undefined"?new TextEncoder:null,$=l=>D?D.encode(l).length:l.length,K=l=>{let g=[],y=2;for(let x of l){let _=$(JSON.stringify(x))+1;if(g.length>0&&y+_>57344||g.length>=r)break;g.push(x),y+=_}return g},E=()=>{try{if(Date.now()<h)return;for(;n.length>0;){let l=n.filter(y=>!a.has(y.id));if(n.length=0,l.length===0)break;let g=K(l);if(g.length===0)break;g.length<l.length&&n.push(...l.slice(g.length)),P(g)}}catch(l){}},A=!0,u=null;u=setInterval(()=>{A&&E()},t);let p=()=>{document.visibilityState==="hidden"&&E()},S=()=>{E()};return document.addEventListener("visibilitychange",p),window.addEventListener("beforeunload",S),{push(l){m(l),n.length>=r&&E()},flush:E,destroy(){A=!1,u!==null&&(clearInterval(u),u=null),document.removeEventListener("visibilitychange",p),window.removeEventListener("beforeunload",S),E()}}}var F="_snt_asgn_";function Q(e,t){return`${e}:${t}`}function Ae(e,t){return`${F}${e}_${t}`}function j(){try{let e=[];for(let t=0;t<localStorage.length;t++){let r=localStorage.key(t);r!=null&&r.startsWith(F)&&e.push(r)}return e}catch(e){return[]}}function te(e=18e5){let t=new Map,r=i=>i.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let i of j())try{let s=localStorage.getItem(i);if(!s)continue;let n=JSON.parse(s);if(r(n)){localStorage.removeItem(i);continue}let a=i.slice(F.length),c=a.lastIndexOf("_");if(c<0)continue;let f=a.slice(0,c),d=a.slice(c+1);t.set(Q(f,d),n)}catch(s){}})(),{get(i,s){let n=t.get(Q(i,s));return n?r(n)?(t.delete(Q(i,s)),null):n:null},set(i,s,n){let a=Q(i,s);t.set(a,n);try{localStorage.setItem(Ae(i,s),JSON.stringify(n))}catch(c){}},invalidate(i){let s=`${i}:`;for(let n of[...t.keys()])n.startsWith(s)&&t.delete(n);for(let n of j()){let a=n.slice(F.length),c=a.lastIndexOf("_");if(c<0)continue;if(a.slice(0,c)===i)try{localStorage.removeItem(n)}catch(d){}}},clear(){t.clear();for(let i of j())try{localStorage.removeItem(i)}catch(s){}}}}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 R(e,t){if(!e)return"direct";try{let r=new URL(e);if(t)try{if(new URL(t).host===r.host)return"direct"}catch(i){}let o=r.hostname.toLowerCase();return/(^|\.)(google|bing|duckduckgo|yahoo)\./.test(o)?"search":/(^|\.)(twitter|x\.com|facebook|linkedin|reddit|t\.co)/.test(o)?"social":"referral"}catch(r){return"direct"}}function U(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function L(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function ne(e){let t=Oe("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function Oe(e,t){var s,n,a,c,f,d,m;let r=(n=(s=t==null?void 0:t.userAgent)==null?void 0:s.trim())!=null?n:"",o=(c=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?c:"",i=(f=t==null?void 0:t.now)!=null?f:new Date;return{sessionId:e,ephemeral:!1,utmParams:(d=t==null?void 0:t.utmParams)!=null?d:{},deviceClass:r?O(r):"desktop",trafficSource:o?R(o,t==null?void 0:t.appOrigin):"direct",referrerDomain:U(o),timeOfDay:L(i),dayOfWeek:(m=["sun","mon","tue","wed","thu","fri","sat"][i.getDay()])!=null?m:"sun"}}function ie(e,t,r){let o=[];{let n=!1,a=[],c=()=>{if(n)return;let f=Date.now();for(a.push(f);a.length>0&&f-a[0]>500;)a.shift();a.length>=3&&(n=!0,e("rage_click"))};t.addEventListener("click",c),o.push(()=>t.removeEventListener("click",c))}{let i=!1,s=n=>{if(i||!(n.target instanceof Node)||!t.contains(n.target)&&t!==n.target)return;i=!0;let a=typeof window!="undefined"?window.getSelection():null,c=a?a.toString().length:0;e("text_copy",{selectionLength:c})};document.addEventListener("copy",s),o.push(()=>document.removeEventListener("copy",s))}{let i=!1,s=!1,n=null,a=()=>{n!==null&&(clearTimeout(n),n=null)},c=()=>{i||!s||(a(),n=setTimeout(()=>{!i&&s&&(i=!0,e("scroll_hesitation"))},3e3))},f=()=>{a(),c()},d=v=>{for(let h of v)s=h.intersectionRatio>.3,s?c():a()};window.__lastIOCallback=d;let m=new IntersectionObserver(d,{threshold:[.3]});m.observe(t),window.addEventListener("scroll",f,{passive:!0}),o.push(()=>{m.disconnect(),window.removeEventListener("scroll",f),a()})}{let i=!1,s=r!=null?r:Date.now(),n=()=>{if(i||document.visibilityState!=="hidden")return;let a=Date.now()-s;a<15e3&&(i=!0,e("tab_loss",{timeOnPage:a}))};document.addEventListener("visibilitychange",n),o.push(()=>document.removeEventListener("visibilitychange",n))}return()=>{for(let i of o)i()}}var re="https://sentient-api.fly.dev/v1/events",H=null,Y=null;function Re(){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 M={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Ue(){try{let e={},t=new URLSearchParams(window.location.search);for(let[r,o]of t)r.startsWith("utm_")&&(e[r]=o);return e}catch(e){return{}}}function se(e){return e.replace(/\/events\/?$/,"")}function Le(){if(typeof window=="undefined")return;if(!H){console.warn("[sentient] grantConsent() called before init()");return}let e=Y;Y=null;let t=oe(z(B({},H),{consent:!0}));e==null||e(t)}function Me(e){var i;let t=se((i=e.ingestUrl)!=null?i:re),r={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},o={track:()=>{},goal:()=>{},identify:()=>{},getAssignment:()=>null,async assign(s,n,a){try{let c=new URLSearchParams({componentId:s});for(let m of n!=null?n:[])c.append("variantIds[]",m);let f=await fetch(`${t}/winner?${c.toString()}`,{headers:r});return f.ok?{variantId:(await f.json()).variantId,assignmentTtlMs:0}:n!=null&&n[0]?{variantId:n[0],assignmentTtlMs:0}:null}catch(c){return n!=null&&n[0]?{variantId:n[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return Y=s=>{o=s},{track:s=>o.track(s),goal:(s,n)=>o.goal(s,n),identify:s=>o.identify(s),getAssignment:(s,n)=>o.getAssignment(s,n),assign:(s,n,a,c)=>o.assign(s,n,a,c),getGraph:()=>o.getGraph(),destroy:()=>o.destroy()}}function oe(e){var D,$,K,E,A;if(typeof window=="undefined")return M;if(H=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."),M):Me(e):M;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."),M;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),M;let t=(D=e.ingestUrl)!=null?D:re,r=Date.now(),o=Z(),i=te(),s=ee({ingestUrl:t,apiKey:e.apiKey}),n=se(t),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c=O(($=navigator.userAgent)!=null?$:""),f=typeof window!="undefined"?window.location.origin:void 0,d=R((K=document.referrer)!=null?K:"",f),m=(E=e.sessionSegment)!=null?E:`${c}:${d}`,v=new Map;if(e.initialAssignments)for(let[u,p]of Object.entries(e.initialAssignments))i.set(u,m,{variantId:p,assignedAt:Date.now(),segment:m,confidence:1});let h=Promise.resolve(),w=o.getSessionId();if(w){let u=U((A=document.referrer)!=null?A:""),p=B({sessionId:w,deviceClass:c,trafficSource:d,referrerDomain:u,utmParams:Ue(),timeOfDay:L(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:o.isEphemeral()},e.userId?{userId:e.userId}:{});try{h=fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(p),headers:a}).then(S=>{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(()=>{})}catch(S){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:s});let P={goal(u,p={},S=1,I=0){let k=o.getSessionId();k&&h.then(()=>{fetch(`${n}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:k,name:u,metadata:p,weight:S,stepIndex:I}),headers:a}).catch(()=>{})})},identify(u){let p=o.getSessionId();p&&h.then(()=>{fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:p,userId:u,ephemeral:o.isEphemeral()}),headers:a}).catch(()=>{})})},track(u){let p=o.getSessionId();if(!p)return;let S=z(B({},u),{id:Re(),sessionId:p,timestamp:Date.now(),timeInSession:Date.now()-r});s.push(S),e.debug&&console.log("[sentient] track",S)},getAssignment(u,p){return i.get(u,p)},async assign(u,p,S,I){let k=o.getSessionId();if(!k)return null;let C=i.get(u,m);if(C)return{variantId:C.variantId,assignmentTtlMs:0,content:C.content};let l=v.get(u);if(l)return l;let g=(async()=>{await h;try{let y={sessionId:k,componentId:u,variantIds:p};I!==void 0?y.agentDataByVariant=I:S!==void 0&&(y.agentData=S);let x=await fetch(`${n}/assign`,{method:"POST",body:JSON.stringify(y),headers:a});if(!x.ok)return null;let _=await x.json();return i.set(u,m,{variantId:_.variantId,assignedAt:Date.now(),segment:m,confidence:1,content:_.content}),_}catch(y){return null}finally{v.delete(u)}})();return v.set(u,g),g},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){s.destroy(),o.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let u=window;u.__sentient&&(u.__sentient.client=P)}return P}0&&(module.exports={attachMicroSignalDetectors,deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,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,l as j}from"./chunk-CJD3GMCD.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};
1
+ import{a as f,b as g,c as h}from"./chunk-GL5EXCWW.mjs";import{c as a,d as b,e as c,f as d,g as e}from"./chunk-QCYVBCUV.mjs";export{f as attachMicroSignalDetectors,e as deriveSessionSegment,a as detectDeviceClass,d as detectTimeOfDay,b as detectTrafficSource,g as grantConsent,h as init,c as referrerDomainFromReferer};
@@ -0,0 +1,34 @@
1
+ /** Session metadata helpers (browser + Node). No DOM APIs. */
2
+ declare function detectDeviceClass(userAgent: string): string;
3
+ declare function detectTrafficSource(referrer: string, appOrigin?: string): string;
4
+ declare function referrerDomainFromReferer(referrer: string): string | null;
5
+ declare function detectTimeOfDay(d: Date): string;
6
+ type SessionUpsertPayload = {
7
+ sessionId: string;
8
+ ephemeral: boolean;
9
+ utmParams: Record<string, string>;
10
+ deviceClass: string;
11
+ trafficSource: string;
12
+ referrerDomain: string | null;
13
+ timeOfDay: string;
14
+ dayOfWeek: string;
15
+ };
16
+ /** Bandit segment key: `<device_class>:<traffic_source>`. */
17
+ declare function deriveSessionSegment(opts?: {
18
+ userAgent?: string;
19
+ referer?: string;
20
+ appOrigin?: string;
21
+ }): string;
22
+ /**
23
+ * Builds a session upsert body aligned with the browser SDK so SSR assign uses
24
+ * the same segment key (`device:source`) as the client after hydration.
25
+ */
26
+ declare function buildSessionUpsertPayload(sessionId: string, opts?: {
27
+ userAgent?: string;
28
+ referer?: string;
29
+ appOrigin?: string;
30
+ utmParams?: Record<string, string>;
31
+ now?: Date;
32
+ }): SessionUpsertPayload;
33
+
34
+ export { type SessionUpsertPayload as S, detectDeviceClass as a, buildSessionUpsertPayload as b, detectTimeOfDay as c, deriveSessionSegment as d, detectTrafficSource as e, referrerDomainFromReferer as r };
@@ -0,0 +1,34 @@
1
+ /** Session metadata helpers (browser + Node). No DOM APIs. */
2
+ declare function detectDeviceClass(userAgent: string): string;
3
+ declare function detectTrafficSource(referrer: string, appOrigin?: string): string;
4
+ declare function referrerDomainFromReferer(referrer: string): string | null;
5
+ declare function detectTimeOfDay(d: Date): string;
6
+ type SessionUpsertPayload = {
7
+ sessionId: string;
8
+ ephemeral: boolean;
9
+ utmParams: Record<string, string>;
10
+ deviceClass: string;
11
+ trafficSource: string;
12
+ referrerDomain: string | null;
13
+ timeOfDay: string;
14
+ dayOfWeek: string;
15
+ };
16
+ /** Bandit segment key: `<device_class>:<traffic_source>`. */
17
+ declare function deriveSessionSegment(opts?: {
18
+ userAgent?: string;
19
+ referer?: string;
20
+ appOrigin?: string;
21
+ }): string;
22
+ /**
23
+ * Builds a session upsert body aligned with the browser SDK so SSR assign uses
24
+ * the same segment key (`device:source`) as the client after hydration.
25
+ */
26
+ declare function buildSessionUpsertPayload(sessionId: string, opts?: {
27
+ userAgent?: string;
28
+ referer?: string;
29
+ appOrigin?: string;
30
+ utmParams?: Record<string, string>;
31
+ now?: Date;
32
+ }): SessionUpsertPayload;
33
+
34
+ export { type SessionUpsertPayload as S, detectDeviceClass as a, buildSessionUpsertPayload as b, detectTimeOfDay as c, deriveSessionSegment as d, detectTrafficSource as e, referrerDomainFromReferer as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/core",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,6 +16,11 @@
16
16
  "types": "./dist/index-graph.d.ts",
17
17
  "import": "./dist/index-graph.mjs",
18
18
  "require": "./dist/index-graph.js"
19
+ },
20
+ "./server": {
21
+ "types": "./dist/index-server.d.ts",
22
+ "import": "./dist/index-server.mjs",
23
+ "require": "./dist/index-server.js"
19
24
  }
20
25
  },
21
26
  "files": [
@@ -1 +0,0 @@
1
- var ie=Object.defineProperty,oe=Object.defineProperties;var ae=Object.getOwnPropertyDescriptors;var V=Object.getOwnPropertySymbols;var ce=Object.prototype.hasOwnProperty,ue=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(V)for(var n of V(t))ue.call(t,n)&&X(e,n,t[n]);return e},U=(e,t)=>oe(e,ae(t));var de="_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 me(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(o){}}function fe(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 d,l,f,h,S;if(typeof window=="undefined")return Ae;let t=(d=e==null?void 0:e.cookieName)!=null?d:de,o=((l=e==null?void 0:e.cookieTTLDays)!=null?l:365)*24*60*60,s=(S=(h=(f=ge(t))!=null?f:fe(k))!=null?h:ye(k))!=null?S:le();me(t,s,o);let i=pe(k,s),r=ve(t),a=i?!1:he(k,s),u=!i&&!r&&!a;return{getSessionId:()=>s,isEphemeral:()=>u,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 I,E,D;if(typeof window=="undefined")return be;let t=(I=e.flushIntervalMs)!=null?I:5e3,n=(E=e.maxBatchSize)!=null?E:20,o=(D=e.maxRetrySize)!=null?D:100,s=e.ingestUrl,i=e.apiKey,r=[],a=new Set,u=[],d=c=>{for(let p of c)l.delete(p),!a.has(p)&&(a.add(p),u.push(p));for(;u.length>500;){let p=u.shift();p&&a.delete(p)}},l=new Set,f=c=>{a.has(c.id)||l.has(c.id)||(l.add(c.id),r.push(c))},h=Ie(o);for(let c of h)f(c);let S=0,v=0,P=c=>{if(c.length===0)return;let p=JSON.stringify(c),x=c.map(A=>A.id),b;try{b=fetch(s,{method:"POST",keepalive:!0,body:p,headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}})}catch(A){W(c,o);for(let z of x)l.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){d(x),v=0,S=0;return}W(c,o);for(let z of x)l.delete(z);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};b instanceof Promise?b.then(O).catch(()=>{W(c,o);for(let A of x)l.delete(A);v++,S=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):O(b)},C=typeof TextEncoder!="undefined"?new TextEncoder:null,M=c=>C?C.encode(c).length:c.length,$=c=>{let p=[],x=2;for(let b of c){let O=M(JSON.stringify(b))+1;if(p.length>0&&x+O>57344||p.length>=n)break;p.push(b),x+=O}return p},w=()=>{try{if(Date.now()<S)return;for(;r.length>0;){let c=r.filter(x=>!a.has(x.id));if(r.length=0,c.length===0)break;let p=$(c);if(p.length===0)break;p.length<c.length&&r.push(...c.slice(p.length)),P(p)}}catch(c){}},g=!0,m=null;m=setInterval(()=>{g&&w()},t);let y=()=>{document.visibilityState==="hidden"&&w()},T=()=>{w()};return document.addEventListener("visibilitychange",y),window.addEventListener("beforeunload",T),{push(c){f(c),r.length>=n&&w()},flush:w,destroy(){g=!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),u=a.lastIndexOf("_");if(u<0)continue;let d=a.slice(0,u),l=a.slice(u+1);t.set(K(d,l),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(u){}},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),u=a.lastIndexOf("_");if(u<0)continue;if(a.slice(0,u)===s)try{localStorage.removeItem(r)}catch(l){}}},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,u,d,l,f;let n=(r=(i=t==null?void 0:t.userAgent)==null?void 0:i.trim())!=null?r:"",o=(u=(a=t==null?void 0:t.referer)==null?void 0:a.trim())!=null?u:"",s=(d=t==null?void 0:t.now)!=null?d:new Date;return{sessionId:e,ephemeral:!1,utmParams:(l=t==null?void 0:t.utmParams)!=null?l:{},deviceClass:n?B(n):"desktop",trafficSource:o?G(o,t==null?void 0:t.appOrigin):"direct",referrerDomain:Q(o),timeOfDay:J(s),dayOfWeek:(f=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?f:"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 u;let o=(u=n.timeoutMs)!=null?u: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(d){}let r=await Promise.allSettled(e.map(async({id:d,variantIds:l})=>{let f=await F(`${n.baseUrl}/assign`,{method:"POST",headers:s,body:JSON.stringify({sessionId:t,componentId:d,variantIds:l})},o);if(!f.ok)return null;let h=await f.json();return{id:d,variantId:h.variantId}})),a={};for(let d of r)d.status==="fulfilled"&&d.value&&(a[d.value.id]=d.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(u){}try{let u=await F(`${n.baseUrl}/decide`,{method:"POST",headers:i,body:JSON.stringify({sessionId:t,sections:e.sections.map(d=>({id:d})),components:e.components})},o);return u.ok?await u.json():s}catch(u){return s}}var re="https://sentient-api.fly.dev/v1/events",q=null,H=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=H;H=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 u=new URLSearchParams({componentId:i});for(let f of r!=null?r:[])u.append("variantIds[]",f);let d=await fetch(`${t}/winner?${u.toString()}`,{headers:n});return d.ok?{variantId:(await d.json()).variantId,assignmentTtlMs:0}:r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}catch(u){return r!=null&&r[0]?{variantId:r[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};return H=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)=>o.assign(i,r,a),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}`},u=B((C=navigator.userAgent)!=null?C:""),d=typeof window!="undefined"?window.location.origin:void 0,l=G((M=document.referrer)!=null?M:"",d),f=($=e.sessionSegment)!=null?$:`${u}:${l}`;if(e.initialAssignments)for(let[g,m]of Object.entries(e.initialAssignments))s.set(g,f,{variantId:m,assignedAt:Date.now(),segment:f,confidence:1});let h=Promise.resolve(),S=o.getSessionId();if(S){let g=Q((w=document.referrer)!=null?w:""),m=_({sessionId:S,deviceClass:u,trafficSource:l,referrerDomain:g,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(g,m={}){let y=o.getSessionId();y&&h.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:y,name:g,metadata:m}),headers:a}).catch(()=>{})})},identify(g){let m=o.getSessionId();m&&h.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:m,userId:g,ephemeral:o.isEphemeral()}),headers:a}).catch(()=>{})})},track(g){let m=o.getSessionId();if(!m)return;let y=U(_({},g),{id:De(),sessionId:m,timestamp:Date.now(),timeInSession:Date.now()-n});i.push(y),e.debug&&console.log("[sentient] track",y)},getAssignment(g,m){return s.get(g,m)},async assign(g,m,y){let T=o.getSessionId();if(!T)return null;let I=s.get(g,f);if(I)return{variantId:I.variantId,assignmentTtlMs:0,content:I.content};await h;try{let E={sessionId:T,componentId:g,variantIds:m};y!==void 0&&(E.agentData=y);let D=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(E),headers:a});if(!D.ok)return null;let c=await D.json();return s.set(g,f,{variantId:c.variantId,assignedAt:Date.now(),segment:f,confidence:1,content:c.content}),c}catch(E){return null}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){i.destroy(),o.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(e.debug){let g=window;g.__sentient&&(g.__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};