UNPKG

@langchain/langgraph-checkpoint

Version:

Library with base interfaces for LangGraph checkpoint savers.

150 lines 4.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonPlusSerializer = void 0; /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable no-instanceof/no-instanceof */ const load_1 = require("@langchain/core/load"); const index_js_1 = require("./utils/fast-safe-stringify/index.cjs"); function isLangChainSerializedObject(value) { return (value !== null && value.lc === 1 && value.type === "constructor" && Array.isArray(value.id)); } /** * The replacer in stringify does not allow delegation to built-in LangChain * serialization methods, and instead immediately calls `.toJSON()` and * continues to stringify subfields. * * We therefore must start from the most nested elements in the input and * deserialize upwards rather than top-down. */ async function _reviver(value) { if (value && typeof value === "object") { if (Array.isArray(value)) { const revivedArray = await Promise.all(value.map((item) => _reviver(item))); return revivedArray; } else { const revivedObj = {}; for (const [k, v] of Object.entries(value)) { revivedObj[k] = await _reviver(v); } if (revivedObj.lc === 2 && revivedObj.type === "undefined") { return undefined; } 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; default: return revivedObj; } if (revivedObj.method) { return constructor[revivedObj.method](...(revivedObj.args || [])); } else { return new constructor(...(revivedObj.args || [])); } } catch (error) { return revivedObj; } } else if (isLangChainSerializedObject(revivedObj)) { return (0, load_1.load)(JSON.stringify(revivedObj)); } return revivedObj; } } return value; } function _encodeConstructorArgs( // eslint-disable-next-line @typescript-eslint/ban-types constructor, method, args, kwargs) { return { lc: 2, type: "constructor", id: [constructor.name], method: method ?? null, args: args ?? [], kwargs: kwargs ?? {}, }; } function _default(obj) { if (obj === undefined) { return { lc: 2, type: "undefined", }; } else if (obj instanceof Set || obj instanceof Map) { return _encodeConstructorArgs(obj.constructor, undefined, [ Array.from(obj), ]); } else if (obj instanceof RegExp) { return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]); } else if (obj instanceof Error) { return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]); // TODO: Remove special case } else if (obj?.lg_name === "Send") { return { node: obj.node, args: obj.args, }; } else { return obj; } } class JsonPlusSerializer { _dumps(obj) { const encoder = new TextEncoder(); return encoder.encode((0, index_js_1.stringify)(obj, (_, value) => { return _default(value); })); } dumpsTyped(obj) { if (obj instanceof Uint8Array) { return ["bytes", obj]; } else { return ["json", this._dumps(obj)]; } } async _loads(data) { const parsed = JSON.parse(data); return _reviver(parsed); } async loadsTyped(type, data) { if (type === "bytes") { return typeof data === "string" ? new TextEncoder().encode(data) : data; } else if (type === "json") { return this._loads(typeof data === "string" ? data : new TextDecoder().decode(data)); } else { throw new Error(`Unknown serialization type: ${type}`); } } } exports.JsonPlusSerializer = JsonPlusSerializer; //# sourceMappingURL=jsonplus.js.map