UNPKG

@langchain/langgraph

Version:
1 lines 8.66 kB
{"version":3,"file":"subgraphs.cjs","names":["hasPrefix","nsKey"],"sources":["../../../src/stream/transformers/subgraphs.ts"],"sourcesContent":["/**\n * SubgraphDiscoveryTransformer - materializes a {@link StreamHandle} for\n * each newly observed top-level subgraph namespace and announces it on\n * the mux's shared {@link StreamMux._discoveries} channel.\n *\n * Previously this work was inlined in {@link StreamMux.push}. Extracting\n * it into a transformer aligns discovery with the rest of the stream\n * architecture (lifecycle, values, messages are all transformers),\n * isolates the factory wiring, and makes discovery behavior\n * independently testable.\n *\n * The transformer also owns the read-side of discovery: it exposes an\n * `AsyncIterable<TStream>` projection (`subgraphs`) scoped to the root\n * namespace, and a {@link filterSubgraphHandles} helper that callers\n * can use to scope the same channel to any descendant namespace. This\n * lets `GraphRunStream` drop its bespoke `subscribeSubgraphs`\n * delegation and surface child streams via the standard native\n * projection pattern.\n *\n * Only first-level namespace segments are announced. Deeper segments\n * (e.g. `[\"researcher:uuid\", \"tools:uuid\"]`) are internal Pregel\n * checkpoint namespaces for nodes inside a subgraph and should not\n * appear as user-facing `SubgraphRunStream` instances; the mux still\n * resolves their values via its own `#streamMap` when registered\n * elsewhere.\n */\n\nimport { hasPrefix, nsKey } from \"../mux.js\";\nimport type { StreamHandle, StreamMux, SubgraphDiscovery } from \"../mux.js\";\nimport type {\n Namespace,\n NativeStreamTransformer,\n ProtocolEvent,\n} from \"../types.js\";\nimport type { StreamChannel } from \"../stream-channel.js\";\n\n/**\n * Projection returned by {@link createSubgraphDiscoveryTransformer}.\n *\n * @typeParam TStream - Concrete stream handle type produced by the\n * configured factory (e.g. `SubgraphRunStream`).\n */\nexport interface SubgraphDiscoveryProjection<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Shared discovery channel on the mux. The transformer writes to it so\n * the channel's lifetime stays tied to the mux (closed on `mux.close()`\n * / failed on `mux.fail()`). The underscore prefix signals internal\n * wiring: consumers should iterate {@link subgraphs} instead.\n */\n _discoveries: StreamChannel<SubgraphDiscovery>;\n\n /**\n * Async iterable of direct child stream handles of the root\n * namespace. Wired onto `GraphRunStream.subgraphs` during root\n * stream construction. For descendant namespaces, use\n * {@link filterSubgraphHandles} to scope the same log.\n */\n subgraphs: AsyncIterable<TStream>;\n}\n\n/**\n * Configuration for {@link createSubgraphDiscoveryTransformer}.\n */\nexport interface SubgraphDiscoveryTransformerOptions<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Factory invoked once per newly observed top-level namespace.\n *\n * Receives the discovery-channel and event-channel offsets so the resulting\n * stream can iterate only events arriving after the namespace was\n * first seen (no retroactive replay).\n *\n * @param path - The single-segment top-level namespace.\n * @param discoveryStart - Current size of the mux discovery log.\n * @param eventStart - Current size of the mux event log.\n * @returns A stream handle registered with the mux for values/error\n * resolution on close/fail.\n */\n createStream: (\n path: Namespace,\n discoveryStart: number,\n eventStart: number\n ) => TStream;\n}\n\n/**\n * Filter a {@link SubgraphDiscovery} channel to only the direct children\n * of a given namespace.\n *\n * Returns an `AsyncIterable` whose iterator yields stream handles for\n * discoveries whose namespace is exactly one segment deeper than\n * {@link path} and shares it as a prefix. Iteration begins at\n * {@link startAt} (so each caller picks up only discoveries added\n * after its construction) and terminates when the underlying log\n * closes or fails.\n *\n * @typeParam TStream - Concrete stream type recorded in the log.\n * Callers may cast if the log was populated by a specific factory.\n * @param log - The shared discovery channel (`mux._discoveries`).\n * @param path - Parent namespace whose direct children should be\n * yielded.\n * @param startAt - Zero-based index into the discovery log to begin\n * from.\n * @returns An async iterable of stream handles.\n */\nexport function filterSubgraphHandles<\n TStream extends StreamHandle = StreamHandle,\n>(\n log: StreamChannel<SubgraphDiscovery>,\n path: Namespace,\n startAt = 0\n): AsyncIterable<TStream> {\n const targetDepth = path.length + 1;\n return {\n [Symbol.asyncIterator](): AsyncIterator<TStream> {\n const base = log.iterate(startAt);\n return {\n async next(): Promise<IteratorResult<TStream>> {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const result = await base.next();\n if (result.done) {\n return { value: undefined as unknown as TStream, done: true };\n }\n const { ns, stream } = result.value;\n if (ns.length === targetDepth && hasPrefix(ns, path)) {\n return { value: stream as TStream, done: false };\n }\n }\n },\n };\n },\n };\n}\n\n/**\n * Create the subgraph discovery transformer.\n *\n * Registering this transformer against a mux replaces the legacy\n * inline behavior that previously lived in {@link StreamMux.push}.\n * The mux no longer knows about the subgraph factory: instead, this\n * transformer is the single component that materializes stream\n * handles and announces them on `_discoveries`.\n *\n * Marked as a {@link NativeStreamTransformer} so the projection is\n * treated as internal wiring (not merged into `run.extensions` and\n * not auto-forwarded via {@link StreamMux.wireChannels}).\n *\n * @typeParam TStream - Concrete stream handle type produced by\n * {@link SubgraphDiscoveryTransformerOptions.createStream}.\n * Defaults to the base {@link StreamHandle} interface.\n * @param mux - The mux whose `_discoveries` log should receive\n * discovery entries and whose `register` will be called for each\n * new stream handle.\n * @param options - Factory and related wiring.\n * @returns A native transformer that populates\n * {@link StreamMux._discoveries} and exposes a root-scoped\n * `subgraphs` iterable via its projection.\n */\nexport function createSubgraphDiscoveryTransformer<\n TStream extends StreamHandle = StreamHandle,\n>(\n mux: StreamMux,\n options: SubgraphDiscoveryTransformerOptions<TStream>\n): NativeStreamTransformer<SubgraphDiscoveryProjection<TStream>> {\n const { createStream } = options;\n const seen = new Set<string>();\n\n return {\n __native: true,\n\n init() {\n return {\n _discoveries: mux._discoveries,\n subgraphs: filterSubgraphHandles<TStream>(mux._discoveries, [], 0),\n };\n },\n\n process(event: ProtocolEvent): boolean {\n const ns = event.params.namespace;\n if (ns.length === 0) return true;\n\n const topNs = ns.slice(0, 1);\n const topKey = nsKey(topNs);\n if (seen.has(topKey)) return true;\n seen.add(topKey);\n\n const stream = createStream(\n topNs,\n mux._discoveries.size,\n mux._events.size\n );\n mux.register(topNs, stream);\n mux._discoveries.push({ ns: topNs, stream });\n return true;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,SAAgB,sBAGd,KACA,MACA,UAAU,GACc;CACxB,MAAM,cAAc,KAAK,SAAS;AAClC,QAAO,EACL,CAAC,OAAO,iBAAyC;EAC/C,MAAM,OAAO,IAAI,QAAQ,QAAQ;AACjC,SAAO,EACL,MAAM,OAAyC;AAE7C,UAAO,MAAM;IACX,MAAM,SAAS,MAAM,KAAK,MAAM;AAChC,QAAI,OAAO,KACT,QAAO;KAAE,OAAO,KAAA;KAAiC,MAAM;KAAM;IAE/D,MAAM,EAAE,IAAI,WAAW,OAAO;AAC9B,QAAI,GAAG,WAAW,eAAeA,YAAAA,UAAU,IAAI,KAAK,CAClD,QAAO;KAAE,OAAO;KAAmB,MAAM;KAAO;;KAIvD;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BH,SAAgB,mCAGd,KACA,SAC+D;CAC/D,MAAM,EAAE,iBAAiB;CACzB,MAAM,uBAAO,IAAI,KAAa;AAE9B,QAAO;EACL,UAAU;EAEV,OAAO;AACL,UAAO;IACL,cAAc,IAAI;IAClB,WAAW,sBAA+B,IAAI,cAAc,EAAE,EAAE,EAAE;IACnE;;EAGH,QAAQ,OAA+B;GACrC,MAAM,KAAK,MAAM,OAAO;AACxB,OAAI,GAAG,WAAW,EAAG,QAAO;GAE5B,MAAM,QAAQ,GAAG,MAAM,GAAG,EAAE;GAC5B,MAAM,SAASC,YAAAA,MAAM,MAAM;AAC3B,OAAI,KAAK,IAAI,OAAO,CAAE,QAAO;AAC7B,QAAK,IAAI,OAAO;GAEhB,MAAM,SAAS,aACb,OACA,IAAI,aAAa,MACjB,IAAI,QAAQ,KACb;AACD,OAAI,SAAS,OAAO,OAAO;AAC3B,OAAI,aAAa,KAAK;IAAE,IAAI;IAAO;IAAQ,CAAC;AAC5C,UAAO;;EAEV"}