UNPKG

@langchain/langgraph

Version:
135 lines (134 loc) 5.41 kB
const require_constants = require("../constants.cjs"); const require_errors = require("../errors.cjs"); const require_base = require("./base.cjs"); let _langchain_langgraph_checkpoint = require("@langchain/langgraph-checkpoint"); //#region src/channels/delta.ts const isDeltaChannel = (value) => { return value != null && value.lc_graph_name === "DeltaChannel"; }; /** * Reducer channel that stores only a sentinel in checkpoint blobs and * reconstructs state by replaying ancestor writes through the reducer. * * `DeltaChannel` avoids re-serializing the full accumulated value at every * step. Instead of writing the value into `channel_values`, the channel is * omitted entirely and its state is reconstructed on read by walking the * ancestor chain and replaying the per-step writes through the reducer (see * {@link BaseCheckpointSaver.getDeltaChannelHistory}). * * Snapshot cadence is driven by two counters: a per-channel update count and * the total supersteps since the last snapshot. A full {@link DeltaSnapshot} * blob is written when EITHER the update count reaches `snapshotFrequency` OR * the supersteps count reaches the system-wide * `DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT` bound (default 5000), bounding replay * depth even for channels that stop receiving writes. * * @remarks Beta. The API and on-disk representation may change in future * releases. Threads written with `DeltaChannel` today are expected to remain * readable, but the surrounding contract (`getDeltaChannelHistory`, the * `DeltaSnapshot` blob shape, the `counters_since_delta_snapshot` metadata * field) is not yet stable. * * @example * ```typescript * import { Annotation } from "@langchain/langgraph"; * import { DeltaChannel, messagesDeltaReducer } from "@langchain/langgraph"; * * const State = Annotation.Root({ * messages: Annotation<BaseMessage[]>({ * reducer: () => [], // ignored; DeltaChannel is supplied below * }), * }); * ``` */ var DeltaChannel = class DeltaChannel extends require_base.BaseChannel { lc_graph_name = "DeltaChannel"; /** `undefined` represents the Python `MISSING` sentinel (empty channel). */ value; reducer; snapshotFrequency; initialValueFactory; constructor(reducer, options) { super(); const snapshotFrequency = options?.snapshotFrequency ?? 1e3; if (!Number.isInteger(snapshotFrequency) || snapshotFrequency <= 0) throw new Error(`snapshotFrequency must be a positive integer, got ${snapshotFrequency}`); this.reducer = reducer; this.snapshotFrequency = snapshotFrequency; this.initialValueFactory = options?.initialValueFactory ?? (() => []); this.value = void 0; } fromCheckpoint(checkpoint) { const empty = new DeltaChannel(this.reducer, { snapshotFrequency: this.snapshotFrequency, initialValueFactory: this.initialValueFactory }); if (checkpoint === void 0) empty.value = this.initialValueFactory(); else if ((0, _langchain_langgraph_checkpoint.isDeltaSnapshot)(checkpoint)) empty.value = checkpoint.value; else empty.value = checkpoint; return empty; } /** * Apply ancestor writes oldest-to-newest via a single reducer call. * * If any write is an Overwrite, the last one in the sequence acts as the * reset point: its value becomes the new base and only writes after it are * passed to the reducer. */ replayWrites(writes) { const values = writes.map((w) => w[2]); if (values.length === 0) return; let base = this.value; let start = 0; for (let i = 0; i < values.length; i += 1) { const [isOverwrite, overwriteValue] = require_constants._getOverwriteValue(values[i]); if (isOverwrite) { base = overwriteValue !== void 0 && overwriteValue !== null ? overwriteValue : this.initialValueFactory(); start = i + 1; } } const remaining = values.slice(start); this.value = remaining.length > 0 ? this.reducer(base, remaining) : base; } update(values) { if (values.length === 0) return false; let overwriteValue; let hasOverwrite = false; for (const value of values) if (require_constants._isOverwriteValue(value)) { if (hasOverwrite) throw new require_errors.InvalidUpdateError("Can receive only one Overwrite value per step."); hasOverwrite = true; [, overwriteValue] = require_constants._getOverwriteValue(value); } if (hasOverwrite) { this.value = overwriteValue !== void 0 && overwriteValue !== null ? overwriteValue : this.initialValueFactory(); return true; } const base = this.value === void 0 ? this.initialValueFactory() : this.value; this.value = this.reducer(base, values); return true; } get() { if (this.value === void 0) throw new require_errors.EmptyChannelError(); return this.value; } /** * Always returns `undefined` (the Python `MISSING` sentinel). Snapshot * decisions live in `createCheckpoint`, which has the channel version and * writes a {@link DeltaSnapshot} directly into `channel_values`. For * non-snapshot steps the channel does not appear in `channel_values`; * reconstruction walks ancestor writes via the saver's * `getDeltaChannelHistory`. */ checkpoint() {} isAvailable() { return this.value !== void 0; } equals(other) { if (this === other) return true; if (!isDeltaChannel(other)) return false; if (this.snapshotFrequency !== other.snapshotFrequency) return false; return this.reducer === other.reducer; } }; //#endregion exports.DeltaChannel = DeltaChannel; //# sourceMappingURL=delta.cjs.map