{"version":3,"file":"selectors.cjs","names":["NAMESPACE_SEPARATOR","useProjection","getRegistry","STREAM_CONTROLLER"],"sources":["../src/selectors.ts"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useMemo, useSyncExternalStore } from \"react\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type {\n  MessageMetadata,\n  MessageMetadataMap,\n  SubmissionQueueEntry,\n  SubmissionQueueSnapshot,\n} from \"@langchain/langgraph-sdk/stream\";\nimport {\n  NAMESPACE_SEPARATOR,\n  audioProjection,\n  channelProjection,\n  extensionProjection,\n  filesProjection,\n  imagesProjection,\n  messagesProjection,\n  toolCallsProjection,\n  valuesProjection,\n  videoProjection,\n  type AssembledToolCall,\n  type AudioMedia,\n  type Channel,\n  type ChannelProjectionOptions,\n  type Event,\n  type FileMedia,\n  type ImageMedia,\n  type InferToolCalls,\n  type InferStateType,\n  type SubagentDiscoverySnapshot,\n  type SubgraphDiscoverySnapshot,\n  type VideoMedia,\n} from \"@langchain/langgraph-sdk/stream\";\nimport {\n  getRegistry,\n  STREAM_CONTROLLER,\n  type UseStreamReturn,\n} from \"./use-stream.js\";\nimport { useProjection } from \"./use-projection.js\";\n\n/**\n * Selector hooks don't need to carry `InterruptType` /\n * `ConfigurableType` — they only ever read state. Accepting a\n * `StateType`-parameterised stream (with the other two generics\n * widened to `any`) lets callers keep their full\n * `useStream<State, Interrupt, Configurable>()` handle\n * without re-declaring the interrupt / configurable shapes at every\n * selector call site.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype StreamHandle<StateType extends object> = UseStreamReturn<\n  StateType,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  any,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  any\n>;\n\n/**\n * What a selector hook can be targeted at. Callers can pass any of:\n *  - `undefined`                      — root namespace (cheap: served by the always-on root store)\n *  - a {@link SubagentDiscoverySnapshot}  — the snapshot returned by `stream.subagents.get(...)`\n *  - a {@link SubgraphDiscoverySnapshot}  — the snapshot returned by `stream.subgraphs.get(...)`\n *  - an explicit `{ namespace: string[] }` — any other namespaced scope\n *  - a raw `string[]`                  — escape hatch identical to the object form\n */\nexport type SelectorTarget =\n  | undefined\n  | null\n  | readonly string[]\n  | { namespace: readonly string[] }\n  | SubagentDiscoverySnapshot\n  | SubgraphDiscoverySnapshot;\n\nfunction resolveNamespace(target: SelectorTarget): readonly string[] {\n  if (target == null) return EMPTY_NAMESPACE;\n  if (Array.isArray(target)) return target;\n  const obj = target as { namespace?: readonly string[] };\n  return obj.namespace ?? EMPTY_NAMESPACE;\n}\n\nconst EMPTY_NAMESPACE: readonly string[] = [];\n\nfunction isRoot(namespace: readonly string[]): boolean {\n  return namespace.length === 0;\n}\n\nfunction namespaceKey(namespace: readonly string[]): string {\n  return namespace.join(NAMESPACE_SEPARATOR);\n}\n\n// The stream type we accept for selectors — purposely loose so\n// selector hooks remain callable from components that don't carry\n// the exact State/Interrupt/Configurable generics. We use `any` for\n// all three generics because `UseStreamReturn` is\n// invariant in `State` and `Configurable` (they flow through both\n// reader and writer positions), so a concrete\n// `useStream<typeof agent>()` handle wouldn't flow into\n// a `<object, unknown, object>` slot otherwise.\n//\n// Typed selectors (`useValues<S>` etc.) use {@link StreamHandle}\n// above so the concrete `StateType` flows into the return; hooks\n// that don't depend on state (`useMessages`, `useAudio`, …) stay on\n// `AnyStream` for maximum flexibility.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyStream = UseStreamReturn<any, any, any>;\n\n/**\n * Subscribe to a scoped `messages` stream. Pass `stream` and\n * optionally a subagent/subgraph snapshot (or any namespaced target).\n *\n * Contract:\n *  - At the root (no target) this returns `stream.messages` directly\n *    — no extra subscription is opened. `stream.messages` is the\n *    live merge of `messages`-channel token deltas and\n *    `values.messages` snapshots (see\n *    {@link UseStreamReturn.messages}), so token-by-token\n *    streaming here depends on the backend emitting `messages`\n *    channel events. Backends that only emit `values` updates will\n *    render full turns at once rather than streaming.\n *  - For any other namespace, the mount triggers a ref-counted\n *    `messages` subscription scoped to that namespace. Unmounting\n *    the last component that watches this namespace closes the\n *    subscription automatically.\n *\n * Messages are always `BaseMessage` class instances from\n * `@langchain/core/messages`.\n */\nexport function useMessages(\n  stream: AnyStream,\n  target?: SelectorTarget\n): BaseMessage[] {\n  const namespace = resolveNamespace(target);\n  const key = `messages|${namespaceKey(namespace)}`;\n  const registry = isRoot(namespace) ? null : getRegistry(stream);\n  const scoped = useProjection<BaseMessage[]>(\n    registry,\n    () => messagesProjection(namespace),\n    key,\n    EMPTY_MESSAGES\n  );\n  return isRoot(namespace) ? stream.messages : scoped;\n}\n\nconst EMPTY_MESSAGES: BaseMessage[] = [];\n\n/**\n * Subscribe to a scoped `tools` (tool-call) stream. Same target and\n * lifecycle rules as {@link useMessages}; at the root this just returns\n * `stream.toolCalls`.\n *\n * The optional generic `T` can be passed to narrow the type of\n * assembled tool calls on the returned array. Accepts either:\n *  - an agent brand (`typeof agent`) — union is derived from the\n *    agent's declared tools via {@link InferToolCalls};\n *  - an array of LangGraph tools (`typeof tools`) — union is derived\n *    from {@link InferToolCalls} (parallel to {@link ToolCallsFromTools}).\n *\n * When omitted, returns the plain `AssembledToolCall[]` union used by\n * the controller.\n */\nexport function useToolCalls(\n  stream: AnyStream,\n  target?: SelectorTarget\n): AssembledToolCall[];\nexport function useToolCalls<T>(\n  stream: AnyStream,\n  target?: SelectorTarget\n): InferToolCalls<T>[];\nexport function useToolCalls(\n  stream: AnyStream,\n  target?: SelectorTarget\n): AssembledToolCall[] {\n  const namespace = resolveNamespace(target);\n  const key = `toolCalls|${namespaceKey(namespace)}`;\n  const registry = isRoot(namespace) ? null : getRegistry(stream);\n  const scoped = useProjection<AssembledToolCall[]>(\n    registry,\n    () => toolCallsProjection(namespace),\n    key,\n    EMPTY_TOOLCALLS\n  );\n  return isRoot(namespace) ? stream.toolCalls : scoped;\n}\n\nconst EMPTY_TOOLCALLS: AssembledToolCall[] = [];\n\n/**\n * Subscribe to a scoped `values` stream — most-recent state payload\n * for a namespace. Equivalent to reading `stream.values` at the root.\n *\n * When the payload carries a `messages` array, it is coerced to\n * `BaseMessage` instances to keep parity with the root projection.\n *\n * Typing:\n *  - **Root** (`useValues(stream)`): returns the `StateType` declared\n *    on the parent `useStream<State>()` — no explicit\n *    generic required. Non-nullable because the root snapshot always\n *    carries `values` (falling back to `initialValues ?? {}`).\n *  - **Scoped** (`useValues(stream, target)`): the scoped payload can\n *    have a different shape than the root state (e.g. a subagent\n *    returning its own substate). Callers should annotate the\n *    expected shape explicitly: `useValues<SubagentState>(stream, sub)`.\n *    Defaults to `unknown` when not annotated.\n */\nexport function useValues<StateType extends object>(\n  stream: StreamHandle<StateType>\n): StateType;\n/**\n * Explicit-generic override. Accepts:\n *  - an agent brand or compiled graph (unwrapped via\n *    {@link InferStateType});\n *  - a plain state shape (returned as-is).\n *\n * The root-call form is non-nullable (the root snapshot is always\n * present); the scoped form returns `T | undefined` because a\n * projection may not have emitted a payload yet.\n */\nexport function useValues<T>(stream: AnyStream): InferStateType<T>;\nexport function useValues<T = unknown>(\n  stream: AnyStream,\n  target: SelectorTarget,\n  options?: { messagesKey?: string }\n): T | undefined;\nexport function useValues(\n  stream: AnyStream,\n  target?: SelectorTarget,\n  options?: { messagesKey?: string }\n): unknown {\n  const namespace = resolveNamespace(target);\n  const messagesKey = options?.messagesKey ?? \"messages\";\n  const key = `values|${messagesKey}|${namespaceKey(namespace)}`;\n  const registry = isRoot(namespace) ? null : getRegistry(stream);\n  const scoped = useProjection<unknown>(\n    registry,\n    () => valuesProjection<unknown>(namespace, messagesKey),\n    key,\n    undefined\n  );\n  return isRoot(namespace) ? stream.values : scoped;\n}\n\n/**\n * Subscribe to a `custom:<name>` stream extension — most-recent\n * payload emitted by the transformer, scoped to the target namespace.\n */\nexport function useExtension<T = unknown>(\n  stream: AnyStream,\n  name: string,\n  target?: SelectorTarget\n): T | undefined {\n  const namespace = resolveNamespace(target);\n  const key = `extension|${name}|${namespaceKey(namespace)}`;\n  return useProjection<T | undefined>(\n    getRegistry(stream),\n    () => extensionProjection<T>(name, namespace),\n    key,\n    undefined\n  );\n}\n\n/**\n * Raw-events escape hatch. Subscribes to one or more channels at a\n * namespace and returns a bounded buffer of raw protocol events.\n * Prefer {@link useMessages} / {@link useToolCalls} / {@link useValues}\n * for the common cases.\n */\n/**\n * Subscribe to a scoped audio-media stream. Returns an array of\n * {@link AudioMedia} handles, one per message containing at least one\n * `AudioBlock` in the target namespace.\n *\n * Each handle is yielded on its first matching `content-block-start`,\n * exposes `.partialBytes` for live access, settles `.blob` /\n * `.objectURL` / `.transcript` on `message-finish`, and surfaces\n * fail-loud errors via `.error`.\n *\n * Pair with {@link useMediaURL} to turn a handle into an `<audio src>`.\n */\nexport function useAudio(\n  stream: AnyStream,\n  target?: SelectorTarget\n): AudioMedia[] {\n  const namespace = resolveNamespace(target);\n  const key = `audio|${namespaceKey(namespace)}`;\n  return useProjection<AudioMedia[]>(\n    getRegistry(stream),\n    () => audioProjection(namespace),\n    key,\n    EMPTY_AUDIO\n  );\n}\n\nconst EMPTY_AUDIO: AudioMedia[] = [];\n\n/**\n * Subscribe to a scoped image-media stream. See {@link useAudio} for\n * shared semantics; pair with {@link useMediaURL} for `<img src>`.\n */\nexport function useImages(\n  stream: AnyStream,\n  target?: SelectorTarget\n): ImageMedia[] {\n  const namespace = resolveNamespace(target);\n  const key = `images|${namespaceKey(namespace)}`;\n  return useProjection<ImageMedia[]>(\n    getRegistry(stream),\n    () => imagesProjection(namespace),\n    key,\n    EMPTY_IMAGES\n  );\n}\n\nconst EMPTY_IMAGES: ImageMedia[] = [];\n\n/**\n * Subscribe to a scoped video-media stream. See {@link useAudio} for\n * shared semantics; pair with {@link useMediaURL} for `<video src>`.\n */\nexport function useVideo(\n  stream: AnyStream,\n  target?: SelectorTarget\n): VideoMedia[] {\n  const namespace = resolveNamespace(target);\n  const key = `video|${namespaceKey(namespace)}`;\n  return useProjection<VideoMedia[]>(\n    getRegistry(stream),\n    () => videoProjection(namespace),\n    key,\n    EMPTY_VIDEO\n  );\n}\n\nconst EMPTY_VIDEO: VideoMedia[] = [];\n\n/**\n * Subscribe to a scoped file-media stream. See {@link useAudio} for\n * shared semantics; pair with {@link useMediaURL} for an\n * `<a download href>` target.\n */\nexport function useFiles(\n  stream: AnyStream,\n  target?: SelectorTarget\n): FileMedia[] {\n  const namespace = resolveNamespace(target);\n  const key = `files|${namespaceKey(namespace)}`;\n  return useProjection<FileMedia[]>(\n    getRegistry(stream),\n    () => filesProjection(namespace),\n    key,\n    EMPTY_FILES\n  );\n}\n\nconst EMPTY_FILES: FileMedia[] = [];\n\nexport type UseChannelOptions = ChannelProjectionOptions;\n\nexport function useChannel(\n  stream: AnyStream,\n  channels: readonly Channel[],\n  target?: SelectorTarget,\n  options?: UseChannelOptions\n): Event[] {\n  const namespace = resolveNamespace(target);\n  const channelKey = useMemo(() => [...channels].sort().join(\",\"), [channels]);\n  const key = `channel|${options?.bufferSize ?? \"default\"}|${(options?.replay ?? true) ? \"replay\" : \"live\"}|${channelKey}|${namespaceKey(namespace)}`;\n  return useProjection<Event[]>(\n    getRegistry(stream),\n    () => channelProjection(channels, namespace, options),\n    key,\n    EMPTY_EVENTS\n  );\n}\n\nconst EMPTY_EVENTS: Event[] = [];\n\n/**\n * Read metadata recorded for a specific message id — today exposes\n * `parentCheckpointId`, the checkpoint the message was first seen on.\n * Designed for fork / edit flows:\n *\n * ```tsx\n * const { parentCheckpointId } = useMessageMetadata(stream, msg.id) ?? {};\n * if (parentCheckpointId) {\n *   await stream.submit(input, { forkFrom: parentCheckpointId });\n * }\n * ```\n *\n * Returns `undefined` when the id isn't known yet (e.g. the server\n * hasn't emitted `parent_checkpoint` for that message, or the message\n * arrived via `messages`-channel deltas only and no `values` snapshot\n * has landed for it yet).\n */\nexport function useMessageMetadata(\n  stream: AnyStream,\n  messageId: string | undefined\n): MessageMetadata | undefined {\n  const store = stream[STREAM_CONTROLLER].messageMetadataStore;\n  const snapshot = useSyncExternalStore<MessageMetadataMap>(\n    store.subscribe,\n    store.getSnapshot,\n    store.getSnapshot\n  );\n  return messageId == null ? undefined : snapshot.get(messageId);\n}\n\n/**\n * Reactive handle on the server-side submission queue.\n *\n * Populated when `submit()` is invoked with `multitaskStrategy:\n * \"enqueue\"` while another run is in flight. The returned object is\n * stable per snapshot so consumers can pass `entries` straight into a\n * `<Fragment key={e.id}>` list without extra memoisation.\n */\nexport interface UseSubmissionQueueReturn<\n  StateType extends object = Record<string, unknown>,\n> {\n  readonly entries: SubmissionQueueSnapshot<StateType>;\n  readonly size: number;\n  cancel(id: string): Promise<boolean>;\n  clear(): Promise<void>;\n}\n\nexport function useSubmissionQueue<StateType extends object>(\n  stream: StreamHandle<StateType>\n): UseSubmissionQueueReturn<StateType>;\nexport function useSubmissionQueue(stream: AnyStream): UseSubmissionQueueReturn;\nexport function useSubmissionQueue(\n  stream: AnyStream\n): UseSubmissionQueueReturn {\n  const controller = stream[STREAM_CONTROLLER];\n  const store = controller.queueStore;\n  const entries = useSyncExternalStore<SubmissionQueueSnapshot>(\n    store.subscribe,\n    store.getSnapshot,\n    store.getSnapshot\n  );\n  return useMemo<UseSubmissionQueueReturn>(\n    () => ({\n      entries,\n      size: entries.length,\n      cancel: (id) => controller.cancelQueued(id),\n      clear: () => controller.clearQueue(),\n    }),\n    [entries, controller]\n  );\n}\n\nexport type { SubmissionQueueEntry, SubmissionQueueSnapshot };\n"],"mappings":"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"}