New:Socket for Asana Is Now Available.Learn more
Get Started

@langchain/langgraph-checkpoint

Package Overview
Dependencies
Maintainers
2
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@langchain/langgraph-checkpoint - npm Package Compare versions

Comparing version
1.1.3
to
1.1.4
+2
-2
dist/index.d.cts

@@ -6,3 +6,3 @@ import { SerializerProtocol } from "./serde/base.cjs";

import { uuid5, uuid6 } from "./id.cjs";
import { ChannelProtocol, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot } from "./serde/types.cjs";
import { ChannelProtocol, ConstructorRecord, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot } from "./serde/types.cjs";
import { BaseStore, GetOperation, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PutOperation, SearchItem, SearchOperation, getTextAtPath, tokenizePath } from "./store/base.cjs";

@@ -13,2 +13,2 @@ import { AsyncBatchedStore } from "./store/batch.cjs";

import { InMemoryCache } from "./cache/memory.cjs";
export { All, AsyncBatchedStore, BaseCache, BaseCheckpointSaver, BaseStore, CacheFullKey, CacheNamespace, ChannelProtocol, ChannelVersions, Checkpoint, CheckpointListOptions, CheckpointMetadata, CheckpointPendingWrite, CheckpointTuple, DeltaChannelHistory, DeltaSnapshot, ERROR, EXCLUDED_METADATA_KEYS, GetOperation, INTERRUPT, InMemoryCache, InMemoryStore, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, MemorySaver, MemoryStore, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PendingWrite, PendingWriteValue, PutOperation, RESUME, ReadonlyCheckpoint, SCHEDULED, SearchItem, SearchOperation, SendProtocol, SerializerProtocol, TASKS, WRITES_IDX_MAP, compareChannelVersions, copyCheckpoint, deepCopy, emptyCheckpoint, getCheckpointId, getTextAtPath, isDeltaSnapshot, maxChannelVersion, tokenizePath, uuid5, uuid6 };
export { All, AsyncBatchedStore, BaseCache, BaseCheckpointSaver, BaseStore, CacheFullKey, CacheNamespace, ChannelProtocol, ChannelVersions, Checkpoint, CheckpointListOptions, CheckpointMetadata, CheckpointPendingWrite, CheckpointTuple, ConstructorRecord, DeltaChannelHistory, DeltaSnapshot, ERROR, EXCLUDED_METADATA_KEYS, GetOperation, INTERRUPT, InMemoryCache, InMemoryStore, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, MemorySaver, MemoryStore, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PendingWrite, PendingWriteValue, PutOperation, RESUME, ReadonlyCheckpoint, SCHEDULED, SearchItem, SearchOperation, SendProtocol, SerializerProtocol, TASKS, WRITES_IDX_MAP, compareChannelVersions, copyCheckpoint, deepCopy, emptyCheckpoint, getCheckpointId, getTextAtPath, isDeltaSnapshot, maxChannelVersion, tokenizePath, uuid5, uuid6 };

@@ -6,3 +6,3 @@ import { SerializerProtocol } from "./serde/base.js";

import { uuid5, uuid6 } from "./id.js";
import { ChannelProtocol, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot } from "./serde/types.js";
import { ChannelProtocol, ConstructorRecord, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot } from "./serde/types.js";
import { BaseStore, GetOperation, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PutOperation, SearchItem, SearchOperation, getTextAtPath, tokenizePath } from "./store/base.js";

@@ -13,2 +13,2 @@ import { AsyncBatchedStore } from "./store/batch.js";

import { InMemoryCache } from "./cache/memory.js";
export { All, AsyncBatchedStore, BaseCache, BaseCheckpointSaver, BaseStore, CacheFullKey, CacheNamespace, ChannelProtocol, ChannelVersions, Checkpoint, CheckpointListOptions, CheckpointMetadata, CheckpointPendingWrite, CheckpointTuple, DeltaChannelHistory, DeltaSnapshot, ERROR, EXCLUDED_METADATA_KEYS, GetOperation, INTERRUPT, InMemoryCache, InMemoryStore, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, MemorySaver, MemoryStore, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PendingWrite, PendingWriteValue, PutOperation, RESUME, ReadonlyCheckpoint, SCHEDULED, SearchItem, SearchOperation, SendProtocol, SerializerProtocol, TASKS, WRITES_IDX_MAP, compareChannelVersions, copyCheckpoint, deepCopy, emptyCheckpoint, getCheckpointId, getTextAtPath, isDeltaSnapshot, maxChannelVersion, tokenizePath, uuid5, uuid6 };
export { All, AsyncBatchedStore, BaseCache, BaseCheckpointSaver, BaseStore, CacheFullKey, CacheNamespace, ChannelProtocol, ChannelVersions, Checkpoint, CheckpointListOptions, CheckpointMetadata, CheckpointPendingWrite, CheckpointTuple, ConstructorRecord, DeltaChannelHistory, DeltaSnapshot, ERROR, EXCLUDED_METADATA_KEYS, GetOperation, INTERRUPT, InMemoryCache, InMemoryStore, IndexConfig, InvalidNamespaceError, Item, ListNamespacesOperation, MatchCondition, MemorySaver, MemoryStore, NameSpacePath, NamespaceMatchType, Operation, OperationResults, PendingWrite, PendingWriteValue, PutOperation, RESUME, ReadonlyCheckpoint, SCHEDULED, SearchItem, SearchOperation, SendProtocol, SerializerProtocol, TASKS, WRITES_IDX_MAP, compareChannelVersions, copyCheckpoint, deepCopy, emptyCheckpoint, getCheckpointId, getTextAtPath, isDeltaSnapshot, maxChannelVersion, tokenizePath, uuid5, uuid6 };

@@ -8,3 +8,57 @@ const require_types = require("./types.cjs");

}
function isUndefinedRecord(value) {
return value.lc === 2 && value.type === "undefined";
}
function isDeltaSnapshotRecord(value) {
return value.lc === 2 && value.type === "delta_snapshot" && Object.prototype.hasOwnProperty.call(value, "value");
}
function isConstructorRecord(value) {
return value.lc === 2 && value.type === "constructor";
}
function hasConstructorId(record, name) {
return Array.isArray(record.id) && record.id.length === 1 && record.id[0] === name;
}
function hasNoMethod(record) {
return record.method === void 0 || record.method === null;
}
function hasSingleArrayArg(record) {
return Array.isArray(record.args) && record.args.length === 1 && Array.isArray(record.args[0]);
}
function isByteArray(value) {
return value.every((item) => typeof item === "number" && Number.isInteger(item) && item >= 0 && item <= 255);
}
/**
* Reconstruct only the closed set of lc:2 values written by `_default`.
*
* A constructor record is serialized data, not an instruction to resolve a
* property or invoke a method. Invalid and unsupported records are kept inert
* by the caller so old or attacker-controlled checkpoint data cannot execute.
*/
function reviveConstructorRecord(record) {
if (hasConstructorId(record, "Set") && hasNoMethod(record)) {
if (!hasSingleArrayArg(record)) return void 0;
return new Set(record.args[0]);
}
if (hasConstructorId(record, "Map") && hasNoMethod(record)) {
if (!hasSingleArrayArg(record) || !record.args[0].every((entry) => Array.isArray(entry) && entry.length === 2)) return;
return new Map(record.args[0]);
}
if (hasConstructorId(record, "RegExp") && hasNoMethod(record)) {
if (!Array.isArray(record.args) || record.args.length !== 2 || typeof record.args[0] !== "string" || typeof record.args[1] !== "string") return;
try {
return new RegExp(record.args[0], record.args[1]);
} catch {
return;
}
}
if (hasConstructorId(record, "Error") && hasNoMethod(record)) {
if (!Array.isArray(record.args) || record.args.length !== 1 || typeof record.args[0] !== "string") return;
return new Error(record.args[0]);
}
if (hasConstructorId(record, "Uint8Array") && (hasNoMethod(record) || record.method === "from")) {
if (!hasSingleArrayArg(record) || !isByteArray(record.args[0])) return;
return new Uint8Array(record.args[0]);
}
}
/**
* The replacer in stringify does not allow delegation to built-in LangChain

@@ -22,30 +76,5 @@ * serialization methods, and instead immediately calls `.toJSON()` and

for (const [k, v] of Object.entries(value)) revivedObj[k] = await _reviver(v);
if (revivedObj.lc === 2 && revivedObj.type === "undefined") return;
else if (revivedObj.lc === 2 && revivedObj.type === "delta_snapshot") return new require_types.DeltaSnapshot(revivedObj.value);
else if (revivedObj.lc === 2 && revivedObj.type === "constructor" && Array.isArray(revivedObj.id)) try {
const constructorName = revivedObj.id[revivedObj.id.length - 1];
let constructor;
switch (constructorName) {
case "Set":
constructor = Set;
break;
case "Map":
constructor = Map;
break;
case "RegExp":
constructor = RegExp;
break;
case "Error":
constructor = Error;
break;
case "Uint8Array":
constructor = Uint8Array;
break;
default: return revivedObj;
}
if (revivedObj.method) return constructor[revivedObj.method](...revivedObj.args || []);
else return new constructor(...revivedObj.args || []);
} catch {
return revivedObj;
}
if (isUndefinedRecord(revivedObj)) return;
else if (isDeltaSnapshotRecord(revivedObj)) return new require_types.DeltaSnapshot(revivedObj.value);
else if (isConstructorRecord(revivedObj)) return reviveConstructorRecord(revivedObj) ?? revivedObj;
else if (isLangChainSerializedObject(revivedObj)) return (0, _langchain_core_load.load)(JSON.stringify(revivedObj));

@@ -78,3 +107,3 @@ return revivedObj;

else if (obj instanceof RegExp) return _encodeConstructorArgs(RegExp, void 0, [obj.source, obj.flags]);
else if (obj instanceof Error) return _encodeConstructorArgs(obj.constructor, void 0, [obj.message]);
else if (obj instanceof Error) return _encodeConstructorArgs(Error, void 0, [obj.message]);
else if (obj?.lg_name === "Send") return {

@@ -81,0 +110,0 @@ node: obj.node,

@@ -1,1 +0,1 @@

{"version":3,"file":"jsonplus.cjs","names":["DeltaSnapshot","stringify"],"sources":["../../src/serde/jsonplus.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-instanceof/no-instanceof */\nimport { load } from \"@langchain/core/load\";\nimport { SerializerProtocol } from \"./base.js\";\nimport { stringify } from \"./utils/fast-safe-stringify/index.js\";\nimport { DeltaSnapshot } from \"./types.js\";\n\nfunction isLangChainSerializedObject(value: Record<string, unknown>) {\n return (\n value !== null &&\n value.lc === 1 &&\n value.type === \"constructor\" &&\n Array.isArray(value.id)\n );\n}\n\n/**\n * The replacer in stringify does not allow delegation to built-in LangChain\n * serialization methods, and instead immediately calls `.toJSON()` and\n * continues to stringify subfields.\n *\n * We therefore must start from the most nested elements in the input and\n * deserialize upwards rather than top-down.\n */\nasync function _reviver(value: any): Promise<any> {\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n const revivedArray = await Promise.all(\n value.map((item) => _reviver(item))\n );\n return revivedArray;\n } else {\n const revivedObj: any = {};\n for (const [k, v] of Object.entries(value)) {\n revivedObj[k] = await _reviver(v);\n }\n\n if (revivedObj.lc === 2 && revivedObj.type === \"undefined\") {\n return undefined;\n } else if (revivedObj.lc === 2 && revivedObj.type === \"delta_snapshot\") {\n // Wrapped value is already revived (bottom-up traversal).\n return new DeltaSnapshot(revivedObj.value);\n } else if (\n revivedObj.lc === 2 &&\n revivedObj.type === \"constructor\" &&\n Array.isArray(revivedObj.id)\n ) {\n try {\n const constructorName = revivedObj.id[revivedObj.id.length - 1];\n let constructor: any;\n\n switch (constructorName) {\n case \"Set\":\n constructor = Set;\n break;\n case \"Map\":\n constructor = Map;\n break;\n case \"RegExp\":\n constructor = RegExp;\n break;\n case \"Error\":\n constructor = Error;\n break;\n case \"Uint8Array\":\n constructor = Uint8Array;\n break;\n default:\n return revivedObj;\n }\n if (revivedObj.method) {\n return (constructor as any)[revivedObj.method](\n ...(revivedObj.args || [])\n );\n } else {\n return new (constructor as any)(...(revivedObj.args || []));\n }\n } catch {\n return revivedObj;\n }\n } else if (isLangChainSerializedObject(revivedObj)) {\n return load(JSON.stringify(revivedObj));\n }\n\n return revivedObj;\n }\n }\n return value;\n}\n\nfunction _encodeConstructorArgs(\n // oxlint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor: Function,\n method?: string,\n args?: any[],\n kwargs?: Record<string, any>\n): object {\n return {\n lc: 2,\n type: \"constructor\",\n id: [constructor.name],\n method: method ?? null,\n args: args ?? [],\n kwargs: kwargs ?? {},\n };\n}\n\nfunction _default(obj: any): any {\n if (obj === undefined) {\n return {\n lc: 2,\n type: \"undefined\",\n };\n } else if (obj instanceof DeltaSnapshot) {\n return {\n lc: 2,\n type: \"delta_snapshot\",\n // `value` continues to be walked by `stringify`, so nested\n // serializable types (messages, Maps, etc.) are encoded normally.\n value: obj.value,\n };\n } else if (obj instanceof Set || obj instanceof Map) {\n return _encodeConstructorArgs(obj.constructor, undefined, [\n Array.from(obj),\n ]);\n } else if (obj instanceof RegExp) {\n return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);\n } else if (obj instanceof Error) {\n return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);\n // TODO: Remove special case\n } else if (obj?.lg_name === \"Send\") {\n return {\n node: obj.node,\n args: obj.args,\n // preserve an optional per-task timeout policy across (de)serialization\n ...(obj.timeout !== undefined ? { timeout: obj.timeout } : {}),\n };\n } else if (obj instanceof Uint8Array) {\n return _encodeConstructorArgs(Uint8Array, \"from\", [Array.from(obj)]);\n } else {\n return obj;\n }\n}\n\nexport class JsonPlusSerializer implements SerializerProtocol {\n protected _dumps(obj: any): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(\n stringify(obj, (_: string, value: any) => {\n return _default(value);\n })\n );\n }\n\n async dumpsTyped(obj: any): Promise<[string, Uint8Array]> {\n if (obj instanceof Uint8Array) {\n return [\"bytes\", obj];\n } else {\n return [\"json\", this._dumps(obj)];\n }\n }\n\n protected async _loads(data: string): Promise<any> {\n const parsed = JSON.parse(data);\n return _reviver(parsed);\n }\n\n async loadsTyped(type: string, data: Uint8Array | string): Promise<any> {\n if (type === \"bytes\") {\n return typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n } else if (type === \"json\") {\n return this._loads(\n typeof data === \"string\" ? data : new TextDecoder().decode(data)\n );\n } else {\n throw new Error(`Unknown serialization type: ${type}`);\n }\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"jsonplus.cjs","names":["DeltaSnapshot","stringify"],"sources":["../../src/serde/jsonplus.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-instanceof/no-instanceof */\nimport { load } from \"@langchain/core/load\";\nimport { SerializerProtocol } from \"./base.js\";\nimport { stringify } from \"./utils/fast-safe-stringify/index.js\";\nimport { type ConstructorRecord, DeltaSnapshot } from \"./types.js\";\n\nfunction isLangChainSerializedObject(value: Record<string, unknown>) {\n return (\n value !== null &&\n value.lc === 1 &&\n value.type === \"constructor\" &&\n Array.isArray(value.id)\n );\n}\n\nfunction isUndefinedRecord(value: Record<string, unknown>): boolean {\n return value.lc === 2 && value.type === \"undefined\";\n}\n\nfunction isDeltaSnapshotRecord(value: Record<string, unknown>): boolean {\n return (\n value.lc === 2 &&\n value.type === \"delta_snapshot\" &&\n Object.prototype.hasOwnProperty.call(value, \"value\")\n );\n}\n\nfunction isConstructorRecord(\n value: Record<string, unknown>\n): value is ConstructorRecord {\n return value.lc === 2 && value.type === \"constructor\";\n}\n\nfunction hasConstructorId(record: ConstructorRecord, name: string): boolean {\n return (\n Array.isArray(record.id) && record.id.length === 1 && record.id[0] === name\n );\n}\n\nfunction hasNoMethod(record: ConstructorRecord): boolean {\n return record.method === undefined || record.method === null;\n}\n\nfunction hasSingleArrayArg(\n record: ConstructorRecord\n): record is ConstructorRecord & { args: unknown[][] } {\n return (\n Array.isArray(record.args) &&\n record.args.length === 1 &&\n Array.isArray(record.args[0])\n );\n}\n\nfunction isByteArray(value: unknown[]): value is number[] {\n return value.every(\n (item) =>\n typeof item === \"number\" &&\n Number.isInteger(item) &&\n item >= 0 &&\n item <= 255\n );\n}\n\n/**\n * Reconstruct only the closed set of lc:2 values written by `_default`.\n *\n * A constructor record is serialized data, not an instruction to resolve a\n * property or invoke a method. Invalid and unsupported records are kept inert\n * by the caller so old or attacker-controlled checkpoint data cannot execute.\n */\nfunction reviveConstructorRecord(\n record: ConstructorRecord\n): unknown | undefined {\n if (hasConstructorId(record, \"Set\") && hasNoMethod(record)) {\n if (!hasSingleArrayArg(record)) return undefined;\n return new Set(record.args[0]);\n }\n\n if (hasConstructorId(record, \"Map\") && hasNoMethod(record)) {\n if (\n !hasSingleArrayArg(record) ||\n !record.args[0].every(\n (entry) => Array.isArray(entry) && entry.length === 2\n )\n ) {\n return undefined;\n }\n return new Map(record.args[0] as [unknown, unknown][]);\n }\n\n if (hasConstructorId(record, \"RegExp\") && hasNoMethod(record)) {\n if (\n !Array.isArray(record.args) ||\n record.args.length !== 2 ||\n typeof record.args[0] !== \"string\" ||\n typeof record.args[1] !== \"string\"\n ) {\n return undefined;\n }\n try {\n return new RegExp(record.args[0], record.args[1]);\n } catch {\n // Invalid patterns are malformed persisted data and stay inert.\n return undefined;\n }\n }\n\n if (hasConstructorId(record, \"Error\") && hasNoMethod(record)) {\n if (\n !Array.isArray(record.args) ||\n record.args.length !== 1 ||\n typeof record.args[0] !== \"string\"\n ) {\n return undefined;\n }\n return new Error(record.args[0]);\n }\n\n if (\n hasConstructorId(record, \"Uint8Array\") &&\n (hasNoMethod(record) || record.method === \"from\")\n ) {\n if (!hasSingleArrayArg(record) || !isByteArray(record.args[0])) {\n return undefined;\n }\n // `from` is a legacy format tag. Do not forward its serialized method or\n // any extra arguments: the validated bytes are the entire persisted form.\n return new Uint8Array(record.args[0]);\n }\n\n return undefined;\n}\n\n/**\n * The replacer in stringify does not allow delegation to built-in LangChain\n * serialization methods, and instead immediately calls `.toJSON()` and\n * continues to stringify subfields.\n *\n * We therefore must start from the most nested elements in the input and\n * deserialize upwards rather than top-down.\n */\nasync function _reviver(value: any): Promise<any> {\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n const revivedArray = await Promise.all(\n value.map((item) => _reviver(item))\n );\n return revivedArray;\n } else {\n const revivedObj: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n revivedObj[k] = await _reviver(v);\n }\n\n if (isUndefinedRecord(revivedObj)) {\n return undefined;\n } else if (isDeltaSnapshotRecord(revivedObj)) {\n // Wrapped value is already revived (bottom-up traversal).\n return new DeltaSnapshot(revivedObj.value);\n } else if (isConstructorRecord(revivedObj)) {\n return reviveConstructorRecord(revivedObj) ?? revivedObj;\n } else if (isLangChainSerializedObject(revivedObj)) {\n return load(JSON.stringify(revivedObj));\n }\n\n return revivedObj;\n }\n }\n return value;\n}\n\nfunction _encodeConstructorArgs(\n // oxlint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor: Function,\n method?: string,\n args?: any[],\n kwargs?: Record<string, any>\n): object {\n return {\n lc: 2,\n type: \"constructor\",\n id: [constructor.name],\n method: method ?? null,\n args: args ?? [],\n kwargs: kwargs ?? {},\n };\n}\n\nfunction _default(obj: any): any {\n if (obj === undefined) {\n return {\n lc: 2,\n type: \"undefined\",\n };\n } else if (obj instanceof DeltaSnapshot) {\n return {\n lc: 2,\n type: \"delta_snapshot\",\n // `value` continues to be walked by `stringify`, so nested\n // serializable types (messages, Maps, etc.) are encoded normally.\n value: obj.value,\n };\n } else if (obj instanceof Set || obj instanceof Map) {\n return _encodeConstructorArgs(obj.constructor, undefined, [\n Array.from(obj),\n ]);\n } else if (obj instanceof RegExp) {\n return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);\n } else if (obj instanceof Error) {\n return _encodeConstructorArgs(Error, undefined, [obj.message]);\n // TODO: Remove special case\n } else if (obj?.lg_name === \"Send\") {\n return {\n node: obj.node,\n args: obj.args,\n // preserve an optional per-task timeout policy across (de)serialization\n ...(obj.timeout !== undefined ? { timeout: obj.timeout } : {}),\n };\n } else if (obj instanceof Uint8Array) {\n return _encodeConstructorArgs(Uint8Array, \"from\", [Array.from(obj)]);\n } else {\n return obj;\n }\n}\n\nexport class JsonPlusSerializer implements SerializerProtocol {\n protected _dumps(obj: any): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(\n stringify(obj, (_: string, value: any) => {\n return _default(value);\n })\n );\n }\n\n async dumpsTyped(obj: any): Promise<[string, Uint8Array]> {\n if (obj instanceof Uint8Array) {\n return [\"bytes\", obj];\n } else {\n return [\"json\", this._dumps(obj)];\n }\n }\n\n protected async _loads(data: string): Promise<any> {\n const parsed = JSON.parse(data);\n return _reviver(parsed);\n }\n\n async loadsTyped(type: string, data: Uint8Array | string): Promise<any> {\n if (type === \"bytes\") {\n return typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n } else if (type === \"json\") {\n return this._loads(\n typeof data === \"string\" ? data : new TextDecoder().decode(data)\n );\n } else {\n throw new Error(`Unknown serialization type: ${type}`);\n }\n }\n}\n"],"mappings":"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"}

@@ -8,3 +8,57 @@ import { DeltaSnapshot } from "./types.js";

}
function isUndefinedRecord(value) {
return value.lc === 2 && value.type === "undefined";
}
function isDeltaSnapshotRecord(value) {
return value.lc === 2 && value.type === "delta_snapshot" && Object.prototype.hasOwnProperty.call(value, "value");
}
function isConstructorRecord(value) {
return value.lc === 2 && value.type === "constructor";
}
function hasConstructorId(record, name) {
return Array.isArray(record.id) && record.id.length === 1 && record.id[0] === name;
}
function hasNoMethod(record) {
return record.method === void 0 || record.method === null;
}
function hasSingleArrayArg(record) {
return Array.isArray(record.args) && record.args.length === 1 && Array.isArray(record.args[0]);
}
function isByteArray(value) {
return value.every((item) => typeof item === "number" && Number.isInteger(item) && item >= 0 && item <= 255);
}
/**
* Reconstruct only the closed set of lc:2 values written by `_default`.
*
* A constructor record is serialized data, not an instruction to resolve a
* property or invoke a method. Invalid and unsupported records are kept inert
* by the caller so old or attacker-controlled checkpoint data cannot execute.
*/
function reviveConstructorRecord(record) {
if (hasConstructorId(record, "Set") && hasNoMethod(record)) {
if (!hasSingleArrayArg(record)) return void 0;
return new Set(record.args[0]);
}
if (hasConstructorId(record, "Map") && hasNoMethod(record)) {
if (!hasSingleArrayArg(record) || !record.args[0].every((entry) => Array.isArray(entry) && entry.length === 2)) return;
return new Map(record.args[0]);
}
if (hasConstructorId(record, "RegExp") && hasNoMethod(record)) {
if (!Array.isArray(record.args) || record.args.length !== 2 || typeof record.args[0] !== "string" || typeof record.args[1] !== "string") return;
try {
return new RegExp(record.args[0], record.args[1]);
} catch {
return;
}
}
if (hasConstructorId(record, "Error") && hasNoMethod(record)) {
if (!Array.isArray(record.args) || record.args.length !== 1 || typeof record.args[0] !== "string") return;
return new Error(record.args[0]);
}
if (hasConstructorId(record, "Uint8Array") && (hasNoMethod(record) || record.method === "from")) {
if (!hasSingleArrayArg(record) || !isByteArray(record.args[0])) return;
return new Uint8Array(record.args[0]);
}
}
/**
* The replacer in stringify does not allow delegation to built-in LangChain

@@ -22,30 +76,5 @@ * serialization methods, and instead immediately calls `.toJSON()` and

for (const [k, v] of Object.entries(value)) revivedObj[k] = await _reviver(v);
if (revivedObj.lc === 2 && revivedObj.type === "undefined") return;
else if (revivedObj.lc === 2 && revivedObj.type === "delta_snapshot") return new DeltaSnapshot(revivedObj.value);
else if (revivedObj.lc === 2 && revivedObj.type === "constructor" && Array.isArray(revivedObj.id)) try {
const constructorName = revivedObj.id[revivedObj.id.length - 1];
let constructor;
switch (constructorName) {
case "Set":
constructor = Set;
break;
case "Map":
constructor = Map;
break;
case "RegExp":
constructor = RegExp;
break;
case "Error":
constructor = Error;
break;
case "Uint8Array":
constructor = Uint8Array;
break;
default: return revivedObj;
}
if (revivedObj.method) return constructor[revivedObj.method](...revivedObj.args || []);
else return new constructor(...revivedObj.args || []);
} catch {
return revivedObj;
}
if (isUndefinedRecord(revivedObj)) return;
else if (isDeltaSnapshotRecord(revivedObj)) return new DeltaSnapshot(revivedObj.value);
else if (isConstructorRecord(revivedObj)) return reviveConstructorRecord(revivedObj) ?? revivedObj;
else if (isLangChainSerializedObject(revivedObj)) return load(JSON.stringify(revivedObj));

@@ -78,3 +107,3 @@ return revivedObj;

else if (obj instanceof RegExp) return _encodeConstructorArgs(RegExp, void 0, [obj.source, obj.flags]);
else if (obj instanceof Error) return _encodeConstructorArgs(obj.constructor, void 0, [obj.message]);
else if (obj instanceof Error) return _encodeConstructorArgs(Error, void 0, [obj.message]);
else if (obj?.lg_name === "Send") return {

@@ -81,0 +110,0 @@ node: obj.node,

@@ -1,1 +0,1 @@

{"version":3,"file":"jsonplus.js","names":[],"sources":["../../src/serde/jsonplus.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-instanceof/no-instanceof */\nimport { load } from \"@langchain/core/load\";\nimport { SerializerProtocol } from \"./base.js\";\nimport { stringify } from \"./utils/fast-safe-stringify/index.js\";\nimport { DeltaSnapshot } from \"./types.js\";\n\nfunction isLangChainSerializedObject(value: Record<string, unknown>) {\n return (\n value !== null &&\n value.lc === 1 &&\n value.type === \"constructor\" &&\n Array.isArray(value.id)\n );\n}\n\n/**\n * The replacer in stringify does not allow delegation to built-in LangChain\n * serialization methods, and instead immediately calls `.toJSON()` and\n * continues to stringify subfields.\n *\n * We therefore must start from the most nested elements in the input and\n * deserialize upwards rather than top-down.\n */\nasync function _reviver(value: any): Promise<any> {\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n const revivedArray = await Promise.all(\n value.map((item) => _reviver(item))\n );\n return revivedArray;\n } else {\n const revivedObj: any = {};\n for (const [k, v] of Object.entries(value)) {\n revivedObj[k] = await _reviver(v);\n }\n\n if (revivedObj.lc === 2 && revivedObj.type === \"undefined\") {\n return undefined;\n } else if (revivedObj.lc === 2 && revivedObj.type === \"delta_snapshot\") {\n // Wrapped value is already revived (bottom-up traversal).\n return new DeltaSnapshot(revivedObj.value);\n } else if (\n revivedObj.lc === 2 &&\n revivedObj.type === \"constructor\" &&\n Array.isArray(revivedObj.id)\n ) {\n try {\n const constructorName = revivedObj.id[revivedObj.id.length - 1];\n let constructor: any;\n\n switch (constructorName) {\n case \"Set\":\n constructor = Set;\n break;\n case \"Map\":\n constructor = Map;\n break;\n case \"RegExp\":\n constructor = RegExp;\n break;\n case \"Error\":\n constructor = Error;\n break;\n case \"Uint8Array\":\n constructor = Uint8Array;\n break;\n default:\n return revivedObj;\n }\n if (revivedObj.method) {\n return (constructor as any)[revivedObj.method](\n ...(revivedObj.args || [])\n );\n } else {\n return new (constructor as any)(...(revivedObj.args || []));\n }\n } catch {\n return revivedObj;\n }\n } else if (isLangChainSerializedObject(revivedObj)) {\n return load(JSON.stringify(revivedObj));\n }\n\n return revivedObj;\n }\n }\n return value;\n}\n\nfunction _encodeConstructorArgs(\n // oxlint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor: Function,\n method?: string,\n args?: any[],\n kwargs?: Record<string, any>\n): object {\n return {\n lc: 2,\n type: \"constructor\",\n id: [constructor.name],\n method: method ?? null,\n args: args ?? [],\n kwargs: kwargs ?? {},\n };\n}\n\nfunction _default(obj: any): any {\n if (obj === undefined) {\n return {\n lc: 2,\n type: \"undefined\",\n };\n } else if (obj instanceof DeltaSnapshot) {\n return {\n lc: 2,\n type: \"delta_snapshot\",\n // `value` continues to be walked by `stringify`, so nested\n // serializable types (messages, Maps, etc.) are encoded normally.\n value: obj.value,\n };\n } else if (obj instanceof Set || obj instanceof Map) {\n return _encodeConstructorArgs(obj.constructor, undefined, [\n Array.from(obj),\n ]);\n } else if (obj instanceof RegExp) {\n return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);\n } else if (obj instanceof Error) {\n return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);\n // TODO: Remove special case\n } else if (obj?.lg_name === \"Send\") {\n return {\n node: obj.node,\n args: obj.args,\n // preserve an optional per-task timeout policy across (de)serialization\n ...(obj.timeout !== undefined ? { timeout: obj.timeout } : {}),\n };\n } else if (obj instanceof Uint8Array) {\n return _encodeConstructorArgs(Uint8Array, \"from\", [Array.from(obj)]);\n } else {\n return obj;\n }\n}\n\nexport class JsonPlusSerializer implements SerializerProtocol {\n protected _dumps(obj: any): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(\n stringify(obj, (_: string, value: any) => {\n return _default(value);\n })\n );\n }\n\n async dumpsTyped(obj: any): Promise<[string, Uint8Array]> {\n if (obj instanceof Uint8Array) {\n return [\"bytes\", obj];\n } else {\n return [\"json\", this._dumps(obj)];\n }\n }\n\n protected async _loads(data: string): Promise<any> {\n const parsed = JSON.parse(data);\n return _reviver(parsed);\n }\n\n async loadsTyped(type: string, data: Uint8Array | string): Promise<any> {\n if (type === \"bytes\") {\n return typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n } else if (type === \"json\") {\n return this._loads(\n typeof data === \"string\" ? data : new TextDecoder().decode(data)\n );\n } else {\n throw new Error(`Unknown serialization type: ${type}`);\n }\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"jsonplus.js","names":[],"sources":["../../src/serde/jsonplus.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-instanceof/no-instanceof */\nimport { load } from \"@langchain/core/load\";\nimport { SerializerProtocol } from \"./base.js\";\nimport { stringify } from \"./utils/fast-safe-stringify/index.js\";\nimport { type ConstructorRecord, DeltaSnapshot } from \"./types.js\";\n\nfunction isLangChainSerializedObject(value: Record<string, unknown>) {\n return (\n value !== null &&\n value.lc === 1 &&\n value.type === \"constructor\" &&\n Array.isArray(value.id)\n );\n}\n\nfunction isUndefinedRecord(value: Record<string, unknown>): boolean {\n return value.lc === 2 && value.type === \"undefined\";\n}\n\nfunction isDeltaSnapshotRecord(value: Record<string, unknown>): boolean {\n return (\n value.lc === 2 &&\n value.type === \"delta_snapshot\" &&\n Object.prototype.hasOwnProperty.call(value, \"value\")\n );\n}\n\nfunction isConstructorRecord(\n value: Record<string, unknown>\n): value is ConstructorRecord {\n return value.lc === 2 && value.type === \"constructor\";\n}\n\nfunction hasConstructorId(record: ConstructorRecord, name: string): boolean {\n return (\n Array.isArray(record.id) && record.id.length === 1 && record.id[0] === name\n );\n}\n\nfunction hasNoMethod(record: ConstructorRecord): boolean {\n return record.method === undefined || record.method === null;\n}\n\nfunction hasSingleArrayArg(\n record: ConstructorRecord\n): record is ConstructorRecord & { args: unknown[][] } {\n return (\n Array.isArray(record.args) &&\n record.args.length === 1 &&\n Array.isArray(record.args[0])\n );\n}\n\nfunction isByteArray(value: unknown[]): value is number[] {\n return value.every(\n (item) =>\n typeof item === \"number\" &&\n Number.isInteger(item) &&\n item >= 0 &&\n item <= 255\n );\n}\n\n/**\n * Reconstruct only the closed set of lc:2 values written by `_default`.\n *\n * A constructor record is serialized data, not an instruction to resolve a\n * property or invoke a method. Invalid and unsupported records are kept inert\n * by the caller so old or attacker-controlled checkpoint data cannot execute.\n */\nfunction reviveConstructorRecord(\n record: ConstructorRecord\n): unknown | undefined {\n if (hasConstructorId(record, \"Set\") && hasNoMethod(record)) {\n if (!hasSingleArrayArg(record)) return undefined;\n return new Set(record.args[0]);\n }\n\n if (hasConstructorId(record, \"Map\") && hasNoMethod(record)) {\n if (\n !hasSingleArrayArg(record) ||\n !record.args[0].every(\n (entry) => Array.isArray(entry) && entry.length === 2\n )\n ) {\n return undefined;\n }\n return new Map(record.args[0] as [unknown, unknown][]);\n }\n\n if (hasConstructorId(record, \"RegExp\") && hasNoMethod(record)) {\n if (\n !Array.isArray(record.args) ||\n record.args.length !== 2 ||\n typeof record.args[0] !== \"string\" ||\n typeof record.args[1] !== \"string\"\n ) {\n return undefined;\n }\n try {\n return new RegExp(record.args[0], record.args[1]);\n } catch {\n // Invalid patterns are malformed persisted data and stay inert.\n return undefined;\n }\n }\n\n if (hasConstructorId(record, \"Error\") && hasNoMethod(record)) {\n if (\n !Array.isArray(record.args) ||\n record.args.length !== 1 ||\n typeof record.args[0] !== \"string\"\n ) {\n return undefined;\n }\n return new Error(record.args[0]);\n }\n\n if (\n hasConstructorId(record, \"Uint8Array\") &&\n (hasNoMethod(record) || record.method === \"from\")\n ) {\n if (!hasSingleArrayArg(record) || !isByteArray(record.args[0])) {\n return undefined;\n }\n // `from` is a legacy format tag. Do not forward its serialized method or\n // any extra arguments: the validated bytes are the entire persisted form.\n return new Uint8Array(record.args[0]);\n }\n\n return undefined;\n}\n\n/**\n * The replacer in stringify does not allow delegation to built-in LangChain\n * serialization methods, and instead immediately calls `.toJSON()` and\n * continues to stringify subfields.\n *\n * We therefore must start from the most nested elements in the input and\n * deserialize upwards rather than top-down.\n */\nasync function _reviver(value: any): Promise<any> {\n if (value && typeof value === \"object\") {\n if (Array.isArray(value)) {\n const revivedArray = await Promise.all(\n value.map((item) => _reviver(item))\n );\n return revivedArray;\n } else {\n const revivedObj: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n revivedObj[k] = await _reviver(v);\n }\n\n if (isUndefinedRecord(revivedObj)) {\n return undefined;\n } else if (isDeltaSnapshotRecord(revivedObj)) {\n // Wrapped value is already revived (bottom-up traversal).\n return new DeltaSnapshot(revivedObj.value);\n } else if (isConstructorRecord(revivedObj)) {\n return reviveConstructorRecord(revivedObj) ?? revivedObj;\n } else if (isLangChainSerializedObject(revivedObj)) {\n return load(JSON.stringify(revivedObj));\n }\n\n return revivedObj;\n }\n }\n return value;\n}\n\nfunction _encodeConstructorArgs(\n // oxlint-disable-next-line @typescript-eslint/no-unsafe-function-type\n constructor: Function,\n method?: string,\n args?: any[],\n kwargs?: Record<string, any>\n): object {\n return {\n lc: 2,\n type: \"constructor\",\n id: [constructor.name],\n method: method ?? null,\n args: args ?? [],\n kwargs: kwargs ?? {},\n };\n}\n\nfunction _default(obj: any): any {\n if (obj === undefined) {\n return {\n lc: 2,\n type: \"undefined\",\n };\n } else if (obj instanceof DeltaSnapshot) {\n return {\n lc: 2,\n type: \"delta_snapshot\",\n // `value` continues to be walked by `stringify`, so nested\n // serializable types (messages, Maps, etc.) are encoded normally.\n value: obj.value,\n };\n } else if (obj instanceof Set || obj instanceof Map) {\n return _encodeConstructorArgs(obj.constructor, undefined, [\n Array.from(obj),\n ]);\n } else if (obj instanceof RegExp) {\n return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);\n } else if (obj instanceof Error) {\n return _encodeConstructorArgs(Error, undefined, [obj.message]);\n // TODO: Remove special case\n } else if (obj?.lg_name === \"Send\") {\n return {\n node: obj.node,\n args: obj.args,\n // preserve an optional per-task timeout policy across (de)serialization\n ...(obj.timeout !== undefined ? { timeout: obj.timeout } : {}),\n };\n } else if (obj instanceof Uint8Array) {\n return _encodeConstructorArgs(Uint8Array, \"from\", [Array.from(obj)]);\n } else {\n return obj;\n }\n}\n\nexport class JsonPlusSerializer implements SerializerProtocol {\n protected _dumps(obj: any): Uint8Array {\n const encoder = new TextEncoder();\n return encoder.encode(\n stringify(obj, (_: string, value: any) => {\n return _default(value);\n })\n );\n }\n\n async dumpsTyped(obj: any): Promise<[string, Uint8Array]> {\n if (obj instanceof Uint8Array) {\n return [\"bytes\", obj];\n } else {\n return [\"json\", this._dumps(obj)];\n }\n }\n\n protected async _loads(data: string): Promise<any> {\n const parsed = JSON.parse(data);\n return _reviver(parsed);\n }\n\n async loadsTyped(type: string, data: Uint8Array | string): Promise<any> {\n if (type === \"bytes\") {\n return typeof data === \"string\" ? new TextEncoder().encode(data) : data;\n } else if (type === \"json\") {\n return this._loads(\n typeof data === \"string\" ? data : new TextDecoder().decode(data)\n );\n } else {\n throw new Error(`Unknown serialization type: ${type}`);\n }\n }\n}\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"types.cjs","names":[],"sources":["../../src/serde/types.ts"],"sourcesContent":["export const TASKS = \"__pregel_tasks\";\nexport const ERROR = \"__error__\";\nexport const SCHEDULED = \"__scheduled__\";\nexport const INTERRUPT = \"__interrupt__\";\nexport const RESUME = \"__resume__\";\n\n/**\n * Snapshot blob for a `DeltaChannel` with finite snapshot frequency.\n *\n * Stored directly in a checkpoint's `channel_values` in place of the full\n * accumulated value. The ancestor walk in\n * {@link BaseCheckpointSaver.getDeltaChannelHistory} terminates when it\n * encounters a populated `channel_values` entry for a channel; a\n * `DeltaSnapshot` value is the materialized state at that ancestor, so the\n * channel reconstructs directly from `.value` without replaying earlier\n * writes.\n *\n * @remarks Beta. The on-disk representation may change in future releases.\n */\nexport class DeltaSnapshot<Value = unknown> {\n /** Marker used for structural detection across module/realm boundaries. */\n lg_name = \"DeltaSnapshot\" as const;\n\n value: Value;\n\n constructor(value: Value) {\n this.value = value;\n }\n}\n\n/**\n * Structural type guard for {@link DeltaSnapshot}. Uses the `lg_name` marker\n * so it survives serialization round-trips and cross-package duplication.\n */\nexport function isDeltaSnapshot<Value = unknown>(\n value: unknown\n): value is DeltaSnapshot<Value> {\n return (\n value != null &&\n typeof value === \"object\" &&\n (value as { lg_name?: string }).lg_name === \"DeltaSnapshot\"\n );\n}\n\n// Mirrors BaseChannel in \"@langchain/langgraph\"\nexport interface ChannelProtocol<\n ValueType = unknown,\n UpdateType = unknown,\n CheckpointType = unknown,\n> {\n ValueType: ValueType;\n\n UpdateType: UpdateType;\n\n /**\n * The name of the channel.\n */\n lc_graph_name: string;\n\n /**\n * Return a new identical channel, optionally initialized from a checkpoint.\n * Can be thought of as a \"restoration\" from a checkpoint which is a \"snapshot\" of the channel's state.\n *\n * @param {CheckpointType | undefined} checkpoint\n * @returns {this}\n */\n fromCheckpoint(checkpoint?: CheckpointType): this;\n\n /**\n * Update the channel's value with the given sequence of updates.\n * The order of the updates in the sequence is arbitrary.\n *\n * @throws {InvalidUpdateError} if the sequence of updates is invalid.\n * @param {Array<UpdateType>} values\n * @returns {void}\n */\n update(values: UpdateType[]): void;\n\n /**\n * Return the current value of the channel.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet).\n * @returns {ValueType}\n */\n get(): ValueType;\n\n /**\n * Return a string representation of the channel's current state.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet), or doesn't support checkpoints.\n * @returns {CheckpointType | undefined}\n */\n checkpoint(): CheckpointType | undefined;\n}\n\n// Mirrors SendInterface in \"@langchain/langgraph\"\nexport interface SendProtocol {\n node: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args: any;\n // Optional per-task timeout policy. Structural to avoid a dependency on the\n // langgraph package; mirrors `TimeoutPolicy` in \"@langchain/langgraph\".\n timeout?: {\n runTimeout?: number;\n idleTimeout?: number;\n refreshOn?: \"auto\" | \"heartbeat\";\n };\n}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS;;;;;;;;;;;;;;AAetB,IAAa,gBAAb,MAA4C;;CAE1C,UAAU;CAEV;CAEA,YAAY,OAAc;AACxB,OAAK,QAAQ;;;;;;;AAQjB,SAAgB,gBACd,OAC+B;AAC/B,QACE,SAAS,QACT,OAAO,UAAU,YAChB,MAA+B,YAAY"}
{"version":3,"file":"types.cjs","names":[],"sources":["../../src/serde/types.ts"],"sourcesContent":["export type ConstructorRecord = {\n lc: 2;\n type: \"constructor\";\n id: unknown;\n method?: unknown;\n args?: unknown;\n};\n\nexport const TASKS = \"__pregel_tasks\";\nexport const ERROR = \"__error__\";\nexport const SCHEDULED = \"__scheduled__\";\nexport const INTERRUPT = \"__interrupt__\";\nexport const RESUME = \"__resume__\";\n\n/**\n * Snapshot blob for a `DeltaChannel` with finite snapshot frequency.\n *\n * Stored directly in a checkpoint's `channel_values` in place of the full\n * accumulated value. The ancestor walk in\n * {@link BaseCheckpointSaver.getDeltaChannelHistory} terminates when it\n * encounters a populated `channel_values` entry for a channel; a\n * `DeltaSnapshot` value is the materialized state at that ancestor, so the\n * channel reconstructs directly from `.value` without replaying earlier\n * writes.\n *\n * @remarks Beta. The on-disk representation may change in future releases.\n */\nexport class DeltaSnapshot<Value = unknown> {\n /** Marker used for structural detection across module/realm boundaries. */\n lg_name = \"DeltaSnapshot\" as const;\n\n value: Value;\n\n constructor(value: Value) {\n this.value = value;\n }\n}\n\n/**\n * Structural type guard for {@link DeltaSnapshot}. Uses the `lg_name` marker\n * so it survives serialization round-trips and cross-package duplication.\n */\nexport function isDeltaSnapshot<Value = unknown>(\n value: unknown\n): value is DeltaSnapshot<Value> {\n return (\n value != null &&\n typeof value === \"object\" &&\n (value as { lg_name?: string }).lg_name === \"DeltaSnapshot\"\n );\n}\n\n// Mirrors BaseChannel in \"@langchain/langgraph\"\nexport interface ChannelProtocol<\n ValueType = unknown,\n UpdateType = unknown,\n CheckpointType = unknown,\n> {\n ValueType: ValueType;\n\n UpdateType: UpdateType;\n\n /**\n * The name of the channel.\n */\n lc_graph_name: string;\n\n /**\n * Return a new identical channel, optionally initialized from a checkpoint.\n * Can be thought of as a \"restoration\" from a checkpoint which is a \"snapshot\" of the channel's state.\n *\n * @param {CheckpointType | undefined} checkpoint\n * @returns {this}\n */\n fromCheckpoint(checkpoint?: CheckpointType): this;\n\n /**\n * Update the channel's value with the given sequence of updates.\n * The order of the updates in the sequence is arbitrary.\n *\n * @throws {InvalidUpdateError} if the sequence of updates is invalid.\n * @param {Array<UpdateType>} values\n * @returns {void}\n */\n update(values: UpdateType[]): void;\n\n /**\n * Return the current value of the channel.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet).\n * @returns {ValueType}\n */\n get(): ValueType;\n\n /**\n * Return a string representation of the channel's current state.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet), or doesn't support checkpoints.\n * @returns {CheckpointType | undefined}\n */\n checkpoint(): CheckpointType | undefined;\n}\n\n// Mirrors SendInterface in \"@langchain/langgraph\"\nexport interface SendProtocol {\n node: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args: any;\n // Optional per-task timeout policy. Structural to avoid a dependency on the\n // langgraph package; mirrors `TimeoutPolicy` in \"@langchain/langgraph\".\n timeout?: {\n runTimeout?: number;\n idleTimeout?: number;\n refreshOn?: \"auto\" | \"heartbeat\";\n };\n}\n"],"mappings":";AAQA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS;;;;;;;;;;;;;;AAetB,IAAa,gBAAb,MAA4C;;CAE1C,UAAU;CAEV;CAEA,YAAY,OAAc;AACxB,OAAK,QAAQ;;;;;;;AAQjB,SAAgB,gBACd,OAC+B;AAC/B,QACE,SAAS,QACT,OAAO,UAAU,YAChB,MAA+B,YAAY"}
//#region src/serde/types.d.ts
type ConstructorRecord = {
lc: 2;
type: "constructor";
id: unknown;
method?: unknown;
args?: unknown;
};
declare const TASKS = "__pregel_tasks";

@@ -80,3 +87,3 @@ declare const ERROR = "__error__";

//#endregion
export { ChannelProtocol, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot };
export { ChannelProtocol, ConstructorRecord, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot };
//# sourceMappingURL=types.d.cts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/serde/types.ts"],"mappings":";cAAa,KAAA;AAAA,cACA,KAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA;AAAA,cACA,MAAA;;AAHb;;;;;AACA;;;;;AACA;;cAgBa,aAAA;EAhBS;EAkBpB,OAAA;EAEA,KAAA,EAAO,KAAA;EAEP,WAAA,CAAY,KAAA,EAAO,KAAA;AAAA;;;AANrB;;iBAegB,eAAA,iBAAA,CACd,KAAA,YACC,KAAA,IAAS,aAAA,CAAc,KAAA;AAAA,UAST,eAAA;EAKf,SAAA,EAAW,SAAA;EAEX,UAAA,EAAY,UAAA;EA7BZ;;;EAkCA,aAAA;EAhCY;;;AASd;;;;EAgCE,cAAA,CAAe,UAAA,GAAa,cAAA;EA/B5B;;;;;;AAUF;;EA+BE,MAAA,CAAO,MAAA,EAAQ,UAAA;EA1BJ;;;;;;EAkCX,GAAA,IAAO,SAAA;EAQqB;;;;;;EAA5B,UAAA,IAAc,cAAA;AAAA;AAAA,UAIC,YAAA;EACf,IAAA;EAEA,IAAA;EAGA,OAAA;IACE,UAAA;IACA,WAAA;IACA,SAAA;EAAA;AAAA"}
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/serde/types.ts"],"mappings":";KAAY,iBAAA;EACV,EAAA;EACA,IAAA;EACA,EAAA;EACA,MAAA;EACA,IAAA;AAAA;AAAA,cAGW,KAAA;AAAA,cACA,KAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA;AAAA,cACA,MAAA;AAJb;;;;;AACA;;;;;AACA;;;AAFA,cAmBa,aAAA;EAjBS;EAmBpB,OAAA;EAEA,KAAA,EAAO,KAAA;EAEP,WAAA,CAAY,KAAA,EAAO,KAAA;AAAA;;AArBrB;;;iBA8BgB,eAAA,iBAAA,CACd,KAAA,YACC,KAAA,IAAS,aAAA,CAAc,KAAA;AAAA,UAST,eAAA;EAKf,SAAA,EAAW,SAAA;EAEX,UAAA,EAAY,UAAA;EAjCY;;;EAsCxB,aAAA;EAlCA;;;;;;;EA2CA,cAAA,CAAe,UAAA,GAAa,cAAA;EAhCC;;;;;;;;EA0C7B,MAAA,CAAO,MAAA,EAAQ,UAAA;EAxCc;AAS/B;;;;;EAuCE,GAAA,IAAO,SAAA;EARQ;;;;;;EAgBf,UAAA,IAAc,cAAA;AAAA;AAAA,UAIC,YAAA;EACf,IAAA;EAEA,IAAA;EAGA,OAAA;IACE,UAAA;IACA,WAAA;IACA,SAAA;EAAA;AAAA"}
//#region src/serde/types.d.ts
type ConstructorRecord = {
lc: 2;
type: "constructor";
id: unknown;
method?: unknown;
args?: unknown;
};
declare const TASKS = "__pregel_tasks";

@@ -80,3 +87,3 @@ declare const ERROR = "__error__";

//#endregion
export { ChannelProtocol, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot };
export { ChannelProtocol, ConstructorRecord, DeltaSnapshot, ERROR, INTERRUPT, RESUME, SCHEDULED, SendProtocol, TASKS, isDeltaSnapshot };
//# sourceMappingURL=types.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/serde/types.ts"],"mappings":";cAAa,KAAA;AAAA,cACA,KAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA;AAAA,cACA,MAAA;;AAHb;;;;;AACA;;;;;AACA;;cAgBa,aAAA;EAhBS;EAkBpB,OAAA;EAEA,KAAA,EAAO,KAAA;EAEP,WAAA,CAAY,KAAA,EAAO,KAAA;AAAA;;;AANrB;;iBAegB,eAAA,iBAAA,CACd,KAAA,YACC,KAAA,IAAS,aAAA,CAAc,KAAA;AAAA,UAST,eAAA;EAKf,SAAA,EAAW,SAAA;EAEX,UAAA,EAAY,UAAA;EA7BZ;;;EAkCA,aAAA;EAhCY;;;AASd;;;;EAgCE,cAAA,CAAe,UAAA,GAAa,cAAA;EA/B5B;;;;;;AAUF;;EA+BE,MAAA,CAAO,MAAA,EAAQ,UAAA;EA1BJ;;;;;;EAkCX,GAAA,IAAO,SAAA;EAQqB;;;;;;EAA5B,UAAA,IAAc,cAAA;AAAA;AAAA,UAIC,YAAA;EACf,IAAA;EAEA,IAAA;EAGA,OAAA;IACE,UAAA;IACA,WAAA;IACA,SAAA;EAAA;AAAA"}
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/serde/types.ts"],"mappings":";KAAY,iBAAA;EACV,EAAA;EACA,IAAA;EACA,EAAA;EACA,MAAA;EACA,IAAA;AAAA;AAAA,cAGW,KAAA;AAAA,cACA,KAAA;AAAA,cACA,SAAA;AAAA,cACA,SAAA;AAAA,cACA,MAAA;AAJb;;;;;AACA;;;;;AACA;;;AAFA,cAmBa,aAAA;EAjBS;EAmBpB,OAAA;EAEA,KAAA,EAAO,KAAA;EAEP,WAAA,CAAY,KAAA,EAAO,KAAA;AAAA;;AArBrB;;;iBA8BgB,eAAA,iBAAA,CACd,KAAA,YACC,KAAA,IAAS,aAAA,CAAc,KAAA;AAAA,UAST,eAAA;EAKf,SAAA,EAAW,SAAA;EAEX,UAAA,EAAY,UAAA;EAjCY;;;EAsCxB,aAAA;EAlCA;;;;;;;EA2CA,cAAA,CAAe,UAAA,GAAa,cAAA;EAhCC;;;;;;;;EA0C7B,MAAA,CAAO,MAAA,EAAQ,UAAA;EAxCc;AAS/B;;;;;EAuCE,GAAA,IAAO,SAAA;EARQ;;;;;;EAgBf,UAAA,IAAc,cAAA;AAAA;AAAA,UAIC,YAAA;EACf,IAAA;EAEA,IAAA;EAGA,OAAA;IACE,UAAA;IACA,WAAA;IACA,SAAA;EAAA;AAAA"}

@@ -1,1 +0,1 @@

{"version":3,"file":"types.js","names":[],"sources":["../../src/serde/types.ts"],"sourcesContent":["export const TASKS = \"__pregel_tasks\";\nexport const ERROR = \"__error__\";\nexport const SCHEDULED = \"__scheduled__\";\nexport const INTERRUPT = \"__interrupt__\";\nexport const RESUME = \"__resume__\";\n\n/**\n * Snapshot blob for a `DeltaChannel` with finite snapshot frequency.\n *\n * Stored directly in a checkpoint's `channel_values` in place of the full\n * accumulated value. The ancestor walk in\n * {@link BaseCheckpointSaver.getDeltaChannelHistory} terminates when it\n * encounters a populated `channel_values` entry for a channel; a\n * `DeltaSnapshot` value is the materialized state at that ancestor, so the\n * channel reconstructs directly from `.value` without replaying earlier\n * writes.\n *\n * @remarks Beta. The on-disk representation may change in future releases.\n */\nexport class DeltaSnapshot<Value = unknown> {\n /** Marker used for structural detection across module/realm boundaries. */\n lg_name = \"DeltaSnapshot\" as const;\n\n value: Value;\n\n constructor(value: Value) {\n this.value = value;\n }\n}\n\n/**\n * Structural type guard for {@link DeltaSnapshot}. Uses the `lg_name` marker\n * so it survives serialization round-trips and cross-package duplication.\n */\nexport function isDeltaSnapshot<Value = unknown>(\n value: unknown\n): value is DeltaSnapshot<Value> {\n return (\n value != null &&\n typeof value === \"object\" &&\n (value as { lg_name?: string }).lg_name === \"DeltaSnapshot\"\n );\n}\n\n// Mirrors BaseChannel in \"@langchain/langgraph\"\nexport interface ChannelProtocol<\n ValueType = unknown,\n UpdateType = unknown,\n CheckpointType = unknown,\n> {\n ValueType: ValueType;\n\n UpdateType: UpdateType;\n\n /**\n * The name of the channel.\n */\n lc_graph_name: string;\n\n /**\n * Return a new identical channel, optionally initialized from a checkpoint.\n * Can be thought of as a \"restoration\" from a checkpoint which is a \"snapshot\" of the channel's state.\n *\n * @param {CheckpointType | undefined} checkpoint\n * @returns {this}\n */\n fromCheckpoint(checkpoint?: CheckpointType): this;\n\n /**\n * Update the channel's value with the given sequence of updates.\n * The order of the updates in the sequence is arbitrary.\n *\n * @throws {InvalidUpdateError} if the sequence of updates is invalid.\n * @param {Array<UpdateType>} values\n * @returns {void}\n */\n update(values: UpdateType[]): void;\n\n /**\n * Return the current value of the channel.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet).\n * @returns {ValueType}\n */\n get(): ValueType;\n\n /**\n * Return a string representation of the channel's current state.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet), or doesn't support checkpoints.\n * @returns {CheckpointType | undefined}\n */\n checkpoint(): CheckpointType | undefined;\n}\n\n// Mirrors SendInterface in \"@langchain/langgraph\"\nexport interface SendProtocol {\n node: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args: any;\n // Optional per-task timeout policy. Structural to avoid a dependency on the\n // langgraph package; mirrors `TimeoutPolicy` in \"@langchain/langgraph\".\n timeout?: {\n runTimeout?: number;\n idleTimeout?: number;\n refreshOn?: \"auto\" | \"heartbeat\";\n };\n}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS;;;;;;;;;;;;;;AAetB,IAAa,gBAAb,MAA4C;;CAE1C,UAAU;CAEV;CAEA,YAAY,OAAc;AACxB,OAAK,QAAQ;;;;;;;AAQjB,SAAgB,gBACd,OAC+B;AAC/B,QACE,SAAS,QACT,OAAO,UAAU,YAChB,MAA+B,YAAY"}
{"version":3,"file":"types.js","names":[],"sources":["../../src/serde/types.ts"],"sourcesContent":["export type ConstructorRecord = {\n lc: 2;\n type: \"constructor\";\n id: unknown;\n method?: unknown;\n args?: unknown;\n};\n\nexport const TASKS = \"__pregel_tasks\";\nexport const ERROR = \"__error__\";\nexport const SCHEDULED = \"__scheduled__\";\nexport const INTERRUPT = \"__interrupt__\";\nexport const RESUME = \"__resume__\";\n\n/**\n * Snapshot blob for a `DeltaChannel` with finite snapshot frequency.\n *\n * Stored directly in a checkpoint's `channel_values` in place of the full\n * accumulated value. The ancestor walk in\n * {@link BaseCheckpointSaver.getDeltaChannelHistory} terminates when it\n * encounters a populated `channel_values` entry for a channel; a\n * `DeltaSnapshot` value is the materialized state at that ancestor, so the\n * channel reconstructs directly from `.value` without replaying earlier\n * writes.\n *\n * @remarks Beta. The on-disk representation may change in future releases.\n */\nexport class DeltaSnapshot<Value = unknown> {\n /** Marker used for structural detection across module/realm boundaries. */\n lg_name = \"DeltaSnapshot\" as const;\n\n value: Value;\n\n constructor(value: Value) {\n this.value = value;\n }\n}\n\n/**\n * Structural type guard for {@link DeltaSnapshot}. Uses the `lg_name` marker\n * so it survives serialization round-trips and cross-package duplication.\n */\nexport function isDeltaSnapshot<Value = unknown>(\n value: unknown\n): value is DeltaSnapshot<Value> {\n return (\n value != null &&\n typeof value === \"object\" &&\n (value as { lg_name?: string }).lg_name === \"DeltaSnapshot\"\n );\n}\n\n// Mirrors BaseChannel in \"@langchain/langgraph\"\nexport interface ChannelProtocol<\n ValueType = unknown,\n UpdateType = unknown,\n CheckpointType = unknown,\n> {\n ValueType: ValueType;\n\n UpdateType: UpdateType;\n\n /**\n * The name of the channel.\n */\n lc_graph_name: string;\n\n /**\n * Return a new identical channel, optionally initialized from a checkpoint.\n * Can be thought of as a \"restoration\" from a checkpoint which is a \"snapshot\" of the channel's state.\n *\n * @param {CheckpointType | undefined} checkpoint\n * @returns {this}\n */\n fromCheckpoint(checkpoint?: CheckpointType): this;\n\n /**\n * Update the channel's value with the given sequence of updates.\n * The order of the updates in the sequence is arbitrary.\n *\n * @throws {InvalidUpdateError} if the sequence of updates is invalid.\n * @param {Array<UpdateType>} values\n * @returns {void}\n */\n update(values: UpdateType[]): void;\n\n /**\n * Return the current value of the channel.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet).\n * @returns {ValueType}\n */\n get(): ValueType;\n\n /**\n * Return a string representation of the channel's current state.\n *\n * @throws {EmptyChannelError} if the channel is empty (never updated yet), or doesn't support checkpoints.\n * @returns {CheckpointType | undefined}\n */\n checkpoint(): CheckpointType | undefined;\n}\n\n// Mirrors SendInterface in \"@langchain/langgraph\"\nexport interface SendProtocol {\n node: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args: any;\n // Optional per-task timeout policy. Structural to avoid a dependency on the\n // langgraph package; mirrors `TimeoutPolicy` in \"@langchain/langgraph\".\n timeout?: {\n runTimeout?: number;\n idleTimeout?: number;\n refreshOn?: \"auto\" | \"heartbeat\";\n };\n}\n"],"mappings":";AAQA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS;;;;;;;;;;;;;;AAetB,IAAa,gBAAb,MAA4C;;CAE1C,UAAU;CAEV;CAEA,YAAY,OAAc;AACxB,OAAK,QAAQ;;;;;;;AAQjB,SAAgB,gBACd,OAC+B;AAC/B,QACE,SAAS,QACT,OAAO,UAAU,YAChB,MAA+B,YAAY"}
{
"name": "@langchain/langgraph-checkpoint",
"version": "1.1.3",
"version": "1.1.4",
"description": "Library with base interfaces for LangGraph checkpoint savers.",

@@ -26,6 +26,6 @@ "type": "module",

"dpdm": "^3.12.0",
"rollup": "^4.37.0",
"rollup": "^4.62.3",
"tsx": "^4.19.3",
"typescript": "^4.9.5 || ^5.4.5",
"vitest": "^4.1.0"
"vitest": "^4.1.10"
},

@@ -32,0 +32,0 @@ "publishConfig": {

@@ -33,2 +33,13 @@ # @langchain/langgraph-checkpoint

### When are checkpoints persisted
By default (`durability: "async"`) checkpoint writes are dispatched in the background while the graph keeps executing, which keeps runs fast. Regardless of the `durability` mode, LangGraph **awaits all outstanding checkpointer writes before `invoke()` / `stream()` resolves**, `invoke()` fully drains the underlying stream, and the stream awaits every pending checkpointer promise before it completes.
In practice this means:
- If you `await graph.invoke(...)` (or fully consume `for await (... of graph.stream(...))`), persistence is guaranteed to be complete by the time the call returns. You do **not** need to keep the process/runtime alive for any trailing background writes.
- On serverless/edge runtimes (e.g. Cloudflare Workers) you therefore do not need `ctx.waitUntil()` to flush checkpoints, just make sure you `await` the run before returning a response. The only way to orphan writes is to start a stream and never consume it (e.g. piping `graph.stream()` into a detached, un-awaited task).
> Note: this guarantees the *write was issued and awaited*, not that your database driver works in a given runtime. See the runtime-compatibility notes in the [Postgres](../checkpoint-postgres/README.md#edge--serverless-runtimes-cloudflare-workers-etc) and [Redis](../checkpoint-redis/README.md#edge--serverless-runtimes-cloudflare-workers-etc) checkpointer READMEs.
## Interface

@@ -35,0 +46,0 @@