@sentientui/react 0.15.3 → 0.15.4
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 +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/weights-store.ts","../src/preview-mode.ts","../src/override-events.ts","../src/devtools-config.ts","../src/devtools-registry.ts","../src/adaptive.tsx","../src/use-assignment.ts","../src/adaptive-shared.ts","../src/adaptive-text.tsx","../src/use-adaptive-goal.ts","../src/persona-script.tsx","../src/use-adaptive-tokens.ts","../src/use-slot-result.ts","../src/use-adaptive.ts","../src/adaptive-group.tsx","../src/segment.ts","../src/agent-feed.ts"],"sourcesContent":["'use client';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport {\n detectDeviceClass,\n detectTrafficSource,\n init,\n type SentientClient,\n type SentientConfig,\n type SlotResult,\n} from '@sentientui/core';\nimport { update as updateWeightsStore, type ComponentWeights } from './weights-store.js';\nimport { getPreviewMode, subscribePreview, createPreviewClient } from './preview-mode.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { publishDevtoolsConfig } from './devtools-config.js';\nimport { registerSections } from './devtools-registry.js';\n\n/**\n * Mirrors the segment derivation inside core `init()` so the cache key used\n * by `useAssignment` always matches the key `assign()` writes under. Before\n * this, the context defaulted to 'desktop:direct' while core used the\n * detected segment — a systematic cache miss for every integration that\n * didn't pass `sessionSegment` explicitly.\n */\nfunction deriveDefaultSegment(): string {\n if (typeof window === 'undefined') return 'desktop:direct';\n try {\n const device = detectDeviceClass(navigator.userAgent ?? '');\n const source = detectTrafficSource(document.referrer ?? '', window.location.origin);\n return `${device}:${source}`;\n } catch {\n return 'desktop:direct';\n }\n}\n\nconst DEFAULT_API_BASE_URL = 'https://api.sentient-ui.com/v1';\n\n/** How to render adaptive slots during SSR when assignments are not preloaded. */\nexport type SsrFallback = 'first' | 'none';\n\ntype AdaptiveContextValue = {\n client: SentientClient | null;\n // The publishable API key (pk_…). Historically named `projectId` because the\n // API uses it as the project identifier on the wire, but it is the API key,\n // not the project UUID. Field renamed for clarity.\n apiKey: string;\n initialAssignments: Record<string, string>;\n sessionSegment: string;\n ssrFallback: SsrFallback;\n onAssignment: ((componentId: string, variantId: string) => void) | undefined;\n initialLayoutOrder: string[] | null;\n initialSlots: Record<string, SlotResult>;\n initialPersona: { persona: string; confidence: number } | null;\n apiBaseUrl: string;\n};\n\nconst AdaptiveContext = createContext<AdaptiveContextValue>({\n client: null,\n apiKey: '',\n initialAssignments: {},\n sessionSegment: 'desktop:direct',\n ssrFallback: 'first',\n onAssignment: undefined,\n initialLayoutOrder: null,\n initialSlots: {},\n initialPersona: null,\n apiBaseUrl: DEFAULT_API_BASE_URL,\n});\n\nexport type AdaptiveProviderProps = {\n apiKey: string;\n context: SentientConfig['context'];\n debug?: boolean;\n /**\n * SSR-preloaded assignments from `preloadAssignments()` / `loadAdaptiveAssignments()`.\n * Passed through to `useAssignment` as synchronous initial state so crawlers and\n * the first paint see real content (recommended for SEO).\n */\n initialAssignments?: Record<string, string>;\n /**\n * Bandit segment from SSR (`device:source`). Keeps cache, assign, and worker\n * weights on one row — must match `loadAdaptiveAssignments` / session upsert.\n */\n sessionSegment?: string;\n /**\n * When no `initialAssignments` exist for a component, `'first'` renders\n * `variantIds[0]` in server HTML (safe default for SEO). Use `'none'` only for\n * decorative slots marked `clientOnly`.\n * @default 'first'\n */\n ssrFallback?: SsrFallback;\n /**\n * Consent gate. When `false` the SDK is not initialised and no events are\n * sent. Flip to `true` (e.g. after the user accepts the cookie banner) to\n * initialise and begin tracking.\n */\n consent?: boolean;\n /**\n * Behavior before consent is granted. Pass `'statistical_winner'` to serve the\n * best-performing variant via `GET /v1/winner` with zero tracking while the\n * consent banner is showing. Requires `consent: false`.\n * @see SentientConfig.preConsentBehavior\n */\n preConsentBehavior?: 'statistical_winner' | 'control';\n /**\n * Honor the browser's Do Not Track signal. Defaults to `true`: when DNT is\n * enabled the SDK sets no cookies and sends no tracking data (overriding\n * `consent: true`). Set `false` to make your own consent gate authoritative.\n * @see SentientConfig.respectDoNotTrack\n */\n respectDoNotTrack?: boolean;\n /**\n * Called once per component the first time a variant is resolved for that\n * component in this session. Use to forward assignments to your own analytics\n * (Mixpanel, PostHog, Segment, etc.) without having to wrap `useAssignment`.\n */\n onAssignment?: (componentId: string, variantId: string) => void;\n /**\n * SSR-preloaded section order from `loadAdaptiveDecision()`.\n * Pass the `layoutOrder` field from `DecideResult`. When set,\n * `useLayoutOrder()` returns this on first render so there is no layout shift.\n */\n initialLayoutOrder?: string[] | null;\n /**\n * SSR-preloaded slot results from `loadAdaptiveDecision()` (the `slots`\n * field of its result). Guarantees `useAdaptiveTokens`/`AdaptiveGroup`\n * render the decided arm in server HTML — zero flicker, hydration-safe.\n */\n initialSlots?: Record<string, SlotResult>;\n /**\n * Persona decided during SSR (`persona` + `confidence` fields of\n * `loadAdaptiveDecision()`'s result). Adopted by the core client;\n * rendered into html attributes only by `SentientPersonaScript`.\n */\n initialPersona?: { persona: string; confidence: number };\n /**\n * Base URL of the Sentient API (no trailing slash). Read by the devtools\n * panel for /v1/explain and by future client helpers. Defaults to the\n * hosted API.\n */\n apiBaseUrl?: string;\n /**\n * Session ID generated during SSR (the `sessionId` field returned by\n * `loadAdaptiveAssignments` / `loadAdaptiveDecision`). When provided and no\n * existing session cookie or localStorage entry is found, the client adopts\n * this ID so events and goals are attributed to the same session the server\n * used for variant assignment.\n */\n ssrSessionId?: string;\n /**\n * ISO 3166-1 alpha-2 country code. Pass the value of the `CF-IPCountry`\n * header from your Next.js server component to populate country on landing\n * sessions without client-side geo lookup.\n */\n country?: string;\n /**\n * Keyless local mode. 'auto' (default) simulates decisions on-device in\n * development builds when no valid API key is configured; `true` forces the\n * local engine; `false` restores the silent keyless no-op.\n * @see SentientConfig.localMode\n */\n localMode?: 'auto' | boolean;\n /**\n * Enable DOM graph scanning + page-structure sync. When `true`, the provider\n * dynamically loads `@sentientui/core/graph` and uses its graph-capable\n * `init()` for the single client, so the SDK scans your page structure and\n * syncs it to power the dashboard graph page. Left off (default), the lean\n * bundle is used and the graph entry is never loaded.\n */\n enableGraph?: boolean;\n children: ReactNode;\n};\n\n/**\n * Initialises the Sentient core SDK in a useEffect (SSR-safe) and exposes the\n * client via React context. Re-initialises when `consent` changes.\n */\nexport function AdaptiveProvider(props: AdaptiveProviderProps): JSX.Element {\n const [client, setClient] = useState<SentientClient | null>(null);\n // Derived once per mount: identical to what core init() computes, so cache\n // reads (context segment) and cache writes (core segment) always agree.\n const [sessionSegment] = useState(() => props.sessionSegment ?? deriveDefaultSegment());\n // Devtools preview: when on, expose an event-suppressing client so previewing\n // variants/personas writes nothing. Off by default (inert in production).\n const [previewOn, setPreviewOn] = useState(getPreviewMode());\n useEffect(() => subscribePreview(() => setPreviewOn(getPreviewMode())), []);\n\n useEffect(() => {\n // When consent is explicitly false with no preConsentBehavior, tear down any existing client.\n if (props.consent === false && !props.preConsentBehavior) {\n setClient((prev: SentientClient | null) => {\n prev?.destroy();\n return null;\n });\n return;\n }\n\n const config = {\n apiKey: props.apiKey,\n context: props.context,\n debug: props.debug,\n initialAssignments: props.initialAssignments,\n sessionSegment,\n consent: props.consent,\n preConsentBehavior: props.preConsentBehavior,\n respectDoNotTrack: props.respectDoNotTrack,\n ssrSessionId: props.ssrSessionId,\n country: props.country,\n localMode: props.localMode,\n initialSlots: props.initialSlots,\n initialPersona: props.initialPersona,\n ingestUrl: props.apiBaseUrl ? `${props.apiBaseUrl.replace(/\\/$/, '')}/events` : undefined,\n };\n\n // Track the client created by this effect run so cleanup destroys exactly\n // the right one, and so a late-resolving dynamic import can bail if the\n // effect was already torn down (unmount / consent change).\n let cancelled = false;\n let created: SentientClient | null = null;\n\n if (props.enableGraph) {\n // Load the graph entry only when asked — keeps the DOM scanner out of the\n // lean bundle. The provider still creates ONE client (graph-capable).\n void import('@sentientui/core/graph').then(({ init: initGraph }) => {\n if (cancelled) return;\n created = initGraph({ ...config, graph: true });\n setClient(created);\n });\n } else {\n created = init(config);\n setClient(created);\n }\n\n return () => {\n cancelled = true;\n // dispose, not destroy: effect cleanup runs on unmount, StrictMode's\n // dev double-invoke, and consent re-init — the visitor identity must\n // survive all of those. Full destroy() happens only on the explicit\n // consent-revocation branch above.\n created?.dispose();\n };\n // Re-init when consent changes. Other props (incl. enableGraph) are\n // intentionally stable for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.consent]);\n\n // Poll /v1/weights every 60 s so long-lived sessions see updated bandit weights\n // without a page reload. useAssignment subscribers react via weights-store.\n useEffect(() => {\n if (!client) return;\n let cancelled = false;\n const poll = async (): Promise<void> => {\n if (cancelled) return;\n let entries;\n try {\n entries = await client.fetchWeights();\n } catch {\n // Network/transient error: skip this cycle and retry on the next\n // interval. Swallowed deliberately so a failed poll never surfaces as\n // an unhandled rejection.\n return;\n }\n if (cancelled) return;\n for (const entry of entries) {\n const weights: ComponentWeights = {\n componentId: entry.componentId,\n updatedAt: entry.updatedAt,\n variants: entry.variants.map((v) => ({\n variantId: v.variantId,\n pulls: v.pulls,\n avgReward: v.avgReward ?? 0,\n })),\n };\n updateWeightsStore(entry.componentId, weights);\n }\n };\n void poll();\n const timerId = setInterval(() => void poll(), 60_000);\n return () => {\n cancelled = true;\n clearInterval(timerId);\n };\n }, [client]);\n\n const ssrFallback = props.ssrFallback ?? 'first';\n const apiBaseUrl = props.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n\n // Publish devtools config through window: the /devtools entry is a separate\n // bundle and cannot read this provider's context instance. Dev-only.\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n publishDevtoolsConfig({\n apiKey: props.apiKey,\n apiBaseUrl,\n isLocal: client?.isLocal === true,\n });\n }, [client, props.apiKey, apiBaseUrl]);\n\n // Sections registry for devtools /v1/explain + local simulation.\n useEffect(() => {\n if (props.initialLayoutOrder && props.initialLayoutOrder.length > 0) {\n registerSections(props.initialLayoutOrder);\n }\n }, [props.initialLayoutOrder]);\n\n // The client exposed to consumers — wrapped to suppress events while previewing.\n const exposedClient = useMemo(\n () => (client && previewOn ? createPreviewClient(client) : client),\n [client, previewOn],\n );\n\n // Memoized so unrelated parent re-renders don't cascade through every\n // useSentient / useAssignment consumer via a fresh context object.\n const value = useMemo<AdaptiveContextValue>(\n () => ({\n client: exposedClient,\n apiKey: props.apiKey,\n initialAssignments: props.initialAssignments ?? {},\n sessionSegment,\n ssrFallback,\n onAssignment: props.onAssignment,\n initialLayoutOrder: props.initialLayoutOrder ?? null,\n initialSlots: props.initialSlots ?? {},\n initialPersona: props.initialPersona ?? null,\n apiBaseUrl,\n }),\n [\n exposedClient,\n props.apiKey,\n props.initialAssignments,\n sessionSegment,\n ssrFallback,\n props.onAssignment,\n props.initialLayoutOrder,\n props.initialSlots,\n props.initialPersona,\n apiBaseUrl,\n ],\n );\n\n return (\n <AdaptiveContext.Provider value={value}>\n {props.children}\n </AdaptiveContext.Provider>\n );\n}\n\n/**\n * Returns the SentientClient, or null until the provider has finished\n * initialising on the client.\n */\nexport function useSentient(): SentientClient | null {\n return useContext(AdaptiveContext).client;\n}\n\n/** Internal: publishable API key carried alongside the client. */\nexport function useAdaptiveApiKey(): string {\n return useContext(AdaptiveContext).apiKey;\n}\n\n/**\n * @deprecated Renamed to `useAdaptiveApiKey`. Kept as an alias so external\n * imports from earlier versions of this package keep working. Will be removed\n * in 1.0.0.\n */\nlet warnedProjectIdAlias = false;\nexport function useAdaptiveProjectId(): string {\n if (\n !warnedProjectIdAlias &&\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV !== 'production'\n ) {\n warnedProjectIdAlias = true;\n console.warn(\n '[@sentientui/react] useAdaptiveProjectId is deprecated; use useAdaptiveApiKey. Will be removed in 1.0.0.',\n );\n }\n return useAdaptiveApiKey();\n}\n\n/** Internal: SSR-preloaded assignments for hydration-safe first render. */\nexport function useInitialAssignments(): Record<string, string> {\n return useContext(AdaptiveContext).initialAssignments;\n}\n\n/** Internal: bandit segment aligned with SSR session upsert. */\nexport function useSessionSegment(): string {\n return useContext(AdaptiveContext).sessionSegment;\n}\n\n/** Internal: SSR fallback strategy when a slot has no preloaded assignment. */\nexport function useSsrFallback(): SsrFallback {\n return useContext(AdaptiveContext).ssrFallback;\n}\n\n/** Internal: forwarding hook for consumer analytics integration. */\nexport function useOnAssignment(): ((componentId: string, variantId: string) => void) | undefined {\n return useContext(AdaptiveContext).onAssignment;\n}\n\n/**\n * Returns the persona-specific section order from SSR, or null when no\n * sections were declared on AdaptiveRoot or reliability is below threshold.\n * Devtools/testing can force it via `window.__sentient_layout_override`;\n * consumers re-render when the devtools notifies an override change.\n */\nexport function useLayoutOrder(): string[] | null {\n const contextOrder = useContext(AdaptiveContext).initialLayoutOrder;\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () =>\n typeof window === 'undefined'\n ? null\n : ((window as unknown as { __sentient_layout_override?: string[] })\n .__sentient_layout_override ?? null),\n () => null,\n );\n return override ?? contextOrder;\n}\n\n/** Internal: SSR-preloaded slot results for hydration-safe first render. */\nexport function useInitialSlots(): Record<string, SlotResult> {\n return useContext(AdaptiveContext).initialSlots;\n}\n\n/** Internal: SSR-decided persona carried alongside the client. */\nexport function useInitialPersona(): { persona: string; confidence: number } | null {\n return useContext(AdaptiveContext).initialPersona;\n}\n\n/** Internal: configured API base URL (devtools fetches /v1/explain against this, never a relative URL). */\nexport function useAdaptiveApiBaseUrl(): string {\n return useContext(AdaptiveContext).apiBaseUrl;\n}\n","/** Per-component weights store with isolated subscriptions. */\n\nexport type VariantWeight = {\n variantId: string;\n pulls: number;\n avgReward: number;\n};\n\nexport type ComponentWeights = {\n componentId: string;\n variants: VariantWeight[];\n updatedAt: number;\n};\n\ntype Listener = (weights: ComponentWeights) => void;\n\nconst store = new Map<string, ComponentWeights>();\nconst listeners = new Map<string, Set<Listener>>();\n\n/**\n * Subscribes a listener to a single component. Returns an unsubscribe function.\n * Updates to other components never trigger this listener.\n */\nexport function subscribe(componentId: string, cb: Listener): () => void {\n let set = listeners.get(componentId);\n if (!set) {\n set = new Set();\n listeners.set(componentId, set);\n }\n set.add(cb);\n return () => {\n set!.delete(cb);\n if (set!.size === 0) listeners.delete(componentId);\n };\n}\n\n/**\n * Replaces the weights for a component and notifies only that component's\n * subscribers.\n */\nexport function update(componentId: string, weights: ComponentWeights): void {\n store.set(componentId, weights);\n const set = listeners.get(componentId);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(weights);\n } catch {\n /* never throw to other listeners */\n }\n }\n}\n\n/**\n * Returns the latest known weights for a component, or null if none seen.\n */\nexport function getWeights(componentId: string): ComponentWeights | null {\n return store.get(componentId) ?? null;\n}\n\n/** Test-only: wipe the entire store. */\nexport function _resetWeightsStore(): void {\n store.clear();\n listeners.clear();\n}\n","import type { SentientClient } from '@sentientui/core';\n\ntype PreviewState = { on: boolean; listeners: Set<() => void> };\nconst ssrFallback: PreviewState = { on: false, listeners: new Set() };\n\n// Window-backed: the /devtools entry (a separate bundle) toggles preview mode\n// and the provider (main bundle) must observe it.\nfunction state(): PreviewState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_preview?: PreviewState };\n if (!w.__sentient_preview) w.__sentient_preview = { on: false, listeners: new Set() };\n return w.__sentient_preview;\n}\n\nexport function setPreviewMode(on: boolean): void {\n const s = state();\n if (s.on === on) return;\n s.on = on;\n for (const fn of s.listeners) fn();\n}\n\nexport function getPreviewMode(): boolean {\n return state().on;\n}\n\nexport function subscribePreview(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/**\n * Wraps a client so it writes nothing: reads pass through, all emitters no-op.\n * Used while previewing variants/personas so no `variant_assigned`, goal, or\n * session events are sent.\n */\nexport function createPreviewClient(inner: SentientClient): SentientClient {\n return {\n isLocal: inner.isLocal,\n track: () => undefined,\n goal: () => undefined,\n componentGoal: () => undefined,\n identify: () => undefined,\n fetchWeights: () => Promise.resolve([]),\n getAssignment: (componentId, segment) => inner.getAssignment(componentId, segment),\n assign: (componentId, variantIds, agentData, agentDataByVariant) =>\n inner.assign(componentId, variantIds, agentData, agentDataByVariant),\n // Reads pass through; decide is a write (slot decisions persist server-side)\n // so preview mode never issues it.\n decide: () => Promise.resolve(null),\n getSlotResult: (slotId) => inner.getSlotResult(slotId),\n getPersona: () => inner.getPersona(),\n getGraph: () => inner.getGraph(),\n dispose: () => inner.dispose(),\n destroy: () => inner.destroy(),\n };\n}\n","/**\n * Cross-bundle re-render bus for devtools overrides. The main entry and the\n * /devtools entry are separate bundles, so state and notifications go through\n * window (a version counter + a DOM event) — never module-local state.\n */\nconst EVENT = 'sentient:overrides-changed';\n\ntype VersionWindow = Window & { __sentient_overrides_version?: number };\n\nexport function getOverridesVersion(): number {\n if (typeof window === 'undefined') return 0;\n return (window as VersionWindow).__sentient_overrides_version ?? 0;\n}\n\nexport function notifyOverridesChanged(): void {\n if (typeof window === 'undefined') return;\n const w = window as VersionWindow;\n w.__sentient_overrides_version = (w.__sentient_overrides_version ?? 0) + 1;\n window.dispatchEvent(new Event(EVENT));\n}\n\nexport function subscribeOverridesChanged(fn: () => void): () => void {\n if (typeof window === 'undefined') return () => undefined;\n window.addEventListener(EVENT, fn);\n return () => window.removeEventListener(EVENT, fn);\n}\n","/** Provider → devtools config handoff. Window-backed: the /devtools entry is a\n * separate bundle and cannot share the provider's React context instance. */\nexport type DevtoolsConfig = {\n apiKey: string;\n apiBaseUrl: string;\n isLocal: boolean;\n};\n\ntype ConfigWindow = Window & { __sentient_devtools_config?: DevtoolsConfig };\n\nexport function publishDevtoolsConfig(config: DevtoolsConfig): void {\n if (typeof window === 'undefined') return;\n (window as ConfigWindow).__sentient_devtools_config = config;\n}\n\nexport function readDevtoolsConfig(): DevtoolsConfig | null {\n if (typeof window === 'undefined') return null;\n return (window as ConfigWindow).__sentient_devtools_config ?? null;\n}\n","export type RegisteredComponent = { id: string; variantIds: string[]; goal?: string };\nexport type RegisteredSlot = {\n id: string;\n arms?: string[];\n dims?: Record<string, readonly string[]>;\n};\n\ntype RegistryState = {\n components: Map<string, RegisteredComponent>;\n slots: Map<string, RegisteredSlot>;\n sections: string[];\n listeners: Set<() => void>;\n /** Bumped on every mutation so `useSyncExternalStore` can read a stable, comparable snapshot. */\n version: number;\n};\n\n// Shared through a window global: the main entry and the /devtools entry are\n// separate bundles, each with its own copy of this module — module-local\n// state would give the devtools an always-empty registry in published apps.\nconst ssrFallback: RegistryState = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n};\n\nfunction state(): RegistryState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_registry?: RegistryState };\n if (!w.__sentient_registry) {\n w.__sentient_registry = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n };\n }\n return w.__sentient_registry;\n}\n\nfunction emit(): void {\n // Bump BEFORE notifying so a useSyncExternalStore consumer re-reading its\n // snapshot inside the notification sees the new value and re-renders.\n state().version += 1;\n for (const fn of state().listeners) fn();\n}\n\n/** Register (or re-register) a component. Returns an unregister function. */\nexport function registerComponent(c: RegisteredComponent): () => void {\n state().components.set(c.id, c);\n emit();\n return () => {\n state().components.delete(c.id);\n emit();\n };\n}\n\n/** Register (or re-register) a slot declaration. Returns an unregister function. */\nexport function registerSlot(s: RegisteredSlot): () => void {\n state().slots.set(s.id, s);\n emit();\n return () => {\n state().slots.delete(s.id);\n emit();\n };\n}\n\n/** Register the page's declared section ids (from AdaptiveRoot/provider). */\nexport function registerSections(sections: string[]): void {\n state().sections = [...sections];\n emit();\n}\n\nexport function getRegistered(): RegisteredComponent[] {\n return [...state().components.values()];\n}\n\nexport function getRegisteredSlots(): RegisteredSlot[] {\n return [...state().slots.values()];\n}\n\nexport function getRegisteredSections(): string[] {\n return [...state().sections];\n}\n\nexport function subscribeRegistry(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/** Monotonic snapshot for `useSyncExternalStore` — changes on every registry mutation. */\nexport function getRegistryVersion(): number {\n return state().version;\n}\n","'use client';\n\nimport { memo, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { attachMicroSignalDetectors, type MicroSignalType } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\n\nexport type {\n ScrollDepthGoal,\n ClickGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n GoalConfig,\n} from './adaptive-shared.js';\nimport { attachGoalListeners, isDevBuild, normalizeGoal, trackExposure, type GoalConfig } from './adaptive-shared.js';\n\n/** Maps a detected micro-signal to a named session goal (`client.goal`). */\nexport type MicroSignalGoalConfig = string | { name: string; weight?: number; stepIndex?: number };\nexport type MicroSignalGoals = Partial<Record<MicroSignalType, MicroSignalGoalConfig>>;\n\nexport type AdaptiveProps = {\n id: string;\n variants: Record<string, ReactNode>;\n goal: string | GoalConfig;\n /**\n * When a passive micro-signal fires on this component, also record a named goal.\n * Use for inferred goals surfaced in the dashboard (e.g. rage_click → 'confused_by_hero').\n */\n microSignalGoals?: MicroSignalGoals;\n /**\n * When true, renders nothing during SSR and before client hydration.\n * Use when you cannot pass `initialAssignments` and prefer a blank slot over\n * a hydration mismatch. Tradeoff: minor CLS on first paint.\n */\n clientOnly?: boolean;\n /**\n * Variant-specific structured data for AI agent consumption via /sentient.json and\n * GET /v1/agent/layout. Keyed by variant ID — only the assigned variant's entry is stored,\n * so agents see only the content currently being served to visitors.\n *\n * Prefer this over `agentData` when variants have meaningfully different content.\n */\n agentDataByVariant?: Record<string, unknown>;\n /** @deprecated Use agentDataByVariant for variant-specific content. Stored as-is for the assigned variant. */\n agentData?: unknown;\n};\n\nfunction AdaptiveImpl(props: AdaptiveProps): JSX.Element | null {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const variantIds = useMemo(() => Object.keys(props.variants), [props.variants]);\n const { variantId, content, isOverride } = useAssignment(props.id, variantIds, props.agentData, props.agentDataByVariant);\n const containerRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => { setMounted(true); }, []);\n const goalFiredRef = useRef(false);\n const microGoalFiredRef = useRef<Set<MicroSignalType>>(new Set());\n const assignTrackedRef = useRef<string | null>(null);\n const goalKey = typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n const goal = useMemo(() => normalizeGoal(props.goal), [goalKey]);\n const goalLabel = typeof props.goal === 'string' ? props.goal : goal.type;\n\n // Register with the devtools registry so the dev widget can list this\n // component + its variants. Inert in production (registry has no UI); the\n // cleanup unregisters on unmount.\n useEffect(() => registerComponent({ id: props.id, variantIds, goal: goalLabel }), [props.id, variantIds, goalLabel]);\n\n // Track variant_assigned exactly once per (component, variant) mount.\n // Captures innerHTML as previewHtml so the dashboard can render a live preview\n // without requiring manual registry calls. First-seen wins on the server.\n // `mounted` is in deps so the effect re-runs after clientOnly components hydrate\n // and their container div is actually in the DOM.\n useEffect(() => {\n // A forced variant is a dev/test view, not a real exposure — recording it\n // would train the bandit on the override. Same gate on every tracking\n // effect below (\"no events recorded, weights unchanged\").\n if (isOverride) return;\n if (!client || !variantId || !apiKey) return;\n if (assignTrackedRef.current === variantId) return;\n const rawHtml = containerRef.current?.innerHTML ?? '';\n // Wait until content is in the DOM; will re-run when mounted changes.\n if (!rawHtml) return;\n assignTrackedRef.current = variantId;\n trackExposure(client, apiKey, props.id, variantId, containerRef.current);\n }, [client, variantId, apiKey, props.id, mounted, content, isOverride]);\n\n // Reset goal latch when variant or goal changes.\n useEffect(() => {\n goalFiredRef.current = false;\n microGoalFiredRef.current = new Set();\n }, [variantId, goal]);\n\n // Emit cursor_signal after 800 ms of continuous hover.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n let timerId: ReturnType<typeof setTimeout> | null = null;\n let hoverStart = 0;\n\n const onEnter = (): void => {\n hoverStart = Date.now();\n timerId = setTimeout(() => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'cursor_signal',\n payload: { hoverDuration: Date.now() - hoverStart },\n });\n timerId = null;\n }, 800);\n };\n\n const onLeave = (): void => {\n if (timerId !== null) {\n clearTimeout(timerId);\n timerId = null;\n }\n };\n\n node.addEventListener('mouseenter', onEnter);\n node.addEventListener('mouseleave', onLeave);\n return () => {\n node.removeEventListener('mouseenter', onEnter);\n node.removeEventListener('mouseleave', onLeave);\n if (timerId !== null) clearTimeout(timerId);\n };\n }, [client, variantId, apiKey, props.id, isOverride]);\n\n // Attach micro-signal detectors passively — rage click, text copy, scroll hesitation, tab loss.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n\n const mapping = props.microSignalGoals?.[signalType];\n if (!mapping || microGoalFiredRef.current.has(signalType)) return;\n microGoalFiredRef.current.add(signalType);\n const name = typeof mapping === 'string' ? mapping : mapping.name;\n const weight = typeof mapping === 'string' ? 1.0 : (mapping.weight ?? 1.0);\n const stepIndex = typeof mapping === 'string' ? 0 : (mapping.stepIndex ?? 0);\n client.goal(name, { signalType, ...extra }, weight, stepIndex);\n },\n node,\n assignedAt,\n );\n }, [client, variantId, apiKey, props.id, props.microSignalGoals, isOverride]);\n\n // Attach goal tracking (shared machinery — see adaptive-shared.ts).\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: props.id, variantId }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, variantId, apiKey, props.id, goal, goalLabel, isOverride]);\n\n // Decorative slots: empty in SSR HTML and until the client has mounted.\n if (props.clientOnly && (!mounted || !client)) return null;\n if (!variantId) return null;\n\n const jsxContent = props.variants[variantId] ?? null;\n const managedContent = jsxContent === null ? content : null;\n\n if (isDevBuild() && jsxContent === null && managedContent === null) {\n console.warn(\n `[sentient] <Adaptive id=\"${props.id}\"> was assigned variant \"${variantId}\" but no matching key exists in props.variants.` +\n ` If this is a dashboard-managed text variant, use <AdaptiveText id=\"${props.id}\"> instead.`,\n );\n }\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={variantId}>\n {jsxContent ?? managedContent}\n </div>\n );\n}\n\n/** Re-renders only when the chosen variant changes. */\nexport const Adaptive = memo(AdaptiveImpl, (prev, next) => {\n if (prev.id !== next.id) return false;\n if (JSON.stringify(prev.goal) !== JSON.stringify(next.goal)) return false;\n if (prev.microSignalGoals !== next.microSignalGoals) return false;\n if (prev.variants === next.variants) return true;\n const prevKeys = Object.keys(prev.variants);\n const nextKeys = Object.keys(next.variants);\n if (prevKeys.length !== nextKeys.length) return false;\n return prevKeys.every((k) => k in next.variants);\n});\n","import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { type AssignResult } from '@sentientui/core';\nimport { useSentient, useInitialAssignments, useSessionSegment, useSsrFallback, useOnAssignment } from './provider.js';\nimport { subscribe, getWeights, type ComponentWeights } from './weights-store.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\n\ndeclare global {\n interface Window { __sentient_overrides?: Record<string, string>; }\n}\n\nfunction getDevOverride(componentId: string): string | null {\n if (typeof window === 'undefined') return null;\n const global = window.__sentient_overrides?.[componentId];\n if (global) return global;\n try {\n const params = new URLSearchParams(window.location.search);\n for (const raw of params.getAll('sentient_variant')) {\n // sentient_variant=componentId:variantId (repeatable for multiple components)\n const sep = raw.indexOf(':');\n if (sep === -1) continue;\n if (raw.slice(0, sep) === componentId) return raw.slice(sep + 1);\n }\n } catch { /* non-browser env */ }\n return null;\n}\n\nexport type AssignmentState = {\n variantId: string | null;\n /** Populated when the assigned variant is a dashboard-managed text variant. */\n content: string | null;\n isLoading: boolean;\n /**\n * True while a dev override (?sentient_variant= / window.__sentient_overrides)\n * is forcing this variant. Consumers must suppress ALL tracking while set —\n * the override contract is \"no events recorded, weights unchanged\".\n */\n isOverride?: boolean;\n};\n\nfunction pickFromWeights(weights: ComponentWeights, variantIds: string[]): string | null {\n let best: { variantId: string; avgReward: number } | null = null;\n for (const v of weights.variants) {\n if (!variantIds.includes(v.variantId)) continue;\n if (!best || v.avgReward > best.avgReward) {\n best = { variantId: v.variantId, avgReward: v.avgReward };\n }\n }\n return best?.variantId ?? null;\n}\n\n/**\n * Returns a sticky variant assignment for a component.\n *\n * @deprecated Since 0.13.0 — use {@link useAdaptive} instead. `useAssignment`\n * only SELECTS a variant; it wires no exposure tracking, no goal listeners,\n * and no micro-signals, so components using it directly accumulate no\n * learning signal. It keeps working (it is `useAdaptive`'s internal\n * selection engine) but will move to internal-only in 1.0.0.\n *\n * First render reads the local SDK cache; if empty, falls back to a\n * deterministic default and asynchronously calls `/v1/assign`. The server\n * picks the actual variant via Thompson Sampling and the result replaces the fallback\n * on the next render. Subsequent paints read synchronously from cache —\n * no flicker, no loading state after first paint.\n */\nexport function useAssignment(componentId: string, variantIds: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): AssignmentState {\n const initialAssignments = useInitialAssignments();\n const ssrFallback = useSsrFallback();\n const client = useSentient();\n const segment = useSessionSegment();\n const onAssignment = useOnAssignment();\n const assignmentReportedRef = useRef<string | null>(null);\n\n // Re-render when the devtools writes window.__sentient_overrides. Without this\n // the override store is only read at mount, so forcing a variant from the panel\n // has no effect until an unrelated re-render. Mirrors useSlotResult.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n\n // Dev override: URL param ?sentient_variant=componentId:variantId\n // or window.__sentient_overrides[componentId]. Short-circuits the bandit entirely.\n const devOverride = getDevOverride(componentId);\n const overrideVariant = devOverride && variantIds.includes(devOverride) ? devOverride : null;\n const overrideLoggedRef = useRef<string | null>(null);\n if (overrideVariant && overrideLoggedRef.current !== overrideVariant) {\n overrideLoggedRef.current = overrideVariant;\n console.info(`[sentient] override active: ${componentId} -> ${overrideVariant}`);\n }\n\n const initial = (() => {\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false };\n }\n // SSR / pre-hydration: no client yet. Use initialAssignments if provided so\n // the server and client first render agree on the same variant (no mismatch).\n if (!client) {\n const preloaded = initialAssignments[componentId];\n if (preloaded && variantIds.includes(preloaded)) {\n return { variantId: preloaded, content: null, isLoading: false };\n }\n if (ssrFallback === 'first' && variantIds.length > 0) {\n return { variantId: variantIds[0], content: null, isLoading: false };\n }\n return { variantId: null, content: null, isLoading: true };\n }\n const cached = client.getAssignment(componentId, segment);\n // Allow cached managed variants (content present) even if not in variantIds.\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n return { variantId: cached.variantId, content: cached.content ?? null, isLoading: false };\n }\n const weights = getWeights(componentId);\n if (weights) {\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) return { variantId: chosen, content: null, isLoading: false };\n }\n return { variantId: variantIds[0] ?? null, content: null, isLoading: false };\n })();\n\n const [state, setState] = useState<AssignmentState>(initial);\n\n // Helper: call onAssignment at most once per resolved variant.\n const reportAssignment = (variantId: string): void => {\n if (!onAssignment) return;\n if (assignmentReportedRef.current === variantId) return;\n assignmentReportedRef.current = variantId;\n onAssignment(componentId, variantId);\n };\n\n // As soon as the client is ready, unblock the UI immediately with variantIds[0]\n // (or a cached value) so the component never stays invisible while assign is\n // in-flight. The async assign call below then swaps to the bandit-chosen variant.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false });\n reportAssignment(cached.variantId);\n return;\n }\n setState((prev) => prev.variantId ? prev : { variantId: variantIds[0] ?? null, content: null, isLoading: false });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Ask the server for a real assignment when we have a client but no cached one.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && variantIds.includes(cached.variantId)) return;\n\n let cancelled = false;\n void client.assign(componentId, variantIds, agentData, agentDataByVariant).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) return;\n // Allow the result if it's a known code variant OR a managed text variant (has content).\n if (!variantIds.includes(result.variantId) && !result.content) return;\n setState({ variantId: result.variantId, content: result.content ?? null, isLoading: false });\n reportAssignment(result.variantId);\n });\n return () => { cancelled = true; };\n // variantIds intentionally excluded — changing variants mid-mount is unsupported\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Live weight updates from the dashboard SSE stream (when wired).\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n return subscribe(componentId, (weights) => {\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false });\n return;\n }\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) setState({ variantId: chosen, content: null, isLoading: false });\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, isOverride: true };\n }\n\n return state;\n}\n","import type { SentientClient } from '@sentientui/core';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\n/**\n * True unless NODE_ENV is 'production'. Never `process?.env` — optional\n * chaining still throws ReferenceError on an undeclared global, and browsers\n * without a bundler shim (raw esbuild, vanilla script tags) have no `process`.\n */\nexport function isDevBuild(): boolean {\n return typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n}\n\nexport type ScrollDepthGoal = { type: 'scroll_depth'; threshold: number };\nexport type ClickGoal = { type: 'click'; selector?: string };\nexport type FormSubmitGoal = { type: 'form_submit' };\nexport type CompositeGoal = { type: 'composite'; all: GoalConfig[] };\nexport type WeightedStep = { goal: GoalConfig; name: string; weight: number };\nexport type WeightedCompositeGoal = { type: 'weighted_composite'; steps: WeightedStep[] };\nexport type GoalConfig = ScrollDepthGoal | ClickGoal | FormSubmitGoal | CompositeGoal | WeightedCompositeGoal;\n\nexport function normalizeGoal(goal: string | GoalConfig): GoalConfig {\n if (typeof goal === 'string') return { type: 'click' };\n return goal;\n}\n\n/** The goalType label events are recorded under (named goal or config type). */\nexport function goalLabelOf(goal: string | GoalConfig): string {\n return typeof goal === 'string' ? goal : goal.type;\n}\n\nexport const PREVIEW_HTML_MAX_CHARS = 30_000;\n\n/**\n * previewHtml is the largest payload the SDK sends (up to 30 KB). The server\n * keeps the first-seen preview per (component, variant), so re-sending it on\n * every mount/navigation is pure waste — send it once per browser session.\n */\nexport function shouldSendPreviewHtml(componentId: string, variantId: string): boolean {\n try {\n const key = `_snt_pv_${componentId}_${variantId}`;\n if (sessionStorage.getItem(key)) return false;\n sessionStorage.setItem(key, '1');\n return true;\n } catch {\n // Storage unavailable (private mode, quota) — keep prior behavior.\n return true;\n }\n}\n\nfunction isClickableTarget(el: EventTarget | null): boolean {\n if (!(el instanceof Element)) return false;\n const tag = el.tagName.toLowerCase();\n if (tag === 'a' || tag === 'button') return true;\n const role = el.getAttribute('role');\n return role === 'button';\n}\n\nexport function findClickable(start: Element, container: Element, selector?: string): boolean {\n if (selector) {\n try {\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (cursor.matches(selector)) return true;\n cursor = cursor.parentElement;\n }\n } catch {\n // Invalid CSS selector — treat as no match rather than breaking all click handlers.\n }\n return false;\n }\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (isClickableTarget(cursor)) return true;\n cursor = cursor.parentElement;\n }\n return false;\n}\n\nexport type GoalHandlers = {\n /** Primary goal completion. Latch-once semantics are the CALLER's job. */\n fireGoal: () => void;\n /** Weighted-composite step completion (already deduped per step here). */\n fireStep: (name: string, weight: number, stepIndex: number) => void;\n};\n\n/**\n * Attaches the goal-detection listeners `<Adaptive>`'s container uses —\n * click / form_submit / scroll_depth, composite (all-of), and\n * weighted_composite (independent steps). Returns the cleanup function.\n * Extracted from adaptive.tsx so useAdaptive / useAdaptiveTokens /\n * AdaptiveGroup wire the SAME machinery instead of duplicating it.\n */\nexport function attachGoalListeners(node: Element, goal: GoalConfig, handlers: GoalHandlers): () => void {\n // --- Weighted composite: each step fires independently as it completes ---\n if (goal.type === 'weighted_composite') {\n const firedSteps = new Set<number>();\n const wcCleanups: Array<() => void> = [];\n\n goal.steps.forEach(({ goal: sub, name: stepName, weight: stepWeight }, idx) => {\n const fireStep = (): void => {\n if (firedSteps.has(idx)) return;\n firedSteps.add(idx);\n handlers.fireStep(stepName, stepWeight, idx);\n };\n\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n fireStep();\n };\n node.addEventListener('click', onClick);\n wcCleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n fireStep();\n };\n node.addEventListener('submit', onSubmit);\n wcCleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n fireStep();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n wcCleanups.push(() => io.disconnect());\n }\n });\n\n return () => {\n for (const c of wcCleanups) c();\n };\n }\n // --- End weighted composite ---\n\n const subgoals: GoalConfig[] = goal.type === 'composite' ? goal.all : [goal];\n const remaining = new Set<number>(subgoals.map((_, i) => i));\n const checkComposite = (idx: number): void => {\n remaining.delete(idx);\n if (remaining.size === 0) handlers.fireGoal();\n };\n\n const cleanups: Array<() => void> = [];\n\n subgoals.forEach((sub, idx) => {\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('click', onClick);\n cleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('submit', onSubmit);\n cleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n cleanups.push(() => io.disconnect());\n return;\n }\n });\n\n return () => {\n for (const c of cleanups) c();\n };\n}\n\n/**\n * Records the `variant_assigned` exposure event, capturing previewHtml from\n * `container` when present (first send per browser session). Pass\n * `container: null` for surfaces with no owned DOM (token slots).\n */\nexport function trackExposure(\n client: SentientClient,\n apiKey: string,\n componentId: string,\n variantId: string,\n container: Element | null,\n): void {\n const rawHtml = container?.innerHTML ?? '';\n const includePreview = rawHtml !== '' && shouldSendPreviewHtml(componentId, variantId);\n client.track({\n projectId: apiKey,\n componentId,\n variantId,\n eventType: 'variant_assigned',\n payload: includePreview ? { previewHtml: rawHtml.slice(0, PREVIEW_HTML_MAX_CHARS) } : {},\n });\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { AssignResult } from '@sentientui/core';\nimport { useSentient, useAdaptiveApiKey, useOnAssignment, useSessionSegment } from './provider.js';\nimport { isDevBuild } from './adaptive-shared.js';\n\nexport type AdaptiveTextProps = {\n id: string;\n default: string;\n component?: keyof JSX.IntrinsicElements;\n className?: string;\n};\n\nexport function AdaptiveText({\n id,\n default: defaultText,\n component: Tag = 'span',\n className,\n}: AdaptiveTextProps) {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const onAssignment = useOnAssignment();\n const segment = useSessionSegment();\n const trackedRef = useRef<string | null>(null);\n\n // Seed from cache synchronously so remounts don't flash back to defaultText.\n const [text, setText] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.content ?? null\n );\n const [variantId, setVariantId] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.variantId ?? null\n );\n\n useEffect(() => {\n if (!client) return;\n // Skip if content already cached; assign() re-checks internally but this avoids the async round-trip on remount.\n if (client.getAssignment(id, segment)?.content !== undefined) return;\n\n let cancelled = false;\n void client.assign(id).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) {\n if (isDevBuild()) {\n console.warn(`[sentient] <AdaptiveText id=\"${id}\"> assignment failed — showing default text.`);\n }\n return;\n }\n setVariantId(result.variantId);\n if (result.content) setText(result.content);\n });\n return () => {\n cancelled = true;\n };\n }, [client, id, segment]);\n\n useEffect(() => {\n if (!client || !variantId || !apiKey) return;\n if (trackedRef.current === variantId) return;\n trackedRef.current = variantId;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n onAssignment?.(id, variantId);\n }, [client, variantId, apiKey, id, onAssignment]);\n\n return <Tag className={className}>{text ?? defaultText}</Tag>;\n}\n","import { useCallback } from 'react';\nimport type { ComponentGoalOptions } from '@sentientui/core';\nimport { useSentient } from './provider.js';\n\nexport type FireGoal = (goalType: string, opts?: ComponentGoalOptions) => void;\n\n/**\n * Returns a `fireGoal(goalType, opts?)` callback that records a conversion\n * attributed to the variant currently served for `componentId` — so it shows\n * up in the per-variant CVR funnel with no manual variantId/projectId plumbing.\n *\n * The served variant is resolved from the SDK's assignment cache (the same one\n * `<Adaptive id={componentId}>` populates), so render that component before\n * firing. Use this for imperative handlers (click, form submit, custom events);\n * for purely declarative goals prefer `<Adaptive goal={...}>`.\n *\n * @example\n * const fireContact = useAdaptiveGoal('hero_headline');\n * <button onClick={() => fireContact('hero_contact', { metadata: { method } })}>Call</button>\n */\nexport function useAdaptiveGoal(componentId: string): FireGoal {\n const client = useSentient();\n return useCallback<FireGoal>(\n (goalType, opts) => {\n client?.componentGoal(componentId, goalType, opts);\n },\n [client, componentId],\n );\n}\n","import { renderPrePaintScript } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\n\nexport type SentientPersonaScriptProps = {\n /** Publishable API key — selects the localStorage snapshot in the fallback path. */\n apiKey: string;\n /**\n * SSR-decided persona (from `loadAdaptiveDecision`). When present the\n * script embeds the literal values; when absent it reads the local\n * decision snapshot (SPA / return-visit path).\n */\n persona?: { persona: string; confidence: number } | null;\n};\n\n/** JSON string literal that is also safe inside an inline <script> element. */\nfunction inlineJsString(value: string): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\n/** Exported for tests. Builds the inline JS (concatenation only — no backticks). */\nexport function personaScriptBody(props: SentientPersonaScriptProps): string {\n if (props.persona) {\n return (\n '(function(){try{var d=document.documentElement;' +\n 'if(d.hasAttribute(\"data-sentient-persona\"))return;' +\n 'd.setAttribute(\"data-sentient-persona\",' + inlineJsString(props.persona.persona) + ');' +\n 'd.setAttribute(\"data-sentient-confidence\",' + inlineJsString(confidenceBand(props.persona.confidence)) + ');' +\n '}catch(e){}})();'\n );\n }\n return renderPrePaintScript(props.apiKey);\n}\n\n/**\n * Single writer of the Rung-1a `<html>` attributes\n * (`data-sentient-persona`, `data-sentient-confidence`), executed pre-paint.\n *\n * `AdaptiveRoot` renders this automatically as its first child. For Pages\n * Router / Remix, render it yourself in `_document` / the root layout.\n *\n * IMPORTANT (install docs): add `suppressHydrationWarning` to your `<html>`\n * element — this script mutates documentElement before React hydrates it\n * (the same pattern next-themes uses). The client SDK adopts the attributes\n * as truth and never rewrites them mid-session.\n */\nexport function SentientPersonaScript(props: SentientPersonaScriptProps): JSX.Element {\n return (\n <script\n data-sentient-persona-script=\"\"\n dangerouslySetInnerHTML={{ __html: personaScriptBody(props) }}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { validateSlotDecl } from '@sentientui/policy';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveTokensOptions = { goal?: string | GoalConfig };\nexport type UseAdaptiveTokensResult = {\n tokens: Record<string, string>;\n /** Spread on the slot's element: `data-<dim>` per dim + `data-sentient-slot`. */\n props: Record<string, string>;\n};\n\n// Warn once per slot id per page lifetime — not per render.\nconst warnedTokenSlots = new Set<string>();\n\nfunction cssEscape(value: string): string {\n return typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(value)\n : value.replace(/\"/g, '\\\\\"');\n}\n\n/**\n * Rung 1b — adaptive design tokens. Declares a bounded token space; the\n * optimizer picks per persona; values apply as element-scoped data\n * attributes so they serialize through SSR markup (zero flicker,\n * hydration-safe). First value of each dim = baseline.\n *\n * ```tsx\n * const t = useAdaptiveTokens('hero', { tone: ['calm', 'urgent'] });\n * return <section {...t.props} className=\"hero\">…</section>;\n * // CSS: .hero[data-tone=\"urgent\"] .cta { … }\n * ```\n */\nexport function useAdaptiveTokens(\n id: string,\n dims: Record<string, readonly string[]>,\n opts?: UseAdaptiveTokensOptions,\n): UseAdaptiveTokensResult {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n\n // A slot's declared space is fixed for the session (same rule as\n // <Adaptive> variants) — memoize on id only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const decl = useMemo<SlotDeclInput>(() => ({ id, dims }), [id]);\n const { result, arm } = useSlotResult(id, decl);\n const tokens = useMemo<Record<string, string>>(\n () => (typeof result === 'string' ? {} : result),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [arm],\n );\n\n if (isDevBuild() && !warnedTokenSlots.has(id)) {\n const validity = validateSlotDecl({\n id,\n dims: Object.fromEntries(Object.entries(dims).map(([k, v]) => [k, [...v]])),\n });\n const space = Object.values(dims).reduce((n, values) => n * values.length, 1);\n if (!validity.ok) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): invalid declaration — ${validity.reason}. Serving baseline.`,\n );\n } else if (space > 4) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\") declares ${space} combinations — more than the recommended 4. Each extra combination needs more traffic to learn; consider fewer dims/values.`,\n );\n }\n }\n\n const goalKey =\n opts?.goal === undefined ? null : typeof opts.goal === 'string' ? opts.goal : JSON.stringify(opts.goal);\n\n // Devtools slot registry — the declared dims space drives both persona\n // simulation and the panel's per-dim override buttons. A slot is NOT a\n // component: registering it as one produced buttons that wrote the wrong\n // override channel (`__sentient_overrides` instead of `__sentient_slot_overrides`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => registerSlot({ id, dims }), [id]);\n\n // Exposure — the slot equivalent of <Adaptive>'s variant_assigned event,\n // once per (slot, arm). variantId = canonical arm string. No container\n // (token slots own no DOM), so no previewHtml.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n if (!client || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, id, arm, null);\n }, [client, apiKey, id, arm]);\n\n // Optional goal: the returned props carry data-sentient-slot, so the slot's\n // element is findable without a ref (the pinned return type has no ref).\n // Credit flows through componentGoal(slot id) — the core resolves the\n // attributed arm from its slot state (Task 3.3 fallback).\n useEffect(() => {\n if (!client || !opts?.goal) return;\n const node = document.querySelector(`[data-sentient-slot=\"${cssEscape(id)}\"]`);\n if (!node) {\n if (isDevBuild()) {\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): a goal is declared but no element carries the returned props — spread {...props} on the slot's element.`,\n );\n }\n return;\n }\n const label = goalLabelOf(opts.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(opts.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n client.componentGoal(id, label);\n },\n fireStep: (name, weight) => {\n client.componentGoal(id, name, { reward: weight });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, id, goalKey, arm]);\n\n const props = useMemo(() => {\n const p: Record<string, string> = { 'data-sentient-slot': id };\n for (const [dim, value] of Object.entries(tokens)) p[`data-${dim}`] = value;\n return p;\n }, [id, tokens]);\n\n return { tokens, props };\n}\n","import { useEffect, useReducer, useSyncExternalStore } from 'react';\nimport { armOfResult, baselineResultFor, type SlotDeclInput, type SlotResult } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\nimport { useInitialPersona, useInitialSlots, useSentient } from './provider.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\n\ndeclare global {\n interface Window {\n /** Test/devtools forcing: slot id → forced result (applyScenario sets this). */\n __sentient_slot_overrides?: Record<string, SlotResult>;\n /** Test/devtools forcing: forced persona (applyScenario sets this). */\n __sentient_persona_override?: { persona: string; confidence?: number };\n }\n}\n\nexport type SlotResolution = {\n result: SlotResult;\n /** Canonical arm string (`dim=value|…` for dims slots, arm id for arms slots). */\n arm: string;\n source: 'override' | 'preloaded' | 'client' | 'baseline';\n};\n\n/**\n * Internal. Resolves what a slot serves this render, synchronously:\n * test/devtools override → SSR-preloaded result → core client state\n * (decide cache, snapshot seed, failure baseline) → declared baseline.\n * Purely read-side: exposure/goal wiring belongs to the calling hook.\n */\nexport function useSlotResult(slotId: string, decl: SlotDeclInput): SlotResolution {\n // Re-render when devtools writes window.__sentient_slot_overrides.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const client = useSentient();\n const initialSlots = useInitialSlots();\n const [, bump] = useReducer((n: number) => n + 1, 0);\n\n const override =\n typeof window !== 'undefined' ? window.__sentient_slot_overrides?.[slotId] : undefined;\n const preloaded = override === undefined ? initialSlots[slotId] : undefined;\n const fromClient =\n override === undefined && preloaded === undefined && client\n ? client.getSlotResult(slotId)\n : null;\n\n // Keyless local mode on a CSR-only page: nothing has decided this slot yet\n // (no SSR preload, no snapshot), so ask the local engine — zero network,\n // deterministic — and re-render when the decision lands. Keyed clients\n // never take this path: their slots decide server-side (SSR preload).\n const needsLocalDecide =\n client?.isLocal === true &&\n override === undefined &&\n preloaded === undefined &&\n fromClient === null;\n useEffect(() => {\n if (!needsLocalDecide || !client) return;\n let cancelled = false;\n void client.decide({ slots: [decl] }).then((outcome) => {\n if (!cancelled && outcome) bump();\n });\n return () => {\n cancelled = true;\n };\n // decl identity is fixed per slot id (callers memoize it on id).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slotId, needsLocalDecide]);\n\n if (override !== undefined) {\n return { result: override, arm: armOfResult(override), source: 'override' };\n }\n if (preloaded !== undefined) {\n return { result: preloaded, arm: armOfResult(preloaded), source: 'preloaded' };\n }\n if (fromClient !== null) {\n return { result: fromClient, arm: armOfResult(fromClient), source: 'client' };\n }\n const baseline = baselineResultFor(decl);\n return { result: baseline, arm: armOfResult(baseline), source: 'baseline' };\n}\n\n/**\n * Internal. Reads a forced persona: `window.__sentient_persona_override`\n * (tests/devtools) or `?sentient_persona=<PersonaKey>` (mirrors the\n * `?sentient_variant=` mechanism in use-assignment.ts).\n */\nexport function getPersonaOverride(): { persona: string; confidence: number } | null {\n if (typeof window === 'undefined') return null;\n const forced = window.__sentient_persona_override;\n if (forced?.persona) return { persona: forced.persona, confidence: forced.confidence ?? 1 };\n try {\n const value = new URLSearchParams(window.location.search).get('sentient_persona');\n if (value) return { persona: value, confidence: 1 };\n } catch {\n /* non-browser env */\n }\n return null;\n}\n\n/**\n * Internal. Current persona estimate for React consumers:\n * override → SSR initialPersona → client state (adopted attrs / snapshot / decide).\n */\nexport function useAdaptivePersona(): { persona: string; confidence: number; band: 'low' | 'medium' | 'high' } | null {\n const client = useSentient();\n const initialPersona = useInitialPersona();\n\n const override = getPersonaOverride();\n if (override) return { ...override, band: confidenceBand(override.confidence) };\n if (initialPersona) return { ...initialPersona, band: confidenceBand(initialPersona.confidence) };\n return client ? client.getPersona() : null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { attachMicroSignalDetectors, type ComponentGoalOptions } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveBind = {\n ref: (el: HTMLElement | null) => void;\n 'data-sentient-id': string;\n 'data-sentient-variant': string;\n};\n\nexport type UseAdaptiveResult<T> = {\n variant: string;\n value: T;\n /** Spread on the rendered element — wires exposure, goal listeners, and micro-signals. */\n bind: UseAdaptiveBind;\n fireGoal: (goalType?: string, opts?: ComponentGoalOptions) => void;\n};\n\nconst warnedUnbound = new Set<string>();\n\n/**\n * Rung 2 — headless, measurement-complete variant swap. Supersedes\n * `useAssignment` (which selects a variant but wires no measurement).\n *\n * `goal` is REQUIRED: without one the optimizer accumulates exposures with\n * zero rewards and cannot learn. `bind` MUST be attached to the rendered\n * element — dev mode warns loudly when a slot renders unbound.\n *\n * ```tsx\n * const { value, bind } = useAdaptive('buy-box', {\n * variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline\n * goal: 'buy_click',\n * });\n * return <div {...bind}>{value}</div>;\n * ```\n */\nexport function useAdaptive<T>(\n id: string,\n config: { variants: Record<string, T>; goal: string | GoalConfig },\n): UseAdaptiveResult<T> {\n if (isDevBuild() && !config.goal) {\n throw new Error(\n `[sentient] useAdaptive(\"${id}\"): a goal is required — without one the optimizer accumulates exposures with no rewards and cannot learn. Pass e.g. goal: 'buy_click'.`,\n );\n }\n\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Declared space is fixed per slot id for a session (same rule as <Adaptive>).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(config.variants), [id]);\n const { variantId, isOverride } = useAssignment(id, variantIds);\n const variant = variantId ?? variantIds[0] ?? '';\n const value = config.variants[variant] as T;\n\n const [node, setNode] = useState<HTMLElement | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n const ref = useCallback((el: HTMLElement | null) => {\n nodeRef.current = el;\n setNode(el);\n }, []);\n\n const goalKey = typeof config.goal === 'string' ? config.goal : JSON.stringify(config.goal);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const goal = useMemo(() => normalizeGoal(config.goal), [goalKey]);\n const goalLabel = goalLabelOf(config.goal);\n\n useEffect(() => registerComponent({ id, variantIds, goal: goalLabel }), [id, variantIds, goalLabel]);\n\n // Exposure — same variant_assigned mechanics as <Adaptive>, fired once per\n // (id, variant) and only once the bind target is in the DOM (previewHtml\n // is captured from it).\n const exposedRef = useRef<string | null>(null);\n useEffect(() => {\n // Forced variants are a dev/test view — no exposure, no goals, no\n // micro-signals may be recorded (same gate as <Adaptive>).\n if (isOverride) return;\n if (!client || !variant || !node) return;\n if (exposedRef.current === variant) return;\n exposedRef.current = variant;\n trackExposure(client, apiKey, id, variant, node);\n }, [client, apiKey, id, variant, node, isOverride]);\n\n // Goal listeners — identical machinery to <Adaptive> (shared helper).\n const goalFiredRef = useRef(false);\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variant, goalKey]);\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: id, variantId: variant }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, node, variant, apiKey, id, goal, goalLabel, isOverride]);\n\n // Micro-signal detectors — the third thing <Adaptive>'s container wires.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n },\n node,\n assignedAt,\n );\n }, [client, node, variant, apiKey, id, isOverride]);\n\n // Dev warning: bind never attached shortly after mount → exposures would\n // never fire and the slot cannot learn. Once per slot id.\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client) return;\n const timer = setTimeout(() => {\n if (!nodeRef.current && !warnedUnbound.has(id)) {\n warnedUnbound.add(id);\n console.warn(\n `[sentient] useAdaptive(\"${id}\"): bind was never attached — spread {...bind} on the rendered element, otherwise exposure and goal tracking cannot work and the optimizer learns nothing.`,\n );\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [client, id]);\n\n const fireGoal = useCallback(\n (goalType?: string, opts?: ComponentGoalOptions) => {\n if (isOverride) return; // forced variants record nothing, even manual goals\n client?.componentGoal(id, goalType ?? goalLabel, opts);\n },\n [client, id, goalLabel, isOverride],\n );\n\n const bind = useMemo<UseAdaptiveBind>(\n () => ({ ref, 'data-sentient-id': id, 'data-sentient-variant': variant }),\n [ref, id, variant],\n );\n\n return { variant, value, bind, fireGoal };\n}\n","import { Children, isValidElement, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type AdaptiveGroupProps = {\n id: string;\n /** Arrangement id → ordered child keys. FIRST key = baseline default. */\n arrangements: Record<string, string[]>;\n /** Explicit baseline arrangement id (defaults to the first declared). */\n baseline?: string;\n /** Optional slot-scoped goal — credited via componentGoal(group id). */\n goal?: string | GoalConfig;\n /** Keyed children — every key referenced by an arrangement must exist. */\n children: ReactNode;\n};\n\n// Warn once per group id per page lifetime.\nconst warnedGroups = new Set<string>();\n\n/**\n * Rung 3 — bounded mini-layout. Reorders KEYED children into the decided\n * arrangement (enumerated-arms slot: arms = Object.keys(arrangements)).\n * Declared orders only — never free permutation, never show/hide.\n * Fail-safe: unknown arrangement or key mismatch renders declaration order.\n */\nexport function AdaptiveGroup(props: AdaptiveGroupProps): JSX.Element {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Declared space is fixed per group id for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const arrangementIds = useMemo(() => Object.keys(props.arrangements), [props.id]);\n const decl = useMemo<SlotDeclInput>(\n () => ({\n id: props.id,\n arms: arrangementIds,\n ...(props.baseline !== undefined ? { baseline: props.baseline } : {}),\n }),\n [props.id, arrangementIds, props.baseline],\n );\n const { arm } = useSlotResult(props.id, decl);\n\n if (\n isDevBuild() &&\n props.baseline !== undefined &&\n props.baseline !== arrangementIds[0] &&\n !warnedGroups.has(props.id + ':baseline')\n ) {\n warnedGroups.add(props.id + ':baseline');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: baseline \"${props.baseline}\" is not the first-declared arrangement (\"${arrangementIds[0]}\"). The first arrangement should usually be the page's real incumbent (the holdout sees it).`,\n );\n }\n\n const childArray = Children.toArray(props.children).filter(isValidElement);\n const byKey = new Map<string, (typeof childArray)[number]>();\n for (const child of childArray) {\n // Children.toArray prefixes explicit keys with '.$'.\n byKey.set(String(child.key ?? '').replace(/^\\.\\$/, ''), child);\n }\n\n const order = props.arrangements[arm];\n const canReorder =\n order !== undefined &&\n order.length === childArray.length &&\n order.every((key) => byKey.has(key));\n\n if (\n isDevBuild() &&\n order !== undefined &&\n !canReorder &&\n !warnedGroups.has(props.id + ':keys')\n ) {\n warnedGroups.add(props.id + ':keys');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: arrangement \"${arm}\" [${order.join(', ')}] does not match the children's keys — rendering declaration order (fail-safe).`,\n );\n }\n\n const ordered = canReorder ? order.map((key) => byKey.get(key)!) : childArray;\n\n // Devtools slot registry — the declared arms space drives persona simulation\n // and the panel's per-arm override buttons. A group is a slot, not a component:\n // registering it as one produced buttons that wrote the wrong override channel.\n useEffect(\n () => registerSlot({ id: props.id, arms: Object.keys(props.arrangements) }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [props.id],\n );\n\n // Exposure — once per (group, arrangement); previewHtml from the container.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n if (!client || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, props.id, arm, containerRef.current);\n }, [client, apiKey, props.id, arm]);\n\n // Optional goal — slot-scoped credit through componentGoal (the core\n // resolves the attributed arm from its slot state; see Task 3.3).\n const goalKey =\n props.goal === undefined ? null : typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n useEffect(() => {\n if (!client || props.goal === undefined) return;\n const node = containerRef.current;\n if (!node) return;\n const label = goalLabelOf(props.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(props.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n client.componentGoal(props.id, label);\n },\n fireStep: (name, weight) => {\n client.componentGoal(props.id, name, { reward: weight });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, props.id, goalKey, arm]);\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={arm}>\n {ordered}\n </div>\n );\n}\n","/** @deprecated Use `useSessionSegment()` from the provider, or `deriveSessionSegment` from `@sentientui/core`. */\nexport { deriveSessionSegment as detectSegment } from '@sentientui/core';\n","/**\n * Agent-readable content feed. Merges SDK-known data (winning variants, layout\n * order) with developer-supplied page content, and renders it either as a\n * server-rendered inline JSON-LD block (read by passive AI crawlers, which do\n * not run JS) or as Markdown (for agents that content-negotiate `text/markdown`).\n *\n * No React or DOM APIs — safe to import in server components, route handlers,\n * and middleware.\n */\n\nexport type AgentBlock = {\n /** Component ID. */\n id: string;\n /** Winning variant ID currently served. */\n variant: string;\n /** Agent-readable data attached to the served variant, if any. */\n content?: unknown;\n};\n\nexport type AgentFeed = {\n page: string;\n title?: string;\n summary?: string;\n layoutOrder?: string[];\n blocks: AgentBlock[];\n /** Developer-supplied extra fields (products, specs, arbitrary JSON). */\n [key: string]: unknown;\n};\n\n/** Fields the SDK owns — developer content can never overwrite these. */\nconst RESERVED_FIELDS = ['page', 'blocks', 'layoutOrder'] as const;\n\nconst registry = new Map<string, Record<string, unknown>>();\n\n/**\n * Register page-level structured content the SDK can't infer (title, summary,\n * product fields, arbitrary JSON), keyed by page path. Call at module load.\n */\nexport function defineAgentContent(page: string, content: Record<string, unknown>): void {\n registry.set(page, content);\n}\n\n/** Look up registered content for a page. */\nexport function getAgentContent(page: string): Record<string, unknown> | undefined {\n return registry.get(page);\n}\n\n/** Clear the registry — intended for tests. */\nexport function clearAgentContent(): void {\n registry.clear();\n}\n\n/**\n * Merge SDK-known data with developer-supplied content into a single feed.\n * Developer content fills in title/summary/etc. but can never overwrite the\n * SDK-authoritative fields (`page`, `blocks`, `layoutOrder`).\n */\nexport function buildAgentFeed(input: {\n page: string;\n blocks: AgentBlock[];\n layoutOrder?: string[];\n content?: Record<string, unknown>;\n}): AgentFeed {\n const supplied = input.content ?? getAgentContent(input.page) ?? {};\n const safe: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(supplied)) {\n if (!(RESERVED_FIELDS as readonly string[]).includes(k)) safe[k] = v;\n }\n const feed: AgentFeed = {\n ...safe,\n page: input.page,\n blocks: input.blocks,\n };\n if (input.layoutOrder) feed.layoutOrder = input.layoutOrder;\n return feed;\n}\n\n/**\n * Render the feed as a server-rendered inline JSON-LD `<script>` string. `<` is\n * escaped to `<` so embedded content cannot break out of the script\n * element. MUST be emitted on the server — passive crawlers never run client JS.\n */\nexport function renderAgentJsonLd(feed: AgentFeed): string {\n return `<script type=\"application/ld+json\">${renderAgentJsonLdBody(feed)}</script>`;\n}\n\n/**\n * The escaped JSON-LD body only (no `<script>` wrapper). For React server\n * components, inject via `<script type=\"application/ld+json\"\n * dangerouslySetInnerHTML={{ __html: renderAgentJsonLdBody(feed) }} />`.\n */\nexport function renderAgentJsonLdBody(feed: AgentFeed): string {\n return JSON.stringify({ '@context': 'https://schema.org', '@type': 'WebPage', ...feed })\n .replace(/</g, '\\\\u003c');\n}\n\n/** Render the feed as Markdown for agents that negotiate `text/markdown`. */\nexport function renderAgentMarkdown(feed: AgentFeed): string {\n const lines: string[] = [];\n if (feed.title) lines.push(`# ${feed.title}`, '');\n if (feed.summary) lines.push(String(feed.summary), '');\n\n for (const [k, v] of Object.entries(feed)) {\n if (['page', 'title', 'summary', 'blocks', 'layoutOrder'].includes(k)) continue;\n lines.push(`## ${k}`, '', '```json', JSON.stringify(v, null, 2), '```', '');\n }\n\n if (feed.blocks.length > 0) {\n lines.push('## blocks', '');\n for (const b of feed.blocks) {\n lines.push(`- **${b.id}** → variant \\`${b.variant}\\``);\n if (b.content !== undefined) {\n lines.push('', ' ```json', JSON.stringify(b.content, null, 2), ' ```');\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n').trimEnd() + '\\n';\n}\n"],"mappings":"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","names":["createContext","useContext","useEffect","useMemo","useState","useSyncExternalStore","detectDeviceClass","detectTrafficSource","init","store","listeners","subscribe","componentId","cb","set","update","weights","e","getWeights","_a","ssrFallback","state","w","getPreviewMode","state","subscribePreview","fn","listeners","createPreviewClient","inner","componentId","segment","variantIds","agentData","agentDataByVariant","slotId","EVENT","getOverridesVersion","_a","subscribeOverridesChanged","fn","EVENT","publishDevtoolsConfig","config","ssrFallback","state","w","emit","fn","registerComponent","c","registerSlot","s","registerSections","sections","jsx","deriveDefaultSegment","_a","_b","device","detectDeviceClass","source","detectTrafficSource","e","DEFAULT_API_BASE_URL","AdaptiveContext","createContext","AdaptiveProvider","props","client","setClient","useState","sessionSegment","previewOn","setPreviewOn","getPreviewMode","useEffect","subscribePreview","prev","config","cancelled","created","initGraph","__spreadProps","__spreadValues","init","poll","entries","entry","weights","v","update","timerId","ssrFallback","apiBaseUrl","publishDevtoolsConfig","registerSections","exposedClient","useMemo","createPreviewClient","value","_c","_d","useSentient","useContext","useAdaptiveApiKey","useInitialAssignments","useContext","AdaptiveContext","useSessionSegment","useSsrFallback","useOnAssignment","useLayoutOrder","contextOrder","override","useSyncExternalStore","subscribeOverridesChanged","_a","useInitialSlots","useAdaptiveApiBaseUrl","useContext","AdaptiveContext","memo","useEffect","useMemo","useRef","useState","attachMicroSignalDetectors","useEffect","useRef","useState","useSyncExternalStore","getDevOverride","componentId","_a","global","params","raw","sep","e","pickFromWeights","weights","variantIds","best","v","useAssignment","agentData","agentDataByVariant","initialAssignments","useInitialAssignments","ssrFallback","useSsrFallback","client","useSentient","segment","useSessionSegment","onAssignment","useOnAssignment","assignmentReportedRef","useRef","useSyncExternalStore","subscribeOverridesChanged","getOverridesVersion","devOverride","overrideVariant","overrideLoggedRef","initial","_b","preloaded","cached","getWeights","chosen","state","setState","useState","reportAssignment","variantId","useEffect","prev","cancelled","result","subscribe","isDevBuild","_a","normalizeGoal","goal","goalLabelOf","PREVIEW_HTML_MAX_CHARS","shouldSendPreviewHtml","componentId","variantId","key","e","isClickableTarget","el","tag","findClickable","start","container","selector","cursor","attachGoalListeners","node","handlers","firedSteps","wcCleanups","sub","stepName","stepWeight","idx","fireStep","onClick","target","onSubmit","threshold","io","entries","entry","subgoals","remaining","_","i","checkComposite","cleanups","c","trackExposure","client","apiKey","rawHtml","includePreview","jsx","AdaptiveImpl","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","variantIds","useMemo","variantId","content","isOverride","useAssignment","containerRef","useRef","mounted","setMounted","useState","useEffect","goalFiredRef","microGoalFiredRef","assignTrackedRef","goalKey","goal","normalizeGoal","goalLabel","registerComponent","_b","trackExposure","node","timerId","hoverStart","onEnter","onLeave","assignedAt","attachMicroSignalDetectors","signalType","extra","_c","__spreadValues","mapping","name","weight","stepIndex","attachGoalListeners","jsxContent","managedContent","isDevBuild","Adaptive","memo","prev","next","prevKeys","nextKeys","k","useEffect","useRef","useState","jsx","AdaptiveText","id","defaultText","Tag","className","client","useSentient","apiKey","useAdaptiveApiKey","onAssignment","useOnAssignment","segment","useSessionSegment","trackedRef","useRef","text","setText","useState","_a","_b","variantId","setVariantId","useEffect","cancelled","result","isDevBuild","useCallback","useAdaptiveGoal","componentId","client","useSentient","useCallback","goalType","opts","renderPrePaintScript","confidenceBand","jsx","inlineJsString","value","personaScriptBody","props","SentientPersonaScript","useEffect","useMemo","useRef","validateSlotDecl","useEffect","useReducer","useSyncExternalStore","armOfResult","baselineResultFor","confidenceBand","useSlotResult","slotId","decl","_a","useSyncExternalStore","subscribeOverridesChanged","getOverridesVersion","client","useSentient","initialSlots","useInitialSlots","bump","useReducer","n","override","preloaded","fromClient","needsLocalDecide","useEffect","cancelled","outcome","armOfResult","baseline","baselineResultFor","warnedTokenSlots","cssEscape","value","useAdaptiveTokens","id","dims","opts","client","useSentient","apiKey","useAdaptiveApiKey","decl","useMemo","result","arm","useSlotResult","tokens","isDevBuild","validity","validateSlotDecl","k","v","space","n","values","goalKey","useEffect","registerSlot","exposedArmRef","useRef","trackExposure","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","props","p","dim","useCallback","useEffect","useMemo","useRef","useState","attachMicroSignalDetectors","warnedUnbound","useAdaptive","id","config","_a","isDevBuild","client","useSentient","apiKey","useAdaptiveApiKey","variantIds","useMemo","variantId","isOverride","useAssignment","variant","value","node","setNode","useState","nodeRef","useRef","ref","useCallback","el","goalKey","goal","normalizeGoal","goalLabel","goalLabelOf","useEffect","registerComponent","exposedRef","trackExposure","goalFiredRef","attachGoalListeners","name","weight","stepIndex","assignedAt","attachMicroSignalDetectors","signalType","extra","__spreadValues","timer","fireGoal","goalType","opts","bind","Children","isValidElement","useEffect","useMemo","useRef","jsx","warnedGroups","AdaptiveGroup","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","containerRef","useRef","arrangementIds","useMemo","decl","__spreadValues","arm","useSlotResult","isDevBuild","childArray","Children","isValidElement","byKey","child","order","canReorder","key","ordered","useEffect","registerSlot","exposedArmRef","trackExposure","goalKey","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","deriveSessionSegment","RESERVED_FIELDS","registry","defineAgentContent","page","content","getAgentContent","buildAgentFeed","input","_a","_b","supplied","getAgentContent","safe","k","v","RESERVED_FIELDS","feed","__spreadProps","__spreadValues","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","lines","b"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/weights-store.ts","../src/preview-mode.ts","../src/override-events.ts","../src/devtools-config.ts","../src/devtools-registry.ts","../src/adaptive.tsx","../src/use-assignment.ts","../src/adaptive-shared.ts","../src/adaptive-text.tsx","../src/use-adaptive-goal.ts","../src/persona-script.tsx","../src/use-adaptive-tokens.ts","../src/use-slot-result.ts","../src/use-adaptive.ts","../src/adaptive-group.tsx","../src/segment.ts","../src/agent-feed.ts"],"sourcesContent":["'use client';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport {\n detectDeviceClass,\n detectTrafficSource,\n init,\n type SentientClient,\n type SentientConfig,\n type SlotResult,\n} from '@sentientui/core';\nimport { update as updateWeightsStore, type ComponentWeights } from './weights-store.js';\nimport { getPreviewMode, subscribePreview, createPreviewClient } from './preview-mode.js';\nimport { subscribeOverridesChanged } from './override-events.js';\nimport { publishDevtoolsConfig } from './devtools-config.js';\nimport { registerSections } from './devtools-registry.js';\n\n/**\n * Mirrors the segment derivation inside core `init()` so the cache key used\n * by `useAssignment` always matches the key `assign()` writes under. Before\n * this, the context defaulted to 'desktop:direct' while core used the\n * detected segment — a systematic cache miss for every integration that\n * didn't pass `sessionSegment` explicitly.\n */\nfunction deriveDefaultSegment(): string {\n if (typeof window === 'undefined') return 'desktop:direct';\n try {\n const device = detectDeviceClass(navigator.userAgent ?? '');\n const source = detectTrafficSource(document.referrer ?? '', window.location.origin);\n return `${device}:${source}`;\n } catch {\n return 'desktop:direct';\n }\n}\n\nconst DEFAULT_API_BASE_URL = 'https://api.sentient-ui.com/v1';\n\n/** How to render adaptive slots during SSR when assignments are not preloaded. */\nexport type SsrFallback = 'first' | 'none';\n\ntype AdaptiveContextValue = {\n client: SentientClient | null;\n // The publishable API key (pk_…). Historically named `projectId` because the\n // API uses it as the project identifier on the wire, but it is the API key,\n // not the project UUID. Field renamed for clarity.\n apiKey: string;\n initialAssignments: Record<string, string>;\n sessionSegment: string;\n ssrFallback: SsrFallback;\n onAssignment: ((componentId: string, variantId: string) => void) | undefined;\n initialLayoutOrder: string[] | null;\n initialSlots: Record<string, SlotResult>;\n initialPersona: { persona: string; confidence: number } | null;\n apiBaseUrl: string;\n};\n\nconst AdaptiveContext = createContext<AdaptiveContextValue>({\n client: null,\n apiKey: '',\n initialAssignments: {},\n sessionSegment: 'desktop:direct',\n ssrFallback: 'first',\n onAssignment: undefined,\n initialLayoutOrder: null,\n initialSlots: {},\n initialPersona: null,\n apiBaseUrl: DEFAULT_API_BASE_URL,\n});\n\nexport type AdaptiveProviderProps = {\n apiKey: string;\n context: SentientConfig['context'];\n debug?: boolean;\n /**\n * SSR-preloaded assignments from `preloadAssignments()` / `loadAdaptiveAssignments()`.\n * Passed through to `useAssignment` as synchronous initial state so crawlers and\n * the first paint see real content (recommended for SEO).\n */\n initialAssignments?: Record<string, string>;\n /**\n * Bandit segment from SSR (`device:source`). Keeps cache, assign, and worker\n * weights on one row — must match `loadAdaptiveAssignments` / session upsert.\n */\n sessionSegment?: string;\n /**\n * When no `initialAssignments` exist for a component, `'first'` renders\n * `variantIds[0]` in server HTML (safe default for SEO). Use `'none'` only for\n * decorative slots marked `clientOnly`.\n * @default 'first'\n */\n ssrFallback?: SsrFallback;\n /**\n * Consent gate. When `false` the SDK is not initialised and no events are\n * sent. Flip to `true` (e.g. after the user accepts the cookie banner) to\n * initialise and begin tracking.\n */\n consent?: boolean;\n /**\n * Behavior before consent is granted. Pass `'statistical_winner'` to serve the\n * best-performing variant via `GET /v1/winner` with zero tracking while the\n * consent banner is showing. Requires `consent: false`.\n * @see SentientConfig.preConsentBehavior\n */\n preConsentBehavior?: 'statistical_winner' | 'control';\n /**\n * Honor the browser's Do Not Track signal. Defaults to `true`: when DNT is\n * enabled the SDK sets no cookies and sends no tracking data (overriding\n * `consent: true`). Set `false` to make your own consent gate authoritative.\n * @see SentientConfig.respectDoNotTrack\n */\n respectDoNotTrack?: boolean;\n /**\n * Called once per component the first time a variant is resolved for that\n * component in this session. Use to forward assignments to your own analytics\n * (Mixpanel, PostHog, Segment, etc.) without having to wrap `useAssignment`.\n */\n onAssignment?: (componentId: string, variantId: string) => void;\n /**\n * SSR-preloaded section order from `loadAdaptiveDecision()`.\n * Pass the `layoutOrder` field from `DecideResult`. When set,\n * `useLayoutOrder()` returns this on first render so there is no layout shift.\n */\n initialLayoutOrder?: string[] | null;\n /**\n * SSR-preloaded slot results from `loadAdaptiveDecision()` (the `slots`\n * field of its result). Guarantees `useAdaptiveTokens`/`AdaptiveGroup`\n * render the decided arm in server HTML — zero flicker, hydration-safe.\n */\n initialSlots?: Record<string, SlotResult>;\n /**\n * Persona decided during SSR (`persona` + `confidence` fields of\n * `loadAdaptiveDecision()`'s result). Adopted by the core client;\n * rendered into html attributes only by `SentientPersonaScript`.\n */\n initialPersona?: { persona: string; confidence: number };\n /**\n * Base URL of the Sentient API (no trailing slash). Read by the devtools\n * panel for /v1/explain and by future client helpers. Defaults to the\n * hosted API.\n */\n apiBaseUrl?: string;\n /**\n * Session ID generated during SSR (the `sessionId` field returned by\n * `loadAdaptiveAssignments` / `loadAdaptiveDecision`). When provided and no\n * existing session cookie or localStorage entry is found, the client adopts\n * this ID so events and goals are attributed to the same session the server\n * used for variant assignment.\n */\n ssrSessionId?: string;\n /**\n * ISO 3166-1 alpha-2 country code. Pass the value of the `CF-IPCountry`\n * header from your Next.js server component to populate country on landing\n * sessions without client-side geo lookup.\n */\n country?: string;\n /**\n * Keyless local mode. 'auto' (default) simulates decisions on-device in\n * development builds when no valid API key is configured; `true` forces the\n * local engine; `false` restores the silent keyless no-op.\n * @see SentientConfig.localMode\n */\n localMode?: 'auto' | boolean;\n /**\n * Enable DOM graph scanning + page-structure sync. When `true`, the provider\n * dynamically loads `@sentientui/core/graph` and uses its graph-capable\n * `init()` for the single client, so the SDK scans your page structure and\n * syncs it to power the dashboard graph page. Left off (default), the lean\n * bundle is used and the graph entry is never loaded.\n */\n enableGraph?: boolean;\n children: ReactNode;\n};\n\n/**\n * Initialises the Sentient core SDK in a useEffect (SSR-safe) and exposes the\n * client via React context. Re-initialises when `consent` changes.\n */\nexport function AdaptiveProvider(props: AdaptiveProviderProps): JSX.Element {\n const [client, setClient] = useState<SentientClient | null>(null);\n // Derived once per mount: identical to what core init() computes, so cache\n // reads (context segment) and cache writes (core segment) always agree.\n const [sessionSegment] = useState(() => props.sessionSegment ?? deriveDefaultSegment());\n // Devtools preview: when on, expose an event-suppressing client so previewing\n // variants/personas writes nothing. Off by default (inert in production).\n const [previewOn, setPreviewOn] = useState(getPreviewMode());\n useEffect(() => subscribePreview(() => setPreviewOn(getPreviewMode())), []);\n\n useEffect(() => {\n // When consent is explicitly false with no preConsentBehavior, tear down any existing client.\n if (props.consent === false && !props.preConsentBehavior) {\n setClient((prev: SentientClient | null) => {\n prev?.destroy();\n return null;\n });\n return;\n }\n\n const config = {\n apiKey: props.apiKey,\n context: props.context,\n debug: props.debug,\n initialAssignments: props.initialAssignments,\n sessionSegment,\n consent: props.consent,\n preConsentBehavior: props.preConsentBehavior,\n respectDoNotTrack: props.respectDoNotTrack,\n ssrSessionId: props.ssrSessionId,\n country: props.country,\n localMode: props.localMode,\n initialSlots: props.initialSlots,\n initialPersona: props.initialPersona,\n ingestUrl: props.apiBaseUrl ? `${props.apiBaseUrl.replace(/\\/$/, '')}/events` : undefined,\n };\n\n // Track the client created by this effect run so cleanup destroys exactly\n // the right one, and so a late-resolving dynamic import can bail if the\n // effect was already torn down (unmount / consent change).\n let cancelled = false;\n let created: SentientClient | null = null;\n\n if (props.enableGraph) {\n // Load the graph entry only when asked — keeps the DOM scanner out of the\n // lean bundle. The provider still creates ONE client (graph-capable).\n void import('@sentientui/core/graph').then(({ init: initGraph }) => {\n if (cancelled) return;\n created = initGraph({ ...config, graph: true });\n setClient(created);\n });\n } else {\n created = init(config);\n setClient(created);\n }\n\n return () => {\n cancelled = true;\n // dispose, not destroy: effect cleanup runs on unmount, StrictMode's\n // dev double-invoke, and consent re-init — the visitor identity must\n // survive all of those. Full destroy() happens only on the explicit\n // consent-revocation branch above.\n created?.dispose();\n };\n // Re-init when consent changes. Other props (incl. enableGraph) are\n // intentionally stable for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [props.consent]);\n\n // Poll /v1/weights every 60 s so long-lived sessions see updated bandit weights\n // without a page reload. useAssignment subscribers react via weights-store.\n useEffect(() => {\n if (!client) return;\n let cancelled = false;\n const poll = async (): Promise<void> => {\n if (cancelled) return;\n let entries;\n try {\n entries = await client.fetchWeights();\n } catch {\n // Network/transient error: skip this cycle and retry on the next\n // interval. Swallowed deliberately so a failed poll never surfaces as\n // an unhandled rejection.\n return;\n }\n if (cancelled) return;\n for (const entry of entries) {\n const weights: ComponentWeights = {\n componentId: entry.componentId,\n updatedAt: entry.updatedAt,\n variants: entry.variants.map((v) => ({\n variantId: v.variantId,\n pulls: v.pulls,\n avgReward: v.avgReward ?? 0,\n })),\n };\n updateWeightsStore(entry.componentId, weights);\n }\n };\n void poll();\n const timerId = setInterval(() => void poll(), 60_000);\n return () => {\n cancelled = true;\n clearInterval(timerId);\n };\n }, [client]);\n\n const ssrFallback = props.ssrFallback ?? 'first';\n const apiBaseUrl = props.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n\n // Publish devtools config through window: the /devtools entry is a separate\n // bundle and cannot read this provider's context instance. Dev-only.\n useEffect(() => {\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n publishDevtoolsConfig({\n apiKey: props.apiKey,\n apiBaseUrl,\n isLocal: client?.isLocal === true,\n });\n }, [client, props.apiKey, apiBaseUrl]);\n\n // Sections registry for devtools /v1/explain + local simulation.\n useEffect(() => {\n if (props.initialLayoutOrder && props.initialLayoutOrder.length > 0) {\n registerSections(props.initialLayoutOrder);\n }\n }, [props.initialLayoutOrder]);\n\n // The client exposed to consumers — wrapped to suppress events while previewing.\n const exposedClient = useMemo(\n () => (client && previewOn ? createPreviewClient(client) : client),\n [client, previewOn],\n );\n\n // Memoized so unrelated parent re-renders don't cascade through every\n // useSentient / useAssignment consumer via a fresh context object.\n const value = useMemo<AdaptiveContextValue>(\n () => ({\n client: exposedClient,\n apiKey: props.apiKey,\n initialAssignments: props.initialAssignments ?? {},\n sessionSegment,\n ssrFallback,\n onAssignment: props.onAssignment,\n initialLayoutOrder: props.initialLayoutOrder ?? null,\n initialSlots: props.initialSlots ?? {},\n initialPersona: props.initialPersona ?? null,\n apiBaseUrl,\n }),\n [\n exposedClient,\n props.apiKey,\n props.initialAssignments,\n sessionSegment,\n ssrFallback,\n props.onAssignment,\n props.initialLayoutOrder,\n props.initialSlots,\n props.initialPersona,\n apiBaseUrl,\n ],\n );\n\n return (\n <AdaptiveContext.Provider value={value}>\n {props.children}\n </AdaptiveContext.Provider>\n );\n}\n\n/**\n * Returns the SentientClient, or null until the provider has finished\n * initialising on the client.\n */\nexport function useSentient(): SentientClient | null {\n return useContext(AdaptiveContext).client;\n}\n\n/** Internal: publishable API key carried alongside the client. */\nexport function useAdaptiveApiKey(): string {\n return useContext(AdaptiveContext).apiKey;\n}\n\n/**\n * @deprecated Renamed to `useAdaptiveApiKey`. Kept as an alias so external\n * imports from earlier versions of this package keep working. Will be removed\n * in 1.0.0.\n */\nlet warnedProjectIdAlias = false;\nexport function useAdaptiveProjectId(): string {\n if (\n !warnedProjectIdAlias &&\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV !== 'production'\n ) {\n warnedProjectIdAlias = true;\n console.warn(\n '[@sentientui/react] useAdaptiveProjectId is deprecated; use useAdaptiveApiKey. Will be removed in 1.0.0.',\n );\n }\n return useAdaptiveApiKey();\n}\n\n/** Internal: SSR-preloaded assignments for hydration-safe first render. */\nexport function useInitialAssignments(): Record<string, string> {\n return useContext(AdaptiveContext).initialAssignments;\n}\n\n/** Internal: bandit segment aligned with SSR session upsert. */\nexport function useSessionSegment(): string {\n return useContext(AdaptiveContext).sessionSegment;\n}\n\n/** Internal: SSR fallback strategy when a slot has no preloaded assignment. */\nexport function useSsrFallback(): SsrFallback {\n return useContext(AdaptiveContext).ssrFallback;\n}\n\n/** Internal: forwarding hook for consumer analytics integration. */\nexport function useOnAssignment(): ((componentId: string, variantId: string) => void) | undefined {\n return useContext(AdaptiveContext).onAssignment;\n}\n\n/**\n * Returns the persona-specific section order from SSR, or null when no\n * sections were declared on AdaptiveRoot or reliability is below threshold.\n * Devtools/testing can force it via `window.__sentient_layout_override`;\n * consumers re-render when the devtools notifies an override change.\n */\nexport function useLayoutOrder(): string[] | null {\n const contextOrder = useContext(AdaptiveContext).initialLayoutOrder;\n const override = useSyncExternalStore(\n subscribeOverridesChanged,\n () =>\n typeof window === 'undefined'\n ? null\n : ((window as unknown as { __sentient_layout_override?: string[] })\n .__sentient_layout_override ?? null),\n () => null,\n );\n return override ?? contextOrder;\n}\n\n/** Internal: SSR-preloaded slot results for hydration-safe first render. */\nexport function useInitialSlots(): Record<string, SlotResult> {\n return useContext(AdaptiveContext).initialSlots;\n}\n\n/** Internal: SSR-decided persona carried alongside the client. */\nexport function useInitialPersona(): { persona: string; confidence: number } | null {\n return useContext(AdaptiveContext).initialPersona;\n}\n\n/** Internal: configured API base URL (devtools fetches /v1/explain against this, never a relative URL). */\nexport function useAdaptiveApiBaseUrl(): string {\n return useContext(AdaptiveContext).apiBaseUrl;\n}\n","/** Per-component weights store with isolated subscriptions. */\n\nexport type VariantWeight = {\n variantId: string;\n pulls: number;\n avgReward: number;\n};\n\nexport type ComponentWeights = {\n componentId: string;\n variants: VariantWeight[];\n updatedAt: number;\n};\n\ntype Listener = (weights: ComponentWeights) => void;\n\nconst store = new Map<string, ComponentWeights>();\nconst listeners = new Map<string, Set<Listener>>();\n\n/**\n * Subscribes a listener to a single component. Returns an unsubscribe function.\n * Updates to other components never trigger this listener.\n */\nexport function subscribe(componentId: string, cb: Listener): () => void {\n let set = listeners.get(componentId);\n if (!set) {\n set = new Set();\n listeners.set(componentId, set);\n }\n set.add(cb);\n return () => {\n set!.delete(cb);\n if (set!.size === 0) listeners.delete(componentId);\n };\n}\n\n/**\n * Replaces the weights for a component and notifies only that component's\n * subscribers.\n */\nexport function update(componentId: string, weights: ComponentWeights): void {\n store.set(componentId, weights);\n const set = listeners.get(componentId);\n if (!set) return;\n for (const cb of set) {\n try {\n cb(weights);\n } catch {\n /* never throw to other listeners */\n }\n }\n}\n\n/**\n * Returns the latest known weights for a component, or null if none seen.\n */\nexport function getWeights(componentId: string): ComponentWeights | null {\n return store.get(componentId) ?? null;\n}\n\n/** Test-only: wipe the entire store. */\nexport function _resetWeightsStore(): void {\n store.clear();\n listeners.clear();\n}\n","import type { SentientClient } from '@sentientui/core';\n\ntype PreviewState = { on: boolean; listeners: Set<() => void> };\nconst ssrFallback: PreviewState = { on: false, listeners: new Set() };\n\n// Window-backed: the /devtools entry (a separate bundle) toggles preview mode\n// and the provider (main bundle) must observe it.\nfunction state(): PreviewState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_preview?: PreviewState };\n if (!w.__sentient_preview) w.__sentient_preview = { on: false, listeners: new Set() };\n return w.__sentient_preview;\n}\n\nexport function setPreviewMode(on: boolean): void {\n const s = state();\n if (s.on === on) return;\n s.on = on;\n for (const fn of s.listeners) fn();\n}\n\nexport function getPreviewMode(): boolean {\n return state().on;\n}\n\nexport function subscribePreview(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/**\n * Wraps a client so it writes nothing: reads pass through, all emitters no-op.\n * Used while previewing variants/personas so no `variant_assigned`, goal, or\n * session events are sent.\n */\nexport function createPreviewClient(inner: SentientClient): SentientClient {\n return {\n isLocal: inner.isLocal,\n track: () => undefined,\n goal: () => undefined,\n componentGoal: () => undefined,\n identify: () => undefined,\n fetchWeights: () => Promise.resolve([]),\n getAssignment: (componentId, segment) => inner.getAssignment(componentId, segment),\n assign: (componentId, variantIds, agentData, agentDataByVariant) =>\n inner.assign(componentId, variantIds, agentData, agentDataByVariant),\n // Reads pass through; decide is a write (slot decisions persist server-side)\n // so preview mode never issues it.\n decide: () => Promise.resolve(null),\n getSlotResult: (slotId) => inner.getSlotResult(slotId),\n getPersona: () => inner.getPersona(),\n getGraph: () => inner.getGraph(),\n dispose: () => inner.dispose(),\n destroy: () => inner.destroy(),\n };\n}\n","/**\n * Cross-bundle re-render bus for devtools overrides. The main entry and the\n * /devtools entry are separate bundles, so state and notifications go through\n * window (a version counter + a DOM event) — never module-local state.\n */\nconst EVENT = 'sentient:overrides-changed';\n\ntype VersionWindow = Window & { __sentient_overrides_version?: number };\n\nexport function getOverridesVersion(): number {\n if (typeof window === 'undefined') return 0;\n return (window as VersionWindow).__sentient_overrides_version ?? 0;\n}\n\nexport function notifyOverridesChanged(): void {\n if (typeof window === 'undefined') return;\n const w = window as VersionWindow;\n w.__sentient_overrides_version = (w.__sentient_overrides_version ?? 0) + 1;\n window.dispatchEvent(new Event(EVENT));\n}\n\nexport function subscribeOverridesChanged(fn: () => void): () => void {\n if (typeof window === 'undefined') return () => undefined;\n window.addEventListener(EVENT, fn);\n return () => window.removeEventListener(EVENT, fn);\n}\n","/** Provider → devtools config handoff. Window-backed: the /devtools entry is a\n * separate bundle and cannot share the provider's React context instance. */\nexport type DevtoolsConfig = {\n apiKey: string;\n apiBaseUrl: string;\n isLocal: boolean;\n};\n\ntype ConfigWindow = Window & { __sentient_devtools_config?: DevtoolsConfig };\n\nexport function publishDevtoolsConfig(config: DevtoolsConfig): void {\n if (typeof window === 'undefined') return;\n (window as ConfigWindow).__sentient_devtools_config = config;\n}\n\nexport function readDevtoolsConfig(): DevtoolsConfig | null {\n if (typeof window === 'undefined') return null;\n return (window as ConfigWindow).__sentient_devtools_config ?? null;\n}\n","export type RegisteredComponent = { id: string; variantIds: string[]; goal?: string };\nexport type RegisteredSlot = {\n id: string;\n arms?: string[];\n dims?: Record<string, readonly string[]>;\n};\n\ntype RegistryState = {\n components: Map<string, RegisteredComponent>;\n slots: Map<string, RegisteredSlot>;\n sections: string[];\n listeners: Set<() => void>;\n /** Bumped on every mutation so `useSyncExternalStore` can read a stable, comparable snapshot. */\n version: number;\n};\n\n// Shared through a window global: the main entry and the /devtools entry are\n// separate bundles, each with its own copy of this module — module-local\n// state would give the devtools an always-empty registry in published apps.\nconst ssrFallback: RegistryState = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n};\n\nfunction state(): RegistryState {\n if (typeof window === 'undefined') return ssrFallback;\n const w = window as unknown as { __sentient_registry?: RegistryState };\n if (!w.__sentient_registry) {\n w.__sentient_registry = {\n components: new Map(),\n slots: new Map(),\n sections: [],\n listeners: new Set(),\n version: 0,\n };\n }\n return w.__sentient_registry;\n}\n\nfunction emit(): void {\n // Bump BEFORE notifying so a useSyncExternalStore consumer re-reading its\n // snapshot inside the notification sees the new value and re-renders.\n state().version += 1;\n for (const fn of state().listeners) fn();\n}\n\n/** Register (or re-register) a component. Returns an unregister function. */\nexport function registerComponent(c: RegisteredComponent): () => void {\n state().components.set(c.id, c);\n emit();\n return () => {\n state().components.delete(c.id);\n emit();\n };\n}\n\n/** Register (or re-register) a slot declaration. Returns an unregister function. */\nexport function registerSlot(s: RegisteredSlot): () => void {\n state().slots.set(s.id, s);\n emit();\n return () => {\n state().slots.delete(s.id);\n emit();\n };\n}\n\n/** Register the page's declared section ids (from AdaptiveRoot/provider). */\nexport function registerSections(sections: string[]): void {\n state().sections = [...sections];\n emit();\n}\n\nexport function getRegistered(): RegisteredComponent[] {\n return [...state().components.values()];\n}\n\nexport function getRegisteredSlots(): RegisteredSlot[] {\n return [...state().slots.values()];\n}\n\nexport function getRegisteredSections(): string[] {\n return [...state().sections];\n}\n\nexport function subscribeRegistry(fn: () => void): () => void {\n const listeners = state().listeners;\n listeners.add(fn);\n return () => {\n listeners.delete(fn);\n };\n}\n\n/** Monotonic snapshot for `useSyncExternalStore` — changes on every registry mutation. */\nexport function getRegistryVersion(): number {\n return state().version;\n}\n","'use client';\n\nimport { memo, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { attachMicroSignalDetectors, type MicroSignalType } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\n\nexport type {\n ScrollDepthGoal,\n ClickGoal,\n FormSubmitGoal,\n CompositeGoal,\n WeightedStep,\n WeightedCompositeGoal,\n GoalConfig,\n} from './adaptive-shared.js';\nimport { attachGoalListeners, isDevBuild, normalizeGoal, trackExposure, type GoalConfig } from './adaptive-shared.js';\n\n/** Maps a detected micro-signal to a named session goal (`client.goal`). */\nexport type MicroSignalGoalConfig = string | { name: string; weight?: number; stepIndex?: number };\nexport type MicroSignalGoals = Partial<Record<MicroSignalType, MicroSignalGoalConfig>>;\n\nexport type AdaptiveProps = {\n id: string;\n variants: Record<string, ReactNode>;\n goal: string | GoalConfig;\n /**\n * When a passive micro-signal fires on this component, also record a named goal.\n * Use for inferred goals surfaced in the dashboard (e.g. rage_click → 'confused_by_hero').\n */\n microSignalGoals?: MicroSignalGoals;\n /**\n * When true, renders nothing during SSR and before client hydration.\n * Use when you cannot pass `initialAssignments` and prefer a blank slot over\n * a hydration mismatch. Tradeoff: minor CLS on first paint.\n */\n clientOnly?: boolean;\n /**\n * Variant-specific structured data for AI agent consumption via /sentient.json and\n * GET /v1/agent/layout. Keyed by variant ID — only the assigned variant's entry is stored,\n * so agents see only the content currently being served to visitors.\n *\n * Prefer this over `agentData` when variants have meaningfully different content.\n */\n agentDataByVariant?: Record<string, unknown>;\n /** @deprecated Use agentDataByVariant for variant-specific content. Stored as-is for the assigned variant. */\n agentData?: unknown;\n};\n\nfunction AdaptiveImpl(props: AdaptiveProps): JSX.Element | null {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const variantIds = useMemo(() => Object.keys(props.variants), [props.variants]);\n const { variantId, content, isOverride } = useAssignment(props.id, variantIds, props.agentData, props.agentDataByVariant);\n const containerRef = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => { setMounted(true); }, []);\n const goalFiredRef = useRef(false);\n const microGoalFiredRef = useRef<Set<MicroSignalType>>(new Set());\n const assignTrackedRef = useRef<string | null>(null);\n const goalKey = typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n const goal = useMemo(() => normalizeGoal(props.goal), [goalKey]);\n const goalLabel = typeof props.goal === 'string' ? props.goal : goal.type;\n\n // Register with the devtools registry so the dev widget can list this\n // component + its variants. Inert in production (registry has no UI); the\n // cleanup unregisters on unmount.\n useEffect(() => registerComponent({ id: props.id, variantIds, goal: goalLabel }), [props.id, variantIds, goalLabel]);\n\n // Track variant_assigned exactly once per (component, variant) mount.\n // Captures innerHTML as previewHtml so the dashboard can render a live preview\n // without requiring manual registry calls. First-seen wins on the server.\n // `mounted` is in deps so the effect re-runs after clientOnly components hydrate\n // and their container div is actually in the DOM.\n useEffect(() => {\n // A forced variant is a dev/test view, not a real exposure — recording it\n // would train the bandit on the override. Same gate on every tracking\n // effect below (\"no events recorded, weights unchanged\").\n if (isOverride) return;\n if (!client || !variantId || !apiKey) return;\n if (assignTrackedRef.current === variantId) return;\n const rawHtml = containerRef.current?.innerHTML ?? '';\n // Wait until content is in the DOM; will re-run when mounted changes.\n if (!rawHtml) return;\n assignTrackedRef.current = variantId;\n trackExposure(client, apiKey, props.id, variantId, containerRef.current);\n }, [client, variantId, apiKey, props.id, mounted, content, isOverride]);\n\n // Reset goal latch when variant or goal changes.\n useEffect(() => {\n goalFiredRef.current = false;\n microGoalFiredRef.current = new Set();\n }, [variantId, goal]);\n\n // Emit cursor_signal after 800 ms of continuous hover.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n let timerId: ReturnType<typeof setTimeout> | null = null;\n let hoverStart = 0;\n\n const onEnter = (): void => {\n hoverStart = Date.now();\n timerId = setTimeout(() => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'cursor_signal',\n payload: { hoverDuration: Date.now() - hoverStart },\n });\n timerId = null;\n }, 800);\n };\n\n const onLeave = (): void => {\n if (timerId !== null) {\n clearTimeout(timerId);\n timerId = null;\n }\n };\n\n node.addEventListener('mouseenter', onEnter);\n node.addEventListener('mouseleave', onLeave);\n return () => {\n node.removeEventListener('mouseenter', onEnter);\n node.removeEventListener('mouseleave', onLeave);\n if (timerId !== null) clearTimeout(timerId);\n };\n }, [client, variantId, apiKey, props.id, isOverride]);\n\n // Attach micro-signal detectors passively — rage click, text copy, scroll hesitation, tab loss.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n\n const mapping = props.microSignalGoals?.[signalType];\n if (!mapping || microGoalFiredRef.current.has(signalType)) return;\n microGoalFiredRef.current.add(signalType);\n const name = typeof mapping === 'string' ? mapping : mapping.name;\n const weight = typeof mapping === 'string' ? 1.0 : (mapping.weight ?? 1.0);\n const stepIndex = typeof mapping === 'string' ? 0 : (mapping.stepIndex ?? 0);\n client.goal(name, { signalType, ...extra }, weight, stepIndex);\n },\n node,\n assignedAt,\n );\n }, [client, variantId, apiKey, props.id, props.microSignalGoals, isOverride]);\n\n // Attach goal tracking (shared machinery — see adaptive-shared.ts).\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variantId) return;\n const node = containerRef.current;\n if (!node) return;\n\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: props.id, variantId }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: props.id,\n variantId: variantId!,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, variantId, apiKey, props.id, goal, goalLabel, isOverride]);\n\n // Decorative slots: empty in SSR HTML and until the client has mounted.\n if (props.clientOnly && (!mounted || !client)) return null;\n if (!variantId) return null;\n\n const jsxContent = props.variants[variantId] ?? null;\n const managedContent = jsxContent === null ? content : null;\n\n if (isDevBuild() && jsxContent === null && managedContent === null) {\n console.warn(\n `[sentient] <Adaptive id=\"${props.id}\"> was assigned variant \"${variantId}\" but no matching key exists in props.variants.` +\n ` If this is a dashboard-managed text variant, use <AdaptiveText id=\"${props.id}\"> instead.`,\n );\n }\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={variantId}>\n {jsxContent ?? managedContent}\n </div>\n );\n}\n\n/**\n * Skips re-render only when nothing the output depends on has changed. The\n * variant node values must be compared, not just their keys: the assigned\n * `variantId` is stable, so if we compared keys alone, dynamic content inside a\n * variant (e.g. `<Price value={price}/>`) would render once and then freeze when\n * `price` changes. Elements are compared by reference — a caller that recreates\n * variant JSX on every render re-renders every time (correct), while stable/\n * memoized elements keep the optimization.\n */\nexport const Adaptive = memo(AdaptiveImpl, (prev, next) => {\n if (prev.id !== next.id) return false;\n if (JSON.stringify(prev.goal) !== JSON.stringify(next.goal)) return false;\n if (prev.microSignalGoals !== next.microSignalGoals) return false;\n if (prev.clientOnly !== next.clientOnly) return false;\n if (prev.agentData !== next.agentData) return false;\n if (prev.agentDataByVariant !== next.agentDataByVariant) return false;\n if (prev.variants === next.variants) return true;\n const prevKeys = Object.keys(prev.variants);\n const nextKeys = Object.keys(next.variants);\n if (prevKeys.length !== nextKeys.length) return false;\n return prevKeys.every((k) => k in next.variants && Object.is(prev.variants[k], next.variants[k]));\n});\n","import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { type AssignResult } from '@sentientui/core';\nimport { useSentient, useInitialAssignments, useSessionSegment, useSsrFallback, useOnAssignment } from './provider.js';\nimport { subscribe, getWeights, type ComponentWeights } from './weights-store.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\n\ndeclare global {\n interface Window { __sentient_overrides?: Record<string, string>; }\n}\n\nfunction getDevOverride(componentId: string): string | null {\n if (typeof window === 'undefined') return null;\n const global = window.__sentient_overrides?.[componentId];\n if (global) return global;\n try {\n const params = new URLSearchParams(window.location.search);\n for (const raw of params.getAll('sentient_variant')) {\n // sentient_variant=componentId:variantId (repeatable for multiple components)\n const sep = raw.indexOf(':');\n if (sep === -1) continue;\n if (raw.slice(0, sep) === componentId) return raw.slice(sep + 1);\n }\n } catch { /* non-browser env */ }\n return null;\n}\n\nexport type AssignmentState = {\n variantId: string | null;\n /** Populated when the assigned variant is a dashboard-managed text variant. */\n content: string | null;\n isLoading: boolean;\n /**\n * True while a dev override (?sentient_variant= / window.__sentient_overrides)\n * is forcing this variant. Consumers must suppress ALL tracking while set —\n * the override contract is \"no events recorded, weights unchanged\".\n */\n isOverride?: boolean;\n};\n\nfunction pickFromWeights(weights: ComponentWeights, variantIds: string[]): string | null {\n let best: { variantId: string; avgReward: number } | null = null;\n for (const v of weights.variants) {\n if (!variantIds.includes(v.variantId)) continue;\n if (!best || v.avgReward > best.avgReward) {\n best = { variantId: v.variantId, avgReward: v.avgReward };\n }\n }\n return best?.variantId ?? null;\n}\n\n/**\n * Returns a sticky variant assignment for a component.\n *\n * @deprecated Since 0.13.0 — use {@link useAdaptive} instead. `useAssignment`\n * only SELECTS a variant; it wires no exposure tracking, no goal listeners,\n * and no micro-signals, so components using it directly accumulate no\n * learning signal. It keeps working (it is `useAdaptive`'s internal\n * selection engine) but will move to internal-only in 1.0.0.\n *\n * First render reads the local SDK cache; if empty, falls back to a\n * deterministic default and asynchronously calls `/v1/assign`. The server\n * picks the actual variant via Thompson Sampling and the result replaces the fallback\n * on the next render. Subsequent paints read synchronously from cache —\n * no flicker, no loading state after first paint.\n */\nexport function useAssignment(componentId: string, variantIds: string[], agentData?: unknown, agentDataByVariant?: Record<string, unknown>): AssignmentState {\n const initialAssignments = useInitialAssignments();\n const ssrFallback = useSsrFallback();\n const client = useSentient();\n const segment = useSessionSegment();\n const onAssignment = useOnAssignment();\n const assignmentReportedRef = useRef<string | null>(null);\n\n // Re-render when the devtools writes window.__sentient_overrides. Without this\n // the override store is only read at mount, so forcing a variant from the panel\n // has no effect until an unrelated re-render. Mirrors useSlotResult.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n\n // Dev override: URL param ?sentient_variant=componentId:variantId\n // or window.__sentient_overrides[componentId]. Short-circuits the bandit entirely.\n const devOverride = getDevOverride(componentId);\n const overrideVariant = devOverride && variantIds.includes(devOverride) ? devOverride : null;\n const overrideLoggedRef = useRef<string | null>(null);\n if (overrideVariant && overrideLoggedRef.current !== overrideVariant) {\n overrideLoggedRef.current = overrideVariant;\n console.info(`[sentient] override active: ${componentId} -> ${overrideVariant}`);\n }\n\n const initial = (() => {\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false };\n }\n // SSR / pre-hydration: no client yet. Use initialAssignments if provided so\n // the server and client first render agree on the same variant (no mismatch).\n if (!client) {\n const preloaded = initialAssignments[componentId];\n if (preloaded && variantIds.includes(preloaded)) {\n return { variantId: preloaded, content: null, isLoading: false };\n }\n if (ssrFallback === 'first' && variantIds.length > 0) {\n return { variantId: variantIds[0], content: null, isLoading: false };\n }\n return { variantId: null, content: null, isLoading: true };\n }\n const cached = client.getAssignment(componentId, segment);\n // Allow cached managed variants (content present) even if not in variantIds.\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n return { variantId: cached.variantId, content: cached.content ?? null, isLoading: false };\n }\n const weights = getWeights(componentId);\n if (weights) {\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) return { variantId: chosen, content: null, isLoading: false };\n }\n return { variantId: variantIds[0] ?? null, content: null, isLoading: false };\n })();\n\n const [state, setState] = useState<AssignmentState>(initial);\n\n // Helper: call onAssignment at most once per resolved variant.\n const reportAssignment = (variantId: string): void => {\n if (!onAssignment) return;\n if (assignmentReportedRef.current === variantId) return;\n assignmentReportedRef.current = variantId;\n onAssignment(componentId, variantId);\n };\n\n // As soon as the client is ready, unblock the UI immediately with variantIds[0]\n // (or a cached value) so the component never stays invisible while assign is\n // in-flight. The async assign call below then swaps to the bandit-chosen variant.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false });\n reportAssignment(cached.variantId);\n return;\n }\n setState((prev) => prev.variantId ? prev : { variantId: variantIds[0] ?? null, content: null, isLoading: false });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Ask the server for a real assignment when we have a client but no cached one.\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n const cached = client.getAssignment(componentId, segment);\n if (cached && variantIds.includes(cached.variantId)) return;\n\n let cancelled = false;\n void client.assign(componentId, variantIds, agentData, agentDataByVariant).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) return;\n // Allow the result if it's a known code variant OR a managed text variant (has content).\n if (!variantIds.includes(result.variantId) && !result.content) return;\n setState({ variantId: result.variantId, content: result.content ?? null, isLoading: false });\n reportAssignment(result.variantId);\n });\n return () => { cancelled = true; };\n // variantIds intentionally excluded — changing variants mid-mount is unsupported\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n // Live weight updates from the dashboard SSE stream (when wired).\n useEffect(() => {\n if (overrideVariant) return;\n if (!client) return;\n return subscribe(componentId, (weights) => {\n const cached = client.getAssignment(componentId, segment);\n if (cached && (variantIds.includes(cached.variantId) || cached.content)) {\n setState({ variantId: cached.variantId, content: cached.content ?? null, isLoading: false });\n return;\n }\n const chosen = pickFromWeights(weights, variantIds);\n if (chosen) setState({ variantId: chosen, content: null, isLoading: false });\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [overrideVariant, client, componentId, segment]);\n\n if (overrideVariant) {\n return { variantId: overrideVariant, content: null, isLoading: false, isOverride: true };\n }\n\n return state;\n}\n","import type { SentientClient } from '@sentientui/core';\n\ndeclare const process: { env?: { NODE_ENV?: string } } | undefined;\n\n/**\n * True unless NODE_ENV is 'production'. Never `process?.env` — optional\n * chaining still throws ReferenceError on an undeclared global, and browsers\n * without a bundler shim (raw esbuild, vanilla script tags) have no `process`.\n */\nexport function isDevBuild(): boolean {\n return typeof process === 'undefined' || process.env?.NODE_ENV !== 'production';\n}\n\nexport type ScrollDepthGoal = { type: 'scroll_depth'; threshold: number };\nexport type ClickGoal = { type: 'click'; selector?: string };\nexport type FormSubmitGoal = { type: 'form_submit' };\nexport type CompositeGoal = { type: 'composite'; all: GoalConfig[] };\nexport type WeightedStep = { goal: GoalConfig; name: string; weight: number };\nexport type WeightedCompositeGoal = { type: 'weighted_composite'; steps: WeightedStep[] };\nexport type GoalConfig = ScrollDepthGoal | ClickGoal | FormSubmitGoal | CompositeGoal | WeightedCompositeGoal;\n\nexport function normalizeGoal(goal: string | GoalConfig): GoalConfig {\n if (typeof goal === 'string') return { type: 'click' };\n return goal;\n}\n\n/** The goalType label events are recorded under (named goal or config type). */\nexport function goalLabelOf(goal: string | GoalConfig): string {\n return typeof goal === 'string' ? goal : goal.type;\n}\n\nexport const PREVIEW_HTML_MAX_CHARS = 30_000;\n\n/**\n * previewHtml is the largest payload the SDK sends (up to 30 KB). The server\n * keeps the first-seen preview per (component, variant), so re-sending it on\n * every mount/navigation is pure waste — send it once per browser session.\n */\nexport function shouldSendPreviewHtml(componentId: string, variantId: string): boolean {\n try {\n const key = `_snt_pv_${componentId}_${variantId}`;\n if (sessionStorage.getItem(key)) return false;\n sessionStorage.setItem(key, '1');\n return true;\n } catch {\n // Storage unavailable (private mode, quota) — keep prior behavior.\n return true;\n }\n}\n\nfunction isClickableTarget(el: EventTarget | null): boolean {\n if (!(el instanceof Element)) return false;\n const tag = el.tagName.toLowerCase();\n if (tag === 'a' || tag === 'button') return true;\n const role = el.getAttribute('role');\n return role === 'button';\n}\n\nexport function findClickable(start: Element, container: Element, selector?: string): boolean {\n if (selector) {\n try {\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (cursor.matches(selector)) return true;\n cursor = cursor.parentElement;\n }\n } catch {\n // Invalid CSS selector — treat as no match rather than breaking all click handlers.\n }\n return false;\n }\n let cursor: Element | null = start;\n while (cursor && cursor !== container) {\n if (isClickableTarget(cursor)) return true;\n cursor = cursor.parentElement;\n }\n return false;\n}\n\nexport type GoalHandlers = {\n /** Primary goal completion. Latch-once semantics are the CALLER's job. */\n fireGoal: () => void;\n /** Weighted-composite step completion (already deduped per step here). */\n fireStep: (name: string, weight: number, stepIndex: number) => void;\n};\n\n/**\n * Attaches the goal-detection listeners `<Adaptive>`'s container uses —\n * click / form_submit / scroll_depth, composite (all-of), and\n * weighted_composite (independent steps). Returns the cleanup function.\n * Extracted from adaptive.tsx so useAdaptive / useAdaptiveTokens /\n * AdaptiveGroup wire the SAME machinery instead of duplicating it.\n */\nexport function attachGoalListeners(node: Element, goal: GoalConfig, handlers: GoalHandlers): () => void {\n // --- Weighted composite: each step fires independently as it completes ---\n if (goal.type === 'weighted_composite') {\n const firedSteps = new Set<number>();\n const wcCleanups: Array<() => void> = [];\n\n goal.steps.forEach(({ goal: sub, name: stepName, weight: stepWeight }, idx) => {\n const fireStep = (): void => {\n if (firedSteps.has(idx)) return;\n firedSteps.add(idx);\n handlers.fireStep(stepName, stepWeight, idx);\n };\n\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n fireStep();\n };\n node.addEventListener('click', onClick);\n wcCleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n fireStep();\n };\n node.addEventListener('submit', onSubmit);\n wcCleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n fireStep();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n wcCleanups.push(() => io.disconnect());\n }\n });\n\n return () => {\n for (const c of wcCleanups) c();\n };\n }\n // --- End weighted composite ---\n\n const subgoals: GoalConfig[] = goal.type === 'composite' ? goal.all : [goal];\n const remaining = new Set<number>(subgoals.map((_, i) => i));\n const checkComposite = (idx: number): void => {\n remaining.delete(idx);\n if (remaining.size === 0) handlers.fireGoal();\n };\n\n const cleanups: Array<() => void> = [];\n\n subgoals.forEach((sub, idx) => {\n if (sub.type === 'click') {\n const onClick = (e: Event): void => {\n const target = e.target;\n if (!(target instanceof Element)) return;\n if (!findClickable(target, node, sub.selector)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('click', onClick);\n cleanups.push(() => node.removeEventListener('click', onClick));\n return;\n }\n\n if (sub.type === 'form_submit') {\n const onSubmit = (e: Event): void => {\n if (!(e.target instanceof HTMLFormElement)) return;\n if (!node.contains(e.target)) return;\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n };\n node.addEventListener('submit', onSubmit);\n cleanups.push(() => node.removeEventListener('submit', onSubmit));\n return;\n }\n\n if (sub.type === 'scroll_depth') {\n const threshold = Math.max(0, Math.min(1, sub.threshold));\n const io = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.intersectionRatio >= threshold) {\n if (goal.type === 'composite') checkComposite(idx);\n else handlers.fireGoal();\n io.disconnect();\n break;\n }\n }\n },\n { threshold: [threshold] },\n );\n io.observe(node);\n cleanups.push(() => io.disconnect());\n return;\n }\n });\n\n return () => {\n for (const c of cleanups) c();\n };\n}\n\n/**\n * Records the `variant_assigned` exposure event, capturing previewHtml from\n * `container` when present (first send per browser session). Pass\n * `container: null` for surfaces with no owned DOM (token slots).\n */\nexport function trackExposure(\n client: SentientClient,\n apiKey: string,\n componentId: string,\n variantId: string,\n container: Element | null,\n): void {\n const rawHtml = container?.innerHTML ?? '';\n const includePreview = rawHtml !== '' && shouldSendPreviewHtml(componentId, variantId);\n client.track({\n projectId: apiKey,\n componentId,\n variantId,\n eventType: 'variant_assigned',\n payload: includePreview ? { previewHtml: rawHtml.slice(0, PREVIEW_HTML_MAX_CHARS) } : {},\n });\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { AssignResult } from '@sentientui/core';\nimport { useSentient, useAdaptiveApiKey, useOnAssignment, useSessionSegment } from './provider.js';\nimport { isDevBuild } from './adaptive-shared.js';\n\nexport type AdaptiveTextProps = {\n id: string;\n default: string;\n component?: keyof JSX.IntrinsicElements;\n className?: string;\n};\n\nexport function AdaptiveText({\n id,\n default: defaultText,\n component: Tag = 'span',\n className,\n}: AdaptiveTextProps) {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const onAssignment = useOnAssignment();\n const segment = useSessionSegment();\n const trackedRef = useRef<string | null>(null);\n\n // Seed from cache synchronously so remounts don't flash back to defaultText.\n const [text, setText] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.content ?? null\n );\n const [variantId, setVariantId] = useState<string | null>(() =>\n client?.getAssignment(id, segment)?.variantId ?? null\n );\n\n useEffect(() => {\n if (!client) return;\n // Skip if content already cached; assign() re-checks internally but this avoids the async round-trip on remount.\n if (client.getAssignment(id, segment)?.content !== undefined) return;\n\n let cancelled = false;\n void client.assign(id).then((result: AssignResult | null) => {\n if (cancelled) return;\n if (!result) {\n if (isDevBuild()) {\n console.warn(`[sentient] <AdaptiveText id=\"${id}\"> assignment failed — showing default text.`);\n }\n return;\n }\n setVariantId(result.variantId);\n if (result.content) setText(result.content);\n });\n return () => {\n cancelled = true;\n };\n }, [client, id, segment]);\n\n useEffect(() => {\n if (!client || !variantId || !apiKey) return;\n if (trackedRef.current === variantId) return;\n trackedRef.current = variantId;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId,\n eventType: 'variant_assigned',\n payload: {},\n });\n onAssignment?.(id, variantId);\n }, [client, variantId, apiKey, id, onAssignment]);\n\n return <Tag className={className}>{text ?? defaultText}</Tag>;\n}\n","import { useCallback } from 'react';\nimport type { ComponentGoalOptions } from '@sentientui/core';\nimport { useSentient } from './provider.js';\n\nexport type FireGoal = (goalType: string, opts?: ComponentGoalOptions) => void;\n\n/**\n * Returns a `fireGoal(goalType, opts?)` callback that records a conversion\n * attributed to the variant currently served for `componentId` — so it shows\n * up in the per-variant CVR funnel with no manual variantId/projectId plumbing.\n *\n * The served variant is resolved from the SDK's assignment cache (the same one\n * `<Adaptive id={componentId}>` populates), so render that component before\n * firing. Use this for imperative handlers (click, form submit, custom events);\n * for purely declarative goals prefer `<Adaptive goal={...}>`.\n *\n * @example\n * const fireContact = useAdaptiveGoal('hero_headline');\n * <button onClick={() => fireContact('hero_contact', { metadata: { method } })}>Call</button>\n */\nexport function useAdaptiveGoal(componentId: string): FireGoal {\n const client = useSentient();\n return useCallback<FireGoal>(\n (goalType, opts) => {\n client?.componentGoal(componentId, goalType, opts);\n },\n [client, componentId],\n );\n}\n","import { renderPrePaintScript } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\n\nexport type SentientPersonaScriptProps = {\n /** Publishable API key — selects the localStorage snapshot in the fallback path. */\n apiKey: string;\n /**\n * SSR-decided persona (from `loadAdaptiveDecision`). When present the\n * script embeds the literal values; when absent it reads the local\n * decision snapshot (SPA / return-visit path).\n */\n persona?: { persona: string; confidence: number } | null;\n};\n\n/** JSON string literal that is also safe inside an inline <script> element. */\nfunction inlineJsString(value: string): string {\n return JSON.stringify(value).replace(/</g, '\\\\u003c');\n}\n\n/** Exported for tests. Builds the inline JS (concatenation only — no backticks). */\nexport function personaScriptBody(props: SentientPersonaScriptProps): string {\n if (props.persona) {\n return (\n '(function(){try{var d=document.documentElement;' +\n 'if(d.hasAttribute(\"data-sentient-persona\"))return;' +\n 'd.setAttribute(\"data-sentient-persona\",' + inlineJsString(props.persona.persona) + ');' +\n 'd.setAttribute(\"data-sentient-confidence\",' + inlineJsString(confidenceBand(props.persona.confidence)) + ');' +\n '}catch(e){}})();'\n );\n }\n return renderPrePaintScript(props.apiKey);\n}\n\n/**\n * Single writer of the Rung-1a `<html>` attributes\n * (`data-sentient-persona`, `data-sentient-confidence`), executed pre-paint.\n *\n * `AdaptiveRoot` renders this automatically as its first child. For Pages\n * Router / Remix, render it yourself in `_document` / the root layout.\n *\n * IMPORTANT (install docs): add `suppressHydrationWarning` to your `<html>`\n * element — this script mutates documentElement before React hydrates it\n * (the same pattern next-themes uses). The client SDK adopts the attributes\n * as truth and never rewrites them mid-session.\n */\nexport function SentientPersonaScript(props: SentientPersonaScriptProps): JSX.Element {\n return (\n <script\n data-sentient-persona-script=\"\"\n dangerouslySetInnerHTML={{ __html: personaScriptBody(props) }}\n />\n );\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { validateSlotDecl } from '@sentientui/policy';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveTokensOptions = { goal?: string | GoalConfig };\nexport type UseAdaptiveTokensResult = {\n tokens: Record<string, string>;\n /** Spread on the slot's element: `data-<dim>` per dim + `data-sentient-slot`. */\n props: Record<string, string>;\n};\n\n// Warn once per slot id per page lifetime — not per render.\nconst warnedTokenSlots = new Set<string>();\n\nfunction cssEscape(value: string): string {\n return typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(value)\n : value.replace(/\"/g, '\\\\\"');\n}\n\n/**\n * Rung 1b — adaptive design tokens. Declares a bounded token space; the\n * optimizer picks per persona; values apply as element-scoped data\n * attributes so they serialize through SSR markup (zero flicker,\n * hydration-safe). First value of each dim = baseline.\n *\n * ```tsx\n * const t = useAdaptiveTokens('hero', { tone: ['calm', 'urgent'] });\n * return <section {...t.props} className=\"hero\">…</section>;\n * // CSS: .hero[data-tone=\"urgent\"] .cta { … }\n * ```\n */\nexport function useAdaptiveTokens(\n id: string,\n dims: Record<string, readonly string[]>,\n opts?: UseAdaptiveTokensOptions,\n): UseAdaptiveTokensResult {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n\n // A slot's declared space is fixed for the session (same rule as\n // <Adaptive> variants) — memoize on id only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const decl = useMemo<SlotDeclInput>(() => ({ id, dims }), [id]);\n const { result, arm } = useSlotResult(id, decl);\n const tokens = useMemo<Record<string, string>>(\n () => (typeof result === 'string' ? {} : result),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [arm],\n );\n\n if (isDevBuild() && !warnedTokenSlots.has(id)) {\n const validity = validateSlotDecl({\n id,\n dims: Object.fromEntries(Object.entries(dims).map(([k, v]) => [k, [...v]])),\n });\n const space = Object.values(dims).reduce((n, values) => n * values.length, 1);\n if (!validity.ok) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): invalid declaration — ${validity.reason}. Serving baseline.`,\n );\n } else if (space > 4) {\n warnedTokenSlots.add(id);\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\") declares ${space} combinations — more than the recommended 4. Each extra combination needs more traffic to learn; consider fewer dims/values.`,\n );\n }\n }\n\n const goalKey =\n opts?.goal === undefined ? null : typeof opts.goal === 'string' ? opts.goal : JSON.stringify(opts.goal);\n\n // Devtools slot registry — the declared dims space drives both persona\n // simulation and the panel's per-dim override buttons. A slot is NOT a\n // component: registering it as one produced buttons that wrote the wrong\n // override channel (`__sentient_overrides` instead of `__sentient_slot_overrides`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => registerSlot({ id, dims }), [id]);\n\n // Exposure — the slot equivalent of <Adaptive>'s variant_assigned event,\n // once per (slot, arm). variantId = canonical arm string. No container\n // (token slots own no DOM), so no previewHtml.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n if (!client || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, id, arm, null);\n }, [client, apiKey, id, arm]);\n\n // Optional goal: the returned props carry data-sentient-slot, so the slot's\n // element is findable without a ref (the pinned return type has no ref).\n // Credit flows through componentGoal(slot id) — the core resolves the\n // attributed arm from its slot state (Task 3.3 fallback).\n useEffect(() => {\n if (!client || !opts?.goal) return;\n const node = document.querySelector(`[data-sentient-slot=\"${cssEscape(id)}\"]`);\n if (!node) {\n if (isDevBuild()) {\n console.warn(\n `[sentient] useAdaptiveTokens(\"${id}\"): a goal is declared but no element carries the returned props — spread {...props} on the slot's element.`,\n );\n }\n return;\n }\n const label = goalLabelOf(opts.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(opts.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n client.componentGoal(id, label);\n },\n fireStep: (name, weight) => {\n client.componentGoal(id, name, { reward: weight });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, id, goalKey, arm]);\n\n const props = useMemo(() => {\n const p: Record<string, string> = { 'data-sentient-slot': id };\n for (const [dim, value] of Object.entries(tokens)) p[`data-${dim}`] = value;\n return p;\n }, [id, tokens]);\n\n return { tokens, props };\n}\n","import { useEffect, useReducer, useSyncExternalStore } from 'react';\nimport { armOfResult, baselineResultFor, type SlotDeclInput, type SlotResult } from '@sentientui/core';\nimport { confidenceBand } from '@sentientui/policy';\nimport { useInitialPersona, useInitialSlots, useSentient } from './provider.js';\nimport { subscribeOverridesChanged, getOverridesVersion } from './override-events.js';\n\ndeclare global {\n interface Window {\n /** Test/devtools forcing: slot id → forced result (applyScenario sets this). */\n __sentient_slot_overrides?: Record<string, SlotResult>;\n /** Test/devtools forcing: forced persona (applyScenario sets this). */\n __sentient_persona_override?: { persona: string; confidence?: number };\n }\n}\n\nexport type SlotResolution = {\n result: SlotResult;\n /** Canonical arm string (`dim=value|…` for dims slots, arm id for arms slots). */\n arm: string;\n source: 'override' | 'preloaded' | 'client' | 'baseline';\n};\n\n/**\n * Internal. Resolves what a slot serves this render, synchronously:\n * test/devtools override → SSR-preloaded result → core client state\n * (decide cache, snapshot seed, failure baseline) → declared baseline.\n * Purely read-side: exposure/goal wiring belongs to the calling hook.\n */\nexport function useSlotResult(slotId: string, decl: SlotDeclInput): SlotResolution {\n // Re-render when devtools writes window.__sentient_slot_overrides.\n useSyncExternalStore(subscribeOverridesChanged, getOverridesVersion, () => 0);\n const client = useSentient();\n const initialSlots = useInitialSlots();\n const [, bump] = useReducer((n: number) => n + 1, 0);\n\n const override =\n typeof window !== 'undefined' ? window.__sentient_slot_overrides?.[slotId] : undefined;\n const preloaded = override === undefined ? initialSlots[slotId] : undefined;\n const fromClient =\n override === undefined && preloaded === undefined && client\n ? client.getSlotResult(slotId)\n : null;\n\n // Keyless local mode on a CSR-only page: nothing has decided this slot yet\n // (no SSR preload, no snapshot), so ask the local engine — zero network,\n // deterministic — and re-render when the decision lands. Keyed clients\n // never take this path: their slots decide server-side (SSR preload).\n const needsLocalDecide =\n client?.isLocal === true &&\n override === undefined &&\n preloaded === undefined &&\n fromClient === null;\n useEffect(() => {\n if (!needsLocalDecide || !client) return;\n let cancelled = false;\n void client.decide({ slots: [decl] }).then((outcome) => {\n if (!cancelled && outcome) bump();\n });\n return () => {\n cancelled = true;\n };\n // decl identity is fixed per slot id (callers memoize it on id).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, slotId, needsLocalDecide]);\n\n if (override !== undefined) {\n return { result: override, arm: armOfResult(override), source: 'override' };\n }\n if (preloaded !== undefined) {\n return { result: preloaded, arm: armOfResult(preloaded), source: 'preloaded' };\n }\n if (fromClient !== null) {\n return { result: fromClient, arm: armOfResult(fromClient), source: 'client' };\n }\n const baseline = baselineResultFor(decl);\n return { result: baseline, arm: armOfResult(baseline), source: 'baseline' };\n}\n\n/**\n * Internal. Reads a forced persona: `window.__sentient_persona_override`\n * (tests/devtools) or `?sentient_persona=<PersonaKey>` (mirrors the\n * `?sentient_variant=` mechanism in use-assignment.ts).\n */\nexport function getPersonaOverride(): { persona: string; confidence: number } | null {\n if (typeof window === 'undefined') return null;\n const forced = window.__sentient_persona_override;\n if (forced?.persona) return { persona: forced.persona, confidence: forced.confidence ?? 1 };\n try {\n const value = new URLSearchParams(window.location.search).get('sentient_persona');\n if (value) return { persona: value, confidence: 1 };\n } catch {\n /* non-browser env */\n }\n return null;\n}\n\n/**\n * Internal. Current persona estimate for React consumers:\n * override → SSR initialPersona → client state (adopted attrs / snapshot / decide).\n */\nexport function useAdaptivePersona(): { persona: string; confidence: number; band: 'low' | 'medium' | 'high' } | null {\n const client = useSentient();\n const initialPersona = useInitialPersona();\n\n const override = getPersonaOverride();\n if (override) return { ...override, band: confidenceBand(override.confidence) };\n if (initialPersona) return { ...initialPersona, band: confidenceBand(initialPersona.confidence) };\n return client ? client.getPersona() : null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { attachMicroSignalDetectors, type ComponentGoalOptions } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useAssignment } from './use-assignment.js';\nimport { registerComponent } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type UseAdaptiveBind = {\n ref: (el: HTMLElement | null) => void;\n 'data-sentient-id': string;\n 'data-sentient-variant': string;\n};\n\nexport type UseAdaptiveResult<T> = {\n variant: string;\n value: T;\n /** Spread on the rendered element — wires exposure, goal listeners, and micro-signals. */\n bind: UseAdaptiveBind;\n fireGoal: (goalType?: string, opts?: ComponentGoalOptions) => void;\n};\n\nconst warnedUnbound = new Set<string>();\n\n/**\n * Rung 2 — headless, measurement-complete variant swap. Supersedes\n * `useAssignment` (which selects a variant but wires no measurement).\n *\n * `goal` is REQUIRED: without one the optimizer accumulates exposures with\n * zero rewards and cannot learn. `bind` MUST be attached to the rendered\n * element — dev mode warns loudly when a slot renders unbound.\n *\n * ```tsx\n * const { value, bind } = useAdaptive('buy-box', {\n * variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline\n * goal: 'buy_click',\n * });\n * return <div {...bind}>{value}</div>;\n * ```\n */\nexport function useAdaptive<T>(\n id: string,\n config: { variants: Record<string, T>; goal: string | GoalConfig },\n): UseAdaptiveResult<T> {\n if (isDevBuild() && !config.goal) {\n throw new Error(\n `[sentient] useAdaptive(\"${id}\"): a goal is required — without one the optimizer accumulates exposures with no rewards and cannot learn. Pass e.g. goal: 'buy_click'.`,\n );\n }\n\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n // Declared space is fixed per slot id for a session (same rule as <Adaptive>).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const variantIds = useMemo(() => Object.keys(config.variants), [id]);\n const { variantId, isOverride } = useAssignment(id, variantIds);\n const variant = variantId ?? variantIds[0] ?? '';\n const value = config.variants[variant] as T;\n\n const [node, setNode] = useState<HTMLElement | null>(null);\n const nodeRef = useRef<HTMLElement | null>(null);\n const ref = useCallback((el: HTMLElement | null) => {\n nodeRef.current = el;\n setNode(el);\n }, []);\n\n const goalKey = typeof config.goal === 'string' ? config.goal : JSON.stringify(config.goal);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const goal = useMemo(() => normalizeGoal(config.goal), [goalKey]);\n const goalLabel = goalLabelOf(config.goal);\n\n useEffect(() => registerComponent({ id, variantIds, goal: goalLabel }), [id, variantIds, goalLabel]);\n\n // Exposure — same variant_assigned mechanics as <Adaptive>, fired once per\n // (id, variant) and only once the bind target is in the DOM (previewHtml\n // is captured from it).\n const exposedRef = useRef<string | null>(null);\n useEffect(() => {\n // Forced variants are a dev/test view — no exposure, no goals, no\n // micro-signals may be recorded (same gate as <Adaptive>).\n if (isOverride) return;\n if (!client || !variant || !node) return;\n if (exposedRef.current === variant) return;\n exposedRef.current = variant;\n trackExposure(client, apiKey, id, variant, node);\n }, [client, apiKey, id, variant, node, isOverride]);\n\n // Goal listeners — identical machinery to <Adaptive> (shared helper).\n const goalFiredRef = useRef(false);\n useEffect(() => {\n goalFiredRef.current = false;\n }, [variant, goalKey]);\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n return attachGoalListeners(node, goal, {\n fireGoal: () => {\n if (goalFiredRef.current) return;\n goalFiredRef.current = true;\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: goalLabel,\n payload: { reward: 1.0 },\n });\n client.goal(goalLabel, { componentId: id, variantId: variant }, 1.0, 0);\n },\n fireStep: (name, weight, stepIndex) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'goal_achieved',\n goalType: name,\n payload: { reward: weight },\n });\n client.goal(name, {}, weight, stepIndex);\n },\n });\n }, [client, node, variant, apiKey, id, goal, goalLabel, isOverride]);\n\n // Micro-signal detectors — the third thing <Adaptive>'s container wires.\n useEffect(() => {\n if (isOverride) return;\n if (!client || !variant || !node) return;\n const assignedAt = Date.now();\n return attachMicroSignalDetectors(\n (signalType, extra = {}) => {\n client.track({\n projectId: apiKey,\n componentId: id,\n variantId: variant,\n eventType: 'micro_signal',\n payload: { signalType, ...extra },\n });\n },\n node,\n assignedAt,\n );\n }, [client, node, variant, apiKey, id, isOverride]);\n\n // Dev warning: bind never attached shortly after mount → exposures would\n // never fire and the slot cannot learn. Once per slot id.\n useEffect(() => {\n if (!isDevBuild()) return;\n if (!client) return;\n const timer = setTimeout(() => {\n if (!nodeRef.current && !warnedUnbound.has(id)) {\n warnedUnbound.add(id);\n console.warn(\n `[sentient] useAdaptive(\"${id}\"): bind was never attached — spread {...bind} on the rendered element, otherwise exposure and goal tracking cannot work and the optimizer learns nothing.`,\n );\n }\n }, 0);\n return () => clearTimeout(timer);\n }, [client, id]);\n\n const fireGoal = useCallback(\n (goalType?: string, opts?: ComponentGoalOptions) => {\n if (isOverride) return; // forced variants record nothing, even manual goals\n client?.componentGoal(id, goalType ?? goalLabel, opts);\n },\n [client, id, goalLabel, isOverride],\n );\n\n const bind = useMemo<UseAdaptiveBind>(\n () => ({ ref, 'data-sentient-id': id, 'data-sentient-variant': variant }),\n [ref, id, variant],\n );\n\n return { variant, value, bind, fireGoal };\n}\n","import { Children, isValidElement, useEffect, useMemo, useRef, type ReactNode } from 'react';\nimport type { SlotDeclInput } from '@sentientui/core';\nimport { useAdaptiveApiKey, useSentient } from './provider.js';\nimport { useSlotResult } from './use-slot-result.js';\nimport { registerSlot } from './devtools-registry.js';\nimport {\n attachGoalListeners,\n goalLabelOf,\n isDevBuild,\n normalizeGoal,\n trackExposure,\n type GoalConfig,\n} from './adaptive-shared.js';\n\nexport type AdaptiveGroupProps = {\n id: string;\n /** Arrangement id → ordered child keys. FIRST key = baseline default. */\n arrangements: Record<string, string[]>;\n /** Explicit baseline arrangement id (defaults to the first declared). */\n baseline?: string;\n /** Optional slot-scoped goal — credited via componentGoal(group id). */\n goal?: string | GoalConfig;\n /** Keyed children — every key referenced by an arrangement must exist. */\n children: ReactNode;\n};\n\n// Warn once per group id per page lifetime.\nconst warnedGroups = new Set<string>();\n\n/**\n * Rung 3 — bounded mini-layout. Reorders KEYED children into the decided\n * arrangement (enumerated-arms slot: arms = Object.keys(arrangements)).\n * Declared orders only — never free permutation, never show/hide.\n * Fail-safe: unknown arrangement or key mismatch renders declaration order.\n */\nexport function AdaptiveGroup(props: AdaptiveGroupProps): JSX.Element {\n const client = useSentient();\n const apiKey = useAdaptiveApiKey();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Declared space is fixed per group id for a session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const arrangementIds = useMemo(() => Object.keys(props.arrangements), [props.id]);\n const decl = useMemo<SlotDeclInput>(\n () => ({\n id: props.id,\n arms: arrangementIds,\n ...(props.baseline !== undefined ? { baseline: props.baseline } : {}),\n }),\n [props.id, arrangementIds, props.baseline],\n );\n const { arm } = useSlotResult(props.id, decl);\n\n if (\n isDevBuild() &&\n props.baseline !== undefined &&\n props.baseline !== arrangementIds[0] &&\n !warnedGroups.has(props.id + ':baseline')\n ) {\n warnedGroups.add(props.id + ':baseline');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: baseline \"${props.baseline}\" is not the first-declared arrangement (\"${arrangementIds[0]}\"). The first arrangement should usually be the page's real incumbent (the holdout sees it).`,\n );\n }\n\n const childArray = Children.toArray(props.children).filter(isValidElement);\n const byKey = new Map<string, (typeof childArray)[number]>();\n for (const child of childArray) {\n // Children.toArray prefixes explicit keys with '.$'.\n byKey.set(String(child.key ?? '').replace(/^\\.\\$/, ''), child);\n }\n\n const order = props.arrangements[arm];\n const canReorder =\n order !== undefined &&\n order.length === childArray.length &&\n order.every((key) => byKey.has(key));\n\n if (\n isDevBuild() &&\n order !== undefined &&\n !canReorder &&\n !warnedGroups.has(props.id + ':keys')\n ) {\n warnedGroups.add(props.id + ':keys');\n console.warn(\n `[sentient] <AdaptiveGroup id=\"${props.id}\">: arrangement \"${arm}\" [${order.join(', ')}] does not match the children's keys — rendering declaration order (fail-safe).`,\n );\n }\n\n const ordered = canReorder ? order.map((key) => byKey.get(key)!) : childArray;\n\n // Devtools slot registry — the declared arms space drives persona simulation\n // and the panel's per-arm override buttons. A group is a slot, not a component:\n // registering it as one produced buttons that wrote the wrong override channel.\n useEffect(\n () => registerSlot({ id: props.id, arms: Object.keys(props.arrangements) }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [props.id],\n );\n\n // Exposure — once per (group, arrangement); previewHtml from the container.\n const exposedArmRef = useRef<string | null>(null);\n useEffect(() => {\n if (!client || exposedArmRef.current === arm) return;\n exposedArmRef.current = arm;\n trackExposure(client, apiKey, props.id, arm, containerRef.current);\n }, [client, apiKey, props.id, arm]);\n\n // Optional goal — slot-scoped credit through componentGoal (the core\n // resolves the attributed arm from its slot state; see Task 3.3).\n const goalKey =\n props.goal === undefined ? null : typeof props.goal === 'string' ? props.goal : JSON.stringify(props.goal);\n useEffect(() => {\n if (!client || props.goal === undefined) return;\n const node = containerRef.current;\n if (!node) return;\n const label = goalLabelOf(props.goal);\n let fired = false;\n return attachGoalListeners(node, normalizeGoal(props.goal), {\n fireGoal: () => {\n if (fired) return;\n fired = true;\n client.componentGoal(props.id, label);\n },\n fireStep: (name, weight) => {\n client.componentGoal(props.id, name, { reward: weight });\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, props.id, goalKey, arm]);\n\n return (\n <div ref={containerRef} data-sentient-id={props.id} data-sentient-variant={arm}>\n {ordered}\n </div>\n );\n}\n","/** @deprecated Use `useSessionSegment()` from the provider, or `deriveSessionSegment` from `@sentientui/core`. */\nexport { deriveSessionSegment as detectSegment } from '@sentientui/core';\n","/**\n * Agent-readable content feed. Merges SDK-known data (winning variants, layout\n * order) with developer-supplied page content, and renders it either as a\n * server-rendered inline JSON-LD block (read by passive AI crawlers, which do\n * not run JS) or as Markdown (for agents that content-negotiate `text/markdown`).\n *\n * No React or DOM APIs — safe to import in server components, route handlers,\n * and middleware.\n */\n\nexport type AgentBlock = {\n /** Component ID. */\n id: string;\n /** Winning variant ID currently served. */\n variant: string;\n /** Agent-readable data attached to the served variant, if any. */\n content?: unknown;\n};\n\nexport type AgentFeed = {\n page: string;\n title?: string;\n summary?: string;\n layoutOrder?: string[];\n blocks: AgentBlock[];\n /** Developer-supplied extra fields (products, specs, arbitrary JSON). */\n [key: string]: unknown;\n};\n\n/** Fields the SDK owns — developer content can never overwrite these. */\nconst RESERVED_FIELDS = ['page', 'blocks', 'layoutOrder'] as const;\n\nconst registry = new Map<string, Record<string, unknown>>();\n\n/**\n * Register page-level structured content the SDK can't infer (title, summary,\n * product fields, arbitrary JSON), keyed by page path. Call at module load.\n */\nexport function defineAgentContent(page: string, content: Record<string, unknown>): void {\n registry.set(page, content);\n}\n\n/** Look up registered content for a page. */\nexport function getAgentContent(page: string): Record<string, unknown> | undefined {\n return registry.get(page);\n}\n\n/** Clear the registry — intended for tests. */\nexport function clearAgentContent(): void {\n registry.clear();\n}\n\n/**\n * Merge SDK-known data with developer-supplied content into a single feed.\n * Developer content fills in title/summary/etc. but can never overwrite the\n * SDK-authoritative fields (`page`, `blocks`, `layoutOrder`).\n */\nexport function buildAgentFeed(input: {\n page: string;\n blocks: AgentBlock[];\n layoutOrder?: string[];\n content?: Record<string, unknown>;\n}): AgentFeed {\n const supplied = input.content ?? getAgentContent(input.page) ?? {};\n const safe: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(supplied)) {\n if (!(RESERVED_FIELDS as readonly string[]).includes(k)) safe[k] = v;\n }\n const feed: AgentFeed = {\n ...safe,\n page: input.page,\n blocks: input.blocks,\n };\n if (input.layoutOrder) feed.layoutOrder = input.layoutOrder;\n return feed;\n}\n\n/**\n * Render the feed as a server-rendered inline JSON-LD `<script>` string. `<` is\n * escaped to `<` so embedded content cannot break out of the script\n * element. MUST be emitted on the server — passive crawlers never run client JS.\n */\nexport function renderAgentJsonLd(feed: AgentFeed): string {\n return `<script type=\"application/ld+json\">${renderAgentJsonLdBody(feed)}</script>`;\n}\n\n/**\n * The escaped JSON-LD body only (no `<script>` wrapper). For React server\n * components, inject via `<script type=\"application/ld+json\"\n * dangerouslySetInnerHTML={{ __html: renderAgentJsonLdBody(feed) }} />`.\n */\nexport function renderAgentJsonLdBody(feed: AgentFeed): string {\n return JSON.stringify({ '@context': 'https://schema.org', '@type': 'WebPage', ...feed })\n .replace(/</g, '\\\\u003c');\n}\n\n/** Render the feed as Markdown for agents that negotiate `text/markdown`. */\nexport function renderAgentMarkdown(feed: AgentFeed): string {\n const lines: string[] = [];\n if (feed.title) lines.push(`# ${feed.title}`, '');\n if (feed.summary) lines.push(String(feed.summary), '');\n\n for (const [k, v] of Object.entries(feed)) {\n if (['page', 'title', 'summary', 'blocks', 'layoutOrder'].includes(k)) continue;\n lines.push(`## ${k}`, '', '```json', JSON.stringify(v, null, 2), '```', '');\n }\n\n if (feed.blocks.length > 0) {\n lines.push('## blocks', '');\n for (const b of feed.blocks) {\n lines.push(`- **${b.id}** → variant \\`${b.variant}\\``);\n if (b.content !== undefined) {\n lines.push('', ' ```json', JSON.stringify(b.content, null, 2), ' ```');\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n').trimEnd() + '\\n';\n}\n"],"mappings":"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","names":["createContext","useContext","useEffect","useMemo","useState","useSyncExternalStore","detectDeviceClass","detectTrafficSource","init","store","listeners","subscribe","componentId","cb","set","update","weights","e","getWeights","_a","ssrFallback","state","w","getPreviewMode","state","subscribePreview","fn","listeners","createPreviewClient","inner","componentId","segment","variantIds","agentData","agentDataByVariant","slotId","EVENT","getOverridesVersion","_a","subscribeOverridesChanged","fn","EVENT","publishDevtoolsConfig","config","ssrFallback","state","w","emit","fn","registerComponent","c","registerSlot","s","registerSections","sections","jsx","deriveDefaultSegment","_a","_b","device","detectDeviceClass","source","detectTrafficSource","e","DEFAULT_API_BASE_URL","AdaptiveContext","createContext","AdaptiveProvider","props","client","setClient","useState","sessionSegment","previewOn","setPreviewOn","getPreviewMode","useEffect","subscribePreview","prev","config","cancelled","created","initGraph","__spreadProps","__spreadValues","init","poll","entries","entry","weights","v","update","timerId","ssrFallback","apiBaseUrl","publishDevtoolsConfig","registerSections","exposedClient","useMemo","createPreviewClient","value","_c","_d","useSentient","useContext","useAdaptiveApiKey","useInitialAssignments","useContext","AdaptiveContext","useSessionSegment","useSsrFallback","useOnAssignment","useLayoutOrder","contextOrder","override","useSyncExternalStore","subscribeOverridesChanged","_a","useInitialSlots","useAdaptiveApiBaseUrl","useContext","AdaptiveContext","memo","useEffect","useMemo","useRef","useState","attachMicroSignalDetectors","useEffect","useRef","useState","useSyncExternalStore","getDevOverride","componentId","_a","global","params","raw","sep","e","pickFromWeights","weights","variantIds","best","v","useAssignment","agentData","agentDataByVariant","initialAssignments","useInitialAssignments","ssrFallback","useSsrFallback","client","useSentient","segment","useSessionSegment","onAssignment","useOnAssignment","assignmentReportedRef","useRef","useSyncExternalStore","subscribeOverridesChanged","getOverridesVersion","devOverride","overrideVariant","overrideLoggedRef","initial","_b","preloaded","cached","getWeights","chosen","state","setState","useState","reportAssignment","variantId","useEffect","prev","cancelled","result","subscribe","isDevBuild","_a","normalizeGoal","goal","goalLabelOf","PREVIEW_HTML_MAX_CHARS","shouldSendPreviewHtml","componentId","variantId","key","e","isClickableTarget","el","tag","findClickable","start","container","selector","cursor","attachGoalListeners","node","handlers","firedSteps","wcCleanups","sub","stepName","stepWeight","idx","fireStep","onClick","target","onSubmit","threshold","io","entries","entry","subgoals","remaining","_","i","checkComposite","cleanups","c","trackExposure","client","apiKey","rawHtml","includePreview","jsx","AdaptiveImpl","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","variantIds","useMemo","variantId","content","isOverride","useAssignment","containerRef","useRef","mounted","setMounted","useState","useEffect","goalFiredRef","microGoalFiredRef","assignTrackedRef","goalKey","goal","normalizeGoal","goalLabel","registerComponent","_b","trackExposure","node","timerId","hoverStart","onEnter","onLeave","assignedAt","attachMicroSignalDetectors","signalType","extra","_c","__spreadValues","mapping","name","weight","stepIndex","attachGoalListeners","jsxContent","managedContent","isDevBuild","Adaptive","memo","prev","next","prevKeys","nextKeys","k","useEffect","useRef","useState","jsx","AdaptiveText","id","defaultText","Tag","className","client","useSentient","apiKey","useAdaptiveApiKey","onAssignment","useOnAssignment","segment","useSessionSegment","trackedRef","useRef","text","setText","useState","_a","_b","variantId","setVariantId","useEffect","cancelled","result","isDevBuild","useCallback","useAdaptiveGoal","componentId","client","useSentient","useCallback","goalType","opts","renderPrePaintScript","confidenceBand","jsx","inlineJsString","value","personaScriptBody","props","SentientPersonaScript","useEffect","useMemo","useRef","validateSlotDecl","useEffect","useReducer","useSyncExternalStore","armOfResult","baselineResultFor","confidenceBand","useSlotResult","slotId","decl","_a","useSyncExternalStore","subscribeOverridesChanged","getOverridesVersion","client","useSentient","initialSlots","useInitialSlots","bump","useReducer","n","override","preloaded","fromClient","needsLocalDecide","useEffect","cancelled","outcome","armOfResult","baseline","baselineResultFor","warnedTokenSlots","cssEscape","value","useAdaptiveTokens","id","dims","opts","client","useSentient","apiKey","useAdaptiveApiKey","decl","useMemo","result","arm","useSlotResult","tokens","isDevBuild","validity","validateSlotDecl","k","v","space","n","values","goalKey","useEffect","registerSlot","exposedArmRef","useRef","trackExposure","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","props","p","dim","useCallback","useEffect","useMemo","useRef","useState","attachMicroSignalDetectors","warnedUnbound","useAdaptive","id","config","_a","isDevBuild","client","useSentient","apiKey","useAdaptiveApiKey","variantIds","useMemo","variantId","isOverride","useAssignment","variant","value","node","setNode","useState","nodeRef","useRef","ref","useCallback","el","goalKey","goal","normalizeGoal","goalLabel","goalLabelOf","useEffect","registerComponent","exposedRef","trackExposure","goalFiredRef","attachGoalListeners","name","weight","stepIndex","assignedAt","attachMicroSignalDetectors","signalType","extra","__spreadValues","timer","fireGoal","goalType","opts","bind","Children","isValidElement","useEffect","useMemo","useRef","jsx","warnedGroups","AdaptiveGroup","props","_a","client","useSentient","apiKey","useAdaptiveApiKey","containerRef","useRef","arrangementIds","useMemo","decl","__spreadValues","arm","useSlotResult","isDevBuild","childArray","Children","isValidElement","byKey","child","order","canReorder","key","ordered","useEffect","registerSlot","exposedArmRef","trackExposure","goalKey","node","label","goalLabelOf","fired","attachGoalListeners","normalizeGoal","name","weight","deriveSessionSegment","RESERVED_FIELDS","registry","defineAgentContent","page","content","getAgentContent","buildAgentFeed","input","_a","_b","supplied","getAgentContent","safe","k","v","RESERVED_FIELDS","feed","__spreadProps","__spreadValues","renderAgentJsonLd","renderAgentJsonLdBody","renderAgentMarkdown","lines","b"]}
|