@langchain/langgraph 0.2.18 → 0.2.20-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/dist/errors.cjs +14 -1
- package/dist/errors.d.ts +7 -0
- package/dist/errors.js +12 -0
- package/dist/graph/graph.cjs +150 -0
- package/dist/graph/graph.d.ts +8 -0
- package/dist/graph/graph.js +151 -1
- package/dist/pregel/index.cjs +140 -108
- package/dist/pregel/index.d.ts +7 -25
- package/dist/pregel/index.js +141 -106
- package/dist/pregel/loop.cjs +54 -14
- package/dist/pregel/loop.d.ts +14 -6
- package/dist/pregel/loop.js +52 -12
- package/dist/pregel/remote.cjs +447 -0
- package/dist/pregel/remote.d.ts +113 -0
- package/dist/pregel/remote.js +443 -0
- package/dist/pregel/retry.cjs +1 -1
- package/dist/pregel/retry.js +1 -1
- package/dist/pregel/types.d.ts +44 -5
- package/dist/pregel/utils/subgraph.cjs +1 -4
- package/dist/pregel/utils/subgraph.js +1 -4
- package/dist/remote.cjs +5 -0
- package/dist/remote.d.ts +1 -0
- package/dist/remote.js +1 -0
- package/package.json +21 -9
- package/remote.cjs +1 -0
- package/remote.d.cts +1 -0
- package/remote.d.ts +1 -0
- package/remote.js +1 -0
package/dist/pregel/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */
|
|
2
2
|
import { Runnable, RunnableSequence, getCallbackManagerForConfig, mergeConfigs, patchConfig, _coerceToRunnable, } from "@langchain/core/runnables";
|
|
3
3
|
import { compareChannelVersions, copyCheckpoint, emptyCheckpoint, uuid5, } from "@langchain/langgraph-checkpoint";
|
|
4
|
-
import Deque from "double-ended-queue";
|
|
5
4
|
import { createCheckpoint, emptyChannels, isBaseChannel, } from "../channels/base.js";
|
|
6
5
|
import { PregelNode } from "./read.js";
|
|
7
6
|
import { validateGraph, validateKeys } from "./validate.js";
|
|
@@ -13,7 +12,7 @@ import { GraphRecursionError, GraphValueError, InvalidUpdateError, isGraphInterr
|
|
|
13
12
|
import { _prepareNextTasks, _localRead, _applyWrites, } from "./algo.js";
|
|
14
13
|
import { _coerceToDict, getNewChannelVersions, patchCheckpointMap, } from "./utils/index.js";
|
|
15
14
|
import { findSubgraphPregel } from "./utils/subgraph.js";
|
|
16
|
-
import { PregelLoop,
|
|
15
|
+
import { PregelLoop, IterableReadableWritableStream } from "./loop.js";
|
|
17
16
|
import { executeTasksWithRetry } from "./retry.js";
|
|
18
17
|
import { ChannelKeyPlaceholder, isConfiguredManagedValue, ManagedValueMapping, NoopManagedValue, } from "../managed/base.js";
|
|
19
18
|
import { gatherIterator, patchConfigurable } from "../utils.js";
|
|
@@ -88,6 +87,12 @@ export class Pregel extends Runnable {
|
|
|
88
87
|
writable: true,
|
|
89
88
|
value: ["langgraph", "pregel"]
|
|
90
89
|
});
|
|
90
|
+
Object.defineProperty(this, "lg_is_pregel", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
configurable: true,
|
|
93
|
+
writable: true,
|
|
94
|
+
value: true
|
|
95
|
+
});
|
|
91
96
|
Object.defineProperty(this, "nodes", {
|
|
92
97
|
enumerable: true,
|
|
93
98
|
configurable: true,
|
|
@@ -204,8 +209,9 @@ export class Pregel extends Runnable {
|
|
|
204
209
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
205
210
|
// @ts-ignore Remove ignore when we remove support for 0.2 versions of core
|
|
206
211
|
withConfig(config) {
|
|
212
|
+
const mergedConfig = mergeConfigs(this.config, config);
|
|
207
213
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
208
|
-
return new this.constructor({ ...this, config });
|
|
214
|
+
return new this.constructor({ ...this, config: mergedConfig });
|
|
209
215
|
}
|
|
210
216
|
validate() {
|
|
211
217
|
validateGraph({
|
|
@@ -238,6 +244,10 @@ export class Pregel extends Runnable {
|
|
|
238
244
|
return Object.keys(this.channels);
|
|
239
245
|
}
|
|
240
246
|
}
|
|
247
|
+
async getGraphAsync(config) {
|
|
248
|
+
return this.getGraph(config);
|
|
249
|
+
}
|
|
250
|
+
/** @deprecated Use getSubgraphsAsync instead. The async method will become the default in the next minor release. */
|
|
241
251
|
*getSubgraphs(namespace, recurse
|
|
242
252
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
243
253
|
) {
|
|
@@ -275,6 +285,11 @@ export class Pregel extends Runnable {
|
|
|
275
285
|
}
|
|
276
286
|
}
|
|
277
287
|
}
|
|
288
|
+
async *getSubgraphsAsync(namespace, recurse
|
|
289
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
290
|
+
) {
|
|
291
|
+
yield* this.getSubgraphs(namespace, recurse);
|
|
292
|
+
}
|
|
278
293
|
async _prepareStateSnapshot({ config, saved, subgraphCheckpointer, }) {
|
|
279
294
|
if (saved === undefined) {
|
|
280
295
|
return {
|
|
@@ -288,7 +303,7 @@ export class Pregel extends Runnable {
|
|
|
288
303
|
const { managed } = await this.prepareSpecs(config, { skipManaged: true });
|
|
289
304
|
const channels = emptyChannels(this.channels, saved.checkpoint);
|
|
290
305
|
const nextTasks = Object.values(_prepareNextTasks(saved.checkpoint, this.nodes, channels, managed, saved.config, false, { step: (saved.metadata?.step ?? -1) + 1 }));
|
|
291
|
-
const subgraphs = await gatherIterator(this.
|
|
306
|
+
const subgraphs = await gatherIterator(this.getSubgraphsAsync());
|
|
292
307
|
const parentNamespace = saved.config.configurable?.checkpoint_ns ?? "";
|
|
293
308
|
const taskStates = {};
|
|
294
309
|
for (const task of nextTasks) {
|
|
@@ -352,7 +367,7 @@ export class Pregel extends Runnable {
|
|
|
352
367
|
.split(CHECKPOINT_NAMESPACE_SEPARATOR)
|
|
353
368
|
.map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])
|
|
354
369
|
.join(CHECKPOINT_NAMESPACE_SEPARATOR);
|
|
355
|
-
for (const [name, subgraph] of this.
|
|
370
|
+
for await (const [name, subgraph] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
|
|
356
371
|
if (name === recastCheckpointNamespace) {
|
|
357
372
|
return await subgraph.getState(patchConfigurable(config, {
|
|
358
373
|
[CONFIG_KEY_CHECKPOINTER]: checkpointer,
|
|
@@ -386,7 +401,7 @@ export class Pregel extends Runnable {
|
|
|
386
401
|
.map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])
|
|
387
402
|
.join(CHECKPOINT_NAMESPACE_SEPARATOR);
|
|
388
403
|
// find the subgraph with the matching name
|
|
389
|
-
for (const [name, pregel] of this.
|
|
404
|
+
for await (const [name, pregel] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
|
|
390
405
|
if (name === recastCheckpointNamespace) {
|
|
391
406
|
yield* pregel.getStateHistory(patchConfigurable(config, {
|
|
392
407
|
[CONFIG_KEY_CHECKPOINTER]: checkpointer,
|
|
@@ -429,7 +444,7 @@ export class Pregel extends Runnable {
|
|
|
429
444
|
.join(CHECKPOINT_NAMESPACE_SEPARATOR);
|
|
430
445
|
// find the subgraph with the matching name
|
|
431
446
|
// eslint-disable-next-line no-unreachable-loop
|
|
432
|
-
for (const [, pregel] of this.
|
|
447
|
+
for await (const [, pregel] of this.getSubgraphsAsync(recastCheckpointNamespace, true)) {
|
|
433
448
|
return await pregel.updateState(patchConfigurable(inputConfig, {
|
|
434
449
|
[CONFIG_KEY_CHECKPOINTER]: checkpointer,
|
|
435
450
|
}), values, asNode);
|
|
@@ -688,15 +703,125 @@ export class Pregel extends Runnable {
|
|
|
688
703
|
// assign defaults
|
|
689
704
|
const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer, store,] = this._defaults(inputConfig);
|
|
690
705
|
const { channelSpecs, managed } = await this.prepareSpecs(config);
|
|
706
|
+
const stream = new IterableReadableWritableStream({
|
|
707
|
+
modes: new Set(streamMode),
|
|
708
|
+
});
|
|
691
709
|
let loop;
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
710
|
+
let loopError;
|
|
711
|
+
const runLoop = async () => {
|
|
712
|
+
try {
|
|
713
|
+
loop = await PregelLoop.initialize({
|
|
714
|
+
input,
|
|
715
|
+
config,
|
|
716
|
+
checkpointer,
|
|
717
|
+
nodes: this.nodes,
|
|
718
|
+
channelSpecs,
|
|
719
|
+
managed,
|
|
720
|
+
outputKeys,
|
|
721
|
+
streamKeys: this.streamChannelsAsIs,
|
|
722
|
+
store,
|
|
723
|
+
stream,
|
|
724
|
+
});
|
|
725
|
+
if (options?.subgraphs) {
|
|
726
|
+
loop.config.configurable = {
|
|
727
|
+
...loop.config.configurable,
|
|
728
|
+
[CONFIG_KEY_STREAM]: loop.stream,
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
while (await loop.tick({
|
|
732
|
+
inputKeys: this.inputChannels,
|
|
733
|
+
interruptAfter,
|
|
734
|
+
interruptBefore,
|
|
735
|
+
manager: runManager,
|
|
736
|
+
})) {
|
|
737
|
+
if (debug) {
|
|
738
|
+
printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
|
|
739
|
+
}
|
|
740
|
+
if (debug) {
|
|
741
|
+
printStepTasks(loop.step, Object.values(loop.tasks));
|
|
742
|
+
}
|
|
743
|
+
// execute tasks, and wait for one to fail or all to finish.
|
|
744
|
+
// each task is independent from all other concurrent tasks
|
|
745
|
+
// yield updates/debug output as each task finishes
|
|
746
|
+
const taskStream = executeTasksWithRetry(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
|
|
747
|
+
stepTimeout: this.stepTimeout,
|
|
748
|
+
signal: config.signal,
|
|
749
|
+
retryPolicy: this.retryPolicy,
|
|
750
|
+
});
|
|
751
|
+
// Timeouts will be thrown
|
|
752
|
+
for await (const { task, error } of taskStream) {
|
|
753
|
+
if (error !== undefined) {
|
|
754
|
+
if (isGraphInterrupt(error)) {
|
|
755
|
+
if (loop.isNested) {
|
|
756
|
+
throw error;
|
|
757
|
+
}
|
|
758
|
+
if (error.interrupts.length) {
|
|
759
|
+
loop.putWrites(task.id, error.interrupts.map((interrupt) => [INTERRUPT, interrupt]));
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
loop.putWrites(task.id, [
|
|
764
|
+
[ERROR, { message: error.message, name: error.name }],
|
|
765
|
+
]);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
loop.putWrites(task.id, task.writes);
|
|
770
|
+
}
|
|
771
|
+
if (error !== undefined && !isGraphInterrupt(error)) {
|
|
772
|
+
throw error;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
if (debug) {
|
|
776
|
+
printStepWrites(loop.step, Object.values(loop.tasks)
|
|
777
|
+
.map((task) => task.writes)
|
|
778
|
+
.flat(), this.streamChannelsList);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (loop.status === "out_of_steps") {
|
|
782
|
+
throw new GraphRecursionError([
|
|
783
|
+
`Recursion limit of ${config.recursionLimit} reached`,
|
|
784
|
+
"without hitting a stop condition. You can increase the",
|
|
785
|
+
`limit by setting the "recursionLimit" config key.`,
|
|
786
|
+
].join(" "), {
|
|
787
|
+
lc_error_code: "GRAPH_RECURSION_LIMIT",
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
catch (e) {
|
|
792
|
+
loopError = e;
|
|
793
|
+
}
|
|
794
|
+
finally {
|
|
795
|
+
try {
|
|
796
|
+
// Call `.stop()` again incase it was not called in the loop, e.g due to an error.
|
|
797
|
+
if (loop) {
|
|
798
|
+
await loop.store?.stop();
|
|
799
|
+
}
|
|
800
|
+
await Promise.all([
|
|
801
|
+
...(loop?.checkpointerPromises ?? []),
|
|
802
|
+
...Array.from(managed.values()).map((mv) => mv.promises()),
|
|
803
|
+
]);
|
|
804
|
+
}
|
|
805
|
+
catch (e) {
|
|
806
|
+
loopError = loopError ?? e;
|
|
807
|
+
}
|
|
808
|
+
if (loopError) {
|
|
809
|
+
// Will throw an error outside of this method
|
|
810
|
+
stream.error(loopError);
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
// Will end the iterator outside of this method
|
|
814
|
+
stream.close();
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
const runLoopPromise = runLoop();
|
|
819
|
+
try {
|
|
820
|
+
for await (const chunk of stream) {
|
|
821
|
+
if (chunk === undefined) {
|
|
697
822
|
throw new Error("Data structure error.");
|
|
698
823
|
}
|
|
699
|
-
const [namespace, mode, payload] =
|
|
824
|
+
const [namespace, mode, payload] = chunk;
|
|
700
825
|
if (streamMode.includes(mode)) {
|
|
701
826
|
if (streamSubgraphs && streamMode.length > 1) {
|
|
702
827
|
yield [namespace, mode, payload];
|
|
@@ -713,104 +838,14 @@ export class Pregel extends Runnable {
|
|
|
713
838
|
}
|
|
714
839
|
}
|
|
715
840
|
}
|
|
716
|
-
try {
|
|
717
|
-
loop = await PregelLoop.initialize({
|
|
718
|
-
input,
|
|
719
|
-
config,
|
|
720
|
-
checkpointer,
|
|
721
|
-
nodes: this.nodes,
|
|
722
|
-
channelSpecs,
|
|
723
|
-
managed,
|
|
724
|
-
outputKeys,
|
|
725
|
-
streamKeys: this.streamChannelsAsIs,
|
|
726
|
-
store,
|
|
727
|
-
stream: new StreamProtocol((chunk) => stream.push(chunk), new Set(streamMode)),
|
|
728
|
-
});
|
|
729
|
-
if (options?.subgraphs) {
|
|
730
|
-
loop.config.configurable = {
|
|
731
|
-
...loop.config.configurable,
|
|
732
|
-
[CONFIG_KEY_STREAM]: loop.stream,
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
|
-
while (await loop.tick({
|
|
736
|
-
inputKeys: this.inputChannels,
|
|
737
|
-
interruptAfter,
|
|
738
|
-
interruptBefore,
|
|
739
|
-
manager: runManager,
|
|
740
|
-
})) {
|
|
741
|
-
if (debug) {
|
|
742
|
-
printStepCheckpoint(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
|
|
743
|
-
}
|
|
744
|
-
yield* emitCurrentLoopOutputs();
|
|
745
|
-
if (debug) {
|
|
746
|
-
printStepTasks(loop.step, Object.values(loop.tasks));
|
|
747
|
-
}
|
|
748
|
-
// execute tasks, and wait for one to fail or all to finish.
|
|
749
|
-
// each task is independent from all other concurrent tasks
|
|
750
|
-
// yield updates/debug output as each task finishes
|
|
751
|
-
const taskStream = executeTasksWithRetry(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
|
|
752
|
-
stepTimeout: this.stepTimeout,
|
|
753
|
-
signal: config.signal,
|
|
754
|
-
retryPolicy: this.retryPolicy,
|
|
755
|
-
});
|
|
756
|
-
// Timeouts will be thrown
|
|
757
|
-
for await (const { task, error } of taskStream) {
|
|
758
|
-
if (error !== undefined) {
|
|
759
|
-
if (isGraphInterrupt(error)) {
|
|
760
|
-
if (loop.isNested) {
|
|
761
|
-
throw error;
|
|
762
|
-
}
|
|
763
|
-
if (error.interrupts.length) {
|
|
764
|
-
loop.putWrites(task.id, error.interrupts.map((interrupt) => [INTERRUPT, interrupt]));
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
else {
|
|
768
|
-
loop.putWrites(task.id, [
|
|
769
|
-
[ERROR, { message: error.message, name: error.name }],
|
|
770
|
-
]);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
else {
|
|
774
|
-
loop.putWrites(task.id, task.writes);
|
|
775
|
-
}
|
|
776
|
-
yield* emitCurrentLoopOutputs();
|
|
777
|
-
if (error !== undefined && !isGraphInterrupt(error)) {
|
|
778
|
-
throw error;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
if (debug) {
|
|
782
|
-
printStepWrites(loop.step, Object.values(loop.tasks)
|
|
783
|
-
.map((task) => task.writes)
|
|
784
|
-
.flat(), this.streamChannelsList);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
yield* emitCurrentLoopOutputs();
|
|
788
|
-
if (loop.status === "out_of_steps") {
|
|
789
|
-
throw new GraphRecursionError([
|
|
790
|
-
`Recursion limit of ${config.recursionLimit} reached`,
|
|
791
|
-
"without hitting a stop condition. You can increase the",
|
|
792
|
-
`limit by setting the "recursionLimit" config key.`,
|
|
793
|
-
].join(" "), {
|
|
794
|
-
lc_error_code: "GRAPH_RECURSION_LIMIT",
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
await Promise.all(loop?.checkpointerPromises ?? []);
|
|
798
|
-
await runManager?.handleChainEnd(loop.output);
|
|
799
|
-
}
|
|
800
841
|
catch (e) {
|
|
801
|
-
await runManager?.handleChainError(
|
|
842
|
+
await runManager?.handleChainError(loopError);
|
|
802
843
|
throw e;
|
|
803
844
|
}
|
|
804
845
|
finally {
|
|
805
|
-
|
|
806
|
-
if (loop) {
|
|
807
|
-
await loop.store?.stop();
|
|
808
|
-
}
|
|
809
|
-
await Promise.all([
|
|
810
|
-
...(loop?.checkpointerPromises ?? []),
|
|
811
|
-
...Array.from(managed.values()).map((mv) => mv.promises()),
|
|
812
|
-
]);
|
|
846
|
+
await runLoopPromise;
|
|
813
847
|
}
|
|
848
|
+
await runManager?.handleChainEnd(loop?.output ?? {});
|
|
814
849
|
}
|
|
815
850
|
/**
|
|
816
851
|
* Run the graph with a single input and config.
|
package/dist/pregel/loop.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PregelLoop = exports.
|
|
3
|
+
exports.PregelLoop = exports.IterableReadableWritableStream = void 0;
|
|
4
|
+
const stream_1 = require("@langchain/core/utils/stream");
|
|
4
5
|
const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
|
|
5
6
|
const base_js_1 = require("../channels/base.cjs");
|
|
6
7
|
const constants_js_1 = require("../constants.cjs");
|
|
@@ -14,33 +15,72 @@ const INPUT_DONE = Symbol.for("INPUT_DONE");
|
|
|
14
15
|
const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
|
|
15
16
|
const DEFAULT_LOOP_LIMIT = 25;
|
|
16
17
|
const SPECIAL_CHANNELS = [constants_js_1.ERROR, constants_js_1.INTERRUPT];
|
|
17
|
-
class
|
|
18
|
-
constructor(
|
|
19
|
-
|
|
18
|
+
class IterableReadableWritableStream extends stream_1.IterableReadableStream {
|
|
19
|
+
constructor(params) {
|
|
20
|
+
let streamControllerPromiseResolver;
|
|
21
|
+
let streamControllerPromise = new Promise((resolve) => {
|
|
22
|
+
streamControllerPromiseResolver = resolve;
|
|
23
|
+
});
|
|
24
|
+
super({
|
|
25
|
+
start: (controller) => {
|
|
26
|
+
streamControllerPromiseResolver(controller);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(this, "modes", {
|
|
20
30
|
enumerable: true,
|
|
21
31
|
configurable: true,
|
|
22
32
|
writable: true,
|
|
23
33
|
value: void 0
|
|
24
34
|
});
|
|
25
|
-
Object.defineProperty(this, "
|
|
35
|
+
Object.defineProperty(this, "controller", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
writable: true,
|
|
39
|
+
value: void 0
|
|
40
|
+
});
|
|
41
|
+
Object.defineProperty(this, "passthroughFn", {
|
|
26
42
|
enumerable: true,
|
|
27
43
|
configurable: true,
|
|
28
44
|
writable: true,
|
|
29
45
|
value: void 0
|
|
30
46
|
});
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
// .start() will always be called before the stream can be interacted
|
|
48
|
+
// with anyway
|
|
49
|
+
streamControllerPromise.then((controller) => {
|
|
50
|
+
this.controller = controller;
|
|
51
|
+
});
|
|
52
|
+
this.passthroughFn = params.passthroughFn;
|
|
53
|
+
this.modes = params.modes;
|
|
54
|
+
}
|
|
55
|
+
push(chunk) {
|
|
56
|
+
this.passthroughFn?.(chunk);
|
|
57
|
+
this.controller.enqueue(chunk);
|
|
58
|
+
}
|
|
59
|
+
close() {
|
|
60
|
+
try {
|
|
61
|
+
this.controller.close();
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
// pass
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
+
error(e) {
|
|
69
|
+
this.controller.error(e);
|
|
33
70
|
}
|
|
34
71
|
}
|
|
35
|
-
exports.
|
|
72
|
+
exports.IterableReadableWritableStream = IterableReadableWritableStream;
|
|
36
73
|
function createDuplexStream(...streams) {
|
|
37
|
-
return new
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
stream.
|
|
74
|
+
return new IterableReadableWritableStream({
|
|
75
|
+
passthroughFn: (value) => {
|
|
76
|
+
for (const stream of streams) {
|
|
77
|
+
if (stream.modes.has(value[1])) {
|
|
78
|
+
stream.push(value);
|
|
79
|
+
}
|
|
41
80
|
}
|
|
42
|
-
}
|
|
43
|
-
|
|
81
|
+
},
|
|
82
|
+
modes: new Set(streams.flatMap((s) => Array.from(s.modes))),
|
|
83
|
+
});
|
|
44
84
|
}
|
|
45
85
|
class PregelLoop {
|
|
46
86
|
constructor(params) {
|
package/dist/pregel/loop.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
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";
|
|
3
4
|
import { BaseCheckpointSaver, Checkpoint, PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All, BaseStore, AsyncBatchedStore } from "@langchain/langgraph-checkpoint";
|
|
4
5
|
import { BaseChannel } from "../channels/base.js";
|
|
5
6
|
import { PregelExecutableTask, StreamMode } from "./types.js";
|
|
@@ -16,7 +17,7 @@ export type PregelLoopInitializeParams = {
|
|
|
16
17
|
nodes: Record<string, PregelNode>;
|
|
17
18
|
channelSpecs: Record<string, BaseChannel>;
|
|
18
19
|
managed: ManagedValueMapping;
|
|
19
|
-
stream:
|
|
20
|
+
stream: IterableReadableWritableStream;
|
|
20
21
|
store?: BaseStore;
|
|
21
22
|
checkSubgraphs?: boolean;
|
|
22
23
|
};
|
|
@@ -39,14 +40,21 @@ type PregelLoopParams = {
|
|
|
39
40
|
checkpointNamespace: string[];
|
|
40
41
|
skipDoneTasks: boolean;
|
|
41
42
|
isNested: boolean;
|
|
42
|
-
stream:
|
|
43
|
+
stream: IterableReadableWritableStream;
|
|
43
44
|
store?: AsyncBatchedStore;
|
|
44
45
|
prevCheckpointConfig: RunnableConfig | undefined;
|
|
45
46
|
};
|
|
46
|
-
export declare class
|
|
47
|
-
push: (chunk: StreamChunk) => void;
|
|
47
|
+
export declare class IterableReadableWritableStream extends IterableReadableStream<StreamChunk> {
|
|
48
48
|
modes: Set<StreamMode>;
|
|
49
|
-
|
|
49
|
+
private controller;
|
|
50
|
+
private passthroughFn?;
|
|
51
|
+
constructor(params: {
|
|
52
|
+
passthroughFn?: (chunk: StreamChunk) => void;
|
|
53
|
+
modes: Set<StreamMode>;
|
|
54
|
+
});
|
|
55
|
+
push(chunk: StreamChunk): void;
|
|
56
|
+
close(): void;
|
|
57
|
+
error(e: any): void;
|
|
50
58
|
}
|
|
51
59
|
export declare class PregelLoop {
|
|
52
60
|
protected input?: any;
|
|
@@ -72,7 +80,7 @@ export declare class PregelLoop {
|
|
|
72
80
|
protected prevCheckpointConfig: RunnableConfig | undefined;
|
|
73
81
|
status: "pending" | "done" | "interrupt_before" | "interrupt_after" | "out_of_steps";
|
|
74
82
|
tasks: Record<string, PregelExecutableTask<any, any>>;
|
|
75
|
-
stream:
|
|
83
|
+
stream: IterableReadableWritableStream;
|
|
76
84
|
checkpointerPromises: Promise<unknown>[];
|
|
77
85
|
isNested: boolean;
|
|
78
86
|
protected _checkpointerChainedPromise: Promise<unknown>;
|
package/dist/pregel/loop.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
|
1
2
|
import { copyCheckpoint, emptyCheckpoint, AsyncBatchedStore, } from "@langchain/langgraph-checkpoint";
|
|
2
3
|
import { createCheckpoint, emptyChannels, } from "../channels/base.js";
|
|
3
4
|
import { CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINT_MAP, CONFIG_KEY_READ, CONFIG_KEY_RESUMING, CONFIG_KEY_STREAM, ERROR, INPUT, INTERRUPT, TAG_HIDDEN, TASKS, } from "../constants.js";
|
|
@@ -11,32 +12,71 @@ const INPUT_DONE = Symbol.for("INPUT_DONE");
|
|
|
11
12
|
const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
|
|
12
13
|
const DEFAULT_LOOP_LIMIT = 25;
|
|
13
14
|
const SPECIAL_CHANNELS = [ERROR, INTERRUPT];
|
|
14
|
-
export class
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
15
|
+
export class IterableReadableWritableStream extends IterableReadableStream {
|
|
16
|
+
constructor(params) {
|
|
17
|
+
let streamControllerPromiseResolver;
|
|
18
|
+
let streamControllerPromise = new Promise((resolve) => {
|
|
19
|
+
streamControllerPromiseResolver = resolve;
|
|
20
|
+
});
|
|
21
|
+
super({
|
|
22
|
+
start: (controller) => {
|
|
23
|
+
streamControllerPromiseResolver(controller);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(this, "modes", {
|
|
17
27
|
enumerable: true,
|
|
18
28
|
configurable: true,
|
|
19
29
|
writable: true,
|
|
20
30
|
value: void 0
|
|
21
31
|
});
|
|
22
|
-
Object.defineProperty(this, "
|
|
32
|
+
Object.defineProperty(this, "controller", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: void 0
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(this, "passthroughFn", {
|
|
23
39
|
enumerable: true,
|
|
24
40
|
configurable: true,
|
|
25
41
|
writable: true,
|
|
26
42
|
value: void 0
|
|
27
43
|
});
|
|
28
|
-
|
|
29
|
-
|
|
44
|
+
// .start() will always be called before the stream can be interacted
|
|
45
|
+
// with anyway
|
|
46
|
+
streamControllerPromise.then((controller) => {
|
|
47
|
+
this.controller = controller;
|
|
48
|
+
});
|
|
49
|
+
this.passthroughFn = params.passthroughFn;
|
|
50
|
+
this.modes = params.modes;
|
|
51
|
+
}
|
|
52
|
+
push(chunk) {
|
|
53
|
+
this.passthroughFn?.(chunk);
|
|
54
|
+
this.controller.enqueue(chunk);
|
|
55
|
+
}
|
|
56
|
+
close() {
|
|
57
|
+
try {
|
|
58
|
+
this.controller.close();
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
// pass
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
error(e) {
|
|
66
|
+
this.controller.error(e);
|
|
30
67
|
}
|
|
31
68
|
}
|
|
32
69
|
function createDuplexStream(...streams) {
|
|
33
|
-
return new
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
stream.
|
|
70
|
+
return new IterableReadableWritableStream({
|
|
71
|
+
passthroughFn: (value) => {
|
|
72
|
+
for (const stream of streams) {
|
|
73
|
+
if (stream.modes.has(value[1])) {
|
|
74
|
+
stream.push(value);
|
|
75
|
+
}
|
|
37
76
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
77
|
+
},
|
|
78
|
+
modes: new Set(streams.flatMap((s) => Array.from(s.modes))),
|
|
79
|
+
});
|
|
40
80
|
}
|
|
41
81
|
export class PregelLoop {
|
|
42
82
|
constructor(params) {
|