@sentientui/core 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,7 @@
1
- export { a as agentUaList, d as deriveSessionSegment, c as detectDeviceClass, e as detectTimeOfDay, f as detectTrafficSource, m as matchedAgentToken, r as referrerDomainFromReferer, u as uaTokenMatch } from './session-meta-D5IgJuRW.cjs';
1
+ import { a as SlotDeclInput } from './session-meta-DU_3mY7U.cjs';
2
+ export { b as agentUaList, c as armOfResult, d as baselineResultFor, e as baselineSlots, g as deriveSessionSegment, h as detectDeviceClass, i as detectTimeOfDay, j as detectTrafficSource, m as matchedAgentToken, r as referrerDomainFromReferer, t as toWireSlot, u as uaTokenMatch } from './session-meta-DU_3mY7U.cjs';
3
+ import { SlotResult } from '@sentientui/policy';
4
+ export { SlotResult } from '@sentientui/policy';
2
5
 
3
6
  /** Manages anonymous session identity with cookie + localStorage layers. */
4
7
  type SessionConfig = {
@@ -132,6 +135,41 @@ type GraphClient = {
132
135
  destroy(): void;
133
136
  };
134
137
 
138
+ declare const PROD_KEYLESS_ERROR = "[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.";
139
+ declare const LOCAL_MODE_BANNER = "[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.";
140
+
141
+ /**
142
+ * Decision snapshot: the SPA / return-visit pre-paint source. Written after
143
+ * every successful decide; read by the inline pre-paint script (before any
144
+ * framework code runs) and by init() to seed slot/persona state.
145
+ */
146
+
147
+ declare const SNAPSHOT_STORAGE_KEY_PREFIX = "_snt_snap:";
148
+ type DecisionSnapshot = {
149
+ v: 1;
150
+ persona: string;
151
+ band: 'low' | 'medium' | 'high';
152
+ slots: Record<string, SlotResult>;
153
+ layoutOrder: string[] | null;
154
+ savedAt: number;
155
+ };
156
+ /** Returns null on missing, corrupt, or wrong-version data — never throws. */
157
+ declare function readSnapshot(apiKey: string): DecisionSnapshot | null;
158
+ /** Best-effort persist — storage failures are swallowed. */
159
+ declare function writeSnapshot(apiKey: string, snap: DecisionSnapshot): void;
160
+ /**
161
+ * Inline pre-paint script (Rung 1a): reads the snapshot and sets
162
+ * `data-sentient-persona` / `data-sentient-confidence` on <html> before
163
+ * first paint. Single-writer: it never overwrites attributes already set.
164
+ *
165
+ * Safety properties (pinned by tests):
166
+ * - apiKey goes through JSON.stringify, then '<' is escaped to <, so a
167
+ * hostile key can neither break the JS string nor terminate the <script>.
168
+ * - Built by string concatenation and contains no backticks, so the output
169
+ * survives being embedded in template-literal-based renderers.
170
+ */
171
+ declare function renderPrePaintScript(apiKey: string): string;
172
+
135
173
  type MicroSignalEmitter = (signalType: 'rage_click' | 'text_copy' | 'scroll_hesitation' | 'tab_loss', extra?: Record<string, unknown>) => void;
136
174
  type MicroSignalType = Parameters<MicroSignalEmitter>[0];
137
175
  /**
@@ -194,12 +232,50 @@ type SentientConfig = {
194
232
  * geo lookup.
195
233
  */
196
234
  country?: string;
235
+ /**
236
+ * Pre-seeded slot results from `preloadDecisions()` / `loadAdaptiveDecision()`
237
+ * (SSR). Seeds the local slot state so `getSlotResult()` agrees with the
238
+ * server-rendered markup on first paint.
239
+ */
240
+ initialSlots?: Record<string, SlotResult>;
241
+ /**
242
+ * Persona decided during SSR. Takes priority over the html-attribute
243
+ * adoption and the local snapshot.
244
+ */
245
+ initialPersona?: {
246
+ persona: string;
247
+ confidence: number;
248
+ };
249
+ /**
250
+ * Keyless local mode. 'auto' (default) simulates decisions on-device when no
251
+ * valid API key is configured — but only in development builds (the
252
+ * `development` export condition); production bundles physically exclude the
253
+ * engine. `true` forces the local engine regardless of key (escape hatch);
254
+ * `false` restores the silent keyless no-op.
255
+ */
256
+ localMode?: 'auto' | boolean;
197
257
  };
198
258
  type AssignResult = {
199
259
  variantId: string;
200
260
  assignmentTtlMs: number;
201
261
  content?: string;
202
262
  };
263
+
264
+ type DecideOutcome = {
265
+ layoutOrder: string[] | null;
266
+ assignments: Record<string, string>;
267
+ slots: Record<string, SlotResult>;
268
+ persona: string;
269
+ confidence: number;
270
+ };
271
+ type DecideInput = {
272
+ sections?: string[];
273
+ components?: Array<{
274
+ id: string;
275
+ variantIds?: string[];
276
+ }>;
277
+ slots?: SlotDeclInput[];
278
+ };
203
279
  type WeightEntry = {
204
280
  variantId: string;
205
281
  pulls: number;
@@ -232,10 +308,28 @@ type SentientClient = {
232
308
  getAssignment(componentId: string, segment: string): Assignment | null;
233
309
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
234
310
  assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
311
+ /**
312
+ * Single-roundtrip decision for layout sections, component variants, and
313
+ * adaptive slots. Awaits the session upsert (like `assign`) so the server
314
+ * never decides for a session row that doesn't exist yet. A response
315
+ * without a `slots` field means the server predates slots — every declared
316
+ * slot resolves to its baseline and no retry is made.
317
+ */
318
+ decide(input: DecideInput): Promise<DecideOutcome | null>;
319
+ /** Slot result served this session (decide result, SSR seed, snapshot, or failure baseline). Null when unknown. */
320
+ getSlotResult(slotId: string): SlotResult | null;
321
+ /** Current persona estimate. Band is always `confidenceBand(confidence)`. Null when nothing is known yet. */
322
+ getPersona(): {
323
+ persona: string;
324
+ confidence: number;
325
+ band: 'low' | 'medium' | 'high';
326
+ } | null;
235
327
  /** Fetches current bandit weights for all components in this project. Used by the provider to keep live-weight polling fresh. */
236
328
  fetchWeights(): Promise<ComponentWeightEntry[]>;
237
329
  getGraph(): GraphSnapshot;
238
330
  destroy(): void;
331
+ /** True when this client is the keyless local-mode client (dev only). */
332
+ readonly isLocal?: boolean;
239
333
  };
240
334
 
241
335
  /**
@@ -257,4 +351,4 @@ declare function grantConsent(apiKey?: string): void;
257
351
  */
258
352
  declare function init(config: SentientConfig): SentientClient;
259
353
 
260
- export { type AssignResult, type Assignment, type AssignmentCache, type ComponentGoalOptions, type ComponentWeightEntry, type ContentAddedEvent, type DOMScanner, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type MicroSignalEmitter, type MicroSignalType, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, type WeightEntry, attachMicroSignalDetectors, grantConsent, init, isDoNotTrackEnabled };
354
+ export { type AssignResult, type Assignment, type AssignmentCache, type ComponentGoalOptions, type ComponentWeightEntry, type ContentAddedEvent, type DOMScanner, type DecideInput, type DecideOutcome, type DecisionSnapshot, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, LOCAL_MODE_BANNER, type MicroSignalEmitter, type MicroSignalType, PROD_KEYLESS_ERROR, type PageNode, type QueueConfig, SNAPSHOT_STORAGE_KEY_PREFIX, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, SlotDeclInput, type WeightEntry, attachMicroSignalDetectors, grantConsent, init, isDoNotTrackEnabled, readSnapshot, renderPrePaintScript, writeSnapshot };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- export { a as agentUaList, d as deriveSessionSegment, c as detectDeviceClass, e as detectTimeOfDay, f as detectTrafficSource, m as matchedAgentToken, r as referrerDomainFromReferer, u as uaTokenMatch } from './session-meta-D5IgJuRW.js';
1
+ import { a as SlotDeclInput } from './session-meta-DU_3mY7U.js';
2
+ export { b as agentUaList, c as armOfResult, d as baselineResultFor, e as baselineSlots, g as deriveSessionSegment, h as detectDeviceClass, i as detectTimeOfDay, j as detectTrafficSource, m as matchedAgentToken, r as referrerDomainFromReferer, t as toWireSlot, u as uaTokenMatch } from './session-meta-DU_3mY7U.js';
3
+ import { SlotResult } from '@sentientui/policy';
4
+ export { SlotResult } from '@sentientui/policy';
2
5
 
3
6
  /** Manages anonymous session identity with cookie + localStorage layers. */
4
7
  type SessionConfig = {
@@ -132,6 +135,41 @@ type GraphClient = {
132
135
  destroy(): void;
133
136
  };
134
137
 
138
+ declare const PROD_KEYLESS_ERROR = "[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.";
139
+ declare const LOCAL_MODE_BANNER = "[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.";
140
+
141
+ /**
142
+ * Decision snapshot: the SPA / return-visit pre-paint source. Written after
143
+ * every successful decide; read by the inline pre-paint script (before any
144
+ * framework code runs) and by init() to seed slot/persona state.
145
+ */
146
+
147
+ declare const SNAPSHOT_STORAGE_KEY_PREFIX = "_snt_snap:";
148
+ type DecisionSnapshot = {
149
+ v: 1;
150
+ persona: string;
151
+ band: 'low' | 'medium' | 'high';
152
+ slots: Record<string, SlotResult>;
153
+ layoutOrder: string[] | null;
154
+ savedAt: number;
155
+ };
156
+ /** Returns null on missing, corrupt, or wrong-version data — never throws. */
157
+ declare function readSnapshot(apiKey: string): DecisionSnapshot | null;
158
+ /** Best-effort persist — storage failures are swallowed. */
159
+ declare function writeSnapshot(apiKey: string, snap: DecisionSnapshot): void;
160
+ /**
161
+ * Inline pre-paint script (Rung 1a): reads the snapshot and sets
162
+ * `data-sentient-persona` / `data-sentient-confidence` on <html> before
163
+ * first paint. Single-writer: it never overwrites attributes already set.
164
+ *
165
+ * Safety properties (pinned by tests):
166
+ * - apiKey goes through JSON.stringify, then '<' is escaped to <, so a
167
+ * hostile key can neither break the JS string nor terminate the <script>.
168
+ * - Built by string concatenation and contains no backticks, so the output
169
+ * survives being embedded in template-literal-based renderers.
170
+ */
171
+ declare function renderPrePaintScript(apiKey: string): string;
172
+
135
173
  type MicroSignalEmitter = (signalType: 'rage_click' | 'text_copy' | 'scroll_hesitation' | 'tab_loss', extra?: Record<string, unknown>) => void;
136
174
  type MicroSignalType = Parameters<MicroSignalEmitter>[0];
137
175
  /**
@@ -194,12 +232,50 @@ type SentientConfig = {
194
232
  * geo lookup.
195
233
  */
196
234
  country?: string;
235
+ /**
236
+ * Pre-seeded slot results from `preloadDecisions()` / `loadAdaptiveDecision()`
237
+ * (SSR). Seeds the local slot state so `getSlotResult()` agrees with the
238
+ * server-rendered markup on first paint.
239
+ */
240
+ initialSlots?: Record<string, SlotResult>;
241
+ /**
242
+ * Persona decided during SSR. Takes priority over the html-attribute
243
+ * adoption and the local snapshot.
244
+ */
245
+ initialPersona?: {
246
+ persona: string;
247
+ confidence: number;
248
+ };
249
+ /**
250
+ * Keyless local mode. 'auto' (default) simulates decisions on-device when no
251
+ * valid API key is configured — but only in development builds (the
252
+ * `development` export condition); production bundles physically exclude the
253
+ * engine. `true` forces the local engine regardless of key (escape hatch);
254
+ * `false` restores the silent keyless no-op.
255
+ */
256
+ localMode?: 'auto' | boolean;
197
257
  };
198
258
  type AssignResult = {
199
259
  variantId: string;
200
260
  assignmentTtlMs: number;
201
261
  content?: string;
202
262
  };
263
+
264
+ type DecideOutcome = {
265
+ layoutOrder: string[] | null;
266
+ assignments: Record<string, string>;
267
+ slots: Record<string, SlotResult>;
268
+ persona: string;
269
+ confidence: number;
270
+ };
271
+ type DecideInput = {
272
+ sections?: string[];
273
+ components?: Array<{
274
+ id: string;
275
+ variantIds?: string[];
276
+ }>;
277
+ slots?: SlotDeclInput[];
278
+ };
203
279
  type WeightEntry = {
204
280
  variantId: string;
205
281
  pulls: number;
@@ -232,10 +308,28 @@ type SentientClient = {
232
308
  getAssignment(componentId: string, segment: string): Assignment | null;
233
309
  /** Server-side variant assignment. Caches the result locally per (component, segment). */
234
310
  assign(componentId: string, variantIds?: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): Promise<AssignResult | null>;
311
+ /**
312
+ * Single-roundtrip decision for layout sections, component variants, and
313
+ * adaptive slots. Awaits the session upsert (like `assign`) so the server
314
+ * never decides for a session row that doesn't exist yet. A response
315
+ * without a `slots` field means the server predates slots — every declared
316
+ * slot resolves to its baseline and no retry is made.
317
+ */
318
+ decide(input: DecideInput): Promise<DecideOutcome | null>;
319
+ /** Slot result served this session (decide result, SSR seed, snapshot, or failure baseline). Null when unknown. */
320
+ getSlotResult(slotId: string): SlotResult | null;
321
+ /** Current persona estimate. Band is always `confidenceBand(confidence)`. Null when nothing is known yet. */
322
+ getPersona(): {
323
+ persona: string;
324
+ confidence: number;
325
+ band: 'low' | 'medium' | 'high';
326
+ } | null;
235
327
  /** Fetches current bandit weights for all components in this project. Used by the provider to keep live-weight polling fresh. */
236
328
  fetchWeights(): Promise<ComponentWeightEntry[]>;
237
329
  getGraph(): GraphSnapshot;
238
330
  destroy(): void;
331
+ /** True when this client is the keyless local-mode client (dev only). */
332
+ readonly isLocal?: boolean;
239
333
  };
240
334
 
241
335
  /**
@@ -257,4 +351,4 @@ declare function grantConsent(apiKey?: string): void;
257
351
  */
258
352
  declare function init(config: SentientConfig): SentientClient;
259
353
 
260
- export { type AssignResult, type Assignment, type AssignmentCache, type ComponentGoalOptions, type ComponentWeightEntry, type ContentAddedEvent, type DOMScanner, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, type MicroSignalEmitter, type MicroSignalType, type PageNode, type QueueConfig, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, type WeightEntry, attachMicroSignalDetectors, grantConsent, init, isDoNotTrackEnabled };
354
+ export { type AssignResult, type Assignment, type AssignmentCache, type ComponentGoalOptions, type ComponentWeightEntry, type ContentAddedEvent, type DOMScanner, type DecideInput, type DecideOutcome, type DecisionSnapshot, type EventQueue, type EventType, type GraphClient, type GraphConfig, type GraphSnapshot, LOCAL_MODE_BANNER, type MicroSignalEmitter, type MicroSignalType, PROD_KEYLESS_ERROR, type PageNode, type QueueConfig, SNAPSHOT_STORAGE_KEY_PREFIX, type ScanResult, type ScannedNode, type SentientClient, type SentientConfig, type SentientEvent, type SessionConfig, type SessionManager, SlotDeclInput, type WeightEntry, attachMicroSignalDetectors, grantConsent, init, isDoNotTrackEnabled, readSnapshot, renderPrePaintScript, writeSnapshot };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var Q=Object.defineProperty,fe=Object.defineProperties,me=Object.getOwnPropertyDescriptor,pe=Object.getOwnPropertyDescriptors,he=Object.getOwnPropertyNames,ee=Object.getOwnPropertySymbols;var ne=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var te=(e,t,n)=>t in e?Q(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,D=(e,t)=>{for(var n in t||(t={}))ne.call(t,n)&&te(e,n,t[n]);if(ee)for(var n of ee(t))ye.call(t,n)&&te(e,n,t[n]);return e},F=(e,t)=>fe(e,pe(t));var Se=(e,t)=>{for(var n in t)Q(e,n,{get:t[n],enumerable:!0})},ve=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of he(t))!ne.call(e,s)&&s!==n&&Q(e,s,{get:()=>t[s],enumerable:!(o=me(t,s))||o.enumerable});return e};var we=e=>ve(Q({},"__esModule",{value:!0}),e);var Be={};Se(Be,{agentUaList:()=>Y,attachMicroSignalDetectors:()=>ce,deriveSessionSegment:()=>ae,detectDeviceClass:()=>L,detectTimeOfDay:()=>P,detectTrafficSource:()=>M,grantConsent:()=>Ge,init:()=>ge,isDoNotTrackEnabled:()=>Z,matchedAgentToken:()=>q,referrerDomainFromReferer:()=>N,uaTokenMatch:()=>U});module.exports=we(Be);var xe="_snt_uid";var A="_snt_uid";function Ee(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(t){}let e=()=>Math.floor(Math.random()*4294967295).toString(16).padStart(8,"0");return`${e()}-${e()}-${e()}-${e()}`}function be(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function ke(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(o){}}function Ie(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 Te(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function Ce(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function De(e){try{sessionStorage.removeItem(e)}catch(t){}}function Ae(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 Oe(e){try{localStorage.removeItem(e)}catch(t){}}function Re(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var Ue={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function re(e){var g,m,p,S,x,y;if(typeof window=="undefined")return Ue;let t=(g=e==null?void 0:e.cookieName)!=null?g:xe,o=((m=e==null?void 0:e.cookieTTLDays)!=null?m:365)*24*60*60,s=(y=(x=(S=(p=be(t))!=null?p:Ie(A))!=null?S:Te(A))!=null?x:e==null?void 0:e.ssrSessionId)!=null?y:Ee();ke(t,s,o);let a=_e(A,s),c=Ae(t),r=a?!1:Ce(A,s),i=!a&&!c&&!r;return{getSessionId:()=>s,isEphemeral:()=>i,destroy:()=>{s=null,Re(t),Oe(A),De(A)}}}var Le={push:()=>{},flush:()=>{},destroy:()=>{}};function Me(e,t){try{let n=localStorage.getItem(t);if(!n)return[];let o=JSON.parse(n);return Array.isArray(o)?(localStorage.removeItem(t),o.slice(-e)):[]}catch(n){return[]}}function J(e,t,n){try{let s=[...(()=>{try{let a=localStorage.getItem(n);if(!a)return[];let c=JSON.parse(a);return Array.isArray(c)?c:[]}catch(a){return[]}})(),...e].slice(-t);localStorage.setItem(n,JSON.stringify(s))}catch(o){}}function ie(e){var h,I,b;if(typeof window=="undefined")return Le;let t=(h=e.flushIntervalMs)!=null?h:5e3,n=(I=e.maxBatchSize)!=null?I:20,o=(b=e.maxRetrySize)!=null?b:100,s=e.ingestUrl,a=e.apiKey,c=`_snt_retry_${a.slice(0,12)}`,r=[],i=new Set,g=[],m=l=>{for(let f of l)p.delete(f),!i.has(f)&&(i.add(f),g.push(f));for(;g.length>500;){let f=g.shift();f&&i.delete(f)}},p=new Set,S=l=>{i.has(l.id)||p.has(l.id)||(p.add(l.id),r.push(l))},x=Me(o,c);for(let l of x)S(l);let y=0,k=0,K=l=>{if(l.length===0)return;let f=JSON.stringify(l),v=l.map(w=>w.id),E;try{E=fetch(s,{method:"POST",keepalive:!0,body:f,headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`}})}catch(w){J(l,o,c);for(let j of v)p.delete(j);k++,y=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6));return}let T=w=>{if(w.ok||w.status>=400&&w.status<500&&w.status!==429){m(v),k=0,y=0;return}J(l,o,c);for(let j of v)p.delete(j);k++,y=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6))};E instanceof Promise?E.then(T).catch(()=>{J(l,o,c);for(let w of v)p.delete(w);k++,y=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6))}):T(E)},O=typeof TextEncoder!="undefined"?new TextEncoder:null,B=l=>O?O.encode(l).length:l.length,W=l=>{let f=[],v=2;for(let E of l){let T=B(JSON.stringify(E))+1;if(f.length>0&&v+T>57344||f.length>=n)break;f.push(E),v+=T}return f},_=()=>{try{if(Date.now()<y)return;for(;r.length>0;){let l=r.filter(v=>!i.has(v.id));if(r.length=0,l.length===0)break;let f=W(l);if(f.length===0)break;f.length<l.length&&r.push(...l.slice(f.length)),K(f)}}catch(l){}},R=!0,C=null;C=setInterval(()=>{R&&_()},t);let d=()=>{document.visibilityState==="hidden"&&_()},u=()=>{_()};return document.addEventListener("visibilitychange",d),window.addEventListener("beforeunload",u),{push(l){S(l),r.length>=n&&_()},flush:_,destroy(){R=!1,C!==null&&(clearInterval(C),C=null),document.removeEventListener("visibilitychange",d),window.removeEventListener("beforeunload",u),_()}}}var V="_snt_asgn_";function z(e,t){return`${e}:${t}`}function Ne(e,t){return`${V}${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function se(e){let t=e.slice(V.length),n=t.indexOf(":");if(n<0)return null;try{return{componentId:decodeURIComponent(t.slice(0,n)),segment:decodeURIComponent(t.slice(n+1))}}catch(o){return null}}function H(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(V)&&e.push(n)}return e}catch(e){return[]}}function oe(e=18e5){let t=new Map,n=s=>s.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let s of H())try{let a=localStorage.getItem(s);if(!a)continue;let c=JSON.parse(a);if(n(c)){localStorage.removeItem(s);continue}let r=se(s);if(!r)continue;t.set(z(r.componentId,r.segment),c)}catch(a){}})(),{get(s,a){let c=t.get(z(s,a));return c?n(c)?(t.delete(z(s,a)),null):c:null},set(s,a,c){let r=z(s,a);t.set(r,c);try{localStorage.setItem(Ne(s,a),JSON.stringify(c))}catch(i){}},invalidate(s){let a=`${s}:`;for(let c of[...t.keys()])c.startsWith(a)&&t.delete(c);for(let c of H()){let r=se(c);if((r==null?void 0:r.componentId)===s)try{localStorage.removeItem(c)}catch(i){}}},clear(){t.clear();for(let s of H())try{localStorage.removeItem(s)}catch(a){}}}}var Y=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function U(e){return q(e)!==null}function q(e){var n;if(!e)return null;let t=e.toLowerCase();return(n=Y.find(o=>t.includes(o.toLowerCase())))!=null?n:null}function L(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(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 N(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 ae(e){let t=Pe("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function Pe(e,t){var a,c,r,i,g,m,p;let n=(c=(a=t==null?void 0:t.userAgent)==null?void 0:a.trim())!=null?c:"",o=(i=(r=t==null?void 0:t.referer)==null?void 0:r.trim())!=null?i:"",s=(g=t==null?void 0:t.now)!=null?g:new Date;return{sessionId:e,ephemeral:!1,utmParams:(m=t==null?void 0:t.utmParams)!=null?m:{},deviceClass:n?L(n):"desktop",trafficSource:o?M(o,t==null?void 0:t.appOrigin):"direct",referrerDomain:N(o),timeOfDay:P(s),dayOfWeek:(p=["sun","mon","tue","wed","thu","fri","sat"][s.getDay()])!=null?p:"sun",automation:(t==null?void 0:t.webdriver)===!0||U(n)}}function ce(e,t,n){var s;let o=[];{let r=!1,i=[],g=()=>{if(r)return;let m=Date.now();for(i.push(m);i.length>0&&m-i[0]>500;)i.shift();i.length>=3&&(r=!0,e("rage_click"))};t.addEventListener("click",g),o.push(()=>t.removeEventListener("click",g))}{let a=!1,c=r=>{if(a||!(r.target instanceof Node)||!t.contains(r.target)&&t!==r.target)return;a=!0;let i=typeof window!="undefined"?window.getSelection():null,g=i?i.toString().length:0;e("text_copy",{selectionLength:g})};document.addEventListener("copy",c),o.push(()=>document.removeEventListener("copy",c))}{let a=!1,c=!1,r=null,i=()=>{r!==null&&(clearTimeout(r),r=null)},g=()=>{a||!c||(i(),r=setTimeout(()=>{!a&&c&&(a=!0,e("scroll_hesitation"))},3e3))},m=()=>{i(),g()},p=x=>{for(let y of x)c=y.intersectionRatio>.3,c?g():i()};typeof process!="undefined"&&((s=process.env)==null?void 0:s.NODE_ENV)!=="production"&&(window.__lastIOCallback=p);let S=new IntersectionObserver(p,{threshold:[.3]});S.observe(t),window.addEventListener("scroll",m,{passive:!0}),o.push(()=>{S.disconnect(),window.removeEventListener("scroll",m),i()})}{let a=!1,c=n!=null?n:Date.now(),r=()=>{if(a||document.visibilityState!=="hidden")return;let i=Date.now()-c;i<15e3&&(a=!0,e("tab_loss",{timeOnPage:i}))};document.addEventListener("visibilitychange",r),o.push(()=>document.removeEventListener("visibilitychange",r))}return()=>{for(let a of o)a()}}var le="https://api.sentient-ui.com/v1/events",G=new Map,de=null;function X(){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:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function $e(){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 ue(e){return e.replace(/\/events\/?$/,"")}function Z(){return[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(t=>t==="1"||t==="yes")}function Ge(e){if(typeof window=="undefined")return;let t=e!=null?e:de;if(!t){console.warn("[sentient] grantConsent() called before init()");return}let n=G.get(t);if(!n){console.warn("[sentient] grantConsent() called before init()");return}let{config:o,upgrade:s}=n;if(!s||o.respectDoNotTrack!==!1&&Z())return;let a=ge(F(D({},o),{consent:!0}));s(a),G.set(t,{config:F(D({},o),{consent:!0}),upgrade:null})}function Ke(e){var c;let t=ue((c=e.ingestUrl)!=null?c:le),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},o={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),async assign(r,i,g){try{let m=new URLSearchParams({componentId:r});for(let x of i!=null?i:[])m.append("variantIds[]",x);let p=await fetch(`${t}/winner?${m.toString()}`,{headers:n});return p.ok?{variantId:(await p.json()).variantId,assignmentTtlMs:0}:i!=null&&i[0]?{variantId:i[0],assignmentTtlMs:0}:null}catch(m){return i!=null&&i[0]?{variantId:i[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}},s={track:r=>o.track(r),goal:(r,i,g,m)=>o.goal(r,i,g,m),componentGoal:(r,i,g)=>o.componentGoal(r,i,g),identify:r=>o.identify(r),getAssignment:(r,i)=>o.getAssignment(r,i),assign:(r,i,g,m)=>o.assign(r,i,g,m),fetchWeights:()=>o.fetchWeights(),getGraph:()=>o.getGraph(),destroy:()=>o.destroy()};function a(r){o=r}return{proxy:s,setInner:a}}function ge(e){var O,B,W,_,R,C;if(typeof window=="undefined")return $;de=e.apiKey;let t=e.respectDoNotTrack!==!1&&Z();if(e.consent===!1||t){if(e.preConsentBehavior==="statistical_winner"){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."),$;let{proxy:d,setInner:u}=Ke(e);return G.set(e.apiKey,{config:e,upgrade:t?null:u}),d}return G.set(e.apiKey,{config:e,upgrade:null}),$}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 n=(O=e.ingestUrl)!=null?O:le,o=Date.now(),s=re({ssrSessionId:e.ssrSessionId}),a=oe(),c=ie({ingestUrl:n,apiKey:e.apiKey}),r=ue(n),i={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},g=L((B=navigator.userAgent)!=null?B:""),m=typeof window!="undefined"?window.location.origin:void 0,p=M((W=document.referrer)!=null?W:"",m),S=(_=e.sessionSegment)!=null?_:`${g}:${p}`,x=new Map;if(e.initialAssignments)for(let[d,u]of Object.entries(e.initialAssignments))a.set(d,S,{variantId:u,assignedAt:Date.now(),segment:S,confidence:1});let y=Promise.resolve(),k=s.getSessionId();if(k){let d=N((R=document.referrer)!=null?R:""),u=D(D({sessionId:k,deviceClass:g,trafficSource:p,referrerDomain:d,utmParams:$e(),timeOfDay:P(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:s.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||U((C=navigator.userAgent)!=null?C:"")},e.userId?{userId:e.userId}:{}),e.country?{country:e.country}:{});try{y=fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(u),headers:i}).then(h=>{h.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing")}).catch(()=>{})}catch(h){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:c});let K={goal(d,u={},h=1,I=0){let b=s.getSessionId();if(!b)return;let l=X();y.then(()=>{fetch(`${r}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:b,name:d,metadata:u,weight:h,stepIndex:I,goalId:l}),headers:i}).catch(()=>{})})},componentGoal(d,u,h){var f,v;let I=s.getSessionId();if(!I)return;let b=a.get(d,S);if(!b){e.debug&&console.warn(`[sentient] componentGoal("${d}"): no assignment yet \u2014 render its <Adaptive> or call assign() before recording a goal.`);return}let l={id:X(),sessionId:I,projectId:e.apiKey,componentId:d,variantId:b.variantId,eventType:"goal_achieved",goalType:u,payload:D({reward:(f=h==null?void 0:h.reward)!=null?f:1},(v=h==null?void 0:h.metadata)!=null?v:{}),timestamp:Date.now(),timeInSession:Date.now()-o};e.debug&&console.log("[sentient] componentGoal",l),y.then(()=>c.push(l))},identify(d){let u=s.getSessionId();u&&y.then(()=>{fetch(`${r}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:u,userId:d,ephemeral:s.isEphemeral()}),headers:i}).catch(()=>{})})},track(d){let u=s.getSessionId();if(!u)return;let h=F(D({},d),{id:X(),sessionId:u,timestamp:Date.now(),timeInSession:Date.now()-o});e.debug&&console.log("[sentient] track",h),y.then(()=>c.push(h))},getAssignment(d,u){return a.get(d,u)},async assign(d,u,h,I){let b=s.getSessionId();if(!b)return null;let l=a.get(d,S);if(l&&(u!=null&&u.length||l.content!==void 0))return{variantId:l.variantId,assignmentTtlMs:0,content:l.content};let f=x.get(d);if(f)return f;let v=(async()=>{await y;try{let E={sessionId:b,componentId:d,variantIds:u};I!==void 0?E.agentDataByVariant=I:h!==void 0&&(E.agentData=h);let T=await fetch(`${r}/assign`,{method:"POST",body:JSON.stringify(E),headers:i});if(!T.ok)return null;let w=await T.json();return a.set(d,S,{variantId:w.variantId,assignedAt:Date.now(),segment:S,confidence:1,content:w.content}),w}catch(E){return null}finally{x.delete(d)}})();return x.set(d,v),v},async fetchWeights(){var d;try{let u=await fetch(`${r}/weights`,{headers:i});return u.ok?(d=(await u.json()).components)!=null?d:[]:[]}catch(u){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){c.destroy(),s.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(G.set(e.apiKey,{config:e,upgrade:null}),e.debug){let d=window;d.__sentient&&(d.__sentient.client=K)}return K}0&&(module.exports={agentUaList,attachMicroSignalDetectors,deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,isDoNotTrackEnabled,matchedAgentToken,referrerDomainFromReferer,uaTokenMatch});
1
+ "use strict";var Qe=Object.create;var X=Object.defineProperty,Ye=Object.defineProperties,ze=Object.getOwnPropertyDescriptor,Ve=Object.getOwnPropertyDescriptors,He=Object.getOwnPropertyNames,Ae=Object.getOwnPropertySymbols,qe=Object.getPrototypeOf,Ce=Object.prototype.hasOwnProperty,Xe=Object.prototype.propertyIsEnumerable;var Oe=(e,t,n)=>t in e?X(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,w=(e,t)=>{for(var n in t||(t={}))Ce.call(t,n)&&Oe(e,n,t[n]);if(Ae)for(var n of Ae(t))Xe.call(t,n)&&Oe(e,n,t[n]);return e},K=(e,t)=>Ye(e,Ve(t));var Ze=(e,t)=>{for(var n in t)X(e,n,{get:t[n],enumerable:!0})},Te=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let d of He(t))!Ce.call(e,d)&&d!==n&&X(e,d,{get:()=>t[d],enumerable:!(i=ze(t,d))||i.enumerable});return e};var et=(e,t,n)=>(n=e!=null?Qe(qe(e)):{},Te(t||!e||!e.__esModule?X(n,"default",{value:e,enumerable:!0}):n,e)),tt=e=>Te(X({},"__esModule",{value:!0}),e);var It={};Ze(It,{LOCAL_MODE_BANNER:()=>Ee,PROD_KEYLESS_ERROR:()=>pe,SNAPSHOT_STORAGE_KEY_PREFIX:()=>se,agentUaList:()=>we,armOfResult:()=>de,attachMicroSignalDetectors:()=>$e,baselineResultFor:()=>$,baselineSlots:()=>Ue,deriveSessionSegment:()=>Me,detectDeviceClass:()=>ee,detectTimeOfDay:()=>re,detectTrafficSource:()=>te,grantConsent:()=>Et,init:()=>Je,isDoNotTrackEnabled:()=>_e,matchedAgentToken:()=>be,readSnapshot:()=>ue,referrerDomainFromReferer:()=>ne,renderPrePaintScript:()=>Ke,toWireSlot:()=>oe,uaTokenMatch:()=>Z,writeSnapshot:()=>W});module.exports=tt(It);var nt="_snt_uid";var G="_snt_uid";function rt(){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 ot(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function st(e,t,n){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${n}; SameSite=strict; path=/`}catch(i){}}function it(e){try{return localStorage.getItem(e)}catch(t){return null}}function at(e,t){try{return localStorage.setItem(e,t),!0}catch(n){return!1}}function lt(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function ct(e,t){try{return sessionStorage.setItem(e,t),!0}catch(n){return!1}}function dt(e){try{sessionStorage.removeItem(e)}catch(t){}}function ut(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 gt(e){try{localStorage.removeItem(e)}catch(t){}}function ft(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var pt={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function le(e){var l,g,m,S,h,b;if(typeof window=="undefined")return pt;let t=(l=e==null?void 0:e.cookieName)!=null?l:nt,i=((g=e==null?void 0:e.cookieTTLDays)!=null?g:365)*24*60*60,d=(b=(h=(S=(m=ot(t))!=null?m:it(G))!=null?S:lt(G))!=null?h:e==null?void 0:e.ssrSessionId)!=null?b:rt();st(t,d,i);let r=at(G,d),c=ut(t),s=r?!1:ct(G,d),o=!r&&!c&&!s;return{getSessionId:()=>d,isEphemeral:()=>o,destroy:()=>{d=null,ft(t),gt(G),dt(G)}}}var mt={push:()=>{},flush:()=>{},destroy:()=>{}};function yt(e,t){try{let n=localStorage.getItem(t);if(!n)return[];let i=JSON.parse(n);return Array.isArray(i)?(localStorage.removeItem(t),i.slice(-e)):[]}catch(n){return[]}}function he(e,t,n){try{let d=[...(()=>{try{let r=localStorage.getItem(n);if(!r)return[];let c=JSON.parse(r);return Array.isArray(c)?c:[]}catch(r){return[]}})(),...e].slice(-t);localStorage.setItem(n,JSON.stringify(d))}catch(i){}}function Pe(e){var z,V,H;if(typeof window=="undefined")return mt;let t=(z=e.flushIntervalMs)!=null?z:5e3,n=(V=e.maxBatchSize)!=null?V:20,i=(H=e.maxRetrySize)!=null?H:100,d=e.ingestUrl,r=e.apiKey,c=`_snt_retry_${r.slice(0,12)}`,s=[],o=new Set,l=[],g=f=>{for(let y of f)m.delete(y),!o.has(y)&&(o.add(y),l.push(y));for(;l.length>500;){let y=l.shift();y&&o.delete(y)}},m=new Set,S=f=>{o.has(f.id)||m.has(f.id)||(m.add(f.id),s.push(f))},h=yt(i,c);for(let f of h)S(f);let b=0,v=0,E=f=>{if(f.length===0)return;let y=JSON.stringify(f),_=f.map(u=>u.id),R;try{R=fetch(d,{method:"POST",keepalive:!0,body:y,headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`}})}catch(u){he(f,i,c);for(let p of _)m.delete(p);v++,b=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6));return}let a=u=>{if(u.ok||u.status>=400&&u.status<500&&u.status!==429){g(_),v=0,b=0;return}he(f,i,c);for(let p of _)m.delete(p);v++,b=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))};R instanceof Promise?R.then(a).catch(()=>{he(f,i,c);for(let u of _)m.delete(u);v++,b=Date.now()+Math.min(6e4,1e3*2**Math.min(v,6))}):a(R)},F=typeof TextEncoder!="undefined"?new TextEncoder:null,L=f=>F?F.encode(f).length:f.length,ae=f=>{let y=[],_=2;for(let R of f){let a=L(JSON.stringify(R))+1;if(y.length>0&&_+a>57344||y.length>=n)break;y.push(R),_+=a}return y},x=()=>{try{if(Date.now()<b)return;for(;s.length>0;){let f=s.filter(_=>!o.has(_.id));if(s.length=0,f.length===0)break;let y=ae(f);if(y.length===0)break;y.length<f.length&&s.push(...f.slice(y.length)),E(y)}}catch(f){}},J=!0,N=null;N=setInterval(()=>{J&&x()},t);let Q=()=>{document.visibilityState==="hidden"&&x()},Y=()=>{x()};return document.addEventListener("visibilitychange",Q),window.addEventListener("beforeunload",Y),{push(f){S(f),s.length>=n&&x()},flush:x,destroy(){J=!1,N!==null&&(clearInterval(N),N=null),document.removeEventListener("visibilitychange",Q),window.removeEventListener("beforeunload",Y),x()}}}var ve="_snt_asgn_";function ce(e,t){return`${e}:${t}`}function ht(e,t){return`${ve}${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function Le(e){let t=e.slice(ve.length),n=t.indexOf(":");if(n<0)return null;try{return{componentId:decodeURIComponent(t.slice(0,n)),segment:decodeURIComponent(t.slice(n+1))}}catch(i){return null}}function Se(){try{let e=[];for(let t=0;t<localStorage.length;t++){let n=localStorage.key(t);n!=null&&n.startsWith(ve)&&e.push(n)}return e}catch(e){return[]}}function Ne(e=18e5){let t=new Map,n=d=>d.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let d of Se())try{let r=localStorage.getItem(d);if(!r)continue;let c=JSON.parse(r);if(n(c)){localStorage.removeItem(d);continue}let s=Le(d);if(!s)continue;t.set(ce(s.componentId,s.segment),c)}catch(r){}})(),{get(d,r){let c=t.get(ce(d,r));return c?n(c)?(t.delete(ce(d,r)),null):c:null},set(d,r,c){let s=ce(d,r);t.set(s,c);try{localStorage.setItem(ht(d,r),JSON.stringify(c))}catch(o){}},invalidate(d){let r=`${d}:`;for(let c of[...t.keys()])c.startsWith(r)&&t.delete(c);for(let c of Se()){let s=Le(c);if((s==null?void 0:s.componentId)===d)try{localStorage.removeItem(c)}catch(o){}}},clear(){t.clear();for(let d of Se())try{localStorage.removeItem(d)}catch(r){}}}}var we=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function Z(e){return be(e)!==null}function be(e){var n;if(!e)return null;let t=e.toLowerCase();return(n=we.find(i=>t.includes(i.toLowerCase())))!=null?n:null}function ee(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 te(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(d){}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 ne(e){if(!e)return null;try{return new URL(e).hostname}catch(t){return null}}function re(e){let t=e.getHours();return t<6?"night":t<12?"morning":t<18?"afternoon":"evening"}function Me(e){let t=St("__segment__",e);return`${t.deviceClass}:${t.trafficSource}`}function St(e,t){var r,c,s,o,l,g,m;let n=(c=(r=t==null?void 0:t.userAgent)==null?void 0:r.trim())!=null?c:"",i=(o=(s=t==null?void 0:t.referer)==null?void 0:s.trim())!=null?o:"",d=(l=t==null?void 0:t.now)!=null?l:new Date;return{sessionId:e,ephemeral:!1,utmParams:(g=t==null?void 0:t.utmParams)!=null?g:{},deviceClass:n?ee(n):"desktop",trafficSource:i?te(i,t==null?void 0:t.appOrigin):"direct",referrerDomain:ne(i),timeOfDay:re(d),dayOfWeek:(m=["sun","mon","tue","wed","thu","fri","sat"][d.getDay()])!=null?m:"sun",automation:(t==null?void 0:t.webdriver)===!0||Z(n)}}var B=require("@sentientui/policy");function oe(e){return w(w(w({id:e.id},e.arms?{arms:[...e.arms]}:{}),e.dims?{dims:Object.fromEntries(Object.entries(e.dims).map(([t,n])=>[t,[...n]]))}:{}),e.baseline!==void 0?{baseline:e.baseline}:{})}function $(e){let t=oe(e);return(0,B.slotResultFor)(t,(0,B.slotBaselineArm)(t))}function Ue(e){let t={};for(let n of e)t[n.id]=$(n);return t}function de(e){return typeof e=="string"?e:(0,B.canonicalArm)(e)}var se="_snt_snap:",vt=["low","medium","high"];function ue(e){try{let t=localStorage.getItem(se+e);if(!t)return null;let n=JSON.parse(t);return!n||typeof n!="object"||n.v!==1||typeof n.persona!="string"||typeof n.band!="string"||!vt.includes(n.band)||typeof n.slots!="object"||n.slots===null||Array.isArray(n.slots)||!(n.layoutOrder===null||Array.isArray(n.layoutOrder))||typeof n.savedAt!="number"?null:n}catch(t){return null}}function W(e,t){try{localStorage.setItem(se+e,JSON.stringify(t))}catch(n){}}function Ke(e){return"(function(){try{var r=localStorage.getItem("+JSON.stringify(se+e).replace(/</g,"\\u003c")+');if(!r)return;var s=JSON.parse(r);if(!s||s.v!==1||typeof s.persona!=="string"||typeof s.band!=="string")return;var d=document.documentElement;if(d.hasAttribute("data-sentient-persona"))return;d.setAttribute("data-sentient-persona",s.persona);d.setAttribute("data-sentient-confidence",s.band);}catch(e){}})();'}var Ie=require("@sentientui/policy");var fe=require("@sentientui/policy");var pe="[sentient] No API key configured \u2014 nothing is being learned. Set NEXT_PUBLIC_SENTIENT_API_KEY or pass localMode: true for local development.",Ee="[sentient] Local mode \u2014 decisions are simulated on-device and nothing is sent over the network. Add an API key to learn from real traffic.",Ge=!1,ge=!1;function wt(){var e;try{return(e=new URLSearchParams(window.location.search).get("sentient_persona"))!=null?e:void 0}catch(t){return}}function Be(e){var s;let t=le({ssrSessionId:e.ssrSessionId}),n=(s=t.getSessionId())!=null?s:"local",i=wt(),d=import("@sentientui/core/local").then(o=>{let l=o;return l.LOCAL_ENGINE_AVAILABLE?(Ge||(Ge=!0,console.info(Ee)),l):(ge||(ge=!0,console.error(pe)),null)}).catch(()=>(ge||(ge=!0,console.error(pe)),null)),r=null;function c(o){let l=document.documentElement;l.dataset.sentientPersona===void 0&&(l.dataset.sentientPersona=o.persona,l.dataset.sentientConfidence=(0,fe.confidenceBand)(o.confidence))}return{isLocal:!0,async decide(o){var m,S,h;let l=await d;if(!l)return null;let g=l.createLocalEngine({sessionId:n,forcedPersona:i}).decide(o);return r=K(w({},g),{layoutOrder:(S=(m=g.layoutOrder)!=null?m:r==null?void 0:r.layoutOrder)!=null?S:null,slots:w(w({},(h=r==null?void 0:r.slots)!=null?h:{}),g.slots)}),W(e.apiKey||"local",{v:1,persona:r.persona,band:(0,fe.confidenceBand)(r.confidence),slots:r.slots,layoutOrder:r.layoutOrder,savedAt:Date.now()}),c(g),g},getSlotResult(o){var l,g,m;return(m=(g=r==null?void 0:r.slots[o])!=null?g:(l=e.initialSlots)==null?void 0:l[o])!=null?m:null},getPersona(){return r?{persona:r.persona,confidence:r.confidence,band:(0,fe.confidenceBand)(r.confidence)}:null},async assign(o,l){var S;let g=await d;return!g||!l||l.length===0?l!=null&&l[0]?{variantId:l[0],assignmentTtlMs:0}:null:{variantId:(S=g.createLocalEngine({sessionId:n,forcedPersona:i}).decide({components:[{id:o,variantIds:l}]}).assignments[o])!=null?S:l[0],assignmentTtlMs:0}},track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>t.destroy()}}function $e(e,t,n){var d;let i=[];{let s=!1,o=[],l=()=>{if(s)return;let g=Date.now();for(o.push(g);o.length>0&&g-o[0]>500;)o.shift();o.length>=3&&(s=!0,e("rage_click"))};t.addEventListener("click",l),i.push(()=>t.removeEventListener("click",l))}{let r=!1,c=s=>{if(r||!(s.target instanceof Node)||!t.contains(s.target)&&t!==s.target)return;r=!0;let o=typeof window!="undefined"?window.getSelection():null,l=o?o.toString().length:0;e("text_copy",{selectionLength:l})};document.addEventListener("copy",c),i.push(()=>document.removeEventListener("copy",c))}{let r=!1,c=!1,s=null,o=()=>{s!==null&&(clearTimeout(s),s=null)},l=()=>{r||!c||(o(),s=setTimeout(()=>{!r&&c&&(r=!0,e("scroll_hesitation"))},3e3))},g=()=>{o(),l()},m=h=>{for(let b of h)c=b.intersectionRatio>.3,c?l():o()};typeof process!="undefined"&&((d=process.env)==null?void 0:d.NODE_ENV)!=="production"&&(window.__lastIOCallback=m);let S=new IntersectionObserver(m,{threshold:[.3]});S.observe(t),window.addEventListener("scroll",g,{passive:!0}),i.push(()=>{S.disconnect(),window.removeEventListener("scroll",g),o()})}{let r=!1,c=n!=null?n:Date.now(),s=()=>{if(r||document.visibilityState!=="hidden")return;let o=Date.now()-c;o<15e3&&(r=!0,e("tab_loss",{timeOnPage:o}))};document.addEventListener("visibilitychange",s),i.push(()=>document.removeEventListener("visibilitychange",s))}return()=>{for(let r of i)r()}}var We="https://api.sentient-ui.com/v1/events",j=new Map,je=null;function xe(){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 ie={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function bt(){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 Fe(e){return e.replace(/\/events\/?$/,"")}function _e(){return[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(t=>t==="1"||t==="yes")}function Et(e){if(typeof window=="undefined")return;let t=e!=null?e:je;if(!t){console.warn("[sentient] grantConsent() called before init()");return}let n=j.get(t);if(!n){console.warn("[sentient] grantConsent() called before init()");return}let{config:i,upgrade:d}=n;if(!d||i.respectDoNotTrack!==!1&&_e())return;let r=Je(K(w({},i),{consent:!0}));d(r),j.set(t,{config:K(w({},i),{consent:!0}),upgrade:null})}function xt(e){var c;let t=Fe((c=e.ingestUrl)!=null?c:We),n={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},i={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),async assign(s,o,l){try{let g=new URLSearchParams({componentId:s});for(let h of o!=null?o:[])g.append("variantIds[]",h);let m=await fetch(`${t}/winner?${g.toString()}`,{headers:n});return m.ok?{variantId:(await m.json()).variantId,assignmentTtlMs:0}:o!=null&&o[0]?{variantId:o[0],assignmentTtlMs:0}:null}catch(g){return o!=null&&o[0]?{variantId:o[0],assignmentTtlMs:0}:null}},decide:()=>Promise.resolve(null),getSlotResult:()=>null,getPersona:()=>null,getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}},d={track:s=>i.track(s),goal:(s,o,l,g)=>i.goal(s,o,l,g),componentGoal:(s,o,l)=>i.componentGoal(s,o,l),identify:s=>i.identify(s),getAssignment:(s,o)=>i.getAssignment(s,o),assign:(s,o,l,g)=>i.assign(s,o,l,g),decide:s=>i.decide(s),getSlotResult:s=>i.getSlotResult(s),getPersona:()=>i.getPersona(),fetchWeights:()=>i.fetchWeights(),getGraph:()=>i.getGraph(),destroy:()=>i.destroy()};function r(s){i=s}return{proxy:d,setInner:r}}function Je(e){var Q,Y,z,V,H,f,y,_,R;if(typeof window=="undefined")return ie;je=e.apiKey;let t=typeof e.apiKey=="string"&&e.apiKey.startsWith("pk_");if(e.localMode===!0||!t&&e.localMode!==!1)return j.set(e.apiKey||"local",{config:e,upgrade:null}),Be(e);let n=e.respectDoNotTrack!==!1&&_e();if(e.consent===!1||n){if(e.preConsentBehavior==="statistical_winner"){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."),ie;let{proxy:a,setInner:u}=xt(e);return j.set(e.apiKey,{config:e,upgrade:n?null:u}),a}return j.set(e.apiKey,{config:e,upgrade:null}),ie}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."),ie;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),ie;let i=(Q=e.ingestUrl)!=null?Q:We,d=Date.now(),r=le({ssrSessionId:e.ssrSessionId}),c=Ne(),s=Pe({ingestUrl:i,apiKey:e.apiKey}),o=Fe(i),l={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},g=ee((Y=navigator.userAgent)!=null?Y:""),m=typeof window!="undefined"?window.location.origin:void 0,S=te((z=document.referrer)!=null?z:"",m),h=(V=e.sessionSegment)!=null?V:`${g}:${S}`,b=new Map,v=new Map,E=null,F=a=>{for(let u of a)v.has(u.id)||v.set(u.id,$(u))};if(e.initialSlots)for(let[a,u]of Object.entries(e.initialSlots))v.set(a,u);let L=ue(e.apiKey);if(L)for(let[a,u]of Object.entries(L.slots))v.has(a)||v.set(a,u);let ae={low:.15,medium:.5,high:.85};if(e.initialPersona)E=w({},e.initialPersona);else{let a=document.documentElement.dataset;a.sentientPersona?E={persona:a.sentientPersona,confidence:(f=ae[(H=a.sentientConfidence)!=null?H:"low"])!=null?f:.15}:L&&(E={persona:L.persona,confidence:(y=ae[L.band])!=null?y:.15})}if(e.initialAssignments)for(let[a,u]of Object.entries(e.initialAssignments))c.set(a,h,{variantId:u,assignedAt:Date.now(),segment:h,confidence:1});let x=Promise.resolve(),J=r.getSessionId();if(J){let a=ne((_=document.referrer)!=null?_:""),u=w(w({sessionId:J,deviceClass:g,trafficSource:S,referrerDomain:a,utmParams:bt(),timeOfDay:re(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:r.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||Z((R=navigator.userAgent)!=null?R:"")},e.userId?{userId:e.userId}:{}),e.country?{country:e.country}:{});try{x=fetch(`${o}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(u),headers:l}).then(p=>{p.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing")}).catch(()=>{})}catch(p){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:s});let N={goal(a,u={},p=1,D=0){let I=r.getSessionId();if(!I)return;let k=xe();x.then(()=>{fetch(`${o}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:I,name:a,metadata:u,weight:p,stepIndex:D,goalId:k}),headers:l}).catch(()=>{})})},componentGoal(a,u,p){var A,P,O;let D=r.getSessionId();if(!D)return;let I=c.get(a,h),k=I?null:(A=v.get(a))!=null?A:null;if(!I&&k===null){e.debug&&console.warn(`[sentient] componentGoal("${a}"): no assignment or slot decision yet \u2014 render its <Adaptive>/adaptive hook or call assign()/decide() before recording a goal.`);return}let M=I?I.variantId:de(k),T={id:xe(),sessionId:D,projectId:e.apiKey,componentId:a,variantId:M,eventType:"goal_achieved",goalType:u,payload:w({reward:(P=p==null?void 0:p.reward)!=null?P:1},(O=p==null?void 0:p.metadata)!=null?O:{}),timestamp:Date.now(),timeInSession:Date.now()-d};e.debug&&console.log("[sentient] componentGoal",T),x.then(()=>s.push(T))},identify(a){let u=r.getSessionId();u&&x.then(()=>{fetch(`${o}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:u,userId:a,ephemeral:r.isEphemeral()}),headers:l}).catch(()=>{})})},track(a){let u=r.getSessionId();if(!u)return;let p=K(w({},a),{id:xe(),sessionId:u,timestamp:Date.now(),timeInSession:Date.now()-d});e.debug&&console.log("[sentient] track",p),x.then(()=>s.push(p))},getAssignment(a,u){return c.get(a,u)},async assign(a,u,p,D){let I=r.getSessionId();if(!I)return null;let k=c.get(a,h);if(k&&(u!=null&&u.length||k.content!==void 0))return{variantId:k.variantId,assignmentTtlMs:0,content:k.content};let M=b.get(a);if(M)return M;let T=(async()=>{await x;try{let A={sessionId:I,componentId:a,variantIds:u};D!==void 0?A.agentDataByVariant=D:p!==void 0&&(A.agentData=p);let P=await fetch(`${o}/assign`,{method:"POST",body:JSON.stringify(A),headers:l});if(!P.ok)return null;let O=await P.json();return c.set(a,h,{variantId:O.variantId,assignedAt:Date.now(),segment:h,confidence:1,content:O.content}),O}catch(A){return null}finally{b.delete(a)}})();return b.set(a,T),T},async decide(a){var D,I,k,M,T,A,P,O,ke,Re;let u=r.getSessionId();if(!u)return null;let p=(D=a.slots)!=null?D:[];await x;try{let q={sessionId:u};a.sections&&a.sections.length>0&&(q.sections=a.sections.map(C=>({id:C}))),q.components=(I=a.components)!=null?I:[],p.length>0&&(q.slots=p.map(oe));let De=await fetch(`${o}/decide`,{method:"POST",body:JSON.stringify(q),headers:l});if(!De.ok)return F(p),null;let U=await De.json(),me={};for(let C of p)me[C.id]=(M=(k=U.slots)==null?void 0:k[C.id])!=null?M:$(C);for(let[C,ye]of Object.entries(me))v.set(C,ye);E={persona:(T=U.persona)!=null?T:"unknown",confidence:(A=U.confidence)!=null?A:0};for(let[C,ye]of Object.entries((P=U.assignments)!=null?P:{}))c.set(C,h,{variantId:ye,assignedAt:Date.now(),segment:h,confidence:1});return W(e.apiKey,{v:1,persona:E.persona,band:(0,Ie.confidenceBand)(E.confidence),slots:Object.fromEntries(v),layoutOrder:(O=U.layoutOrder)!=null?O:null,savedAt:Date.now()}),{layoutOrder:(ke=U.layoutOrder)!=null?ke:null,assignments:(Re=U.assignments)!=null?Re:{},slots:me,persona:E.persona,confidence:E.confidence}}catch(q){return F(p),null}},getSlotResult(a){var u;return(u=v.get(a))!=null?u:null},getPersona(){return E?{persona:E.persona,confidence:E.confidence,band:(0,Ie.confidenceBand)(E.confidence)}:null},async fetchWeights(){var a;try{let u=await fetch(`${o}/weights`,{headers:l});return u.ok?(a=(await u.json()).components)!=null?a:[]:[]}catch(u){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){s.destroy(),r.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(j.set(e.apiKey,{config:e,upgrade:null}),e.debug){let a=window;a.__sentient&&(a.__sentient.client=N)}return N}0&&(module.exports={LOCAL_MODE_BANNER,PROD_KEYLESS_ERROR,SNAPSHOT_STORAGE_KEY_PREFIX,agentUaList,armOfResult,attachMicroSignalDetectors,baselineResultFor,baselineSlots,deriveSessionSegment,detectDeviceClass,detectTimeOfDay,detectTrafficSource,grantConsent,init,isDoNotTrackEnabled,matchedAgentToken,readSnapshot,referrerDomainFromReferer,renderPrePaintScript,toWireSlot,uaTokenMatch,writeSnapshot});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as i,b as j,c as k,d as l}from"./chunk-6PD6FNO7.mjs";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}from"./chunk-CFXMEZCZ.mjs";export{a as agentUaList,i as attachMicroSignalDetectors,h as deriveSessionSegment,d as detectDeviceClass,g as detectTimeOfDay,e as detectTrafficSource,k as grantConsent,l as init,j as isDoNotTrackEnabled,c as matchedAgentToken,f as referrerDomainFromReferer,b as uaTokenMatch};
1
+ import{a as m,b as n,c as o,d as p,e as q,f as r,g as s,h as t,i as u,j as v}from"./chunk-X2URHWFL.mjs";import{a,b,c,d,e,f,g,h,j as i,k as j,l as k,m as l}from"./chunk-SVYHTU5Z.mjs";import"./chunk-HGGX55FR.mjs";export{r as LOCAL_MODE_BANNER,q as PROD_KEYLESS_ERROR,m as SNAPSHOT_STORAGE_KEY_PREFIX,a as agentUaList,l as armOfResult,s as attachMicroSignalDetectors,j as baselineResultFor,k as baselineSlots,h as deriveSessionSegment,d as detectDeviceClass,g as detectTimeOfDay,e as detectTrafficSource,u as grantConsent,v as init,t as isDoNotTrackEnabled,c as matchedAgentToken,n as readSnapshot,f as referrerDomainFromReferer,p as renderPrePaintScript,i as toWireSlot,b as uaTokenMatch,o as writeSnapshot};
@@ -1,3 +1,34 @@
1
+ import { SlotResult, SlotDecl } from '@sentientui/policy';
2
+
3
+ /**
4
+ * Slot declaration helpers shared by the browser client (decide) and the
5
+ * server preload path. Pure wrappers over @sentientui/policy.
6
+ */
7
+
8
+ /** SDK-facing slot declaration. `dims` accepts readonly arrays (`as const`). */
9
+ type SlotDeclInput = {
10
+ id: string;
11
+ arms?: string[];
12
+ dims?: Record<string, readonly string[]>;
13
+ baseline?: string | Record<string, string>;
14
+ };
15
+
16
+ /**
17
+ * Whitelists the wire fields of a slot declaration. Anything an SDK layer
18
+ * attached (goal configs, refs, …) is stripped so it never reaches the zod
19
+ * schema on the API. Also normalizes readonly arrays to mutable ones.
20
+ */
21
+ declare function toWireSlot(d: SlotDeclInput): SlotDecl;
22
+ /** The declared (or default first-declared) baseline result for a slot. */
23
+ declare function baselineResultFor(d: SlotDeclInput): SlotResult;
24
+ /** Baseline results for a whole declaration list, keyed by slot id. */
25
+ declare function baselineSlots(decls: SlotDeclInput[]): Record<string, SlotResult>;
26
+ /**
27
+ * Canonical arm string of a slot result: dims results encode as sorted
28
+ * `dim=value` pairs joined with '|'; arms results are the arm id verbatim.
29
+ */
30
+ declare function armOfResult(result: SlotResult): string;
31
+
1
32
  /** Session metadata helpers (browser + Node). No DOM APIs. */
2
33
  /**
3
34
  * Known AI-agent / crawler user-agent tokens. Matched case-insensitively as
@@ -50,4 +81,4 @@ declare function buildSessionUpsertPayload(sessionId: string, opts?: {
50
81
  webdriver?: boolean;
51
82
  }): SessionUpsertPayload;
52
83
 
53
- export { type SessionUpsertPayload as S, agentUaList as a, buildSessionUpsertPayload as b, detectDeviceClass as c, deriveSessionSegment as d, detectTimeOfDay as e, detectTrafficSource as f, matchedAgentToken as m, referrerDomainFromReferer as r, uaTokenMatch as u };
84
+ export { type SessionUpsertPayload as S, type SlotDeclInput as a, agentUaList as b, armOfResult as c, baselineResultFor as d, baselineSlots as e, buildSessionUpsertPayload as f, deriveSessionSegment as g, detectDeviceClass as h, detectTimeOfDay as i, detectTrafficSource as j, matchedAgentToken as m, referrerDomainFromReferer as r, toWireSlot as t, uaTokenMatch as u };
@@ -1,3 +1,34 @@
1
+ import { SlotResult, SlotDecl } from '@sentientui/policy';
2
+
3
+ /**
4
+ * Slot declaration helpers shared by the browser client (decide) and the
5
+ * server preload path. Pure wrappers over @sentientui/policy.
6
+ */
7
+
8
+ /** SDK-facing slot declaration. `dims` accepts readonly arrays (`as const`). */
9
+ type SlotDeclInput = {
10
+ id: string;
11
+ arms?: string[];
12
+ dims?: Record<string, readonly string[]>;
13
+ baseline?: string | Record<string, string>;
14
+ };
15
+
16
+ /**
17
+ * Whitelists the wire fields of a slot declaration. Anything an SDK layer
18
+ * attached (goal configs, refs, …) is stripped so it never reaches the zod
19
+ * schema on the API. Also normalizes readonly arrays to mutable ones.
20
+ */
21
+ declare function toWireSlot(d: SlotDeclInput): SlotDecl;
22
+ /** The declared (or default first-declared) baseline result for a slot. */
23
+ declare function baselineResultFor(d: SlotDeclInput): SlotResult;
24
+ /** Baseline results for a whole declaration list, keyed by slot id. */
25
+ declare function baselineSlots(decls: SlotDeclInput[]): Record<string, SlotResult>;
26
+ /**
27
+ * Canonical arm string of a slot result: dims results encode as sorted
28
+ * `dim=value` pairs joined with '|'; arms results are the arm id verbatim.
29
+ */
30
+ declare function armOfResult(result: SlotResult): string;
31
+
1
32
  /** Session metadata helpers (browser + Node). No DOM APIs. */
2
33
  /**
3
34
  * Known AI-agent / crawler user-agent tokens. Matched case-insensitively as
@@ -50,4 +81,4 @@ declare function buildSessionUpsertPayload(sessionId: string, opts?: {
50
81
  webdriver?: boolean;
51
82
  }): SessionUpsertPayload;
52
83
 
53
- export { type SessionUpsertPayload as S, agentUaList as a, buildSessionUpsertPayload as b, detectDeviceClass as c, deriveSessionSegment as d, detectTimeOfDay as e, detectTrafficSource as f, matchedAgentToken as m, referrerDomainFromReferer as r, uaTokenMatch as u };
84
+ export { type SessionUpsertPayload as S, type SlotDeclInput as a, agentUaList as b, armOfResult as c, baselineResultFor as d, baselineSlots as e, buildSessionUpsertPayload as f, deriveSessionSegment as g, detectDeviceClass as h, detectTimeOfDay as i, detectTrafficSource as j, matchedAgentToken as m, referrerDomainFromReferer as r, toWireSlot as t, uaTokenMatch as u };
package/llms.txt ADDED
@@ -0,0 +1,46 @@
1
+ # SentientUI
2
+
3
+ > SentientUI makes websites adapt to each visitor. The SDK observes behaviour, classifies
4
+ > visitors into personas (buyer, researcher, deal_seeker, browser, unknown), and a server-side
5
+ > persona-keyed optimizer picks — per visitor type — which styling, content, and section order
6
+ > to show, learning from real conversions. Decisions are locked per session: Visit 1 learns,
7
+ > Visit 2 converts. React SDK, vanilla JS SDK, and a script-tag snippet are open source; the
8
+ > learning API is hosted (api.sentient-ui.com).
9
+
10
+ ## Install (agent quickstart)
11
+
12
+ - React app: `npx sentientui init` — detects the framework (Next App/Pages, Vite, Remix, CRA),
13
+ installs @sentientui/react, wraps the app with the provider, writes .env.local, scaffolds an
14
+ example. Works with NO API key (keyless local mode: deterministic simulated decisions).
15
+ Verify by opening the app with `?sentient_persona=buyer` vs `?sentient_persona=deal_seeker`.
16
+ - Real learning: create a project at https://sentient-ui.com, put the pk_ key in
17
+ NEXT_PUBLIC_SENTIENT_API_KEY, add the domain to allowed origins.
18
+ - Non-React site: use @sentientui/snippet (one script tag, Style rung only) or
19
+ @sentientui/core (full JS SDK).
20
+
21
+ ## Core API
22
+
23
+ - init(config: SentientConfig): SentientClient
24
+ - client.assign(componentId, variantIds?)
25
+ - client.decide({ sections?, components?, slots? }): Promise<DecideOutcome | null>
26
+ - client.getSlotResult(slotId)
27
+ - client.getPersona()
28
+ - client.goal(name, metadata?, weight?, stepIndex?)
29
+ - client.componentGoal(componentId, goalType, opts?)
30
+ - client.identify(userId)
31
+ - readSnapshot(apiKey) / writeSnapshot(apiKey, snap) / renderPrePaintScript(apiKey)
32
+ - createLocalEngine({ sessionId, forcedPersona? }) from '@sentientui/core/local'
33
+ (keyless mode, development export condition only)
34
+
35
+ ## Non-React wire surface
36
+
37
+ POST /v1/decide accepts slots: [{ id, arms?: string[], dims?: Record<string, string[]>,
38
+ baseline? }] and returns slots: Record<string, string | Record<string, string>>.
39
+ @sentientui/core: init({ apiKey, context }) → client.decide({ sections?, components?, slots? }),
40
+ client.getPersona(), decision snapshot in localStorage ('_snt_snap:<apiKey>') for pre-paint.
41
+
42
+ ## Docs
43
+
44
+ - React SDK: packages/react/README.md (in-repo) or https://sentient-ui.com/docs
45
+ - Core SDK: packages/core/README.md
46
+ - MCP server for agents: @sentientui/mcp (tool get_integration_guide returns this guide expanded)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/core",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,13 +21,31 @@
21
21
  "types": "./dist/index-server.d.ts",
22
22
  "import": "./dist/index-server.mjs",
23
23
  "require": "./dist/index-server.js"
24
+ },
25
+ "./local": {
26
+ "types": "./dist/index-local.d.ts",
27
+ "development": {
28
+ "import": "./dist/index-local.mjs",
29
+ "require": "./dist/index-local.js"
30
+ },
31
+ "production": {
32
+ "import": "./dist/index-local-stub.mjs",
33
+ "require": "./dist/index-local-stub.js"
34
+ },
35
+ "import": "./dist/index-local-stub.mjs",
36
+ "require": "./dist/index-local-stub.js"
24
37
  }
25
38
  },
26
39
  "files": [
27
- "dist"
40
+ "dist",
41
+ "llms.txt"
28
42
  ],
43
+ "dependencies": {
44
+ "@sentientui/policy": "0.2.0"
45
+ },
29
46
  "devDependencies": {
30
47
  "@types/node": "^22.10.2",
48
+ "esbuild": "^0.24.0",
31
49
  "jsdom": "^25.0.1",
32
50
  "tsup": "^8.3.5",
33
51
  "tsx": "^4.19.2",
@@ -37,8 +55,9 @@
37
55
  "scripts": {
38
56
  "build": "tsup",
39
57
  "test": "vitest run",
40
- "typecheck": "tsc --noEmit",
58
+ "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
41
59
  "size-check": "tsx scripts/size-check.ts",
60
+ "verify:local-exclusion": "tsx scripts/verify-local-exclusion.ts",
42
61
  "lint": "eslint src"
43
62
  }
44
63
  }
@@ -1 +0,0 @@
1
- import{a as D,b as K,d as W,f as B,g as Q,h as F,i as j}from"./chunk-CFXMEZCZ.mjs";var ie="_snt_uid";var A="_snt_uid";function oe(){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 re(e){try{let t=document.cookie.match(new RegExp(`(?:^|; )${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}catch(t){return null}}function ae(e,t,a){try{document.cookie=`${e}=${encodeURIComponent(t)}; max-age=${a}; SameSite=strict; path=/`}catch(c){}}function ce(e){try{return localStorage.getItem(e)}catch(t){return null}}function le(e,t){try{return localStorage.setItem(e,t),!0}catch(a){return!1}}function de(e){try{return sessionStorage.getItem(e)}catch(t){return null}}function ue(e,t){try{return sessionStorage.setItem(e,t),!0}catch(a){return!1}}function ge(e){try{sessionStorage.removeItem(e)}catch(t){}}function pe(e){try{return document.cookie=`${e}_probe=1; max-age=1; SameSite=strict; path=/`,/(?:^|; )_snt_uid_probe=1/.test(document.cookie)||document.cookie.indexOf(`${e}_probe=1`)!==-1}catch(t){return!1}}function fe(e){try{localStorage.removeItem(e)}catch(t){}}function me(e){try{document.cookie=`${e}=; max-age=0; SameSite=strict; path=/`}catch(t){}}var ye={getSessionId:()=>null,isEphemeral:()=>!1,destroy:()=>{}};function Y(e){var p,m,y,S,E,h;if(typeof window=="undefined")return ye;let t=(p=e==null?void 0:e.cookieName)!=null?p:ie,c=((m=e==null?void 0:e.cookieTTLDays)!=null?m:365)*24*60*60,o=(h=(E=(S=(y=re(t))!=null?y:ce(A))!=null?S:de(A))!=null?E:e==null?void 0:e.ssrSessionId)!=null?h:oe();ae(t,o,c);let i=le(A,o),r=pe(t),n=i?!1:ue(A,o),s=!i&&!r&&!n;return{getSessionId:()=>o,isEphemeral:()=>s,destroy:()=>{o=null,me(t),fe(A),ge(A)}}}var he={push:()=>{},flush:()=>{},destroy:()=>{}};function Se(e,t){try{let a=localStorage.getItem(t);if(!a)return[];let c=JSON.parse(a);return Array.isArray(c)?(localStorage.removeItem(t),c.slice(-e)):[]}catch(a){return[]}}function z(e,t,a){try{let o=[...(()=>{try{let i=localStorage.getItem(a);if(!i)return[];let r=JSON.parse(i);return Array.isArray(r)?r:[]}catch(i){return[]}})(),...e].slice(-t);localStorage.setItem(a,JSON.stringify(o))}catch(c){}}function q(e){var f,_,I;if(typeof window=="undefined")return he;let t=(f=e.flushIntervalMs)!=null?f:5e3,a=(_=e.maxBatchSize)!=null?_:20,c=(I=e.maxRetrySize)!=null?I:100,o=e.ingestUrl,i=e.apiKey,r=`_snt_retry_${i.slice(0,12)}`,n=[],s=new Set,p=[],m=l=>{for(let g of l)y.delete(g),!s.has(g)&&(s.add(g),p.push(g));for(;p.length>500;){let g=p.shift();g&&s.delete(g)}},y=new Set,S=l=>{s.has(l.id)||y.has(l.id)||(y.add(l.id),n.push(l))},E=Se(c,r);for(let l of E)S(l);let h=0,k=0,N=l=>{if(l.length===0)return;let g=JSON.stringify(l),v=l.map(w=>w.id),x;try{x=fetch(o,{method:"POST",keepalive:!0,body:g,headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`}})}catch(w){z(l,c,r);for(let G of v)y.delete(G);k++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6));return}let T=w=>{if(w.ok||w.status>=400&&w.status<500&&w.status!==429){m(v),k=0,h=0;return}z(l,c,r);for(let G of v)y.delete(G);k++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6))};x instanceof Promise?x.then(T).catch(()=>{z(l,c,r);for(let w of v)y.delete(w);k++,h=Date.now()+Math.min(6e4,1e3*2**Math.min(k,6))}):T(x)},O=typeof TextEncoder!="undefined"?new TextEncoder:null,L=l=>O?O.encode(l).length:l.length,$=l=>{let g=[],v=2;for(let x of l){let T=L(JSON.stringify(x))+1;if(g.length>0&&v+T>57344||g.length>=a)break;g.push(x),v+=T}return g},b=()=>{try{if(Date.now()<h)return;for(;n.length>0;){let l=n.filter(v=>!s.has(v.id));if(n.length=0,l.length===0)break;let g=$(l);if(g.length===0)break;g.length<l.length&&n.push(...l.slice(g.length)),N(g)}}catch(l){}},R=!0,C=null;C=setInterval(()=>{R&&b()},t);let d=()=>{document.visibilityState==="hidden"&&b()},u=()=>{b()};return document.addEventListener("visibilitychange",d),window.addEventListener("beforeunload",u),{push(l){S(l),n.length>=a&&b()},flush:b,destroy(){R=!1,C!==null&&(clearInterval(C),C=null),document.removeEventListener("visibilitychange",d),window.removeEventListener("beforeunload",u),b()}}}var H="_snt_asgn_";function P(e,t){return`${e}:${t}`}function ve(e,t){return`${H}${encodeURIComponent(e)}:${encodeURIComponent(t)}`}function X(e){let t=e.slice(H.length),a=t.indexOf(":");if(a<0)return null;try{return{componentId:decodeURIComponent(t.slice(0,a)),segment:decodeURIComponent(t.slice(a+1))}}catch(c){return null}}function J(){try{let e=[];for(let t=0;t<localStorage.length;t++){let a=localStorage.key(t);a!=null&&a.startsWith(H)&&e.push(a)}return e}catch(e){return[]}}function Z(e=18e5){let t=new Map,a=o=>o.assignedAt+e<Date.now();return typeof window!="undefined"&&(()=>{for(let o of J())try{let i=localStorage.getItem(o);if(!i)continue;let r=JSON.parse(i);if(a(r)){localStorage.removeItem(o);continue}let n=X(o);if(!n)continue;t.set(P(n.componentId,n.segment),r)}catch(i){}})(),{get(o,i){let r=t.get(P(o,i));return r?a(r)?(t.delete(P(o,i)),null):r:null},set(o,i,r){let n=P(o,i);t.set(n,r);try{localStorage.setItem(ve(o,i),JSON.stringify(r))}catch(s){}},invalidate(o){let i=`${o}:`;for(let r of[...t.keys()])r.startsWith(i)&&t.delete(r);for(let r of J()){let n=X(r);if((n==null?void 0:n.componentId)===o)try{localStorage.removeItem(r)}catch(s){}}},clear(){t.clear();for(let o of J())try{localStorage.removeItem(o)}catch(i){}}}}function we(e,t,a){var o;let c=[];{let n=!1,s=[],p=()=>{if(n)return;let m=Date.now();for(s.push(m);s.length>0&&m-s[0]>500;)s.shift();s.length>=3&&(n=!0,e("rage_click"))};t.addEventListener("click",p),c.push(()=>t.removeEventListener("click",p))}{let i=!1,r=n=>{if(i||!(n.target instanceof Node)||!t.contains(n.target)&&t!==n.target)return;i=!0;let s=typeof window!="undefined"?window.getSelection():null,p=s?s.toString().length:0;e("text_copy",{selectionLength:p})};document.addEventListener("copy",r),c.push(()=>document.removeEventListener("copy",r))}{let i=!1,r=!1,n=null,s=()=>{n!==null&&(clearTimeout(n),n=null)},p=()=>{i||!r||(s(),n=setTimeout(()=>{!i&&r&&(i=!0,e("scroll_hesitation"))},3e3))},m=()=>{s(),p()},y=E=>{for(let h of E)r=h.intersectionRatio>.3,r?p():s()};typeof process!="undefined"&&((o=process.env)==null?void 0:o.NODE_ENV)!=="production"&&(window.__lastIOCallback=y);let S=new IntersectionObserver(y,{threshold:[.3]});S.observe(t),window.addEventListener("scroll",m,{passive:!0}),c.push(()=>{S.disconnect(),window.removeEventListener("scroll",m),s()})}{let i=!1,r=a!=null?a:Date.now(),n=()=>{if(i||document.visibilityState!=="hidden")return;let s=Date.now()-r;s<15e3&&(i=!0,e("tab_loss",{timeOnPage:s}))};document.addEventListener("visibilitychange",n),c.push(()=>document.removeEventListener("visibilitychange",n))}return()=>{for(let i of c)i()}}var ee="https://api.sentient-ui.com/v1/events",M=new Map,te=null;function V(){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 U={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,assign:()=>Promise.resolve(null),fetchWeights:()=>Promise.resolve([]),getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}};function Ee(){try{let e={},t=new URLSearchParams(window.location.search);for(let[a,c]of t)a.startsWith("utm_")&&(e[a]=c);return e}catch(e){return{}}}function ne(e){return e.replace(/\/events\/?$/,"")}function se(){return[typeof navigator!="undefined"?navigator.doNotTrack:void 0,typeof window!="undefined"?window.doNotTrack:void 0,typeof navigator!="undefined"?navigator.msDoNotTrack:void 0].some(t=>t==="1"||t==="yes")}function Ne(e){if(typeof window=="undefined")return;let t=e!=null?e:te;if(!t){console.warn("[sentient] grantConsent() called before init()");return}let a=M.get(t);if(!a){console.warn("[sentient] grantConsent() called before init()");return}let{config:c,upgrade:o}=a;if(!o||c.respectDoNotTrack!==!1&&se())return;let i=Ie(K(D({},c),{consent:!0}));o(i),M.set(t,{config:K(D({},c),{consent:!0}),upgrade:null})}function xe(e){var r;let t=ne((r=e.ingestUrl)!=null?r:ee),a={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},c={track:()=>{},goal:()=>{},componentGoal:()=>{},identify:()=>{},getAssignment:()=>null,fetchWeights:()=>Promise.resolve([]),async assign(n,s,p){try{let m=new URLSearchParams({componentId:n});for(let E of s!=null?s:[])m.append("variantIds[]",E);let y=await fetch(`${t}/winner?${m.toString()}`,{headers:a});return y.ok?{variantId:(await y.json()).variantId,assignmentTtlMs:0}:s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}catch(m){return s!=null&&s[0]?{variantId:s[0],assignmentTtlMs:0}:null}},getGraph:()=>({pageNodes:[],capturedAt:0}),destroy:()=>{}},o={track:n=>c.track(n),goal:(n,s,p,m)=>c.goal(n,s,p,m),componentGoal:(n,s,p)=>c.componentGoal(n,s,p),identify:n=>c.identify(n),getAssignment:(n,s)=>c.getAssignment(n,s),assign:(n,s,p,m)=>c.assign(n,s,p,m),fetchWeights:()=>c.fetchWeights(),getGraph:()=>c.getGraph(),destroy:()=>c.destroy()};function i(n){c=n}return{proxy:o,setInner:i}}function Ie(e){var O,L,$,b,R,C;if(typeof window=="undefined")return U;te=e.apiKey;let t=e.respectDoNotTrack!==!1&&se();if(e.consent===!1||t){if(e.preConsentBehavior==="statistical_winner"){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."),U;let{proxy:d,setInner:u}=xe(e);return M.set(e.apiKey,{config:e,upgrade:t?null:u}),d}return M.set(e.apiKey,{config:e,upgrade:null}),U}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."),U;if(e.ingestUrl==="")return console.warn("[sentient] init() called with an empty ingestUrl. SDK disabled."),U;let a=(O=e.ingestUrl)!=null?O:ee,c=Date.now(),o=Y({ssrSessionId:e.ssrSessionId}),i=Z(),r=q({ingestUrl:a,apiKey:e.apiKey}),n=ne(a),s={"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`},p=B((L=navigator.userAgent)!=null?L:""),m=typeof window!="undefined"?window.location.origin:void 0,y=Q(($=document.referrer)!=null?$:"",m),S=(b=e.sessionSegment)!=null?b:`${p}:${y}`,E=new Map;if(e.initialAssignments)for(let[d,u]of Object.entries(e.initialAssignments))i.set(d,S,{variantId:u,assignedAt:Date.now(),segment:S,confidence:1});let h=Promise.resolve(),k=o.getSessionId();if(k){let d=F((R=document.referrer)!=null?R:""),u=D(D({sessionId:k,deviceClass:p,trafficSource:y,referrerDomain:d,utmParams:Ee(),timeOfDay:j(new Date),dayOfWeek:["sun","mon","tue","wed","thu","fri","sat"][new Date().getDay()],ephemeral:o.isEphemeral(),automation:typeof navigator!="undefined"&&navigator.webdriver===!0||W((C=navigator.userAgent)!=null?C:"")},e.userId?{userId:e.userId}:{}),e.country?{country:e.country}:{});try{h=fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify(u),headers:s}).then(f=>{f.status===402&&console.warn("[SentientUI] Session limit exceeded for this project. The bandit will stop learning until the limit resets. Upgrade at sentient-ui.com/pricing")}).catch(()=>{})}catch(f){}}e.debug&&(console.log("[sentient] initialized",{context:e.context}),window.__sentient={client:null,queue:r});let N={goal(d,u={},f=1,_=0){let I=o.getSessionId();if(!I)return;let l=V();h.then(()=>{fetch(`${n}/goals`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:I,name:d,metadata:u,weight:f,stepIndex:_,goalId:l}),headers:s}).catch(()=>{})})},componentGoal(d,u,f){var g,v;let _=o.getSessionId();if(!_)return;let I=i.get(d,S);if(!I){e.debug&&console.warn(`[sentient] componentGoal("${d}"): no assignment yet \u2014 render its <Adaptive> or call assign() before recording a goal.`);return}let l={id:V(),sessionId:_,projectId:e.apiKey,componentId:d,variantId:I.variantId,eventType:"goal_achieved",goalType:u,payload:D({reward:(g=f==null?void 0:f.reward)!=null?g:1},(v=f==null?void 0:f.metadata)!=null?v:{}),timestamp:Date.now(),timeInSession:Date.now()-c};e.debug&&console.log("[sentient] componentGoal",l),h.then(()=>r.push(l))},identify(d){let u=o.getSessionId();u&&h.then(()=>{fetch(`${n}/sessions`,{method:"POST",keepalive:!0,body:JSON.stringify({sessionId:u,userId:d,ephemeral:o.isEphemeral()}),headers:s}).catch(()=>{})})},track(d){let u=o.getSessionId();if(!u)return;let f=K(D({},d),{id:V(),sessionId:u,timestamp:Date.now(),timeInSession:Date.now()-c});e.debug&&console.log("[sentient] track",f),h.then(()=>r.push(f))},getAssignment(d,u){return i.get(d,u)},async assign(d,u,f,_){let I=o.getSessionId();if(!I)return null;let l=i.get(d,S);if(l&&(u!=null&&u.length||l.content!==void 0))return{variantId:l.variantId,assignmentTtlMs:0,content:l.content};let g=E.get(d);if(g)return g;let v=(async()=>{await h;try{let x={sessionId:I,componentId:d,variantIds:u};_!==void 0?x.agentDataByVariant=_:f!==void 0&&(x.agentData=f);let T=await fetch(`${n}/assign`,{method:"POST",body:JSON.stringify(x),headers:s});if(!T.ok)return null;let w=await T.json();return i.set(d,S,{variantId:w.variantId,assignedAt:Date.now(),segment:S,confidence:1,content:w.content}),w}catch(x){return null}finally{E.delete(d)}})();return E.set(d,v),v},async fetchWeights(){var d;try{let u=await fetch(`${n}/weights`,{headers:s});return u.ok?(d=(await u.json()).components)!=null?d:[]:[]}catch(u){return[]}},getGraph(){return{pageNodes:[],capturedAt:0}},destroy(){r.destroy(),o.destroy(),e.debug&&console.log("[sentient] destroyed")}};if(M.set(e.apiKey,{config:e,upgrade:null}),e.debug){let d=window;d.__sentient&&(d.__sentient.client=N)}return N}export{we as a,se as b,Ne as c,Ie as d};
@@ -1 +0,0 @@
1
- var m=Object.defineProperty,h=Object.defineProperties;var y=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var b=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var f=(r,e,t)=>e in r?m(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,L=(r,e)=>{for(var t in e||(e={}))b.call(e,t)&&f(r,t,e[t]);if(d)for(var t of d(e))x.call(e,t)&&f(r,t,e[t]);return r},O=(r,e)=>h(r,y(e));var w=["GPTBot","ChatGPT-User","OAI-SearchBot","ClaudeBot","Claude-User","Claude-SearchBot","PerplexityBot","Perplexity-User","Google-Extended","Applebot-Extended","Meta-ExternalAgent","Bytespider","CCBot","Amazonbot","cohere-ai","Diffbot"];function C(r){return k(r)!==null}function k(r){var t;if(!r)return null;let e=r.toLowerCase();return(t=w.find(n=>e.includes(n.toLowerCase())))!=null?t:null}function D(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 P(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 U(r){let e=r.getHours();return e<6?"night":e<12?"morning":e<18?"afternoon":"evening"}function B(r){let e=v("__segment__",r);return`${e.deviceClass}:${e.trafficSource}`}function v(r,e){var o,a,s,u,c,l,g;let t=(a=(o=e==null?void 0:e.userAgent)==null?void 0:o.trim())!=null?a:"",n=(u=(s=e==null?void 0:e.referer)==null?void 0:s.trim())!=null?u:"",i=(c=e==null?void 0:e.now)!=null?c:new Date;return{sessionId:r,ephemeral:!1,utmParams:(l=e==null?void 0:e.utmParams)!=null?l:{},deviceClass:t?D(t):"desktop",trafficSource:n?P(n,e==null?void 0:e.appOrigin):"direct",referrerDomain:S(n),timeOfDay:U(i),dayOfWeek:(g=["sun","mon","tue","wed","thu","fri","sat"][i.getDay()])!=null?g:"sun",automation:(e==null?void 0:e.webdriver)===!0||C(t)}}export{L as a,O as b,w as c,C as d,k as e,D as f,P as g,S as h,U as i,B as j,v as k};