@langchain/langgraph 0.1.0-rc.0 → 0.1.0

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.
Files changed (62) hide show
  1. package/LICENSE +1 -1
  2. package/dist/channels/base.cjs +20 -15
  3. package/dist/channels/base.d.ts +2 -3
  4. package/dist/channels/base.js +18 -13
  5. package/dist/checkpoint/sqlite.cjs +14 -199
  6. package/dist/checkpoint/sqlite.d.ts +1 -16
  7. package/dist/checkpoint/sqlite.js +1 -195
  8. package/dist/graph/graph.d.ts +1 -1
  9. package/dist/graph/message.d.ts +0 -3
  10. package/dist/graph/messages_annotation.cjs +12 -0
  11. package/dist/graph/messages_annotation.d.ts +4 -0
  12. package/dist/graph/messages_annotation.js +9 -0
  13. package/dist/graph/state.cjs +2 -1
  14. package/dist/graph/state.d.ts +1 -1
  15. package/dist/graph/state.js +2 -1
  16. package/dist/index.cjs +3 -0
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/prebuilt/react_agent_executor.d.ts +3 -3
  20. package/dist/prebuilt/tool_node.d.ts +3 -3
  21. package/dist/pregel/algo.cjs +112 -105
  22. package/dist/pregel/algo.d.ts +8 -5
  23. package/dist/pregel/algo.js +109 -102
  24. package/dist/pregel/debug.cjs +9 -12
  25. package/dist/pregel/debug.d.ts +3 -2
  26. package/dist/pregel/debug.js +6 -10
  27. package/dist/pregel/index.cjs +92 -26
  28. package/dist/pregel/index.d.ts +41 -3
  29. package/dist/pregel/index.js +90 -24
  30. package/dist/pregel/io.d.ts +1 -1
  31. package/dist/pregel/loop.cjs +13 -9
  32. package/dist/pregel/loop.d.ts +1 -2
  33. package/dist/pregel/loop.js +8 -4
  34. package/dist/pregel/types.d.ts +5 -2
  35. package/dist/pregel/utils.cjs +25 -10
  36. package/dist/pregel/utils.d.ts +8 -1
  37. package/dist/pregel/utils.js +22 -9
  38. package/dist/web.cjs +6 -7
  39. package/dist/web.d.ts +1 -4
  40. package/dist/web.js +1 -2
  41. package/package.json +12 -12
  42. package/dist/checkpoint/base.cjs +0 -75
  43. package/dist/checkpoint/base.d.ts +0 -78
  44. package/dist/checkpoint/base.js +0 -66
  45. package/dist/checkpoint/id.cjs +0 -20
  46. package/dist/checkpoint/id.d.ts +0 -2
  47. package/dist/checkpoint/id.js +0 -15
  48. package/dist/checkpoint/index.cjs +0 -9
  49. package/dist/checkpoint/index.d.ts +0 -3
  50. package/dist/checkpoint/index.js +0 -2
  51. package/dist/checkpoint/memory.cjs +0 -195
  52. package/dist/checkpoint/memory.d.ts +0 -13
  53. package/dist/checkpoint/memory.js +0 -191
  54. package/dist/checkpoint/serde/types.cjs +0 -2
  55. package/dist/checkpoint/serde/types.d.ts +0 -40
  56. package/dist/checkpoint/serde/types.js +0 -1
  57. package/dist/checkpoint/types.cjs +0 -2
  58. package/dist/checkpoint/types.d.ts +0 -28
  59. package/dist/checkpoint/types.js +0 -1
  60. package/dist/serde/base.cjs +0 -8
  61. package/dist/serde/base.d.ts +0 -12
  62. package/dist/serde/base.js +0 -5
@@ -1,75 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseCheckpointSaver = exports.copyCheckpoint = exports.emptyCheckpoint = exports.deepCopy = exports.getVersionSeen = exports.getChannelVersion = void 0;
4
- const base_js_1 = require("../serde/base.cjs");
5
- const id_js_1 = require("./id.cjs");
6
- function getChannelVersion(checkpoint, channel) {
7
- return checkpoint.channel_versions[channel] ?? 0;
8
- }
9
- exports.getChannelVersion = getChannelVersion;
10
- function getVersionSeen(checkpoint, node, channel) {
11
- return checkpoint.versions_seen[node]?.[channel] ?? 0;
12
- }
13
- exports.getVersionSeen = getVersionSeen;
14
- function deepCopy(obj) {
15
- if (typeof obj !== "object" || obj === null) {
16
- return obj;
17
- }
18
- const newObj = Array.isArray(obj) ? [] : {};
19
- for (const key in obj) {
20
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
21
- newObj[key] = deepCopy(obj[key]);
22
- }
23
- }
24
- return newObj;
25
- }
26
- exports.deepCopy = deepCopy;
27
- function emptyCheckpoint() {
28
- return {
29
- v: 1,
30
- id: (0, id_js_1.uuid6)(-2),
31
- ts: new Date().toISOString(),
32
- channel_values: {},
33
- channel_versions: {},
34
- versions_seen: {},
35
- pending_sends: [],
36
- };
37
- }
38
- exports.emptyCheckpoint = emptyCheckpoint;
39
- function copyCheckpoint(checkpoint) {
40
- return {
41
- v: checkpoint.v,
42
- id: checkpoint.id,
43
- ts: checkpoint.ts,
44
- channel_values: { ...checkpoint.channel_values },
45
- channel_versions: { ...checkpoint.channel_versions },
46
- versions_seen: deepCopy(checkpoint.versions_seen),
47
- pending_sends: [...checkpoint.pending_sends],
48
- };
49
- }
50
- exports.copyCheckpoint = copyCheckpoint;
51
- class BaseCheckpointSaver {
52
- constructor(serde) {
53
- Object.defineProperty(this, "serde", {
54
- enumerable: true,
55
- configurable: true,
56
- writable: true,
57
- value: base_js_1.DefaultSerializer
58
- });
59
- this.serde = serde || this.serde;
60
- }
61
- async get(config) {
62
- const value = await this.getTuple(config);
63
- return value ? value.checkpoint : undefined;
64
- }
65
- /**
66
- * Generate the next version ID for a channel.
67
- *
68
- * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,
69
- * as long as they are monotonically increasing.
70
- */
71
- getNextVersion(current, _channel) {
72
- return current !== undefined ? current + 1 : 1;
73
- }
74
- }
75
- exports.BaseCheckpointSaver = BaseCheckpointSaver;
@@ -1,78 +0,0 @@
1
- import { RunnableConfig } from "@langchain/core/runnables";
2
- import { SerializerProtocol } from "../serde/base.js";
3
- import { SendInterface } from "../constants.js";
4
- import type { PendingWrite, CheckpointPendingWrite, CheckpointMetadata } from "./types.js";
5
- import { ChannelProtocol } from "./serde/types.js";
6
- export type ChannelVersions = Record<string, string | number>;
7
- export interface Checkpoint<N extends string = string, C extends string = string> {
8
- /**
9
- * Version number
10
- */
11
- v: number;
12
- /**
13
- * Checkpoint ID {uuid6}
14
- */
15
- id: string;
16
- /**
17
- * Timestamp {new Date().toISOString()}
18
- */
19
- ts: string;
20
- /**
21
- * @default {}
22
- */
23
- channel_values: Record<C, unknown>;
24
- /**
25
- * @default {}
26
- */
27
- channel_versions: Record<C, number>;
28
- /**
29
- * @default {}
30
- */
31
- versions_seen: Record<N, Record<C, number>>;
32
- /**
33
- * List of packets sent to nodes but not yet processed.
34
- * Cleared by the next checkpoint.
35
- */
36
- pending_sends: SendInterface[];
37
- }
38
- export interface ReadonlyCheckpoint extends Readonly<Checkpoint> {
39
- readonly channel_values: Readonly<Record<string, unknown>>;
40
- readonly channel_versions: Readonly<Record<string, number>>;
41
- readonly versions_seen: Readonly<Record<string, Readonly<Record<string, number>>>>;
42
- }
43
- export declare function getChannelVersion(checkpoint: ReadonlyCheckpoint, channel: string): number;
44
- export declare function getVersionSeen(checkpoint: ReadonlyCheckpoint, node: string, channel: string): number;
45
- export declare function deepCopy<T>(obj: T): T;
46
- export declare function emptyCheckpoint(): Checkpoint;
47
- export declare function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint;
48
- export interface CheckpointTuple {
49
- config: RunnableConfig;
50
- checkpoint: Checkpoint;
51
- metadata?: CheckpointMetadata;
52
- parentConfig?: RunnableConfig;
53
- pendingWrites?: CheckpointPendingWrite[];
54
- }
55
- export type CheckpointListOptions = {
56
- limit?: number;
57
- before?: RunnableConfig;
58
- filter?: Record<string, any>;
59
- };
60
- export declare abstract class BaseCheckpointSaver<V = number> {
61
- serde: SerializerProtocol<unknown>;
62
- constructor(serde?: SerializerProtocol<unknown>);
63
- get(config: RunnableConfig): Promise<Checkpoint | undefined>;
64
- abstract getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined>;
65
- abstract list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
66
- abstract put(config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata, newVersions: ChannelVersions): Promise<RunnableConfig>;
67
- /**
68
- * Store intermediate writes linked to a checkpoint.
69
- */
70
- abstract putWrites(config: RunnableConfig, writes: PendingWrite[], taskId: string): Promise<void>;
71
- /**
72
- * Generate the next version ID for a channel.
73
- *
74
- * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,
75
- * as long as they are monotonically increasing.
76
- */
77
- getNextVersion(current: V | undefined, _channel: ChannelProtocol): number;
78
- }
@@ -1,66 +0,0 @@
1
- import { DefaultSerializer } from "../serde/base.js";
2
- import { uuid6 } from "./id.js";
3
- export function getChannelVersion(checkpoint, channel) {
4
- return checkpoint.channel_versions[channel] ?? 0;
5
- }
6
- export function getVersionSeen(checkpoint, node, channel) {
7
- return checkpoint.versions_seen[node]?.[channel] ?? 0;
8
- }
9
- export function deepCopy(obj) {
10
- if (typeof obj !== "object" || obj === null) {
11
- return obj;
12
- }
13
- const newObj = Array.isArray(obj) ? [] : {};
14
- for (const key in obj) {
15
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
16
- newObj[key] = deepCopy(obj[key]);
17
- }
18
- }
19
- return newObj;
20
- }
21
- export function emptyCheckpoint() {
22
- return {
23
- v: 1,
24
- id: uuid6(-2),
25
- ts: new Date().toISOString(),
26
- channel_values: {},
27
- channel_versions: {},
28
- versions_seen: {},
29
- pending_sends: [],
30
- };
31
- }
32
- export function copyCheckpoint(checkpoint) {
33
- return {
34
- v: checkpoint.v,
35
- id: checkpoint.id,
36
- ts: checkpoint.ts,
37
- channel_values: { ...checkpoint.channel_values },
38
- channel_versions: { ...checkpoint.channel_versions },
39
- versions_seen: deepCopy(checkpoint.versions_seen),
40
- pending_sends: [...checkpoint.pending_sends],
41
- };
42
- }
43
- export class BaseCheckpointSaver {
44
- constructor(serde) {
45
- Object.defineProperty(this, "serde", {
46
- enumerable: true,
47
- configurable: true,
48
- writable: true,
49
- value: DefaultSerializer
50
- });
51
- this.serde = serde || this.serde;
52
- }
53
- async get(config) {
54
- const value = await this.getTuple(config);
55
- return value ? value.checkpoint : undefined;
56
- }
57
- /**
58
- * Generate the next version ID for a channel.
59
- *
60
- * Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,
61
- * as long as they are monotonically increasing.
62
- */
63
- getNextVersion(current, _channel) {
64
- return current !== undefined ? current + 1 : 1;
65
- }
66
- }
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uuid5 = exports.uuid6 = void 0;
4
- const uuid_1 = require("uuid");
5
- function uuid6(clockseq) {
6
- return (0, uuid_1.v6)({ clockseq });
7
- }
8
- exports.uuid6 = uuid6;
9
- // Skip UUID validation check, since UUID6s
10
- // generated with negative clockseq are not
11
- // technically compliant, but still work.
12
- // See: https://github.com/uuidjs/uuid/issues/511
13
- function uuid5(name, namespace) {
14
- const namespaceBytes = namespace
15
- .replace(/-/g, "")
16
- .match(/.{2}/g)
17
- .map((byte) => parseInt(byte, 16));
18
- return (0, uuid_1.v5)(name, new Uint8Array(namespaceBytes));
19
- }
20
- exports.uuid5 = uuid5;
@@ -1,2 +0,0 @@
1
- export declare function uuid6(clockseq: number): string;
2
- export declare function uuid5(name: string, namespace: string): string;
@@ -1,15 +0,0 @@
1
- import { v5, v6 } from "uuid";
2
- export function uuid6(clockseq) {
3
- return v6({ clockseq });
4
- }
5
- // Skip UUID validation check, since UUID6s
6
- // generated with negative clockseq are not
7
- // technically compliant, but still work.
8
- // See: https://github.com/uuidjs/uuid/issues/511
9
- export function uuid5(name, namespace) {
10
- const namespaceBytes = namespace
11
- .replace(/-/g, "")
12
- .match(/.{2}/g)
13
- .map((byte) => parseInt(byte, 16));
14
- return v5(name, new Uint8Array(namespaceBytes));
15
- }
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseCheckpointSaver = exports.emptyCheckpoint = exports.copyCheckpoint = exports.MemorySaver = void 0;
4
- var memory_js_1 = require("./memory.cjs");
5
- Object.defineProperty(exports, "MemorySaver", { enumerable: true, get: function () { return memory_js_1.MemorySaver; } });
6
- var base_js_1 = require("./base.cjs");
7
- Object.defineProperty(exports, "copyCheckpoint", { enumerable: true, get: function () { return base_js_1.copyCheckpoint; } });
8
- Object.defineProperty(exports, "emptyCheckpoint", { enumerable: true, get: function () { return base_js_1.emptyCheckpoint; } });
9
- Object.defineProperty(exports, "BaseCheckpointSaver", { enumerable: true, get: function () { return base_js_1.BaseCheckpointSaver; } });
@@ -1,3 +0,0 @@
1
- export { MemorySaver } from "./memory.js";
2
- export { type Checkpoint, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "./base.js";
3
- export { type CheckpointMetadata } from "./types.js";
@@ -1,2 +0,0 @@
1
- export { MemorySaver } from "./memory.js";
2
- export { copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "./base.js";
@@ -1,195 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MemorySaver = void 0;
4
- const base_js_1 = require("./base.cjs");
5
- function _generateKey(threadId, checkpointNamespace, checkpointId) {
6
- return JSON.stringify([threadId, checkpointNamespace, checkpointId]);
7
- }
8
- class MemorySaver extends base_js_1.BaseCheckpointSaver {
9
- constructor(serde) {
10
- super(serde);
11
- // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping
12
- Object.defineProperty(this, "storage", {
13
- enumerable: true,
14
- configurable: true,
15
- writable: true,
16
- value: {}
17
- });
18
- Object.defineProperty(this, "writes", {
19
- enumerable: true,
20
- configurable: true,
21
- writable: true,
22
- value: {}
23
- });
24
- }
25
- async getTuple(config) {
26
- const thread_id = config.configurable?.thread_id;
27
- const checkpoint_ns = config.configurable?.checkpoint_ns ?? "";
28
- const checkpoint_id = config.configurable?.checkpoint_id;
29
- if (checkpoint_id) {
30
- const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];
31
- if (saved !== undefined) {
32
- const [checkpoint, metadata, parentCheckpointId] = saved;
33
- const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
34
- [];
35
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
36
- return [taskId, channel, await this.serde.parse(value)];
37
- }));
38
- const parentConfig = parentCheckpointId !== undefined
39
- ? {
40
- configurable: {
41
- thread_id,
42
- checkpoint_ns,
43
- checkpoint_id,
44
- },
45
- }
46
- : undefined;
47
- return {
48
- config,
49
- checkpoint: (await this.serde.parse(checkpoint)),
50
- metadata: (await this.serde.parse(metadata)),
51
- pendingWrites,
52
- parentConfig,
53
- };
54
- }
55
- }
56
- else {
57
- const checkpoints = this.storage[thread_id]?.[checkpoint_ns];
58
- if (checkpoints !== undefined) {
59
- const maxThreadTs = Object.keys(checkpoints).sort((a, b) => b.localeCompare(a))[0];
60
- const saved = checkpoints[maxThreadTs];
61
- const [checkpoint, metadata, parentCheckpointId] = saved;
62
- const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
63
- [];
64
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
65
- return [taskId, channel, await this.serde.parse(value)];
66
- }));
67
- const parentConfig = parentCheckpointId !== undefined
68
- ? {
69
- configurable: {
70
- thread_id,
71
- checkpoint_ns,
72
- checkpoint_id: parentCheckpointId,
73
- },
74
- }
75
- : undefined;
76
- return {
77
- config: {
78
- configurable: {
79
- thread_id,
80
- checkpoint_id: maxThreadTs,
81
- checkpoint_ns,
82
- },
83
- },
84
- checkpoint: (await this.serde.parse(checkpoint)),
85
- metadata: (await this.serde.parse(metadata)),
86
- pendingWrites,
87
- parentConfig,
88
- };
89
- }
90
- }
91
- return undefined;
92
- }
93
- async *list(config, options) {
94
- // eslint-disable-next-line prefer-const
95
- let { before, limit } = options ?? {};
96
- const threadIds = config.configurable?.thread_id
97
- ? [config.configurable?.thread_id]
98
- : Object.keys(this.storage);
99
- const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
100
- for (const threadId of threadIds) {
101
- const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};
102
- const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) => b[0].localeCompare(a[0]));
103
- for (const [checkpointId, [checkpoint, metadataStr, parentCheckpointId],] of sortedCheckpoints) {
104
- // Filter by checkpoint ID
105
- if (before &&
106
- before.configurable?.checkpoint_id &&
107
- checkpointId >= before.configurable.checkpoint_id) {
108
- continue;
109
- }
110
- // Parse metadata
111
- const metadata = (await this.serde.parse(metadataStr));
112
- // Limit search results
113
- if (limit !== undefined) {
114
- if (limit <= 0)
115
- break;
116
- // eslint-disable-next-line no-param-reassign
117
- limit -= 1;
118
- }
119
- const writes = this.writes[_generateKey(threadId, checkpointNamespace, checkpointId)] ?? [];
120
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
121
- return [taskId, channel, await this.serde.parse(value)];
122
- }));
123
- yield {
124
- config: {
125
- configurable: {
126
- thread_id: threadId,
127
- checkpoint_ns: checkpointNamespace,
128
- checkpoint_id: checkpointId,
129
- },
130
- },
131
- checkpoint: (await this.serde.parse(checkpoint)),
132
- metadata,
133
- pendingWrites,
134
- parentConfig: parentCheckpointId
135
- ? {
136
- configurable: {
137
- thread_id: threadId,
138
- checkpoint_ns: checkpointNamespace,
139
- checkpoint_id: parentCheckpointId,
140
- },
141
- }
142
- : undefined,
143
- };
144
- }
145
- }
146
- }
147
- async put(config, checkpoint, metadata) {
148
- const threadId = config.configurable?.thread_id;
149
- const checkpointNamespace = config.configurable?.checkpoint_ns;
150
- if (threadId === undefined) {
151
- throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property.`);
152
- }
153
- if (checkpointNamespace === undefined) {
154
- throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "checkpoint_ns" field in its "configurable" property.`);
155
- }
156
- if (!this.storage[threadId]) {
157
- this.storage[threadId] = {};
158
- }
159
- if (!this.storage[threadId][checkpointNamespace]) {
160
- this.storage[threadId][checkpointNamespace] = {};
161
- }
162
- this.storage[threadId][checkpointNamespace][checkpoint.id] = [
163
- this.serde.stringify(checkpoint),
164
- this.serde.stringify(metadata),
165
- config.configurable?.checkpoint_id, // parent
166
- ];
167
- return {
168
- configurable: {
169
- thread_id: threadId,
170
- checkpoint_ns: checkpointNamespace,
171
- checkpoint_id: checkpoint.id,
172
- },
173
- };
174
- }
175
- async putWrites(config, writes, taskId) {
176
- const threadId = config.configurable?.thread_id;
177
- const checkpointNamespace = config.configurable?.checkpoint_ns;
178
- const checkpointId = config.configurable?.checkpoint_id;
179
- if (threadId === undefined) {
180
- throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property`);
181
- }
182
- if (checkpointId === undefined) {
183
- throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "checkpoint_id" field in its "configurable" property.`);
184
- }
185
- const key = _generateKey(threadId, checkpointNamespace, checkpointId);
186
- if (this.writes[key] === undefined) {
187
- this.writes[key] = [];
188
- }
189
- const pendingWrites = writes.map(([channel, value]) => {
190
- return [taskId, channel, this.serde.stringify(value)];
191
- });
192
- this.writes[key].push(...pendingWrites);
193
- }
194
- }
195
- exports.MemorySaver = MemorySaver;
@@ -1,13 +0,0 @@
1
- import { RunnableConfig } from "@langchain/core/runnables";
2
- import { BaseCheckpointSaver, Checkpoint, CheckpointListOptions, CheckpointTuple } from "./base.js";
3
- import { SerializerProtocol } from "../serde/base.js";
4
- import { CheckpointMetadata, CheckpointPendingWrite, PendingWrite } from "../checkpoint/types.js";
5
- export declare class MemorySaver extends BaseCheckpointSaver {
6
- storage: Record<string, Record<string, Record<string, [string, string, string | undefined]>>>;
7
- writes: Record<string, CheckpointPendingWrite[]>;
8
- constructor(serde?: SerializerProtocol<unknown>);
9
- getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined>;
10
- list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
11
- put(config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata): Promise<RunnableConfig>;
12
- putWrites(config: RunnableConfig, writes: PendingWrite[], taskId: string): Promise<void>;
13
- }
@@ -1,191 +0,0 @@
1
- import { BaseCheckpointSaver, } from "./base.js";
2
- function _generateKey(threadId, checkpointNamespace, checkpointId) {
3
- return JSON.stringify([threadId, checkpointNamespace, checkpointId]);
4
- }
5
- export class MemorySaver extends BaseCheckpointSaver {
6
- constructor(serde) {
7
- super(serde);
8
- // thread ID -> checkpoint namespace -> checkpoint ID -> checkpoint mapping
9
- Object.defineProperty(this, "storage", {
10
- enumerable: true,
11
- configurable: true,
12
- writable: true,
13
- value: {}
14
- });
15
- Object.defineProperty(this, "writes", {
16
- enumerable: true,
17
- configurable: true,
18
- writable: true,
19
- value: {}
20
- });
21
- }
22
- async getTuple(config) {
23
- const thread_id = config.configurable?.thread_id;
24
- const checkpoint_ns = config.configurable?.checkpoint_ns ?? "";
25
- const checkpoint_id = config.configurable?.checkpoint_id;
26
- if (checkpoint_id) {
27
- const saved = this.storage[thread_id]?.[checkpoint_ns]?.[checkpoint_id];
28
- if (saved !== undefined) {
29
- const [checkpoint, metadata, parentCheckpointId] = saved;
30
- const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
31
- [];
32
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
33
- return [taskId, channel, await this.serde.parse(value)];
34
- }));
35
- const parentConfig = parentCheckpointId !== undefined
36
- ? {
37
- configurable: {
38
- thread_id,
39
- checkpoint_ns,
40
- checkpoint_id,
41
- },
42
- }
43
- : undefined;
44
- return {
45
- config,
46
- checkpoint: (await this.serde.parse(checkpoint)),
47
- metadata: (await this.serde.parse(metadata)),
48
- pendingWrites,
49
- parentConfig,
50
- };
51
- }
52
- }
53
- else {
54
- const checkpoints = this.storage[thread_id]?.[checkpoint_ns];
55
- if (checkpoints !== undefined) {
56
- const maxThreadTs = Object.keys(checkpoints).sort((a, b) => b.localeCompare(a))[0];
57
- const saved = checkpoints[maxThreadTs];
58
- const [checkpoint, metadata, parentCheckpointId] = saved;
59
- const writes = this.writes[_generateKey(thread_id, checkpoint_ns, checkpoint_id)] ??
60
- [];
61
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
62
- return [taskId, channel, await this.serde.parse(value)];
63
- }));
64
- const parentConfig = parentCheckpointId !== undefined
65
- ? {
66
- configurable: {
67
- thread_id,
68
- checkpoint_ns,
69
- checkpoint_id: parentCheckpointId,
70
- },
71
- }
72
- : undefined;
73
- return {
74
- config: {
75
- configurable: {
76
- thread_id,
77
- checkpoint_id: maxThreadTs,
78
- checkpoint_ns,
79
- },
80
- },
81
- checkpoint: (await this.serde.parse(checkpoint)),
82
- metadata: (await this.serde.parse(metadata)),
83
- pendingWrites,
84
- parentConfig,
85
- };
86
- }
87
- }
88
- return undefined;
89
- }
90
- async *list(config, options) {
91
- // eslint-disable-next-line prefer-const
92
- let { before, limit } = options ?? {};
93
- const threadIds = config.configurable?.thread_id
94
- ? [config.configurable?.thread_id]
95
- : Object.keys(this.storage);
96
- const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
97
- for (const threadId of threadIds) {
98
- const checkpoints = this.storage[threadId]?.[checkpointNamespace] ?? {};
99
- const sortedCheckpoints = Object.entries(checkpoints).sort((a, b) => b[0].localeCompare(a[0]));
100
- for (const [checkpointId, [checkpoint, metadataStr, parentCheckpointId],] of sortedCheckpoints) {
101
- // Filter by checkpoint ID
102
- if (before &&
103
- before.configurable?.checkpoint_id &&
104
- checkpointId >= before.configurable.checkpoint_id) {
105
- continue;
106
- }
107
- // Parse metadata
108
- const metadata = (await this.serde.parse(metadataStr));
109
- // Limit search results
110
- if (limit !== undefined) {
111
- if (limit <= 0)
112
- break;
113
- // eslint-disable-next-line no-param-reassign
114
- limit -= 1;
115
- }
116
- const writes = this.writes[_generateKey(threadId, checkpointNamespace, checkpointId)] ?? [];
117
- const pendingWrites = await Promise.all(writes.map(async ([taskId, channel, value]) => {
118
- return [taskId, channel, await this.serde.parse(value)];
119
- }));
120
- yield {
121
- config: {
122
- configurable: {
123
- thread_id: threadId,
124
- checkpoint_ns: checkpointNamespace,
125
- checkpoint_id: checkpointId,
126
- },
127
- },
128
- checkpoint: (await this.serde.parse(checkpoint)),
129
- metadata,
130
- pendingWrites,
131
- parentConfig: parentCheckpointId
132
- ? {
133
- configurable: {
134
- thread_id: threadId,
135
- checkpoint_ns: checkpointNamespace,
136
- checkpoint_id: parentCheckpointId,
137
- },
138
- }
139
- : undefined,
140
- };
141
- }
142
- }
143
- }
144
- async put(config, checkpoint, metadata) {
145
- const threadId = config.configurable?.thread_id;
146
- const checkpointNamespace = config.configurable?.checkpoint_ns;
147
- if (threadId === undefined) {
148
- throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property.`);
149
- }
150
- if (checkpointNamespace === undefined) {
151
- throw new Error(`Failed to put checkpoint. The passed RunnableConfig is missing a required "checkpoint_ns" field in its "configurable" property.`);
152
- }
153
- if (!this.storage[threadId]) {
154
- this.storage[threadId] = {};
155
- }
156
- if (!this.storage[threadId][checkpointNamespace]) {
157
- this.storage[threadId][checkpointNamespace] = {};
158
- }
159
- this.storage[threadId][checkpointNamespace][checkpoint.id] = [
160
- this.serde.stringify(checkpoint),
161
- this.serde.stringify(metadata),
162
- config.configurable?.checkpoint_id, // parent
163
- ];
164
- return {
165
- configurable: {
166
- thread_id: threadId,
167
- checkpoint_ns: checkpointNamespace,
168
- checkpoint_id: checkpoint.id,
169
- },
170
- };
171
- }
172
- async putWrites(config, writes, taskId) {
173
- const threadId = config.configurable?.thread_id;
174
- const checkpointNamespace = config.configurable?.checkpoint_ns;
175
- const checkpointId = config.configurable?.checkpoint_id;
176
- if (threadId === undefined) {
177
- throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "thread_id" field in its "configurable" property`);
178
- }
179
- if (checkpointId === undefined) {
180
- throw new Error(`Failed to put writes. The passed RunnableConfig is missing a required "checkpoint_id" field in its "configurable" property.`);
181
- }
182
- const key = _generateKey(threadId, checkpointNamespace, checkpointId);
183
- if (this.writes[key] === undefined) {
184
- this.writes[key] = [];
185
- }
186
- const pendingWrites = writes.map(([channel, value]) => {
187
- return [taskId, channel, this.serde.stringify(value)];
188
- });
189
- this.writes[key].push(...pendingWrites);
190
- }
191
- }