{"version":3,"file":"io.cjs","names":["EmptyChannelError","Command","InvalidUpdateError","_isSend","NULL_TASK_ID","TASKS","isXXH3","RESUME","RETURN"],"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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"}