{"version":3,"file":"delta.cjs","names":["BaseChannel","_getOverwriteValue","_isOverwriteValue","InvalidUpdateError","EmptyChannelError"],"sources":["../../src/channels/delta.ts"],"sourcesContent":["import {\n  type CheckpointPendingWrite,\n  DeltaSnapshot,\n  isDeltaSnapshot,\n} from \"@langchain/langgraph-checkpoint\";\nimport {\n  _getOverwriteValue,\n  _isOverwriteValue,\n  type OverwriteValue,\n} from \"../constants.js\";\nimport { EmptyChannelError, InvalidUpdateError } from \"../errors.js\";\nimport { BaseChannel } from \"./base.js\";\n\n/**\n * A batch reducer for use with {@link DeltaChannel}.\n *\n * Receives the current accumulated value and a batch of writes in one call,\n * returning the new accumulated value:\n * `reducer(state, [write1, write2, ...]) -> newState`.\n *\n * Reducers must be deterministic and batching-invariant (associative across\n * folds): applying two consecutive write batches separately must produce the\n * same state as applying their concatenation once:\n *\n * ```text\n * reducer(reducer(state, xs), ys) === reducer(state, xs.concat(ys))\n * ```\n *\n * This lets LangGraph replay checkpointed writes in larger batches than they\n * were originally produced without changing reconstructed state. If your\n * reducer is not associative, use {@link BinaryOperatorAggregate} instead —\n * `DeltaChannel` is not a drop-in replacement for every reducer.\n */\nexport type DeltaReducer<ValueType, UpdateType = unknown> = (\n  state: ValueType,\n  writes: UpdateType[]\n) => ValueType;\n\ntype OverwriteOrValue<ValueType, UpdateType> =\n  | OverwriteValue<ValueType>\n  | UpdateType;\n\nconst isDeltaChannel = (\n  value: BaseChannel\n): value is DeltaChannel<unknown, unknown> => {\n  return value != null && value.lc_graph_name === \"DeltaChannel\";\n};\n\n/**\n * Reducer channel that stores only a sentinel in checkpoint blobs and\n * reconstructs state by replaying ancestor writes through the reducer.\n *\n * `DeltaChannel` avoids re-serializing the full accumulated value at every\n * step. Instead of writing the value into `channel_values`, the channel is\n * omitted entirely and its state is reconstructed on read by walking the\n * ancestor chain and replaying the per-step writes through the reducer (see\n * {@link BaseCheckpointSaver.getDeltaChannelHistory}).\n *\n * Snapshot cadence is driven by two counters: a per-channel update count and\n * the total supersteps since the last snapshot. A full {@link DeltaSnapshot}\n * blob is written when EITHER the update count reaches `snapshotFrequency` OR\n * the supersteps count reaches the system-wide\n * `DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT` bound (default 5000), bounding replay\n * depth even for channels that stop receiving writes.\n *\n * @remarks Beta. The API and on-disk representation may change in future\n * releases. Threads written with `DeltaChannel` today are expected to remain\n * readable, but the surrounding contract (`getDeltaChannelHistory`, the\n * `DeltaSnapshot` blob shape, the `counters_since_delta_snapshot` metadata\n * field) is not yet stable.\n *\n * @example\n * ```typescript\n * import { Annotation } from \"@langchain/langgraph\";\n * import { DeltaChannel, messagesDeltaReducer } from \"@langchain/langgraph\";\n *\n * const State = Annotation.Root({\n *   messages: Annotation<BaseMessage[]>({\n *     reducer: () => [], // ignored; DeltaChannel is supplied below\n *   }),\n * });\n * ```\n */\nexport class DeltaChannel<\n  ValueType = unknown,\n  UpdateType = unknown,\n> extends BaseChannel<\n  ValueType,\n  OverwriteOrValue<ValueType, UpdateType>,\n  undefined\n> {\n  lc_graph_name = \"DeltaChannel\";\n\n  /** `undefined` represents the Python `MISSING` sentinel (empty channel). */\n  value: ValueType | undefined;\n\n  reducer: DeltaReducer<ValueType, UpdateType>;\n\n  snapshotFrequency: number;\n\n  initialValueFactory: () => ValueType;\n\n  constructor(\n    reducer: DeltaReducer<ValueType, UpdateType>,\n    options?: {\n      snapshotFrequency?: number;\n      initialValueFactory?: () => ValueType;\n    }\n  ) {\n    super();\n    const snapshotFrequency = options?.snapshotFrequency ?? 1000;\n    if (!Number.isInteger(snapshotFrequency) || snapshotFrequency <= 0) {\n      throw new Error(\n        `snapshotFrequency must be a positive integer, got ${snapshotFrequency}`\n      );\n    }\n    this.reducer = reducer;\n    this.snapshotFrequency = snapshotFrequency;\n    this.initialValueFactory =\n      options?.initialValueFactory ?? (() => [] as ValueType);\n    this.value = undefined;\n  }\n\n  public fromCheckpoint(checkpoint?: undefined | DeltaSnapshot | ValueType) {\n    const empty = new DeltaChannel<ValueType, UpdateType>(this.reducer, {\n      snapshotFrequency: this.snapshotFrequency,\n      initialValueFactory: this.initialValueFactory,\n    });\n    if (checkpoint === undefined) {\n      empty.value = this.initialValueFactory();\n    } else if (isDeltaSnapshot(checkpoint)) {\n      empty.value = checkpoint.value as ValueType;\n    } else {\n      empty.value = checkpoint as ValueType;\n    }\n    return empty as this;\n  }\n\n  /**\n   * Apply ancestor writes oldest-to-newest via a single reducer call.\n   *\n   * If any write is an Overwrite, the last one in the sequence acts as the\n   * reset point: its value becomes the new base and only writes after it are\n   * passed to the reducer.\n   */\n  public replayWrites(writes: CheckpointPendingWrite[]): void {\n    const values = writes.map((w) => w[2]);\n    if (values.length === 0) return;\n    let base = this.value as ValueType;\n    let start = 0;\n    for (let i = 0; i < values.length; i += 1) {\n      const [isOverwrite, overwriteValue] = _getOverwriteValue<ValueType>(\n        values[i]\n      );\n      if (isOverwrite) {\n        base =\n          overwriteValue !== undefined && overwriteValue !== null\n            ? overwriteValue\n            : this.initialValueFactory();\n        start = i + 1;\n      }\n    }\n    const remaining = values.slice(start) as UpdateType[];\n    this.value = remaining.length > 0 ? this.reducer(base, remaining) : base;\n  }\n\n  public update(values: OverwriteOrValue<ValueType, UpdateType>[]): boolean {\n    if (values.length === 0) return false;\n\n    let overwriteIdx: number | undefined;\n    for (let i = 0; i < values.length; i += 1) {\n      if (_isOverwriteValue<ValueType>(values[i])) {\n        if (overwriteIdx !== undefined) {\n          throw new InvalidUpdateError(\n            \"Can receive only one Overwrite value per step.\"\n          );\n        }\n        overwriteIdx = i;\n      }\n    }\n\n    if (overwriteIdx !== undefined) {\n      const [, overwriteValue] = _getOverwriteValue<ValueType>(\n        values[overwriteIdx]\n      );\n      const base =\n        overwriteValue !== undefined && overwriteValue !== null\n          ? overwriteValue\n          : this.initialValueFactory();\n      // Treat Overwrite as a hard reset: drop everything up to and including\n      // the overwrite, keeping only writes that follow it. This mirrors\n      // `replayWrites` so reconstruction from a checkpoint reproduces the live\n      // state even when a plain write precedes the Overwrite in the same step.\n      const remaining = values.slice(overwriteIdx + 1) as UpdateType[];\n      this.value = remaining.length > 0 ? this.reducer(base, remaining) : base;\n      return true;\n    }\n\n    const base =\n      this.value === undefined ? this.initialValueFactory() : this.value;\n    this.value = this.reducer(base, values as UpdateType[]);\n    return true;\n  }\n\n  public get(): ValueType {\n    if (this.value === undefined) {\n      throw new EmptyChannelError();\n    }\n    return this.value;\n  }\n\n  /**\n   * Always returns `undefined` (the Python `MISSING` sentinel). Snapshot\n   * decisions live in `createCheckpoint`, which has the channel version and\n   * writes a {@link DeltaSnapshot} directly into `channel_values`. For\n   * non-snapshot steps the channel does not appear in `channel_values`;\n   * reconstruction walks ancestor writes via the saver's\n   * `getDeltaChannelHistory`.\n   */\n  public checkpoint(): undefined {\n    return undefined;\n  }\n\n  isAvailable(): boolean {\n    return this.value !== undefined;\n  }\n\n  equals(other: BaseChannel): boolean {\n    if (this === other) return true;\n    if (!isDeltaChannel(other)) return false;\n    if (this.snapshotFrequency !== other.snapshotFrequency) return false;\n    return this.reducer === other.reducer;\n  }\n}\n"],"mappings":";;;;;AA0CA,MAAM,kBACJ,UAC4C;AAC5C,QAAO,SAAS,QAAQ,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsClD,IAAa,eAAb,MAAa,qBAGHA,aAAAA,YAIR;CACA,gBAAgB;;CAGhB;CAEA;CAEA;CAEA;CAEA,YACE,SACA,SAIA;AACA,SAAO;EACP,MAAM,oBAAoB,SAAS,qBAAqB;AACxD,MAAI,CAAC,OAAO,UAAU,kBAAkB,IAAI,qBAAqB,EAC/D,OAAM,IAAI,MACR,qDAAqD,oBACtD;AAEH,OAAK,UAAU;AACf,OAAK,oBAAoB;AACzB,OAAK,sBACH,SAAS,8BAA8B,EAAE;AAC3C,OAAK,QAAQ,KAAA;;CAGf,eAAsB,YAAoD;EACxE,MAAM,QAAQ,IAAI,aAAoC,KAAK,SAAS;GAClE,mBAAmB,KAAK;GACxB,qBAAqB,KAAK;GAC3B,CAAC;AACF,MAAI,eAAe,KAAA,EACjB,OAAM,QAAQ,KAAK,qBAAqB;gEACf,WAAW,CACpC,OAAM,QAAQ,WAAW;MAEzB,OAAM,QAAQ;AAEhB,SAAO;;;;;;;;;CAUT,aAAoB,QAAwC;EAC1D,MAAM,SAAS,OAAO,KAAK,MAAM,EAAE,GAAG;AACtC,MAAI,OAAO,WAAW,EAAG;EACzB,IAAI,OAAO,KAAK;EAChB,IAAI,QAAQ;AACZ,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;GACzC,MAAM,CAAC,aAAa,kBAAkBC,kBAAAA,mBACpC,OAAO,GACR;AACD,OAAI,aAAa;AACf,WACE,mBAAmB,KAAA,KAAa,mBAAmB,OAC/C,iBACA,KAAK,qBAAqB;AAChC,YAAQ,IAAI;;;EAGhB,MAAM,YAAY,OAAO,MAAM,MAAM;AACrC,OAAK,QAAQ,UAAU,SAAS,IAAI,KAAK,QAAQ,MAAM,UAAU,GAAG;;CAGtE,OAAc,QAA4D;AACxE,MAAI,OAAO,WAAW,EAAG,QAAO;EAEhC,IAAI;AACJ,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,EACtC,KAAIC,kBAAAA,kBAA6B,OAAO,GAAG,EAAE;AAC3C,OAAI,iBAAiB,KAAA,EACnB,OAAM,IAAIC,eAAAA,mBACR,iDACD;AAEH,kBAAe;;AAInB,MAAI,iBAAiB,KAAA,GAAW;GAC9B,MAAM,GAAG,kBAAkBF,kBAAAA,mBACzB,OAAO,cACR;GACD,MAAM,OACJ,mBAAmB,KAAA,KAAa,mBAAmB,OAC/C,iBACA,KAAK,qBAAqB;GAKhC,MAAM,YAAY,OAAO,MAAM,eAAe,EAAE;AAChD,QAAK,QAAQ,UAAU,SAAS,IAAI,KAAK,QAAQ,MAAM,UAAU,GAAG;AACpE,UAAO;;EAGT,MAAM,OACJ,KAAK,UAAU,KAAA,IAAY,KAAK,qBAAqB,GAAG,KAAK;AAC/D,OAAK,QAAQ,KAAK,QAAQ,MAAM,OAAuB;AACvD,SAAO;;CAGT,MAAwB;AACtB,MAAI,KAAK,UAAU,KAAA,EACjB,OAAM,IAAIG,eAAAA,mBAAmB;AAE/B,SAAO,KAAK;;;;;;;;;;CAWd,aAA+B;CAI/B,cAAuB;AACrB,SAAO,KAAK,UAAU,KAAA;;CAGxB,OAAO,OAA6B;AAClC,MAAI,SAAS,MAAO,QAAO;AAC3B,MAAI,CAAC,eAAe,MAAM,CAAE,QAAO;AACnC,MAAI,KAAK,sBAAsB,MAAM,kBAAmB,QAAO;AAC/D,SAAO,KAAK,YAAY,MAAM"}