@langchain/langgraph 0.0.14 → 0.0.16
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/checkpoint/base.cjs +11 -2
- package/dist/checkpoint/base.d.ts +6 -4
- package/dist/checkpoint/base.js +8 -1
- package/dist/checkpoint/memory.cjs +6 -6
- package/dist/checkpoint/memory.js +6 -6
- package/dist/checkpoint/sqlite.cjs +6 -6
- package/dist/checkpoint/sqlite.js +6 -6
- package/dist/pregel/index.cjs +8 -9
- package/dist/pregel/index.js +9 -10
- package/dist/serde/base.cjs +6 -0
- package/dist/serde/base.d.ts +9 -1
- package/dist/serde/base.js +5 -1
- package/dist/tests/pregel.test.js +27 -0
- package/package.json +1 -1
package/dist/checkpoint/base.cjs
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BaseCheckpointSaver = exports.copyCheckpoint = exports.emptyCheckpoint = exports.deepCopy = void 0;
|
|
3
|
+
exports.BaseCheckpointSaver = exports.copyCheckpoint = exports.emptyCheckpoint = exports.deepCopy = exports.getVersionSeen = exports.getChannelVersion = void 0;
|
|
4
|
+
const base_js_1 = require("../serde/base.cjs");
|
|
4
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;
|
|
5
14
|
function deepCopy(obj) {
|
|
6
15
|
if (typeof obj !== "object" || obj === null) {
|
|
7
16
|
return obj;
|
|
@@ -43,7 +52,7 @@ class BaseCheckpointSaver {
|
|
|
43
52
|
enumerable: true,
|
|
44
53
|
configurable: true,
|
|
45
54
|
writable: true,
|
|
46
|
-
value:
|
|
55
|
+
value: base_js_1.DefaultSerializer
|
|
47
56
|
});
|
|
48
57
|
this.serde = serde || this.serde;
|
|
49
58
|
}
|
|
@@ -15,7 +15,7 @@ export interface CheckpointMetadata {
|
|
|
15
15
|
* ... for the nth checkpoint afterwards. */
|
|
16
16
|
writes?: Record<string, unknown>;
|
|
17
17
|
}
|
|
18
|
-
export interface Checkpoint {
|
|
18
|
+
export interface Checkpoint<N extends string = string, C extends string = string> {
|
|
19
19
|
/**
|
|
20
20
|
* Version number
|
|
21
21
|
*/
|
|
@@ -31,21 +31,23 @@ export interface Checkpoint {
|
|
|
31
31
|
/**
|
|
32
32
|
* @default {}
|
|
33
33
|
*/
|
|
34
|
-
channel_values: Record<
|
|
34
|
+
channel_values: Record<C, unknown>;
|
|
35
35
|
/**
|
|
36
36
|
* @default {}
|
|
37
37
|
*/
|
|
38
|
-
channel_versions: Record<
|
|
38
|
+
channel_versions: Record<C, number>;
|
|
39
39
|
/**
|
|
40
40
|
* @default {}
|
|
41
41
|
*/
|
|
42
|
-
versions_seen: Record<
|
|
42
|
+
versions_seen: Record<N, Record<C, number>>;
|
|
43
43
|
}
|
|
44
44
|
export interface ReadonlyCheckpoint extends Readonly<Checkpoint> {
|
|
45
45
|
readonly channel_values: Readonly<Record<string, unknown>>;
|
|
46
46
|
readonly channel_versions: Readonly<Record<string, number>>;
|
|
47
47
|
readonly versions_seen: Readonly<Record<string, Readonly<Record<string, number>>>>;
|
|
48
48
|
}
|
|
49
|
+
export declare function getChannelVersion(checkpoint: ReadonlyCheckpoint, channel: string): number;
|
|
50
|
+
export declare function getVersionSeen(checkpoint: ReadonlyCheckpoint, node: string, channel: string): number;
|
|
49
51
|
export declare function deepCopy<T>(obj: T): T;
|
|
50
52
|
export declare function emptyCheckpoint(): Checkpoint;
|
|
51
53
|
export declare function copyCheckpoint(checkpoint: ReadonlyCheckpoint): Checkpoint;
|
package/dist/checkpoint/base.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { DefaultSerializer } from "../serde/base.js";
|
|
1
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
|
+
}
|
|
2
9
|
export function deepCopy(obj) {
|
|
3
10
|
if (typeof obj !== "object" || obj === null) {
|
|
4
11
|
return obj;
|
|
@@ -37,7 +44,7 @@ export class BaseCheckpointSaver {
|
|
|
37
44
|
enumerable: true,
|
|
38
45
|
configurable: true,
|
|
39
46
|
writable: true,
|
|
40
|
-
value:
|
|
47
|
+
value: DefaultSerializer
|
|
41
48
|
});
|
|
42
49
|
this.serde = serde || this.serde;
|
|
43
50
|
}
|
|
@@ -22,8 +22,8 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
|
|
|
22
22
|
if (checkpoint) {
|
|
23
23
|
return {
|
|
24
24
|
config,
|
|
25
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
26
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
25
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
26
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -33,8 +33,8 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
|
|
|
33
33
|
const checkpoint = checkpoints[maxThreadTs];
|
|
34
34
|
return {
|
|
35
35
|
config: { configurable: { thread_id, checkpoint_id: maxThreadTs } },
|
|
36
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
37
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
36
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
37
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -50,8 +50,8 @@ class MemorySaver extends base_js_1.BaseCheckpointSaver {
|
|
|
50
50
|
.slice(0, limit)) {
|
|
51
51
|
yield {
|
|
52
52
|
config: { configurable: { thread_id, checkpoint_id } },
|
|
53
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
54
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
53
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
54
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -19,8 +19,8 @@ export class MemorySaver extends BaseCheckpointSaver {
|
|
|
19
19
|
if (checkpoint) {
|
|
20
20
|
return {
|
|
21
21
|
config,
|
|
22
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
23
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
22
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
23
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -30,8 +30,8 @@ export class MemorySaver extends BaseCheckpointSaver {
|
|
|
30
30
|
const checkpoint = checkpoints[maxThreadTs];
|
|
31
31
|
return {
|
|
32
32
|
config: { configurable: { thread_id, checkpoint_id: maxThreadTs } },
|
|
33
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
34
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
33
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
34
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -47,8 +47,8 @@ export class MemorySaver extends BaseCheckpointSaver {
|
|
|
47
47
|
.slice(0, limit)) {
|
|
48
48
|
yield {
|
|
49
49
|
config: { configurable: { thread_id, checkpoint_id } },
|
|
50
|
-
checkpoint: this.serde.parse(checkpoint[0]),
|
|
51
|
-
metadata: this.serde.parse(checkpoint[1]),
|
|
50
|
+
checkpoint: (await this.serde.parse(checkpoint[0])),
|
|
51
|
+
metadata: (await this.serde.parse(checkpoint[1])),
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -61,8 +61,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
61
61
|
if (row) {
|
|
62
62
|
return {
|
|
63
63
|
config,
|
|
64
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
65
|
-
metadata: this.serde.parse(row.metadata),
|
|
64
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
65
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
66
66
|
parentConfig: row.parent_id
|
|
67
67
|
? {
|
|
68
68
|
configurable: {
|
|
@@ -91,8 +91,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
91
91
|
checkpoint_id: row.checkpoint_id,
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
95
|
-
metadata: this.serde.parse(row.metadata),
|
|
94
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
95
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
96
96
|
parentConfig: row.parent_id
|
|
97
97
|
? {
|
|
98
98
|
configurable: {
|
|
@@ -125,8 +125,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
125
125
|
checkpoint_id: row.checkpoint_id,
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
129
|
-
metadata: this.serde.parse(row.metadata),
|
|
128
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
129
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
130
130
|
parentConfig: row.parent_id
|
|
131
131
|
? {
|
|
132
132
|
configurable: {
|
|
@@ -55,8 +55,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
55
55
|
if (row) {
|
|
56
56
|
return {
|
|
57
57
|
config,
|
|
58
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
59
|
-
metadata: this.serde.parse(row.metadata),
|
|
58
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
59
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
60
60
|
parentConfig: row.parent_id
|
|
61
61
|
? {
|
|
62
62
|
configurable: {
|
|
@@ -85,8 +85,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
85
85
|
checkpoint_id: row.checkpoint_id,
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
89
|
-
metadata: this.serde.parse(row.metadata),
|
|
88
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
89
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
90
90
|
parentConfig: row.parent_id
|
|
91
91
|
? {
|
|
92
92
|
configurable: {
|
|
@@ -119,8 +119,8 @@ CREATE TABLE IF NOT EXISTS checkpoints (
|
|
|
119
119
|
checkpoint_id: row.checkpoint_id,
|
|
120
120
|
},
|
|
121
121
|
},
|
|
122
|
-
checkpoint: this.serde.parse(row.checkpoint),
|
|
123
|
-
metadata: this.serde.parse(row.metadata),
|
|
122
|
+
checkpoint: (await this.serde.parse(row.checkpoint)),
|
|
123
|
+
metadata: (await this.serde.parse(row.metadata)),
|
|
124
124
|
parentConfig: row.parent_id
|
|
125
125
|
? {
|
|
126
126
|
configurable: {
|
package/dist/pregel/index.cjs
CHANGED
|
@@ -551,8 +551,8 @@ async function executeTasks(tasks, stepTimeout) {
|
|
|
551
551
|
}
|
|
552
552
|
}
|
|
553
553
|
function _shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, tasks) {
|
|
554
|
-
const
|
|
555
|
-
|
|
554
|
+
const anySnapshotChannelUpdated = snapshotChannels.some((chan) => (0, base_js_2.getChannelVersion)(checkpoint, chan) >
|
|
555
|
+
(0, base_js_2.getVersionSeen)(checkpoint, constants_js_1.INTERRUPT, chan));
|
|
556
556
|
const anyTaskNodeInInterruptNodes = tasks.some((task) => interruptNodes === "*"
|
|
557
557
|
? !task.config?.tags?.includes(constants_js_1.TAG_HIDDEN)
|
|
558
558
|
: interruptNodes.includes(task.name));
|
|
@@ -627,11 +627,6 @@ function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
|
627
627
|
// Check if any processes should be run in next step
|
|
628
628
|
// If so, prepare the values to be passed to them
|
|
629
629
|
for (const [name, proc] of Object.entries(processes)) {
|
|
630
|
-
let seen = newCheckpoint.versions_seen[name];
|
|
631
|
-
if (!seen) {
|
|
632
|
-
newCheckpoint.versions_seen[name] = {};
|
|
633
|
-
seen = newCheckpoint.versions_seen[name];
|
|
634
|
-
}
|
|
635
630
|
// If any of the channels read by this process were updated
|
|
636
631
|
if (proc.triggers
|
|
637
632
|
.filter((chan) => {
|
|
@@ -643,7 +638,8 @@ function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
|
643
638
|
return false;
|
|
644
639
|
}
|
|
645
640
|
})
|
|
646
|
-
.some((chan) => newCheckpoint
|
|
641
|
+
.some((chan) => (0, base_js_2.getChannelVersion)(newCheckpoint, chan) >
|
|
642
|
+
(0, base_js_2.getVersionSeen)(newCheckpoint, name, chan))) {
|
|
647
643
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
648
644
|
let val;
|
|
649
645
|
// If all trigger channels subscribed by this process are not empty
|
|
@@ -696,11 +692,14 @@ function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
|
696
692
|
}
|
|
697
693
|
if (forExecution) {
|
|
698
694
|
// Update seen versions
|
|
695
|
+
if (!newCheckpoint.versions_seen[name]) {
|
|
696
|
+
newCheckpoint.versions_seen[name] = {};
|
|
697
|
+
}
|
|
699
698
|
proc.triggers.forEach((chan) => {
|
|
700
699
|
const version = newCheckpoint.channel_versions[chan];
|
|
701
700
|
if (version !== undefined) {
|
|
702
701
|
// side effect: updates newCheckpoint
|
|
703
|
-
|
|
702
|
+
newCheckpoint.versions_seen[name][chan] = version;
|
|
704
703
|
}
|
|
705
704
|
});
|
|
706
705
|
const node = proc.getNode();
|
package/dist/pregel/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Runnable, RunnableSequence, _coerceToRunnable, ensureConfig, patchConfig, } from "@langchain/core/runnables";
|
|
3
3
|
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
4
4
|
import { createCheckpoint, emptyChannels, } from "../channels/base.js";
|
|
5
|
-
import { copyCheckpoint, emptyCheckpoint, } from "../checkpoint/base.js";
|
|
5
|
+
import { copyCheckpoint, emptyCheckpoint, getChannelVersion, getVersionSeen, } from "../checkpoint/base.js";
|
|
6
6
|
import { PregelNode } from "./read.js";
|
|
7
7
|
import { validateGraph, validateKeys } from "./validate.js";
|
|
8
8
|
import { mapInput, mapOutputUpdates, mapOutputValues, readChannel, readChannels, single, } from "./io.js";
|
|
@@ -546,8 +546,8 @@ async function executeTasks(tasks, stepTimeout) {
|
|
|
546
546
|
}
|
|
547
547
|
}
|
|
548
548
|
export function _shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, tasks) {
|
|
549
|
-
const
|
|
550
|
-
|
|
549
|
+
const anySnapshotChannelUpdated = snapshotChannels.some((chan) => getChannelVersion(checkpoint, chan) >
|
|
550
|
+
getVersionSeen(checkpoint, INTERRUPT, chan));
|
|
551
551
|
const anyTaskNodeInInterruptNodes = tasks.some((task) => interruptNodes === "*"
|
|
552
552
|
? !task.config?.tags?.includes(TAG_HIDDEN)
|
|
553
553
|
: interruptNodes.includes(task.name));
|
|
@@ -619,11 +619,6 @@ export function _prepareNextTasks(checkpoint, processes, channels, forExecution)
|
|
|
619
619
|
// Check if any processes should be run in next step
|
|
620
620
|
// If so, prepare the values to be passed to them
|
|
621
621
|
for (const [name, proc] of Object.entries(processes)) {
|
|
622
|
-
let seen = newCheckpoint.versions_seen[name];
|
|
623
|
-
if (!seen) {
|
|
624
|
-
newCheckpoint.versions_seen[name] = {};
|
|
625
|
-
seen = newCheckpoint.versions_seen[name];
|
|
626
|
-
}
|
|
627
622
|
// If any of the channels read by this process were updated
|
|
628
623
|
if (proc.triggers
|
|
629
624
|
.filter((chan) => {
|
|
@@ -635,7 +630,8 @@ export function _prepareNextTasks(checkpoint, processes, channels, forExecution)
|
|
|
635
630
|
return false;
|
|
636
631
|
}
|
|
637
632
|
})
|
|
638
|
-
.some((chan) => newCheckpoint
|
|
633
|
+
.some((chan) => getChannelVersion(newCheckpoint, chan) >
|
|
634
|
+
getVersionSeen(newCheckpoint, name, chan))) {
|
|
639
635
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
640
636
|
let val;
|
|
641
637
|
// If all trigger channels subscribed by this process are not empty
|
|
@@ -688,11 +684,14 @@ export function _prepareNextTasks(checkpoint, processes, channels, forExecution)
|
|
|
688
684
|
}
|
|
689
685
|
if (forExecution) {
|
|
690
686
|
// Update seen versions
|
|
687
|
+
if (!newCheckpoint.versions_seen[name]) {
|
|
688
|
+
newCheckpoint.versions_seen[name] = {};
|
|
689
|
+
}
|
|
691
690
|
proc.triggers.forEach((chan) => {
|
|
692
691
|
const version = newCheckpoint.channel_versions[chan];
|
|
693
692
|
if (version !== undefined) {
|
|
694
693
|
// side effect: updates newCheckpoint
|
|
695
|
-
|
|
694
|
+
newCheckpoint.versions_seen[name][chan] = version;
|
|
696
695
|
}
|
|
697
696
|
});
|
|
698
697
|
const node = proc.getNode();
|
package/dist/serde/base.cjs
CHANGED
package/dist/serde/base.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import { load } from "@langchain/core/load";
|
|
1
2
|
export interface SerializerProtocol<D> {
|
|
2
3
|
stringify(obj: D): string;
|
|
3
|
-
parse(data: string): D
|
|
4
|
+
parse(data: string): Promise<D>;
|
|
4
5
|
}
|
|
6
|
+
export declare const DefaultSerializer: {
|
|
7
|
+
stringify: {
|
|
8
|
+
(value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
|
|
9
|
+
(value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
|
|
10
|
+
};
|
|
11
|
+
parse: typeof load;
|
|
12
|
+
};
|
package/dist/serde/base.js
CHANGED
|
@@ -209,6 +209,33 @@ describe("_shouldInterrupt", () => {
|
|
|
209
209
|
},
|
|
210
210
|
])).toBe(true);
|
|
211
211
|
});
|
|
212
|
+
it("should return true if any snapshot channel has been updated since last interrupt and any channel written to is in interrupt nodes list", () => {
|
|
213
|
+
// set up test
|
|
214
|
+
const checkpoint = {
|
|
215
|
+
v: 1,
|
|
216
|
+
id: uuid6(-1),
|
|
217
|
+
ts: "2024-04-19T17:19:07.952Z",
|
|
218
|
+
channel_values: {
|
|
219
|
+
channel1: "channel1value",
|
|
220
|
+
},
|
|
221
|
+
channel_versions: {
|
|
222
|
+
channel1: 2, // current channel version is greater than last version seen
|
|
223
|
+
},
|
|
224
|
+
versions_seen: {},
|
|
225
|
+
};
|
|
226
|
+
const interruptNodes = ["node1"];
|
|
227
|
+
const snapshotChannels = ["channel1"];
|
|
228
|
+
// call method / assertions
|
|
229
|
+
expect(_shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, [
|
|
230
|
+
{
|
|
231
|
+
name: "node1",
|
|
232
|
+
input: undefined,
|
|
233
|
+
proc: new RunnablePassthrough(),
|
|
234
|
+
writes: [],
|
|
235
|
+
config: undefined,
|
|
236
|
+
},
|
|
237
|
+
])).toBe(true);
|
|
238
|
+
});
|
|
212
239
|
it("should return false if all snapshot channels have not been updated", () => {
|
|
213
240
|
// set up test
|
|
214
241
|
const checkpoint = {
|