{"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":";;;;;AAqBA,SAAgB,YACd,UACA,MACA,cAAuB,MACvB,kBAA2B,OACX;AAChB,KAAI;AACF,SAAO,SAAS,MAAM;UAEfA,GAAQ;AACf,MAAI,EAAE,SAASC,iCAAkB,mBAC/B;OAAI,gBACF,QAAO;YACE,YACT,QAAO;;AAGX,QAAM;;;AAIV,SAAgB,aACd,UACA,QACA,YAAqB,MAEM;AAC3B,KAAI,MAAM,QAAQ,SAAS;EAEzB,MAAM,SAAS;AACf,OAAK,MAAM,KAAK,OACd,KAAI;AACF,UAAO,KAAK,YAAY,UAAU,GAAG,CAAC;WAE/BD,GAAQ;AACf,OAAI,EAAE,SAASC,iCAAkB,kBAC/B;;AAIN,SAAO;OAEP,QAAO,YAAY,UAAU;;;;;AAOjC,UAAiB,WACf,KACA,eACsC;AACtC,KAAI,IAAI,UAAUC,0BAAQ,OACxB,OAAM,IAAIC,kCAAmB;AAE/B,KAAI,IAAI,MAAM;EACZ,IAAI;AACJ,MAAI,MAAM,QAAQ,IAAI,MACpB,SAAQ,IAAI;MAEZ,SAAQ,CAAC,IAAI;AAEf,OAAK,MAAM,QAAQ,MACjB,KAAIC,0BAAQ,MACV,OAAM;GAACC;GAAcC;GAAO;;WACnB,OAAO,SAAS,SACzB,OAAM;GAACD;GAAc,aAAa;GAAQ;;MAE1C,OAAM,IAAI,MACR,iDAAiD,OAAO;;AAKhE,KAAI,IAAI,OACN,KACE,OAAO,IAAI,WAAW,YACtB,OAAO,KAAK,IAAI,QAAQ,UACxB,OAAO,KAAK,IAAI,QAAQ,MAAME,qBAE9B,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,IAAI,SAAS;EACtD,MAAM,WACJ,cACG,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE,OAAOC,0BACvC,KAAK,MAAM,EAAE,IACb,MAAM,GAAG,MAAM;AACpB,WAAS,KAAK;AACd,QAAM;GAAC;GAAKA;GAAQ;;;KAGtB,OAAM;EAACH;EAAcG;EAAQ,IAAI;;AAGrC,KAAI,IAAI,QAAQ;AACd,MAAI,OAAO,IAAI,WAAW,YAAY,CAAC,IAAI,OACzC,OAAM,IAAI,MACR;AAIJ,MAAI,MAAM,QAAQ,IAAI,QACpB,MAAK,MAAM,CAAC,GAAG,MAAM,IAAI,OACvB,OAAM;GAACH;GAAc;GAAG;;MAG1B,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,IAAI,QACtC,OAAM;GAACA;GAAc;GAAG;;;;;;;AAShC,UAAiB,SACf,eAEA,OAEqB;AACrB,KAAI,UAAU,UAAa,UAAU,KACnC,KACE,MAAM,QAAQ,kBACd,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,QAEf;OAAK,MAAM,KAAK,MACd,KAAI,cAAc,SAAS,GACzB,OAAM,CAAC,GAAQ,MAAM;YAGhB,MAAM,QAAQ,eACvB,OAAM,IAAI,MACR;KAGF,OAAM,CAAC,eAAe;;;;;AAQ5B,UAAiB,gBACf,gBACA,eACA,UAEqC;AACrC,KAAI,MAAM,QAAQ,iBAChB;MACE,kBAAkB,QAClB,cAAc,MAAM,CAAC,MAAM,OAAO,eAAe,SAAS,OAE1D,OAAM,aAAa,UAAU;YAI7B,kBAAkB,QAClB,cAAc,MAAM,CAAC,MAAM,OAAO,SAAS,gBAG3C,OAAM,YAAY,UAAU;;;;;;;;;;;;AAelC,UAAiB,iBACf,gBACA,OACA,QACyD;CACzD,MAAM,cAAc,MAAM,QAAQ,CAAC,MAAM,QAAQ;AAC/C,UACG,KAAK,WAAW,UAAa,CAAC,KAAK,OAAO,MAAM,SAASI,kCAC1D,GAAG,GAAG,OAAOC,2BACb,GAAG,GAAG,OAAOC;;AAGjB,KAAI,CAAC,YAAY,OACf;CAGF,IAAIC;AAEJ,KACE,YAAY,MAAM,CAAC,UACjB,KAAK,OAAO,MAAM,CAAC,MAAM,OAAO,SAASC,2BAI3C,WAAU,YAAY,SAAS,CAAC,UAC9B,KAAK,OACF,QAAQ,CAAC,MAAM,OAAO,SAASA,0BAC/B,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,MAAM;UAE5B,CAAC,MAAM,QAAQ,gBAGxB,WAAU,YAAY,SAAS,CAAC,UAC9B,KAAK,OACF,QAAQ,CAAC,MAAM,OAAO,SAAS,gBAC/B,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,MAAM;KAGrC,WAAU,YAAY,SAAS,CAAC,UAAU;EACxC,MAAM,EAAE,WAAW;EACnB,MAAMC,SAA4B;AAClC,OAAK,MAAM,CAAC,SAAS,OACnB,KAAI,eAAe,SAAS,MAC1B,QAAO,SAAS,OAAO,SAAS,KAAK;AAIzC,MAAK,OAAO,OAAO,QAAqB,MAAM,UAAU,QAAQ,GAE9D,QAAO,OACJ,QAAQ,CAAC,UAAU,eAAe,SAAS,OAC3C,KACE,CAAC,MAAM,WACN,CAAC,KAAK,MAAM,GAAG,OAAO;MAI5B,QAAO,CACL,CACE,KAAK,MACL,OAAO,YACL,OAAO,QAAQ,CAAC,UAAU,eAAe,SAAS;;CAQ9D,MAAM,UAAU;AAEhB,MAAK,MAAM,CAAC,MAAM,UAAU,SAAS;AACnC,MAAI,EAAE,QAAQ,SACZ,SAAQ,QAAQ;AAElB,UAAQ,MAAM,KAAK;;CAGrB,MAAM,YAAY;AAClB,MAAK,MAAM,QAAQ,QACjB,KAAI,QAAQ,MAAM,WAAW,GAAG;EAC9B,MAAM,CAAC,SAAS,QAAQ;AACxB,YAAU,QAAQ;OAElB,WAAU,QAAQ,QAAQ;AAI9B,KAAI,OACF,WAAU,kBAAuB,EAAE;AAErC,OAAM"}