@langchain/langgraph 0.2.41 → 0.2.43-rc.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.
- package/README.md +237 -154
- package/dist/channels/any_value.cjs +10 -10
- package/dist/channels/any_value.d.ts +1 -1
- package/dist/channels/any_value.js +10 -10
- package/dist/channels/ephemeral_value.cjs +10 -9
- package/dist/channels/ephemeral_value.d.ts +1 -1
- package/dist/channels/ephemeral_value.js +10 -9
- package/dist/channels/last_value.cjs +8 -7
- package/dist/channels/last_value.d.ts +1 -1
- package/dist/channels/last_value.js +8 -7
- package/dist/constants.cjs +33 -6
- package/dist/constants.d.ts +17 -2
- package/dist/constants.js +32 -5
- package/dist/errors.d.ts +3 -3
- package/dist/func/index.cjs +272 -0
- package/dist/func/index.d.ts +310 -0
- package/dist/func/index.js +267 -0
- package/dist/func/types.cjs +15 -0
- package/dist/func/types.d.ts +59 -0
- package/dist/func/types.js +11 -0
- package/dist/graph/graph.cjs +31 -35
- package/dist/graph/graph.d.ts +1 -5
- package/dist/graph/graph.js +1 -5
- package/dist/graph/index.cjs +1 -3
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/index.js +1 -1
- package/dist/graph/message.d.ts +1 -1
- package/dist/graph/state.cjs +17 -17
- package/dist/graph/state.d.ts +2 -1
- package/dist/graph/state.js +2 -2
- package/dist/index.cjs +8 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/interrupt.cjs +21 -34
- package/dist/interrupt.d.ts +1 -1
- package/dist/interrupt.js +22 -35
- package/dist/prebuilt/agent_executor.cjs +3 -3
- package/dist/prebuilt/agent_executor.d.ts +1 -1
- package/dist/prebuilt/agent_executor.js +1 -1
- package/dist/prebuilt/chat_agent_executor.cjs +3 -3
- package/dist/prebuilt/chat_agent_executor.d.ts +1 -1
- package/dist/prebuilt/chat_agent_executor.js +1 -1
- package/dist/prebuilt/react_agent_executor.cjs +33 -8
- package/dist/prebuilt/react_agent_executor.d.ts +4 -1
- package/dist/prebuilt/react_agent_executor.js +31 -6
- package/dist/prebuilt/tool_node.cjs +1 -2
- package/dist/prebuilt/tool_node.d.ts +1 -1
- package/dist/prebuilt/tool_node.js +1 -2
- package/dist/pregel/algo.cjs +121 -12
- package/dist/pregel/algo.d.ts +8 -6
- package/dist/pregel/algo.js +122 -13
- package/dist/pregel/call.cjs +77 -0
- package/dist/pregel/call.d.ts +15 -0
- package/dist/pregel/call.js +71 -0
- package/dist/pregel/index.cjs +59 -96
- package/dist/pregel/index.d.ts +1 -10
- package/dist/pregel/index.js +61 -98
- package/dist/pregel/io.cjs +6 -1
- package/dist/pregel/io.js +7 -2
- package/dist/pregel/loop.cjs +109 -75
- package/dist/pregel/loop.d.ts +17 -23
- package/dist/pregel/loop.js +110 -75
- package/dist/pregel/messages.d.ts +1 -1
- package/dist/pregel/retry.cjs +22 -50
- package/dist/pregel/retry.d.ts +6 -6
- package/dist/pregel/retry.js +22 -50
- package/dist/pregel/runner.cjs +275 -0
- package/dist/pregel/runner.d.ts +64 -0
- package/dist/pregel/runner.js +271 -0
- package/dist/pregel/stream.cjs +71 -0
- package/dist/pregel/stream.d.ts +17 -0
- package/dist/pregel/stream.js +67 -0
- package/dist/pregel/types.cjs +54 -0
- package/dist/pregel/types.d.ts +78 -6
- package/dist/pregel/types.js +51 -1
- package/dist/pregel/utils/config.cjs +26 -1
- package/dist/pregel/utils/config.d.ts +14 -0
- package/dist/pregel/utils/config.js +22 -0
- package/dist/pregel/write.d.ts +1 -1
- package/dist/utils.cjs +15 -1
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +12 -0
- package/dist/web.cjs +7 -5
- package/dist/web.d.ts +4 -4
- package/dist/web.js +3 -3
- package/package.json +8 -8
package/dist/pregel/index.js
CHANGED
|
@@ -7,17 +7,18 @@ import { validateGraph, validateKeys } from "./validate.js";
|
|
|
7
7
|
import { readChannels } from "./io.js";
|
|
8
8
|
import { printStepCheckpoint, printStepTasks, printStepWrites, tasksWithWrites, } from "./debug.js";
|
|
9
9
|
import { ChannelWrite, PASSTHROUGH } from "./write.js";
|
|
10
|
-
import { CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_READ, CONFIG_KEY_SEND, ERROR, INTERRUPT, CHECKPOINT_NAMESPACE_SEPARATOR, CHECKPOINT_NAMESPACE_END, CONFIG_KEY_STREAM, CONFIG_KEY_TASK_ID, NULL_TASK_ID, INPUT,
|
|
11
|
-
import { GraphRecursionError, GraphValueError, InvalidUpdateError,
|
|
10
|
+
import { CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_READ, CONFIG_KEY_SEND, ERROR, INTERRUPT, CHECKPOINT_NAMESPACE_SEPARATOR, CHECKPOINT_NAMESPACE_END, CONFIG_KEY_STREAM, CONFIG_KEY_TASK_ID, NULL_TASK_ID, INPUT, PUSH, } from "../constants.js";
|
|
11
|
+
import { GraphRecursionError, GraphValueError, InvalidUpdateError, } from "../errors.js";
|
|
12
12
|
import { _prepareNextTasks, _localRead, _applyWrites, } from "./algo.js";
|
|
13
13
|
import { _coerceToDict, getNewChannelVersions, patchCheckpointMap, } from "./utils/index.js";
|
|
14
14
|
import { findSubgraphPregel } from "./utils/subgraph.js";
|
|
15
|
-
import { PregelLoop
|
|
16
|
-
import { executeTasksWithRetry } from "./retry.js";
|
|
15
|
+
import { PregelLoop } from "./loop.js";
|
|
17
16
|
import { ChannelKeyPlaceholder, isConfiguredManagedValue, ManagedValueMapping, NoopManagedValue, } from "../managed/base.js";
|
|
18
17
|
import { gatherIterator, patchConfigurable } from "../utils.js";
|
|
19
18
|
import { ensureLangGraphConfig } from "./utils/config.js";
|
|
20
19
|
import { StreamMessagesHandler } from "./messages.js";
|
|
20
|
+
import { PregelRunner } from "./runner.js";
|
|
21
|
+
import { IterableReadableWritableStream } from "./stream.js";
|
|
21
22
|
function isString(value) {
|
|
22
23
|
return typeof value === "string";
|
|
23
24
|
}
|
|
@@ -820,92 +821,6 @@ export class Pregel extends Runnable {
|
|
|
820
821
|
managed,
|
|
821
822
|
};
|
|
822
823
|
}
|
|
823
|
-
async _runLoop(params) {
|
|
824
|
-
const { loop, interruptAfter, interruptBefore, runManager, debug, config } = params;
|
|
825
|
-
let tickError;
|
|
826
|
-
try {
|
|
827
|
-
while (await loop.tick({
|
|
828
|
-
inputKeys: this.inputChannels,
|
|
829
|
-
interruptAfter,
|
|
830
|
-
interruptBefore,
|
|
831
|
-
manager: runManager,
|
|
832
|
-
})) {
|
|
833
|
-
if (debug) {
|
|
834
|
-
printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
|
|
835
|
-
}
|
|
836
|
-
if (debug) {
|
|
837
|
-
printStepTasks(loop.step, Object.values(loop.tasks));
|
|
838
|
-
}
|
|
839
|
-
// execute tasks, and wait for one to fail or all to finish.
|
|
840
|
-
// each task is independent from all other concurrent tasks
|
|
841
|
-
// yield updates/debug output as each task finishes
|
|
842
|
-
const taskStream = executeTasksWithRetry(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
|
|
843
|
-
stepTimeout: this.stepTimeout,
|
|
844
|
-
signal: config.signal,
|
|
845
|
-
retryPolicy: this.retryPolicy,
|
|
846
|
-
});
|
|
847
|
-
let graphInterrupt;
|
|
848
|
-
for await (const { task, error } of taskStream) {
|
|
849
|
-
if (error !== undefined) {
|
|
850
|
-
if (isGraphBubbleUp(error)) {
|
|
851
|
-
if (loop.isNested) {
|
|
852
|
-
throw error;
|
|
853
|
-
}
|
|
854
|
-
if (isGraphInterrupt(error)) {
|
|
855
|
-
graphInterrupt = error;
|
|
856
|
-
if (error.interrupts.length) {
|
|
857
|
-
const interrupts = error.interrupts.map((interrupt) => [INTERRUPT, interrupt]);
|
|
858
|
-
const resumes = task.writes.filter((w) => w[0] === RESUME);
|
|
859
|
-
if (resumes.length) {
|
|
860
|
-
interrupts.push(...resumes);
|
|
861
|
-
}
|
|
862
|
-
loop.putWrites(task.id, interrupts);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
else {
|
|
867
|
-
loop.putWrites(task.id, [
|
|
868
|
-
[ERROR, { message: error.message, name: error.name }],
|
|
869
|
-
]);
|
|
870
|
-
throw error;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
else {
|
|
874
|
-
loop.putWrites(task.id, task.writes);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
if (debug) {
|
|
878
|
-
printStepWrites(loop.step, Object.values(loop.tasks)
|
|
879
|
-
.map((task) => task.writes)
|
|
880
|
-
.flat(), this.streamChannelsList);
|
|
881
|
-
}
|
|
882
|
-
if (graphInterrupt !== undefined) {
|
|
883
|
-
throw graphInterrupt;
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
if (loop.status === "out_of_steps") {
|
|
887
|
-
throw new GraphRecursionError([
|
|
888
|
-
`Recursion limit of ${config.recursionLimit} reached`,
|
|
889
|
-
"without hitting a stop condition. You can increase the",
|
|
890
|
-
`limit by setting the "recursionLimit" config key.`,
|
|
891
|
-
].join(" "), {
|
|
892
|
-
lc_error_code: "GRAPH_RECURSION_LIMIT",
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
catch (e) {
|
|
897
|
-
tickError = e;
|
|
898
|
-
const suppress = await loop.finishAndHandleError(tickError);
|
|
899
|
-
if (!suppress) {
|
|
900
|
-
throw e;
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
finally {
|
|
904
|
-
if (tickError === undefined) {
|
|
905
|
-
await loop.finishAndHandleError();
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
824
|
async *_streamIterator(input, options) {
|
|
910
825
|
const streamSubgraphs = options?.subgraphs;
|
|
911
826
|
const inputConfig = ensureLangGraphConfig(this.config, options);
|
|
@@ -970,6 +885,14 @@ export class Pregel extends Runnable {
|
|
|
970
885
|
streamKeys: this.streamChannelsAsIs,
|
|
971
886
|
store,
|
|
972
887
|
stream,
|
|
888
|
+
interruptAfter,
|
|
889
|
+
interruptBefore,
|
|
890
|
+
manager: runManager,
|
|
891
|
+
debug: this.debug,
|
|
892
|
+
});
|
|
893
|
+
const runner = new PregelRunner({
|
|
894
|
+
loop,
|
|
895
|
+
nodeFinished: config.configurable?.nodeFinished,
|
|
973
896
|
});
|
|
974
897
|
if (options?.subgraphs) {
|
|
975
898
|
loop.config.configurable = {
|
|
@@ -977,14 +900,7 @@ export class Pregel extends Runnable {
|
|
|
977
900
|
[CONFIG_KEY_STREAM]: loop.stream,
|
|
978
901
|
};
|
|
979
902
|
}
|
|
980
|
-
await this._runLoop({
|
|
981
|
-
loop,
|
|
982
|
-
interruptAfter,
|
|
983
|
-
interruptBefore,
|
|
984
|
-
runManager,
|
|
985
|
-
debug,
|
|
986
|
-
config,
|
|
987
|
-
});
|
|
903
|
+
await this._runLoop({ loop, runner, debug, config });
|
|
988
904
|
}
|
|
989
905
|
catch (e) {
|
|
990
906
|
loopError = e;
|
|
@@ -1082,4 +998,51 @@ export class Pregel extends Runnable {
|
|
|
1082
998
|
}
|
|
1083
999
|
return chunks;
|
|
1084
1000
|
}
|
|
1001
|
+
async _runLoop(params) {
|
|
1002
|
+
const { loop, runner, debug, config } = params;
|
|
1003
|
+
let tickError;
|
|
1004
|
+
try {
|
|
1005
|
+
while (await loop.tick({
|
|
1006
|
+
inputKeys: this.inputChannels,
|
|
1007
|
+
})) {
|
|
1008
|
+
if (debug) {
|
|
1009
|
+
printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
|
|
1010
|
+
}
|
|
1011
|
+
if (debug) {
|
|
1012
|
+
printStepTasks(loop.step, Object.values(loop.tasks));
|
|
1013
|
+
}
|
|
1014
|
+
await runner.tick({
|
|
1015
|
+
timeout: this.stepTimeout,
|
|
1016
|
+
retryPolicy: this.retryPolicy,
|
|
1017
|
+
onStepWrite: (step, writes) => {
|
|
1018
|
+
if (debug) {
|
|
1019
|
+
printStepWrites(step, writes, this.streamChannelsList);
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
signal: config.signal,
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
if (loop.status === "out_of_steps") {
|
|
1026
|
+
throw new GraphRecursionError([
|
|
1027
|
+
`Recursion limit of ${config.recursionLimit} reached`,
|
|
1028
|
+
"without hitting a stop condition. You can increase the",
|
|
1029
|
+
`limit by setting the "recursionLimit" config key.`,
|
|
1030
|
+
].join(" "), {
|
|
1031
|
+
lc_error_code: "GRAPH_RECURSION_LIMIT",
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
catch (e) {
|
|
1036
|
+
tickError = e;
|
|
1037
|
+
const suppress = await loop.finishAndHandleError(tickError);
|
|
1038
|
+
if (!suppress) {
|
|
1039
|
+
throw e;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
finally {
|
|
1043
|
+
if (tickError === undefined) {
|
|
1044
|
+
await loop.finishAndHandleError();
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1085
1048
|
}
|
package/dist/pregel/io.cjs
CHANGED
|
@@ -171,7 +171,12 @@ function* mapOutputUpdates(outputChannels, tasks, cached
|
|
|
171
171
|
}
|
|
172
172
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
173
173
|
let updated;
|
|
174
|
-
if (
|
|
174
|
+
if (outputTasks.some(([task]) => task.writes.some(([chan, _]) => chan === constants_js_1.RETURN))) {
|
|
175
|
+
updated = outputTasks.flatMap(([task]) => task.writes
|
|
176
|
+
.filter(([chan, _]) => chan === constants_js_1.RETURN)
|
|
177
|
+
.map(([_, value]) => [task.name, value]));
|
|
178
|
+
}
|
|
179
|
+
else if (!Array.isArray(outputChannels)) {
|
|
175
180
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
176
181
|
.filter(([chan, _]) => chan === outputChannels)
|
|
177
182
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
package/dist/pregel/io.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { validate } from "uuid";
|
|
2
|
-
import { _isSend, Command, ERROR, INTERRUPT, NULL_TASK_ID, RESUME, SELF, TAG_HIDDEN, TASKS, } from "../constants.js";
|
|
2
|
+
import { _isSend, Command, ERROR, INTERRUPT, NULL_TASK_ID, RESUME, RETURN, SELF, TAG_HIDDEN, TASKS, } from "../constants.js";
|
|
3
3
|
import { EmptyChannelError, InvalidUpdateError } from "../errors.js";
|
|
4
4
|
export function readChannel(channels, chan, catchErrors = true, returnException = false) {
|
|
5
5
|
try {
|
|
@@ -163,7 +163,12 @@ export function* mapOutputUpdates(outputChannels, tasks, cached
|
|
|
163
163
|
}
|
|
164
164
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
165
165
|
let updated;
|
|
166
|
-
if (
|
|
166
|
+
if (outputTasks.some(([task]) => task.writes.some(([chan, _]) => chan === RETURN))) {
|
|
167
|
+
updated = outputTasks.flatMap(([task]) => task.writes
|
|
168
|
+
.filter(([chan, _]) => chan === RETURN)
|
|
169
|
+
.map(([_, value]) => [task.name, value]));
|
|
170
|
+
}
|
|
171
|
+
else if (!Array.isArray(outputChannels)) {
|
|
167
172
|
updated = outputTasks.flatMap(([task]) => task.writes
|
|
168
173
|
.filter(([chan, _]) => chan === outputChannels)
|
|
169
174
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
package/dist/pregel/loop.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PregelLoop =
|
|
4
|
-
const stream_1 = require("@langchain/core/utils/stream");
|
|
3
|
+
exports.PregelLoop = void 0;
|
|
5
4
|
const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
|
|
6
5
|
const base_js_1 = require("../channels/base.cjs");
|
|
7
6
|
const constants_js_1 = require("../constants.cjs");
|
|
@@ -11,66 +10,12 @@ const io_js_1 = require("./io.cjs");
|
|
|
11
10
|
const errors_js_1 = require("../errors.cjs");
|
|
12
11
|
const index_js_1 = require("./utils/index.cjs");
|
|
13
12
|
const debug_js_1 = require("./debug.cjs");
|
|
13
|
+
const stream_js_1 = require("./stream.cjs");
|
|
14
14
|
const INPUT_DONE = Symbol.for("INPUT_DONE");
|
|
15
15
|
const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
|
|
16
16
|
const DEFAULT_LOOP_LIMIT = 25;
|
|
17
|
-
class IterableReadableWritableStream extends stream_1.IterableReadableStream {
|
|
18
|
-
constructor(params) {
|
|
19
|
-
let streamControllerPromiseResolver;
|
|
20
|
-
const streamControllerPromise = new Promise((resolve) => {
|
|
21
|
-
streamControllerPromiseResolver = resolve;
|
|
22
|
-
});
|
|
23
|
-
super({
|
|
24
|
-
start: (controller) => {
|
|
25
|
-
streamControllerPromiseResolver(controller);
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
Object.defineProperty(this, "modes", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: void 0
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "controller", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: void 0
|
|
39
|
-
});
|
|
40
|
-
Object.defineProperty(this, "passthroughFn", {
|
|
41
|
-
enumerable: true,
|
|
42
|
-
configurable: true,
|
|
43
|
-
writable: true,
|
|
44
|
-
value: void 0
|
|
45
|
-
});
|
|
46
|
-
// .start() will always be called before the stream can be interacted
|
|
47
|
-
// with anyway
|
|
48
|
-
void streamControllerPromise.then((controller) => {
|
|
49
|
-
this.controller = controller;
|
|
50
|
-
});
|
|
51
|
-
this.passthroughFn = params.passthroughFn;
|
|
52
|
-
this.modes = params.modes;
|
|
53
|
-
}
|
|
54
|
-
push(chunk) {
|
|
55
|
-
this.passthroughFn?.(chunk);
|
|
56
|
-
this.controller.enqueue(chunk);
|
|
57
|
-
}
|
|
58
|
-
close() {
|
|
59
|
-
try {
|
|
60
|
-
this.controller.close();
|
|
61
|
-
}
|
|
62
|
-
catch (e) {
|
|
63
|
-
// pass
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
-
error(e) {
|
|
68
|
-
this.controller.error(e);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
exports.IterableReadableWritableStream = IterableReadableWritableStream;
|
|
72
17
|
function createDuplexStream(...streams) {
|
|
73
|
-
return new IterableReadableWritableStream({
|
|
18
|
+
return new stream_js_1.IterableReadableWritableStream({
|
|
74
19
|
passthroughFn: (value) => {
|
|
75
20
|
for (const stream of streams) {
|
|
76
21
|
if (stream.modes.has(value[1])) {
|
|
@@ -249,6 +194,36 @@ class PregelLoop {
|
|
|
249
194
|
writable: true,
|
|
250
195
|
value: void 0
|
|
251
196
|
});
|
|
197
|
+
Object.defineProperty(this, "manager", {
|
|
198
|
+
enumerable: true,
|
|
199
|
+
configurable: true,
|
|
200
|
+
writable: true,
|
|
201
|
+
value: void 0
|
|
202
|
+
});
|
|
203
|
+
Object.defineProperty(this, "interruptAfter", {
|
|
204
|
+
enumerable: true,
|
|
205
|
+
configurable: true,
|
|
206
|
+
writable: true,
|
|
207
|
+
value: void 0
|
|
208
|
+
});
|
|
209
|
+
Object.defineProperty(this, "interruptBefore", {
|
|
210
|
+
enumerable: true,
|
|
211
|
+
configurable: true,
|
|
212
|
+
writable: true,
|
|
213
|
+
value: void 0
|
|
214
|
+
});
|
|
215
|
+
Object.defineProperty(this, "toInterrupt", {
|
|
216
|
+
enumerable: true,
|
|
217
|
+
configurable: true,
|
|
218
|
+
writable: true,
|
|
219
|
+
value: []
|
|
220
|
+
});
|
|
221
|
+
Object.defineProperty(this, "debug", {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
configurable: true,
|
|
224
|
+
writable: true,
|
|
225
|
+
value: false
|
|
226
|
+
});
|
|
252
227
|
this.input = params.input;
|
|
253
228
|
this.checkpointer = params.checkpointer;
|
|
254
229
|
// TODO: if managed values no longer needs graph we can replace with
|
|
@@ -270,6 +245,7 @@ class PregelLoop {
|
|
|
270
245
|
this.config = params.config;
|
|
271
246
|
this.checkpointConfig = params.checkpointConfig;
|
|
272
247
|
this.isNested = params.isNested;
|
|
248
|
+
this.manager = params.manager;
|
|
273
249
|
this.outputKeys = params.outputKeys;
|
|
274
250
|
this.streamKeys = params.streamKeys;
|
|
275
251
|
this.nodes = params.nodes;
|
|
@@ -278,6 +254,9 @@ class PregelLoop {
|
|
|
278
254
|
this.stream = params.stream;
|
|
279
255
|
this.checkpointNamespace = params.checkpointNamespace;
|
|
280
256
|
this.prevCheckpointConfig = params.prevCheckpointConfig;
|
|
257
|
+
this.interruptAfter = params.interruptAfter;
|
|
258
|
+
this.interruptBefore = params.interruptBefore;
|
|
259
|
+
this.debug = params.debug;
|
|
281
260
|
}
|
|
282
261
|
static async initialize(params) {
|
|
283
262
|
let { config, stream } = params;
|
|
@@ -368,6 +347,7 @@ class PregelLoop {
|
|
|
368
347
|
channels,
|
|
369
348
|
managed: params.managed,
|
|
370
349
|
isNested,
|
|
350
|
+
manager: params.manager,
|
|
371
351
|
skipDoneTasks,
|
|
372
352
|
step,
|
|
373
353
|
stop,
|
|
@@ -378,6 +358,9 @@ class PregelLoop {
|
|
|
378
358
|
nodes: params.nodes,
|
|
379
359
|
stream,
|
|
380
360
|
store,
|
|
361
|
+
interruptAfter: params.interruptAfter,
|
|
362
|
+
interruptBefore: params.interruptBefore,
|
|
363
|
+
debug: params.debug,
|
|
381
364
|
});
|
|
382
365
|
}
|
|
383
366
|
_checkpointerPutAfterPrevious(input) {
|
|
@@ -458,7 +441,7 @@ class PregelLoop {
|
|
|
458
441
|
if (this.store && !this.store.isRunning) {
|
|
459
442
|
this.store?.start();
|
|
460
443
|
}
|
|
461
|
-
const { inputKeys = []
|
|
444
|
+
const { inputKeys = [] } = params;
|
|
462
445
|
if (this.status !== "pending") {
|
|
463
446
|
throw new Error(`Cannot tick when status is no longer "pending". Current status: "${this.status}"`);
|
|
464
447
|
}
|
|
@@ -482,7 +465,7 @@ class PregelLoop {
|
|
|
482
465
|
writes: (0, io_js_1.mapOutputUpdates)(this.outputKeys, Object.values(this.tasks).map((task) => [task, task.writes])).next().value ?? null,
|
|
483
466
|
});
|
|
484
467
|
// after execution, check if we should interrupt
|
|
485
|
-
if ((0, algo_js_1.shouldInterrupt)(this.checkpoint, interruptAfter, Object.values(this.tasks))) {
|
|
468
|
+
if ((0, algo_js_1.shouldInterrupt)(this.checkpoint, this.interruptAfter, Object.values(this.tasks))) {
|
|
486
469
|
this.status = "interrupt_after";
|
|
487
470
|
throw new errors_js_1.GraphInterrupt();
|
|
488
471
|
}
|
|
@@ -498,8 +481,9 @@ class PregelLoop {
|
|
|
498
481
|
step: this.step,
|
|
499
482
|
checkpointer: this.checkpointer,
|
|
500
483
|
isResuming: this.input === INPUT_RESUMING,
|
|
501
|
-
manager,
|
|
484
|
+
manager: this.manager,
|
|
502
485
|
store: this.store,
|
|
486
|
+
stream: this.stream,
|
|
503
487
|
});
|
|
504
488
|
this.tasks = nextTasks;
|
|
505
489
|
// Produce debug output
|
|
@@ -530,15 +514,10 @@ class PregelLoop {
|
|
|
530
514
|
}
|
|
531
515
|
// if all tasks have finished, re-tick
|
|
532
516
|
if (Object.values(this.tasks).every((task) => task.writes.length > 0)) {
|
|
533
|
-
return this.tick({
|
|
534
|
-
inputKeys,
|
|
535
|
-
interruptAfter,
|
|
536
|
-
interruptBefore,
|
|
537
|
-
manager,
|
|
538
|
-
});
|
|
517
|
+
return this.tick({ inputKeys });
|
|
539
518
|
}
|
|
540
519
|
// Before execution, check if we should interrupt
|
|
541
|
-
if ((0, algo_js_1.shouldInterrupt)(this.checkpoint, interruptBefore, Object.values(this.tasks))) {
|
|
520
|
+
if ((0, algo_js_1.shouldInterrupt)(this.checkpoint, this.interruptBefore, Object.values(this.tasks))) {
|
|
542
521
|
this.status = "interrupt_before";
|
|
543
522
|
throw new errors_js_1.GraphInterrupt();
|
|
544
523
|
}
|
|
@@ -575,20 +554,59 @@ class PregelLoop {
|
|
|
575
554
|
}
|
|
576
555
|
return suppress;
|
|
577
556
|
}
|
|
557
|
+
acceptPush(task, writeIdx, call) {
|
|
558
|
+
if (this.interruptAfter?.length > 0 &&
|
|
559
|
+
(0, algo_js_1.shouldInterrupt)(this.checkpoint, this.interruptAfter, [task])) {
|
|
560
|
+
this.toInterrupt.push(task);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const pushed = (0, algo_js_1._prepareSingleTask)([constants_js_1.PUSH, task.path ?? [], writeIdx, task.id, call], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, this.config, true, {
|
|
564
|
+
step: this.step,
|
|
565
|
+
checkpointer: this.checkpointer,
|
|
566
|
+
manager: this.manager,
|
|
567
|
+
store: this.store,
|
|
568
|
+
stream: this.stream,
|
|
569
|
+
});
|
|
570
|
+
if (pushed) {
|
|
571
|
+
if (this.interruptBefore?.length > 0 &&
|
|
572
|
+
(0, algo_js_1.shouldInterrupt)(this.checkpoint, this.interruptBefore, [pushed])) {
|
|
573
|
+
this.toInterrupt.push(pushed);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
this._emit((0, utils_js_1.gatherIteratorSync)((0, utils_js_1.prefixGenerator)((0, debug_js_1.mapDebugTasks)(this.step, [pushed]), "debug")));
|
|
577
|
+
if (this.debug) {
|
|
578
|
+
(0, debug_js_1.printStepTasks)(this.step, [pushed]);
|
|
579
|
+
}
|
|
580
|
+
this.tasks[pushed.id] = pushed;
|
|
581
|
+
if (this.skipDoneTasks) {
|
|
582
|
+
this._matchWrites({ [pushed.id]: pushed });
|
|
583
|
+
}
|
|
584
|
+
return pushed;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
578
587
|
_suppressInterrupt(e) {
|
|
579
588
|
return (0, errors_js_1.isGraphInterrupt)(e) && !this.isNested;
|
|
580
589
|
}
|
|
581
|
-
/**
|
|
582
|
-
* Resuming from previous checkpoint requires
|
|
583
|
-
* - finding a previous checkpoint
|
|
584
|
-
* - receiving null input (outer graph) or RESUMING flag (subgraph)
|
|
585
|
-
*/
|
|
586
590
|
async _first(inputKeys) {
|
|
591
|
+
/*
|
|
592
|
+
* Resuming from previous checkpoint requires
|
|
593
|
+
* - finding a previous checkpoint
|
|
594
|
+
* - receiving null input (outer graph) or RESUMING flag (subgraph)
|
|
595
|
+
*/
|
|
596
|
+
const { configurable } = this.config;
|
|
587
597
|
const isResuming = Object.keys(this.checkpoint.channel_versions).length !== 0 &&
|
|
588
598
|
(this.config.configurable?.[constants_js_1.CONFIG_KEY_RESUMING] !== undefined ||
|
|
589
599
|
this.input === null ||
|
|
590
600
|
(0, constants_js_1.isCommand)(this.input));
|
|
601
|
+
// take resume value from parent
|
|
602
|
+
const scratchpad = configurable?.[constants_js_1.CONFIG_KEY_SCRATCHPAD];
|
|
603
|
+
if (scratchpad && scratchpad.nullResume !== undefined) {
|
|
604
|
+
this.putWrites(constants_js_1.NULL_TASK_ID, [[constants_js_1.RESUME, scratchpad.nullResume]]);
|
|
605
|
+
}
|
|
591
606
|
if ((0, constants_js_1.isCommand)(this.input)) {
|
|
607
|
+
if (this.input.resume != null && this.checkpointer == null) {
|
|
608
|
+
throw new Error("Cannot use Command(resume=...) without checkpointer");
|
|
609
|
+
}
|
|
592
610
|
const writes = {};
|
|
593
611
|
// group writes by task id
|
|
594
612
|
for (const [tid, key, value] of (0, io_js_1.mapCommand)(this.input, this.checkpointPendingWrites)) {
|
|
@@ -653,10 +671,10 @@ class PregelLoop {
|
|
|
653
671
|
});
|
|
654
672
|
}
|
|
655
673
|
// done with input
|
|
656
|
-
this.input =
|
|
674
|
+
this.input = this.input === INPUT_RESUMING ? INPUT_RESUMING : INPUT_DONE;
|
|
657
675
|
if (!this.isNested) {
|
|
658
676
|
this.config = (0, index_js_1.patchConfigurable)(this.config, {
|
|
659
|
-
[constants_js_1.CONFIG_KEY_RESUMING]:
|
|
677
|
+
[constants_js_1.CONFIG_KEY_RESUMING]: this.input === INPUT_RESUMING,
|
|
660
678
|
});
|
|
661
679
|
}
|
|
662
680
|
}
|
|
@@ -717,5 +735,21 @@ class PregelLoop {
|
|
|
717
735
|
}
|
|
718
736
|
this.step += 1;
|
|
719
737
|
}
|
|
738
|
+
_matchWrites(tasks) {
|
|
739
|
+
for (const [tid, k, v] of this.checkpointPendingWrites) {
|
|
740
|
+
if (k === constants_js_1.ERROR || k === constants_js_1.INTERRUPT || k === constants_js_1.RESUME) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const task = Object.values(tasks).find((t) => t.id === tid);
|
|
744
|
+
if (task) {
|
|
745
|
+
task.writes.push([k, v]);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
for (const task of Object.values(tasks)) {
|
|
749
|
+
if (task.writes.length > 0) {
|
|
750
|
+
this._outputWrites(task.id, task.writes, true);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
720
754
|
}
|
|
721
755
|
exports.PregelLoop = PregelLoop;
|
package/dist/pregel/loop.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { RunnableConfig } from "@langchain/core/runnables";
|
|
2
2
|
import type { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
|
|
3
|
-
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
4
3
|
import { BaseCheckpointSaver, Checkpoint, PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All, BaseStore, AsyncBatchedStore } from "@langchain/langgraph-checkpoint";
|
|
5
4
|
import { BaseChannel } from "../channels/base.js";
|
|
6
|
-
import { PregelExecutableTask, StreamMode } from "./types.js";
|
|
5
|
+
import { Call, PregelExecutableTask, StreamMode } from "./types.js";
|
|
7
6
|
import { Command } from "../constants.js";
|
|
8
7
|
import { PregelNode } from "./read.js";
|
|
9
8
|
import { ManagedValueMapping } from "../managed/base.js";
|
|
10
9
|
import { LangGraphRunnableConfig } from "./runnable_types.js";
|
|
11
|
-
|
|
10
|
+
import { IterableReadableWritableStream } from "./stream.js";
|
|
12
11
|
export type PregelLoopInitializeParams = {
|
|
13
12
|
input?: any | Command;
|
|
14
13
|
config: RunnableConfig;
|
|
@@ -21,6 +20,10 @@ export type PregelLoopInitializeParams = {
|
|
|
21
20
|
stream: IterableReadableWritableStream;
|
|
22
21
|
store?: BaseStore;
|
|
23
22
|
checkSubgraphs?: boolean;
|
|
23
|
+
interruptAfter: string[] | All;
|
|
24
|
+
interruptBefore: string[] | All;
|
|
25
|
+
manager?: CallbackManagerForChainRun;
|
|
26
|
+
debug: boolean;
|
|
24
27
|
};
|
|
25
28
|
type PregelLoopParams = {
|
|
26
29
|
input?: any | Command;
|
|
@@ -41,22 +44,14 @@ type PregelLoopParams = {
|
|
|
41
44
|
checkpointNamespace: string[];
|
|
42
45
|
skipDoneTasks: boolean;
|
|
43
46
|
isNested: boolean;
|
|
47
|
+
manager?: CallbackManagerForChainRun;
|
|
44
48
|
stream: IterableReadableWritableStream;
|
|
45
49
|
store?: AsyncBatchedStore;
|
|
46
50
|
prevCheckpointConfig: RunnableConfig | undefined;
|
|
51
|
+
interruptAfter: string[] | All;
|
|
52
|
+
interruptBefore: string[] | All;
|
|
53
|
+
debug: boolean;
|
|
47
54
|
};
|
|
48
|
-
export declare class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {
|
|
49
|
-
modes: Set<StreamMode>;
|
|
50
|
-
private controller;
|
|
51
|
-
private passthroughFn?;
|
|
52
|
-
constructor(params: {
|
|
53
|
-
passthroughFn?: (chunk: StreamChunk) => void;
|
|
54
|
-
modes: Set<StreamMode>;
|
|
55
|
-
});
|
|
56
|
-
push(chunk: StreamChunk): void;
|
|
57
|
-
close(): void;
|
|
58
|
-
error(e: any): void;
|
|
59
|
-
}
|
|
60
55
|
export declare class PregelLoop {
|
|
61
56
|
protected input?: any | Command;
|
|
62
57
|
output: any;
|
|
@@ -85,6 +80,11 @@ export declare class PregelLoop {
|
|
|
85
80
|
isNested: boolean;
|
|
86
81
|
protected _checkpointerChainedPromise: Promise<unknown>;
|
|
87
82
|
store?: AsyncBatchedStore;
|
|
83
|
+
manager?: CallbackManagerForChainRun;
|
|
84
|
+
interruptAfter: string[] | All;
|
|
85
|
+
interruptBefore: string[] | All;
|
|
86
|
+
toInterrupt: PregelExecutableTask<string, string>[];
|
|
87
|
+
debug: boolean;
|
|
88
88
|
constructor(params: PregelLoopParams);
|
|
89
89
|
static initialize(params: PregelLoopInitializeParams): Promise<PregelLoop>;
|
|
90
90
|
protected _checkpointerPutAfterPrevious(input: {
|
|
@@ -108,19 +108,13 @@ export declare class PregelLoop {
|
|
|
108
108
|
*/
|
|
109
109
|
tick(params: {
|
|
110
110
|
inputKeys?: string | string[];
|
|
111
|
-
interruptAfter: string[] | All;
|
|
112
|
-
interruptBefore: string[] | All;
|
|
113
|
-
manager?: CallbackManagerForChainRun;
|
|
114
111
|
}): Promise<boolean>;
|
|
115
112
|
finishAndHandleError(error?: Error): Promise<boolean>;
|
|
113
|
+
acceptPush(task: PregelExecutableTask<string, string>, writeIdx: number, call?: Call): PregelExecutableTask<string, string> | void;
|
|
116
114
|
protected _suppressInterrupt(e?: Error): boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Resuming from previous checkpoint requires
|
|
119
|
-
* - finding a previous checkpoint
|
|
120
|
-
* - receiving null input (outer graph) or RESUMING flag (subgraph)
|
|
121
|
-
*/
|
|
122
115
|
protected _first(inputKeys: string | string[]): Promise<void>;
|
|
123
116
|
protected _emit(values: [StreamMode, unknown][]): void;
|
|
124
117
|
protected _putCheckpoint(inputMetadata: Omit<CheckpointMetadata, "step" | "parents">): Promise<void>;
|
|
118
|
+
protected _matchWrites(tasks: Record<string, PregelExecutableTask<string, string>>): void;
|
|
125
119
|
}
|
|
126
120
|
export {};
|