@langchain/langgraph 1.3.4 → 1.3.5
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 +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/{setup/async_local_storage.cjs → node.cjs} +2 -2
- package/dist/node.cjs.map +1 -0
- package/dist/{setup/async_local_storage.js → node.js} +2 -2
- package/dist/node.js.map +1 -0
- package/dist/pregel/index.cjs +13 -12
- package/dist/pregel/index.cjs.map +1 -1
- package/dist/pregel/index.d.cts.map +1 -1
- package/dist/pregel/index.d.ts.map +1 -1
- package/dist/pregel/index.js +13 -12
- package/dist/pregel/index.js.map +1 -1
- package/dist/pregel/loop.cjs +19 -33
- package/dist/pregel/loop.cjs.map +1 -1
- package/dist/pregel/loop.js +19 -33
- package/dist/pregel/loop.js.map +1 -1
- package/dist/pregel/remote.cjs +1 -1
- package/dist/pregel/remote.cjs.map +1 -1
- package/dist/pregel/remote.d.cts +4 -3
- package/dist/pregel/remote.d.cts.map +1 -1
- package/dist/pregel/remote.d.ts +4 -3
- package/dist/pregel/remote.d.ts.map +1 -1
- package/dist/pregel/remote.js +1 -1
- package/dist/pregel/remote.js.map +1 -1
- package/dist/pregel/stream.cjs +12 -0
- package/dist/pregel/stream.cjs.map +1 -1
- package/dist/pregel/stream.d.cts +2 -24
- package/dist/pregel/stream.d.cts.map +1 -1
- package/dist/pregel/stream.d.ts +2 -24
- package/dist/pregel/stream.d.ts.map +1 -1
- package/dist/pregel/stream.js +12 -1
- package/dist/pregel/stream.js.map +1 -1
- package/dist/stream/convert.cjs +29 -23
- package/dist/stream/convert.cjs.map +1 -1
- package/dist/stream/convert.d.cts +9 -38
- package/dist/stream/convert.d.cts.map +1 -1
- package/dist/stream/convert.d.ts +9 -38
- package/dist/stream/convert.d.ts.map +1 -1
- package/dist/stream/convert.js +29 -24
- package/dist/stream/convert.js.map +1 -1
- package/dist/stream/index.cjs +1 -1
- package/dist/stream/index.d.cts +1 -1
- package/dist/stream/index.d.ts +1 -1
- package/dist/stream/index.js +1 -1
- package/dist/stream/mux.cjs +3 -4
- package/dist/stream/mux.cjs.map +1 -1
- package/dist/stream/mux.js +3 -4
- package/dist/stream/mux.js.map +1 -1
- package/dist/stream/types.d.cts +2 -2
- package/dist/stream/types.d.ts +2 -2
- package/dist/web.cjs +2 -1
- package/dist/web.d.cts +2 -2
- package/dist/web.d.ts +2 -2
- package/dist/web.js +2 -2
- package/package.json +13 -12
- package/dist/setup/async_local_storage.cjs.map +0 -1
- package/dist/setup/async_local_storage.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.js","names":["#prepareRunRequest","DrawableGraph"],"sources":["../../src/pregel/remote.ts"],"sourcesContent":["import {\n Client,\n type Checkpoint,\n type ThreadState,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Graph as DrawableGraph,\n Node as DrawableNode,\n} from \"@langchain/core/runnables/graph\";\nimport {\n mergeConfigs,\n Runnable,\n RunnableConfig,\n} from \"@langchain/core/runnables\";\nimport {\n All,\n CheckpointListOptions,\n CheckpointMetadata,\n} from \"@langchain/langgraph-checkpoint\";\nimport { StreamEvent } from \"@langchain/core/tracers/log_stream\";\nimport { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport { BaseMessage } from \"@langchain/core/messages\";\n\nimport {\n BaseChannel,\n GraphInterrupt,\n LangGraphRunnableConfig,\n RemoteException,\n} from \"../web.js\";\nimport { StrRecord } from \"./algo.js\";\nimport { PregelInputType, PregelOptions, PregelOutputType } from \"./index.js\";\nimport { PregelNode } from \"./read.js\";\nimport {\n PregelParams,\n PregelInterface,\n PregelTaskDescription,\n StateSnapshot,\n StreamMode,\n} from \"./types.js\";\nimport {\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_STREAM,\n INTERRUPT,\n isCommand,\n} from \"../constants.js\";\nimport { propagateConfigurableToMetadata } from \"./utils/config.js\";\n\nexport type RemoteGraphParams = Omit<\n PregelParams<StrRecord<string, PregelNode>, StrRecord<string, BaseChannel>>,\n \"channels\" | \"nodes\" | \"inputChannels\" | \"outputChannels\"\n> & {\n graphId: string;\n client?: Client;\n url?: string;\n apiKey?: string;\n headers?: Record<string, string>;\n streamResumable?: boolean;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst _serializeInputs = (obj: any): any => {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(_serializeInputs);\n }\n\n // Handle BaseMessage instances by converting them to a serializable format\n if (BaseMessage.isInstance(obj)) {\n const dict = obj.toDict();\n return {\n ...dict.data,\n role: obj.getType(),\n };\n }\n\n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [key, _serializeInputs(value)])\n );\n};\n\n/**\n * Return a tuple of the final list of stream modes sent to the\n * remote graph and a boolean flag indicating if only one stream mode was\n * originally requested and whether stream mode 'updates'\n * was present in the original list of stream modes.\n *\n * 'updates' mode is always added to the list of stream modes so that interrupts\n * can be detected in the remote graph.\n */\nconst getStreamModes = (\n streamMode?: StreamMode | StreamMode[],\n defaultStreamMode: StreamMode = \"updates\"\n) => {\n const updatedStreamModes: StreamMode[] = [];\n let reqUpdates = false;\n let reqSingle = true;\n\n if (\n streamMode !== undefined &&\n (typeof streamMode === \"string\" ||\n (Array.isArray(streamMode) && streamMode.length > 0))\n ) {\n reqSingle = typeof streamMode === \"string\";\n const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];\n updatedStreamModes.push(...mapped);\n } else {\n updatedStreamModes.push(defaultStreamMode);\n }\n if (updatedStreamModes.includes(\"updates\")) {\n reqUpdates = true;\n } else {\n updatedStreamModes.push(\"updates\");\n }\n return {\n updatedStreamModes,\n reqUpdates,\n reqSingle,\n };\n};\n\n/**\n * The `RemoteGraph` class is a client implementation for calling remote\n * APIs that implement the LangGraph Server API specification.\n *\n * For example, the `RemoteGraph` class can be used to call APIs from deployments\n * on LangSmith Deployment.\n *\n * `RemoteGraph` behaves the same way as a `StateGraph` and can be used directly as\n * a node in another `StateGraph`.\n *\n * @example\n * ```ts\n * import { RemoteGraph } from \"@langchain/langgraph/remote\";\n *\n * // Can also pass a LangGraph SDK client instance directly\n * const remoteGraph = new RemoteGraph({\n * graphId: process.env.LANGGRAPH_REMOTE_GRAPH_ID!,\n * apiKey: process.env.LANGGRAPH_REMOTE_GRAPH_API_KEY,\n * url: process.env.LANGGRAPH_REMOTE_GRAPH_API_URL,\n * });\n *\n * const input = {\n * messages: [\n * {\n * role: \"human\",\n * content: \"Hello world!\",\n * },\n * ],\n * };\n *\n * const config = {\n * configurable: { thread_id: \"threadId1\" },\n * };\n *\n * await remoteGraph.invoke(input, config);\n * ```\n */\nexport class RemoteGraph<\n Nn extends StrRecord<string, PregelNode> = StrRecord<string, PregelNode>,\n Cc extends StrRecord<string, BaseChannel> = StrRecord<string, BaseChannel>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ContextType extends Record<string, any> = StrRecord<string, any>,\n>\n extends Runnable<\n PregelInputType,\n PregelOutputType,\n PregelOptions<Nn, Cc, ContextType>\n >\n implements PregelInterface<Nn, Cc, ContextType>\n{\n static lc_name() {\n return \"RemoteGraph\";\n }\n\n lc_namespace = [\"langgraph\", \"pregel\"];\n\n lg_is_pregel = true;\n\n config?: RunnableConfig;\n\n graphId: string;\n\n protected client: Client;\n\n protected interruptBefore?: Array<keyof Nn> | All;\n\n protected interruptAfter?: Array<keyof Nn> | All;\n\n protected streamResumable?: boolean;\n\n constructor(params: RemoteGraphParams) {\n super(params);\n\n this.graphId = params.graphId;\n this.client =\n params.client ??\n new Client({\n apiUrl: params.url,\n apiKey: params.apiKey,\n defaultHeaders: params.headers,\n });\n this.config = params.config;\n this.interruptBefore = params.interruptBefore;\n this.interruptAfter = params.interruptAfter;\n this.streamResumable = params.streamResumable;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore Remove ignore when we remove support for 0.2 versions of core\n override withConfig(config: RunnableConfig): typeof this {\n const mergedConfig = mergeConfigs(this.config, config);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new (this.constructor as any)({ ...this, config: mergedConfig });\n }\n\n protected _sanitizeConfig(config: RunnableConfig) {\n const reservedConfigurableKeys = new Set([\n \"callbacks\",\n \"checkpoint_map\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n ]);\n\n const sanitizeObj = <T>(obj: T): T => {\n try {\n // This will only throw if we're trying to serialize a circular reference\n // or trying to serialize a BigInt...\n JSON.stringify(obj);\n return obj;\n } catch {\n const seen = new WeakSet();\n return JSON.parse(\n JSON.stringify(obj, (_, value) => {\n if (typeof value === \"object\" && value != null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n\n if (typeof value === \"bigint\") return value.toString();\n return value;\n })\n );\n }\n };\n\n const propagateMetadataDefaults = (obj: unknown) => {\n const seen = new WeakSet<object>();\n const visit = (value: unknown) => {\n if (typeof value !== \"object\" || value == null) {\n return;\n }\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n const record = value as Record<string, unknown>;\n const configurable = record.configurable;\n if (\n typeof configurable === \"object\" &&\n configurable != null &&\n !Array.isArray(configurable)\n ) {\n const metadata =\n typeof record.metadata === \"object\" &&\n record.metadata != null &&\n !Array.isArray(record.metadata)\n ? (record.metadata as Record<string, unknown>)\n : undefined;\n record.metadata =\n propagateConfigurableToMetadata(\n configurable as Record<string, unknown>,\n metadata\n ) ?? record.metadata;\n }\n for (const nestedValue of Object.values(record)) {\n visit(nestedValue);\n }\n };\n visit(obj);\n };\n\n propagateMetadataDefaults(config);\n\n // Remove non-JSON serializable fields from the config\n const sanitizedConfig = sanitizeObj(config);\n\n // Only include configurable keys that are not reserved and\n // not starting with \"__pregel_\" prefix\n const newConfigurable = Object.fromEntries(\n Object.entries(sanitizedConfig.configurable ?? {}).filter(\n ([k]) => !reservedConfigurableKeys.has(k) && !k.startsWith(\"__pregel_\")\n )\n );\n\n return {\n tags: sanitizedConfig.tags ?? [],\n metadata: sanitizedConfig.metadata ?? {},\n configurable: newConfigurable,\n recursion_limit: sanitizedConfig.recursionLimit,\n };\n }\n\n /**\n * Prepare config and thread ID for remote run API calls.\n *\n * `thread_id` is passed via the URL path, not in `config.configurable`, so the\n * server can accept a separate `context` payload for stateful runs.\n */\n #prepareRunRequest(mergedConfig: LangGraphRunnableConfig): {\n threadId: string | undefined;\n context: unknown;\n config: ReturnType<RemoteGraph[\"_sanitizeConfig\"]>;\n } {\n const context = mergedConfig.context;\n const sanitizedConfig = this._sanitizeConfig(mergedConfig);\n const configurable = { ...sanitizedConfig.configurable };\n const threadId = configurable.thread_id as string | undefined;\n delete configurable.thread_id;\n\n return {\n threadId,\n context,\n config: {\n ...sanitizedConfig,\n configurable,\n },\n };\n }\n\n protected _getConfig(checkpoint: Record<string, unknown>): RunnableConfig {\n return {\n configurable: {\n thread_id: checkpoint.thread_id,\n checkpoint_ns: checkpoint.checkpoint_ns,\n checkpoint_id: checkpoint.checkpoint_id,\n checkpoint_map: checkpoint.checkpoint_map ?? {},\n },\n };\n }\n\n protected _checkpointToConfig(\n checkpoint?: Partial<Checkpoint> | null,\n fallbackConfig?: RunnableConfig\n ): RunnableConfig {\n const resolvedCheckpoint =\n checkpoint ?? this._getCheckpoint(fallbackConfig);\n if (resolvedCheckpoint == null) {\n return { configurable: {} };\n }\n\n const configurable: Record<string, unknown> = {};\n if (resolvedCheckpoint.thread_id !== undefined) {\n configurable.thread_id = resolvedCheckpoint.thread_id;\n }\n if (resolvedCheckpoint.checkpoint_ns !== undefined) {\n configurable.checkpoint_ns = resolvedCheckpoint.checkpoint_ns;\n }\n if (resolvedCheckpoint.checkpoint_id !== undefined) {\n configurable.checkpoint_id = resolvedCheckpoint.checkpoint_id;\n }\n\n const hasCheckpointFields =\n resolvedCheckpoint.checkpoint_ns !== undefined ||\n resolvedCheckpoint.checkpoint_id !== undefined ||\n resolvedCheckpoint.checkpoint_map !== undefined;\n if (hasCheckpointFields) {\n configurable.checkpoint_map = resolvedCheckpoint.checkpoint_map ?? {};\n }\n\n return { configurable };\n }\n\n protected _getCheckpoint(config?: RunnableConfig): Checkpoint | undefined {\n if (config?.configurable === undefined) {\n return undefined;\n }\n\n const checkpointKeys = [\n \"thread_id\",\n \"checkpoint_ns\",\n \"checkpoint_id\",\n \"checkpoint_map\",\n ] as const;\n\n const checkpoint = Object.fromEntries(\n checkpointKeys\n .map((key) => [key, config.configurable![key]])\n .filter(([_, value]) => value !== undefined)\n );\n\n return Object.keys(checkpoint).length > 0 ? checkpoint : undefined;\n }\n\n protected _createStateSnapshot(\n state: ThreadState,\n fallbackConfig?: RunnableConfig\n ): StateSnapshot {\n const tasks: PregelTaskDescription[] = state.tasks.map((task) => {\n return {\n id: task.id,\n name: task.name,\n error: task.error ? { message: task.error } : undefined,\n // TODO: remove in LangGraph.js 0.4\n interrupts: task.interrupts.map(({ id, ...rest }) => ({\n interrupt_id: id,\n ...rest,\n })),\n // eslint-disable-next-line no-nested-ternary\n state: task.state\n ? this._createStateSnapshot(\n task.state,\n task.checkpoint\n ? this._checkpointToConfig(task.checkpoint)\n : fallbackConfig\n )\n : task.checkpoint\n ? { configurable: task.checkpoint }\n : undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result: (task as any).result,\n };\n });\n\n return {\n values: state.values,\n next: state.next ? [...state.next] : [],\n // TODO: Fix SDK typing. `ThreadState.checkpoint` is typed as non-null,\n // but deployments can return `null` (e.g. a thread that exists but has\n // not produced a checkpoint yet). See #2328.\n config: this._checkpointToConfig(\n state.checkpoint as Checkpoint | null,\n fallbackConfig\n ),\n metadata: state.metadata\n ? (state.metadata as CheckpointMetadata)\n : undefined,\n createdAt: state.created_at ?? undefined,\n parentConfig: state.parent_checkpoint\n ? this._checkpointToConfig(state.parent_checkpoint)\n : undefined,\n tasks,\n };\n }\n\n override async invoke(\n input: PregelInputType,\n options?: Partial<PregelOptions<Nn, Cc, ContextType>>\n ): Promise<PregelOutputType> {\n let lastValue;\n const stream = await this.stream(input, {\n ...options,\n streamMode: \"values\",\n });\n for await (const chunk of stream) {\n lastValue = chunk;\n }\n return lastValue;\n }\n\n override streamEvents(\n input: PregelInputType,\n options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n }\n ): IterableReadableStream<StreamEvent>;\n\n override streamEvents(\n input: PregelInputType,\n options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n encoding: never;\n }\n ): IterableReadableStream<never>;\n\n override streamEvents(\n _input: PregelInputType,\n _options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n encoding?: never;\n }\n ): IterableReadableStream<StreamEvent> {\n throw new Error(\"Not implemented.\");\n }\n\n override async *_streamIterator(\n input: PregelInputType,\n options?: Partial<PregelOptions<Nn, Cc, ContextType>>\n ): AsyncGenerator<PregelOutputType> {\n const mergedConfig = mergeConfigs(\n this.config,\n options\n ) as LangGraphRunnableConfig;\n const {\n threadId,\n context,\n config: sanitizedConfig,\n } = this.#prepareRunRequest(mergedConfig);\n\n const streamProtocolInstance = options?.configurable?.[CONFIG_KEY_STREAM];\n\n const streamSubgraphs =\n options?.subgraphs ?? streamProtocolInstance !== undefined;\n\n const interruptBefore = options?.interruptBefore ?? this.interruptBefore;\n const interruptAfter = options?.interruptAfter ?? this.interruptAfter;\n\n const { updatedStreamModes, reqSingle, reqUpdates } = getStreamModes(\n options?.streamMode\n );\n\n const extendedStreamModes = [\n ...new Set([\n ...updatedStreamModes,\n ...(streamProtocolInstance?.modes ?? new Set()),\n ]),\n ].map((mode) => {\n if (mode === \"messages\") return \"messages-tuple\";\n return mode;\n });\n\n let command;\n let serializedInput;\n if (isCommand(input)) {\n // TODO: Remove cast when SDK type fix gets merged\n command = input.toJSON() as Record<string, unknown>;\n serializedInput = undefined;\n } else {\n serializedInput = _serializeInputs(input);\n }\n\n const streamPayload = {\n command,\n input: serializedInput,\n config: sanitizedConfig,\n context,\n streamMode: extendedStreamModes,\n interruptBefore: interruptBefore as string[],\n interruptAfter: interruptAfter as string[],\n streamSubgraphs,\n ifNotExists: \"create\" as const,\n signal: mergedConfig.signal,\n streamResumable: this.streamResumable,\n };\n\n const runStream =\n threadId != null\n ? this.client.runs.stream(threadId, this.graphId, streamPayload)\n : this.client.runs.stream(null, this.graphId, streamPayload);\n\n for await (const chunk of runStream) {\n let mode;\n let namespace: string[];\n if (chunk.event.includes(CHECKPOINT_NAMESPACE_SEPARATOR)) {\n const eventComponents = chunk.event.split(\n CHECKPOINT_NAMESPACE_SEPARATOR\n );\n // eslint-disable-next-line prefer-destructuring\n mode = eventComponents[0];\n namespace = eventComponents.slice(1);\n } else {\n mode = chunk.event;\n namespace = [];\n }\n const callerNamespace = options?.configurable?.checkpoint_ns;\n if (typeof callerNamespace === \"string\") {\n namespace = callerNamespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .concat(namespace);\n }\n if (\n streamProtocolInstance !== undefined &&\n streamProtocolInstance.modes?.has(chunk.event)\n ) {\n streamProtocolInstance.push([namespace, mode, chunk.data]);\n }\n if (chunk.event.startsWith(\"updates\")) {\n if (\n typeof chunk.data === \"object\" &&\n chunk.data?.[INTERRUPT] !== undefined\n ) {\n throw new GraphInterrupt(chunk.data[INTERRUPT]);\n }\n if (!reqUpdates) {\n continue;\n }\n } else if (chunk.event?.startsWith(\"error\")) {\n throw new RemoteException(\n typeof chunk.data === \"string\"\n ? chunk.data\n : JSON.stringify(chunk.data)\n );\n }\n if (\n !updatedStreamModes.includes(\n chunk.event.split(CHECKPOINT_NAMESPACE_SEPARATOR)[0] as StreamMode\n )\n ) {\n continue;\n }\n if (options?.subgraphs) {\n if (reqSingle) {\n yield [namespace, chunk.data];\n } else {\n yield [namespace, mode, chunk.data];\n }\n } else if (reqSingle) {\n yield chunk.data;\n } else {\n yield [mode, chunk.data];\n }\n }\n }\n\n async updateState(\n inputConfig: LangGraphRunnableConfig,\n values: Record<string, unknown>,\n asNode?: string\n ): Promise<RunnableConfig> {\n const mergedConfig = mergeConfigs(this.config, inputConfig);\n const response = await this.client.threads.updateState(\n mergedConfig.configurable?.thread_id,\n { values, asNode, checkpoint: this._getCheckpoint(mergedConfig) }\n );\n // TODO: Fix SDK typing\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this._getConfig((response as any).checkpoint);\n }\n\n async *getStateHistory(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncIterableIterator<StateSnapshot> {\n const mergedConfig = mergeConfigs(this.config, config);\n const states = await this.client.threads.getHistory(\n mergedConfig.configurable?.thread_id,\n {\n limit: options?.limit ?? 10,\n // TODO: Fix type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n before: this._getCheckpoint(options?.before) as any,\n metadata: options?.filter,\n checkpoint: this._getCheckpoint(mergedConfig),\n }\n );\n for (const state of states) {\n yield this._createStateSnapshot(state, mergedConfig);\n }\n }\n\n protected _getDrawableNodes(\n nodes: Array<{\n id: string | number;\n name?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data?: Record<string, any> | string;\n metadata?: unknown;\n }>\n ): Record<string, DrawableNode> {\n const nodesMap: Record<string, DrawableNode> = {};\n for (const node of nodes) {\n const nodeId = node.id;\n nodesMap[nodeId] = {\n id: nodeId.toString(),\n name:\n typeof node.data === \"string\" ? node.data : (node.data?.name ?? \"\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data: (node.data as any) ?? {},\n metadata:\n typeof node.data !== \"string\" ? (node.data?.metadata ?? {}) : {},\n };\n }\n return nodesMap;\n }\n\n async getState(\n config: RunnableConfig,\n options?: { subgraphs?: boolean }\n ): Promise<StateSnapshot> {\n const mergedConfig = mergeConfigs(this.config, config);\n\n const state = await this.client.threads.getState(\n mergedConfig.configurable?.thread_id,\n this._getCheckpoint(mergedConfig),\n options\n );\n return this._createStateSnapshot(state, mergedConfig);\n }\n\n /** @deprecated Use getGraphAsync instead. The async method will become the default in the next minor release. */\n override getGraph(\n _?: RunnableConfig & { xray?: boolean | number }\n ): DrawableGraph {\n throw new Error(\n `The synchronous \"getGraph\" is not supported for this graph. Call \"getGraphAsync\" instead.`\n );\n }\n\n /**\n * Returns a drawable representation of the computation graph.\n */\n async getGraphAsync(config?: RunnableConfig & { xray?: boolean | number }) {\n const graph = await this.client.assistants.getGraph(this.graphId, {\n xray: config?.xray,\n });\n return new DrawableGraph({\n nodes: this._getDrawableNodes(graph.nodes),\n edges: graph.edges,\n });\n }\n\n /** @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release. */\n getSubgraphs(): Generator<[string, PregelInterface<Nn, Cc, ContextType>]> {\n throw new Error(\n `The synchronous \"getSubgraphs\" method is not supported for this graph. Call \"getSubgraphsAsync\" instead.`\n );\n }\n\n async *getSubgraphsAsync(\n namespace?: string,\n recurse = false\n ): AsyncGenerator<[string, PregelInterface<Nn, Cc, ContextType>]> {\n const subgraphs = await this.client.assistants.getSubgraphs(this.graphId, {\n namespace,\n recurse,\n });\n\n for (const [ns, graphSchema] of Object.entries(subgraphs)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const remoteSubgraph = new (this.constructor as any)({\n ...this,\n graphId: graphSchema.graph_id,\n });\n yield [ns, remoteSubgraph];\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"remote.js","names":["#prepareRunRequest","DrawableGraph"],"sources":["../../src/pregel/remote.ts"],"sourcesContent":["import {\n Client,\n type Checkpoint,\n type ThreadState,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Graph as DrawableGraph,\n Node as DrawableNode,\n} from \"@langchain/core/runnables/graph\";\nimport {\n mergeConfigs,\n Runnable,\n RunnableConfig,\n} from \"@langchain/core/runnables\";\nimport {\n All,\n CheckpointListOptions,\n CheckpointMetadata,\n} from \"@langchain/langgraph-checkpoint\";\nimport { StreamEvent } from \"@langchain/core/tracers/log_stream\";\nimport { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport { BaseMessage } from \"@langchain/core/messages\";\n\nimport {\n BaseChannel,\n GraphInterrupt,\n LangGraphRunnableConfig,\n RemoteException,\n} from \"../web.js\";\nimport { StrRecord } from \"./algo.js\";\nimport { PregelInputType, PregelOptions, PregelOutputType } from \"./index.js\";\nimport { PregelNode } from \"./read.js\";\nimport {\n PregelParams,\n PregelInterface,\n PregelTaskDescription,\n StateSnapshot,\n StreamMode,\n} from \"./types.js\";\nimport {\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_STREAM,\n INTERRUPT,\n isCommand,\n} from \"../constants.js\";\nimport { propagateConfigurableToMetadata } from \"./utils/config.js\";\n\nexport type RemoteGraphParams = Omit<\n PregelParams<StrRecord<string, PregelNode>, StrRecord<string, BaseChannel>>,\n \"channels\" | \"nodes\" | \"inputChannels\" | \"outputChannels\"\n> & {\n graphId: string;\n client?: Client;\n url?: string;\n apiKey?: string;\n headers?: Record<string, string>;\n streamResumable?: boolean;\n};\n\ntype StreamEventsOptions = Parameters<Runnable[\"streamEvents\"]>[2];\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst _serializeInputs = (obj: any): any => {\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(_serializeInputs);\n }\n\n // Handle BaseMessage instances by converting them to a serializable format\n if (BaseMessage.isInstance(obj)) {\n const dict = obj.toDict();\n return {\n ...dict.data,\n role: obj.getType(),\n };\n }\n\n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [key, _serializeInputs(value)])\n );\n};\n\n/**\n * Return a tuple of the final list of stream modes sent to the\n * remote graph and a boolean flag indicating if only one stream mode was\n * originally requested and whether stream mode 'updates'\n * was present in the original list of stream modes.\n *\n * 'updates' mode is always added to the list of stream modes so that interrupts\n * can be detected in the remote graph.\n */\nconst getStreamModes = (\n streamMode?: StreamMode | StreamMode[],\n defaultStreamMode: StreamMode = \"updates\"\n) => {\n const updatedStreamModes: StreamMode[] = [];\n let reqUpdates = false;\n let reqSingle = true;\n\n if (\n streamMode !== undefined &&\n (typeof streamMode === \"string\" ||\n (Array.isArray(streamMode) && streamMode.length > 0))\n ) {\n reqSingle = typeof streamMode === \"string\";\n const mapped = Array.isArray(streamMode) ? streamMode : [streamMode];\n updatedStreamModes.push(...mapped);\n } else {\n updatedStreamModes.push(defaultStreamMode);\n }\n if (updatedStreamModes.includes(\"updates\")) {\n reqUpdates = true;\n } else {\n updatedStreamModes.push(\"updates\");\n }\n return {\n updatedStreamModes,\n reqUpdates,\n reqSingle,\n };\n};\n\n/**\n * The `RemoteGraph` class is a client implementation for calling remote\n * APIs that implement the LangGraph Server API specification.\n *\n * For example, the `RemoteGraph` class can be used to call APIs from deployments\n * on LangSmith Deployment.\n *\n * `RemoteGraph` behaves the same way as a `StateGraph` and can be used directly as\n * a node in another `StateGraph`.\n *\n * @example\n * ```ts\n * import { RemoteGraph } from \"@langchain/langgraph/remote\";\n *\n * // Can also pass a LangGraph SDK client instance directly\n * const remoteGraph = new RemoteGraph({\n * graphId: process.env.LANGGRAPH_REMOTE_GRAPH_ID!,\n * apiKey: process.env.LANGGRAPH_REMOTE_GRAPH_API_KEY,\n * url: process.env.LANGGRAPH_REMOTE_GRAPH_API_URL,\n * });\n *\n * const input = {\n * messages: [\n * {\n * role: \"human\",\n * content: \"Hello world!\",\n * },\n * ],\n * };\n *\n * const config = {\n * configurable: { thread_id: \"threadId1\" },\n * };\n *\n * await remoteGraph.invoke(input, config);\n * ```\n */\nexport class RemoteGraph<\n Nn extends StrRecord<string, PregelNode> = StrRecord<string, PregelNode>,\n Cc extends StrRecord<string, BaseChannel> = StrRecord<string, BaseChannel>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ContextType extends Record<string, any> = StrRecord<string, any>,\n>\n extends Runnable<\n PregelInputType,\n PregelOutputType,\n PregelOptions<Nn, Cc, ContextType>\n >\n implements PregelInterface<Nn, Cc, ContextType>\n{\n static lc_name() {\n return \"RemoteGraph\";\n }\n\n lc_namespace = [\"langgraph\", \"pregel\"];\n\n lg_is_pregel = true;\n\n config?: RunnableConfig;\n\n graphId: string;\n\n protected client: Client;\n\n protected interruptBefore?: Array<keyof Nn> | All;\n\n protected interruptAfter?: Array<keyof Nn> | All;\n\n protected streamResumable?: boolean;\n\n constructor(params: RemoteGraphParams) {\n super(params);\n\n this.graphId = params.graphId;\n this.client =\n params.client ??\n new Client({\n apiUrl: params.url,\n apiKey: params.apiKey,\n defaultHeaders: params.headers,\n });\n this.config = params.config;\n this.interruptBefore = params.interruptBefore;\n this.interruptAfter = params.interruptAfter;\n this.streamResumable = params.streamResumable;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore Remove ignore when we remove support for 0.2 versions of core\n override withConfig(config: RunnableConfig): typeof this {\n const mergedConfig = mergeConfigs(this.config, config);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new (this.constructor as any)({ ...this, config: mergedConfig });\n }\n\n protected _sanitizeConfig(config: RunnableConfig) {\n const reservedConfigurableKeys = new Set([\n \"callbacks\",\n \"checkpoint_map\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n ]);\n\n const sanitizeObj = <T>(obj: T): T => {\n try {\n // This will only throw if we're trying to serialize a circular reference\n // or trying to serialize a BigInt...\n JSON.stringify(obj);\n return obj;\n } catch {\n const seen = new WeakSet();\n return JSON.parse(\n JSON.stringify(obj, (_, value) => {\n if (typeof value === \"object\" && value != null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n\n if (typeof value === \"bigint\") return value.toString();\n return value;\n })\n );\n }\n };\n\n const propagateMetadataDefaults = (obj: unknown) => {\n const seen = new WeakSet<object>();\n const visit = (value: unknown) => {\n if (typeof value !== \"object\" || value == null) {\n return;\n }\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n const record = value as Record<string, unknown>;\n const configurable = record.configurable;\n if (\n typeof configurable === \"object\" &&\n configurable != null &&\n !Array.isArray(configurable)\n ) {\n const metadata =\n typeof record.metadata === \"object\" &&\n record.metadata != null &&\n !Array.isArray(record.metadata)\n ? (record.metadata as Record<string, unknown>)\n : undefined;\n record.metadata =\n propagateConfigurableToMetadata(\n configurable as Record<string, unknown>,\n metadata\n ) ?? record.metadata;\n }\n for (const nestedValue of Object.values(record)) {\n visit(nestedValue);\n }\n };\n visit(obj);\n };\n\n propagateMetadataDefaults(config);\n\n // Remove non-JSON serializable fields from the config\n const sanitizedConfig = sanitizeObj(config);\n\n // Only include configurable keys that are not reserved and\n // not starting with \"__pregel_\" prefix\n const newConfigurable = Object.fromEntries(\n Object.entries(sanitizedConfig.configurable ?? {}).filter(\n ([k]) => !reservedConfigurableKeys.has(k) && !k.startsWith(\"__pregel_\")\n )\n );\n\n return {\n tags: sanitizedConfig.tags ?? [],\n metadata: sanitizedConfig.metadata ?? {},\n configurable: newConfigurable,\n recursion_limit: sanitizedConfig.recursionLimit,\n };\n }\n\n /**\n * Prepare config and thread ID for remote run API calls.\n *\n * `thread_id` is passed via the URL path, not in `config.configurable`, so the\n * server can accept a separate `context` payload for stateful runs.\n */\n #prepareRunRequest(mergedConfig: LangGraphRunnableConfig): {\n threadId: string | undefined;\n context: unknown;\n config: ReturnType<RemoteGraph[\"_sanitizeConfig\"]>;\n } {\n const context = mergedConfig.context;\n const sanitizedConfig = this._sanitizeConfig(mergedConfig);\n const configurable = { ...sanitizedConfig.configurable };\n const threadId = configurable.thread_id as string | undefined;\n delete configurable.thread_id;\n\n return {\n threadId,\n context,\n config: {\n ...sanitizedConfig,\n configurable,\n },\n };\n }\n\n protected _getConfig(checkpoint: Record<string, unknown>): RunnableConfig {\n return {\n configurable: {\n thread_id: checkpoint.thread_id,\n checkpoint_ns: checkpoint.checkpoint_ns,\n checkpoint_id: checkpoint.checkpoint_id,\n checkpoint_map: checkpoint.checkpoint_map ?? {},\n },\n };\n }\n\n protected _checkpointToConfig(\n checkpoint?: Partial<Checkpoint> | null,\n fallbackConfig?: RunnableConfig\n ): RunnableConfig {\n const resolvedCheckpoint =\n checkpoint ?? this._getCheckpoint(fallbackConfig);\n if (resolvedCheckpoint == null) {\n return { configurable: {} };\n }\n\n const configurable: Record<string, unknown> = {};\n if (resolvedCheckpoint.thread_id !== undefined) {\n configurable.thread_id = resolvedCheckpoint.thread_id;\n }\n if (resolvedCheckpoint.checkpoint_ns !== undefined) {\n configurable.checkpoint_ns = resolvedCheckpoint.checkpoint_ns;\n }\n if (resolvedCheckpoint.checkpoint_id !== undefined) {\n configurable.checkpoint_id = resolvedCheckpoint.checkpoint_id;\n }\n\n const hasCheckpointFields =\n resolvedCheckpoint.checkpoint_ns !== undefined ||\n resolvedCheckpoint.checkpoint_id !== undefined ||\n resolvedCheckpoint.checkpoint_map !== undefined;\n if (hasCheckpointFields) {\n configurable.checkpoint_map = resolvedCheckpoint.checkpoint_map ?? {};\n }\n\n return { configurable };\n }\n\n protected _getCheckpoint(config?: RunnableConfig): Checkpoint | undefined {\n if (config?.configurable === undefined) {\n return undefined;\n }\n\n const checkpointKeys = [\n \"thread_id\",\n \"checkpoint_ns\",\n \"checkpoint_id\",\n \"checkpoint_map\",\n ] as const;\n\n const checkpoint = Object.fromEntries(\n checkpointKeys\n .map((key) => [key, config.configurable![key]])\n .filter(([_, value]) => value !== undefined)\n );\n\n return Object.keys(checkpoint).length > 0 ? checkpoint : undefined;\n }\n\n protected _createStateSnapshot(\n state: ThreadState,\n fallbackConfig?: RunnableConfig\n ): StateSnapshot {\n const tasks: PregelTaskDescription[] = state.tasks.map((task) => {\n return {\n id: task.id,\n name: task.name,\n error: task.error ? { message: task.error } : undefined,\n // TODO: remove in LangGraph.js 0.4\n interrupts: task.interrupts.map(({ id, ...rest }) => ({\n interrupt_id: id,\n ...rest,\n })),\n // eslint-disable-next-line no-nested-ternary\n state: task.state\n ? this._createStateSnapshot(\n task.state,\n task.checkpoint\n ? this._checkpointToConfig(task.checkpoint)\n : fallbackConfig\n )\n : task.checkpoint\n ? { configurable: task.checkpoint }\n : undefined,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result: (task as any).result,\n };\n });\n\n return {\n values: state.values,\n next: state.next ? [...state.next] : [],\n // TODO: Fix SDK typing. `ThreadState.checkpoint` is typed as non-null,\n // but deployments can return `null` (e.g. a thread that exists but has\n // not produced a checkpoint yet). See #2328.\n config: this._checkpointToConfig(\n state.checkpoint as Checkpoint | null,\n fallbackConfig\n ),\n metadata: state.metadata\n ? (state.metadata as CheckpointMetadata)\n : undefined,\n createdAt: state.created_at ?? undefined,\n parentConfig: state.parent_checkpoint\n ? this._checkpointToConfig(state.parent_checkpoint)\n : undefined,\n tasks,\n };\n }\n\n override async invoke(\n input: PregelInputType,\n options?: Partial<PregelOptions<Nn, Cc, ContextType>>\n ): Promise<PregelOutputType> {\n let lastValue;\n const stream = await this.stream(input, {\n ...options,\n streamMode: \"values\",\n });\n for await (const chunk of stream) {\n lastValue = chunk;\n }\n return lastValue;\n }\n\n override streamEvents(\n input: PregelInputType,\n options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n },\n streamOptions?: StreamEventsOptions\n ): IterableReadableStream<StreamEvent>;\n\n override streamEvents(\n input: PregelInputType,\n options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n encoding: \"text/event-stream\";\n },\n streamOptions?: StreamEventsOptions\n ): IterableReadableStream<Uint8Array>;\n\n override streamEvents(\n _input: PregelInputType,\n _options: Partial<PregelOptions<Nn, Cc, ContextType>> & {\n version: \"v1\" | \"v2\";\n encoding?: \"text/event-stream\";\n },\n _streamOptions?: StreamEventsOptions\n ): IterableReadableStream<StreamEvent | Uint8Array> {\n throw new Error(\"Not implemented.\");\n }\n\n override async *_streamIterator(\n input: PregelInputType,\n options?: Partial<PregelOptions<Nn, Cc, ContextType>>\n ): AsyncGenerator<PregelOutputType> {\n const mergedConfig = mergeConfigs(\n this.config,\n options\n ) as LangGraphRunnableConfig;\n const {\n threadId,\n context,\n config: sanitizedConfig,\n } = this.#prepareRunRequest(mergedConfig);\n\n const streamProtocolInstance = options?.configurable?.[CONFIG_KEY_STREAM];\n\n const streamSubgraphs =\n options?.subgraphs ?? streamProtocolInstance !== undefined;\n\n const interruptBefore = options?.interruptBefore ?? this.interruptBefore;\n const interruptAfter = options?.interruptAfter ?? this.interruptAfter;\n\n const { updatedStreamModes, reqSingle, reqUpdates } = getStreamModes(\n options?.streamMode\n );\n\n const extendedStreamModes = [\n ...new Set([\n ...updatedStreamModes,\n ...(streamProtocolInstance?.modes ?? new Set()),\n ]),\n ].map((mode) => {\n if (mode === \"messages\") return \"messages-tuple\";\n return mode;\n });\n\n let command;\n let serializedInput;\n if (isCommand(input)) {\n // TODO: Remove cast when SDK type fix gets merged\n command = input.toJSON() as Record<string, unknown>;\n serializedInput = undefined;\n } else {\n serializedInput = _serializeInputs(input);\n }\n\n const streamPayload = {\n command,\n input: serializedInput,\n config: sanitizedConfig,\n context,\n streamMode: extendedStreamModes,\n interruptBefore: interruptBefore as string[],\n interruptAfter: interruptAfter as string[],\n streamSubgraphs,\n ifNotExists: \"create\" as const,\n signal: mergedConfig.signal,\n streamResumable: this.streamResumable,\n };\n\n const runStream =\n threadId != null\n ? this.client.runs.stream(threadId, this.graphId, streamPayload)\n : this.client.runs.stream(null, this.graphId, streamPayload);\n\n for await (const chunk of runStream) {\n let mode;\n let namespace: string[];\n if (chunk.event.includes(CHECKPOINT_NAMESPACE_SEPARATOR)) {\n const eventComponents = chunk.event.split(\n CHECKPOINT_NAMESPACE_SEPARATOR\n );\n // eslint-disable-next-line prefer-destructuring\n mode = eventComponents[0];\n namespace = eventComponents.slice(1);\n } else {\n mode = chunk.event;\n namespace = [];\n }\n const callerNamespace = options?.configurable?.checkpoint_ns;\n if (typeof callerNamespace === \"string\") {\n namespace = callerNamespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .concat(namespace);\n }\n if (\n streamProtocolInstance !== undefined &&\n streamProtocolInstance.modes?.has(chunk.event)\n ) {\n streamProtocolInstance.push([namespace, mode, chunk.data]);\n }\n if (chunk.event.startsWith(\"updates\")) {\n if (\n typeof chunk.data === \"object\" &&\n chunk.data?.[INTERRUPT] !== undefined\n ) {\n throw new GraphInterrupt(chunk.data[INTERRUPT]);\n }\n if (!reqUpdates) {\n continue;\n }\n } else if (chunk.event?.startsWith(\"error\")) {\n throw new RemoteException(\n typeof chunk.data === \"string\"\n ? chunk.data\n : JSON.stringify(chunk.data)\n );\n }\n if (\n !updatedStreamModes.includes(\n chunk.event.split(CHECKPOINT_NAMESPACE_SEPARATOR)[0] as StreamMode\n )\n ) {\n continue;\n }\n if (options?.subgraphs) {\n if (reqSingle) {\n yield [namespace, chunk.data];\n } else {\n yield [namespace, mode, chunk.data];\n }\n } else if (reqSingle) {\n yield chunk.data;\n } else {\n yield [mode, chunk.data];\n }\n }\n }\n\n async updateState(\n inputConfig: LangGraphRunnableConfig,\n values: Record<string, unknown>,\n asNode?: string\n ): Promise<RunnableConfig> {\n const mergedConfig = mergeConfigs(this.config, inputConfig);\n const response = await this.client.threads.updateState(\n mergedConfig.configurable?.thread_id,\n { values, asNode, checkpoint: this._getCheckpoint(mergedConfig) }\n );\n // TODO: Fix SDK typing\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this._getConfig((response as any).checkpoint);\n }\n\n async *getStateHistory(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncIterableIterator<StateSnapshot> {\n const mergedConfig = mergeConfigs(this.config, config);\n const states = await this.client.threads.getHistory(\n mergedConfig.configurable?.thread_id,\n {\n limit: options?.limit ?? 10,\n // TODO: Fix type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n before: this._getCheckpoint(options?.before) as any,\n metadata: options?.filter,\n checkpoint: this._getCheckpoint(mergedConfig),\n }\n );\n for (const state of states) {\n yield this._createStateSnapshot(state, mergedConfig);\n }\n }\n\n protected _getDrawableNodes(\n nodes: Array<{\n id: string | number;\n name?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data?: Record<string, any> | string;\n metadata?: unknown;\n }>\n ): Record<string, DrawableNode> {\n const nodesMap: Record<string, DrawableNode> = {};\n for (const node of nodes) {\n const nodeId = node.id;\n nodesMap[nodeId] = {\n id: nodeId.toString(),\n name:\n typeof node.data === \"string\" ? node.data : (node.data?.name ?? \"\"),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n data: (node.data as any) ?? {},\n metadata:\n typeof node.data !== \"string\" ? (node.data?.metadata ?? {}) : {},\n };\n }\n return nodesMap;\n }\n\n async getState(\n config: RunnableConfig,\n options?: { subgraphs?: boolean }\n ): Promise<StateSnapshot> {\n const mergedConfig = mergeConfigs(this.config, config);\n\n const state = await this.client.threads.getState(\n mergedConfig.configurable?.thread_id,\n this._getCheckpoint(mergedConfig),\n options\n );\n return this._createStateSnapshot(state, mergedConfig);\n }\n\n /** @deprecated Use getGraphAsync instead. The async method will become the default in the next minor release. */\n override getGraph(\n _?: RunnableConfig & { xray?: boolean | number }\n ): DrawableGraph {\n throw new Error(\n `The synchronous \"getGraph\" is not supported for this graph. Call \"getGraphAsync\" instead.`\n );\n }\n\n /**\n * Returns a drawable representation of the computation graph.\n */\n async getGraphAsync(config?: RunnableConfig & { xray?: boolean | number }) {\n const graph = await this.client.assistants.getGraph(this.graphId, {\n xray: config?.xray,\n });\n return new DrawableGraph({\n nodes: this._getDrawableNodes(graph.nodes),\n edges: graph.edges,\n });\n }\n\n /** @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release. */\n getSubgraphs(): Generator<[string, PregelInterface<Nn, Cc, ContextType>]> {\n throw new Error(\n `The synchronous \"getSubgraphs\" method is not supported for this graph. Call \"getSubgraphsAsync\" instead.`\n );\n }\n\n async *getSubgraphsAsync(\n namespace?: string,\n recurse = false\n ): AsyncGenerator<[string, PregelInterface<Nn, Cc, ContextType>]> {\n const subgraphs = await this.client.assistants.getSubgraphs(this.graphId, {\n namespace,\n recurse,\n });\n\n for (const [ns, graphSchema] of Object.entries(subgraphs)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const remoteSubgraph = new (this.constructor as any)({\n ...this,\n graphId: graphSchema.graph_id,\n });\n yield [ns, remoteSubgraph];\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/pregel/stream.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require("../constants.cjs");
|
|
2
|
+
const require_convert = require("../stream/convert.cjs");
|
|
2
3
|
let _langchain_core_utils_stream = require("@langchain/core/utils/stream");
|
|
3
4
|
let _langchain_core_callbacks_base = require("@langchain/core/callbacks/base");
|
|
4
5
|
//#region src/pregel/stream.ts
|
|
@@ -273,10 +274,21 @@ function toEventStream(stream) {
|
|
|
273
274
|
controller.close();
|
|
274
275
|
} });
|
|
275
276
|
}
|
|
277
|
+
/** Multiplex subgraph stream chunks into the parent pregel stream. */
|
|
278
|
+
function createDuplexStream(...streams) {
|
|
279
|
+
return new IterableReadableWritableStream({
|
|
280
|
+
passthroughFn: (value) => {
|
|
281
|
+
const isEnvelope = value[1] === "checkpoints" && require_convert.isCheckpointEnvelope(value[2]);
|
|
282
|
+
for (const stream of streams) if (stream.modes.has(value[1]) || isEnvelope) stream.push(value);
|
|
283
|
+
},
|
|
284
|
+
modes: new Set(streams.flatMap((s) => Array.from(s.modes)))
|
|
285
|
+
});
|
|
286
|
+
}
|
|
276
287
|
//#endregion
|
|
277
288
|
exports.IterableReadableStreamWithAbortSignal = IterableReadableStreamWithAbortSignal;
|
|
278
289
|
exports.IterableReadableWritableStream = IterableReadableWritableStream;
|
|
279
290
|
exports.StreamToolsHandler = StreamToolsHandler;
|
|
291
|
+
exports.createDuplexStream = createDuplexStream;
|
|
280
292
|
exports.toEventStream = toEventStream;
|
|
281
293
|
|
|
282
294
|
//# sourceMappingURL=stream.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.cjs","names":["IterableReadableStream","BaseCallbackHandler"],"sources":["../../src/pregel/stream.ts"],"sourcesContent":["import { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport type { Checkpoint } from \"../stream/types.js\";\nimport type { StreamMode, StreamOutputMap } from \"./types.js\";\nimport { TAG_HIDDEN } from \"../constants.js\";\n\n/**\n * Optional chunk-level metadata carried alongside the payload. Used by\n * `streamEvents(..., { version: \"v3\" })` to emit a companion `checkpoints`\n * protocol event adjacent to the `values` event for the same superstep, so\n * clients can build branching / time-travel UIs without subscribing to a\n * full-state `checkpoints` stream.\n *\n * v1 consumers that destructure `StreamChunk` as `[ns, mode, payload]`\n * ignore the 4th element and are unaffected.\n */\nexport interface StreamChunkMeta {\n /**\n * Lightweight checkpoint envelope for the superstep that produced this\n * `values` chunk. Shape matches the canonical {@link Checkpoint}\n * generated from `protocol.cddl`. When present, `convertToProtocolEvent`\n * emits a companion `checkpoints` event immediately after the `values`\n * event so clients can correlate by `(namespace, step)` or adjacent\n * `seq` numbers.\n */\n checkpoint?: Checkpoint;\n}\n\n// [namespace, streamMode, payload, meta?]\nexport type StreamChunk = [string[], StreamMode, unknown, StreamChunkMeta?];\n\ntype StreamCheckpointsOutput<StreamValues> = StreamOutputMap<\n \"checkpoints\",\n false,\n StreamValues,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype AnyStreamOutput = StreamOutputMap<\n StreamMode[],\n true,\n unknown,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype ToolRunInfo = {\n ns: string[];\n toolCallId?: string;\n toolName: string;\n input: unknown;\n};\n\n/**\n * A wrapper around an IterableReadableStream that allows for aborting the stream when\n * {@link cancel} is called.\n */\nexport class IterableReadableStreamWithAbortSignal<\n T,\n> extends IterableReadableStream<T> {\n protected _abortController: AbortController;\n\n protected _innerReader: ReadableStreamDefaultReader<T>;\n\n /**\n * @param readableStream - The stream to wrap.\n * @param abortController - The abort controller to use. Optional. One will be created if not provided.\n */\n constructor(\n readableStream: ReadableStream<T>,\n abortController?: AbortController\n ) {\n const reader = readableStream.getReader();\n const ac = abortController ?? new AbortController();\n super({\n start(controller: ReadableStreamDefaultController<T>) {\n return pump();\n function pump(): Promise<T | undefined> {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n controller.close();\n return;\n }\n // Enqueue the next data chunk into our target stream\n controller.enqueue(value);\n return pump();\n });\n }\n },\n });\n this._abortController = ac;\n this._innerReader = reader;\n }\n\n /**\n * Aborts the stream, abandoning any pending operations in progress. Calling this triggers an\n * {@link AbortSignal} that is propagated to the tasks that are producing the data for this stream.\n * @param reason - The reason for aborting the stream. Optional.\n */\n override async cancel(reason?: unknown) {\n this._abortController.abort(reason);\n this._innerReader.releaseLock();\n }\n\n /**\n * The {@link AbortSignal} for the stream. Aborted when {@link cancel} is called.\n */\n get signal() {\n return this._abortController.signal;\n }\n}\n\nexport class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {\n modes: Set<StreamMode>;\n\n private controller: ReadableStreamDefaultController;\n\n private passthroughFn?: (chunk: StreamChunk) => void;\n\n private _closed: boolean = false;\n\n get closed() {\n return this._closed;\n }\n\n constructor(params: {\n passthroughFn?: (chunk: StreamChunk) => void;\n modes: Set<StreamMode>;\n }) {\n let streamControllerPromiseResolver: (\n controller: ReadableStreamDefaultController\n ) => void;\n const streamControllerPromise: Promise<ReadableStreamDefaultController> =\n new Promise<ReadableStreamDefaultController>((resolve) => {\n streamControllerPromiseResolver = resolve;\n });\n\n super({\n start: (controller) => {\n streamControllerPromiseResolver!(controller);\n },\n });\n\n // .start() will always be called before the stream can be interacted\n // with anyway\n void streamControllerPromise.then((controller) => {\n this.controller = controller;\n });\n\n this.passthroughFn = params.passthroughFn;\n this.modes = params.modes;\n }\n\n push(chunk: StreamChunk) {\n // Prevent pushing to a closed stream to avoid race condition errors\n if (this._closed || !this.controller) {\n // Silently drop chunks when stream is closed - this is expected behavior\n // when async operations try to push after stream termination\n return;\n }\n\n // Forward chunk to passthrough function if provided\n this.passthroughFn?.(chunk);\n\n // Attempt to enqueue the chunk to the underlying stream\n this.controller.enqueue(chunk);\n }\n\n close() {\n try {\n this.controller.close();\n } catch {\n // pass\n } finally {\n this._closed = true;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error(e: any) {\n try {\n this.controller?.error(e);\n } finally {\n // Mark the stream as closed so any late `push()` calls from in-flight\n // parallel tasks are dropped instead of throwing on an errored controller.\n this._closed = true;\n }\n }\n}\n\n/**\n * A callback handler that implements stream_mode=tools.\n * Emits on_tool_start, on_tool_event, on_tool_end, on_tool_error events.\n */\nexport class StreamToolsHandler extends BaseCallbackHandler {\n name = \"StreamToolsHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n runs: Record<string, ToolRunInfo | undefined> = {};\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n handleToolStart(\n _tool: Serialized,\n input: string,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n toolCallId?: string\n ) {\n if (!metadata || (tags && tags.includes(TAG_HIDDEN))) return;\n\n const ns = (metadata.langgraph_checkpoint_ns as string)?.split(\"|\") ?? [];\n const info: ToolRunInfo = {\n ns,\n toolCallId,\n toolName: runName ?? \"unknown\",\n input,\n };\n this.runs[runId] = info;\n\n this.streamFn([\n ns,\n \"tools\",\n {\n event: \"on_tool_start\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n input,\n },\n ]);\n }\n\n handleToolEvent(chunk: unknown, runId: string) {\n const info = this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_event\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n data: chunk,\n },\n ]);\n }\n\n handleToolEnd(output: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_end\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n output,\n },\n ]);\n }\n\n handleToolError(err: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_error\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n error: err,\n },\n ]);\n }\n}\n\nfunction _stringifyAsDict(obj: unknown) {\n return JSON.stringify(obj, function (key: string | number, value: unknown) {\n const rawValue = this[key];\n if (\n rawValue != null &&\n typeof rawValue === \"object\" &&\n \"toDict\" in rawValue &&\n typeof rawValue.toDict === \"function\"\n ) {\n const { type, data } = rawValue.toDict();\n return { ...data, type };\n }\n\n return value;\n });\n}\n\nfunction _serializeError(error: unknown) {\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (error instanceof Error) {\n return { error: error.name, message: error.message };\n }\n return { error: \"Error\", message: JSON.stringify(error) };\n}\n\nfunction _isRunnableConfig(\n config: unknown\n): config is RunnableConfig & { configurable: Record<string, unknown> } {\n if (typeof config !== \"object\" || config == null) return false;\n return (\n \"configurable\" in config &&\n typeof config.configurable === \"object\" &&\n config.configurable != null\n );\n}\n\nfunction _extractCheckpointFromConfig(\n config: RunnableConfig | null | undefined\n) {\n if (!_isRunnableConfig(config) || !config.configurable.thread_id) {\n return null;\n }\n\n return {\n thread_id: config.configurable.thread_id,\n checkpoint_ns: config.configurable.checkpoint_ns || \"\",\n checkpoint_id: config.configurable.checkpoint_id || null,\n checkpoint_map: config.configurable.checkpoint_map || null,\n };\n}\n\nfunction _serializeConfig(config: unknown) {\n if (_isRunnableConfig(config)) {\n const configurable = Object.fromEntries(\n Object.entries(config.configurable).filter(\n ([key]) => !key.startsWith(\"__\")\n )\n );\n\n const newConfig = { ...config, configurable };\n delete newConfig.callbacks;\n return newConfig;\n }\n\n return config;\n}\n\nfunction _serializeCheckpoint(payload: StreamCheckpointsOutput<unknown>) {\n const result: Record<string, unknown> = {\n ...payload,\n checkpoint: _extractCheckpointFromConfig(payload.config),\n parent_checkpoint: _extractCheckpointFromConfig(payload.parentConfig),\n\n config: _serializeConfig(payload.config),\n parent_config: _serializeConfig(payload.parentConfig),\n\n tasks: payload.tasks.map((task) => {\n if (_isRunnableConfig(task.state)) {\n const checkpoint = _extractCheckpointFromConfig(task.state);\n if (checkpoint != null) {\n const cloneTask: Record<string, unknown> = { ...task, checkpoint };\n delete cloneTask.state;\n return cloneTask;\n }\n }\n\n return task;\n }),\n };\n\n delete result.parentConfig;\n return result;\n}\n\nexport function toEventStream(stream: AsyncGenerator) {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueueChunk = (sse: {\n id?: string;\n event: string;\n data: unknown;\n }) => {\n controller.enqueue(\n encoder.encode(\n `event: ${sse.event}\\ndata: ${_stringifyAsDict(sse.data)}\\n\\n`\n )\n );\n };\n\n try {\n for await (const payload of stream) {\n const [ns, mode, chunk] = payload as AnyStreamOutput;\n\n let data: unknown = chunk;\n if (mode === \"debug\") {\n const debugChunk = chunk;\n\n if (debugChunk.type === \"checkpoint\") {\n data = {\n ...debugChunk,\n payload: _serializeCheckpoint(debugChunk.payload),\n };\n }\n }\n\n if (mode === \"checkpoints\") {\n data = _serializeCheckpoint(chunk);\n }\n\n const event = ns?.length ? `${mode}|${ns.join(\"|\")}` : mode;\n enqueueChunk({ event, data });\n }\n } catch (error) {\n enqueueChunk({ event: \"error\", data: _serializeError(error) });\n }\n\n controller.close();\n },\n });\n}\n"],"mappings":";;;;;;;;AAkEA,IAAa,wCAAb,cAEUA,6BAAAA,uBAA0B;CAClC;CAEA;;;;;CAMA,YACE,gBACA,iBACA;EACA,MAAM,SAAS,eAAe,WAAW;EACzC,MAAM,KAAK,mBAAmB,IAAI,iBAAiB;AACnD,QAAM,EACJ,MAAM,YAAgD;AACpD,UAAO,MAAM;GACb,SAAS,OAA+B;AACtC,WAAO,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,YAAY;AAE7C,SAAI,MAAM;AACR,iBAAW,OAAO;AAClB;;AAGF,gBAAW,QAAQ,MAAM;AACzB,YAAO,MAAM;MACb;;KAGP,CAAC;AACF,OAAK,mBAAmB;AACxB,OAAK,eAAe;;;;;;;CAQtB,MAAe,OAAO,QAAkB;AACtC,OAAK,iBAAiB,MAAM,OAAO;AACnC,OAAK,aAAa,aAAa;;;;;CAMjC,IAAI,SAAS;AACX,SAAO,KAAK,iBAAiB;;;AAIjC,IAAa,iCAAb,cAAoDA,6BAAAA,uBAAoC;CACtF;CAEA;CAEA;CAEA,UAA2B;CAE3B,IAAI,SAAS;AACX,SAAO,KAAK;;CAGd,YAAY,QAGT;EACD,IAAI;EAGJ,MAAM,0BACJ,IAAI,SAA0C,YAAY;AACxD,qCAAkC;IAClC;AAEJ,QAAM,EACJ,QAAQ,eAAe;AACrB,mCAAiC,WAAW;KAE/C,CAAC;AAIG,0BAAwB,MAAM,eAAe;AAChD,QAAK,aAAa;IAClB;AAEF,OAAK,gBAAgB,OAAO;AAC5B,OAAK,QAAQ,OAAO;;CAGtB,KAAK,OAAoB;AAEvB,MAAI,KAAK,WAAW,CAAC,KAAK,WAGxB;AAIF,OAAK,gBAAgB,MAAM;AAG3B,OAAK,WAAW,QAAQ,MAAM;;CAGhC,QAAQ;AACN,MAAI;AACF,QAAK,WAAW,OAAO;UACjB,WAEE;AACR,QAAK,UAAU;;;CAKnB,MAAM,GAAQ;AACZ,MAAI;AACF,QAAK,YAAY,MAAM,EAAE;YACjB;AAGR,QAAK,UAAU;;;;;;;;AASrB,IAAa,qBAAb,cAAwCC,+BAAAA,oBAAoB;CAC1D,OAAO;CAEP;CAEA,OAAgD,EAAE;CAElD,YAAY,UAA8C;AACxD,SAAO;AACP,OAAK,WAAW;;CAGlB,gBACE,OACA,OACA,OACA,cACA,MACA,UACA,SACA,YACA;AACA,MAAI,CAAC,YAAa,QAAQ,KAAK,SAAA,mBAAoB,CAAG;EAEtD,MAAM,KAAM,SAAS,yBAAoC,MAAM,IAAI,IAAI,EAAE;EACzE,MAAM,OAAoB;GACxB;GACA;GACA,UAAU,WAAW;GACrB;GACD;AACD,OAAK,KAAK,SAAS;AAEnB,OAAK,SAAS;GACZ;GACA;GACA;IACE,OAAO;IACP,YAAY,KAAK;IACjB,MAAM,KAAK;IACX;IACD;GACF,CAAC;;CAGJ,gBAAgB,OAAgB,OAAe;EAC7C,MAAM,OAAO,KAAK,KAAK;AACvB,MAAI,CAAC,KAAM;AAEX,OAAK,SAAS;GACZ,KAAK;GACL;GACA;IACE,OAAO;IACP,YAAY,KAAK;IACjB,MAAM,KAAK;IACX,MAAM;IACP;GACF,CAAC;;CAGJ,cAAc,QAAiB,OAAe;EAC5C,MAAM,OAAO,KAAK,KAAK;AACvB,SAAO,KAAK,KAAK;AACjB,MAAI,CAAC,KAAM;AAEX,OAAK,SAAS;GACZ,KAAK;GACL;GACA;IACE,OAAO;IACP,YAAY,KAAK;IACjB,MAAM,KAAK;IACX;IACD;GACF,CAAC;;CAGJ,gBAAgB,KAAc,OAAe;EAC3C,MAAM,OAAO,KAAK,KAAK;AACvB,SAAO,KAAK,KAAK;AACjB,MAAI,CAAC,KAAM;AAEX,OAAK,SAAS;GACZ,KAAK;GACL;GACA;IACE,OAAO;IACP,YAAY,KAAK;IACjB,MAAM,KAAK;IACX,OAAO;IACR;GACF,CAAC;;;AAIN,SAAS,iBAAiB,KAAc;AACtC,QAAO,KAAK,UAAU,KAAK,SAAU,KAAsB,OAAgB;EACzE,MAAM,WAAW,KAAK;AACtB,MACE,YAAY,QACZ,OAAO,aAAa,YACpB,YAAY,YACZ,OAAO,SAAS,WAAW,YAC3B;GACA,MAAM,EAAE,MAAM,SAAS,SAAS,QAAQ;AACxC,UAAO;IAAE,GAAG;IAAM;IAAM;;AAG1B,SAAO;GACP;;AAGJ,SAAS,gBAAgB,OAAgB;AAEvC,KAAI,iBAAiB,MACnB,QAAO;EAAE,OAAO,MAAM;EAAM,SAAS,MAAM;EAAS;AAEtD,QAAO;EAAE,OAAO;EAAS,SAAS,KAAK,UAAU,MAAM;EAAE;;AAG3D,SAAS,kBACP,QACsE;AACtE,KAAI,OAAO,WAAW,YAAY,UAAU,KAAM,QAAO;AACzD,QACE,kBAAkB,UAClB,OAAO,OAAO,iBAAiB,YAC/B,OAAO,gBAAgB;;AAI3B,SAAS,6BACP,QACA;AACA,KAAI,CAAC,kBAAkB,OAAO,IAAI,CAAC,OAAO,aAAa,UACrD,QAAO;AAGT,QAAO;EACL,WAAW,OAAO,aAAa;EAC/B,eAAe,OAAO,aAAa,iBAAiB;EACpD,eAAe,OAAO,aAAa,iBAAiB;EACpD,gBAAgB,OAAO,aAAa,kBAAkB;EACvD;;AAGH,SAAS,iBAAiB,QAAiB;AACzC,KAAI,kBAAkB,OAAO,EAAE;EAC7B,MAAM,eAAe,OAAO,YAC1B,OAAO,QAAQ,OAAO,aAAa,CAAC,QACjC,CAAC,SAAS,CAAC,IAAI,WAAW,KAAK,CACjC,CACF;EAED,MAAM,YAAY;GAAE,GAAG;GAAQ;GAAc;AAC7C,SAAO,UAAU;AACjB,SAAO;;AAGT,QAAO;;AAGT,SAAS,qBAAqB,SAA2C;CACvE,MAAM,SAAkC;EACtC,GAAG;EACH,YAAY,6BAA6B,QAAQ,OAAO;EACxD,mBAAmB,6BAA6B,QAAQ,aAAa;EAErE,QAAQ,iBAAiB,QAAQ,OAAO;EACxC,eAAe,iBAAiB,QAAQ,aAAa;EAErD,OAAO,QAAQ,MAAM,KAAK,SAAS;AACjC,OAAI,kBAAkB,KAAK,MAAM,EAAE;IACjC,MAAM,aAAa,6BAA6B,KAAK,MAAM;AAC3D,QAAI,cAAc,MAAM;KACtB,MAAM,YAAqC;MAAE,GAAG;MAAM;MAAY;AAClE,YAAO,UAAU;AACjB,YAAO;;;AAIX,UAAO;IACP;EACH;AAED,QAAO,OAAO;AACd,QAAO;;AAGT,SAAgB,cAAc,QAAwB;CACpD,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,IAAI,eAA2B,EACpC,MAAM,MAAM,YAAY;EACtB,MAAM,gBAAgB,QAIhB;AACJ,cAAW,QACT,QAAQ,OACN,UAAU,IAAI,MAAM,UAAU,iBAAiB,IAAI,KAAK,CAAC,MAC1D,CACF;;AAGH,MAAI;AACF,cAAW,MAAM,WAAW,QAAQ;IAClC,MAAM,CAAC,IAAI,MAAM,SAAS;IAE1B,IAAI,OAAgB;AACpB,QAAI,SAAS,SAAS;KACpB,MAAM,aAAa;AAEnB,SAAI,WAAW,SAAS,aACtB,QAAO;MACL,GAAG;MACH,SAAS,qBAAqB,WAAW,QAAQ;MAClD;;AAIL,QAAI,SAAS,cACX,QAAO,qBAAqB,MAAM;AAIpC,iBAAa;KAAE,OADD,IAAI,SAAS,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,KAAK;KACjC;KAAM,CAAC;;WAExB,OAAO;AACd,gBAAa;IAAE,OAAO;IAAS,MAAM,gBAAgB,MAAM;IAAE,CAAC;;AAGhE,aAAW,OAAO;IAErB,CAAC"}
|
|
1
|
+
{"version":3,"file":"stream.cjs","names":["IterableReadableStream","BaseCallbackHandler","isCheckpointEnvelope"],"sources":["../../src/pregel/stream.ts"],"sourcesContent":["import { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { isCheckpointEnvelope } from \"../stream/convert.js\";\nimport type { Checkpoint } from \"../stream/types.js\";\nimport type { StreamMode, StreamOutputMap } from \"./types.js\";\nimport { TAG_HIDDEN } from \"../constants.js\";\n\n/**\n * Optional chunk-level metadata carried alongside the payload. Used by\n * `streamEvents(..., { version: \"v3\" })` to emit a companion `checkpoints`\n * protocol event adjacent to the `values` event for the same superstep, so\n * clients can build branching / time-travel UIs without subscribing to a\n * full-state `checkpoints` stream.\n *\n * Companion checkpoint envelopes are emitted as separate\n * ``[namespace, \"checkpoints\", envelope]`` chunks (see\n * ``PregelLoop._emitValuesWithCheckpointMeta``).\n */\nexport interface StreamChunkMeta {\n /**\n * Lightweight checkpoint envelope for the superstep that produced the\n * paired `values` chunk. Shape matches the canonical {@link Checkpoint}\n * generated from `protocol.cddl`.\n */\n checkpoint?: Checkpoint;\n}\n\n// [namespace, streamMode, payload]\nexport type StreamChunk = [string[], StreamMode, unknown];\n\ntype StreamCheckpointsOutput<StreamValues> = StreamOutputMap<\n \"checkpoints\",\n false,\n StreamValues,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype AnyStreamOutput = StreamOutputMap<\n StreamMode[],\n true,\n unknown,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype ToolRunInfo = {\n ns: string[];\n toolCallId?: string;\n toolName: string;\n input: unknown;\n};\n\n/**\n * A wrapper around an IterableReadableStream that allows for aborting the stream when\n * {@link cancel} is called.\n */\nexport class IterableReadableStreamWithAbortSignal<\n T,\n> extends IterableReadableStream<T> {\n protected _abortController: AbortController;\n\n protected _innerReader: ReadableStreamDefaultReader<T>;\n\n /**\n * @param readableStream - The stream to wrap.\n * @param abortController - The abort controller to use. Optional. One will be created if not provided.\n */\n constructor(\n readableStream: ReadableStream<T>,\n abortController?: AbortController\n ) {\n const reader = readableStream.getReader();\n const ac = abortController ?? new AbortController();\n super({\n start(controller: ReadableStreamDefaultController<T>) {\n return pump();\n function pump(): Promise<T | undefined> {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n controller.close();\n return;\n }\n // Enqueue the next data chunk into our target stream\n controller.enqueue(value);\n return pump();\n });\n }\n },\n });\n this._abortController = ac;\n this._innerReader = reader;\n }\n\n /**\n * Aborts the stream, abandoning any pending operations in progress. Calling this triggers an\n * {@link AbortSignal} that is propagated to the tasks that are producing the data for this stream.\n * @param reason - The reason for aborting the stream. Optional.\n */\n override async cancel(reason?: unknown) {\n this._abortController.abort(reason);\n this._innerReader.releaseLock();\n }\n\n /**\n * The {@link AbortSignal} for the stream. Aborted when {@link cancel} is called.\n */\n get signal() {\n return this._abortController.signal;\n }\n}\n\nexport class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {\n modes: Set<StreamMode>;\n\n private controller: ReadableStreamDefaultController;\n\n private passthroughFn?: (chunk: StreamChunk) => void;\n\n private _closed: boolean = false;\n\n get closed() {\n return this._closed;\n }\n\n constructor(params: {\n passthroughFn?: (chunk: StreamChunk) => void;\n modes: Set<StreamMode>;\n }) {\n let streamControllerPromiseResolver: (\n controller: ReadableStreamDefaultController\n ) => void;\n const streamControllerPromise: Promise<ReadableStreamDefaultController> =\n new Promise<ReadableStreamDefaultController>((resolve) => {\n streamControllerPromiseResolver = resolve;\n });\n\n super({\n start: (controller) => {\n streamControllerPromiseResolver!(controller);\n },\n });\n\n // .start() will always be called before the stream can be interacted\n // with anyway\n void streamControllerPromise.then((controller) => {\n this.controller = controller;\n });\n\n this.passthroughFn = params.passthroughFn;\n this.modes = params.modes;\n }\n\n push(chunk: StreamChunk) {\n // Prevent pushing to a closed stream to avoid race condition errors\n if (this._closed || !this.controller) {\n // Silently drop chunks when stream is closed - this is expected behavior\n // when async operations try to push after stream termination\n return;\n }\n\n // Forward chunk to passthrough function if provided\n this.passthroughFn?.(chunk);\n\n // Attempt to enqueue the chunk to the underlying stream\n this.controller.enqueue(chunk);\n }\n\n close() {\n try {\n this.controller.close();\n } catch {\n // pass\n } finally {\n this._closed = true;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error(e: any) {\n try {\n this.controller?.error(e);\n } finally {\n // Mark the stream as closed so any late `push()` calls from in-flight\n // parallel tasks are dropped instead of throwing on an errored controller.\n this._closed = true;\n }\n }\n}\n\n/**\n * A callback handler that implements stream_mode=tools.\n * Emits on_tool_start, on_tool_event, on_tool_end, on_tool_error events.\n */\nexport class StreamToolsHandler extends BaseCallbackHandler {\n name = \"StreamToolsHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n runs: Record<string, ToolRunInfo | undefined> = {};\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n handleToolStart(\n _tool: Serialized,\n input: string,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n toolCallId?: string\n ) {\n if (!metadata || (tags && tags.includes(TAG_HIDDEN))) return;\n\n const ns = (metadata.langgraph_checkpoint_ns as string)?.split(\"|\") ?? [];\n const info: ToolRunInfo = {\n ns,\n toolCallId,\n toolName: runName ?? \"unknown\",\n input,\n };\n this.runs[runId] = info;\n\n this.streamFn([\n ns,\n \"tools\",\n {\n event: \"on_tool_start\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n input,\n },\n ]);\n }\n\n handleToolEvent(chunk: unknown, runId: string) {\n const info = this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_event\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n data: chunk,\n },\n ]);\n }\n\n handleToolEnd(output: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_end\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n output,\n },\n ]);\n }\n\n handleToolError(err: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_error\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n error: err,\n },\n ]);\n }\n}\n\nfunction _stringifyAsDict(obj: unknown) {\n return JSON.stringify(obj, function (key: string | number, value: unknown) {\n const rawValue = this[key];\n if (\n rawValue != null &&\n typeof rawValue === \"object\" &&\n \"toDict\" in rawValue &&\n typeof rawValue.toDict === \"function\"\n ) {\n const { type, data } = rawValue.toDict();\n return { ...data, type };\n }\n\n return value;\n });\n}\n\nfunction _serializeError(error: unknown) {\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (error instanceof Error) {\n return { error: error.name, message: error.message };\n }\n return { error: \"Error\", message: JSON.stringify(error) };\n}\n\nfunction _isRunnableConfig(\n config: unknown\n): config is RunnableConfig & { configurable: Record<string, unknown> } {\n if (typeof config !== \"object\" || config == null) return false;\n return (\n \"configurable\" in config &&\n typeof config.configurable === \"object\" &&\n config.configurable != null\n );\n}\n\nfunction _extractCheckpointFromConfig(\n config: RunnableConfig | null | undefined\n) {\n if (!_isRunnableConfig(config) || !config.configurable.thread_id) {\n return null;\n }\n\n return {\n thread_id: config.configurable.thread_id,\n checkpoint_ns: config.configurable.checkpoint_ns || \"\",\n checkpoint_id: config.configurable.checkpoint_id || null,\n checkpoint_map: config.configurable.checkpoint_map || null,\n };\n}\n\nfunction _serializeConfig(config: unknown) {\n if (_isRunnableConfig(config)) {\n const configurable = Object.fromEntries(\n Object.entries(config.configurable).filter(\n ([key]) => !key.startsWith(\"__\")\n )\n );\n\n const newConfig = { ...config, configurable };\n delete newConfig.callbacks;\n return newConfig;\n }\n\n return config;\n}\n\nfunction _serializeCheckpoint(payload: StreamCheckpointsOutput<unknown>) {\n const result: Record<string, unknown> = {\n ...payload,\n checkpoint: _extractCheckpointFromConfig(payload.config),\n parent_checkpoint: _extractCheckpointFromConfig(payload.parentConfig),\n\n config: _serializeConfig(payload.config),\n parent_config: _serializeConfig(payload.parentConfig),\n\n tasks: payload.tasks.map((task) => {\n if (_isRunnableConfig(task.state)) {\n const checkpoint = _extractCheckpointFromConfig(task.state);\n if (checkpoint != null) {\n const cloneTask: Record<string, unknown> = { ...task, checkpoint };\n delete cloneTask.state;\n return cloneTask;\n }\n }\n\n return task;\n }),\n };\n\n delete result.parentConfig;\n return result;\n}\n\nexport function toEventStream(stream: AsyncGenerator) {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueueChunk = (sse: {\n id?: string;\n event: string;\n data: unknown;\n }) => {\n controller.enqueue(\n encoder.encode(\n `event: ${sse.event}\\ndata: ${_stringifyAsDict(sse.data)}\\n\\n`\n )\n );\n };\n\n try {\n for await (const payload of stream) {\n const [ns, mode, chunk] = payload as AnyStreamOutput;\n\n let data: unknown = chunk;\n if (mode === \"debug\") {\n const debugChunk = chunk;\n\n if (debugChunk.type === \"checkpoint\") {\n data = {\n ...debugChunk,\n payload: _serializeCheckpoint(debugChunk.payload),\n };\n }\n }\n\n if (mode === \"checkpoints\") {\n data = _serializeCheckpoint(chunk);\n }\n\n const event = ns?.length ? `${mode}|${ns.join(\"|\")}` : mode;\n enqueueChunk({ event, data });\n }\n } catch (error) {\n enqueueChunk({ event: \"error\", data: _serializeError(error) });\n }\n\n controller.close();\n },\n });\n}\n\n/** Multiplex subgraph stream chunks into the parent pregel stream. */\nexport function createDuplexStream(\n ...streams: IterableReadableWritableStream[]\n) {\n return new IterableReadableWritableStream({\n passthroughFn: (value: StreamChunk) => {\n const isEnvelope =\n value[1] === \"checkpoints\" && isCheckpointEnvelope(value[2]);\n for (const stream of streams) {\n if (stream.modes.has(value[1]) || isEnvelope) {\n stream.push(value);\n }\n }\n },\n modes: new Set(streams.flatMap((s) => Array.from(s.modes))),\n });\n}\n"],"mappings":"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"}
|
package/dist/pregel/stream.d.cts
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
import { Checkpoint } from "../stream/types.cjs";
|
|
2
1
|
import { StreamMode } from "./types.cjs";
|
|
3
2
|
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
4
3
|
|
|
5
4
|
//#region src/pregel/stream.d.ts
|
|
6
|
-
|
|
7
|
-
* Optional chunk-level metadata carried alongside the payload. Used by
|
|
8
|
-
* `streamEvents(..., { version: "v3" })` to emit a companion `checkpoints`
|
|
9
|
-
* protocol event adjacent to the `values` event for the same superstep, so
|
|
10
|
-
* clients can build branching / time-travel UIs without subscribing to a
|
|
11
|
-
* full-state `checkpoints` stream.
|
|
12
|
-
*
|
|
13
|
-
* v1 consumers that destructure `StreamChunk` as `[ns, mode, payload]`
|
|
14
|
-
* ignore the 4th element and are unaffected.
|
|
15
|
-
*/
|
|
16
|
-
interface StreamChunkMeta {
|
|
17
|
-
/**
|
|
18
|
-
* Lightweight checkpoint envelope for the superstep that produced this
|
|
19
|
-
* `values` chunk. Shape matches the canonical {@link Checkpoint}
|
|
20
|
-
* generated from `protocol.cddl`. When present, `convertToProtocolEvent`
|
|
21
|
-
* emits a companion `checkpoints` event immediately after the `values`
|
|
22
|
-
* event so clients can correlate by `(namespace, step)` or adjacent
|
|
23
|
-
* `seq` numbers.
|
|
24
|
-
*/
|
|
25
|
-
checkpoint?: Checkpoint;
|
|
26
|
-
}
|
|
27
|
-
type StreamChunk = [string[], StreamMode, unknown, StreamChunkMeta?];
|
|
5
|
+
type StreamChunk = [string[], StreamMode, unknown];
|
|
28
6
|
//#endregion
|
|
29
|
-
export { StreamChunk
|
|
7
|
+
export { StreamChunk };
|
|
30
8
|
//# sourceMappingURL=stream.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.cts","names":[],"sources":["../../src/pregel/stream.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"stream.d.cts","names":[],"sources":["../../src/pregel/stream.ts"],"mappings":";;;;KA8BY,WAAA,cAAyB,UAAA"}
|
package/dist/pregel/stream.d.ts
CHANGED
|
@@ -1,31 +1,9 @@
|
|
|
1
|
-
import { Checkpoint } from "../stream/types.js";
|
|
2
1
|
import { StreamMode } from "./types.js";
|
|
3
2
|
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
4
3
|
import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
|
|
5
4
|
|
|
6
5
|
//#region src/pregel/stream.d.ts
|
|
7
|
-
|
|
8
|
-
* Optional chunk-level metadata carried alongside the payload. Used by
|
|
9
|
-
* `streamEvents(..., { version: "v3" })` to emit a companion `checkpoints`
|
|
10
|
-
* protocol event adjacent to the `values` event for the same superstep, so
|
|
11
|
-
* clients can build branching / time-travel UIs without subscribing to a
|
|
12
|
-
* full-state `checkpoints` stream.
|
|
13
|
-
*
|
|
14
|
-
* v1 consumers that destructure `StreamChunk` as `[ns, mode, payload]`
|
|
15
|
-
* ignore the 4th element and are unaffected.
|
|
16
|
-
*/
|
|
17
|
-
interface StreamChunkMeta {
|
|
18
|
-
/**
|
|
19
|
-
* Lightweight checkpoint envelope for the superstep that produced this
|
|
20
|
-
* `values` chunk. Shape matches the canonical {@link Checkpoint}
|
|
21
|
-
* generated from `protocol.cddl`. When present, `convertToProtocolEvent`
|
|
22
|
-
* emits a companion `checkpoints` event immediately after the `values`
|
|
23
|
-
* event so clients can correlate by `(namespace, step)` or adjacent
|
|
24
|
-
* `seq` numbers.
|
|
25
|
-
*/
|
|
26
|
-
checkpoint?: Checkpoint;
|
|
27
|
-
}
|
|
28
|
-
type StreamChunk = [string[], StreamMode, unknown, StreamChunkMeta?];
|
|
6
|
+
type StreamChunk = [string[], StreamMode, unknown];
|
|
29
7
|
//#endregion
|
|
30
|
-
export { StreamChunk
|
|
8
|
+
export { StreamChunk };
|
|
31
9
|
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","names":[],"sources":["../../src/pregel/stream.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"stream.d.ts","names":[],"sources":["../../src/pregel/stream.ts"],"mappings":";;;;;KA8BY,WAAA,cAAyB,UAAA"}
|
package/dist/pregel/stream.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "../constants.js";
|
|
2
|
+
import { isCheckpointEnvelope } from "../stream/convert.js";
|
|
2
3
|
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
3
4
|
import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
|
|
4
5
|
//#region src/pregel/stream.ts
|
|
@@ -273,7 +274,17 @@ function toEventStream(stream) {
|
|
|
273
274
|
controller.close();
|
|
274
275
|
} });
|
|
275
276
|
}
|
|
277
|
+
/** Multiplex subgraph stream chunks into the parent pregel stream. */
|
|
278
|
+
function createDuplexStream(...streams) {
|
|
279
|
+
return new IterableReadableWritableStream({
|
|
280
|
+
passthroughFn: (value) => {
|
|
281
|
+
const isEnvelope = value[1] === "checkpoints" && isCheckpointEnvelope(value[2]);
|
|
282
|
+
for (const stream of streams) if (stream.modes.has(value[1]) || isEnvelope) stream.push(value);
|
|
283
|
+
},
|
|
284
|
+
modes: new Set(streams.flatMap((s) => Array.from(s.modes)))
|
|
285
|
+
});
|
|
286
|
+
}
|
|
276
287
|
//#endregion
|
|
277
|
-
export { IterableReadableStreamWithAbortSignal, IterableReadableWritableStream, StreamToolsHandler, toEventStream };
|
|
288
|
+
export { IterableReadableStreamWithAbortSignal, IterableReadableWritableStream, StreamToolsHandler, createDuplexStream, toEventStream };
|
|
278
289
|
|
|
279
290
|
//# sourceMappingURL=stream.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","names":[],"sources":["../../src/pregel/stream.ts"],"sourcesContent":["import { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport type { Checkpoint } from \"../stream/types.js\";\nimport type { StreamMode, StreamOutputMap } from \"./types.js\";\nimport { TAG_HIDDEN } from \"../constants.js\";\n\n/**\n * Optional chunk-level metadata carried alongside the payload. Used by\n * `streamEvents(..., { version: \"v3\" })` to emit a companion `checkpoints`\n * protocol event adjacent to the `values` event for the same superstep, so\n * clients can build branching / time-travel UIs without subscribing to a\n * full-state `checkpoints` stream.\n *\n * v1 consumers that destructure `StreamChunk` as `[ns, mode, payload]`\n * ignore the 4th element and are unaffected.\n */\nexport interface StreamChunkMeta {\n /**\n * Lightweight checkpoint envelope for the superstep that produced this\n * `values` chunk. Shape matches the canonical {@link Checkpoint}\n * generated from `protocol.cddl`. When present, `convertToProtocolEvent`\n * emits a companion `checkpoints` event immediately after the `values`\n * event so clients can correlate by `(namespace, step)` or adjacent\n * `seq` numbers.\n */\n checkpoint?: Checkpoint;\n}\n\n// [namespace, streamMode, payload, meta?]\nexport type StreamChunk = [string[], StreamMode, unknown, StreamChunkMeta?];\n\ntype StreamCheckpointsOutput<StreamValues> = StreamOutputMap<\n \"checkpoints\",\n false,\n StreamValues,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype AnyStreamOutput = StreamOutputMap<\n StreamMode[],\n true,\n unknown,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype ToolRunInfo = {\n ns: string[];\n toolCallId?: string;\n toolName: string;\n input: unknown;\n};\n\n/**\n * A wrapper around an IterableReadableStream that allows for aborting the stream when\n * {@link cancel} is called.\n */\nexport class IterableReadableStreamWithAbortSignal<\n T,\n> extends IterableReadableStream<T> {\n protected _abortController: AbortController;\n\n protected _innerReader: ReadableStreamDefaultReader<T>;\n\n /**\n * @param readableStream - The stream to wrap.\n * @param abortController - The abort controller to use. Optional. One will be created if not provided.\n */\n constructor(\n readableStream: ReadableStream<T>,\n abortController?: AbortController\n ) {\n const reader = readableStream.getReader();\n const ac = abortController ?? new AbortController();\n super({\n start(controller: ReadableStreamDefaultController<T>) {\n return pump();\n function pump(): Promise<T | undefined> {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n controller.close();\n return;\n }\n // Enqueue the next data chunk into our target stream\n controller.enqueue(value);\n return pump();\n });\n }\n },\n });\n this._abortController = ac;\n this._innerReader = reader;\n }\n\n /**\n * Aborts the stream, abandoning any pending operations in progress. Calling this triggers an\n * {@link AbortSignal} that is propagated to the tasks that are producing the data for this stream.\n * @param reason - The reason for aborting the stream. Optional.\n */\n override async cancel(reason?: unknown) {\n this._abortController.abort(reason);\n this._innerReader.releaseLock();\n }\n\n /**\n * The {@link AbortSignal} for the stream. Aborted when {@link cancel} is called.\n */\n get signal() {\n return this._abortController.signal;\n }\n}\n\nexport class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {\n modes: Set<StreamMode>;\n\n private controller: ReadableStreamDefaultController;\n\n private passthroughFn?: (chunk: StreamChunk) => void;\n\n private _closed: boolean = false;\n\n get closed() {\n return this._closed;\n }\n\n constructor(params: {\n passthroughFn?: (chunk: StreamChunk) => void;\n modes: Set<StreamMode>;\n }) {\n let streamControllerPromiseResolver: (\n controller: ReadableStreamDefaultController\n ) => void;\n const streamControllerPromise: Promise<ReadableStreamDefaultController> =\n new Promise<ReadableStreamDefaultController>((resolve) => {\n streamControllerPromiseResolver = resolve;\n });\n\n super({\n start: (controller) => {\n streamControllerPromiseResolver!(controller);\n },\n });\n\n // .start() will always be called before the stream can be interacted\n // with anyway\n void streamControllerPromise.then((controller) => {\n this.controller = controller;\n });\n\n this.passthroughFn = params.passthroughFn;\n this.modes = params.modes;\n }\n\n push(chunk: StreamChunk) {\n // Prevent pushing to a closed stream to avoid race condition errors\n if (this._closed || !this.controller) {\n // Silently drop chunks when stream is closed - this is expected behavior\n // when async operations try to push after stream termination\n return;\n }\n\n // Forward chunk to passthrough function if provided\n this.passthroughFn?.(chunk);\n\n // Attempt to enqueue the chunk to the underlying stream\n this.controller.enqueue(chunk);\n }\n\n close() {\n try {\n this.controller.close();\n } catch {\n // pass\n } finally {\n this._closed = true;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error(e: any) {\n try {\n this.controller?.error(e);\n } finally {\n // Mark the stream as closed so any late `push()` calls from in-flight\n // parallel tasks are dropped instead of throwing on an errored controller.\n this._closed = true;\n }\n }\n}\n\n/**\n * A callback handler that implements stream_mode=tools.\n * Emits on_tool_start, on_tool_event, on_tool_end, on_tool_error events.\n */\nexport class StreamToolsHandler extends BaseCallbackHandler {\n name = \"StreamToolsHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n runs: Record<string, ToolRunInfo | undefined> = {};\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n handleToolStart(\n _tool: Serialized,\n input: string,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n toolCallId?: string\n ) {\n if (!metadata || (tags && tags.includes(TAG_HIDDEN))) return;\n\n const ns = (metadata.langgraph_checkpoint_ns as string)?.split(\"|\") ?? [];\n const info: ToolRunInfo = {\n ns,\n toolCallId,\n toolName: runName ?? \"unknown\",\n input,\n };\n this.runs[runId] = info;\n\n this.streamFn([\n ns,\n \"tools\",\n {\n event: \"on_tool_start\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n input,\n },\n ]);\n }\n\n handleToolEvent(chunk: unknown, runId: string) {\n const info = this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_event\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n data: chunk,\n },\n ]);\n }\n\n handleToolEnd(output: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_end\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n output,\n },\n ]);\n }\n\n handleToolError(err: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_error\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n error: err,\n },\n ]);\n }\n}\n\nfunction _stringifyAsDict(obj: unknown) {\n return JSON.stringify(obj, function (key: string | number, value: unknown) {\n const rawValue = this[key];\n if (\n rawValue != null &&\n typeof rawValue === \"object\" &&\n \"toDict\" in rawValue &&\n typeof rawValue.toDict === \"function\"\n ) {\n const { type, data } = rawValue.toDict();\n return { ...data, type };\n }\n\n return value;\n });\n}\n\nfunction _serializeError(error: unknown) {\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (error instanceof Error) {\n return { error: error.name, message: error.message };\n }\n return { error: \"Error\", message: JSON.stringify(error) };\n}\n\nfunction _isRunnableConfig(\n config: unknown\n): config is RunnableConfig & { configurable: Record<string, unknown> } {\n if (typeof config !== \"object\" || config == null) return false;\n return (\n \"configurable\" in config &&\n typeof config.configurable === \"object\" &&\n config.configurable != null\n );\n}\n\nfunction _extractCheckpointFromConfig(\n config: RunnableConfig | null | undefined\n) {\n if (!_isRunnableConfig(config) || !config.configurable.thread_id) {\n return null;\n }\n\n return {\n thread_id: config.configurable.thread_id,\n checkpoint_ns: config.configurable.checkpoint_ns || \"\",\n checkpoint_id: config.configurable.checkpoint_id || null,\n checkpoint_map: config.configurable.checkpoint_map || null,\n };\n}\n\nfunction _serializeConfig(config: unknown) {\n if (_isRunnableConfig(config)) {\n const configurable = Object.fromEntries(\n Object.entries(config.configurable).filter(\n ([key]) => !key.startsWith(\"__\")\n )\n );\n\n const newConfig = { ...config, configurable };\n delete newConfig.callbacks;\n return newConfig;\n }\n\n return config;\n}\n\nfunction _serializeCheckpoint(payload: StreamCheckpointsOutput<unknown>) {\n const result: Record<string, unknown> = {\n ...payload,\n checkpoint: _extractCheckpointFromConfig(payload.config),\n parent_checkpoint: _extractCheckpointFromConfig(payload.parentConfig),\n\n config: _serializeConfig(payload.config),\n parent_config: _serializeConfig(payload.parentConfig),\n\n tasks: payload.tasks.map((task) => {\n if (_isRunnableConfig(task.state)) {\n const checkpoint = _extractCheckpointFromConfig(task.state);\n if (checkpoint != null) {\n const cloneTask: Record<string, unknown> = { ...task, checkpoint };\n delete cloneTask.state;\n return cloneTask;\n }\n }\n\n return task;\n }),\n };\n\n delete result.parentConfig;\n return result;\n}\n\nexport function toEventStream(stream: AsyncGenerator) {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueueChunk = (sse: {\n id?: string;\n event: string;\n data: unknown;\n }) => {\n controller.enqueue(\n encoder.encode(\n `event: ${sse.event}\\ndata: ${_stringifyAsDict(sse.data)}\\n\\n`\n )\n );\n };\n\n try {\n for await (const payload of stream) {\n const [ns, mode, chunk] = payload as AnyStreamOutput;\n\n let data: unknown = chunk;\n if (mode === \"debug\") {\n const debugChunk = chunk;\n\n if (debugChunk.type === \"checkpoint\") {\n data = {\n ...debugChunk,\n payload: _serializeCheckpoint(debugChunk.payload),\n };\n }\n }\n\n if (mode === \"checkpoints\") {\n data = _serializeCheckpoint(chunk);\n }\n\n const event = ns?.length ? `${mode}|${ns.join(\"|\")}` : mode;\n enqueueChunk({ event, data });\n }\n } catch (error) {\n enqueueChunk({ event: \"error\", data: _serializeError(error) });\n }\n\n controller.close();\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.js","names":[],"sources":["../../src/pregel/stream.ts"],"sourcesContent":["import { IterableReadableStream } from \"@langchain/core/utils/stream\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { isCheckpointEnvelope } from \"../stream/convert.js\";\nimport type { Checkpoint } from \"../stream/types.js\";\nimport type { StreamMode, StreamOutputMap } from \"./types.js\";\nimport { TAG_HIDDEN } from \"../constants.js\";\n\n/**\n * Optional chunk-level metadata carried alongside the payload. Used by\n * `streamEvents(..., { version: \"v3\" })` to emit a companion `checkpoints`\n * protocol event adjacent to the `values` event for the same superstep, so\n * clients can build branching / time-travel UIs without subscribing to a\n * full-state `checkpoints` stream.\n *\n * Companion checkpoint envelopes are emitted as separate\n * ``[namespace, \"checkpoints\", envelope]`` chunks (see\n * ``PregelLoop._emitValuesWithCheckpointMeta``).\n */\nexport interface StreamChunkMeta {\n /**\n * Lightweight checkpoint envelope for the superstep that produced the\n * paired `values` chunk. Shape matches the canonical {@link Checkpoint}\n * generated from `protocol.cddl`.\n */\n checkpoint?: Checkpoint;\n}\n\n// [namespace, streamMode, payload]\nexport type StreamChunk = [string[], StreamMode, unknown];\n\ntype StreamCheckpointsOutput<StreamValues> = StreamOutputMap<\n \"checkpoints\",\n false,\n StreamValues,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype AnyStreamOutput = StreamOutputMap<\n StreamMode[],\n true,\n unknown,\n unknown,\n string,\n unknown,\n unknown,\n undefined\n>;\n\ntype ToolRunInfo = {\n ns: string[];\n toolCallId?: string;\n toolName: string;\n input: unknown;\n};\n\n/**\n * A wrapper around an IterableReadableStream that allows for aborting the stream when\n * {@link cancel} is called.\n */\nexport class IterableReadableStreamWithAbortSignal<\n T,\n> extends IterableReadableStream<T> {\n protected _abortController: AbortController;\n\n protected _innerReader: ReadableStreamDefaultReader<T>;\n\n /**\n * @param readableStream - The stream to wrap.\n * @param abortController - The abort controller to use. Optional. One will be created if not provided.\n */\n constructor(\n readableStream: ReadableStream<T>,\n abortController?: AbortController\n ) {\n const reader = readableStream.getReader();\n const ac = abortController ?? new AbortController();\n super({\n start(controller: ReadableStreamDefaultController<T>) {\n return pump();\n function pump(): Promise<T | undefined> {\n return reader.read().then(({ done, value }) => {\n // When no more data needs to be consumed, close the stream\n if (done) {\n controller.close();\n return;\n }\n // Enqueue the next data chunk into our target stream\n controller.enqueue(value);\n return pump();\n });\n }\n },\n });\n this._abortController = ac;\n this._innerReader = reader;\n }\n\n /**\n * Aborts the stream, abandoning any pending operations in progress. Calling this triggers an\n * {@link AbortSignal} that is propagated to the tasks that are producing the data for this stream.\n * @param reason - The reason for aborting the stream. Optional.\n */\n override async cancel(reason?: unknown) {\n this._abortController.abort(reason);\n this._innerReader.releaseLock();\n }\n\n /**\n * The {@link AbortSignal} for the stream. Aborted when {@link cancel} is called.\n */\n get signal() {\n return this._abortController.signal;\n }\n}\n\nexport class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {\n modes: Set<StreamMode>;\n\n private controller: ReadableStreamDefaultController;\n\n private passthroughFn?: (chunk: StreamChunk) => void;\n\n private _closed: boolean = false;\n\n get closed() {\n return this._closed;\n }\n\n constructor(params: {\n passthroughFn?: (chunk: StreamChunk) => void;\n modes: Set<StreamMode>;\n }) {\n let streamControllerPromiseResolver: (\n controller: ReadableStreamDefaultController\n ) => void;\n const streamControllerPromise: Promise<ReadableStreamDefaultController> =\n new Promise<ReadableStreamDefaultController>((resolve) => {\n streamControllerPromiseResolver = resolve;\n });\n\n super({\n start: (controller) => {\n streamControllerPromiseResolver!(controller);\n },\n });\n\n // .start() will always be called before the stream can be interacted\n // with anyway\n void streamControllerPromise.then((controller) => {\n this.controller = controller;\n });\n\n this.passthroughFn = params.passthroughFn;\n this.modes = params.modes;\n }\n\n push(chunk: StreamChunk) {\n // Prevent pushing to a closed stream to avoid race condition errors\n if (this._closed || !this.controller) {\n // Silently drop chunks when stream is closed - this is expected behavior\n // when async operations try to push after stream termination\n return;\n }\n\n // Forward chunk to passthrough function if provided\n this.passthroughFn?.(chunk);\n\n // Attempt to enqueue the chunk to the underlying stream\n this.controller.enqueue(chunk);\n }\n\n close() {\n try {\n this.controller.close();\n } catch {\n // pass\n } finally {\n this._closed = true;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error(e: any) {\n try {\n this.controller?.error(e);\n } finally {\n // Mark the stream as closed so any late `push()` calls from in-flight\n // parallel tasks are dropped instead of throwing on an errored controller.\n this._closed = true;\n }\n }\n}\n\n/**\n * A callback handler that implements stream_mode=tools.\n * Emits on_tool_start, on_tool_event, on_tool_end, on_tool_error events.\n */\nexport class StreamToolsHandler extends BaseCallbackHandler {\n name = \"StreamToolsHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n runs: Record<string, ToolRunInfo | undefined> = {};\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n handleToolStart(\n _tool: Serialized,\n input: string,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string,\n toolCallId?: string\n ) {\n if (!metadata || (tags && tags.includes(TAG_HIDDEN))) return;\n\n const ns = (metadata.langgraph_checkpoint_ns as string)?.split(\"|\") ?? [];\n const info: ToolRunInfo = {\n ns,\n toolCallId,\n toolName: runName ?? \"unknown\",\n input,\n };\n this.runs[runId] = info;\n\n this.streamFn([\n ns,\n \"tools\",\n {\n event: \"on_tool_start\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n input,\n },\n ]);\n }\n\n handleToolEvent(chunk: unknown, runId: string) {\n const info = this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_event\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n data: chunk,\n },\n ]);\n }\n\n handleToolEnd(output: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_end\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n output,\n },\n ]);\n }\n\n handleToolError(err: unknown, runId: string) {\n const info = this.runs[runId];\n delete this.runs[runId];\n if (!info) return;\n\n this.streamFn([\n info.ns,\n \"tools\",\n {\n event: \"on_tool_error\",\n toolCallId: info.toolCallId,\n name: info.toolName,\n error: err,\n },\n ]);\n }\n}\n\nfunction _stringifyAsDict(obj: unknown) {\n return JSON.stringify(obj, function (key: string | number, value: unknown) {\n const rawValue = this[key];\n if (\n rawValue != null &&\n typeof rawValue === \"object\" &&\n \"toDict\" in rawValue &&\n typeof rawValue.toDict === \"function\"\n ) {\n const { type, data } = rawValue.toDict();\n return { ...data, type };\n }\n\n return value;\n });\n}\n\nfunction _serializeError(error: unknown) {\n // eslint-disable-next-line no-instanceof/no-instanceof\n if (error instanceof Error) {\n return { error: error.name, message: error.message };\n }\n return { error: \"Error\", message: JSON.stringify(error) };\n}\n\nfunction _isRunnableConfig(\n config: unknown\n): config is RunnableConfig & { configurable: Record<string, unknown> } {\n if (typeof config !== \"object\" || config == null) return false;\n return (\n \"configurable\" in config &&\n typeof config.configurable === \"object\" &&\n config.configurable != null\n );\n}\n\nfunction _extractCheckpointFromConfig(\n config: RunnableConfig | null | undefined\n) {\n if (!_isRunnableConfig(config) || !config.configurable.thread_id) {\n return null;\n }\n\n return {\n thread_id: config.configurable.thread_id,\n checkpoint_ns: config.configurable.checkpoint_ns || \"\",\n checkpoint_id: config.configurable.checkpoint_id || null,\n checkpoint_map: config.configurable.checkpoint_map || null,\n };\n}\n\nfunction _serializeConfig(config: unknown) {\n if (_isRunnableConfig(config)) {\n const configurable = Object.fromEntries(\n Object.entries(config.configurable).filter(\n ([key]) => !key.startsWith(\"__\")\n )\n );\n\n const newConfig = { ...config, configurable };\n delete newConfig.callbacks;\n return newConfig;\n }\n\n return config;\n}\n\nfunction _serializeCheckpoint(payload: StreamCheckpointsOutput<unknown>) {\n const result: Record<string, unknown> = {\n ...payload,\n checkpoint: _extractCheckpointFromConfig(payload.config),\n parent_checkpoint: _extractCheckpointFromConfig(payload.parentConfig),\n\n config: _serializeConfig(payload.config),\n parent_config: _serializeConfig(payload.parentConfig),\n\n tasks: payload.tasks.map((task) => {\n if (_isRunnableConfig(task.state)) {\n const checkpoint = _extractCheckpointFromConfig(task.state);\n if (checkpoint != null) {\n const cloneTask: Record<string, unknown> = { ...task, checkpoint };\n delete cloneTask.state;\n return cloneTask;\n }\n }\n\n return task;\n }),\n };\n\n delete result.parentConfig;\n return result;\n}\n\nexport function toEventStream(stream: AsyncGenerator) {\n const encoder = new TextEncoder();\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueueChunk = (sse: {\n id?: string;\n event: string;\n data: unknown;\n }) => {\n controller.enqueue(\n encoder.encode(\n `event: ${sse.event}\\ndata: ${_stringifyAsDict(sse.data)}\\n\\n`\n )\n );\n };\n\n try {\n for await (const payload of stream) {\n const [ns, mode, chunk] = payload as AnyStreamOutput;\n\n let data: unknown = chunk;\n if (mode === \"debug\") {\n const debugChunk = chunk;\n\n if (debugChunk.type === \"checkpoint\") {\n data = {\n ...debugChunk,\n payload: _serializeCheckpoint(debugChunk.payload),\n };\n }\n }\n\n if (mode === \"checkpoints\") {\n data = _serializeCheckpoint(chunk);\n }\n\n const event = ns?.length ? `${mode}|${ns.join(\"|\")}` : mode;\n enqueueChunk({ event, data });\n }\n } catch (error) {\n enqueueChunk({ event: \"error\", data: _serializeError(error) });\n }\n\n controller.close();\n },\n });\n}\n\n/** Multiplex subgraph stream chunks into the parent pregel stream. */\nexport function createDuplexStream(\n ...streams: IterableReadableWritableStream[]\n) {\n return new IterableReadableWritableStream({\n passthroughFn: (value: StreamChunk) => {\n const isEnvelope =\n value[1] === \"checkpoints\" && isCheckpointEnvelope(value[2]);\n for (const stream of streams) {\n if (stream.modes.has(value[1]) || isEnvelope) {\n stream.push(value);\n }\n }\n },\n modes: new Set(streams.flatMap((s) => Array.from(s.modes))),\n });\n}\n"],"mappings":"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"}
|
package/dist/stream/convert.cjs
CHANGED
|
@@ -9,12 +9,10 @@
|
|
|
9
9
|
*
|
|
10
10
|
* The `"checkpoints"` mode is likewise excluded from the stream-mode
|
|
11
11
|
* request because the protocol's `checkpoints` channel carries only a
|
|
12
|
-
* lightweight envelope (`id`, `parent_id`, `step`, `source`)
|
|
13
|
-
*
|
|
14
|
-
* the full-state shape
|
|
15
|
-
*
|
|
16
|
-
* next to each `values` event when meta is present, so clients can build
|
|
17
|
-
* branching/time-travel UIs without a full-state `checkpoints` subscription.
|
|
12
|
+
* lightweight envelope (`id`, `parent_id`, `step`, `source`) emitted as a
|
|
13
|
+
* separate ``[namespace, "checkpoints", envelope]`` chunk before each paired
|
|
14
|
+
* `values` chunk — not the full-state shape from Pregel's `checkpoints`
|
|
15
|
+
* stream mode when subscribed via `debug`.
|
|
18
16
|
*/
|
|
19
17
|
const STREAM_EVENTS_V3_MODES = [
|
|
20
18
|
"values",
|
|
@@ -24,6 +22,15 @@ const STREAM_EVENTS_V3_MODES = [
|
|
|
24
22
|
"custom",
|
|
25
23
|
"tasks"
|
|
26
24
|
];
|
|
25
|
+
/**
|
|
26
|
+
* True when `payload` is a lightweight checkpoint envelope (not a full-state
|
|
27
|
+
* Pregel `checkpoints` debug payload).
|
|
28
|
+
*/
|
|
29
|
+
function isCheckpointEnvelope(payload) {
|
|
30
|
+
if (payload == null || typeof payload !== "object") return false;
|
|
31
|
+
const p = payload;
|
|
32
|
+
return typeof p.id === "string" && ("source" in p || typeof p.step === "number") && !("values" in p) && !("config" in p);
|
|
33
|
+
}
|
|
27
34
|
function unwrapMessagesPayload(payload) {
|
|
28
35
|
if (!Array.isArray(payload) || payload.length !== 2) return { data: payload };
|
|
29
36
|
const [data, metadata] = payload;
|
|
@@ -39,7 +46,7 @@ function unwrapMessagesPayload(payload) {
|
|
|
39
46
|
node
|
|
40
47
|
};
|
|
41
48
|
}
|
|
42
|
-
function convertToProtocolEvent({ namespace: ns, mode, payload, seq
|
|
49
|
+
function convertToProtocolEvent({ namespace: ns, mode, payload, seq }) {
|
|
43
50
|
const timestamp = Date.now();
|
|
44
51
|
const base = { type: "event" };
|
|
45
52
|
switch (mode) {
|
|
@@ -67,30 +74,28 @@ function convertToProtocolEvent({ namespace: ns, mode, payload, seq, meta }) {
|
|
|
67
74
|
data: convertToolsPayload(payload)
|
|
68
75
|
}
|
|
69
76
|
}];
|
|
70
|
-
case "
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
case "checkpoints":
|
|
78
|
+
if (!isCheckpointEnvelope(payload)) return [];
|
|
79
|
+
return [{
|
|
73
80
|
...base,
|
|
74
81
|
seq,
|
|
75
82
|
method: "checkpoints",
|
|
76
|
-
params: {
|
|
77
|
-
namespace: ns,
|
|
78
|
-
timestamp,
|
|
79
|
-
data: meta.checkpoint
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
events.push({
|
|
83
|
-
...base,
|
|
84
|
-
seq: meta?.checkpoint != null ? seq + 1 : seq,
|
|
85
|
-
method: "values",
|
|
86
83
|
params: {
|
|
87
84
|
namespace: ns,
|
|
88
85
|
timestamp,
|
|
89
86
|
data: payload
|
|
90
87
|
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
}];
|
|
89
|
+
case "values": return [{
|
|
90
|
+
...base,
|
|
91
|
+
seq,
|
|
92
|
+
method: "values",
|
|
93
|
+
params: {
|
|
94
|
+
namespace: ns,
|
|
95
|
+
timestamp,
|
|
96
|
+
data: payload
|
|
97
|
+
}
|
|
98
|
+
}];
|
|
94
99
|
case "updates": {
|
|
95
100
|
const data = convertUpdatesPayload(payload);
|
|
96
101
|
return [{
|
|
@@ -203,5 +208,6 @@ function convertUpdatesPayload(payload) {
|
|
|
203
208
|
//#endregion
|
|
204
209
|
exports.STREAM_EVENTS_V3_MODES = STREAM_EVENTS_V3_MODES;
|
|
205
210
|
exports.convertToProtocolEvent = convertToProtocolEvent;
|
|
211
|
+
exports.isCheckpointEnvelope = isCheckpointEnvelope;
|
|
206
212
|
|
|
207
213
|
//# sourceMappingURL=convert.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.cjs","names":[],"sources":["../../src/stream/convert.ts"],"sourcesContent":["/**\n * Protocol event conversion — maps raw `[ns, mode, payload, meta?]` stream\n * chunks from graph.stream() to CDDL-aligned ProtocolEvents.\n */\n\nimport type { StreamMode } from \"../pregel/types.js\";\nimport type { StreamChunkMeta } from \"../pregel/stream.js\";\nimport type {\n Namespace,\n ProtocolEvent,\n ToolsEventData,\n UpdatesEventData,\n} from \"./types.js\";\n\n/**\n * The set of stream modes requested by\n * `streamEvents(..., { version: \"v3\" })` — every mode the protocol maps\n * to a channel.\n *\n * The verbose `\"debug\"` mode is intentionally excluded: it was a thin\n * re-wrap of `checkpoints` + `tasks` carrying no new information.\n *\n * The `\"checkpoints\"` mode is likewise excluded from the stream-mode\n * request because the protocol's `checkpoints` channel carries only a\n * lightweight envelope (`id`, `parent_id`, `step`, `source`) derived from\n * {@link StreamChunkMeta.checkpoint} on the adjacent `values` chunk — not\n * the full-state shape that Pregel's `checkpoints` stream mode produces.\n * `convertToProtocolEvent` emits a companion `checkpoints` protocol event\n * next to each `values` event when meta is present, so clients can build\n * branching/time-travel UIs without a full-state `checkpoints` subscription.\n */\nexport const STREAM_EVENTS_V3_MODES: StreamMode[] = [\n \"values\",\n \"updates\",\n \"messages\",\n \"tools\",\n \"custom\",\n \"tasks\",\n];\n\n/**\n * Converts a raw `[ns, mode, payload, meta?]` stream chunk emitted by\n * `graph.stream()` into one or more CDDL-aligned {@link ProtocolEvent}s.\n *\n * Most modes produce a single event. `values` chunks carrying\n * {@link StreamChunkMeta.checkpoint} additionally produce a companion\n * `checkpoints` event immediately after the `values` event, so clients\n * that subscribe only to `checkpoints` can build a branching timeline\n * without also paying for full-state `values` payloads, and clients that\n * subscribe to both can correlate the pair by `(namespace, step)` or by\n * adjacent `seq` numbers.\n *\n * Returns an empty array for stream modes that have no protocol mapping.\n *\n * @param options - Conversion inputs for a single raw stream chunk.\n * @param options.namespace - Hierarchical namespace path identifying the\n * source in the agent tree.\n * @param options.mode - The stream mode that produced this chunk (e.g.\n * `\"messages\"`, `\"tools\"`).\n * @param options.payload - The raw payload emitted by the stream for this\n * mode.\n * @param options.seq - Monotonically increasing sequence number assigned to\n * the first returned event; the companion `checkpoints` event (when\n * emitted) uses `seq + 1`.\n * @param options.meta - Optional chunk-level metadata (e.g. the checkpoint\n * envelope paired with a `values` chunk).\n * @returns An ordered list of {@link ProtocolEvent}s ready for downstream\n * reducers. Callers advance their `seq` counter by `result.length`.\n */\nexport interface ConvertToProtocolEventOptions {\n namespace: Namespace;\n mode: StreamMode;\n payload: unknown;\n seq: number;\n meta?: StreamChunkMeta;\n}\n\nfunction unwrapMessagesPayload(payload: unknown) {\n if (!Array.isArray(payload) || payload.length !== 2) {\n return { data: payload };\n }\n\n const [data, metadata] = payload;\n if (metadata == null || typeof metadata !== \"object\") {\n return { data: payload };\n }\n\n const record = metadata as Record<string, unknown>;\n const node =\n typeof record.langgraph_node === \"string\"\n ? record.langgraph_node\n : undefined;\n const runId = typeof record.run_id === \"string\" ? record.run_id : undefined;\n const dataWithRunId =\n runId != null && data != null && typeof data === \"object\"\n ? { ...(data as Record<string, unknown>), run_id: runId }\n : data;\n\n return { data: dataWithRunId, node };\n}\n\nexport function convertToProtocolEvent({\n namespace: ns,\n mode,\n payload,\n seq,\n meta,\n}: ConvertToProtocolEventOptions): ProtocolEvent[] {\n const timestamp = Date.now();\n const base = { type: \"event\" as const };\n\n switch (mode) {\n case \"messages\": {\n const { data, node } = unwrapMessagesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"messages\",\n params: { namespace: ns, timestamp, ...(node ? { node } : {}), data },\n },\n ];\n }\n\n case \"tools\":\n return [\n {\n ...base,\n seq,\n method: \"tools\",\n params: {\n namespace: ns,\n timestamp,\n data: convertToolsPayload(payload),\n },\n },\n ];\n\n case \"values\": {\n // Emit the `checkpoints` event immediately BEFORE its companion\n // `values` event so clients subscribed to both channels have the\n // envelope buffered by the time the values payload arrives. This\n // lets the SDK attach `parentCheckpointId` to messages extracted\n // from the values snapshot without waiting for a second pass.\n const events: ProtocolEvent[] = [];\n if (meta?.checkpoint != null) {\n events.push({\n ...base,\n seq,\n method: \"checkpoints\",\n params: { namespace: ns, timestamp, data: meta.checkpoint },\n });\n }\n events.push({\n ...base,\n seq: meta?.checkpoint != null ? seq + 1 : seq,\n method: \"values\",\n params: { namespace: ns, timestamp, data: payload },\n });\n return events;\n }\n\n case \"updates\": {\n const data = convertUpdatesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"updates\",\n params: {\n namespace: ns,\n timestamp,\n // Surface the completed node at the top level of `params` so\n // transformers (notably `LifecycleTransformer`) can attribute\n // a finished task to its child namespace without re-parsing\n // the payload. The same value is retained inside `data` for\n // downstream consumers that inspect the event body.\n ...(typeof data.node === \"string\" ? { node: data.node } : {}),\n data,\n },\n },\n ];\n }\n\n case \"custom\": {\n const data =\n typeof payload === \"object\" &&\n payload !== null &&\n !Array.isArray(payload) &&\n \"name\" in payload\n ? payload\n : { payload };\n return [\n {\n ...base,\n seq,\n method: \"custom\",\n params: { namespace: ns, timestamp, data },\n },\n ];\n }\n\n case \"tasks\":\n return [\n {\n ...base,\n seq,\n method: \"tasks\",\n params: { namespace: ns, timestamp, data: payload },\n },\n ];\n\n default:\n return [];\n }\n}\n\n/**\n * Normalises a raw tools-mode payload into a typed {@link ToolsEventData}\n * discriminated union, mapping internal lifecycle events (`on_tool_start`,\n * `on_tool_end`, etc.) to their protocol counterparts.\n *\n * @param payload - The raw payload from a `\"tools\"` stream chunk.\n * @returns A {@link ToolsEventData} object with the appropriate `event`\n * discriminant and associated fields.\n */\nfunction convertToolsPayload(payload: unknown): ToolsEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: \"Unexpected tools payload shape\",\n };\n }\n\n const p = payload as Record<string, unknown>;\n const tool_call_id = String(p.toolCallId ?? \"\");\n\n switch (p.event) {\n case \"on_tool_start\":\n return {\n event: \"tool-started\",\n tool_call_id,\n tool_name: String(p.name ?? \"unknown\"),\n input: p.input,\n };\n\n case \"on_tool_event\": {\n const delta =\n typeof p.data === \"string\" ? p.data : JSON.stringify(p.data ?? \"\");\n return {\n event: \"tool-output-delta\",\n tool_call_id,\n delta,\n };\n }\n\n case \"on_tool_end\":\n return {\n event: \"tool-finished\",\n tool_call_id,\n output: p.output,\n };\n\n case \"on_tool_error\": {\n const err = p.error;\n const errMessage =\n typeof err === \"object\" &&\n err !== null &&\n \"message\" in err &&\n typeof (err as { message: unknown }).message === \"string\"\n ? (err as { message: string }).message\n : String(err ?? \"unknown error\");\n return {\n event: \"tool-error\",\n tool_call_id,\n message: errMessage,\n };\n }\n\n default:\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: `Unknown tool event: ${String(p.event)}`,\n };\n }\n}\n\n/**\n * Extracts the first `{node: delta}` entry from an updates-mode payload and\n * reshapes it into an {@link UpdatesEventData} with explicit `node` and\n * `values` fields. Non-object payloads are coerced to `{ values: {} }`.\n *\n * @param payload - The raw payload from an `\"updates\"` stream chunk,\n * expected to be a `Record<string, unknown>` keyed by node name.\n * @returns An {@link UpdatesEventData} containing the extracted node name\n * and its associated delta values.\n */\nfunction convertUpdatesPayload(payload: unknown): UpdatesEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return { values: {} };\n }\n\n const entries = Object.entries(payload as Record<string, unknown>);\n if (entries.length === 0) {\n return { values: {} };\n }\n\n const [node, values] = entries[0];\n return {\n node,\n values: (typeof values === \"object\" && values !== null\n ? values\n : { value: values }) as Record<string, unknown>,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"convert.cjs","names":[],"sources":["../../src/stream/convert.ts"],"sourcesContent":["/**\n * Protocol event conversion — maps raw `[ns, mode, payload]` stream chunks\n * from graph.stream() to CDDL-aligned ProtocolEvents.\n */\n\nimport type { StreamMode } from \"../pregel/types.js\";\nimport type {\n Namespace,\n ProtocolEvent,\n ToolsEventData,\n UpdatesEventData,\n} from \"./types.js\";\n\n/**\n * The set of stream modes requested by\n * `streamEvents(..., { version: \"v3\" })` — every mode the protocol maps\n * to a channel.\n *\n * The verbose `\"debug\"` mode is intentionally excluded: it was a thin\n * re-wrap of `checkpoints` + `tasks` carrying no new information.\n *\n * The `\"checkpoints\"` mode is likewise excluded from the stream-mode\n * request because the protocol's `checkpoints` channel carries only a\n * lightweight envelope (`id`, `parent_id`, `step`, `source`) emitted as a\n * separate ``[namespace, \"checkpoints\", envelope]`` chunk before each paired\n * `values` chunk — not the full-state shape from Pregel's `checkpoints`\n * stream mode when subscribed via `debug`.\n */\nexport const STREAM_EVENTS_V3_MODES: StreamMode[] = [\n \"values\",\n \"updates\",\n \"messages\",\n \"tools\",\n \"custom\",\n \"tasks\",\n];\n\n/**\n * True when `payload` is a lightweight checkpoint envelope (not a full-state\n * Pregel `checkpoints` debug payload).\n */\nexport function isCheckpointEnvelope(payload: unknown): boolean {\n if (payload == null || typeof payload !== \"object\") return false;\n const p = payload as Record<string, unknown>;\n return (\n typeof p.id === \"string\" &&\n (\"source\" in p || typeof p.step === \"number\") &&\n !(\"values\" in p) &&\n !(\"config\" in p)\n );\n}\n\nexport interface ConvertToProtocolEventOptions {\n namespace: Namespace;\n mode: StreamMode;\n payload: unknown;\n seq: number;\n}\n\nfunction unwrapMessagesPayload(payload: unknown) {\n if (!Array.isArray(payload) || payload.length !== 2) {\n return { data: payload };\n }\n\n const [data, metadata] = payload;\n if (metadata == null || typeof metadata !== \"object\") {\n return { data: payload };\n }\n\n const record = metadata as Record<string, unknown>;\n const node =\n typeof record.langgraph_node === \"string\"\n ? record.langgraph_node\n : undefined;\n const runId = typeof record.run_id === \"string\" ? record.run_id : undefined;\n const dataWithRunId =\n runId != null && data != null && typeof data === \"object\"\n ? { ...(data as Record<string, unknown>), run_id: runId }\n : data;\n\n return { data: dataWithRunId, node };\n}\n\nexport function convertToProtocolEvent({\n namespace: ns,\n mode,\n payload,\n seq,\n}: ConvertToProtocolEventOptions): ProtocolEvent[] {\n const timestamp = Date.now();\n const base = { type: \"event\" as const };\n\n switch (mode) {\n case \"messages\": {\n const { data, node } = unwrapMessagesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"messages\",\n params: { namespace: ns, timestamp, ...(node ? { node } : {}), data },\n },\n ];\n }\n\n case \"tools\":\n return [\n {\n ...base,\n seq,\n method: \"tools\",\n params: {\n namespace: ns,\n timestamp,\n data: convertToolsPayload(payload),\n },\n },\n ];\n\n case \"checkpoints\": {\n if (!isCheckpointEnvelope(payload)) {\n return [];\n }\n return [\n {\n ...base,\n seq,\n method: \"checkpoints\",\n params: { namespace: ns, timestamp, data: payload },\n },\n ];\n }\n\n case \"values\": {\n return [\n {\n ...base,\n seq,\n method: \"values\",\n params: { namespace: ns, timestamp, data: payload },\n },\n ];\n }\n\n case \"updates\": {\n const data = convertUpdatesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"updates\",\n params: {\n namespace: ns,\n timestamp,\n // Surface the completed node at the top level of `params` so\n // transformers (notably `LifecycleTransformer`) can attribute\n // a finished task to its child namespace without re-parsing\n // the payload. The same value is retained inside `data` for\n // downstream consumers that inspect the event body.\n ...(typeof data.node === \"string\" ? { node: data.node } : {}),\n data,\n },\n },\n ];\n }\n\n case \"custom\": {\n const data =\n typeof payload === \"object\" &&\n payload !== null &&\n !Array.isArray(payload) &&\n \"name\" in payload\n ? payload\n : { payload };\n return [\n {\n ...base,\n seq,\n method: \"custom\",\n params: { namespace: ns, timestamp, data },\n },\n ];\n }\n\n case \"tasks\":\n return [\n {\n ...base,\n seq,\n method: \"tasks\",\n params: { namespace: ns, timestamp, data: payload },\n },\n ];\n\n default:\n return [];\n }\n}\n\n/**\n * Normalises a raw tools-mode payload into a typed {@link ToolsEventData}\n * discriminated union, mapping internal lifecycle events (`on_tool_start`,\n * `on_tool_end`, etc.) to their protocol counterparts.\n *\n * @param payload - The raw payload from a `\"tools\"` stream chunk.\n * @returns A {@link ToolsEventData} object with the appropriate `event`\n * discriminant and associated fields.\n */\nfunction convertToolsPayload(payload: unknown): ToolsEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: \"Unexpected tools payload shape\",\n };\n }\n\n const p = payload as Record<string, unknown>;\n const tool_call_id = String(p.toolCallId ?? \"\");\n\n switch (p.event) {\n case \"on_tool_start\":\n return {\n event: \"tool-started\",\n tool_call_id,\n tool_name: String(p.name ?? \"unknown\"),\n input: p.input,\n };\n\n case \"on_tool_event\": {\n const delta =\n typeof p.data === \"string\" ? p.data : JSON.stringify(p.data ?? \"\");\n return {\n event: \"tool-output-delta\",\n tool_call_id,\n delta,\n };\n }\n\n case \"on_tool_end\":\n return {\n event: \"tool-finished\",\n tool_call_id,\n output: p.output,\n };\n\n case \"on_tool_error\": {\n const err = p.error;\n const errMessage =\n typeof err === \"object\" &&\n err !== null &&\n \"message\" in err &&\n typeof (err as { message: unknown }).message === \"string\"\n ? (err as { message: string }).message\n : String(err ?? \"unknown error\");\n return {\n event: \"tool-error\",\n tool_call_id,\n message: errMessage,\n };\n }\n\n default:\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: `Unknown tool event: ${String(p.event)}`,\n };\n }\n}\n\n/**\n * Extracts the first `{node: delta}` entry from an updates-mode payload and\n * reshapes it into an {@link UpdatesEventData} with explicit `node` and\n * `values` fields. Non-object payloads are coerced to `{ values: {} }`.\n *\n * @param payload - The raw payload from an `\"updates\"` stream chunk,\n * expected to be a `Record<string, unknown>` keyed by node name.\n * @returns An {@link UpdatesEventData} containing the extracted node name\n * and its associated delta values.\n */\nfunction convertUpdatesPayload(payload: unknown): UpdatesEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return { values: {} };\n }\n\n const entries = Object.entries(payload as Record<string, unknown>);\n if (entries.length === 0) {\n return { values: {} };\n }\n\n const [node, values] = entries[0];\n return {\n node,\n values: (typeof values === \"object\" && values !== null\n ? values\n : { value: values }) as Record<string, unknown>,\n };\n}\n"],"mappings":"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"}
|