@langchain/langgraph
Version:
LangGraph
1 lines • 12.2 kB
Source Map (JSON)
{"version":3,"file":"io.cjs","names":["e: any","EmptyChannelError","Command","InvalidUpdateError","_isSend","NULL_TASK_ID","TASKS","isXXH3","RESUME","TAG_HIDDEN","ERROR","INTERRUPT","updated: [N, Record<string, unknown>][]","RETURN","counts: Record<C, number>"],"sources":["../../src/pregel/io.ts"],"sourcesContent":["import type {\n CheckpointPendingWrite,\n PendingWrite,\n} from \"@langchain/langgraph-checkpoint\";\n\nimport type { BaseChannel } from \"../channels/base.js\";\nimport type { PregelExecutableTask } from \"./types.js\";\nimport {\n _isSend,\n Command,\n ERROR,\n INTERRUPT,\n NULL_TASK_ID,\n RESUME,\n RETURN,\n TAG_HIDDEN,\n TASKS,\n} from \"../constants.js\";\nimport { EmptyChannelError, InvalidUpdateError } from \"../errors.js\";\nimport { isXXH3 } from \"../hash.js\";\n\nexport function readChannel<C extends PropertyKey>(\n channels: Record<C, BaseChannel>,\n chan: C,\n catchErrors: boolean = true,\n returnException: boolean = false\n): unknown | null {\n try {\n return channels[chan].get();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (e.name === EmptyChannelError.unminifiable_name) {\n if (returnException) {\n return e;\n } else if (catchErrors) {\n return null;\n }\n }\n throw e;\n }\n}\n\nexport function readChannels<C extends PropertyKey>(\n channels: Record<C, BaseChannel>,\n select: C | Array<C>,\n skipEmpty: boolean = true\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Record<string, any> | any {\n if (Array.isArray(select)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const values = {} as Record<C, any>;\n for (const k of select) {\n try {\n values[k] = readChannel(channels, k, !skipEmpty);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (e.name === EmptyChannelError.unminifiable_name) {\n continue;\n }\n }\n }\n return values;\n } else {\n return readChannel(channels, select);\n }\n}\n\n/**\n * Map input chunk to a sequence of pending writes in the form (channel, value).\n */\nexport function* mapCommand(\n cmd: Command,\n pendingWrites: CheckpointPendingWrite[]\n): Generator<[string, string, unknown]> {\n if (cmd.graph === Command.PARENT) {\n throw new InvalidUpdateError(\"There is no parent graph.\");\n }\n if (cmd.goto) {\n let sends;\n if (Array.isArray(cmd.goto)) {\n sends = cmd.goto;\n } else {\n sends = [cmd.goto];\n }\n for (const send of sends) {\n if (_isSend(send)) {\n yield [NULL_TASK_ID, TASKS, send];\n } else if (typeof send === \"string\") {\n yield [NULL_TASK_ID, `branch:to:${send}`, \"__start__\"];\n } else {\n throw new Error(\n `In Command.send, expected Send or string, got ${typeof send}`\n );\n }\n }\n }\n if (cmd.resume) {\n if (\n typeof cmd.resume === \"object\" &&\n Object.keys(cmd.resume).length &&\n Object.keys(cmd.resume).every(isXXH3)\n ) {\n for (const [tid, resume] of Object.entries(cmd.resume)) {\n const existing =\n pendingWrites\n .filter((w) => w[0] === tid && w[1] === RESUME)\n .map((w) => w[2])\n .slice(0, 1) ?? [];\n existing.push(resume);\n yield [tid, RESUME, existing];\n }\n } else {\n yield [NULL_TASK_ID, RESUME, cmd.resume];\n }\n }\n if (cmd.update) {\n if (typeof cmd.update !== \"object\" || !cmd.update) {\n throw new Error(\n \"Expected cmd.update to be a dict mapping channel names to update values\"\n );\n }\n\n if (Array.isArray(cmd.update)) {\n for (const [k, v] of cmd.update) {\n yield [NULL_TASK_ID, k, v];\n }\n } else {\n for (const [k, v] of Object.entries(cmd.update)) {\n yield [NULL_TASK_ID, k, v];\n }\n }\n }\n}\n\n/**\n * Map input chunk to a sequence of pending writes in the form [channel, value].\n */\nexport function* mapInput<C extends PropertyKey>(\n inputChannels: C | Array<C>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n chunk?: any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Generator<[C, any]> {\n if (chunk !== undefined && chunk !== null) {\n if (\n Array.isArray(inputChannels) &&\n typeof chunk === \"object\" &&\n !Array.isArray(chunk)\n ) {\n for (const k in chunk) {\n if (inputChannels.includes(k as C)) {\n yield [k as C, chunk[k]];\n }\n }\n } else if (Array.isArray(inputChannels)) {\n throw new Error(\n `Input chunk must be an object when \"inputChannels\" is an array`\n );\n } else {\n yield [inputChannels, chunk];\n }\n }\n}\n\n/**\n * Map pending writes (a sequence of tuples (channel, value)) to output chunk.\n */\nexport function* mapOutputValues<C extends PropertyKey>(\n outputChannels: C | Array<C>,\n pendingWrites: readonly PendingWrite<C>[] | true,\n channels: Record<C, BaseChannel>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Generator<Record<string, any>, any> {\n if (Array.isArray(outputChannels)) {\n if (\n pendingWrites === true ||\n pendingWrites.find(([chan, _]) => outputChannels.includes(chan))\n ) {\n yield readChannels(channels, outputChannels);\n }\n } else {\n if (\n pendingWrites === true ||\n pendingWrites.some(([chan, _]) => chan === outputChannels)\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n yield readChannel(channels, outputChannels) as any;\n }\n }\n}\n\n/**\n * Map pending writes (a sequence of tuples (channel, value)) to output chunk.\n * @internal\n *\n * @param outputChannels - The channels to output.\n * @param tasks - The tasks to output.\n * @param cached - Whether the output is cached.\n *\n * @returns A generator that yields the output chunk (if any).\n */\nexport function* mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(\n outputChannels: C | Array<C>,\n tasks: readonly [PregelExecutableTask<N, C>, PendingWrite<C>[]][],\n cached?: boolean\n): Generator<Record<N, Record<string, unknown> | unknown>> {\n const outputTasks = tasks.filter(([task, ww]) => {\n return (\n (task.config === undefined || !task.config.tags?.includes(TAG_HIDDEN)) &&\n ww[0][0] !== ERROR &&\n ww[0][0] !== INTERRUPT\n );\n });\n if (!outputTasks.length) {\n return;\n }\n\n let updated: [N, Record<string, unknown>][];\n\n if (\n outputTasks.some(([task]) =>\n task.writes.some(([chan, _]) => chan === RETURN)\n )\n ) {\n // TODO: probably should assert that RETURN is the only \"non-special\" channel (starts with \"__\")\n updated = outputTasks.flatMap(([task]) =>\n task.writes\n .filter(([chan, _]) => chan === RETURN)\n .map(([_, value]) => [task.name, value] as [N, Record<string, unknown>])\n );\n } else if (!Array.isArray(outputChannels)) {\n // special case where graph state is a single channel (MessageGraph)\n // probably using this in functional API, too\n updated = outputTasks.flatMap(([task]) =>\n task.writes\n .filter(([chan, _]) => chan === outputChannels)\n .map(([_, value]) => [task.name, value] as [N, Record<string, unknown>])\n );\n } else {\n updated = outputTasks.flatMap(([task]) => {\n const { writes } = task;\n const counts: Record<C, number> = {} as Record<C, number>;\n for (const [chan] of writes) {\n if (outputChannels.includes(chan)) {\n counts[chan] = (counts[chan] || 0) + 1;\n }\n }\n\n if ((Object.values(counts) as number[]).some((count) => count > 1)) {\n // Multiple writes to the same channel: create separate entries\n return writes\n .filter(([chan]) => outputChannels.includes(chan))\n .map(\n ([chan, value]) =>\n [task.name, { [chan]: value }] as [N, Record<string, unknown>]\n );\n } else {\n // Single write to each channel: create a single combined entry\n return [\n [\n task.name,\n Object.fromEntries(\n writes.filter(([chan]) => outputChannels.includes(chan))\n ),\n ] as [N, Record<string, unknown>],\n ];\n }\n });\n }\n\n const grouped = {} as Record<N, unknown[]>;\n\n for (const [node, value] of updated) {\n if (!(node in grouped)) {\n grouped[node] = [];\n }\n grouped[node].push(value);\n }\n\n const flattened = {} as Record<N, unknown>;\n for (const node in grouped) {\n if (grouped[node].length === 1) {\n const [write] = grouped[node];\n flattened[node] = write;\n } else {\n flattened[node] = grouped[node];\n }\n }\n\n if (cached) {\n flattened[\"__metadata__\" as N] = { cached };\n }\n yield flattened;\n}\n\nexport function single<T>(iter: IterableIterator<T>): T | null {\n // eslint-disable-next-line no-unreachable-loop\n for (const value of iter) {\n return value;\n }\n return null;\n}\n"],"mappings":"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"}