@guidelytech/react 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -198,7 +198,9 @@ var NOOP_RESULTS = {
198
198
  getState: { ready: false, destroyed: false },
199
199
  getContext: null,
200
200
  getSessionId: "",
201
- isRecording: false
201
+ isRecording: false,
202
+ agentConversation: false,
203
+ trackAgentTurn: false
202
204
  };
203
205
  var noopFlags = new Proxy((0, import_flags2.createStaticFlags)(), {
204
206
  get(target, prop, receiver) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/flags.tsx"],"sourcesContent":["import { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide } from \"@guidelytech/sdk-core\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n /**\n * Flags bootstrap from the server (`getFlagsBootstrap()` / `client.getPayload()`): flag hooks\n * render the same values on the server, during hydration and after.\n */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, page and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/** The attributes the server knows about a user: what bootstrap snapshots evaluate with. */\nfunction userAttributes(user: GuidelyUser | null | undefined): Attributes {\n if (!user?.id) return {};\n return { ...(user.traits ?? {}), id: user.id, ...(user.account ? { account: { ...(user.account.traits ?? {}), id: user.account.id } } : {}) };\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const o = optionsRef.current;\n // The user is known up front so flags evaluate for them from the first render (no flicker).\n const c = createGuidely({ ...o, projectId, environment, apiUrl, user: userRef.current?.id ? userRef.current : undefined, flags: o.flags === false ? false : { ...(o.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current } });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n const bootstrap = useBootstrap(payload, { ...userAttributes(user), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>{children}</FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n getSessionId: \"\",\n isRecording: false,\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n","import { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\n/** What the flag hooks read: the live client once created, else a static snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useReader(): FlagsReader {\n const src = useContext(FlagsContext);\n return src?.client ?? src?.bootstrap ?? EMPTY;\n}\n\n/**\n * Subscribes to the flags with `useSyncExternalStore`. Values are compared deeply so object\n * flags keep their identity between renders. The server snapshot is the bootstrap payload, so\n * server-rendered HTML and hydration agree.\n */\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const reader = useReader();\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (or failed to and serve fallbacks); true from the start with a bootstrap payload. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` on the server and before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot for SSR and hydration, rebuilt only when the payload or attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap from the server (`getPayload()`): renders the same values on the server and in the browser. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Creates a flags client in an effect (never during\n * SSR) and destroys it on unmount; until then hooks read the `payload` snapshot. Changing\n * `attributes` re-evaluates without recreating the client.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" attributes={{ id: user.id, plan: user.plan }} payload={bootstrap}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n\n useEffect(() => {\n if (external || !sdkKey || typeof window === \"undefined\") return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n return () => {\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n"],"mappings":"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","names":["import_flags","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/flags.tsx"],"sourcesContent":["import { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide, AgentTurnInput, AgentTurnRedactor } from \"@guidelytech/sdk-core\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n /**\n * Flags bootstrap from the server (`getFlagsBootstrap()` / `client.getPayload()`): flag hooks\n * render the same values on the server, during hydration and after.\n */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, page and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/** The attributes the server knows about a user: what bootstrap snapshots evaluate with. */\nfunction userAttributes(user: GuidelyUser | null | undefined): Attributes {\n if (!user?.id) return {};\n return { ...(user.traits ?? {}), id: user.id, ...(user.account ? { account: { ...(user.account.traits ?? {}), id: user.account.id } } : {}) };\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const o = optionsRef.current;\n // The user is known up front so flags evaluate for them from the first render (no flicker).\n const c = createGuidely({ ...o, projectId, environment, apiUrl, user: userRef.current?.id ? userRef.current : undefined, flags: o.flags === false ? false : { ...(o.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current } });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n const bootstrap = useBootstrap(payload, { ...userAttributes(user), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>{children}</FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n getSessionId: \"\",\n isRecording: false,\n agentConversation: false,\n trackAgentTurn: false,\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n","import { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\n/** What the flag hooks read: the live client once created, else a static snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useReader(): FlagsReader {\n const src = useContext(FlagsContext);\n return src?.client ?? src?.bootstrap ?? EMPTY;\n}\n\n/**\n * Subscribes to the flags with `useSyncExternalStore`. Values are compared deeply so object\n * flags keep their identity between renders. The server snapshot is the bootstrap payload, so\n * server-rendered HTML and hydration agree.\n */\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const reader = useReader();\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (or failed to and serve fallbacks); true from the start with a bootstrap payload. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` on the server and before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot for SSR and hydration, rebuilt only when the payload or attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap from the server (`getPayload()`): renders the same values on the server and in the browser. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Creates a flags client in an effect (never during\n * SSR) and destroys it on unmount; until then hooks read the `payload` snapshot. Changing\n * `attributes` re-evaluates without recreating the client.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" attributes={{ id: user.id, plan: user.plan }} payload={bootstrap}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n\n useEffect(() => {\n if (external || !sdkKey || typeof window === \"undefined\") return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n return () => {\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n"],"mappings":"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","names":["import_flags","import_react","import_jsx_runtime"]}
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { JsonValue, FlagsClientOptions, FlagsBootstrap, FlagsClient, FlagValue, FlagDetails, Attributes } from '@guidelytech/flags';
4
4
  export { Attributes, EvaluationResult, FlagDetails, FlagsBootstrap, FlagsClient, FlagsClientOptions, FlagsPayload, JsonValue } from '@guidelytech/flags';
5
5
  import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
- export { ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
6
+ export { AgentTurnInput, AgentTurnRedactor, ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
7
7
 
8
8
  /** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */
9
9
  declare function useFlag(key: string, fallback?: boolean): boolean;
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { JsonValue, FlagsClientOptions, FlagsBootstrap, FlagsClient, FlagValue, FlagDetails, Attributes } from '@guidelytech/flags';
4
4
  export { Attributes, EvaluationResult, FlagDetails, FlagsBootstrap, FlagsClient, FlagsClientOptions, FlagsPayload, JsonValue } from '@guidelytech/flags';
5
5
  import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
- export { ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
6
+ export { AgentTurnInput, AgentTurnRedactor, ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
7
7
 
8
8
  /** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */
9
9
  declare function useFlag(key: string, fallback?: boolean): boolean;
package/dist/index.js CHANGED
@@ -158,7 +158,9 @@ var NOOP_RESULTS = {
158
158
  getState: { ready: false, destroyed: false },
159
159
  getContext: null,
160
160
  getSessionId: "",
161
- isRecording: false
161
+ isRecording: false,
162
+ agentConversation: false,
163
+ trackAgentTurn: false
162
164
  };
163
165
  var noopFlags = new Proxy(createStaticFlags2(), {
164
166
  get(target, prop, receiver) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx","../src/flags.tsx"],"sourcesContent":["import { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide } from \"@guidelytech/sdk-core\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n /**\n * Flags bootstrap from the server (`getFlagsBootstrap()` / `client.getPayload()`): flag hooks\n * render the same values on the server, during hydration and after.\n */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, page and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/** The attributes the server knows about a user: what bootstrap snapshots evaluate with. */\nfunction userAttributes(user: GuidelyUser | null | undefined): Attributes {\n if (!user?.id) return {};\n return { ...(user.traits ?? {}), id: user.id, ...(user.account ? { account: { ...(user.account.traits ?? {}), id: user.account.id } } : {}) };\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const o = optionsRef.current;\n // The user is known up front so flags evaluate for them from the first render (no flicker).\n const c = createGuidely({ ...o, projectId, environment, apiUrl, user: userRef.current?.id ? userRef.current : undefined, flags: o.flags === false ? false : { ...(o.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current } });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n const bootstrap = useBootstrap(payload, { ...userAttributes(user), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>{children}</FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n getSessionId: \"\",\n isRecording: false,\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n","import { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\n/** What the flag hooks read: the live client once created, else a static snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useReader(): FlagsReader {\n const src = useContext(FlagsContext);\n return src?.client ?? src?.bootstrap ?? EMPTY;\n}\n\n/**\n * Subscribes to the flags with `useSyncExternalStore`. Values are compared deeply so object\n * flags keep their identity between renders. The server snapshot is the bootstrap payload, so\n * server-rendered HTML and hydration agree.\n */\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const reader = useReader();\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (or failed to and serve fallbacks); true from the start with a bootstrap payload. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` on the server and before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot for SSR and hydration, rebuilt only when the payload or attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap from the server (`getPayload()`): renders the same values on the server and in the browser. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Creates a flags client in an effect (never during\n * SSR) and destroys it on unmount; until then hooks read the `payload` snapshot. Changing\n * `attributes` re-evaluates without recreating the client.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" attributes={{ id: user.id, plan: user.plan }} payload={bootstrap}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n\n useEffect(() => {\n if (external || !sdkKey || typeof window === \"undefined\") return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n return () => {\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n"],"mappings":"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","names":["createStaticFlags","stableStringify","createContext","useContext","useEffect","useMemo","useRef","useState","jsx","createContext","useState","useRef","useMemo","stableStringify","useEffect","createStaticFlags","useContext"]}
1
+ {"version":3,"sources":["../src/index.tsx","../src/flags.tsx"],"sourcesContent":["import { createStaticFlags, stableStringify, type Attributes, type FlagDetails, type FlagsBootstrap, type FlagsClient } from \"@guidelytech/flags\";\nimport { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { FlagsContext, useBootstrap, type FlagsSource } from \"./flags\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide, AgentTurnInput, AgentTurnRedactor } from \"@guidelytech/sdk-core\";\nexport { useFlag, useFeatureValue, useFlagDetails, useFlags, useFlagsReady, useFlagsClient, Feature, FeatureFlag, FeatureValue, FlagsProvider } from \"./flags\";\nexport type { FeatureProps, FeatureValueProps, FlagsProviderProps } from \"./flags\";\nexport type { FlagsClient, FlagsClientOptions, FlagDetails, FlagsBootstrap, FlagsPayload, Attributes, JsonValue, EvaluationResult } from \"@guidelytech/flags\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n /**\n * Flags bootstrap from the server (`getFlagsBootstrap()` / `client.getPayload()`): flag hooks\n * render the same values on the server, during hydration and after.\n */\n flagsPayload?: FlagsBootstrap | null;\n /** Extra flag attributes (merged over the automatic identity, page and device attributes). */\n flagAttributes?: Attributes;\n children?: ReactNode;\n}\n\n/** The attributes the server knows about a user: what bootstrap snapshots evaluate with. */\nfunction userAttributes(user: GuidelyUser | null | undefined): Attributes {\n if (!user?.id) return {};\n return { ...(user.traits ?? {}), id: user.id, ...(user.account ? { account: { ...(user.account.traits ?? {}), id: user.account.id } } : {}) };\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const userRef = useRef(user);\n userRef.current = user;\n const flagsOpts = options.flags === false ? null : (options.flags ?? {});\n const payload = flagsPayload ?? flagsOpts?.payload ?? null;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n const appAttributes = useMemo(() => ({ ...(flagsOpts?.attributes ?? {}), ...(flagAttributes ?? {}) }), [stableStringify(flagsOpts?.attributes ?? {}), stableStringify(flagAttributes ?? {})]);\n const appAttributesRef = useRef(appAttributes);\n appAttributesRef.current = appAttributes;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const o = optionsRef.current;\n // The user is known up front so flags evaluate for them from the first render (no flicker).\n const c = createGuidely({ ...o, projectId, environment, apiUrl, user: userRef.current?.id ? userRef.current : undefined, flags: o.flags === false ? false : { ...(o.flags ?? {}), payload: payloadRef.current ?? undefined, attributes: appAttributesRef.current } });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n useEffect(() => {\n client?.flags.setAttributes(appAttributes);\n }, [client, appAttributes]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n const bootstrap = useBootstrap(payload, { ...userAttributes(user), ...appAttributes });\n const flags = useMemo<FlagsSource>(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);\n return (\n <GuidelyContext.Provider value={client}>\n <FlagsContext.Provider value={flags}>{children}</FlagsContext.Provider>\n </GuidelyContext.Provider>\n );\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n getSessionId: \"\",\n isRecording: false,\n agentConversation: false,\n trackAgentTurn: false,\n};\n\n/** Flags that serve every fallback; `useGuidely().flags` before the provider has a client. */\nconst noopFlags = new Proxy(createStaticFlags() as unknown as FlagsClient, {\n get(target, prop, receiver) {\n if (prop in target) return Reflect.get(target, prop, receiver);\n if (prop === \"ready\" || prop === \"refresh\" || prop === \"flush\") return () => Promise.resolve();\n if (prop === \"getPayload\") return () => null;\n if (prop === \"forUser\") return () => target;\n return typeof prop === \"string\" ? () => undefined : undefined;\n },\n});\n\nconst missing = <T,>(key: string, fallback: T): FlagDetails<T> => ({ key, value: fallback, reason: \"FLAG_NOT_FOUND\", inExperiment: false, usedFallback: true });\n\n/** Methods whose no-op answer depends on the arguments (flag getters return the fallback). */\nconst NOOP_FUNCTIONS: Record<string, (...args: any[]) => unknown> = {\n isFeatureEnabled: (_key: string, fallback = false) => fallback,\n getFeatureValue: (_key: string, fallback: unknown) => fallback,\n getFeatureDetails: (key: string, fallback: unknown) => missing(key, fallback),\n onFlagsChange: () => () => {},\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (prop === \"flags\") return noopFlags;\n if (typeof prop !== \"string\") return undefined;\n return NOOP_FUNCTIONS[prop] ?? (() => NOOP_RESULTS[prop]);\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n","import { createFlagsClient, createStaticFlags, jsonEquals, stableStringify, type Attributes, type FlagDetails, type FlagValue, type FlagsBootstrap, type FlagsClient, type FlagsClientOptions, type FlagsReader, type JsonValue } from \"@guidelytech/flags\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type ReactNode } from \"react\";\n\n/** What the flag hooks read: the live client once created, else a static snapshot of the bootstrap payload. */\nexport interface FlagsSource {\n client: FlagsClient | null;\n bootstrap: FlagsReader;\n}\n\nexport const FlagsContext = createContext<FlagsSource | null>(null);\n\nconst EMPTY = createStaticFlags();\n\nfunction useReader(): FlagsReader {\n const src = useContext(FlagsContext);\n return src?.client ?? src?.bootstrap ?? EMPTY;\n}\n\n/**\n * Subscribes to the flags with `useSyncExternalStore`. Values are compared deeply so object\n * flags keep their identity between renders. The server snapshot is the bootstrap payload, so\n * server-rendered HTML and hydration agree.\n */\nfunction useFlagsValue<T>(select: (reader: FlagsReader) => T): T {\n const reader = useReader();\n const cache = useRef<{ reader: FlagsReader; value: T } | null>(null);\n const get = () => {\n const value = select(reader);\n const c = cache.current;\n if (c && c.reader === reader && jsonEquals(c.value, value)) return c.value;\n cache.current = { reader, value };\n return value;\n };\n return useSyncExternalStore(reader.subscribe, get, get);\n}\n\n/** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */\nexport function useFlag(key: string, fallback = false): boolean {\n return useFlagsValue((r) => r.isEnabled(key, fallback));\n}\n\n/** A flag's value (string, number, JSON…); `fallback` when missing or of a different type. */\nexport function useFeatureValue<T extends JsonValue>(key: string, fallback: T): FlagValue<T> {\n return useFlagsValue((r) => r.getValue(key, fallback));\n}\n\n/** A flag's value plus why it was served (reason, rule, variation, experiment). */\nexport function useFlagDetails<T extends JsonValue>(key: string, fallback: T): FlagDetails<FlagValue<T>> {\n return useFlagsValue((r) => r.getDetails(key, fallback));\n}\n\n/** Every flag's value (records no exposures). */\nexport function useFlags(): Record<string, JsonValue> {\n return useFlagsValue((r) => r.getAll());\n}\n\n/** True once flags have loaded (or failed to and serve fallbacks); true from the start with a bootstrap payload. */\nexport function useFlagsReady(): boolean {\n return useFlagsValue((r) => r.isReady());\n}\n\n/** The flags client (`null` on the server and before the provider has created it). */\nexport function useFlagsClient(): FlagsClient | null {\n return useContext(FlagsContext)?.client ?? null;\n}\n\nexport interface FeatureProps {\n flag: string;\n children?: ReactNode;\n /** Rendered while the flag is off (default: nothing). */\n fallback?: ReactNode;\n}\n\n/** Renders `children` when the boolean flag is on, else `fallback`. */\nexport function Feature({ flag, children, fallback = null }: FeatureProps) {\n return <>{useFlag(flag) ? children : fallback}</>;\n}\n\n/** Alias of {@link Feature}. */\nexport const FeatureFlag = Feature;\n\nexport interface FeatureValueProps extends FeatureProps {\n /** Renders `children` when the flag's value equals this (deep equality). */\n value: JsonValue;\n}\n\n/** Renders `children` when the flag's value equals `value` (e.g. an experiment variation), else `fallback`. */\nexport function FeatureValue({ flag, value, children, fallback = null }: FeatureValueProps) {\n const current = useFeatureValue<JsonValue>(flag, null);\n return <>{jsonEquals(current, value) ? children : fallback}</>;\n}\n\n/** A static snapshot for SSR and hydration, rebuilt only when the payload or attributes change. */\nexport function useBootstrap(payload: FlagsBootstrap | null | undefined, attributes: Attributes): FlagsReader {\n const key = stableStringify(attributes);\n return useMemo(() => (payload ? createStaticFlags({ payload, attributes }) : EMPTY), [payload, key]);\n}\n\nexport interface FlagsProviderProps extends Omit<FlagsClientOptions, \"payload\"> {\n /** Bootstrap from the server (`getPayload()`): renders the same values on the server and in the browser. */\n payload?: FlagsBootstrap | null;\n /** Use an existing client instead of creating one. */\n client?: FlagsClient;\n children?: ReactNode;\n}\n\n/**\n * Feature flags only (no guides or analytics). Creates a flags client in an effect (never during\n * SSR) and destroys it on unmount; until then hooks read the `payload` snapshot. Changing\n * `attributes` re-evaluates without recreating the client.\n *\n * ```tsx\n * <FlagsProvider sdkKey=\"pk_prod_…\" attributes={{ id: user.id, plan: user.plan }} payload={bootstrap}>\n * ```\n */\nexport function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps) {\n const [created, setCreated] = useState<FlagsClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const sdkKey = options.sdkKey ?? options.projectId;\n const { apiUrl, environment } = options;\n const payloadRef = useRef(payload);\n payloadRef.current = payload;\n\n useEffect(() => {\n if (external || !sdkKey || typeof window === \"undefined\") return;\n let c: FlagsClient;\n try {\n c = createFlagsClient({ ...optionsRef.current, sdkKey, payload: payloadRef.current ?? undefined });\n } catch (err) {\n optionsRef.current.onError?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n setCreated(c);\n return () => {\n c.destroy();\n setCreated((cur) => (cur === c ? null : cur));\n };\n }, [external, sdkKey, apiUrl, environment]);\n\n const client = external ?? created;\n const attributes = options.attributes ?? {};\n const attrsKey = stableStringify(attributes);\n useEffect(() => {\n if (client && options.attributes) client.setAttributes(options.attributes);\n }, [client, attrsKey]);\n\n const bootstrap = useBootstrap(payload, attributes);\n const value = useMemo<FlagsSource>(() => ({ client, bootstrap }), [client, bootstrap]);\n return <FlagsContext.Provider value={value}>{children}</FlagsContext.Provider>;\n}\n"],"mappings":"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","names":["createStaticFlags","stableStringify","createContext","useContext","useEffect","useMemo","useRef","useState","jsx","createContext","useState","useRef","useMemo","stableStringify","useEffect","createStaticFlags","useContext"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guidelytech/react",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "React provider and hooks for Guidely",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,9 +20,9 @@
20
20
  "README.md"
21
21
  ],
22
22
  "dependencies": {
23
- "@guidelytech/shared": "0.10.0",
24
- "@guidelytech/flags": "0.10.0",
25
- "@guidelytech/sdk-core": "0.10.0"
23
+ "@guidelytech/sdk-core": "0.12.0",
24
+ "@guidelytech/flags": "0.12.0",
25
+ "@guidelytech/shared": "0.12.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.5.1",