@langchain/langgraph-checkpoint 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/base.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"base.cjs","names":["uuid6","JsonPlusSerializer","ERROR","SCHEDULED","INTERRUPT","RESUME"],"sources":["../src/base.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport { uuid6 } from \"./id.js\";\nimport type {\n PendingWrite,\n CheckpointPendingWrite,\n CheckpointMetadata,\n} from \"./types.js\";\nimport { ERROR, INTERRUPT, RESUME, SCHEDULED } from \"./serde/types.js\";\nimport { JsonPlusSerializer } from \"./serde/jsonplus.js\";\n\n/** @inline */\ntype ChannelVersion = number | string;\n\nexport type ChannelVersions = Record<string, ChannelVersion>;\n\nexport interface Checkpoint<\n N extends string = string,\n C extends string = string\n> {\n /**\n * The version of the checkpoint format. Currently 4\n */\n v: number;\n /**\n * Checkpoint ID {uuid6}\n */\n id: string;\n /**\n * Timestamp {new Date().toISOString()}\n */\n ts: string;\n /**\n * @default {}\n */\n channel_values: Record<C, unknown>;\n /**\n * @default {}\n */\n channel_versions: Record<C, ChannelVersion>;\n /**\n * @default {}\n */\n versions_seen: Record<N, Record<C, ChannelVersion>>;\n}\n\nexport interface ReadonlyCheckpoint extends Readonly<Checkpoint> {\n readonly channel_values: Readonly<Record<string, unknown>>;\n readonly channel_versions: Readonly<Record<string, ChannelVersion>>;\n readonly versions_seen: Readonly<\n Record<string, Readonly<Record<string, ChannelVersion>>>\n >;\n}\n\nexport function deepCopy<T>(obj: T): T {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n const newObj = Array.isArray(obj) ? [] : {};\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (newObj as Record<PropertyKey, unknown>)[key] = deepCopy(\n (obj as Record<string, unknown>)[key]\n );\n }\n }\n\n return newObj as T;\n}\n\n/** @hidden */\nexport function emptyCheckpoint(): Checkpoint {\n return {\n v: 4,\n id: uuid6(-2),\n ts: new Date().toISOString(),\n channel_values: {},\n channel_versions: {},\n versions_seen: {},\n };\n}\n\n/** @hidden */\nexport function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint {\n return {\n v: checkpoint.v,\n id: checkpoint.id,\n ts: checkpoint.ts,\n channel_values: { ...checkpoint.channel_values },\n channel_versions: { ...checkpoint.channel_versions },\n versions_seen: deepCopy(checkpoint.versions_seen),\n };\n}\n\nexport interface CheckpointTuple {\n config: RunnableConfig;\n checkpoint: Checkpoint;\n metadata?: CheckpointMetadata;\n parentConfig?: RunnableConfig;\n pendingWrites?: CheckpointPendingWrite[];\n}\n\nexport type CheckpointListOptions = {\n limit?: number;\n before?: RunnableConfig;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n filter?: Record<string, any>;\n};\n\nexport abstract class BaseCheckpointSaver<V extends string | number = number> {\n serde: SerializerProtocol = new JsonPlusSerializer();\n\n constructor(serde?: SerializerProtocol) {\n this.serde = serde || this.serde;\n }\n\n async get(config: RunnableConfig): Promise<Checkpoint | undefined> {\n const value = await this.getTuple(config);\n return value ? value.checkpoint : undefined;\n }\n\n abstract getTuple(\n config: RunnableConfig\n ): Promise<CheckpointTuple | undefined>;\n\n abstract list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple>;\n\n abstract put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata,\n newVersions: ChannelVersions\n ): Promise<RunnableConfig>;\n\n /**\n * Store intermediate writes linked to a checkpoint.\n */\n abstract putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void>;\n\n /**\n * Delete all checkpoints and writes associated with a specific thread ID.\n * @param threadId The thread ID whose checkpoints should be deleted.\n */\n abstract deleteThread(threadId: string): Promise<void>;\n\n /**\n * Generate the next version ID for a channel.\n *\n * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,\n * as long as they are monotonically increasing.\n */\n getNextVersion(current: V | undefined): V {\n if (typeof current === \"string\") {\n throw new Error(\"Please override this method to use string versions.\");\n }\n return (\n current !== undefined && typeof current === \"number\" ? current + 1 : 1\n ) as V;\n }\n}\n\nexport function compareChannelVersions(\n a: ChannelVersion,\n b: ChannelVersion\n): number {\n if (typeof a === \"number\" && typeof b === \"number\") {\n return Math.sign(a - b);\n }\n\n return String(a).localeCompare(String(b));\n}\n\nexport function maxChannelVersion(\n ...versions: ChannelVersion[]\n): ChannelVersion {\n return versions.reduce((max, version, idx) => {\n if (idx === 0) return version;\n return compareChannelVersions(max, version) >= 0 ? max : version;\n });\n}\n\n/**\n * Mapping from error type to error index.\n * Regular writes just map to their index in the list of writes being saved.\n * Special writes (e.g. errors) map to negative indices, to avoid those writes from\n * conflicting with regular writes.\n * Each Checkpointer implementation should use this mapping in put_writes.\n */\nexport const WRITES_IDX_MAP: Record<string, number> = {\n [ERROR]: -1,\n [SCHEDULED]: -2,\n [INTERRUPT]: -3,\n [RESUME]: -4,\n};\n\nexport function getCheckpointId(config: RunnableConfig): string {\n return (\n config.configurable?.checkpoint_id || config.configurable?.thread_ts || \"\"\n );\n}\n"],"mappings":";;;;AAsDA,SAAgB,SAAY,KAAW;AACrC,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO;CAGT,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAG,EAAE,GAAG,EAAE;AAE3C,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,CAC/C,QAAwC,OAAO,SAC7C,IAAgC,KAClC;AAIL,QAAO;;;AAIT,SAAgB,kBAA8B;AAC5C,QAAO;EACL,GAAG;EACH,IAAIA,WAAAA,MAAM,GAAG;EACb,qBAAI,IAAI,MAAM,EAAC,aAAa;EAC5B,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;EACpB,eAAe,EAAE;EAClB;;;AAIH,SAAgB,eAAe,YAA4C;AACzE,QAAO;EACL,GAAG,WAAW;EACd,IAAI,WAAW;EACf,IAAI,WAAW;EACf,gBAAgB,EAAE,GAAG,WAAW,gBAAgB;EAChD,kBAAkB,EAAE,GAAG,WAAW,kBAAkB;EACpD,eAAe,SAAS,WAAW,cAAc;EAClD;;AAkBH,IAAsB,sBAAtB,MAA8E;CAC5E,QAA4B,IAAIC,iBAAAA,oBAAoB;CAEpD,YAAY,OAA4B;AACtC,OAAK,QAAQ,SAAS,KAAK;;CAG7B,MAAM,IAAI,QAAyD;EACjE,MAAM,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzC,SAAO,QAAQ,MAAM,aAAa,KAAA;;;;;;;;CAwCpC,eAAe,SAA2B;AACxC,MAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,sDAAsD;AAExE,SACE,YAAY,KAAA,KAAa,OAAO,YAAY,WAAW,UAAU,IAAI;;;AAK3E,SAAgB,uBACd,GACA,GACQ;AACR,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO,KAAK,KAAK,IAAI,EAAE;AAGzB,QAAO,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC;;AAG3C,SAAgB,kBACd,GAAG,UACa;AAChB,QAAO,SAAS,QAAQ,KAAK,SAAS,QAAQ;AAC5C,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,uBAAuB,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzD;;;;;;;;;AAUJ,MAAa,iBAAyC;EACnDC,cAAAA,QAAQ;EACRC,cAAAA,YAAY;EACZC,cAAAA,YAAY;EACZC,cAAAA,SAAS;CACX;AAED,SAAgB,gBAAgB,QAAgC;AAC9D,QACE,OAAO,cAAc,iBAAiB,OAAO,cAAc,aAAa"}
1
+ {"version":3,"file":"base.cjs","names":["uuid6","JsonPlusSerializer","ERROR","SCHEDULED","INTERRUPT","RESUME"],"sources":["../src/base.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport { uuid6 } from \"./id.js\";\nimport type {\n PendingWrite,\n CheckpointPendingWrite,\n CheckpointMetadata,\n} from \"./types.js\";\nimport { ERROR, INTERRUPT, RESUME, SCHEDULED } from \"./serde/types.js\";\nimport { JsonPlusSerializer } from \"./serde/jsonplus.js\";\n\n/** @inline */\ntype ChannelVersion = number | string;\n\nexport type ChannelVersions = Record<string, ChannelVersion>;\n\nexport interface Checkpoint<\n N extends string = string,\n C extends string = string,\n> {\n /**\n * The version of the checkpoint format. Currently 4\n */\n v: number;\n /**\n * Checkpoint ID {uuid6}\n */\n id: string;\n /**\n * Timestamp {new Date().toISOString()}\n */\n ts: string;\n /**\n * @default {}\n */\n channel_values: Record<C, unknown>;\n /**\n * @default {}\n */\n channel_versions: Record<C, ChannelVersion>;\n /**\n * @default {}\n */\n versions_seen: Record<N, Record<C, ChannelVersion>>;\n}\n\nexport interface ReadonlyCheckpoint extends Readonly<Checkpoint> {\n readonly channel_values: Readonly<Record<string, unknown>>;\n readonly channel_versions: Readonly<Record<string, ChannelVersion>>;\n readonly versions_seen: Readonly<\n Record<string, Readonly<Record<string, ChannelVersion>>>\n >;\n}\n\nexport function deepCopy<T>(obj: T): T {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n const newObj = Array.isArray(obj) ? [] : {};\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (newObj as Record<PropertyKey, unknown>)[key] = deepCopy(\n (obj as Record<string, unknown>)[key]\n );\n }\n }\n\n return newObj as T;\n}\n\n/** @hidden */\nexport function emptyCheckpoint(): Checkpoint {\n return {\n v: 4,\n id: uuid6(-2),\n ts: new Date().toISOString(),\n channel_values: {},\n channel_versions: {},\n versions_seen: {},\n };\n}\n\n/** @hidden */\nexport function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint {\n return {\n v: checkpoint.v,\n id: checkpoint.id,\n ts: checkpoint.ts,\n channel_values: { ...checkpoint.channel_values },\n channel_versions: { ...checkpoint.channel_versions },\n versions_seen: deepCopy(checkpoint.versions_seen),\n };\n}\n\nexport interface CheckpointTuple {\n config: RunnableConfig;\n checkpoint: Checkpoint;\n metadata?: CheckpointMetadata;\n parentConfig?: RunnableConfig;\n pendingWrites?: CheckpointPendingWrite[];\n}\n\nexport type CheckpointListOptions = {\n limit?: number;\n before?: RunnableConfig;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n filter?: Record<string, any>;\n};\n\nexport abstract class BaseCheckpointSaver<V extends string | number = number> {\n serde: SerializerProtocol = new JsonPlusSerializer();\n\n constructor(serde?: SerializerProtocol) {\n this.serde = serde || this.serde;\n }\n\n async get(config: RunnableConfig): Promise<Checkpoint | undefined> {\n const value = await this.getTuple(config);\n return value ? value.checkpoint : undefined;\n }\n\n abstract getTuple(\n config: RunnableConfig\n ): Promise<CheckpointTuple | undefined>;\n\n abstract list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple>;\n\n abstract put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata,\n newVersions: ChannelVersions\n ): Promise<RunnableConfig>;\n\n /**\n * Store intermediate writes linked to a checkpoint.\n */\n abstract putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void>;\n\n /**\n * Delete all checkpoints and writes associated with a specific thread ID.\n * @param threadId The thread ID whose checkpoints should be deleted.\n */\n abstract deleteThread(threadId: string): Promise<void>;\n\n /**\n * Generate the next version ID for a channel.\n *\n * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,\n * as long as they are monotonically increasing.\n */\n getNextVersion(current: V | undefined): V {\n if (typeof current === \"string\") {\n throw new Error(\"Please override this method to use string versions.\");\n }\n return (\n current !== undefined && typeof current === \"number\" ? current + 1 : 1\n ) as V;\n }\n}\n\nexport function compareChannelVersions(\n a: ChannelVersion,\n b: ChannelVersion\n): number {\n if (typeof a === \"number\" && typeof b === \"number\") {\n return Math.sign(a - b);\n }\n\n return String(a).localeCompare(String(b));\n}\n\nexport function maxChannelVersion(\n ...versions: ChannelVersion[]\n): ChannelVersion {\n return versions.reduce((max, version, idx) => {\n if (idx === 0) return version;\n return compareChannelVersions(max, version) >= 0 ? max : version;\n });\n}\n\n/**\n * Mapping from error type to error index.\n * Regular writes just map to their index in the list of writes being saved.\n * Special writes (e.g. errors) map to negative indices, to avoid those writes from\n * conflicting with regular writes.\n * Each Checkpointer implementation should use this mapping in put_writes.\n */\nexport const WRITES_IDX_MAP: Record<string, number> = {\n [ERROR]: -1,\n [SCHEDULED]: -2,\n [INTERRUPT]: -3,\n [RESUME]: -4,\n};\n\nexport function getCheckpointId(config: RunnableConfig): string {\n return (\n config.configurable?.checkpoint_id || config.configurable?.thread_ts || \"\"\n );\n}\n"],"mappings":";;;;AAsDA,SAAgB,SAAY,KAAW;AACrC,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO;CAGT,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAG,EAAE,GAAG,EAAE;AAE3C,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,CAC/C,QAAwC,OAAO,SAC7C,IAAgC,KAClC;AAIL,QAAO;;;AAIT,SAAgB,kBAA8B;AAC5C,QAAO;EACL,GAAG;EACH,IAAIA,WAAAA,MAAM,GAAG;EACb,qBAAI,IAAI,MAAM,EAAC,aAAa;EAC5B,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;EACpB,eAAe,EAAE;EAClB;;;AAIH,SAAgB,eAAe,YAA4C;AACzE,QAAO;EACL,GAAG,WAAW;EACd,IAAI,WAAW;EACf,IAAI,WAAW;EACf,gBAAgB,EAAE,GAAG,WAAW,gBAAgB;EAChD,kBAAkB,EAAE,GAAG,WAAW,kBAAkB;EACpD,eAAe,SAAS,WAAW,cAAc;EAClD;;AAkBH,IAAsB,sBAAtB,MAA8E;CAC5E,QAA4B,IAAIC,iBAAAA,oBAAoB;CAEpD,YAAY,OAA4B;AACtC,OAAK,QAAQ,SAAS,KAAK;;CAG7B,MAAM,IAAI,QAAyD;EACjE,MAAM,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzC,SAAO,QAAQ,MAAM,aAAa,KAAA;;;;;;;;CAwCpC,eAAe,SAA2B;AACxC,MAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,sDAAsD;AAExE,SACE,YAAY,KAAA,KAAa,OAAO,YAAY,WAAW,UAAU,IAAI;;;AAK3E,SAAgB,uBACd,GACA,GACQ;AACR,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO,KAAK,KAAK,IAAI,EAAE;AAGzB,QAAO,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC;;AAG3C,SAAgB,kBACd,GAAG,UACa;AAChB,QAAO,SAAS,QAAQ,KAAK,SAAS,QAAQ;AAC5C,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,uBAAuB,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzD;;;;;;;;;AAUJ,MAAa,iBAAyC;EACnDC,cAAAA,QAAQ;EACRC,cAAAA,YAAY;EACZC,cAAAA,YAAY;EACZC,cAAAA,SAAS;CACX;AAED,SAAgB,gBAAgB,QAAgC;AAC9D,QACE,OAAO,cAAc,iBAAiB,OAAO,cAAc,aAAa"}
package/dist/base.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../src/base.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport { uuid6 } from \"./id.js\";\nimport type {\n PendingWrite,\n CheckpointPendingWrite,\n CheckpointMetadata,\n} from \"./types.js\";\nimport { ERROR, INTERRUPT, RESUME, SCHEDULED } from \"./serde/types.js\";\nimport { JsonPlusSerializer } from \"./serde/jsonplus.js\";\n\n/** @inline */\ntype ChannelVersion = number | string;\n\nexport type ChannelVersions = Record<string, ChannelVersion>;\n\nexport interface Checkpoint<\n N extends string = string,\n C extends string = string\n> {\n /**\n * The version of the checkpoint format. Currently 4\n */\n v: number;\n /**\n * Checkpoint ID {uuid6}\n */\n id: string;\n /**\n * Timestamp {new Date().toISOString()}\n */\n ts: string;\n /**\n * @default {}\n */\n channel_values: Record<C, unknown>;\n /**\n * @default {}\n */\n channel_versions: Record<C, ChannelVersion>;\n /**\n * @default {}\n */\n versions_seen: Record<N, Record<C, ChannelVersion>>;\n}\n\nexport interface ReadonlyCheckpoint extends Readonly<Checkpoint> {\n readonly channel_values: Readonly<Record<string, unknown>>;\n readonly channel_versions: Readonly<Record<string, ChannelVersion>>;\n readonly versions_seen: Readonly<\n Record<string, Readonly<Record<string, ChannelVersion>>>\n >;\n}\n\nexport function deepCopy<T>(obj: T): T {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n const newObj = Array.isArray(obj) ? [] : {};\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (newObj as Record<PropertyKey, unknown>)[key] = deepCopy(\n (obj as Record<string, unknown>)[key]\n );\n }\n }\n\n return newObj as T;\n}\n\n/** @hidden */\nexport function emptyCheckpoint(): Checkpoint {\n return {\n v: 4,\n id: uuid6(-2),\n ts: new Date().toISOString(),\n channel_values: {},\n channel_versions: {},\n versions_seen: {},\n };\n}\n\n/** @hidden */\nexport function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint {\n return {\n v: checkpoint.v,\n id: checkpoint.id,\n ts: checkpoint.ts,\n channel_values: { ...checkpoint.channel_values },\n channel_versions: { ...checkpoint.channel_versions },\n versions_seen: deepCopy(checkpoint.versions_seen),\n };\n}\n\nexport interface CheckpointTuple {\n config: RunnableConfig;\n checkpoint: Checkpoint;\n metadata?: CheckpointMetadata;\n parentConfig?: RunnableConfig;\n pendingWrites?: CheckpointPendingWrite[];\n}\n\nexport type CheckpointListOptions = {\n limit?: number;\n before?: RunnableConfig;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n filter?: Record<string, any>;\n};\n\nexport abstract class BaseCheckpointSaver<V extends string | number = number> {\n serde: SerializerProtocol = new JsonPlusSerializer();\n\n constructor(serde?: SerializerProtocol) {\n this.serde = serde || this.serde;\n }\n\n async get(config: RunnableConfig): Promise<Checkpoint | undefined> {\n const value = await this.getTuple(config);\n return value ? value.checkpoint : undefined;\n }\n\n abstract getTuple(\n config: RunnableConfig\n ): Promise<CheckpointTuple | undefined>;\n\n abstract list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple>;\n\n abstract put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata,\n newVersions: ChannelVersions\n ): Promise<RunnableConfig>;\n\n /**\n * Store intermediate writes linked to a checkpoint.\n */\n abstract putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void>;\n\n /**\n * Delete all checkpoints and writes associated with a specific thread ID.\n * @param threadId The thread ID whose checkpoints should be deleted.\n */\n abstract deleteThread(threadId: string): Promise<void>;\n\n /**\n * Generate the next version ID for a channel.\n *\n * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,\n * as long as they are monotonically increasing.\n */\n getNextVersion(current: V | undefined): V {\n if (typeof current === \"string\") {\n throw new Error(\"Please override this method to use string versions.\");\n }\n return (\n current !== undefined && typeof current === \"number\" ? current + 1 : 1\n ) as V;\n }\n}\n\nexport function compareChannelVersions(\n a: ChannelVersion,\n b: ChannelVersion\n): number {\n if (typeof a === \"number\" && typeof b === \"number\") {\n return Math.sign(a - b);\n }\n\n return String(a).localeCompare(String(b));\n}\n\nexport function maxChannelVersion(\n ...versions: ChannelVersion[]\n): ChannelVersion {\n return versions.reduce((max, version, idx) => {\n if (idx === 0) return version;\n return compareChannelVersions(max, version) >= 0 ? max : version;\n });\n}\n\n/**\n * Mapping from error type to error index.\n * Regular writes just map to their index in the list of writes being saved.\n * Special writes (e.g. errors) map to negative indices, to avoid those writes from\n * conflicting with regular writes.\n * Each Checkpointer implementation should use this mapping in put_writes.\n */\nexport const WRITES_IDX_MAP: Record<string, number> = {\n [ERROR]: -1,\n [SCHEDULED]: -2,\n [INTERRUPT]: -3,\n [RESUME]: -4,\n};\n\nexport function getCheckpointId(config: RunnableConfig): string {\n return (\n config.configurable?.checkpoint_id || config.configurable?.thread_ts || \"\"\n );\n}\n"],"mappings":";;;;AAsDA,SAAgB,SAAY,KAAW;AACrC,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO;CAGT,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAG,EAAE,GAAG,EAAE;AAE3C,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,CAC/C,QAAwC,OAAO,SAC7C,IAAgC,KAClC;AAIL,QAAO;;;AAIT,SAAgB,kBAA8B;AAC5C,QAAO;EACL,GAAG;EACH,IAAI,MAAM,GAAG;EACb,qBAAI,IAAI,MAAM,EAAC,aAAa;EAC5B,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;EACpB,eAAe,EAAE;EAClB;;;AAIH,SAAgB,eAAe,YAA4C;AACzE,QAAO;EACL,GAAG,WAAW;EACd,IAAI,WAAW;EACf,IAAI,WAAW;EACf,gBAAgB,EAAE,GAAG,WAAW,gBAAgB;EAChD,kBAAkB,EAAE,GAAG,WAAW,kBAAkB;EACpD,eAAe,SAAS,WAAW,cAAc;EAClD;;AAkBH,IAAsB,sBAAtB,MAA8E;CAC5E,QAA4B,IAAI,oBAAoB;CAEpD,YAAY,OAA4B;AACtC,OAAK,QAAQ,SAAS,KAAK;;CAG7B,MAAM,IAAI,QAAyD;EACjE,MAAM,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzC,SAAO,QAAQ,MAAM,aAAa,KAAA;;;;;;;;CAwCpC,eAAe,SAA2B;AACxC,MAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,sDAAsD;AAExE,SACE,YAAY,KAAA,KAAa,OAAO,YAAY,WAAW,UAAU,IAAI;;;AAK3E,SAAgB,uBACd,GACA,GACQ;AACR,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO,KAAK,KAAK,IAAI,EAAE;AAGzB,QAAO,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC;;AAG3C,SAAgB,kBACd,GAAG,UACa;AAChB,QAAO,SAAS,QAAQ,KAAK,SAAS,QAAQ;AAC5C,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,uBAAuB,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzD;;;;;;;;;AAUJ,MAAa,iBAAyC;EACnD,QAAQ;EACR,YAAY;EACZ,YAAY;EACZ,SAAS;CACX;AAED,SAAgB,gBAAgB,QAAgC;AAC9D,QACE,OAAO,cAAc,iBAAiB,OAAO,cAAc,aAAa"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../src/base.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport { uuid6 } from \"./id.js\";\nimport type {\n PendingWrite,\n CheckpointPendingWrite,\n CheckpointMetadata,\n} from \"./types.js\";\nimport { ERROR, INTERRUPT, RESUME, SCHEDULED } from \"./serde/types.js\";\nimport { JsonPlusSerializer } from \"./serde/jsonplus.js\";\n\n/** @inline */\ntype ChannelVersion = number | string;\n\nexport type ChannelVersions = Record<string, ChannelVersion>;\n\nexport interface Checkpoint<\n N extends string = string,\n C extends string = string,\n> {\n /**\n * The version of the checkpoint format. Currently 4\n */\n v: number;\n /**\n * Checkpoint ID {uuid6}\n */\n id: string;\n /**\n * Timestamp {new Date().toISOString()}\n */\n ts: string;\n /**\n * @default {}\n */\n channel_values: Record<C, unknown>;\n /**\n * @default {}\n */\n channel_versions: Record<C, ChannelVersion>;\n /**\n * @default {}\n */\n versions_seen: Record<N, Record<C, ChannelVersion>>;\n}\n\nexport interface ReadonlyCheckpoint extends Readonly<Checkpoint> {\n readonly channel_values: Readonly<Record<string, unknown>>;\n readonly channel_versions: Readonly<Record<string, ChannelVersion>>;\n readonly versions_seen: Readonly<\n Record<string, Readonly<Record<string, ChannelVersion>>>\n >;\n}\n\nexport function deepCopy<T>(obj: T): T {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n const newObj = Array.isArray(obj) ? [] : {};\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n (newObj as Record<PropertyKey, unknown>)[key] = deepCopy(\n (obj as Record<string, unknown>)[key]\n );\n }\n }\n\n return newObj as T;\n}\n\n/** @hidden */\nexport function emptyCheckpoint(): Checkpoint {\n return {\n v: 4,\n id: uuid6(-2),\n ts: new Date().toISOString(),\n channel_values: {},\n channel_versions: {},\n versions_seen: {},\n };\n}\n\n/** @hidden */\nexport function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint {\n return {\n v: checkpoint.v,\n id: checkpoint.id,\n ts: checkpoint.ts,\n channel_values: { ...checkpoint.channel_values },\n channel_versions: { ...checkpoint.channel_versions },\n versions_seen: deepCopy(checkpoint.versions_seen),\n };\n}\n\nexport interface CheckpointTuple {\n config: RunnableConfig;\n checkpoint: Checkpoint;\n metadata?: CheckpointMetadata;\n parentConfig?: RunnableConfig;\n pendingWrites?: CheckpointPendingWrite[];\n}\n\nexport type CheckpointListOptions = {\n limit?: number;\n before?: RunnableConfig;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n filter?: Record<string, any>;\n};\n\nexport abstract class BaseCheckpointSaver<V extends string | number = number> {\n serde: SerializerProtocol = new JsonPlusSerializer();\n\n constructor(serde?: SerializerProtocol) {\n this.serde = serde || this.serde;\n }\n\n async get(config: RunnableConfig): Promise<Checkpoint | undefined> {\n const value = await this.getTuple(config);\n return value ? value.checkpoint : undefined;\n }\n\n abstract getTuple(\n config: RunnableConfig\n ): Promise<CheckpointTuple | undefined>;\n\n abstract list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple>;\n\n abstract put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata,\n newVersions: ChannelVersions\n ): Promise<RunnableConfig>;\n\n /**\n * Store intermediate writes linked to a checkpoint.\n */\n abstract putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void>;\n\n /**\n * Delete all checkpoints and writes associated with a specific thread ID.\n * @param threadId The thread ID whose checkpoints should be deleted.\n */\n abstract deleteThread(threadId: string): Promise<void>;\n\n /**\n * Generate the next version ID for a channel.\n *\n * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,\n * as long as they are monotonically increasing.\n */\n getNextVersion(current: V | undefined): V {\n if (typeof current === \"string\") {\n throw new Error(\"Please override this method to use string versions.\");\n }\n return (\n current !== undefined && typeof current === \"number\" ? current + 1 : 1\n ) as V;\n }\n}\n\nexport function compareChannelVersions(\n a: ChannelVersion,\n b: ChannelVersion\n): number {\n if (typeof a === \"number\" && typeof b === \"number\") {\n return Math.sign(a - b);\n }\n\n return String(a).localeCompare(String(b));\n}\n\nexport function maxChannelVersion(\n ...versions: ChannelVersion[]\n): ChannelVersion {\n return versions.reduce((max, version, idx) => {\n if (idx === 0) return version;\n return compareChannelVersions(max, version) >= 0 ? max : version;\n });\n}\n\n/**\n * Mapping from error type to error index.\n * Regular writes just map to their index in the list of writes being saved.\n * Special writes (e.g. errors) map to negative indices, to avoid those writes from\n * conflicting with regular writes.\n * Each Checkpointer implementation should use this mapping in put_writes.\n */\nexport const WRITES_IDX_MAP: Record<string, number> = {\n [ERROR]: -1,\n [SCHEDULED]: -2,\n [INTERRUPT]: -3,\n [RESUME]: -4,\n};\n\nexport function getCheckpointId(config: RunnableConfig): string {\n return (\n config.configurable?.checkpoint_id || config.configurable?.thread_ts || \"\"\n );\n}\n"],"mappings":";;;;AAsDA,SAAgB,SAAY,KAAW;AACrC,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO;CAGT,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAG,EAAE,GAAG,EAAE;AAE3C,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,CAC/C,QAAwC,OAAO,SAC7C,IAAgC,KAClC;AAIL,QAAO;;;AAIT,SAAgB,kBAA8B;AAC5C,QAAO;EACL,GAAG;EACH,IAAI,MAAM,GAAG;EACb,qBAAI,IAAI,MAAM,EAAC,aAAa;EAC5B,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;EACpB,eAAe,EAAE;EAClB;;;AAIH,SAAgB,eAAe,YAA4C;AACzE,QAAO;EACL,GAAG,WAAW;EACd,IAAI,WAAW;EACf,IAAI,WAAW;EACf,gBAAgB,EAAE,GAAG,WAAW,gBAAgB;EAChD,kBAAkB,EAAE,GAAG,WAAW,kBAAkB;EACpD,eAAe,SAAS,WAAW,cAAc;EAClD;;AAkBH,IAAsB,sBAAtB,MAA8E;CAC5E,QAA4B,IAAI,oBAAoB;CAEpD,YAAY,OAA4B;AACtC,OAAK,QAAQ,SAAS,KAAK;;CAG7B,MAAM,IAAI,QAAyD;EACjE,MAAM,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzC,SAAO,QAAQ,MAAM,aAAa,KAAA;;;;;;;;CAwCpC,eAAe,SAA2B;AACxC,MAAI,OAAO,YAAY,SACrB,OAAM,IAAI,MAAM,sDAAsD;AAExE,SACE,YAAY,KAAA,KAAa,OAAO,YAAY,WAAW,UAAU,IAAI;;;AAK3E,SAAgB,uBACd,GACA,GACQ;AACR,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO,KAAK,KAAK,IAAI,EAAE;AAGzB,QAAO,OAAO,EAAE,CAAC,cAAc,OAAO,EAAE,CAAC;;AAG3C,SAAgB,kBACd,GAAG,UACa;AAChB,QAAO,SAAS,QAAQ,KAAK,SAAS,QAAQ;AAC5C,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,uBAAuB,KAAK,QAAQ,IAAI,IAAI,MAAM;GACzD;;;;;;;;;AAUJ,MAAa,iBAAyC;EACnD,QAAQ;EACR,YAAY;EACZ,YAAY;EACZ,SAAS;CACX;AAED,SAAgB,gBAAgB,QAAgC;AAC9D,QACE,OAAO,cAAc,iBAAiB,OAAO,cAAc,aAAa"}
package/dist/memory.cjs CHANGED
@@ -149,7 +149,7 @@ var MemorySaver = class extends require_base.BaseCheckpointSaver {
149
149
  const preparedCheckpoint = require_base.copyCheckpoint(checkpoint);
150
150
  const threadId = config.configurable?.thread_id;
151
151
  const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
152
- if (threadId === void 0) throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property.`);
152
+ if (threadId === void 0) throw new Error("Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })");
153
153
  if (!this.storage[threadId]) this.storage[threadId] = {};
154
154
  if (!this.storage[threadId][checkpointNamespace]) this.storage[threadId][checkpointNamespace] = {};
155
155
  const [[, serializedCheckpoint], [, serializedMetadata]] = await Promise.all([this.serde.dumpsTyped(preparedCheckpoint), this.serde.dumpsTyped(metadata)]);
@@ -168,7 +168,7 @@ var MemorySaver = class extends require_base.BaseCheckpointSaver {
168
168
  const threadId = config.configurable?.thread_id;
169
169
  const checkpointNamespace = config.configurable?.checkpoint_ns;
170
170
  const checkpointId = config.configurable?.checkpoint_id;
171
- if (threadId === void 0) throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property`);
171
+ if (threadId === void 0) throw new Error("Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })");
172
172
  if (checkpointId === void 0) throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "checkpoint_id" field in its "configurable" property.`);
173
173
  const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);
174
174
  const outerWrites_ = this.writes[outerKey];
@@ -1 +1 @@
1
- {"version":3,"file":"memory.cjs","names":["BaseCheckpointSaver","TASKS","maxChannelVersion","getCheckpointId","copyCheckpoint","WRITES_IDX_MAP"],"sources":["../src/memory.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n BaseCheckpointSaver,\n Checkpoint,\n CheckpointListOptions,\n CheckpointTuple,\n copyCheckpoint,\n getCheckpointId,\n maxChannelVersion,\n WRITES_IDX_MAP,\n} from \"./base.js\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport {\n CheckpointMetadata,\n CheckpointPendingWrite,\n PendingWrite,\n} from \"./types.js\";\nimport { TASKS } from \"./serde/types.js\";\n\nfunction _generateKey(\n threadId: string,\n checkpointNamespace: string,\n checkpointId: string\n) {\n return JSON.stringify([threadId, checkpointNamespace, checkpointId]);\n}\n\nfunction _parseKey(key: string) {\n const [threadId, checkpointNamespace, checkpointId] = JSON.parse(key);\n return { threadId, checkpointNamespace, checkpointId };\n}\n\nexport class MemorySaver extends BaseCheckpointSaver {\n // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping\n storage: Record<\n string,\n Record<string, Record<string, [Uint8Array, Uint8Array, string | undefined]>>\n > = {};\n\n writes: Record<string, Record<string, [string, string, Uint8Array]>> = {};\n\n constructor(serde?: SerializerProtocol) {\n super(serde);\n }\n\n /** @internal */\n async _migratePendingSends(\n mutableCheckpoint: Checkpoint,\n threadId: string,\n checkpointNs: string,\n parentCheckpointId: string\n ) {\n const deseriablizableCheckpoint = mutableCheckpoint;\n const parentKey = _generateKey(threadId, checkpointNs, parentCheckpointId);\n\n const pendingSends = await Promise.all(\n Object.values(this.writes[parentKey] ?? {})\n .filter(([_taskId, channel]) => channel === TASKS)\n .map(\n async ([_taskId, _channel, writes]) =>\n await this.serde.loadsTyped(\"json\", writes)\n )\n );\n\n deseriablizableCheckpoint.channel_values ??= {};\n deseriablizableCheckpoint.channel_values[TASKS] = pendingSends;\n\n deseriablizableCheckpoint.channel_versions ??= {};\n deseriablizableCheckpoint.channel_versions[TASKS] =\n Object.keys(deseriablizableCheckpoint.channel_versions).length > 0\n ? maxChannelVersion(\n ...Object.values(deseriablizableCheckpoint.channel_versions)\n )\n : this.getNextVersion(undefined);\n }\n\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns ?? \"\";\n let checkpoint_id = getCheckpointId(config);\n\n if (checkpoint_id) {\n const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];\n if (saved !== undefined) {\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config,\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n } else {\n const checkpoints = this.storage[thread_id]?.[checkpoint_ns];\n if (checkpoints !== undefined) {\n // eslint-disable-next-line prefer-destructuring\n checkpoint_id = Object.keys(checkpoints).sort((a, b) =>\n b.localeCompare(a)\n )[0];\n const saved = checkpoints[checkpoint_id];\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id,\n checkpoint_id,\n checkpoint_ns,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n }\n\n return undefined;\n }\n\n async *list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple> {\n // eslint-disable-next-line prefer-const\n let { before, limit, filter } = options ?? {};\n const threadIds = config.configurable?.thread_id\n ? [config.configurable?.thread_id]\n : Object.keys(this.storage);\n const configCheckpointNamespace = config.configurable?.checkpoint_ns;\n const configCheckpointId = config.configurable?.checkpoint_id;\n\n for (const threadId of threadIds) {\n for (const checkpointNamespace of Object.keys(\n this.storage[threadId] ?? {}\n )) {\n if (\n configCheckpointNamespace !== undefined &&\n checkpointNamespace !== configCheckpointNamespace\n ) {\n continue;\n }\n const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};\n const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) =>\n b[0].localeCompare(a[0])\n );\n\n for (const [\n checkpointId,\n [checkpoint, metadataStr, parentCheckpointId],\n ] of sortedCheckpoints) {\n // Filter by checkpoint ID from config\n if (configCheckpointId && checkpointId !== configCheckpointId) {\n continue;\n }\n\n // Filter by checkpoint ID from before config\n if (\n before &&\n before.configurable?.checkpoint_id &&\n checkpointId >= before.configurable.checkpoint_id\n ) {\n continue;\n }\n\n // Parse metadata\n const metadata = (await this.serde.loadsTyped(\n \"json\",\n metadataStr\n )) as CheckpointMetadata;\n\n if (\n filter &&\n !Object.entries(filter).every(\n ([key, value]) =>\n (metadata as unknown as Record<string, unknown>)[key] === value\n )\n ) {\n continue;\n }\n\n // Limit search results\n if (limit !== undefined) {\n if (limit <= 0) break;\n limit -= 1;\n }\n\n const key = _generateKey(threadId, checkpointNamespace, checkpointId);\n const writes = Object.values(this.writes[key] || {});\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n writes.map(async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n })\n );\n\n const deserializedCheckpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (\n deserializedCheckpoint.v < 4 &&\n parentCheckpointId !== undefined\n ) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n threadId,\n checkpointNamespace,\n parentCheckpointId\n );\n }\n\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpointId,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n yield checkpointTuple;\n }\n }\n }\n }\n\n async put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata\n ): Promise<RunnableConfig> {\n const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns ?? \"\";\n if (threadId === undefined) {\n throw new Error(\n `Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property.`\n );\n }\n\n if (!this.storage[threadId]) {\n this.storage[threadId] = {};\n }\n if (!this.storage[threadId][checkpointNamespace]) {\n this.storage[threadId][checkpointNamespace] = {};\n }\n\n const [[, serializedCheckpoint], [, serializedMetadata]] =\n await Promise.all([\n this.serde.dumpsTyped(preparedCheckpoint),\n this.serde.dumpsTyped(metadata),\n ]);\n\n this.storage[threadId][checkpointNamespace][checkpoint.id] = [\n serializedCheckpoint,\n serializedMetadata,\n config.configurable?.checkpoint_id, // parent\n ];\n\n return {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpoint.id,\n },\n };\n }\n\n async putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void> {\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns;\n const checkpointId = config.configurable?.checkpoint_id;\n if (threadId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property`\n );\n }\n if (checkpointId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"checkpoint_id\" field in its \"configurable\" property.`\n );\n }\n const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);\n const outerWrites_ = this.writes[outerKey];\n if (this.writes[outerKey] === undefined) {\n this.writes[outerKey] = {};\n }\n\n await Promise.all(\n writes.map(async ([channel, value], idx) => {\n const [, serializedValue] = await this.serde.dumpsTyped(value);\n const innerKey: [string, number] = [\n taskId,\n WRITES_IDX_MAP[channel] || idx,\n ];\n const innerKeyStr = `${innerKey[0]},${innerKey[1]}`;\n if (innerKey[1] >= 0 && outerWrites_ && innerKeyStr in outerWrites_) {\n return;\n }\n this.writes[outerKey][innerKeyStr] = [taskId, channel, serializedValue];\n })\n );\n }\n\n async deleteThread(threadId: string): Promise<void> {\n delete this.storage[threadId];\n for (const key of Object.keys(this.writes)) {\n if (_parseKey(key).threadId === threadId) delete this.writes[key];\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.cjs","names":["BaseCheckpointSaver","TASKS","maxChannelVersion","getCheckpointId","copyCheckpoint","WRITES_IDX_MAP"],"sources":["../src/memory.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n BaseCheckpointSaver,\n Checkpoint,\n CheckpointListOptions,\n CheckpointTuple,\n copyCheckpoint,\n getCheckpointId,\n maxChannelVersion,\n WRITES_IDX_MAP,\n} from \"./base.js\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport {\n CheckpointMetadata,\n CheckpointPendingWrite,\n PendingWrite,\n} from \"./types.js\";\nimport { TASKS } from \"./serde/types.js\";\n\nfunction _generateKey(\n threadId: string,\n checkpointNamespace: string,\n checkpointId: string\n) {\n return JSON.stringify([threadId, checkpointNamespace, checkpointId]);\n}\n\nfunction _parseKey(key: string) {\n const [threadId, checkpointNamespace, checkpointId] = JSON.parse(key);\n return { threadId, checkpointNamespace, checkpointId };\n}\n\nexport class MemorySaver extends BaseCheckpointSaver {\n // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping\n storage: Record<\n string,\n Record<string, Record<string, [Uint8Array, Uint8Array, string | undefined]>>\n > = {};\n\n writes: Record<string, Record<string, [string, string, Uint8Array]>> = {};\n\n constructor(serde?: SerializerProtocol) {\n super(serde);\n }\n\n /** @internal */\n async _migratePendingSends(\n mutableCheckpoint: Checkpoint,\n threadId: string,\n checkpointNs: string,\n parentCheckpointId: string\n ) {\n const deseriablizableCheckpoint = mutableCheckpoint;\n const parentKey = _generateKey(threadId, checkpointNs, parentCheckpointId);\n\n const pendingSends = await Promise.all(\n Object.values(this.writes[parentKey] ?? {})\n .filter(([_taskId, channel]) => channel === TASKS)\n .map(\n async ([_taskId, _channel, writes]) =>\n await this.serde.loadsTyped(\"json\", writes)\n )\n );\n\n deseriablizableCheckpoint.channel_values ??= {};\n deseriablizableCheckpoint.channel_values[TASKS] = pendingSends;\n\n deseriablizableCheckpoint.channel_versions ??= {};\n deseriablizableCheckpoint.channel_versions[TASKS] =\n Object.keys(deseriablizableCheckpoint.channel_versions).length > 0\n ? maxChannelVersion(\n ...Object.values(deseriablizableCheckpoint.channel_versions)\n )\n : this.getNextVersion(undefined);\n }\n\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns ?? \"\";\n let checkpoint_id = getCheckpointId(config);\n\n if (checkpoint_id) {\n const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];\n if (saved !== undefined) {\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config,\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n } else {\n const checkpoints = this.storage[thread_id]?.[checkpoint_ns];\n if (checkpoints !== undefined) {\n // eslint-disable-next-line prefer-destructuring\n checkpoint_id = Object.keys(checkpoints).sort((a, b) =>\n b.localeCompare(a)\n )[0];\n const saved = checkpoints[checkpoint_id];\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id,\n checkpoint_id,\n checkpoint_ns,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n }\n\n return undefined;\n }\n\n async *list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple> {\n // eslint-disable-next-line prefer-const\n let { before, limit, filter } = options ?? {};\n const threadIds = config.configurable?.thread_id\n ? [config.configurable?.thread_id]\n : Object.keys(this.storage);\n const configCheckpointNamespace = config.configurable?.checkpoint_ns;\n const configCheckpointId = config.configurable?.checkpoint_id;\n\n for (const threadId of threadIds) {\n for (const checkpointNamespace of Object.keys(\n this.storage[threadId] ?? {}\n )) {\n if (\n configCheckpointNamespace !== undefined &&\n checkpointNamespace !== configCheckpointNamespace\n ) {\n continue;\n }\n const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};\n const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) =>\n b[0].localeCompare(a[0])\n );\n\n for (const [\n checkpointId,\n [checkpoint, metadataStr, parentCheckpointId],\n ] of sortedCheckpoints) {\n // Filter by checkpoint ID from config\n if (configCheckpointId && checkpointId !== configCheckpointId) {\n continue;\n }\n\n // Filter by checkpoint ID from before config\n if (\n before &&\n before.configurable?.checkpoint_id &&\n checkpointId >= before.configurable.checkpoint_id\n ) {\n continue;\n }\n\n // Parse metadata\n const metadata = (await this.serde.loadsTyped(\n \"json\",\n metadataStr\n )) as CheckpointMetadata;\n\n if (\n filter &&\n !Object.entries(filter).every(\n ([key, value]) =>\n (metadata as unknown as Record<string, unknown>)[key] === value\n )\n ) {\n continue;\n }\n\n // Limit search results\n if (limit !== undefined) {\n if (limit <= 0) break;\n limit -= 1;\n }\n\n const key = _generateKey(threadId, checkpointNamespace, checkpointId);\n const writes = Object.values(this.writes[key] || {});\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n writes.map(async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n })\n );\n\n const deserializedCheckpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (\n deserializedCheckpoint.v < 4 &&\n parentCheckpointId !== undefined\n ) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n threadId,\n checkpointNamespace,\n parentCheckpointId\n );\n }\n\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpointId,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n yield checkpointTuple;\n }\n }\n }\n }\n\n async put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata\n ): Promise<RunnableConfig> {\n const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns ?? \"\";\n if (threadId === undefined) {\n throw new Error(\n `Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. ` +\n `When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. ` +\n `Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })`\n );\n }\n\n if (!this.storage[threadId]) {\n this.storage[threadId] = {};\n }\n if (!this.storage[threadId][checkpointNamespace]) {\n this.storage[threadId][checkpointNamespace] = {};\n }\n\n const [[, serializedCheckpoint], [, serializedMetadata]] =\n await Promise.all([\n this.serde.dumpsTyped(preparedCheckpoint),\n this.serde.dumpsTyped(metadata),\n ]);\n\n this.storage[threadId][checkpointNamespace][checkpoint.id] = [\n serializedCheckpoint,\n serializedMetadata,\n config.configurable?.checkpoint_id, // parent\n ];\n\n return {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpoint.id,\n },\n };\n }\n\n async putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void> {\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns;\n const checkpointId = config.configurable?.checkpoint_id;\n if (threadId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. ` +\n `When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. ` +\n `Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })`\n );\n }\n if (checkpointId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"checkpoint_id\" field in its \"configurable\" property.`\n );\n }\n const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);\n const outerWrites_ = this.writes[outerKey];\n if (this.writes[outerKey] === undefined) {\n this.writes[outerKey] = {};\n }\n\n await Promise.all(\n writes.map(async ([channel, value], idx) => {\n const [, serializedValue] = await this.serde.dumpsTyped(value);\n const innerKey: [string, number] = [\n taskId,\n WRITES_IDX_MAP[channel] || idx,\n ];\n const innerKeyStr = `${innerKey[0]},${innerKey[1]}`;\n if (innerKey[1] >= 0 && outerWrites_ && innerKeyStr in outerWrites_) {\n return;\n }\n this.writes[outerKey][innerKeyStr] = [taskId, channel, serializedValue];\n })\n );\n }\n\n async deleteThread(threadId: string): Promise<void> {\n delete this.storage[threadId];\n for (const key of Object.keys(this.writes)) {\n if (_parseKey(key).threadId === threadId) delete this.writes[key];\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.cts","names":[],"sources":["../src/memory.ts"],"mappings":";;;;;;cAgCa,WAAA,SAAoB,mBAAA;EAE/B,OAAA,EAAS,MAAA,SAEP,MAAA,SAAe,MAAA,UAAgB,UAAA,EAAY,UAAA;EAG7C,MAAA,EAAQ,MAAA,SAAe,MAAA,0BAAgC,UAAA;EAEvD,WAAA,CAAY,KAAA,GAAQ,kBAAA;;EAKd,oBAAA,CACJ,iBAAA,EAAmB,UAAA,EACnB,QAAA,UACA,YAAA,UACA,kBAAA,WAA0B,OAAA;EA0BtB,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAyHzC,IAAA,CACL,MAAA,EAAQ,cAAA,EACR,OAAA,GAAU,qBAAA,GACT,cAAA,CAAe,eAAA;EAyHZ,GAAA,CACJ,MAAA,EAAQ,cAAA,EACR,UAAA,EAAY,UAAA,EACZ,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,cAAA;EAsCL,SAAA,CACJ,MAAA,EAAQ,cAAA,EACR,MAAA,EAAQ,YAAA,IACR,MAAA,WACC,OAAA;EAoCG,YAAA,CAAa,QAAA,WAAmB,OAAA;AAAA"}
1
+ {"version":3,"file":"memory.d.cts","names":[],"sources":["../src/memory.ts"],"mappings":";;;;;;cAgCa,WAAA,SAAoB,mBAAA;EAE/B,OAAA,EAAS,MAAA,SAEP,MAAA,SAAe,MAAA,UAAgB,UAAA,EAAY,UAAA;EAG7C,MAAA,EAAQ,MAAA,SAAe,MAAA,0BAAgC,UAAA;EAEvD,WAAA,CAAY,KAAA,GAAQ,kBAAA;;EAKd,oBAAA,CACJ,iBAAA,EAAmB,UAAA,EACnB,QAAA,UACA,YAAA,UACA,kBAAA,WAA0B,OAAA;EA0BtB,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAyHzC,IAAA,CACL,MAAA,EAAQ,cAAA,EACR,OAAA,GAAU,qBAAA,GACT,cAAA,CAAe,eAAA;EAyHZ,GAAA,CACJ,MAAA,EAAQ,cAAA,EACR,UAAA,EAAY,UAAA,EACZ,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,cAAA;EAwCL,SAAA,CACJ,MAAA,EAAQ,cAAA,EACR,MAAA,EAAQ,YAAA,IACR,MAAA,WACC,OAAA;EAsCG,YAAA,CAAa,QAAA,WAAmB,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","names":[],"sources":["../src/memory.ts"],"mappings":";;;;;;cAgCa,WAAA,SAAoB,mBAAA;EAE/B,OAAA,EAAS,MAAA,SAEP,MAAA,SAAe,MAAA,UAAgB,UAAA,EAAY,UAAA;EAG7C,MAAA,EAAQ,MAAA,SAAe,MAAA,0BAAgC,UAAA;EAEvD,WAAA,CAAY,KAAA,GAAQ,kBAAA;;EAKd,oBAAA,CACJ,iBAAA,EAAmB,UAAA,EACnB,QAAA,UACA,YAAA,UACA,kBAAA,WAA0B,OAAA;EA0BtB,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAyHzC,IAAA,CACL,MAAA,EAAQ,cAAA,EACR,OAAA,GAAU,qBAAA,GACT,cAAA,CAAe,eAAA;EAyHZ,GAAA,CACJ,MAAA,EAAQ,cAAA,EACR,UAAA,EAAY,UAAA,EACZ,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,cAAA;EAsCL,SAAA,CACJ,MAAA,EAAQ,cAAA,EACR,MAAA,EAAQ,YAAA,IACR,MAAA,WACC,OAAA;EAoCG,YAAA,CAAa,QAAA,WAAmB,OAAA;AAAA"}
1
+ {"version":3,"file":"memory.d.ts","names":[],"sources":["../src/memory.ts"],"mappings":";;;;;;cAgCa,WAAA,SAAoB,mBAAA;EAE/B,OAAA,EAAS,MAAA,SAEP,MAAA,SAAe,MAAA,UAAgB,UAAA,EAAY,UAAA;EAG7C,MAAA,EAAQ,MAAA,SAAe,MAAA,0BAAgC,UAAA;EAEvD,WAAA,CAAY,KAAA,GAAQ,kBAAA;;EAKd,oBAAA,CACJ,iBAAA,EAAmB,UAAA,EACnB,QAAA,UACA,YAAA,UACA,kBAAA,WAA0B,OAAA;EA0BtB,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAyHzC,IAAA,CACL,MAAA,EAAQ,cAAA,EACR,OAAA,GAAU,qBAAA,GACT,cAAA,CAAe,eAAA;EAyHZ,GAAA,CACJ,MAAA,EAAQ,cAAA,EACR,UAAA,EAAY,UAAA,EACZ,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,cAAA;EAwCL,SAAA,CACJ,MAAA,EAAQ,cAAA,EACR,MAAA,EAAQ,YAAA,IACR,MAAA,WACC,OAAA;EAsCG,YAAA,CAAa,QAAA,WAAmB,OAAA;AAAA"}
package/dist/memory.js CHANGED
@@ -149,7 +149,7 @@ var MemorySaver = class extends BaseCheckpointSaver {
149
149
  const preparedCheckpoint = copyCheckpoint(checkpoint);
150
150
  const threadId = config.configurable?.thread_id;
151
151
  const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
152
- if (threadId === void 0) throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property.`);
152
+ if (threadId === void 0) throw new Error("Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })");
153
153
  if (!this.storage[threadId]) this.storage[threadId] = {};
154
154
  if (!this.storage[threadId][checkpointNamespace]) this.storage[threadId][checkpointNamespace] = {};
155
155
  const [[, serializedCheckpoint], [, serializedMetadata]] = await Promise.all([this.serde.dumpsTyped(preparedCheckpoint), this.serde.dumpsTyped(metadata)]);
@@ -168,7 +168,7 @@ var MemorySaver = class extends BaseCheckpointSaver {
168
168
  const threadId = config.configurable?.thread_id;
169
169
  const checkpointNamespace = config.configurable?.checkpoint_ns;
170
170
  const checkpointId = config.configurable?.checkpoint_id;
171
- if (threadId === void 0) throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property`);
171
+ if (threadId === void 0) throw new Error("Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })");
172
172
  if (checkpointId === void 0) throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "checkpoint_id" field in its "configurable" property.`);
173
173
  const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);
174
174
  const outerWrites_ = this.writes[outerKey];
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","names":[],"sources":["../src/memory.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n BaseCheckpointSaver,\n Checkpoint,\n CheckpointListOptions,\n CheckpointTuple,\n copyCheckpoint,\n getCheckpointId,\n maxChannelVersion,\n WRITES_IDX_MAP,\n} from \"./base.js\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport {\n CheckpointMetadata,\n CheckpointPendingWrite,\n PendingWrite,\n} from \"./types.js\";\nimport { TASKS } from \"./serde/types.js\";\n\nfunction _generateKey(\n threadId: string,\n checkpointNamespace: string,\n checkpointId: string\n) {\n return JSON.stringify([threadId, checkpointNamespace, checkpointId]);\n}\n\nfunction _parseKey(key: string) {\n const [threadId, checkpointNamespace, checkpointId] = JSON.parse(key);\n return { threadId, checkpointNamespace, checkpointId };\n}\n\nexport class MemorySaver extends BaseCheckpointSaver {\n // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping\n storage: Record<\n string,\n Record<string, Record<string, [Uint8Array, Uint8Array, string | undefined]>>\n > = {};\n\n writes: Record<string, Record<string, [string, string, Uint8Array]>> = {};\n\n constructor(serde?: SerializerProtocol) {\n super(serde);\n }\n\n /** @internal */\n async _migratePendingSends(\n mutableCheckpoint: Checkpoint,\n threadId: string,\n checkpointNs: string,\n parentCheckpointId: string\n ) {\n const deseriablizableCheckpoint = mutableCheckpoint;\n const parentKey = _generateKey(threadId, checkpointNs, parentCheckpointId);\n\n const pendingSends = await Promise.all(\n Object.values(this.writes[parentKey] ?? {})\n .filter(([_taskId, channel]) => channel === TASKS)\n .map(\n async ([_taskId, _channel, writes]) =>\n await this.serde.loadsTyped(\"json\", writes)\n )\n );\n\n deseriablizableCheckpoint.channel_values ??= {};\n deseriablizableCheckpoint.channel_values[TASKS] = pendingSends;\n\n deseriablizableCheckpoint.channel_versions ??= {};\n deseriablizableCheckpoint.channel_versions[TASKS] =\n Object.keys(deseriablizableCheckpoint.channel_versions).length > 0\n ? maxChannelVersion(\n ...Object.values(deseriablizableCheckpoint.channel_versions)\n )\n : this.getNextVersion(undefined);\n }\n\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns ?? \"\";\n let checkpoint_id = getCheckpointId(config);\n\n if (checkpoint_id) {\n const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];\n if (saved !== undefined) {\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config,\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n } else {\n const checkpoints = this.storage[thread_id]?.[checkpoint_ns];\n if (checkpoints !== undefined) {\n // eslint-disable-next-line prefer-destructuring\n checkpoint_id = Object.keys(checkpoints).sort((a, b) =>\n b.localeCompare(a)\n )[0];\n const saved = checkpoints[checkpoint_id];\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id,\n checkpoint_id,\n checkpoint_ns,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n }\n\n return undefined;\n }\n\n async *list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple> {\n // eslint-disable-next-line prefer-const\n let { before, limit, filter } = options ?? {};\n const threadIds = config.configurable?.thread_id\n ? [config.configurable?.thread_id]\n : Object.keys(this.storage);\n const configCheckpointNamespace = config.configurable?.checkpoint_ns;\n const configCheckpointId = config.configurable?.checkpoint_id;\n\n for (const threadId of threadIds) {\n for (const checkpointNamespace of Object.keys(\n this.storage[threadId] ?? {}\n )) {\n if (\n configCheckpointNamespace !== undefined &&\n checkpointNamespace !== configCheckpointNamespace\n ) {\n continue;\n }\n const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};\n const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) =>\n b[0].localeCompare(a[0])\n );\n\n for (const [\n checkpointId,\n [checkpoint, metadataStr, parentCheckpointId],\n ] of sortedCheckpoints) {\n // Filter by checkpoint ID from config\n if (configCheckpointId && checkpointId !== configCheckpointId) {\n continue;\n }\n\n // Filter by checkpoint ID from before config\n if (\n before &&\n before.configurable?.checkpoint_id &&\n checkpointId >= before.configurable.checkpoint_id\n ) {\n continue;\n }\n\n // Parse metadata\n const metadata = (await this.serde.loadsTyped(\n \"json\",\n metadataStr\n )) as CheckpointMetadata;\n\n if (\n filter &&\n !Object.entries(filter).every(\n ([key, value]) =>\n (metadata as unknown as Record<string, unknown>)[key] === value\n )\n ) {\n continue;\n }\n\n // Limit search results\n if (limit !== undefined) {\n if (limit <= 0) break;\n limit -= 1;\n }\n\n const key = _generateKey(threadId, checkpointNamespace, checkpointId);\n const writes = Object.values(this.writes[key] || {});\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n writes.map(async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n })\n );\n\n const deserializedCheckpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (\n deserializedCheckpoint.v < 4 &&\n parentCheckpointId !== undefined\n ) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n threadId,\n checkpointNamespace,\n parentCheckpointId\n );\n }\n\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpointId,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n yield checkpointTuple;\n }\n }\n }\n }\n\n async put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata\n ): Promise<RunnableConfig> {\n const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns ?? \"\";\n if (threadId === undefined) {\n throw new Error(\n `Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property.`\n );\n }\n\n if (!this.storage[threadId]) {\n this.storage[threadId] = {};\n }\n if (!this.storage[threadId][checkpointNamespace]) {\n this.storage[threadId][checkpointNamespace] = {};\n }\n\n const [[, serializedCheckpoint], [, serializedMetadata]] =\n await Promise.all([\n this.serde.dumpsTyped(preparedCheckpoint),\n this.serde.dumpsTyped(metadata),\n ]);\n\n this.storage[threadId][checkpointNamespace][checkpoint.id] = [\n serializedCheckpoint,\n serializedMetadata,\n config.configurable?.checkpoint_id, // parent\n ];\n\n return {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpoint.id,\n },\n };\n }\n\n async putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void> {\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns;\n const checkpointId = config.configurable?.checkpoint_id;\n if (threadId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property`\n );\n }\n if (checkpointId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"checkpoint_id\" field in its \"configurable\" property.`\n );\n }\n const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);\n const outerWrites_ = this.writes[outerKey];\n if (this.writes[outerKey] === undefined) {\n this.writes[outerKey] = {};\n }\n\n await Promise.all(\n writes.map(async ([channel, value], idx) => {\n const [, serializedValue] = await this.serde.dumpsTyped(value);\n const innerKey: [string, number] = [\n taskId,\n WRITES_IDX_MAP[channel] || idx,\n ];\n const innerKeyStr = `${innerKey[0]},${innerKey[1]}`;\n if (innerKey[1] >= 0 && outerWrites_ && innerKeyStr in outerWrites_) {\n return;\n }\n this.writes[outerKey][innerKeyStr] = [taskId, channel, serializedValue];\n })\n );\n }\n\n async deleteThread(threadId: string): Promise<void> {\n delete this.storage[threadId];\n for (const key of Object.keys(this.writes)) {\n if (_parseKey(key).threadId === threadId) delete this.writes[key];\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","names":[],"sources":["../src/memory.ts"],"sourcesContent":["import type { RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n BaseCheckpointSaver,\n Checkpoint,\n CheckpointListOptions,\n CheckpointTuple,\n copyCheckpoint,\n getCheckpointId,\n maxChannelVersion,\n WRITES_IDX_MAP,\n} from \"./base.js\";\nimport { SerializerProtocol } from \"./serde/base.js\";\nimport {\n CheckpointMetadata,\n CheckpointPendingWrite,\n PendingWrite,\n} from \"./types.js\";\nimport { TASKS } from \"./serde/types.js\";\n\nfunction _generateKey(\n threadId: string,\n checkpointNamespace: string,\n checkpointId: string\n) {\n return JSON.stringify([threadId, checkpointNamespace, checkpointId]);\n}\n\nfunction _parseKey(key: string) {\n const [threadId, checkpointNamespace, checkpointId] = JSON.parse(key);\n return { threadId, checkpointNamespace, checkpointId };\n}\n\nexport class MemorySaver extends BaseCheckpointSaver {\n // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping\n storage: Record<\n string,\n Record<string, Record<string, [Uint8Array, Uint8Array, string | undefined]>>\n > = {};\n\n writes: Record<string, Record<string, [string, string, Uint8Array]>> = {};\n\n constructor(serde?: SerializerProtocol) {\n super(serde);\n }\n\n /** @internal */\n async _migratePendingSends(\n mutableCheckpoint: Checkpoint,\n threadId: string,\n checkpointNs: string,\n parentCheckpointId: string\n ) {\n const deseriablizableCheckpoint = mutableCheckpoint;\n const parentKey = _generateKey(threadId, checkpointNs, parentCheckpointId);\n\n const pendingSends = await Promise.all(\n Object.values(this.writes[parentKey] ?? {})\n .filter(([_taskId, channel]) => channel === TASKS)\n .map(\n async ([_taskId, _channel, writes]) =>\n await this.serde.loadsTyped(\"json\", writes)\n )\n );\n\n deseriablizableCheckpoint.channel_values ??= {};\n deseriablizableCheckpoint.channel_values[TASKS] = pendingSends;\n\n deseriablizableCheckpoint.channel_versions ??= {};\n deseriablizableCheckpoint.channel_versions[TASKS] =\n Object.keys(deseriablizableCheckpoint.channel_versions).length > 0\n ? maxChannelVersion(\n ...Object.values(deseriablizableCheckpoint.channel_versions)\n )\n : this.getNextVersion(undefined);\n }\n\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns ?? \"\";\n let checkpoint_id = getCheckpointId(config);\n\n if (checkpoint_id) {\n const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];\n if (saved !== undefined) {\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config,\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n } else {\n const checkpoints = this.storage[thread_id]?.[checkpoint_ns];\n if (checkpoints !== undefined) {\n // eslint-disable-next-line prefer-destructuring\n checkpoint_id = Object.keys(checkpoints).sort((a, b) =>\n b.localeCompare(a)\n )[0];\n const saved = checkpoints[checkpoint_id];\n const [checkpoint, metadata, parentCheckpointId] = saved;\n const key = _generateKey(thread_id, checkpoint_ns, checkpoint_id);\n const deserializedCheckpoint: Checkpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (deserializedCheckpoint.v < 4 && parentCheckpointId !== undefined) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n thread_id,\n checkpoint_ns,\n parentCheckpointId\n );\n }\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n Object.values(this.writes[key] || {}).map(\n async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n }\n )\n );\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id,\n checkpoint_id,\n checkpoint_ns,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata: (await this.serde.loadsTyped(\n \"json\",\n metadata\n )) as CheckpointMetadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n return checkpointTuple;\n }\n }\n\n return undefined;\n }\n\n async *list(\n config: RunnableConfig,\n options?: CheckpointListOptions\n ): AsyncGenerator<CheckpointTuple> {\n // eslint-disable-next-line prefer-const\n let { before, limit, filter } = options ?? {};\n const threadIds = config.configurable?.thread_id\n ? [config.configurable?.thread_id]\n : Object.keys(this.storage);\n const configCheckpointNamespace = config.configurable?.checkpoint_ns;\n const configCheckpointId = config.configurable?.checkpoint_id;\n\n for (const threadId of threadIds) {\n for (const checkpointNamespace of Object.keys(\n this.storage[threadId] ?? {}\n )) {\n if (\n configCheckpointNamespace !== undefined &&\n checkpointNamespace !== configCheckpointNamespace\n ) {\n continue;\n }\n const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};\n const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) =>\n b[0].localeCompare(a[0])\n );\n\n for (const [\n checkpointId,\n [checkpoint, metadataStr, parentCheckpointId],\n ] of sortedCheckpoints) {\n // Filter by checkpoint ID from config\n if (configCheckpointId && checkpointId !== configCheckpointId) {\n continue;\n }\n\n // Filter by checkpoint ID from before config\n if (\n before &&\n before.configurable?.checkpoint_id &&\n checkpointId >= before.configurable.checkpoint_id\n ) {\n continue;\n }\n\n // Parse metadata\n const metadata = (await this.serde.loadsTyped(\n \"json\",\n metadataStr\n )) as CheckpointMetadata;\n\n if (\n filter &&\n !Object.entries(filter).every(\n ([key, value]) =>\n (metadata as unknown as Record<string, unknown>)[key] === value\n )\n ) {\n continue;\n }\n\n // Limit search results\n if (limit !== undefined) {\n if (limit <= 0) break;\n limit -= 1;\n }\n\n const key = _generateKey(threadId, checkpointNamespace, checkpointId);\n const writes = Object.values(this.writes[key] || {});\n\n const pendingWrites: CheckpointPendingWrite[] = await Promise.all(\n writes.map(async ([taskId, channel, value]) => {\n return [\n taskId,\n channel,\n await this.serde.loadsTyped(\"json\", value),\n ];\n })\n );\n\n const deserializedCheckpoint = await this.serde.loadsTyped(\n \"json\",\n checkpoint\n );\n\n if (\n deserializedCheckpoint.v < 4 &&\n parentCheckpointId !== undefined\n ) {\n await this._migratePendingSends(\n deserializedCheckpoint,\n threadId,\n checkpointNamespace,\n parentCheckpointId\n );\n }\n\n const checkpointTuple: CheckpointTuple = {\n config: {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpointId,\n },\n },\n checkpoint: deserializedCheckpoint,\n metadata,\n pendingWrites,\n };\n if (parentCheckpointId !== undefined) {\n checkpointTuple.parentConfig = {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: parentCheckpointId,\n },\n };\n }\n yield checkpointTuple;\n }\n }\n }\n }\n\n async put(\n config: RunnableConfig,\n checkpoint: Checkpoint,\n metadata: CheckpointMetadata\n ): Promise<RunnableConfig> {\n const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns ?? \"\";\n if (threadId === undefined) {\n throw new Error(\n `Failed to put checkpoint. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. ` +\n `When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. ` +\n `Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })`\n );\n }\n\n if (!this.storage[threadId]) {\n this.storage[threadId] = {};\n }\n if (!this.storage[threadId][checkpointNamespace]) {\n this.storage[threadId][checkpointNamespace] = {};\n }\n\n const [[, serializedCheckpoint], [, serializedMetadata]] =\n await Promise.all([\n this.serde.dumpsTyped(preparedCheckpoint),\n this.serde.dumpsTyped(metadata),\n ]);\n\n this.storage[threadId][checkpointNamespace][checkpoint.id] = [\n serializedCheckpoint,\n serializedMetadata,\n config.configurable?.checkpoint_id, // parent\n ];\n\n return {\n configurable: {\n thread_id: threadId,\n checkpoint_ns: checkpointNamespace,\n checkpoint_id: checkpoint.id,\n },\n };\n }\n\n async putWrites(\n config: RunnableConfig,\n writes: PendingWrite[],\n taskId: string\n ): Promise<void> {\n const threadId = config.configurable?.thread_id;\n const checkpointNamespace = config.configurable?.checkpoint_ns;\n const checkpointId = config.configurable?.checkpoint_id;\n if (threadId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"thread_id\" field in its \"configurable\" property. ` +\n `When using a checkpointer, you must pass a \"thread_id\" so the checkpointer knows which conversation thread to persist state for. ` +\n `Example: graph.stream(input, { configurable: { thread_id: \"my-thread-id\" } })`\n );\n }\n if (checkpointId === undefined) {\n throw new Error(\n `Failed to put writes. The passed RunnableConfig is missing a required \"checkpoint_id\" field in its \"configurable\" property.`\n );\n }\n const outerKey = _generateKey(threadId, checkpointNamespace, checkpointId);\n const outerWrites_ = this.writes[outerKey];\n if (this.writes[outerKey] === undefined) {\n this.writes[outerKey] = {};\n }\n\n await Promise.all(\n writes.map(async ([channel, value], idx) => {\n const [, serializedValue] = await this.serde.dumpsTyped(value);\n const innerKey: [string, number] = [\n taskId,\n WRITES_IDX_MAP[channel] || idx,\n ];\n const innerKeyStr = `${innerKey[0]},${innerKey[1]}`;\n if (innerKey[1] >= 0 && outerWrites_ && innerKeyStr in outerWrites_) {\n return;\n }\n this.writes[outerKey][innerKeyStr] = [taskId, channel, serializedValue];\n })\n );\n }\n\n async deleteThread(threadId: string): Promise<void> {\n delete this.storage[threadId];\n for (const key of Object.keys(this.writes)) {\n if (_parseKey(key).threadId === threadId) delete this.writes[key];\n }\n }\n}\n"],"mappings":";;;AAmBA,SAAS,aACP,UACA,qBACA,cACA;AACA,QAAO,KAAK,UAAU;EAAC;EAAU;EAAqB;EAAa,CAAC;;AAGtE,SAAS,UAAU,KAAa;CAC9B,MAAM,CAAC,UAAU,qBAAqB,gBAAgB,KAAK,MAAM,IAAI;AACrE,QAAO;EAAE;EAAU;EAAqB;EAAc;;AAGxD,IAAa,cAAb,cAAiC,oBAAoB;CAEnD,UAGI,EAAE;CAEN,SAAuE,EAAE;CAEzE,YAAY,OAA4B;AACtC,QAAM,MAAM;;;CAId,MAAM,qBACJ,mBACA,UACA,cACA,oBACA;EACA,MAAM,4BAA4B;EAClC,MAAM,YAAY,aAAa,UAAU,cAAc,mBAAmB;EAE1E,MAAM,eAAe,MAAM,QAAQ,IACjC,OAAO,OAAO,KAAK,OAAO,cAAc,EAAE,CAAC,CACxC,QAAQ,CAAC,SAAS,aAAa,YAAY,MAAM,CACjD,IACC,OAAO,CAAC,SAAS,UAAU,YACzB,MAAM,KAAK,MAAM,WAAW,QAAQ,OAAO,CAC9C,CACJ;AAED,4BAA0B,mBAAmB,EAAE;AAC/C,4BAA0B,eAAe,SAAS;AAElD,4BAA0B,qBAAqB,EAAE;AACjD,4BAA0B,iBAAiB,SACzC,OAAO,KAAK,0BAA0B,iBAAiB,CAAC,SAAS,IAC7D,kBACE,GAAG,OAAO,OAAO,0BAA0B,iBAAiB,CAC7D,GACD,KAAK,eAAe,KAAA,EAAU;;CAGtC,MAAM,SAAS,QAA8D;EAC3E,MAAM,YAAY,OAAO,cAAc;EACvC,MAAM,gBAAgB,OAAO,cAAc,iBAAiB;EAC5D,IAAI,gBAAgB,gBAAgB,OAAO;AAE3C,MAAI,eAAe;GACjB,MAAM,QAAQ,KAAK,QAAQ,aAAa,iBAAiB;AACzD,OAAI,UAAU,KAAA,GAAW;IACvB,MAAM,CAAC,YAAY,UAAU,sBAAsB;IACnD,MAAM,MAAM,aAAa,WAAW,eAAe,cAAc;IACjE,MAAM,yBAAqC,MAAM,KAAK,MAAM,WAC1D,QACA,WACD;AAED,QAAI,uBAAuB,IAAI,KAAK,uBAAuB,KAAA,EACzD,OAAM,KAAK,qBACT,wBACA,WACA,eACA,mBACD;IAGH,MAAM,gBAA0C,MAAM,QAAQ,IAC5D,OAAO,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,CAAC,IACpC,OAAO,CAAC,QAAQ,SAAS,WAAW;AAClC,YAAO;MACL;MACA;MACA,MAAM,KAAK,MAAM,WAAW,QAAQ,MAAM;MAC3C;MAEJ,CACF;IACD,MAAM,kBAAmC;KACvC;KACA,YAAY;KACZ,UAAW,MAAM,KAAK,MAAM,WAC1B,QACA,SACD;KACD;KACD;AACD,QAAI,uBAAuB,KAAA,EACzB,iBAAgB,eAAe,EAC7B,cAAc;KACZ;KACA;KACA,eAAe;KAChB,EACF;AAEH,WAAO;;SAEJ;GACL,MAAM,cAAc,KAAK,QAAQ,aAAa;AAC9C,OAAI,gBAAgB,KAAA,GAAW;AAE7B,oBAAgB,OAAO,KAAK,YAAY,CAAC,MAAM,GAAG,MAChD,EAAE,cAAc,EAAE,CACnB,CAAC;IAEF,MAAM,CAAC,YAAY,UAAU,sBADf,YAAY;IAE1B,MAAM,MAAM,aAAa,WAAW,eAAe,cAAc;IACjE,MAAM,yBAAqC,MAAM,KAAK,MAAM,WAC1D,QACA,WACD;AAED,QAAI,uBAAuB,IAAI,KAAK,uBAAuB,KAAA,EACzD,OAAM,KAAK,qBACT,wBACA,WACA,eACA,mBACD;IAGH,MAAM,gBAA0C,MAAM,QAAQ,IAC5D,OAAO,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,CAAC,IACpC,OAAO,CAAC,QAAQ,SAAS,WAAW;AAClC,YAAO;MACL;MACA;MACA,MAAM,KAAK,MAAM,WAAW,QAAQ,MAAM;MAC3C;MAEJ,CACF;IACD,MAAM,kBAAmC;KACvC,QAAQ,EACN,cAAc;MACZ;MACA;MACA;MACD,EACF;KACD,YAAY;KACZ,UAAW,MAAM,KAAK,MAAM,WAC1B,QACA,SACD;KACD;KACD;AACD,QAAI,uBAAuB,KAAA,EACzB,iBAAgB,eAAe,EAC7B,cAAc;KACZ;KACA;KACA,eAAe;KAChB,EACF;AAEH,WAAO;;;;CAOb,OAAO,KACL,QACA,SACiC;EAEjC,IAAI,EAAE,QAAQ,OAAO,WAAW,WAAW,EAAE;EAC7C,MAAM,YAAY,OAAO,cAAc,YACnC,CAAC,OAAO,cAAc,UAAU,GAChC,OAAO,KAAK,KAAK,QAAQ;EAC7B,MAAM,4BAA4B,OAAO,cAAc;EACvD,MAAM,qBAAqB,OAAO,cAAc;AAEhD,OAAK,MAAM,YAAY,UACrB,MAAK,MAAM,uBAAuB,OAAO,KACvC,KAAK,QAAQ,aAAa,EAAE,CAC7B,EAAE;AACD,OACE,8BAA8B,KAAA,KAC9B,wBAAwB,0BAExB;GAEF,MAAM,cAAc,KAAK,QAAQ,YAAY,wBAAwB,EAAE;GACvE,MAAM,oBAAoB,OAAO,QAAQ,YAAY,CAAC,MAAM,GAAG,MAC7D,EAAE,GAAG,cAAc,EAAE,GAAG,CACzB;AAED,QAAK,MAAM,CACT,cACA,CAAC,YAAY,aAAa,wBACvB,mBAAmB;AAEtB,QAAI,sBAAsB,iBAAiB,mBACzC;AAIF,QACE,UACA,OAAO,cAAc,iBACrB,gBAAgB,OAAO,aAAa,cAEpC;IAIF,MAAM,WAAY,MAAM,KAAK,MAAM,WACjC,QACA,YACD;AAED,QACE,UACA,CAAC,OAAO,QAAQ,OAAO,CAAC,OACrB,CAAC,KAAK,WACJ,SAAgD,SAAS,MAC7D,CAED;AAIF,QAAI,UAAU,KAAA,GAAW;AACvB,SAAI,SAAS,EAAG;AAChB,cAAS;;IAGX,MAAM,MAAM,aAAa,UAAU,qBAAqB,aAAa;IACrE,MAAM,SAAS,OAAO,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC;IAEpD,MAAM,gBAA0C,MAAM,QAAQ,IAC5D,OAAO,IAAI,OAAO,CAAC,QAAQ,SAAS,WAAW;AAC7C,YAAO;MACL;MACA;MACA,MAAM,KAAK,MAAM,WAAW,QAAQ,MAAM;MAC3C;MACD,CACH;IAED,MAAM,yBAAyB,MAAM,KAAK,MAAM,WAC9C,QACA,WACD;AAED,QACE,uBAAuB,IAAI,KAC3B,uBAAuB,KAAA,EAEvB,OAAM,KAAK,qBACT,wBACA,UACA,qBACA,mBACD;IAGH,MAAM,kBAAmC;KACvC,QAAQ,EACN,cAAc;MACZ,WAAW;MACX,eAAe;MACf,eAAe;MAChB,EACF;KACD,YAAY;KACZ;KACA;KACD;AACD,QAAI,uBAAuB,KAAA,EACzB,iBAAgB,eAAe,EAC7B,cAAc;KACZ,WAAW;KACX,eAAe;KACf,eAAe;KAChB,EACF;AAEH,UAAM;;;;CAMd,MAAM,IACJ,QACA,YACA,UACyB;EACzB,MAAM,qBAA0C,eAAe,WAAW;EAC1E,MAAM,WAAW,OAAO,cAAc;EACtC,MAAM,sBAAsB,OAAO,cAAc,iBAAiB;AAClE,MAAI,aAAa,KAAA,EACf,OAAM,IAAI,MACR,qVAGD;AAGH,MAAI,CAAC,KAAK,QAAQ,UAChB,MAAK,QAAQ,YAAY,EAAE;AAE7B,MAAI,CAAC,KAAK,QAAQ,UAAU,qBAC1B,MAAK,QAAQ,UAAU,uBAAuB,EAAE;EAGlD,MAAM,CAAC,GAAG,uBAAuB,GAAG,uBAClC,MAAM,QAAQ,IAAI,CAChB,KAAK,MAAM,WAAW,mBAAmB,EACzC,KAAK,MAAM,WAAW,SAAS,CAChC,CAAC;AAEJ,OAAK,QAAQ,UAAU,qBAAqB,WAAW,MAAM;GAC3D;GACA;GACA,OAAO,cAAc;GACtB;AAED,SAAO,EACL,cAAc;GACZ,WAAW;GACX,eAAe;GACf,eAAe,WAAW;GAC3B,EACF;;CAGH,MAAM,UACJ,QACA,QACA,QACe;EACf,MAAM,WAAW,OAAO,cAAc;EACtC,MAAM,sBAAsB,OAAO,cAAc;EACjD,MAAM,eAAe,OAAO,cAAc;AAC1C,MAAI,aAAa,KAAA,EACf,OAAM,IAAI,MACR,iVAGD;AAEH,MAAI,iBAAiB,KAAA,EACnB,OAAM,IAAI,MACR,8HACD;EAEH,MAAM,WAAW,aAAa,UAAU,qBAAqB,aAAa;EAC1E,MAAM,eAAe,KAAK,OAAO;AACjC,MAAI,KAAK,OAAO,cAAc,KAAA,EAC5B,MAAK,OAAO,YAAY,EAAE;AAG5B,QAAM,QAAQ,IACZ,OAAO,IAAI,OAAO,CAAC,SAAS,QAAQ,QAAQ;GAC1C,MAAM,GAAG,mBAAmB,MAAM,KAAK,MAAM,WAAW,MAAM;GAC9D,MAAM,WAA6B,CACjC,QACA,eAAe,YAAY,IAC5B;GACD,MAAM,cAAc,GAAG,SAAS,GAAG,GAAG,SAAS;AAC/C,OAAI,SAAS,MAAM,KAAK,gBAAgB,eAAe,aACrD;AAEF,QAAK,OAAO,UAAU,eAAe;IAAC;IAAQ;IAAS;IAAgB;IACvE,CACH;;CAGH,MAAM,aAAa,UAAiC;AAClD,SAAO,KAAK,QAAQ;AACpB,OAAK,MAAM,OAAO,OAAO,KAAK,KAAK,OAAO,CACxC,KAAI,UAAU,IAAI,CAAC,aAAa,SAAU,QAAO,KAAK,OAAO"}
@@ -41,7 +41,7 @@ async function _reviver(value) {
41
41
  }
42
42
  if (revivedObj.method) return constructor[revivedObj.method](...revivedObj.args || []);
43
43
  else return new constructor(...revivedObj.args || []);
44
- } catch (error) {
44
+ } catch {
45
45
  return revivedObj;
46
46
  }
47
47
  else if (isLangChainSerializedObject(revivedObj)) return (0, _langchain_core_load.load)(JSON.stringify(revivedObj));
@@ -1 +1 @@
1
- {"version":3,"file":"jsonplus.cjs","names":["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\";\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 (\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 (error) {\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 // eslint-disable-next-line @typescript-eslint/ban-types\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 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 };\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
+ {"version":3,"file":"jsonplus.cjs","names":["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\";\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 (\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 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 };\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":";;;AAMA,SAAS,4BAA4B,OAAgC;AACnE,QACE,UAAU,QACV,MAAM,OAAO,KACb,MAAM,SAAS,iBACf,MAAM,QAAQ,MAAM,GAAG;;;;;;;;;;AAY3B,eAAe,SAAS,OAA0B;AAChD,KAAI,SAAS,OAAO,UAAU,SAC5B,KAAI,MAAM,QAAQ,MAAM,CAItB,QAHqB,MAAM,QAAQ,IACjC,MAAM,KAAK,SAAS,SAAS,KAAK,CAAC,CACpC;MAEI;EACL,MAAM,aAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,CACxC,YAAW,KAAK,MAAM,SAAS,EAAE;AAGnC,MAAI,WAAW,OAAO,KAAK,WAAW,SAAS,YAC7C;WAEA,WAAW,OAAO,KAClB,WAAW,SAAS,iBACpB,MAAM,QAAQ,WAAW,GAAG,CAE5B,KAAI;GACF,MAAM,kBAAkB,WAAW,GAAG,WAAW,GAAG,SAAS;GAC7D,IAAI;AAEJ,WAAQ,iBAAR;IACE,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,QACE,QAAO;;AAEX,OAAI,WAAW,OACb,QAAQ,YAAoB,WAAW,QACrC,GAAI,WAAW,QAAQ,EAAE,CAC1B;OAED,QAAO,IAAK,YAAoB,GAAI,WAAW,QAAQ,EAAE,CAAE;UAEvD;AACN,UAAO;;WAEA,4BAA4B,WAAW,CAChD,SAAA,GAAA,qBAAA,MAAY,KAAK,UAAU,WAAW,CAAC;AAGzC,SAAO;;AAGX,QAAO;;AAGT,SAAS,uBAEP,aACA,QACA,MACA,QACQ;AACR,QAAO;EACL,IAAI;EACJ,MAAM;EACN,IAAI,CAAC,YAAY,KAAK;EACtB,QAAQ,UAAU;EAClB,MAAM,QAAQ,EAAE;EAChB,QAAQ,UAAU,EAAE;EACrB;;AAGH,SAAS,SAAS,KAAe;AAC/B,KAAI,QAAQ,KAAA,EACV,QAAO;EACL,IAAI;EACJ,MAAM;EACP;UACQ,eAAe,OAAO,eAAe,IAC9C,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CACxD,MAAM,KAAK,IAAI,CAChB,CAAC;UACO,eAAe,OACxB,QAAO,uBAAuB,QAAQ,KAAA,GAAW,CAAC,IAAI,QAAQ,IAAI,MAAM,CAAC;UAChE,eAAe,MACxB,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CAAC,IAAI,QAAQ,CAAC;UAE/D,KAAK,YAAY,OAC1B,QAAO;EACL,MAAM,IAAI;EACV,MAAM,IAAI;EACX;UACQ,eAAe,WACxB,QAAO,uBAAuB,YAAY,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;KAEpE,QAAO;;AAIX,IAAa,qBAAb,MAA8D;CAC5D,OAAiB,KAAsB;AAErC,SADgB,IAAI,aAAa,CAClB,OACbA,cAAAA,UAAU,MAAM,GAAW,UAAe;AACxC,UAAO,SAAS,MAAM;IACtB,CACH;;CAGH,MAAM,WAAW,KAAyC;AACxD,MAAI,eAAe,WACjB,QAAO,CAAC,SAAS,IAAI;MAErB,QAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC;;CAIrC,MAAgB,OAAO,MAA4B;AAEjD,SAAO,SADQ,KAAK,MAAM,KAAK,CACR;;CAGzB,MAAM,WAAW,MAAc,MAAyC;AACtE,MAAI,SAAS,QACX,QAAO,OAAO,SAAS,WAAW,IAAI,aAAa,CAAC,OAAO,KAAK,GAAG;WAC1D,SAAS,OAClB,QAAO,KAAK,OACV,OAAO,SAAS,WAAW,OAAO,IAAI,aAAa,CAAC,OAAO,KAAK,CACjE;MAED,OAAM,IAAI,MAAM,+BAA+B,OAAO"}
@@ -41,7 +41,7 @@ async function _reviver(value) {
41
41
  }
42
42
  if (revivedObj.method) return constructor[revivedObj.method](...revivedObj.args || []);
43
43
  else return new constructor(...revivedObj.args || []);
44
- } catch (error) {
44
+ } catch {
45
45
  return revivedObj;
46
46
  }
47
47
  else if (isLangChainSerializedObject(revivedObj)) return load(JSON.stringify(revivedObj));
@@ -1 +1 @@
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\";\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 (\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 (error) {\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 // eslint-disable-next-line @typescript-eslint/ban-types\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 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 };\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":";;;AAMA,SAAS,4BAA4B,OAAgC;AACnE,QACE,UAAU,QACV,MAAM,OAAO,KACb,MAAM,SAAS,iBACf,MAAM,QAAQ,MAAM,GAAG;;;;;;;;;;AAY3B,eAAe,SAAS,OAA0B;AAChD,KAAI,SAAS,OAAO,UAAU,SAC5B,KAAI,MAAM,QAAQ,MAAM,CAItB,QAHqB,MAAM,QAAQ,IACjC,MAAM,KAAK,SAAS,SAAS,KAAK,CAAC,CACpC;MAEI;EACL,MAAM,aAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,CACxC,YAAW,KAAK,MAAM,SAAS,EAAE;AAGnC,MAAI,WAAW,OAAO,KAAK,WAAW,SAAS,YAC7C;WAEA,WAAW,OAAO,KAClB,WAAW,SAAS,iBACpB,MAAM,QAAQ,WAAW,GAAG,CAE5B,KAAI;GACF,MAAM,kBAAkB,WAAW,GAAG,WAAW,GAAG,SAAS;GAC7D,IAAI;AAEJ,WAAQ,iBAAR;IACE,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,QACE,QAAO;;AAEX,OAAI,WAAW,OACb,QAAQ,YAAoB,WAAW,QACrC,GAAI,WAAW,QAAQ,EAAE,CAC1B;OAED,QAAO,IAAK,YAAoB,GAAI,WAAW,QAAQ,EAAE,CAAE;WAEtD,OAAO;AACd,UAAO;;WAEA,4BAA4B,WAAW,CAChD,QAAO,KAAK,KAAK,UAAU,WAAW,CAAC;AAGzC,SAAO;;AAGX,QAAO;;AAGT,SAAS,uBAEP,aACA,QACA,MACA,QACQ;AACR,QAAO;EACL,IAAI;EACJ,MAAM;EACN,IAAI,CAAC,YAAY,KAAK;EACtB,QAAQ,UAAU;EAClB,MAAM,QAAQ,EAAE;EAChB,QAAQ,UAAU,EAAE;EACrB;;AAGH,SAAS,SAAS,KAAe;AAC/B,KAAI,QAAQ,KAAA,EACV,QAAO;EACL,IAAI;EACJ,MAAM;EACP;UACQ,eAAe,OAAO,eAAe,IAC9C,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CACxD,MAAM,KAAK,IAAI,CAChB,CAAC;UACO,eAAe,OACxB,QAAO,uBAAuB,QAAQ,KAAA,GAAW,CAAC,IAAI,QAAQ,IAAI,MAAM,CAAC;UAChE,eAAe,MACxB,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CAAC,IAAI,QAAQ,CAAC;UAE/D,KAAK,YAAY,OAC1B,QAAO;EACL,MAAM,IAAI;EACV,MAAM,IAAI;EACX;UACQ,eAAe,WACxB,QAAO,uBAAuB,YAAY,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;KAEpE,QAAO;;AAIX,IAAa,qBAAb,MAA8D;CAC5D,OAAiB,KAAsB;AAErC,SADgB,IAAI,aAAa,CAClB,OACb,UAAU,MAAM,GAAW,UAAe;AACxC,UAAO,SAAS,MAAM;IACtB,CACH;;CAGH,MAAM,WAAW,KAAyC;AACxD,MAAI,eAAe,WACjB,QAAO,CAAC,SAAS,IAAI;MAErB,QAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC;;CAIrC,MAAgB,OAAO,MAA4B;AAEjD,SAAO,SADQ,KAAK,MAAM,KAAK,CACR;;CAGzB,MAAM,WAAW,MAAc,MAAyC;AACtE,MAAI,SAAS,QACX,QAAO,OAAO,SAAS,WAAW,IAAI,aAAa,CAAC,OAAO,KAAK,GAAG;WAC1D,SAAS,OAClB,QAAO,KAAK,OACV,OAAO,SAAS,WAAW,OAAO,IAAI,aAAa,CAAC,OAAO,KAAK,CACjE;MAED,OAAM,IAAI,MAAM,+BAA+B,OAAO"}
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\";\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 (\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 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 };\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":";;;AAMA,SAAS,4BAA4B,OAAgC;AACnE,QACE,UAAU,QACV,MAAM,OAAO,KACb,MAAM,SAAS,iBACf,MAAM,QAAQ,MAAM,GAAG;;;;;;;;;;AAY3B,eAAe,SAAS,OAA0B;AAChD,KAAI,SAAS,OAAO,UAAU,SAC5B,KAAI,MAAM,QAAQ,MAAM,CAItB,QAHqB,MAAM,QAAQ,IACjC,MAAM,KAAK,SAAS,SAAS,KAAK,CAAC,CACpC;MAEI;EACL,MAAM,aAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,CACxC,YAAW,KAAK,MAAM,SAAS,EAAE;AAGnC,MAAI,WAAW,OAAO,KAAK,WAAW,SAAS,YAC7C;WAEA,WAAW,OAAO,KAClB,WAAW,SAAS,iBACpB,MAAM,QAAQ,WAAW,GAAG,CAE5B,KAAI;GACF,MAAM,kBAAkB,WAAW,GAAG,WAAW,GAAG,SAAS;GAC7D,IAAI;AAEJ,WAAQ,iBAAR;IACE,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,KAAK;AACH,mBAAc;AACd;IACF,QACE,QAAO;;AAEX,OAAI,WAAW,OACb,QAAQ,YAAoB,WAAW,QACrC,GAAI,WAAW,QAAQ,EAAE,CAC1B;OAED,QAAO,IAAK,YAAoB,GAAI,WAAW,QAAQ,EAAE,CAAE;UAEvD;AACN,UAAO;;WAEA,4BAA4B,WAAW,CAChD,QAAO,KAAK,KAAK,UAAU,WAAW,CAAC;AAGzC,SAAO;;AAGX,QAAO;;AAGT,SAAS,uBAEP,aACA,QACA,MACA,QACQ;AACR,QAAO;EACL,IAAI;EACJ,MAAM;EACN,IAAI,CAAC,YAAY,KAAK;EACtB,QAAQ,UAAU;EAClB,MAAM,QAAQ,EAAE;EAChB,QAAQ,UAAU,EAAE;EACrB;;AAGH,SAAS,SAAS,KAAe;AAC/B,KAAI,QAAQ,KAAA,EACV,QAAO;EACL,IAAI;EACJ,MAAM;EACP;UACQ,eAAe,OAAO,eAAe,IAC9C,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CACxD,MAAM,KAAK,IAAI,CAChB,CAAC;UACO,eAAe,OACxB,QAAO,uBAAuB,QAAQ,KAAA,GAAW,CAAC,IAAI,QAAQ,IAAI,MAAM,CAAC;UAChE,eAAe,MACxB,QAAO,uBAAuB,IAAI,aAAa,KAAA,GAAW,CAAC,IAAI,QAAQ,CAAC;UAE/D,KAAK,YAAY,OAC1B,QAAO;EACL,MAAM,IAAI;EACV,MAAM,IAAI;EACX;UACQ,eAAe,WACxB,QAAO,uBAAuB,YAAY,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;KAEpE,QAAO;;AAIX,IAAa,qBAAb,MAA8D;CAC5D,OAAiB,KAAsB;AAErC,SADgB,IAAI,aAAa,CAClB,OACb,UAAU,MAAM,GAAW,UAAe;AACxC,UAAO,SAAS,MAAM;IACtB,CACH;;CAGH,MAAM,WAAW,KAAyC;AACxD,MAAI,eAAe,WACjB,QAAO,CAAC,SAAS,IAAI;MAErB,QAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC;;CAIrC,MAAgB,OAAO,MAA4B;AAEjD,SAAO,SADQ,KAAK,MAAM,KAAK,CACR;;CAGzB,MAAM,WAAW,MAAc,MAAyC;AACtE,MAAI,SAAS,QACX,QAAO,OAAO,SAAS,WAAW,IAAI,aAAa,CAAC,OAAO,KAAK,GAAG;WAC1D,SAAS,OAClB,QAAO,KAAK,OACV,OAAO,SAAS,WAAW,OAAO,IAAI,aAAa,CAAC,OAAO,KAAK,CACjE;MAED,OAAM,IAAI,MAAM,+BAA+B,OAAO"}
@@ -1 +1 @@
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// 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}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS"}
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// 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}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS"}
@@ -1 +1 @@
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// 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}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS"}
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// 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}\n"],"mappings":";AAAA,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,YAAY;AACzB,MAAa,YAAY;AACzB,MAAa,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.cjs","names":[],"sources":["../../src/store/base.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Embeddings } from \"@langchain/core/embeddings\";\n\n/**\n * Error thrown when an invalid namespace is provided.\n */\nexport class InvalidNamespaceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvalidNamespaceError\";\n }\n}\n\n/**\n * Validates the provided namespace.\n * @param namespace The namespace to validate.\n * @throws {InvalidNamespaceError} If the namespace is invalid.\n */\nfunction validateNamespace(namespace: string[]): void {\n if (namespace.length === 0) {\n throw new InvalidNamespaceError(\"Namespace cannot be empty.\");\n }\n for (const label of namespace) {\n if (typeof label !== \"string\") {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels ` +\n `must be strings, but got ${typeof label}.`\n );\n }\n if (label.includes(\".\")) {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels cannot contain periods ('.').`\n );\n }\n if (label === \"\") {\n throw new InvalidNamespaceError(\n `Namespace labels cannot be empty strings. Got ${label} in ${namespace}`\n );\n }\n }\n if (namespace[0] === \"langgraph\") {\n throw new InvalidNamespaceError(\n `Root label for namespace cannot be \"langgraph\". Got: ${namespace}`\n );\n }\n}\n\n/**\n * Represents a stored item with metadata.\n */\nexport interface Item {\n /**\n * The stored data as an object. Keys are filterable.\n */\n value: Record<string, any>;\n /**\n * Unique identifier within the namespace.\n */\n key: string;\n /**\n * Hierarchical path defining the collection in which this document resides.\n * Represented as an array of strings, allowing for nested categorization.\n * For example: [\"documents\", \"user123\"]\n */\n namespace: string[];\n /**\n * Timestamp of item creation.\n */\n createdAt: Date;\n /**\n * Timestamp of last update.\n */\n updatedAt: Date;\n}\n\n/**\n * Represents a search result item with relevance score.\n * Extends the base Item interface with an optional similarity score.\n */\nexport interface SearchItem extends Item {\n /**\n * Relevance/similarity score if from a ranked operation.\n * Higher scores indicate better matches.\n *\n * This is typically a cosine similarity score between -1 and 1,\n * where 1 indicates identical vectors and -1 indicates opposite vectors.\n */\n score?: number;\n}\n\n/**\n * Operation to retrieve an item by namespace and ID.\n */\nexport interface GetOperation {\n /**\n * Hierarchical path for the item.\n *\n * @example\n * // Get a user profile\n * namespace: [\"users\", \"profiles\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier within the namespace.\n * Together with namespace forms the complete path to the item.\n *\n * @example\n * key: \"user123\" // For a user profile\n * key: \"doc456\" // For a document\n */\n key: string;\n}\n\n/**\n * Operation to search for items within a namespace prefix.\n */\nexport interface SearchOperation {\n /**\n * Hierarchical path prefix to search within.\n * Only items under this prefix will be searched.\n *\n * @example\n * // Search all user documents\n * namespacePrefix: [\"users\", \"documents\"]\n *\n * // Search everything\n * namespacePrefix: []\n */\n namespacePrefix: string[];\n\n /**\n * Key-value pairs to filter results based on exact matches or comparison operators.\n *\n * Supports both exact matches and operator-based comparisons:\n * - $eq: Equal to (same as direct value comparison)\n * - $ne: Not equal to\n * - $gt: Greater than\n * - $gte: Greater than or equal to\n * - $lt: Less than\n * - $lte: Less than or equal to\n *\n * @example\n * // Exact match\n * filter: { status: \"active\" }\n *\n * // With operators\n * filter: { score: { $gt: 4.99 } }\n *\n * // Multiple conditions\n * filter: {\n * score: { $gte: 3.0 },\n * color: \"red\"\n * }\n */\n filter?: Record<string, any>;\n\n /**\n * Maximum number of items to return.\n * @default 10\n */\n limit?: number;\n\n /**\n * Number of items to skip before returning results.\n * Useful for pagination.\n * @default 0\n */\n offset?: number;\n\n /**\n * Natural language search query for semantic search.\n * When provided, results will be ranked by relevance to this query\n * using vector similarity search.\n *\n * @example\n * // Find technical documentation about APIs\n * query: \"technical documentation about REST APIs\"\n *\n * // Find recent ML papers\n * query: \"machine learning papers from 2023\"\n */\n query?: string;\n}\n\n/**\n * Operation to store, update, or delete an item.\n */\nexport interface PutOperation {\n /**\n * Hierarchical path for the item.\n * Acts as a folder-like structure to organize items.\n * Each element represents one level in the hierarchy.\n *\n * @example\n * // Root level documents\n * namespace: [\"documents\"]\n *\n * // User-specific documents\n * namespace: [\"documents\", \"user123\"]\n *\n * // Nested cache structure\n * namespace: [\"cache\", \"docs\", \"v1\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier for the document within its namespace.\n * Together with namespace forms the complete path to the item.\n *\n * Example: If namespace is [\"documents\", \"user123\"] and key is \"report1\",\n * the full path would effectively be \"documents/user123/report1\"\n */\n key: string;\n\n /**\n * Data to be stored, or null to delete the item.\n * Must be a JSON-serializable object with string keys.\n * Setting to null signals that the item should be deleted.\n *\n * @example\n * {\n * field1: \"string value\",\n * field2: 123,\n * nested: { can: \"contain\", any: \"serializable data\" }\n * }\n */\n value: Record<string, any> | null;\n\n /**\n * Controls how the item's fields are indexed for search operations.\n *\n * - undefined: Uses store's default indexing configuration\n * - false: Disables indexing for this item\n * - string[]: List of field paths to index\n *\n * Path syntax supports:\n * - Nested fields: \"metadata.title\"\n * - Array access: \"chapters[*].content\" (each indexed separately)\n * - Specific indices: \"authors[0].name\"\n *\n * @example\n * // Index specific fields\n * index: [\"metadata.title\", \"chapters[*].content\"]\n *\n * // Disable indexing\n * index: false\n */\n index?: false | string[];\n}\n\n/**\n * Operation to list and filter namespaces in the store.\n */\nexport interface ListNamespacesOperation {\n matchConditions?: MatchCondition[];\n maxDepth?: number;\n limit: number;\n offset: number;\n}\n\nexport type NameSpacePath = (string | \"*\")[];\n\nexport type NamespaceMatchType = \"prefix\" | \"suffix\";\n\nexport interface MatchCondition {\n matchType: NamespaceMatchType;\n path: NameSpacePath;\n}\n\nexport type Operation =\n | GetOperation\n | SearchOperation\n | PutOperation\n | ListNamespacesOperation;\n\nexport type OperationResults<Tuple extends readonly Operation[]> = {\n [K in keyof Tuple]: Tuple[K] extends PutOperation\n ? void\n : Tuple[K] extends SearchOperation\n ? SearchItem[]\n : Tuple[K] extends GetOperation\n ? Item | null\n : Tuple[K] extends ListNamespacesOperation\n ? string[][]\n : never;\n};\n\n/**\n * Configuration for indexing documents for semantic search in the store.\n *\n * This configures how documents are embedded and indexed for vector similarity search.\n */\nexport interface IndexConfig {\n /**\n * Number of dimensions in the embedding vectors.\n *\n * Common embedding model dimensions:\n * - OpenAI text-embedding-3-large: 256, 1024, or 3072\n * - OpenAI text-embedding-3-small: 512 or 1536\n * - OpenAI text-embedding-ada-002: 1536\n * - Cohere embed-english-v3.0: 1024\n * - Cohere embed-english-light-v3.0: 384\n * - Cohere embed-multilingual-v3.0: 1024\n * - Cohere embed-multilingual-light-v3.0: 384\n */\n dims: number;\n\n /**\n * The embeddings model to use for generating vectors.\n * This should be a LangChain Embeddings implementation.\n */\n embeddings: Embeddings;\n\n /**\n * Fields to extract text from for embedding generation.\n *\n * Path syntax supports:\n * - Simple field access: \"field\"\n * - Nested fields: \"metadata.title\"\n * - Array indexing:\n * - All elements: \"chapters[*].content\"\n * - Specific index: \"authors[0].name\"\n * - Last element: \"array[-1]\"\n *\n * @default [\"$\"] Embeds the entire document as one vector\n */\n fields?: string[];\n}\n\n/**\n * Utility function to get text at a specific JSON path\n */\nexport function getTextAtPath(obj: any, path: string): string[] {\n const parts = path.split(\".\");\n let current: any = obj;\n\n for (const part of parts) {\n if (part.includes(\"[\")) {\n const [arrayName, indexStr] = part.split(\"[\");\n const index = indexStr.replace(\"]\", \"\");\n\n if (!current[arrayName]) return [];\n\n if (index === \"*\") {\n const results: string[] = [];\n for (const item of current[arrayName]) {\n if (typeof item === \"string\") results.push(item);\n }\n return results;\n }\n\n const idx = parseInt(index, 10);\n if (Number.isNaN(idx)) return [];\n current = current[arrayName][idx];\n } else {\n current = current[part];\n }\n\n if (current === undefined) return [];\n }\n\n return typeof current === \"string\" ? [current] : [];\n}\n\n/**\n * Tokenizes a JSON path into parts\n */\nexport function tokenizePath(path: string): string[] {\n return path.split(\".\");\n}\n\n/**\n * Abstract base class for persistent key-value stores.\n *\n * Stores enable persistence and memory that can be shared across threads,\n * scoped to user IDs, assistant IDs, or other arbitrary namespaces.\n *\n * Features:\n * - Hierarchical namespaces for organization\n * - Key-value storage with metadata\n * - Vector similarity search (if configured)\n * - Filtering and pagination\n */\nexport abstract class BaseStore {\n /**\n * Execute multiple operations in a single batch.\n * This is more efficient than executing operations individually.\n *\n * @param operations Array of operations to execute\n * @returns Promise resolving to results matching the operations\n */\n abstract batch<Op extends Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>>;\n\n /**\n * Retrieve a single item by its namespace and key.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @returns Promise resolving to the item or null if not found\n */\n async get(namespace: string[], key: string): Promise<Item | null> {\n return (await this.batch<[GetOperation]>([{ namespace, key }]))[0];\n }\n\n /**\n * Search for items within a namespace prefix.\n * Supports both metadata filtering and vector similarity search.\n *\n * @param namespacePrefix Hierarchical path prefix to search within\n * @param options Search options for filtering and pagination\n * @returns Promise resolving to list of matching items with relevance scores\n *\n * @example\n * // Search with filters\n * await store.search([\"documents\"], {\n * filter: { type: \"report\", status: \"active\" },\n * limit: 5,\n * offset: 10\n * });\n *\n * // Vector similarity search\n * await store.search([\"users\", \"content\"], {\n * query: \"technical documentation about APIs\",\n * limit: 20\n * });\n */\n async search(\n namespacePrefix: string[],\n options: {\n filter?: Record<string, any>;\n limit?: number;\n offset?: number;\n query?: string;\n } = {}\n ): Promise<SearchItem[]> {\n const { filter, limit = 10, offset = 0, query } = options;\n return (\n await this.batch<[SearchOperation]>([\n {\n namespacePrefix,\n filter,\n limit,\n offset,\n query,\n },\n ])\n )[0];\n }\n\n /**\n * Store or update an item.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @param value Object containing the item's data\n * @param index Optional indexing configuration\n *\n * @example\n * // Simple storage\n * await store.put([\"docs\"], \"report\", { title: \"Annual Report\" });\n *\n * // With specific field indexing\n * await store.put(\n * [\"docs\"],\n * \"report\",\n * {\n * title: \"Q4 Report\",\n * chapters: [{ content: \"...\" }, { content: \"...\" }]\n * },\n * [\"title\", \"chapters[*].content\"]\n * );\n */\n async put(\n namespace: string[],\n key: string,\n value: Record<string, any>,\n index?: false | string[]\n ): Promise<void> {\n validateNamespace(namespace);\n await this.batch<[PutOperation]>([{ namespace, key, value, index }]);\n }\n\n /**\n * Delete an item from the store.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n */\n async delete(namespace: string[], key: string): Promise<void> {\n await this.batch<[PutOperation]>([{ namespace, key, value: null }]);\n }\n\n /**\n * List and filter namespaces in the store.\n * Used to explore data organization and navigate the namespace hierarchy.\n *\n * @param options Options for listing namespaces\n * @returns Promise resolving to list of namespace paths\n *\n * @example\n * // List all namespaces under \"documents\"\n * await store.listNamespaces({\n * prefix: [\"documents\"],\n * maxDepth: 2\n * });\n *\n * // List namespaces ending with \"v1\"\n * await store.listNamespaces({\n * suffix: [\"v1\"],\n * limit: 50\n * });\n */\n async listNamespaces(\n options: {\n prefix?: string[];\n suffix?: string[];\n maxDepth?: number;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<string[][]> {\n const { prefix, suffix, maxDepth, limit = 100, offset = 0 } = options;\n\n const matchConditions: MatchCondition[] = [];\n if (prefix) {\n matchConditions.push({ matchType: \"prefix\", path: prefix });\n }\n if (suffix) {\n matchConditions.push({ matchType: \"suffix\", path: suffix });\n }\n\n return (\n await this.batch<[ListNamespacesOperation]>([\n {\n matchConditions: matchConditions.length ? matchConditions : undefined,\n maxDepth,\n limit,\n offset,\n },\n ])\n )[0];\n }\n\n /**\n * Start the store. Override if initialization is needed.\n */\n start(): void | Promise<void> {}\n\n /**\n * Stop the store. Override if cleanup is needed.\n */\n stop(): void | Promise<void> {}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base.cjs","names":[],"sources":["../../src/store/base.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Embeddings } from \"@langchain/core/embeddings\";\n\n/**\n * Error thrown when an invalid namespace is provided.\n */\nexport class InvalidNamespaceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvalidNamespaceError\";\n }\n}\n\n/**\n * Validates the provided namespace.\n * @param namespace The namespace to validate.\n * @throws {InvalidNamespaceError} If the namespace is invalid.\n */\nfunction validateNamespace(namespace: string[]): void {\n if (namespace.length === 0) {\n throw new InvalidNamespaceError(\"Namespace cannot be empty.\");\n }\n for (const label of namespace) {\n if (typeof label !== \"string\") {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels ` +\n `must be strings, but got ${typeof label}.`\n );\n }\n if (label.includes(\".\")) {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels cannot contain periods ('.').`\n );\n }\n if (label === \"\") {\n throw new InvalidNamespaceError(\n `Namespace labels cannot be empty strings. Got ${label} in ${namespace}`\n );\n }\n }\n if (namespace[0] === \"langgraph\") {\n throw new InvalidNamespaceError(\n `Root label for namespace cannot be \"langgraph\". Got: ${namespace}`\n );\n }\n}\n\n/**\n * Represents a stored item with metadata.\n */\nexport interface Item {\n /**\n * The stored data as an object. Keys are filterable.\n */\n value: Record<string, any>;\n /**\n * Unique identifier within the namespace.\n */\n key: string;\n /**\n * Hierarchical path defining the collection in which this document resides.\n * Represented as an array of strings, allowing for nested categorization.\n * For example: [\"documents\", \"user123\"]\n */\n namespace: string[];\n /**\n * Timestamp of item creation.\n */\n createdAt: Date;\n /**\n * Timestamp of last update.\n */\n updatedAt: Date;\n}\n\n/**\n * Represents a search result item with relevance score.\n * Extends the base Item interface with an optional similarity score.\n */\nexport interface SearchItem extends Item {\n /**\n * Relevance/similarity score if from a ranked operation.\n * Higher scores indicate better matches.\n *\n * This is typically a cosine similarity score between -1 and 1,\n * where 1 indicates identical vectors and -1 indicates opposite vectors.\n */\n score?: number;\n}\n\n/**\n * Operation to retrieve an item by namespace and ID.\n */\nexport interface GetOperation {\n /**\n * Hierarchical path for the item.\n *\n * @example\n * // Get a user profile\n * namespace: [\"users\", \"profiles\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier within the namespace.\n * Together with namespace forms the complete path to the item.\n *\n * @example\n * key: \"user123\" // For a user profile\n * key: \"doc456\" // For a document\n */\n key: string;\n}\n\n/**\n * Operation to search for items within a namespace prefix.\n */\nexport interface SearchOperation {\n /**\n * Hierarchical path prefix to search within.\n * Only items under this prefix will be searched.\n *\n * @example\n * // Search all user documents\n * namespacePrefix: [\"users\", \"documents\"]\n *\n * // Search everything\n * namespacePrefix: []\n */\n namespacePrefix: string[];\n\n /**\n * Key-value pairs to filter results based on exact matches or comparison operators.\n *\n * Supports both exact matches and operator-based comparisons:\n * - $eq: Equal to (same as direct value comparison)\n * - $ne: Not equal to\n * - $gt: Greater than\n * - $gte: Greater than or equal to\n * - $lt: Less than\n * - $lte: Less than or equal to\n *\n * @example\n * // Exact match\n * filter: { status: \"active\" }\n *\n * // With operators\n * filter: { score: { $gt: 4.99 } }\n *\n * // Multiple conditions\n * filter: {\n * score: { $gte: 3.0 },\n * color: \"red\"\n * }\n */\n filter?: Record<string, any>;\n\n /**\n * Maximum number of items to return.\n * @default 10\n */\n limit?: number;\n\n /**\n * Number of items to skip before returning results.\n * Useful for pagination.\n * @default 0\n */\n offset?: number;\n\n /**\n * Natural language search query for semantic search.\n * When provided, results will be ranked by relevance to this query\n * using vector similarity search.\n *\n * @example\n * // Find technical documentation about APIs\n * query: \"technical documentation about REST APIs\"\n *\n * // Find recent ML papers\n * query: \"machine learning papers from 2023\"\n */\n query?: string;\n}\n\n/**\n * Operation to store, update, or delete an item.\n */\nexport interface PutOperation {\n /**\n * Hierarchical path for the item.\n * Acts as a folder-like structure to organize items.\n * Each element represents one level in the hierarchy.\n *\n * @example\n * // Root level documents\n * namespace: [\"documents\"]\n *\n * // User-specific documents\n * namespace: [\"documents\", \"user123\"]\n *\n * // Nested cache structure\n * namespace: [\"cache\", \"docs\", \"v1\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier for the document within its namespace.\n * Together with namespace forms the complete path to the item.\n *\n * Example: If namespace is [\"documents\", \"user123\"] and key is \"report1\",\n * the full path would effectively be \"documents/user123/report1\"\n */\n key: string;\n\n /**\n * Data to be stored, or null to delete the item.\n * Must be a JSON-serializable object with string keys.\n * Setting to null signals that the item should be deleted.\n *\n * @example\n * {\n * field1: \"string value\",\n * field2: 123,\n * nested: { can: \"contain\", any: \"serializable data\" }\n * }\n */\n value: Record<string, any> | null;\n\n /**\n * Controls how the item's fields are indexed for search operations.\n *\n * - undefined: Uses store's default indexing configuration\n * - false: Disables indexing for this item\n * - string[]: List of field paths to index\n *\n * Path syntax supports:\n * - Nested fields: \"metadata.title\"\n * - Array access: \"chapters[*].content\" (each indexed separately)\n * - Specific indices: \"authors[0].name\"\n *\n * @example\n * // Index specific fields\n * index: [\"metadata.title\", \"chapters[*].content\"]\n *\n * // Disable indexing\n * index: false\n */\n index?: false | string[];\n}\n\n/**\n * Operation to list and filter namespaces in the store.\n */\nexport interface ListNamespacesOperation {\n matchConditions?: MatchCondition[];\n maxDepth?: number;\n limit: number;\n offset: number;\n}\n\nexport type NameSpacePath = (string | \"*\")[];\n\nexport type NamespaceMatchType = \"prefix\" | \"suffix\";\n\nexport interface MatchCondition {\n matchType: NamespaceMatchType;\n path: NameSpacePath;\n}\n\nexport type Operation =\n | GetOperation\n | SearchOperation\n | PutOperation\n | ListNamespacesOperation;\n\nexport type OperationResults<Tuple extends readonly Operation[]> = {\n [K in keyof Tuple]: Tuple[K] extends PutOperation\n ? void\n : Tuple[K] extends SearchOperation\n ? SearchItem[]\n : Tuple[K] extends GetOperation\n ? Item | null\n : Tuple[K] extends ListNamespacesOperation\n ? string[][]\n : never;\n};\n\n/**\n * Configuration for indexing documents for semantic search in the store.\n *\n * This configures how documents are embedded and indexed for vector similarity search.\n */\nexport interface IndexConfig {\n /**\n * Number of dimensions in the embedding vectors.\n *\n * Common embedding model dimensions:\n * - OpenAI text-embedding-3-large: 256, 1024, or 3072\n * - OpenAI text-embedding-3-small: 512 or 1536\n * - OpenAI text-embedding-ada-002: 1536\n * - Cohere embed-english-v3.0: 1024\n * - Cohere embed-english-light-v3.0: 384\n * - Cohere embed-multilingual-v3.0: 1024\n * - Cohere embed-multilingual-light-v3.0: 384\n */\n dims: number;\n\n /**\n * The embeddings model to use for generating vectors.\n * This should be a LangChain Embeddings implementation.\n */\n embeddings: Embeddings;\n\n /**\n * Fields to extract text from for embedding generation.\n *\n * Path syntax supports:\n * - Simple field access: \"field\"\n * - Nested fields: \"metadata.title\"\n * - Array indexing:\n * - All elements: \"chapters[*].content\"\n * - Specific index: \"authors[0].name\"\n * - Last element: \"array[-1]\"\n *\n * @default [\"$\"] Embeds the entire document as one vector\n */\n fields?: string[];\n}\n\n/**\n * Utility function to get text at a specific JSON path\n */\nexport function getTextAtPath(obj: any, path: string): string[] {\n const parts = path.split(\".\");\n let current: any = obj;\n\n for (const part of parts) {\n if (part.includes(\"[\")) {\n const [arrayName, indexStr] = part.split(\"[\");\n const index = indexStr.replace(\"]\", \"\");\n\n if (!current[arrayName]) return [];\n\n if (index === \"*\") {\n const results: string[] = [];\n for (const item of current[arrayName]) {\n if (typeof item === \"string\") results.push(item);\n }\n return results;\n }\n\n const idx = parseInt(index, 10);\n if (Number.isNaN(idx)) return [];\n current = current[arrayName][idx];\n } else {\n current = current[part];\n }\n\n if (current === undefined) return [];\n }\n\n return typeof current === \"string\" ? [current] : [];\n}\n\n/**\n * Tokenizes a JSON path into parts\n */\nexport function tokenizePath(path: string): string[] {\n return path.split(\".\");\n}\n\n/**\n * Abstract base class for persistent key-value stores.\n *\n * Stores enable persistence and memory that can be shared across threads,\n * scoped to user IDs, assistant IDs, or other arbitrary namespaces.\n *\n * Features:\n * - Hierarchical namespaces for organization\n * - Key-value storage with metadata\n * - Vector similarity search (if configured)\n * - Filtering and pagination\n */\nexport abstract class BaseStore {\n /**\n * Execute multiple operations in a single batch.\n * This is more efficient than executing operations individually.\n *\n * @param operations Array of operations to execute\n * @returns Promise resolving to results matching the operations\n */\n abstract batch<Op extends Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>>;\n\n /**\n * Retrieve a single item by its namespace and key.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @returns Promise resolving to the item or null if not found\n */\n async get(namespace: string[], key: string): Promise<Item | null> {\n return (await this.batch<[GetOperation]>([{ namespace, key }]))[0];\n }\n\n /**\n * Search for items within a namespace prefix.\n * Supports both metadata filtering and vector similarity search.\n *\n * @param namespacePrefix Hierarchical path prefix to search within\n * @param options Search options for filtering and pagination\n * @returns Promise resolving to list of matching items with relevance scores\n *\n * @example\n * // Search with filters\n * await store.search([\"documents\"], {\n * filter: { type: \"report\", status: \"active\" },\n * limit: 5,\n * offset: 10\n * });\n *\n * // Vector similarity search\n * await store.search([\"users\", \"content\"], {\n * query: \"technical documentation about APIs\",\n * limit: 20\n * });\n */\n async search(\n namespacePrefix: string[],\n options: {\n filter?: Record<string, any>;\n limit?: number;\n offset?: number;\n query?: string;\n } = {}\n ): Promise<SearchItem[]> {\n const { filter, limit = 10, offset = 0, query } = options;\n return (\n await this.batch<[SearchOperation]>([\n {\n namespacePrefix,\n filter,\n limit,\n offset,\n query,\n },\n ])\n )[0];\n }\n\n /**\n * Store or update an item.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @param value Object containing the item's data\n * @param index Optional indexing configuration\n *\n * @example\n * // Simple storage\n * await store.put([\"docs\"], \"report\", { title: \"Annual Report\" });\n *\n * // With specific field indexing\n * await store.put(\n * [\"docs\"],\n * \"report\",\n * {\n * title: \"Q4 Report\",\n * chapters: [{ content: \"...\" }, { content: \"...\" }]\n * },\n * [\"title\", \"chapters[*].content\"]\n * );\n */\n async put(\n namespace: string[],\n key: string,\n value: Record<string, any>,\n index?: false | string[]\n ): Promise<void> {\n validateNamespace(namespace);\n await this.batch<[PutOperation]>([{ namespace, key, value, index }]);\n }\n\n /**\n * Delete an item from the store.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n */\n async delete(namespace: string[], key: string): Promise<void> {\n await this.batch<[PutOperation]>([{ namespace, key, value: null }]);\n }\n\n /**\n * List and filter namespaces in the store.\n * Used to explore data organization and navigate the namespace hierarchy.\n *\n * @param options Options for listing namespaces\n * @returns Promise resolving to list of namespace paths\n *\n * @example\n * // List all namespaces under \"documents\"\n * await store.listNamespaces({\n * prefix: [\"documents\"],\n * maxDepth: 2\n * });\n *\n * // List namespaces ending with \"v1\"\n * await store.listNamespaces({\n * suffix: [\"v1\"],\n * limit: 50\n * });\n */\n async listNamespaces(\n options: {\n prefix?: string[];\n suffix?: string[];\n maxDepth?: number;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<string[][]> {\n const { prefix, suffix, maxDepth, limit = 100, offset = 0 } = options;\n\n const matchConditions: MatchCondition[] = [];\n if (prefix) {\n matchConditions.push({ matchType: \"prefix\", path: prefix });\n }\n if (suffix) {\n matchConditions.push({ matchType: \"suffix\", path: suffix });\n }\n\n return (\n await this.batch<[ListNamespacesOperation]>([\n {\n matchConditions: matchConditions.length ? matchConditions : undefined,\n maxDepth,\n limit,\n offset,\n },\n ])\n )[0];\n }\n\n /**\n * Start the store. Override if initialization is needed.\n */\n start(): void | Promise<void> {}\n\n /**\n * Stop the store. Override if cleanup is needed.\n */\n stop(): void | Promise<void> {}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.cts","names":[],"sources":["../../src/store/base.ts"],"mappings":";;;;;AAMA;cAAa,qBAAA,SAA8B,KAAA;EACzC,WAAA,CAAY,OAAA;AAAA;;;;UA2CG,IAAA;EA3CY;AA2C7B;;EAIE,KAAA,EAAO,MAAA;EAAA;;;EAIP,GAAA;EAce;;;;;EARf,SAAA;EAIW;;;EAAX,SAAA,EAAW,IAAA;EAII;AAOjB;;EAPE,SAAA,EAAW,IAAA;AAAA;;AAqBb;;;UAdiB,UAAA,SAAmB,IAAA;EAgC/B;AAML;;;;;;EA9BE,KAAA;AAAA;;;;UAMe,YAAA;EA+FA;;;;;;;EAvFf,SAAA;EAmJA;;;AAMF;;;;;EA/IE,GAAA;AAAA;;;;UAMe,eAAA;EAgJL;;;;;AAEZ;;;;;AAEA;EAxIE,eAAA;;;;;;;;;AA6IF;;;;;;;;;;;;;;;AAMA;EAzHE,MAAA,GAAS,MAAA;EAyHiB;;;;EAnH1B,KAAA;EAoHqC;;;;;EA7GrC,MAAA;EAiHU;;;;;;;;;;;;EAnGV,KAAA;AAAA;;;;UAMe,YAAA;EA4FX;;;;;;;;;;AAaN;;;;;EAzFE,SAAA;EA4GY;;;;AAqBd;;;EAxHE,GAAA;EAwHkD;AAmCpD;;;;;AAgBA;;;;;;EA7JE,KAAA,EAAO,MAAA;EAuKJ;;;;;;;;;;;;;;;;;;;EAlJH,KAAA;AAAA;;;;UAMe,uBAAA;EACf,eAAA,GAAkB,cAAA;EAClB,QAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGU,aAAA;AAAA,KAEA,kBAAA;AAAA,UAEK,cAAA;EACf,SAAA,EAAW,kBAAA;EACX,IAAA,EAAM,aAAA;AAAA;AAAA,KAGI,SAAA,GACR,YAAA,GACA,eAAA,GACA,YAAA,GACA,uBAAA;AAAA,KAEQ,gBAAA,wBAAwC,SAAA,oBACtC,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,YAAA,UAEjC,KAAA,CAAM,CAAA,UAAW,eAAA,GACjB,UAAA,KACA,KAAA,CAAM,CAAA,UAAW,YAAA,GACjB,IAAA,UACA,KAAA,CAAM,CAAA,UAAW,uBAAA;;;;;;UAUN,WAAA;EAsMmB;;;;;;;;;;;;EAzLlC,IAAA;EAwPe;;;;EAlPf,UAAA,EAAY,UAAA;;;;;;;;;;;;;;EAeZ,MAAA;AAAA;;;;iBAMc,aAAA,CAAc,GAAA,OAAU,IAAA;;;;iBAmCxB,YAAA,CAAa,IAAA;;;;;;;;;;;;;uBAgBP,SAAA;;;;;;;;WAQX,KAAA,YAAiB,SAAA,GAAA,CACxB,UAAA,EAAY,EAAA,GACX,OAAA,CAAQ,gBAAA,CAAiB,EAAA;;;;;;;;EAStB,GAAA,CAAI,SAAA,YAAqB,GAAA,WAAc,OAAA,CAAQ,IAAA;;;;;;;;;;;;;;;;;;;;;;;EA0B/C,MAAA,CACJ,eAAA,YACA,OAAA;IACE,MAAA,GAAS,MAAA;IACT,KAAA;IACA,MAAA;IACA,KAAA;EAAA,IAED,OAAA,CAAQ,UAAA;;;;;;;;;;;;;;;;;;;;;;;;EAsCL,GAAA,CACJ,SAAA,YACA,GAAA,UACA,KAAA,EAAO,MAAA,eACP,KAAA,sBACC,OAAA;;;;;;;EAWG,MAAA,CAAO,SAAA,YAAqB,GAAA,WAAc,OAAA;;;;;;;;;;;;;;;;;;;;;EAwB1C,cAAA,CACJ,OAAA;IACE,MAAA;IACA,MAAA;IACA,QAAA;IACA,KAAA;IACA,MAAA;EAAA,IAED,OAAA;;;;EA0BH,KAAA,CAAA,UAAgB,OAAA;;;;EAKhB,IAAA,CAAA,UAAe,OAAA;AAAA"}
1
+ {"version":3,"file":"base.d.cts","names":[],"sources":["../../src/store/base.ts"],"mappings":";;;;;AAMA;cAAa,qBAAA,SAA8B,KAAA;EACzC,WAAA,CAAY,OAAA;AAAA;;;;UA2CG,IAAA;EA3CY;AA2C7B;;EAIE,KAAA,EAAO,MAAA;EAAA;;;EAIP,GAAA;EAce;;;;;EARf,SAAA;EAIW;;;EAAX,SAAA,EAAW,IAAA;EAII;AAOjB;;EAPE,SAAA,EAAW,IAAA;AAAA;;AAqBb;;;UAdiB,UAAA,SAAmB,IAAA;EAgC/B;AAML;;;;;;EA9BE,KAAA;AAAA;;;;UAMe,YAAA;EA+FA;;;;;;;EAvFf,SAAA;EAmJA;;;AAMF;;;;;EA/IE,GAAA;AAAA;;;;UAMe,eAAA;EAgJL;;;;;AAEZ;;;;;AAEA;EAxIE,eAAA;;;;;;;;;AA6IF;;;;;;;;;;;;;;;AAMA;EAzHE,MAAA,GAAS,MAAA;EAyHiB;;;;EAnH1B,KAAA;EAoHqC;;;;;EA7GrC,MAAA;EAiHY;;;;;;;;;;;;EAnGZ,KAAA;AAAA;;;;UAMe,YAAA;EA4FT;;;;;;;;;;AAaR;;;;;EAzFE,SAAA;EA4GY;;;;AAqBd;;;EAxHE,GAAA;EAwHkD;AAmCpD;;;;;AAgBA;;;;;;EA7JE,KAAA,EAAO,MAAA;EAuKJ;;;;;;;;;;;;;;;;;;;EAlJH,KAAA;AAAA;;;;UAMe,uBAAA;EACf,eAAA,GAAkB,cAAA;EAClB,QAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGU,aAAA;AAAA,KAEA,kBAAA;AAAA,UAEK,cAAA;EACf,SAAA,EAAW,kBAAA;EACX,IAAA,EAAM,aAAA;AAAA;AAAA,KAGI,SAAA,GACR,YAAA,GACA,eAAA,GACA,YAAA,GACA,uBAAA;AAAA,KAEQ,gBAAA,wBAAwC,SAAA,oBACtC,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,YAAA,UAEjC,KAAA,CAAM,CAAA,UAAW,eAAA,GACf,UAAA,KACA,KAAA,CAAM,CAAA,UAAW,YAAA,GACf,IAAA,UACA,KAAA,CAAM,CAAA,UAAW,uBAAA;;;;;;UAUV,WAAA;EAsMmB;;;;;;;;;;;;EAzLlC,IAAA;EAwPe;;;;EAlPf,UAAA,EAAY,UAAA;;;;;;;;;;;;;;EAeZ,MAAA;AAAA;;;;iBAMc,aAAA,CAAc,GAAA,OAAU,IAAA;;;;iBAmCxB,YAAA,CAAa,IAAA;;;;;;;;;;;;;uBAgBP,SAAA;;;;;;;;WAQX,KAAA,YAAiB,SAAA,GAAA,CACxB,UAAA,EAAY,EAAA,GACX,OAAA,CAAQ,gBAAA,CAAiB,EAAA;;;;;;;;EAStB,GAAA,CAAI,SAAA,YAAqB,GAAA,WAAc,OAAA,CAAQ,IAAA;;;;;;;;;;;;;;;;;;;;;;;EA0B/C,MAAA,CACJ,eAAA,YACA,OAAA;IACE,MAAA,GAAS,MAAA;IACT,KAAA;IACA,MAAA;IACA,KAAA;EAAA,IAED,OAAA,CAAQ,UAAA;;;;;;;;;;;;;;;;;;;;;;;;EAsCL,GAAA,CACJ,SAAA,YACA,GAAA,UACA,KAAA,EAAO,MAAA,eACP,KAAA,sBACC,OAAA;;;;;;;EAWG,MAAA,CAAO,SAAA,YAAqB,GAAA,WAAc,OAAA;;;;;;;;;;;;;;;;;;;;;EAwB1C,cAAA,CACJ,OAAA;IACE,MAAA;IACA,MAAA;IACA,QAAA;IACA,KAAA;IACA,MAAA;EAAA,IAED,OAAA;;;;EA0BH,KAAA,CAAA,UAAgB,OAAA;;;;EAKhB,IAAA,CAAA,UAAe,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","names":[],"sources":["../../src/store/base.ts"],"mappings":";;;;;AAMA;cAAa,qBAAA,SAA8B,KAAA;EACzC,WAAA,CAAY,OAAA;AAAA;;;;UA2CG,IAAA;EA3CY;AA2C7B;;EAIE,KAAA,EAAO,MAAA;EAAA;;;EAIP,GAAA;EAce;;;;;EARf,SAAA;EAIW;;;EAAX,SAAA,EAAW,IAAA;EAII;AAOjB;;EAPE,SAAA,EAAW,IAAA;AAAA;;AAqBb;;;UAdiB,UAAA,SAAmB,IAAA;EAgC/B;AAML;;;;;;EA9BE,KAAA;AAAA;;;;UAMe,YAAA;EA+FA;;;;;;;EAvFf,SAAA;EAmJA;;;AAMF;;;;;EA/IE,GAAA;AAAA;;;;UAMe,eAAA;EAgJL;;;;;AAEZ;;;;;AAEA;EAxIE,eAAA;;;;;;;;;AA6IF;;;;;;;;;;;;;;;AAMA;EAzHE,MAAA,GAAS,MAAA;EAyHiB;;;;EAnH1B,KAAA;EAoHqC;;;;;EA7GrC,MAAA;EAiHU;;;;;;;;;;;;EAnGV,KAAA;AAAA;;;;UAMe,YAAA;EA4FX;;;;;;;;;;AAaN;;;;;EAzFE,SAAA;EA4GY;;;;AAqBd;;;EAxHE,GAAA;EAwHkD;AAmCpD;;;;;AAgBA;;;;;;EA7JE,KAAA,EAAO,MAAA;EAuKJ;;;;;;;;;;;;;;;;;;;EAlJH,KAAA;AAAA;;;;UAMe,uBAAA;EACf,eAAA,GAAkB,cAAA;EAClB,QAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGU,aAAA;AAAA,KAEA,kBAAA;AAAA,UAEK,cAAA;EACf,SAAA,EAAW,kBAAA;EACX,IAAA,EAAM,aAAA;AAAA;AAAA,KAGI,SAAA,GACR,YAAA,GACA,eAAA,GACA,YAAA,GACA,uBAAA;AAAA,KAEQ,gBAAA,wBAAwC,SAAA,oBACtC,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,YAAA,UAEjC,KAAA,CAAM,CAAA,UAAW,eAAA,GACjB,UAAA,KACA,KAAA,CAAM,CAAA,UAAW,YAAA,GACjB,IAAA,UACA,KAAA,CAAM,CAAA,UAAW,uBAAA;;;;;;UAUN,WAAA;EAsMmB;;;;;;;;;;;;EAzLlC,IAAA;EAwPe;;;;EAlPf,UAAA,EAAY,UAAA;;;;;;;;;;;;;;EAeZ,MAAA;AAAA;;;;iBAMc,aAAA,CAAc,GAAA,OAAU,IAAA;;;;iBAmCxB,YAAA,CAAa,IAAA;;;;;;;;;;;;;uBAgBP,SAAA;;;;;;;;WAQX,KAAA,YAAiB,SAAA,GAAA,CACxB,UAAA,EAAY,EAAA,GACX,OAAA,CAAQ,gBAAA,CAAiB,EAAA;;;;;;;;EAStB,GAAA,CAAI,SAAA,YAAqB,GAAA,WAAc,OAAA,CAAQ,IAAA;;;;;;;;;;;;;;;;;;;;;;;EA0B/C,MAAA,CACJ,eAAA,YACA,OAAA;IACE,MAAA,GAAS,MAAA;IACT,KAAA;IACA,MAAA;IACA,KAAA;EAAA,IAED,OAAA,CAAQ,UAAA;;;;;;;;;;;;;;;;;;;;;;;;EAsCL,GAAA,CACJ,SAAA,YACA,GAAA,UACA,KAAA,EAAO,MAAA,eACP,KAAA,sBACC,OAAA;;;;;;;EAWG,MAAA,CAAO,SAAA,YAAqB,GAAA,WAAc,OAAA;;;;;;;;;;;;;;;;;;;;;EAwB1C,cAAA,CACJ,OAAA;IACE,MAAA;IACA,MAAA;IACA,QAAA;IACA,KAAA;IACA,MAAA;EAAA,IAED,OAAA;;;;EA0BH,KAAA,CAAA,UAAgB,OAAA;;;;EAKhB,IAAA,CAAA,UAAe,OAAA;AAAA"}
1
+ {"version":3,"file":"base.d.ts","names":[],"sources":["../../src/store/base.ts"],"mappings":";;;;;AAMA;cAAa,qBAAA,SAA8B,KAAA;EACzC,WAAA,CAAY,OAAA;AAAA;;;;UA2CG,IAAA;EA3CY;AA2C7B;;EAIE,KAAA,EAAO,MAAA;EAAA;;;EAIP,GAAA;EAce;;;;;EARf,SAAA;EAIW;;;EAAX,SAAA,EAAW,IAAA;EAII;AAOjB;;EAPE,SAAA,EAAW,IAAA;AAAA;;AAqBb;;;UAdiB,UAAA,SAAmB,IAAA;EAgC/B;AAML;;;;;;EA9BE,KAAA;AAAA;;;;UAMe,YAAA;EA+FA;;;;;;;EAvFf,SAAA;EAmJA;;;AAMF;;;;;EA/IE,GAAA;AAAA;;;;UAMe,eAAA;EAgJL;;;;;AAEZ;;;;;AAEA;EAxIE,eAAA;;;;;;;;;AA6IF;;;;;;;;;;;;;;;AAMA;EAzHE,MAAA,GAAS,MAAA;EAyHiB;;;;EAnH1B,KAAA;EAoHqC;;;;;EA7GrC,MAAA;EAiHY;;;;;;;;;;;;EAnGZ,KAAA;AAAA;;;;UAMe,YAAA;EA4FT;;;;;;;;;;AAaR;;;;;EAzFE,SAAA;EA4GY;;;;AAqBd;;;EAxHE,GAAA;EAwHkD;AAmCpD;;;;;AAgBA;;;;;;EA7JE,KAAA,EAAO,MAAA;EAuKJ;;;;;;;;;;;;;;;;;;;EAlJH,KAAA;AAAA;;;;UAMe,uBAAA;EACf,eAAA,GAAkB,cAAA;EAClB,QAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,KAGU,aAAA;AAAA,KAEA,kBAAA;AAAA,UAEK,cAAA;EACf,SAAA,EAAW,kBAAA;EACX,IAAA,EAAM,aAAA;AAAA;AAAA,KAGI,SAAA,GACR,YAAA,GACA,eAAA,GACA,YAAA,GACA,uBAAA;AAAA,KAEQ,gBAAA,wBAAwC,SAAA,oBACtC,KAAA,GAAQ,KAAA,CAAM,CAAA,UAAW,YAAA,UAEjC,KAAA,CAAM,CAAA,UAAW,eAAA,GACf,UAAA,KACA,KAAA,CAAM,CAAA,UAAW,YAAA,GACf,IAAA,UACA,KAAA,CAAM,CAAA,UAAW,uBAAA;;;;;;UAUV,WAAA;EAsMmB;;;;;;;;;;;;EAzLlC,IAAA;EAwPe;;;;EAlPf,UAAA,EAAY,UAAA;;;;;;;;;;;;;;EAeZ,MAAA;AAAA;;;;iBAMc,aAAA,CAAc,GAAA,OAAU,IAAA;;;;iBAmCxB,YAAA,CAAa,IAAA;;;;;;;;;;;;;uBAgBP,SAAA;;;;;;;;WAQX,KAAA,YAAiB,SAAA,GAAA,CACxB,UAAA,EAAY,EAAA,GACX,OAAA,CAAQ,gBAAA,CAAiB,EAAA;;;;;;;;EAStB,GAAA,CAAI,SAAA,YAAqB,GAAA,WAAc,OAAA,CAAQ,IAAA;;;;;;;;;;;;;;;;;;;;;;;EA0B/C,MAAA,CACJ,eAAA,YACA,OAAA;IACE,MAAA,GAAS,MAAA;IACT,KAAA;IACA,MAAA;IACA,KAAA;EAAA,IAED,OAAA,CAAQ,UAAA;;;;;;;;;;;;;;;;;;;;;;;;EAsCL,GAAA,CACJ,SAAA,YACA,GAAA,UACA,KAAA,EAAO,MAAA,eACP,KAAA,sBACC,OAAA;;;;;;;EAWG,MAAA,CAAO,SAAA,YAAqB,GAAA,WAAc,OAAA;;;;;;;;;;;;;;;;;;;;;EAwB1C,cAAA,CACJ,OAAA;IACE,MAAA;IACA,MAAA;IACA,QAAA;IACA,KAAA;IACA,MAAA;EAAA,IAED,OAAA;;;;EA0BH,KAAA,CAAA,UAAgB,OAAA;;;;EAKhB,IAAA,CAAA,UAAe,OAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../../src/store/base.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Embeddings } from \"@langchain/core/embeddings\";\n\n/**\n * Error thrown when an invalid namespace is provided.\n */\nexport class InvalidNamespaceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvalidNamespaceError\";\n }\n}\n\n/**\n * Validates the provided namespace.\n * @param namespace The namespace to validate.\n * @throws {InvalidNamespaceError} If the namespace is invalid.\n */\nfunction validateNamespace(namespace: string[]): void {\n if (namespace.length === 0) {\n throw new InvalidNamespaceError(\"Namespace cannot be empty.\");\n }\n for (const label of namespace) {\n if (typeof label !== \"string\") {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels ` +\n `must be strings, but got ${typeof label}.`\n );\n }\n if (label.includes(\".\")) {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels cannot contain periods ('.').`\n );\n }\n if (label === \"\") {\n throw new InvalidNamespaceError(\n `Namespace labels cannot be empty strings. Got ${label} in ${namespace}`\n );\n }\n }\n if (namespace[0] === \"langgraph\") {\n throw new InvalidNamespaceError(\n `Root label for namespace cannot be \"langgraph\". Got: ${namespace}`\n );\n }\n}\n\n/**\n * Represents a stored item with metadata.\n */\nexport interface Item {\n /**\n * The stored data as an object. Keys are filterable.\n */\n value: Record<string, any>;\n /**\n * Unique identifier within the namespace.\n */\n key: string;\n /**\n * Hierarchical path defining the collection in which this document resides.\n * Represented as an array of strings, allowing for nested categorization.\n * For example: [\"documents\", \"user123\"]\n */\n namespace: string[];\n /**\n * Timestamp of item creation.\n */\n createdAt: Date;\n /**\n * Timestamp of last update.\n */\n updatedAt: Date;\n}\n\n/**\n * Represents a search result item with relevance score.\n * Extends the base Item interface with an optional similarity score.\n */\nexport interface SearchItem extends Item {\n /**\n * Relevance/similarity score if from a ranked operation.\n * Higher scores indicate better matches.\n *\n * This is typically a cosine similarity score between -1 and 1,\n * where 1 indicates identical vectors and -1 indicates opposite vectors.\n */\n score?: number;\n}\n\n/**\n * Operation to retrieve an item by namespace and ID.\n */\nexport interface GetOperation {\n /**\n * Hierarchical path for the item.\n *\n * @example\n * // Get a user profile\n * namespace: [\"users\", \"profiles\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier within the namespace.\n * Together with namespace forms the complete path to the item.\n *\n * @example\n * key: \"user123\" // For a user profile\n * key: \"doc456\" // For a document\n */\n key: string;\n}\n\n/**\n * Operation to search for items within a namespace prefix.\n */\nexport interface SearchOperation {\n /**\n * Hierarchical path prefix to search within.\n * Only items under this prefix will be searched.\n *\n * @example\n * // Search all user documents\n * namespacePrefix: [\"users\", \"documents\"]\n *\n * // Search everything\n * namespacePrefix: []\n */\n namespacePrefix: string[];\n\n /**\n * Key-value pairs to filter results based on exact matches or comparison operators.\n *\n * Supports both exact matches and operator-based comparisons:\n * - $eq: Equal to (same as direct value comparison)\n * - $ne: Not equal to\n * - $gt: Greater than\n * - $gte: Greater than or equal to\n * - $lt: Less than\n * - $lte: Less than or equal to\n *\n * @example\n * // Exact match\n * filter: { status: \"active\" }\n *\n * // With operators\n * filter: { score: { $gt: 4.99 } }\n *\n * // Multiple conditions\n * filter: {\n * score: { $gte: 3.0 },\n * color: \"red\"\n * }\n */\n filter?: Record<string, any>;\n\n /**\n * Maximum number of items to return.\n * @default 10\n */\n limit?: number;\n\n /**\n * Number of items to skip before returning results.\n * Useful for pagination.\n * @default 0\n */\n offset?: number;\n\n /**\n * Natural language search query for semantic search.\n * When provided, results will be ranked by relevance to this query\n * using vector similarity search.\n *\n * @example\n * // Find technical documentation about APIs\n * query: \"technical documentation about REST APIs\"\n *\n * // Find recent ML papers\n * query: \"machine learning papers from 2023\"\n */\n query?: string;\n}\n\n/**\n * Operation to store, update, or delete an item.\n */\nexport interface PutOperation {\n /**\n * Hierarchical path for the item.\n * Acts as a folder-like structure to organize items.\n * Each element represents one level in the hierarchy.\n *\n * @example\n * // Root level documents\n * namespace: [\"documents\"]\n *\n * // User-specific documents\n * namespace: [\"documents\", \"user123\"]\n *\n * // Nested cache structure\n * namespace: [\"cache\", \"docs\", \"v1\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier for the document within its namespace.\n * Together with namespace forms the complete path to the item.\n *\n * Example: If namespace is [\"documents\", \"user123\"] and key is \"report1\",\n * the full path would effectively be \"documents/user123/report1\"\n */\n key: string;\n\n /**\n * Data to be stored, or null to delete the item.\n * Must be a JSON-serializable object with string keys.\n * Setting to null signals that the item should be deleted.\n *\n * @example\n * {\n * field1: \"string value\",\n * field2: 123,\n * nested: { can: \"contain\", any: \"serializable data\" }\n * }\n */\n value: Record<string, any> | null;\n\n /**\n * Controls how the item's fields are indexed for search operations.\n *\n * - undefined: Uses store's default indexing configuration\n * - false: Disables indexing for this item\n * - string[]: List of field paths to index\n *\n * Path syntax supports:\n * - Nested fields: \"metadata.title\"\n * - Array access: \"chapters[*].content\" (each indexed separately)\n * - Specific indices: \"authors[0].name\"\n *\n * @example\n * // Index specific fields\n * index: [\"metadata.title\", \"chapters[*].content\"]\n *\n * // Disable indexing\n * index: false\n */\n index?: false | string[];\n}\n\n/**\n * Operation to list and filter namespaces in the store.\n */\nexport interface ListNamespacesOperation {\n matchConditions?: MatchCondition[];\n maxDepth?: number;\n limit: number;\n offset: number;\n}\n\nexport type NameSpacePath = (string | \"*\")[];\n\nexport type NamespaceMatchType = \"prefix\" | \"suffix\";\n\nexport interface MatchCondition {\n matchType: NamespaceMatchType;\n path: NameSpacePath;\n}\n\nexport type Operation =\n | GetOperation\n | SearchOperation\n | PutOperation\n | ListNamespacesOperation;\n\nexport type OperationResults<Tuple extends readonly Operation[]> = {\n [K in keyof Tuple]: Tuple[K] extends PutOperation\n ? void\n : Tuple[K] extends SearchOperation\n ? SearchItem[]\n : Tuple[K] extends GetOperation\n ? Item | null\n : Tuple[K] extends ListNamespacesOperation\n ? string[][]\n : never;\n};\n\n/**\n * Configuration for indexing documents for semantic search in the store.\n *\n * This configures how documents are embedded and indexed for vector similarity search.\n */\nexport interface IndexConfig {\n /**\n * Number of dimensions in the embedding vectors.\n *\n * Common embedding model dimensions:\n * - OpenAI text-embedding-3-large: 256, 1024, or 3072\n * - OpenAI text-embedding-3-small: 512 or 1536\n * - OpenAI text-embedding-ada-002: 1536\n * - Cohere embed-english-v3.0: 1024\n * - Cohere embed-english-light-v3.0: 384\n * - Cohere embed-multilingual-v3.0: 1024\n * - Cohere embed-multilingual-light-v3.0: 384\n */\n dims: number;\n\n /**\n * The embeddings model to use for generating vectors.\n * This should be a LangChain Embeddings implementation.\n */\n embeddings: Embeddings;\n\n /**\n * Fields to extract text from for embedding generation.\n *\n * Path syntax supports:\n * - Simple field access: \"field\"\n * - Nested fields: \"metadata.title\"\n * - Array indexing:\n * - All elements: \"chapters[*].content\"\n * - Specific index: \"authors[0].name\"\n * - Last element: \"array[-1]\"\n *\n * @default [\"$\"] Embeds the entire document as one vector\n */\n fields?: string[];\n}\n\n/**\n * Utility function to get text at a specific JSON path\n */\nexport function getTextAtPath(obj: any, path: string): string[] {\n const parts = path.split(\".\");\n let current: any = obj;\n\n for (const part of parts) {\n if (part.includes(\"[\")) {\n const [arrayName, indexStr] = part.split(\"[\");\n const index = indexStr.replace(\"]\", \"\");\n\n if (!current[arrayName]) return [];\n\n if (index === \"*\") {\n const results: string[] = [];\n for (const item of current[arrayName]) {\n if (typeof item === \"string\") results.push(item);\n }\n return results;\n }\n\n const idx = parseInt(index, 10);\n if (Number.isNaN(idx)) return [];\n current = current[arrayName][idx];\n } else {\n current = current[part];\n }\n\n if (current === undefined) return [];\n }\n\n return typeof current === \"string\" ? [current] : [];\n}\n\n/**\n * Tokenizes a JSON path into parts\n */\nexport function tokenizePath(path: string): string[] {\n return path.split(\".\");\n}\n\n/**\n * Abstract base class for persistent key-value stores.\n *\n * Stores enable persistence and memory that can be shared across threads,\n * scoped to user IDs, assistant IDs, or other arbitrary namespaces.\n *\n * Features:\n * - Hierarchical namespaces for organization\n * - Key-value storage with metadata\n * - Vector similarity search (if configured)\n * - Filtering and pagination\n */\nexport abstract class BaseStore {\n /**\n * Execute multiple operations in a single batch.\n * This is more efficient than executing operations individually.\n *\n * @param operations Array of operations to execute\n * @returns Promise resolving to results matching the operations\n */\n abstract batch<Op extends Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>>;\n\n /**\n * Retrieve a single item by its namespace and key.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @returns Promise resolving to the item or null if not found\n */\n async get(namespace: string[], key: string): Promise<Item | null> {\n return (await this.batch<[GetOperation]>([{ namespace, key }]))[0];\n }\n\n /**\n * Search for items within a namespace prefix.\n * Supports both metadata filtering and vector similarity search.\n *\n * @param namespacePrefix Hierarchical path prefix to search within\n * @param options Search options for filtering and pagination\n * @returns Promise resolving to list of matching items with relevance scores\n *\n * @example\n * // Search with filters\n * await store.search([\"documents\"], {\n * filter: { type: \"report\", status: \"active\" },\n * limit: 5,\n * offset: 10\n * });\n *\n * // Vector similarity search\n * await store.search([\"users\", \"content\"], {\n * query: \"technical documentation about APIs\",\n * limit: 20\n * });\n */\n async search(\n namespacePrefix: string[],\n options: {\n filter?: Record<string, any>;\n limit?: number;\n offset?: number;\n query?: string;\n } = {}\n ): Promise<SearchItem[]> {\n const { filter, limit = 10, offset = 0, query } = options;\n return (\n await this.batch<[SearchOperation]>([\n {\n namespacePrefix,\n filter,\n limit,\n offset,\n query,\n },\n ])\n )[0];\n }\n\n /**\n * Store or update an item.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @param value Object containing the item's data\n * @param index Optional indexing configuration\n *\n * @example\n * // Simple storage\n * await store.put([\"docs\"], \"report\", { title: \"Annual Report\" });\n *\n * // With specific field indexing\n * await store.put(\n * [\"docs\"],\n * \"report\",\n * {\n * title: \"Q4 Report\",\n * chapters: [{ content: \"...\" }, { content: \"...\" }]\n * },\n * [\"title\", \"chapters[*].content\"]\n * );\n */\n async put(\n namespace: string[],\n key: string,\n value: Record<string, any>,\n index?: false | string[]\n ): Promise<void> {\n validateNamespace(namespace);\n await this.batch<[PutOperation]>([{ namespace, key, value, index }]);\n }\n\n /**\n * Delete an item from the store.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n */\n async delete(namespace: string[], key: string): Promise<void> {\n await this.batch<[PutOperation]>([{ namespace, key, value: null }]);\n }\n\n /**\n * List and filter namespaces in the store.\n * Used to explore data organization and navigate the namespace hierarchy.\n *\n * @param options Options for listing namespaces\n * @returns Promise resolving to list of namespace paths\n *\n * @example\n * // List all namespaces under \"documents\"\n * await store.listNamespaces({\n * prefix: [\"documents\"],\n * maxDepth: 2\n * });\n *\n * // List namespaces ending with \"v1\"\n * await store.listNamespaces({\n * suffix: [\"v1\"],\n * limit: 50\n * });\n */\n async listNamespaces(\n options: {\n prefix?: string[];\n suffix?: string[];\n maxDepth?: number;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<string[][]> {\n const { prefix, suffix, maxDepth, limit = 100, offset = 0 } = options;\n\n const matchConditions: MatchCondition[] = [];\n if (prefix) {\n matchConditions.push({ matchType: \"prefix\", path: prefix });\n }\n if (suffix) {\n matchConditions.push({ matchType: \"suffix\", path: suffix });\n }\n\n return (\n await this.batch<[ListNamespacesOperation]>([\n {\n matchConditions: matchConditions.length ? matchConditions : undefined,\n maxDepth,\n limit,\n offset,\n },\n ])\n )[0];\n }\n\n /**\n * Start the store. Override if initialization is needed.\n */\n start(): void | Promise<void> {}\n\n /**\n * Stop the store. Override if cleanup is needed.\n */\n stop(): void | Promise<void> {}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../src/store/base.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Embeddings } from \"@langchain/core/embeddings\";\n\n/**\n * Error thrown when an invalid namespace is provided.\n */\nexport class InvalidNamespaceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvalidNamespaceError\";\n }\n}\n\n/**\n * Validates the provided namespace.\n * @param namespace The namespace to validate.\n * @throws {InvalidNamespaceError} If the namespace is invalid.\n */\nfunction validateNamespace(namespace: string[]): void {\n if (namespace.length === 0) {\n throw new InvalidNamespaceError(\"Namespace cannot be empty.\");\n }\n for (const label of namespace) {\n if (typeof label !== \"string\") {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels ` +\n `must be strings, but got ${typeof label}.`\n );\n }\n if (label.includes(\".\")) {\n throw new InvalidNamespaceError(\n `Invalid namespace label '${label}' found in ${namespace}. Namespace labels cannot contain periods ('.').`\n );\n }\n if (label === \"\") {\n throw new InvalidNamespaceError(\n `Namespace labels cannot be empty strings. Got ${label} in ${namespace}`\n );\n }\n }\n if (namespace[0] === \"langgraph\") {\n throw new InvalidNamespaceError(\n `Root label for namespace cannot be \"langgraph\". Got: ${namespace}`\n );\n }\n}\n\n/**\n * Represents a stored item with metadata.\n */\nexport interface Item {\n /**\n * The stored data as an object. Keys are filterable.\n */\n value: Record<string, any>;\n /**\n * Unique identifier within the namespace.\n */\n key: string;\n /**\n * Hierarchical path defining the collection in which this document resides.\n * Represented as an array of strings, allowing for nested categorization.\n * For example: [\"documents\", \"user123\"]\n */\n namespace: string[];\n /**\n * Timestamp of item creation.\n */\n createdAt: Date;\n /**\n * Timestamp of last update.\n */\n updatedAt: Date;\n}\n\n/**\n * Represents a search result item with relevance score.\n * Extends the base Item interface with an optional similarity score.\n */\nexport interface SearchItem extends Item {\n /**\n * Relevance/similarity score if from a ranked operation.\n * Higher scores indicate better matches.\n *\n * This is typically a cosine similarity score between -1 and 1,\n * where 1 indicates identical vectors and -1 indicates opposite vectors.\n */\n score?: number;\n}\n\n/**\n * Operation to retrieve an item by namespace and ID.\n */\nexport interface GetOperation {\n /**\n * Hierarchical path for the item.\n *\n * @example\n * // Get a user profile\n * namespace: [\"users\", \"profiles\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier within the namespace.\n * Together with namespace forms the complete path to the item.\n *\n * @example\n * key: \"user123\" // For a user profile\n * key: \"doc456\" // For a document\n */\n key: string;\n}\n\n/**\n * Operation to search for items within a namespace prefix.\n */\nexport interface SearchOperation {\n /**\n * Hierarchical path prefix to search within.\n * Only items under this prefix will be searched.\n *\n * @example\n * // Search all user documents\n * namespacePrefix: [\"users\", \"documents\"]\n *\n * // Search everything\n * namespacePrefix: []\n */\n namespacePrefix: string[];\n\n /**\n * Key-value pairs to filter results based on exact matches or comparison operators.\n *\n * Supports both exact matches and operator-based comparisons:\n * - $eq: Equal to (same as direct value comparison)\n * - $ne: Not equal to\n * - $gt: Greater than\n * - $gte: Greater than or equal to\n * - $lt: Less than\n * - $lte: Less than or equal to\n *\n * @example\n * // Exact match\n * filter: { status: \"active\" }\n *\n * // With operators\n * filter: { score: { $gt: 4.99 } }\n *\n * // Multiple conditions\n * filter: {\n * score: { $gte: 3.0 },\n * color: \"red\"\n * }\n */\n filter?: Record<string, any>;\n\n /**\n * Maximum number of items to return.\n * @default 10\n */\n limit?: number;\n\n /**\n * Number of items to skip before returning results.\n * Useful for pagination.\n * @default 0\n */\n offset?: number;\n\n /**\n * Natural language search query for semantic search.\n * When provided, results will be ranked by relevance to this query\n * using vector similarity search.\n *\n * @example\n * // Find technical documentation about APIs\n * query: \"technical documentation about REST APIs\"\n *\n * // Find recent ML papers\n * query: \"machine learning papers from 2023\"\n */\n query?: string;\n}\n\n/**\n * Operation to store, update, or delete an item.\n */\nexport interface PutOperation {\n /**\n * Hierarchical path for the item.\n * Acts as a folder-like structure to organize items.\n * Each element represents one level in the hierarchy.\n *\n * @example\n * // Root level documents\n * namespace: [\"documents\"]\n *\n * // User-specific documents\n * namespace: [\"documents\", \"user123\"]\n *\n * // Nested cache structure\n * namespace: [\"cache\", \"docs\", \"v1\"]\n */\n namespace: string[];\n\n /**\n * Unique identifier for the document within its namespace.\n * Together with namespace forms the complete path to the item.\n *\n * Example: If namespace is [\"documents\", \"user123\"] and key is \"report1\",\n * the full path would effectively be \"documents/user123/report1\"\n */\n key: string;\n\n /**\n * Data to be stored, or null to delete the item.\n * Must be a JSON-serializable object with string keys.\n * Setting to null signals that the item should be deleted.\n *\n * @example\n * {\n * field1: \"string value\",\n * field2: 123,\n * nested: { can: \"contain\", any: \"serializable data\" }\n * }\n */\n value: Record<string, any> | null;\n\n /**\n * Controls how the item's fields are indexed for search operations.\n *\n * - undefined: Uses store's default indexing configuration\n * - false: Disables indexing for this item\n * - string[]: List of field paths to index\n *\n * Path syntax supports:\n * - Nested fields: \"metadata.title\"\n * - Array access: \"chapters[*].content\" (each indexed separately)\n * - Specific indices: \"authors[0].name\"\n *\n * @example\n * // Index specific fields\n * index: [\"metadata.title\", \"chapters[*].content\"]\n *\n * // Disable indexing\n * index: false\n */\n index?: false | string[];\n}\n\n/**\n * Operation to list and filter namespaces in the store.\n */\nexport interface ListNamespacesOperation {\n matchConditions?: MatchCondition[];\n maxDepth?: number;\n limit: number;\n offset: number;\n}\n\nexport type NameSpacePath = (string | \"*\")[];\n\nexport type NamespaceMatchType = \"prefix\" | \"suffix\";\n\nexport interface MatchCondition {\n matchType: NamespaceMatchType;\n path: NameSpacePath;\n}\n\nexport type Operation =\n | GetOperation\n | SearchOperation\n | PutOperation\n | ListNamespacesOperation;\n\nexport type OperationResults<Tuple extends readonly Operation[]> = {\n [K in keyof Tuple]: Tuple[K] extends PutOperation\n ? void\n : Tuple[K] extends SearchOperation\n ? SearchItem[]\n : Tuple[K] extends GetOperation\n ? Item | null\n : Tuple[K] extends ListNamespacesOperation\n ? string[][]\n : never;\n};\n\n/**\n * Configuration for indexing documents for semantic search in the store.\n *\n * This configures how documents are embedded and indexed for vector similarity search.\n */\nexport interface IndexConfig {\n /**\n * Number of dimensions in the embedding vectors.\n *\n * Common embedding model dimensions:\n * - OpenAI text-embedding-3-large: 256, 1024, or 3072\n * - OpenAI text-embedding-3-small: 512 or 1536\n * - OpenAI text-embedding-ada-002: 1536\n * - Cohere embed-english-v3.0: 1024\n * - Cohere embed-english-light-v3.0: 384\n * - Cohere embed-multilingual-v3.0: 1024\n * - Cohere embed-multilingual-light-v3.0: 384\n */\n dims: number;\n\n /**\n * The embeddings model to use for generating vectors.\n * This should be a LangChain Embeddings implementation.\n */\n embeddings: Embeddings;\n\n /**\n * Fields to extract text from for embedding generation.\n *\n * Path syntax supports:\n * - Simple field access: \"field\"\n * - Nested fields: \"metadata.title\"\n * - Array indexing:\n * - All elements: \"chapters[*].content\"\n * - Specific index: \"authors[0].name\"\n * - Last element: \"array[-1]\"\n *\n * @default [\"$\"] Embeds the entire document as one vector\n */\n fields?: string[];\n}\n\n/**\n * Utility function to get text at a specific JSON path\n */\nexport function getTextAtPath(obj: any, path: string): string[] {\n const parts = path.split(\".\");\n let current: any = obj;\n\n for (const part of parts) {\n if (part.includes(\"[\")) {\n const [arrayName, indexStr] = part.split(\"[\");\n const index = indexStr.replace(\"]\", \"\");\n\n if (!current[arrayName]) return [];\n\n if (index === \"*\") {\n const results: string[] = [];\n for (const item of current[arrayName]) {\n if (typeof item === \"string\") results.push(item);\n }\n return results;\n }\n\n const idx = parseInt(index, 10);\n if (Number.isNaN(idx)) return [];\n current = current[arrayName][idx];\n } else {\n current = current[part];\n }\n\n if (current === undefined) return [];\n }\n\n return typeof current === \"string\" ? [current] : [];\n}\n\n/**\n * Tokenizes a JSON path into parts\n */\nexport function tokenizePath(path: string): string[] {\n return path.split(\".\");\n}\n\n/**\n * Abstract base class for persistent key-value stores.\n *\n * Stores enable persistence and memory that can be shared across threads,\n * scoped to user IDs, assistant IDs, or other arbitrary namespaces.\n *\n * Features:\n * - Hierarchical namespaces for organization\n * - Key-value storage with metadata\n * - Vector similarity search (if configured)\n * - Filtering and pagination\n */\nexport abstract class BaseStore {\n /**\n * Execute multiple operations in a single batch.\n * This is more efficient than executing operations individually.\n *\n * @param operations Array of operations to execute\n * @returns Promise resolving to results matching the operations\n */\n abstract batch<Op extends Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>>;\n\n /**\n * Retrieve a single item by its namespace and key.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @returns Promise resolving to the item or null if not found\n */\n async get(namespace: string[], key: string): Promise<Item | null> {\n return (await this.batch<[GetOperation]>([{ namespace, key }]))[0];\n }\n\n /**\n * Search for items within a namespace prefix.\n * Supports both metadata filtering and vector similarity search.\n *\n * @param namespacePrefix Hierarchical path prefix to search within\n * @param options Search options for filtering and pagination\n * @returns Promise resolving to list of matching items with relevance scores\n *\n * @example\n * // Search with filters\n * await store.search([\"documents\"], {\n * filter: { type: \"report\", status: \"active\" },\n * limit: 5,\n * offset: 10\n * });\n *\n * // Vector similarity search\n * await store.search([\"users\", \"content\"], {\n * query: \"technical documentation about APIs\",\n * limit: 20\n * });\n */\n async search(\n namespacePrefix: string[],\n options: {\n filter?: Record<string, any>;\n limit?: number;\n offset?: number;\n query?: string;\n } = {}\n ): Promise<SearchItem[]> {\n const { filter, limit = 10, offset = 0, query } = options;\n return (\n await this.batch<[SearchOperation]>([\n {\n namespacePrefix,\n filter,\n limit,\n offset,\n query,\n },\n ])\n )[0];\n }\n\n /**\n * Store or update an item.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n * @param value Object containing the item's data\n * @param index Optional indexing configuration\n *\n * @example\n * // Simple storage\n * await store.put([\"docs\"], \"report\", { title: \"Annual Report\" });\n *\n * // With specific field indexing\n * await store.put(\n * [\"docs\"],\n * \"report\",\n * {\n * title: \"Q4 Report\",\n * chapters: [{ content: \"...\" }, { content: \"...\" }]\n * },\n * [\"title\", \"chapters[*].content\"]\n * );\n */\n async put(\n namespace: string[],\n key: string,\n value: Record<string, any>,\n index?: false | string[]\n ): Promise<void> {\n validateNamespace(namespace);\n await this.batch<[PutOperation]>([{ namespace, key, value, index }]);\n }\n\n /**\n * Delete an item from the store.\n *\n * @param namespace Hierarchical path for the item\n * @param key Unique identifier within the namespace\n */\n async delete(namespace: string[], key: string): Promise<void> {\n await this.batch<[PutOperation]>([{ namespace, key, value: null }]);\n }\n\n /**\n * List and filter namespaces in the store.\n * Used to explore data organization and navigate the namespace hierarchy.\n *\n * @param options Options for listing namespaces\n * @returns Promise resolving to list of namespace paths\n *\n * @example\n * // List all namespaces under \"documents\"\n * await store.listNamespaces({\n * prefix: [\"documents\"],\n * maxDepth: 2\n * });\n *\n * // List namespaces ending with \"v1\"\n * await store.listNamespaces({\n * suffix: [\"v1\"],\n * limit: 50\n * });\n */\n async listNamespaces(\n options: {\n prefix?: string[];\n suffix?: string[];\n maxDepth?: number;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<string[][]> {\n const { prefix, suffix, maxDepth, limit = 100, offset = 0 } = options;\n\n const matchConditions: MatchCondition[] = [];\n if (prefix) {\n matchConditions.push({ matchType: \"prefix\", path: prefix });\n }\n if (suffix) {\n matchConditions.push({ matchType: \"suffix\", path: suffix });\n }\n\n return (\n await this.batch<[ListNamespacesOperation]>([\n {\n matchConditions: matchConditions.length ? matchConditions : undefined,\n maxDepth,\n limit,\n offset,\n },\n ])\n )[0];\n }\n\n /**\n * Start the store. Override if initialization is needed.\n */\n start(): void | Promise<void> {}\n\n /**\n * Stop the store. Override if cleanup is needed.\n */\n stop(): void | Promise<void> {}\n}\n"],"mappings":";;;;AAMA,IAAa,wBAAb,cAA2C,MAAM;CAC/C,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;;;AAShB,SAAS,kBAAkB,WAA2B;AACpD,KAAI,UAAU,WAAW,EACvB,OAAM,IAAI,sBAAsB,6BAA6B;AAE/D,MAAK,MAAM,SAAS,WAAW;AAC7B,MAAI,OAAO,UAAU,SACnB,OAAM,IAAI,sBACR,4BAA4B,MAAM,aAAa,UAAU,8CAC3B,OAAO,MAAM,GAC5C;AAEH,MAAI,MAAM,SAAS,IAAI,CACrB,OAAM,IAAI,sBACR,4BAA4B,MAAM,aAAa,UAAU,kDAC1D;AAEH,MAAI,UAAU,GACZ,OAAM,IAAI,sBACR,iDAAiD,MAAM,MAAM,YAC9D;;AAGL,KAAI,UAAU,OAAO,YACnB,OAAM,IAAI,sBACR,wDAAwD,YACzD;;;;;AAkSL,SAAgB,cAAc,KAAU,MAAwB;CAC9D,MAAM,QAAQ,KAAK,MAAM,IAAI;CAC7B,IAAI,UAAe;AAEnB,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,KAAK,SAAS,IAAI,EAAE;GACtB,MAAM,CAAC,WAAW,YAAY,KAAK,MAAM,IAAI;GAC7C,MAAM,QAAQ,SAAS,QAAQ,KAAK,GAAG;AAEvC,OAAI,CAAC,QAAQ,WAAY,QAAO,EAAE;AAElC,OAAI,UAAU,KAAK;IACjB,MAAM,UAAoB,EAAE;AAC5B,SAAK,MAAM,QAAQ,QAAQ,WACzB,KAAI,OAAO,SAAS,SAAU,SAAQ,KAAK,KAAK;AAElD,WAAO;;GAGT,MAAM,MAAM,SAAS,OAAO,GAAG;AAC/B,OAAI,OAAO,MAAM,IAAI,CAAE,QAAO,EAAE;AAChC,aAAU,QAAQ,WAAW;QAE7B,WAAU,QAAQ;AAGpB,MAAI,YAAY,KAAA,EAAW,QAAO,EAAE;;AAGtC,QAAO,OAAO,YAAY,WAAW,CAAC,QAAQ,GAAG,EAAE;;;;;AAMrD,SAAgB,aAAa,MAAwB;AACnD,QAAO,KAAK,MAAM,IAAI;;;;;;;;;;;;;;AAexB,IAAsB,YAAtB,MAAgC;;;;;;;;CAmB9B,MAAM,IAAI,WAAqB,KAAmC;AAChE,UAAQ,MAAM,KAAK,MAAsB,CAAC;GAAE;GAAW;GAAK,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;CAyBlE,MAAM,OACJ,iBACA,UAKI,EAAE,EACiB;EACvB,MAAM,EAAE,QAAQ,QAAQ,IAAI,SAAS,GAAG,UAAU;AAClD,UACE,MAAM,KAAK,MAAyB,CAClC;GACE;GACA;GACA;GACA;GACA;GACD,CACF,CAAC,EACF;;;;;;;;;;;;;;;;;;;;;;;;;CA0BJ,MAAM,IACJ,WACA,KACA,OACA,OACe;AACf,oBAAkB,UAAU;AAC5B,QAAM,KAAK,MAAsB,CAAC;GAAE;GAAW;GAAK;GAAO;GAAO,CAAC,CAAC;;;;;;;;CAStE,MAAM,OAAO,WAAqB,KAA4B;AAC5D,QAAM,KAAK,MAAsB,CAAC;GAAE;GAAW;GAAK,OAAO;GAAM,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;CAuBrE,MAAM,eACJ,UAMI,EAAE,EACe;EACrB,MAAM,EAAE,QAAQ,QAAQ,UAAU,QAAQ,KAAK,SAAS,MAAM;EAE9D,MAAM,kBAAoC,EAAE;AAC5C,MAAI,OACF,iBAAgB,KAAK;GAAE,WAAW;GAAU,MAAM;GAAQ,CAAC;AAE7D,MAAI,OACF,iBAAgB,KAAK;GAAE,WAAW;GAAU,MAAM;GAAQ,CAAC;AAG7D,UACE,MAAM,KAAK,MAAiC,CAC1C;GACE,iBAAiB,gBAAgB,SAAS,kBAAkB,KAAA;GAC5D;GACA;GACA;GACD,CACF,CAAC,EACF;;;;;CAMJ,QAA8B;;;;CAK9B,OAA6B"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.cjs","names":["BaseStore","tokenizePath","compareValues","getTextAtPath"],"sources":["../../src/store/memory.ts"],"sourcesContent":["import {\n BaseStore,\n type OperationResults,\n type Item,\n type Operation,\n MatchCondition,\n ListNamespacesOperation,\n PutOperation,\n SearchOperation,\n GetOperation,\n type IndexConfig,\n type SearchItem,\n} from \"./base.js\";\nimport { tokenizePath, compareValues, getTextAtPath } from \"./utils.js\";\n\n/**\n * In-memory key-value store with optional vector search.\n *\n * A lightweight store implementation using JavaScript Maps. Supports basic\n * key-value operations and vector search when configured with embeddings.\n *\n * @example\n * ```typescript\n * // Basic key-value storage\n * const store = new InMemoryStore();\n * await store.put([\"users\", \"123\"], \"prefs\", { theme: \"dark\" });\n * const item = await store.get([\"users\", \"123\"], \"prefs\");\n *\n * // Vector search with embeddings\n * import { OpenAIEmbeddings } from \"@langchain/openai\";\n * const store = new InMemoryStore({\n * index: {\n * dims: 1536,\n * embeddings: new OpenAIEmbeddings({ modelName: \"text-embedding-3-small\" }),\n * }\n * });\n *\n * // Store documents\n * await store.put([\"docs\"], \"doc1\", { text: \"Python tutorial\" });\n * await store.put([\"docs\"], \"doc2\", { text: \"TypeScript guide\" });\n *\n * // Search by similarity\n * const results = await store.search([\"docs\"], { query: \"python programming\" });\n * ```\n *\n * **Warning**: This store keeps all data in memory. Data is lost when the process exits.\n * For persistence, use a database-backed store.\n */\nexport class InMemoryStore extends BaseStore {\n private data: Map<string, Map<string, Item>> = new Map();\n\n // Namespace -> Key -> Path/field -> Vector\n private vectors: Map<string, Map<string, Map<string, number[]>>> = new Map();\n\n private _indexConfig?: IndexConfig & {\n __tokenizedFields: Array<[string, string[]]>;\n };\n\n constructor(options?: { index?: IndexConfig }) {\n super();\n if (options?.index) {\n this._indexConfig = {\n ...options.index,\n __tokenizedFields: (options.index.fields ?? [\"$\"]).map((p) => [\n p,\n p === \"$\" ? [p] : tokenizePath(p),\n ]),\n };\n }\n }\n\n async batch<Op extends readonly Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>> {\n const results = [];\n const putOps = new Map<string, PutOperation>();\n const searchOps = new Map<number, [SearchOperation, Item[]]>();\n\n // First pass - handle gets and prepare search/put operations\n for (let i = 0; i < operations.length; i += 1) {\n const op = operations[i];\n if (\"key\" in op && \"namespace\" in op && !(\"value\" in op)) {\n // GetOperation\n results.push(this.getOperation(op));\n } else if (\"namespacePrefix\" in op) {\n // SearchOperation\n const candidates = this.filterItems(op);\n searchOps.set(i, [op, candidates]);\n results.push(null);\n } else if (\"value\" in op) {\n // PutOperation\n const key = `${op.namespace.join(\":\")}:${op.key}`;\n putOps.set(key, op);\n results.push(null);\n } else if (\"matchConditions\" in op) {\n // ListNamespacesOperation\n results.push(this.listNamespacesOperation(op));\n }\n }\n\n // Handle search operations with embeddings\n if (searchOps.size > 0) {\n if (this._indexConfig?.embeddings) {\n const queries = new Set<string>();\n for (const [op] of searchOps.values()) {\n if (op.query) queries.add(op.query);\n }\n\n // Get embeddings for all queries\n const queryEmbeddings =\n queries.size > 0\n ? await Promise.all(\n Array.from(queries).map((q) =>\n this._indexConfig!.embeddings.embedQuery(q)\n )\n )\n : [];\n const queryVectors = Object.fromEntries(\n Array.from(queries).map((q, i) => [q, queryEmbeddings[i]])\n );\n\n // Process each search operation\n for (const [i, [op, candidates]] of searchOps.entries()) {\n if (op.query && queryVectors[op.query]) {\n const queryVector = queryVectors[op.query];\n const scoredResults = this.scoreResults(\n candidates,\n queryVector,\n op.offset ?? 0,\n op.limit ?? 10\n );\n results[i] = scoredResults;\n } else {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n } else {\n // No embeddings - just paginate the filtered results\n for (const [i, [op, candidates]] of searchOps.entries()) {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n }\n\n // Handle put operations with embeddings\n if (putOps.size > 0 && this._indexConfig?.embeddings) {\n const toEmbed = this.extractTexts(Array.from(putOps.values()));\n if (Object.keys(toEmbed).length > 0) {\n const embeddings = await this._indexConfig.embeddings.embedDocuments(\n Object.keys(toEmbed)\n );\n this.insertVectors(toEmbed, embeddings);\n }\n }\n\n // Apply all put operations\n for (const op of putOps.values()) {\n this.putOperation(op);\n }\n\n return results as OperationResults<Op>;\n }\n\n private getOperation(op: GetOperation): Item | null {\n const namespaceKey = op.namespace.join(\":\");\n const item = this.data.get(namespaceKey)?.get(op.key);\n return item ?? null;\n }\n\n private putOperation(op: PutOperation): void {\n const namespaceKey = op.namespace.join(\":\");\n if (!this.data.has(namespaceKey)) {\n this.data.set(namespaceKey, new Map());\n }\n const namespaceMap = this.data.get(namespaceKey)!;\n\n if (op.value === null) {\n namespaceMap.delete(op.key);\n } else {\n const now = new Date();\n if (namespaceMap.has(op.key)) {\n const item = namespaceMap.get(op.key)!;\n item.value = op.value;\n item.updatedAt = now;\n } else {\n namespaceMap.set(op.key, {\n value: op.value,\n key: op.key,\n namespace: op.namespace,\n createdAt: now,\n updatedAt: now,\n });\n }\n }\n }\n\n private listNamespacesOperation(op: ListNamespacesOperation): string[][] {\n const allNamespaces = Array.from(this.data.keys()).map((ns) =>\n ns.split(\":\")\n );\n let namespaces = allNamespaces;\n\n if (op.matchConditions && op.matchConditions.length > 0) {\n namespaces = namespaces.filter((ns) =>\n op.matchConditions!.every((condition) => this.doesMatch(condition, ns))\n );\n }\n\n if (op.maxDepth !== undefined) {\n namespaces = Array.from(\n new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(\":\")))\n ).map((ns) => ns.split(\":\"));\n }\n\n namespaces.sort((a, b) => a.join(\":\").localeCompare(b.join(\":\")));\n\n return namespaces.slice(\n op.offset ?? 0,\n (op.offset ?? 0) + (op.limit ?? namespaces.length)\n );\n }\n\n private doesMatch(matchCondition: MatchCondition, key: string[]): boolean {\n const { matchType, path } = matchCondition;\n\n if (matchType === \"prefix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[index];\n return pElem === \"*\" || kElem === pElem;\n });\n } else if (matchType === \"suffix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[key.length - path.length + index];\n return pElem === \"*\" || kElem === pElem;\n });\n }\n\n throw new Error(`Unsupported match type: ${matchType}`);\n }\n\n private filterItems(op: SearchOperation): Item[] {\n const candidates: Item[] = [];\n for (const [namespace, items] of this.data.entries()) {\n if (namespace.startsWith(op.namespacePrefix.join(\":\"))) {\n candidates.push(...items.values());\n }\n }\n\n let filteredCandidates = candidates;\n if (op.filter) {\n filteredCandidates = candidates.filter((item) =>\n Object.entries(op.filter!).every(([key, value]) =>\n compareValues(item.value[key], value)\n )\n );\n }\n return filteredCandidates;\n }\n\n private scoreResults(\n candidates: Item[],\n queryVector: number[],\n offset: number = 0,\n limit: number = 10\n ): SearchItem[] {\n const flatItems: Item[] = [];\n const flatVectors: number[][] = [];\n const scoreless: Item[] = [];\n\n for (const item of candidates) {\n const vectors = this.getVectors(item);\n if (vectors.length) {\n for (const vector of vectors) {\n flatItems.push(item);\n flatVectors.push(vector);\n }\n } else {\n scoreless.push(item);\n }\n }\n\n const scores = this.cosineSimilarity(queryVector, flatVectors);\n\n const sortedResults = scores\n .map((score, i) => [score, flatItems[i]] as [number, Item])\n .sort((a, b) => b[0] - a[0]);\n\n const seen = new Set<string>();\n const kept: Array<[number | undefined, Item]> = [];\n\n for (const [score, item] of sortedResults) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (seen.has(key)) continue;\n\n const ix = seen.size;\n if (ix >= offset + limit) break;\n if (ix < offset) {\n seen.add(key);\n continue;\n }\n\n seen.add(key);\n kept.push([score, item]);\n }\n\n if (scoreless.length && kept.length < limit) {\n for (const item of scoreless.slice(0, limit - kept.length)) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (!seen.has(key)) {\n seen.add(key);\n kept.push([undefined, item]);\n }\n }\n }\n return kept.map(([score, item]) => ({\n ...item,\n score,\n }));\n }\n\n private paginateResults(\n results: SearchItem[],\n offset: number,\n limit: number\n ): SearchItem[] {\n return results.slice(offset, offset + limit);\n }\n\n private extractTexts(ops: PutOperation[]): {\n [text: string]: [string[], string, string][];\n } {\n if (!ops.length || !this._indexConfig) {\n return {};\n }\n\n const toEmbed: { [text: string]: [string[], string, string][] } = {};\n\n for (const op of ops) {\n if (op.value !== null && op.index !== false) {\n const paths =\n op.index === null || op.index === undefined\n ? this._indexConfig.__tokenizedFields ?? []\n : op.index.map(\n (ix) => [ix, tokenizePath(ix)] as [string, string[]]\n );\n for (const [path, field] of paths) {\n const texts = getTextAtPath(op.value, field);\n if (texts.length) {\n if (texts.length > 1) {\n texts.forEach((text, i) => {\n if (!toEmbed[text]) toEmbed[text] = [];\n toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);\n });\n } else {\n if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];\n toEmbed[texts[0]].push([op.namespace, op.key, path]);\n }\n }\n }\n }\n }\n\n return toEmbed;\n }\n\n private insertVectors(\n texts: { [text: string]: [string[], string, string][] },\n embeddings: number[][]\n ): void {\n for (const [text, metadata] of Object.entries(texts)) {\n const embedding = embeddings.shift();\n if (!embedding) {\n throw new Error(`No embedding found for text: ${text}`);\n }\n\n for (const [namespace, key, field] of metadata) {\n const namespaceKey = namespace.join(\":\");\n if (!this.vectors.has(namespaceKey)) {\n this.vectors.set(namespaceKey, new Map());\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(key)) {\n namespaceMap.set(key, new Map());\n }\n const itemMap = namespaceMap.get(key)!;\n itemMap.set(field, embedding);\n }\n }\n }\n\n private getVectors(item: Item): number[][] {\n const namespaceKey = item.namespace.join(\":\");\n const itemKey = item.key;\n if (!this.vectors.has(namespaceKey)) {\n return [];\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(itemKey)) {\n return [];\n }\n const itemMap = namespaceMap.get(itemKey)!;\n const vectors = Array.from(itemMap.values());\n if (!vectors.length) {\n return [];\n }\n return vectors;\n }\n\n private cosineSimilarity(X: number[], Y: number[][]): number[] {\n if (!Y.length) return [];\n\n // Calculate dot products for all vectors at once\n const dotProducts = Y.map((vector) =>\n vector.reduce((acc, val, i) => acc + val * X[i], 0)\n );\n\n // Calculate magnitudes\n const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));\n const magnitudes2 = Y.map((vector) =>\n Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0))\n );\n\n // Calculate similarities\n return dotProducts.map((dot, i) => {\n const magnitude2 = magnitudes2[i];\n return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;\n });\n }\n\n public get indexConfig(): IndexConfig | undefined {\n return this._indexConfig;\n }\n}\n\n/** @deprecated Alias for InMemoryStore */\nexport class MemoryStore extends InMemoryStore {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.cjs","names":["BaseStore","tokenizePath","compareValues","getTextAtPath"],"sources":["../../src/store/memory.ts"],"sourcesContent":["import {\n BaseStore,\n type OperationResults,\n type Item,\n type Operation,\n MatchCondition,\n ListNamespacesOperation,\n PutOperation,\n SearchOperation,\n GetOperation,\n type IndexConfig,\n type SearchItem,\n} from \"./base.js\";\nimport { tokenizePath, compareValues, getTextAtPath } from \"./utils.js\";\n\n/**\n * In-memory key-value store with optional vector search.\n *\n * A lightweight store implementation using JavaScript Maps. Supports basic\n * key-value operations and vector search when configured with embeddings.\n *\n * @example\n * ```typescript\n * // Basic key-value storage\n * const store = new InMemoryStore();\n * await store.put([\"users\", \"123\"], \"prefs\", { theme: \"dark\" });\n * const item = await store.get([\"users\", \"123\"], \"prefs\");\n *\n * // Vector search with embeddings\n * import { OpenAIEmbeddings } from \"@langchain/openai\";\n * const store = new InMemoryStore({\n * index: {\n * dims: 1536,\n * embeddings: new OpenAIEmbeddings({ modelName: \"text-embedding-3-small\" }),\n * }\n * });\n *\n * // Store documents\n * await store.put([\"docs\"], \"doc1\", { text: \"Python tutorial\" });\n * await store.put([\"docs\"], \"doc2\", { text: \"TypeScript guide\" });\n *\n * // Search by similarity\n * const results = await store.search([\"docs\"], { query: \"python programming\" });\n * ```\n *\n * **Warning**: This store keeps all data in memory. Data is lost when the process exits.\n * For persistence, use a database-backed store.\n */\nexport class InMemoryStore extends BaseStore {\n private data: Map<string, Map<string, Item>> = new Map();\n\n // Namespace -> Key -> Path/field -> Vector\n private vectors: Map<string, Map<string, Map<string, number[]>>> = new Map();\n\n private _indexConfig?: IndexConfig & {\n __tokenizedFields: Array<[string, string[]]>;\n };\n\n constructor(options?: { index?: IndexConfig }) {\n super();\n if (options?.index) {\n this._indexConfig = {\n ...options.index,\n __tokenizedFields: (options.index.fields ?? [\"$\"]).map((p) => [\n p,\n p === \"$\" ? [p] : tokenizePath(p),\n ]),\n };\n }\n }\n\n async batch<Op extends readonly Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>> {\n const results = [];\n const putOps = new Map<string, PutOperation>();\n const searchOps = new Map<number, [SearchOperation, Item[]]>();\n\n // First pass - handle gets and prepare search/put operations\n for (let i = 0; i < operations.length; i += 1) {\n const op = operations[i];\n if (\"key\" in op && \"namespace\" in op && !(\"value\" in op)) {\n // GetOperation\n results.push(this.getOperation(op));\n } else if (\"namespacePrefix\" in op) {\n // SearchOperation\n const candidates = this.filterItems(op);\n searchOps.set(i, [op, candidates]);\n results.push(null);\n } else if (\"value\" in op) {\n // PutOperation\n const key = `${op.namespace.join(\":\")}:${op.key}`;\n putOps.set(key, op);\n results.push(null);\n } else if (\"matchConditions\" in op) {\n // ListNamespacesOperation\n results.push(this.listNamespacesOperation(op));\n }\n }\n\n // Handle search operations with embeddings\n if (searchOps.size > 0) {\n if (this._indexConfig?.embeddings) {\n const queries = new Set<string>();\n for (const [op] of searchOps.values()) {\n if (op.query) queries.add(op.query);\n }\n\n // Get embeddings for all queries\n const queryEmbeddings =\n queries.size > 0\n ? await Promise.all(\n Array.from(queries).map((q) =>\n this._indexConfig!.embeddings.embedQuery(q)\n )\n )\n : [];\n const queryVectors = Object.fromEntries(\n Array.from(queries).map((q, i) => [q, queryEmbeddings[i]])\n );\n\n // Process each search operation\n for (const [i, [op, candidates]] of searchOps.entries()) {\n if (op.query && queryVectors[op.query]) {\n const queryVector = queryVectors[op.query];\n const scoredResults = this.scoreResults(\n candidates,\n queryVector,\n op.offset ?? 0,\n op.limit ?? 10\n );\n results[i] = scoredResults;\n } else {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n } else {\n // No embeddings - just paginate the filtered results\n for (const [i, [op, candidates]] of searchOps.entries()) {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n }\n\n // Handle put operations with embeddings\n if (putOps.size > 0 && this._indexConfig?.embeddings) {\n const toEmbed = this.extractTexts(Array.from(putOps.values()));\n if (Object.keys(toEmbed).length > 0) {\n const embeddings = await this._indexConfig.embeddings.embedDocuments(\n Object.keys(toEmbed)\n );\n this.insertVectors(toEmbed, embeddings);\n }\n }\n\n // Apply all put operations\n for (const op of putOps.values()) {\n this.putOperation(op);\n }\n\n return results as OperationResults<Op>;\n }\n\n private getOperation(op: GetOperation): Item | null {\n const namespaceKey = op.namespace.join(\":\");\n const item = this.data.get(namespaceKey)?.get(op.key);\n return item ?? null;\n }\n\n private putOperation(op: PutOperation): void {\n const namespaceKey = op.namespace.join(\":\");\n if (!this.data.has(namespaceKey)) {\n this.data.set(namespaceKey, new Map());\n }\n const namespaceMap = this.data.get(namespaceKey)!;\n\n if (op.value === null) {\n namespaceMap.delete(op.key);\n } else {\n const now = new Date();\n if (namespaceMap.has(op.key)) {\n const item = namespaceMap.get(op.key)!;\n item.value = op.value;\n item.updatedAt = now;\n } else {\n namespaceMap.set(op.key, {\n value: op.value,\n key: op.key,\n namespace: op.namespace,\n createdAt: now,\n updatedAt: now,\n });\n }\n }\n }\n\n private listNamespacesOperation(op: ListNamespacesOperation): string[][] {\n const allNamespaces = Array.from(this.data.keys()).map((ns) =>\n ns.split(\":\")\n );\n let namespaces = allNamespaces;\n\n if (op.matchConditions && op.matchConditions.length > 0) {\n namespaces = namespaces.filter((ns) =>\n op.matchConditions!.every((condition) => this.doesMatch(condition, ns))\n );\n }\n\n if (op.maxDepth !== undefined) {\n namespaces = Array.from(\n new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(\":\")))\n ).map((ns) => ns.split(\":\"));\n }\n\n namespaces.sort((a, b) => a.join(\":\").localeCompare(b.join(\":\")));\n\n return namespaces.slice(\n op.offset ?? 0,\n (op.offset ?? 0) + (op.limit ?? namespaces.length)\n );\n }\n\n private doesMatch(matchCondition: MatchCondition, key: string[]): boolean {\n const { matchType, path } = matchCondition;\n\n if (matchType === \"prefix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[index];\n return pElem === \"*\" || kElem === pElem;\n });\n } else if (matchType === \"suffix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[key.length - path.length + index];\n return pElem === \"*\" || kElem === pElem;\n });\n }\n\n throw new Error(`Unsupported match type: ${matchType}`);\n }\n\n private filterItems(op: SearchOperation): Item[] {\n const candidates: Item[] = [];\n for (const [namespace, items] of this.data.entries()) {\n if (namespace.startsWith(op.namespacePrefix.join(\":\"))) {\n candidates.push(...items.values());\n }\n }\n\n let filteredCandidates = candidates;\n if (op.filter) {\n filteredCandidates = candidates.filter((item) =>\n Object.entries(op.filter!).every(([key, value]) =>\n compareValues(item.value[key], value)\n )\n );\n }\n return filteredCandidates;\n }\n\n private scoreResults(\n candidates: Item[],\n queryVector: number[],\n offset: number = 0,\n limit: number = 10\n ): SearchItem[] {\n const flatItems: Item[] = [];\n const flatVectors: number[][] = [];\n const scoreless: Item[] = [];\n\n for (const item of candidates) {\n const vectors = this.getVectors(item);\n if (vectors.length) {\n for (const vector of vectors) {\n flatItems.push(item);\n flatVectors.push(vector);\n }\n } else {\n scoreless.push(item);\n }\n }\n\n const scores = this.cosineSimilarity(queryVector, flatVectors);\n\n const sortedResults = scores\n .map((score, i) => [score, flatItems[i]] as [number, Item])\n .sort((a, b) => b[0] - a[0]);\n\n const seen = new Set<string>();\n const kept: Array<[number | undefined, Item]> = [];\n\n for (const [score, item] of sortedResults) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (seen.has(key)) continue;\n\n const ix = seen.size;\n if (ix >= offset + limit) break;\n if (ix < offset) {\n seen.add(key);\n continue;\n }\n\n seen.add(key);\n kept.push([score, item]);\n }\n\n if (scoreless.length && kept.length < limit) {\n for (const item of scoreless.slice(0, limit - kept.length)) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (!seen.has(key)) {\n seen.add(key);\n kept.push([undefined, item]);\n }\n }\n }\n return kept.map(([score, item]) => ({\n ...item,\n score,\n }));\n }\n\n private paginateResults(\n results: SearchItem[],\n offset: number,\n limit: number\n ): SearchItem[] {\n return results.slice(offset, offset + limit);\n }\n\n private extractTexts(ops: PutOperation[]): {\n [text: string]: [string[], string, string][];\n } {\n if (!ops.length || !this._indexConfig) {\n return {};\n }\n\n const toEmbed: { [text: string]: [string[], string, string][] } = {};\n\n for (const op of ops) {\n if (op.value !== null && op.index !== false) {\n const paths =\n op.index === null || op.index === undefined\n ? (this._indexConfig.__tokenizedFields ?? [])\n : op.index.map(\n (ix) => [ix, tokenizePath(ix)] as [string, string[]]\n );\n for (const [path, field] of paths) {\n const texts = getTextAtPath(op.value, field);\n if (texts.length) {\n if (texts.length > 1) {\n texts.forEach((text, i) => {\n if (!toEmbed[text]) toEmbed[text] = [];\n toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);\n });\n } else {\n if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];\n toEmbed[texts[0]].push([op.namespace, op.key, path]);\n }\n }\n }\n }\n }\n\n return toEmbed;\n }\n\n private insertVectors(\n texts: { [text: string]: [string[], string, string][] },\n embeddings: number[][]\n ): void {\n for (const [text, metadata] of Object.entries(texts)) {\n const embedding = embeddings.shift();\n if (!embedding) {\n throw new Error(`No embedding found for text: ${text}`);\n }\n\n for (const [namespace, key, field] of metadata) {\n const namespaceKey = namespace.join(\":\");\n if (!this.vectors.has(namespaceKey)) {\n this.vectors.set(namespaceKey, new Map());\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(key)) {\n namespaceMap.set(key, new Map());\n }\n const itemMap = namespaceMap.get(key)!;\n itemMap.set(field, embedding);\n }\n }\n }\n\n private getVectors(item: Item): number[][] {\n const namespaceKey = item.namespace.join(\":\");\n const itemKey = item.key;\n if (!this.vectors.has(namespaceKey)) {\n return [];\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(itemKey)) {\n return [];\n }\n const itemMap = namespaceMap.get(itemKey)!;\n const vectors = Array.from(itemMap.values());\n if (!vectors.length) {\n return [];\n }\n return vectors;\n }\n\n private cosineSimilarity(X: number[], Y: number[][]): number[] {\n if (!Y.length) return [];\n\n // Calculate dot products for all vectors at once\n const dotProducts = Y.map((vector) =>\n vector.reduce((acc, val, i) => acc + val * X[i], 0)\n );\n\n // Calculate magnitudes\n const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));\n const magnitudes2 = Y.map((vector) =>\n Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0))\n );\n\n // Calculate similarities\n return dotProducts.map((dot, i) => {\n const magnitude2 = magnitudes2[i];\n return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;\n });\n }\n\n public get indexConfig(): IndexConfig | undefined {\n return this._indexConfig;\n }\n}\n\n/** @deprecated Alias for InMemoryStore */\nexport class MemoryStore extends InMemoryStore {}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","names":[],"sources":["../../src/store/memory.ts"],"sourcesContent":["import {\n BaseStore,\n type OperationResults,\n type Item,\n type Operation,\n MatchCondition,\n ListNamespacesOperation,\n PutOperation,\n SearchOperation,\n GetOperation,\n type IndexConfig,\n type SearchItem,\n} from \"./base.js\";\nimport { tokenizePath, compareValues, getTextAtPath } from \"./utils.js\";\n\n/**\n * In-memory key-value store with optional vector search.\n *\n * A lightweight store implementation using JavaScript Maps. Supports basic\n * key-value operations and vector search when configured with embeddings.\n *\n * @example\n * ```typescript\n * // Basic key-value storage\n * const store = new InMemoryStore();\n * await store.put([\"users\", \"123\"], \"prefs\", { theme: \"dark\" });\n * const item = await store.get([\"users\", \"123\"], \"prefs\");\n *\n * // Vector search with embeddings\n * import { OpenAIEmbeddings } from \"@langchain/openai\";\n * const store = new InMemoryStore({\n * index: {\n * dims: 1536,\n * embeddings: new OpenAIEmbeddings({ modelName: \"text-embedding-3-small\" }),\n * }\n * });\n *\n * // Store documents\n * await store.put([\"docs\"], \"doc1\", { text: \"Python tutorial\" });\n * await store.put([\"docs\"], \"doc2\", { text: \"TypeScript guide\" });\n *\n * // Search by similarity\n * const results = await store.search([\"docs\"], { query: \"python programming\" });\n * ```\n *\n * **Warning**: This store keeps all data in memory. Data is lost when the process exits.\n * For persistence, use a database-backed store.\n */\nexport class InMemoryStore extends BaseStore {\n private data: Map<string, Map<string, Item>> = new Map();\n\n // Namespace -> Key -> Path/field -> Vector\n private vectors: Map<string, Map<string, Map<string, number[]>>> = new Map();\n\n private _indexConfig?: IndexConfig & {\n __tokenizedFields: Array<[string, string[]]>;\n };\n\n constructor(options?: { index?: IndexConfig }) {\n super();\n if (options?.index) {\n this._indexConfig = {\n ...options.index,\n __tokenizedFields: (options.index.fields ?? [\"$\"]).map((p) => [\n p,\n p === \"$\" ? [p] : tokenizePath(p),\n ]),\n };\n }\n }\n\n async batch<Op extends readonly Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>> {\n const results = [];\n const putOps = new Map<string, PutOperation>();\n const searchOps = new Map<number, [SearchOperation, Item[]]>();\n\n // First pass - handle gets and prepare search/put operations\n for (let i = 0; i < operations.length; i += 1) {\n const op = operations[i];\n if (\"key\" in op && \"namespace\" in op && !(\"value\" in op)) {\n // GetOperation\n results.push(this.getOperation(op));\n } else if (\"namespacePrefix\" in op) {\n // SearchOperation\n const candidates = this.filterItems(op);\n searchOps.set(i, [op, candidates]);\n results.push(null);\n } else if (\"value\" in op) {\n // PutOperation\n const key = `${op.namespace.join(\":\")}:${op.key}`;\n putOps.set(key, op);\n results.push(null);\n } else if (\"matchConditions\" in op) {\n // ListNamespacesOperation\n results.push(this.listNamespacesOperation(op));\n }\n }\n\n // Handle search operations with embeddings\n if (searchOps.size > 0) {\n if (this._indexConfig?.embeddings) {\n const queries = new Set<string>();\n for (const [op] of searchOps.values()) {\n if (op.query) queries.add(op.query);\n }\n\n // Get embeddings for all queries\n const queryEmbeddings =\n queries.size > 0\n ? await Promise.all(\n Array.from(queries).map((q) =>\n this._indexConfig!.embeddings.embedQuery(q)\n )\n )\n : [];\n const queryVectors = Object.fromEntries(\n Array.from(queries).map((q, i) => [q, queryEmbeddings[i]])\n );\n\n // Process each search operation\n for (const [i, [op, candidates]] of searchOps.entries()) {\n if (op.query && queryVectors[op.query]) {\n const queryVector = queryVectors[op.query];\n const scoredResults = this.scoreResults(\n candidates,\n queryVector,\n op.offset ?? 0,\n op.limit ?? 10\n );\n results[i] = scoredResults;\n } else {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n } else {\n // No embeddings - just paginate the filtered results\n for (const [i, [op, candidates]] of searchOps.entries()) {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n }\n\n // Handle put operations with embeddings\n if (putOps.size > 0 && this._indexConfig?.embeddings) {\n const toEmbed = this.extractTexts(Array.from(putOps.values()));\n if (Object.keys(toEmbed).length > 0) {\n const embeddings = await this._indexConfig.embeddings.embedDocuments(\n Object.keys(toEmbed)\n );\n this.insertVectors(toEmbed, embeddings);\n }\n }\n\n // Apply all put operations\n for (const op of putOps.values()) {\n this.putOperation(op);\n }\n\n return results as OperationResults<Op>;\n }\n\n private getOperation(op: GetOperation): Item | null {\n const namespaceKey = op.namespace.join(\":\");\n const item = this.data.get(namespaceKey)?.get(op.key);\n return item ?? null;\n }\n\n private putOperation(op: PutOperation): void {\n const namespaceKey = op.namespace.join(\":\");\n if (!this.data.has(namespaceKey)) {\n this.data.set(namespaceKey, new Map());\n }\n const namespaceMap = this.data.get(namespaceKey)!;\n\n if (op.value === null) {\n namespaceMap.delete(op.key);\n } else {\n const now = new Date();\n if (namespaceMap.has(op.key)) {\n const item = namespaceMap.get(op.key)!;\n item.value = op.value;\n item.updatedAt = now;\n } else {\n namespaceMap.set(op.key, {\n value: op.value,\n key: op.key,\n namespace: op.namespace,\n createdAt: now,\n updatedAt: now,\n });\n }\n }\n }\n\n private listNamespacesOperation(op: ListNamespacesOperation): string[][] {\n const allNamespaces = Array.from(this.data.keys()).map((ns) =>\n ns.split(\":\")\n );\n let namespaces = allNamespaces;\n\n if (op.matchConditions && op.matchConditions.length > 0) {\n namespaces = namespaces.filter((ns) =>\n op.matchConditions!.every((condition) => this.doesMatch(condition, ns))\n );\n }\n\n if (op.maxDepth !== undefined) {\n namespaces = Array.from(\n new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(\":\")))\n ).map((ns) => ns.split(\":\"));\n }\n\n namespaces.sort((a, b) => a.join(\":\").localeCompare(b.join(\":\")));\n\n return namespaces.slice(\n op.offset ?? 0,\n (op.offset ?? 0) + (op.limit ?? namespaces.length)\n );\n }\n\n private doesMatch(matchCondition: MatchCondition, key: string[]): boolean {\n const { matchType, path } = matchCondition;\n\n if (matchType === \"prefix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[index];\n return pElem === \"*\" || kElem === pElem;\n });\n } else if (matchType === \"suffix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[key.length - path.length + index];\n return pElem === \"*\" || kElem === pElem;\n });\n }\n\n throw new Error(`Unsupported match type: ${matchType}`);\n }\n\n private filterItems(op: SearchOperation): Item[] {\n const candidates: Item[] = [];\n for (const [namespace, items] of this.data.entries()) {\n if (namespace.startsWith(op.namespacePrefix.join(\":\"))) {\n candidates.push(...items.values());\n }\n }\n\n let filteredCandidates = candidates;\n if (op.filter) {\n filteredCandidates = candidates.filter((item) =>\n Object.entries(op.filter!).every(([key, value]) =>\n compareValues(item.value[key], value)\n )\n );\n }\n return filteredCandidates;\n }\n\n private scoreResults(\n candidates: Item[],\n queryVector: number[],\n offset: number = 0,\n limit: number = 10\n ): SearchItem[] {\n const flatItems: Item[] = [];\n const flatVectors: number[][] = [];\n const scoreless: Item[] = [];\n\n for (const item of candidates) {\n const vectors = this.getVectors(item);\n if (vectors.length) {\n for (const vector of vectors) {\n flatItems.push(item);\n flatVectors.push(vector);\n }\n } else {\n scoreless.push(item);\n }\n }\n\n const scores = this.cosineSimilarity(queryVector, flatVectors);\n\n const sortedResults = scores\n .map((score, i) => [score, flatItems[i]] as [number, Item])\n .sort((a, b) => b[0] - a[0]);\n\n const seen = new Set<string>();\n const kept: Array<[number | undefined, Item]> = [];\n\n for (const [score, item] of sortedResults) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (seen.has(key)) continue;\n\n const ix = seen.size;\n if (ix >= offset + limit) break;\n if (ix < offset) {\n seen.add(key);\n continue;\n }\n\n seen.add(key);\n kept.push([score, item]);\n }\n\n if (scoreless.length && kept.length < limit) {\n for (const item of scoreless.slice(0, limit - kept.length)) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (!seen.has(key)) {\n seen.add(key);\n kept.push([undefined, item]);\n }\n }\n }\n return kept.map(([score, item]) => ({\n ...item,\n score,\n }));\n }\n\n private paginateResults(\n results: SearchItem[],\n offset: number,\n limit: number\n ): SearchItem[] {\n return results.slice(offset, offset + limit);\n }\n\n private extractTexts(ops: PutOperation[]): {\n [text: string]: [string[], string, string][];\n } {\n if (!ops.length || !this._indexConfig) {\n return {};\n }\n\n const toEmbed: { [text: string]: [string[], string, string][] } = {};\n\n for (const op of ops) {\n if (op.value !== null && op.index !== false) {\n const paths =\n op.index === null || op.index === undefined\n ? this._indexConfig.__tokenizedFields ?? []\n : op.index.map(\n (ix) => [ix, tokenizePath(ix)] as [string, string[]]\n );\n for (const [path, field] of paths) {\n const texts = getTextAtPath(op.value, field);\n if (texts.length) {\n if (texts.length > 1) {\n texts.forEach((text, i) => {\n if (!toEmbed[text]) toEmbed[text] = [];\n toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);\n });\n } else {\n if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];\n toEmbed[texts[0]].push([op.namespace, op.key, path]);\n }\n }\n }\n }\n }\n\n return toEmbed;\n }\n\n private insertVectors(\n texts: { [text: string]: [string[], string, string][] },\n embeddings: number[][]\n ): void {\n for (const [text, metadata] of Object.entries(texts)) {\n const embedding = embeddings.shift();\n if (!embedding) {\n throw new Error(`No embedding found for text: ${text}`);\n }\n\n for (const [namespace, key, field] of metadata) {\n const namespaceKey = namespace.join(\":\");\n if (!this.vectors.has(namespaceKey)) {\n this.vectors.set(namespaceKey, new Map());\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(key)) {\n namespaceMap.set(key, new Map());\n }\n const itemMap = namespaceMap.get(key)!;\n itemMap.set(field, embedding);\n }\n }\n }\n\n private getVectors(item: Item): number[][] {\n const namespaceKey = item.namespace.join(\":\");\n const itemKey = item.key;\n if (!this.vectors.has(namespaceKey)) {\n return [];\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(itemKey)) {\n return [];\n }\n const itemMap = namespaceMap.get(itemKey)!;\n const vectors = Array.from(itemMap.values());\n if (!vectors.length) {\n return [];\n }\n return vectors;\n }\n\n private cosineSimilarity(X: number[], Y: number[][]): number[] {\n if (!Y.length) return [];\n\n // Calculate dot products for all vectors at once\n const dotProducts = Y.map((vector) =>\n vector.reduce((acc, val, i) => acc + val * X[i], 0)\n );\n\n // Calculate magnitudes\n const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));\n const magnitudes2 = Y.map((vector) =>\n Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0))\n );\n\n // Calculate similarities\n return dotProducts.map((dot, i) => {\n const magnitude2 = magnitudes2[i];\n return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;\n });\n }\n\n public get indexConfig(): IndexConfig | undefined {\n return this._indexConfig;\n }\n}\n\n/** @deprecated Alias for InMemoryStore */\nexport class MemoryStore extends InMemoryStore {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","names":[],"sources":["../../src/store/memory.ts"],"sourcesContent":["import {\n BaseStore,\n type OperationResults,\n type Item,\n type Operation,\n MatchCondition,\n ListNamespacesOperation,\n PutOperation,\n SearchOperation,\n GetOperation,\n type IndexConfig,\n type SearchItem,\n} from \"./base.js\";\nimport { tokenizePath, compareValues, getTextAtPath } from \"./utils.js\";\n\n/**\n * In-memory key-value store with optional vector search.\n *\n * A lightweight store implementation using JavaScript Maps. Supports basic\n * key-value operations and vector search when configured with embeddings.\n *\n * @example\n * ```typescript\n * // Basic key-value storage\n * const store = new InMemoryStore();\n * await store.put([\"users\", \"123\"], \"prefs\", { theme: \"dark\" });\n * const item = await store.get([\"users\", \"123\"], \"prefs\");\n *\n * // Vector search with embeddings\n * import { OpenAIEmbeddings } from \"@langchain/openai\";\n * const store = new InMemoryStore({\n * index: {\n * dims: 1536,\n * embeddings: new OpenAIEmbeddings({ modelName: \"text-embedding-3-small\" }),\n * }\n * });\n *\n * // Store documents\n * await store.put([\"docs\"], \"doc1\", { text: \"Python tutorial\" });\n * await store.put([\"docs\"], \"doc2\", { text: \"TypeScript guide\" });\n *\n * // Search by similarity\n * const results = await store.search([\"docs\"], { query: \"python programming\" });\n * ```\n *\n * **Warning**: This store keeps all data in memory. Data is lost when the process exits.\n * For persistence, use a database-backed store.\n */\nexport class InMemoryStore extends BaseStore {\n private data: Map<string, Map<string, Item>> = new Map();\n\n // Namespace -> Key -> Path/field -> Vector\n private vectors: Map<string, Map<string, Map<string, number[]>>> = new Map();\n\n private _indexConfig?: IndexConfig & {\n __tokenizedFields: Array<[string, string[]]>;\n };\n\n constructor(options?: { index?: IndexConfig }) {\n super();\n if (options?.index) {\n this._indexConfig = {\n ...options.index,\n __tokenizedFields: (options.index.fields ?? [\"$\"]).map((p) => [\n p,\n p === \"$\" ? [p] : tokenizePath(p),\n ]),\n };\n }\n }\n\n async batch<Op extends readonly Operation[]>(\n operations: Op\n ): Promise<OperationResults<Op>> {\n const results = [];\n const putOps = new Map<string, PutOperation>();\n const searchOps = new Map<number, [SearchOperation, Item[]]>();\n\n // First pass - handle gets and prepare search/put operations\n for (let i = 0; i < operations.length; i += 1) {\n const op = operations[i];\n if (\"key\" in op && \"namespace\" in op && !(\"value\" in op)) {\n // GetOperation\n results.push(this.getOperation(op));\n } else if (\"namespacePrefix\" in op) {\n // SearchOperation\n const candidates = this.filterItems(op);\n searchOps.set(i, [op, candidates]);\n results.push(null);\n } else if (\"value\" in op) {\n // PutOperation\n const key = `${op.namespace.join(\":\")}:${op.key}`;\n putOps.set(key, op);\n results.push(null);\n } else if (\"matchConditions\" in op) {\n // ListNamespacesOperation\n results.push(this.listNamespacesOperation(op));\n }\n }\n\n // Handle search operations with embeddings\n if (searchOps.size > 0) {\n if (this._indexConfig?.embeddings) {\n const queries = new Set<string>();\n for (const [op] of searchOps.values()) {\n if (op.query) queries.add(op.query);\n }\n\n // Get embeddings for all queries\n const queryEmbeddings =\n queries.size > 0\n ? await Promise.all(\n Array.from(queries).map((q) =>\n this._indexConfig!.embeddings.embedQuery(q)\n )\n )\n : [];\n const queryVectors = Object.fromEntries(\n Array.from(queries).map((q, i) => [q, queryEmbeddings[i]])\n );\n\n // Process each search operation\n for (const [i, [op, candidates]] of searchOps.entries()) {\n if (op.query && queryVectors[op.query]) {\n const queryVector = queryVectors[op.query];\n const scoredResults = this.scoreResults(\n candidates,\n queryVector,\n op.offset ?? 0,\n op.limit ?? 10\n );\n results[i] = scoredResults;\n } else {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n } else {\n // No embeddings - just paginate the filtered results\n for (const [i, [op, candidates]] of searchOps.entries()) {\n results[i] = this.paginateResults(\n candidates.map((item) => ({ ...item, score: undefined })),\n op.offset ?? 0,\n op.limit ?? 10\n );\n }\n }\n }\n\n // Handle put operations with embeddings\n if (putOps.size > 0 && this._indexConfig?.embeddings) {\n const toEmbed = this.extractTexts(Array.from(putOps.values()));\n if (Object.keys(toEmbed).length > 0) {\n const embeddings = await this._indexConfig.embeddings.embedDocuments(\n Object.keys(toEmbed)\n );\n this.insertVectors(toEmbed, embeddings);\n }\n }\n\n // Apply all put operations\n for (const op of putOps.values()) {\n this.putOperation(op);\n }\n\n return results as OperationResults<Op>;\n }\n\n private getOperation(op: GetOperation): Item | null {\n const namespaceKey = op.namespace.join(\":\");\n const item = this.data.get(namespaceKey)?.get(op.key);\n return item ?? null;\n }\n\n private putOperation(op: PutOperation): void {\n const namespaceKey = op.namespace.join(\":\");\n if (!this.data.has(namespaceKey)) {\n this.data.set(namespaceKey, new Map());\n }\n const namespaceMap = this.data.get(namespaceKey)!;\n\n if (op.value === null) {\n namespaceMap.delete(op.key);\n } else {\n const now = new Date();\n if (namespaceMap.has(op.key)) {\n const item = namespaceMap.get(op.key)!;\n item.value = op.value;\n item.updatedAt = now;\n } else {\n namespaceMap.set(op.key, {\n value: op.value,\n key: op.key,\n namespace: op.namespace,\n createdAt: now,\n updatedAt: now,\n });\n }\n }\n }\n\n private listNamespacesOperation(op: ListNamespacesOperation): string[][] {\n const allNamespaces = Array.from(this.data.keys()).map((ns) =>\n ns.split(\":\")\n );\n let namespaces = allNamespaces;\n\n if (op.matchConditions && op.matchConditions.length > 0) {\n namespaces = namespaces.filter((ns) =>\n op.matchConditions!.every((condition) => this.doesMatch(condition, ns))\n );\n }\n\n if (op.maxDepth !== undefined) {\n namespaces = Array.from(\n new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(\":\")))\n ).map((ns) => ns.split(\":\"));\n }\n\n namespaces.sort((a, b) => a.join(\":\").localeCompare(b.join(\":\")));\n\n return namespaces.slice(\n op.offset ?? 0,\n (op.offset ?? 0) + (op.limit ?? namespaces.length)\n );\n }\n\n private doesMatch(matchCondition: MatchCondition, key: string[]): boolean {\n const { matchType, path } = matchCondition;\n\n if (matchType === \"prefix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[index];\n return pElem === \"*\" || kElem === pElem;\n });\n } else if (matchType === \"suffix\") {\n if (path.length > key.length) return false;\n return path.every((pElem, index) => {\n const kElem = key[key.length - path.length + index];\n return pElem === \"*\" || kElem === pElem;\n });\n }\n\n throw new Error(`Unsupported match type: ${matchType}`);\n }\n\n private filterItems(op: SearchOperation): Item[] {\n const candidates: Item[] = [];\n for (const [namespace, items] of this.data.entries()) {\n if (namespace.startsWith(op.namespacePrefix.join(\":\"))) {\n candidates.push(...items.values());\n }\n }\n\n let filteredCandidates = candidates;\n if (op.filter) {\n filteredCandidates = candidates.filter((item) =>\n Object.entries(op.filter!).every(([key, value]) =>\n compareValues(item.value[key], value)\n )\n );\n }\n return filteredCandidates;\n }\n\n private scoreResults(\n candidates: Item[],\n queryVector: number[],\n offset: number = 0,\n limit: number = 10\n ): SearchItem[] {\n const flatItems: Item[] = [];\n const flatVectors: number[][] = [];\n const scoreless: Item[] = [];\n\n for (const item of candidates) {\n const vectors = this.getVectors(item);\n if (vectors.length) {\n for (const vector of vectors) {\n flatItems.push(item);\n flatVectors.push(vector);\n }\n } else {\n scoreless.push(item);\n }\n }\n\n const scores = this.cosineSimilarity(queryVector, flatVectors);\n\n const sortedResults = scores\n .map((score, i) => [score, flatItems[i]] as [number, Item])\n .sort((a, b) => b[0] - a[0]);\n\n const seen = new Set<string>();\n const kept: Array<[number | undefined, Item]> = [];\n\n for (const [score, item] of sortedResults) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (seen.has(key)) continue;\n\n const ix = seen.size;\n if (ix >= offset + limit) break;\n if (ix < offset) {\n seen.add(key);\n continue;\n }\n\n seen.add(key);\n kept.push([score, item]);\n }\n\n if (scoreless.length && kept.length < limit) {\n for (const item of scoreless.slice(0, limit - kept.length)) {\n const key = `${item.namespace.join(\":\")}:${item.key}`;\n if (!seen.has(key)) {\n seen.add(key);\n kept.push([undefined, item]);\n }\n }\n }\n return kept.map(([score, item]) => ({\n ...item,\n score,\n }));\n }\n\n private paginateResults(\n results: SearchItem[],\n offset: number,\n limit: number\n ): SearchItem[] {\n return results.slice(offset, offset + limit);\n }\n\n private extractTexts(ops: PutOperation[]): {\n [text: string]: [string[], string, string][];\n } {\n if (!ops.length || !this._indexConfig) {\n return {};\n }\n\n const toEmbed: { [text: string]: [string[], string, string][] } = {};\n\n for (const op of ops) {\n if (op.value !== null && op.index !== false) {\n const paths =\n op.index === null || op.index === undefined\n ? (this._indexConfig.__tokenizedFields ?? [])\n : op.index.map(\n (ix) => [ix, tokenizePath(ix)] as [string, string[]]\n );\n for (const [path, field] of paths) {\n const texts = getTextAtPath(op.value, field);\n if (texts.length) {\n if (texts.length > 1) {\n texts.forEach((text, i) => {\n if (!toEmbed[text]) toEmbed[text] = [];\n toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);\n });\n } else {\n if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];\n toEmbed[texts[0]].push([op.namespace, op.key, path]);\n }\n }\n }\n }\n }\n\n return toEmbed;\n }\n\n private insertVectors(\n texts: { [text: string]: [string[], string, string][] },\n embeddings: number[][]\n ): void {\n for (const [text, metadata] of Object.entries(texts)) {\n const embedding = embeddings.shift();\n if (!embedding) {\n throw new Error(`No embedding found for text: ${text}`);\n }\n\n for (const [namespace, key, field] of metadata) {\n const namespaceKey = namespace.join(\":\");\n if (!this.vectors.has(namespaceKey)) {\n this.vectors.set(namespaceKey, new Map());\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(key)) {\n namespaceMap.set(key, new Map());\n }\n const itemMap = namespaceMap.get(key)!;\n itemMap.set(field, embedding);\n }\n }\n }\n\n private getVectors(item: Item): number[][] {\n const namespaceKey = item.namespace.join(\":\");\n const itemKey = item.key;\n if (!this.vectors.has(namespaceKey)) {\n return [];\n }\n const namespaceMap = this.vectors.get(namespaceKey)!;\n if (!namespaceMap.has(itemKey)) {\n return [];\n }\n const itemMap = namespaceMap.get(itemKey)!;\n const vectors = Array.from(itemMap.values());\n if (!vectors.length) {\n return [];\n }\n return vectors;\n }\n\n private cosineSimilarity(X: number[], Y: number[][]): number[] {\n if (!Y.length) return [];\n\n // Calculate dot products for all vectors at once\n const dotProducts = Y.map((vector) =>\n vector.reduce((acc, val, i) => acc + val * X[i], 0)\n );\n\n // Calculate magnitudes\n const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));\n const magnitudes2 = Y.map((vector) =>\n Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0))\n );\n\n // Calculate similarities\n return dotProducts.map((dot, i) => {\n const magnitude2 = magnitudes2[i];\n return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;\n });\n }\n\n public get indexConfig(): IndexConfig | undefined {\n return this._indexConfig;\n }\n}\n\n/** @deprecated Alias for InMemoryStore */\nexport class MemoryStore extends InMemoryStore {}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph-checkpoint",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Library with base interfaces for LangGraph checkpoint savers.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -19,23 +19,14 @@
19
19
  "uuid": "^10.0.0"
20
20
  },
21
21
  "peerDependencies": {
22
- "@langchain/core": "^1.0.1"
22
+ "@langchain/core": "^1.1.44"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@langchain/scripts": ">=0.1.3 <0.2.0",
26
26
  "@tsconfig/recommended": "^1.0.3",
27
27
  "@types/uuid": "^10",
28
- "@typescript-eslint/eslint-plugin": "^6.12.0",
29
- "@typescript-eslint/parser": "^6.12.0",
30
28
  "dotenv": "^16.3.1",
31
29
  "dpdm": "^3.12.0",
32
- "eslint": "^8.33.0",
33
- "eslint-config-airbnb-base": "^15.0.0",
34
- "eslint-config-prettier": "^8.6.0",
35
- "eslint-plugin-import": "^2.29.1",
36
- "eslint-plugin-no-instanceof": "^1.0.1",
37
- "eslint-plugin-prettier": "^4.2.1",
38
- "prettier": "^2.8.3",
39
30
  "rollup": "^4.37.0",
40
31
  "tsx": "^4.19.3",
41
32
  "typescript": "^4.9.5 || ^5.4.5",
@@ -69,13 +60,9 @@
69
60
  "clean": "rm -rf dist/ dist-cjs/ .turbo/",
70
61
  "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
71
62
  "lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
72
- "lint": "pnpm lint:eslint && pnpm lint:dpdm",
73
- "lint:fix": "pnpm lint:eslint --fix && pnpm lint:dpdm",
74
63
  "prepublish": "pnpm build",
75
64
  "test": "vitest run",
76
65
  "test:watch": "vitest watch",
77
- "test:int": "vitest run --mode int",
78
- "format": "prettier --config .prettierrc --write \"src\"",
79
- "format:check": "prettier --config .prettierrc --check \"src\""
66
+ "test:int": "vitest run --mode int"
80
67
  }
81
68
  }