@langchain/langgraph 0.0.33 → 0.0.34
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 +1 -1
- package/dist/channels/base.cjs +1 -0
- package/dist/channels/base.js +1 -0
- package/dist/channels/ephemeral_value.cjs +1 -1
- package/dist/channels/ephemeral_value.js +1 -1
- package/dist/checkpoint/base.cjs +2 -0
- package/dist/checkpoint/base.d.ts +6 -0
- package/dist/checkpoint/base.js +2 -0
- package/dist/constants.cjs +80 -1
- package/dist/constants.d.ts +57 -0
- package/dist/constants.js +76 -0
- package/dist/graph/annotation.cjs +51 -0
- package/dist/graph/annotation.d.ts +41 -0
- package/dist/graph/annotation.js +45 -0
- package/dist/graph/graph.cjs +19 -4
- package/dist/graph/graph.d.ts +5 -4
- package/dist/graph/graph.js +20 -5
- package/dist/graph/index.cjs +3 -1
- package/dist/graph/index.d.ts +1 -0
- package/dist/graph/index.js +1 -0
- package/dist/graph/message.d.ts +1 -1
- package/dist/graph/state.cjs +24 -39
- package/dist/graph/state.d.ts +4 -29
- package/dist/graph/state.js +22 -36
- package/dist/pregel/index.cjs +111 -16
- package/dist/pregel/index.d.ts +7 -2
- package/dist/pregel/index.js +110 -16
- package/dist/pregel/io.cjs +31 -28
- package/dist/pregel/io.d.ts +1 -1
- package/dist/pregel/io.js +31 -28
- package/dist/pregel/read.cjs +4 -1
- package/dist/pregel/read.js +4 -1
- package/dist/pregel/write.cjs +60 -24
- package/dist/pregel/write.d.ts +11 -6
- package/dist/pregel/write.js +61 -25
- package/dist/web.cjs +4 -1
- package/dist/web.d.ts +2 -1
- package/dist/web.js +2 -1
- package/package.json +3 -2
package/dist/graph/state.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CompiledStateGraph = exports.StateGraph =
|
|
4
|
-
const binop_js_1 = require("../channels/binop.cjs");
|
|
3
|
+
exports.CompiledStateGraph = exports.StateGraph = void 0;
|
|
5
4
|
const graph_js_1 = require("./graph.cjs");
|
|
6
|
-
const last_value_js_1 = require("../channels/last_value.cjs");
|
|
7
5
|
const write_js_1 = require("../pregel/write.cjs");
|
|
8
6
|
const read_js_1 = require("../pregel/read.cjs");
|
|
9
7
|
const named_barrier_value_js_1 = require("../channels/named_barrier_value.cjs");
|
|
@@ -11,17 +9,8 @@ const ephemeral_value_js_1 = require("../channels/ephemeral_value.cjs");
|
|
|
11
9
|
const utils_js_1 = require("../utils.cjs");
|
|
12
10
|
const constants_js_1 = require("../constants.cjs");
|
|
13
11
|
const errors_js_1 = require("../errors.cjs");
|
|
12
|
+
const annotation_js_1 = require("./annotation.cjs");
|
|
14
13
|
const ROOT = "__root__";
|
|
15
|
-
function Annotation(annotation) {
|
|
16
|
-
if (annotation) {
|
|
17
|
-
return getChannel(annotation);
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
// @ts-expect-error - Annotation without reducer
|
|
21
|
-
return new last_value_js_1.LastValue();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.Annotation = Annotation;
|
|
25
14
|
class StateGraph extends graph_js_1.Graph {
|
|
26
15
|
constructor(fields) {
|
|
27
16
|
super();
|
|
@@ -38,9 +27,10 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
38
27
|
writable: true,
|
|
39
28
|
value: new Set()
|
|
40
29
|
});
|
|
41
|
-
if (isStateDefinition(fields)) {
|
|
30
|
+
if (isStateDefinition(fields) || isAnnotationRoot(fields)) {
|
|
31
|
+
const spec = isAnnotationRoot(fields) ? fields.spec : fields;
|
|
42
32
|
this.channels = {};
|
|
43
|
-
for (const [key, val] of Object.entries(
|
|
33
|
+
for (const [key, val] of Object.entries(spec)) {
|
|
44
34
|
if (typeof val === "function") {
|
|
45
35
|
this.channels[key] = val();
|
|
46
36
|
}
|
|
@@ -148,31 +138,15 @@ function _getChannels(schema) {
|
|
|
148
138
|
const channels = {};
|
|
149
139
|
for (const [name, val] of Object.entries(schema)) {
|
|
150
140
|
if (name === ROOT) {
|
|
151
|
-
channels[name] = getChannel(val);
|
|
141
|
+
channels[name] = (0, annotation_js_1.getChannel)(val);
|
|
152
142
|
}
|
|
153
143
|
else {
|
|
154
144
|
const key = name;
|
|
155
|
-
channels[name] = getChannel(val);
|
|
145
|
+
channels[name] = (0, annotation_js_1.getChannel)(val);
|
|
156
146
|
}
|
|
157
147
|
}
|
|
158
148
|
return channels;
|
|
159
149
|
}
|
|
160
|
-
function getChannel(reducer) {
|
|
161
|
-
if (typeof reducer === "object" &&
|
|
162
|
-
reducer &&
|
|
163
|
-
"reducer" in reducer &&
|
|
164
|
-
reducer.reducer) {
|
|
165
|
-
return new binop_js_1.BinaryOperatorAggregate(reducer.reducer, reducer.default);
|
|
166
|
-
}
|
|
167
|
-
if (typeof reducer === "object" &&
|
|
168
|
-
reducer &&
|
|
169
|
-
"value" in reducer &&
|
|
170
|
-
reducer.value) {
|
|
171
|
-
return new binop_js_1.BinaryOperatorAggregate(reducer.value, reducer.default);
|
|
172
|
-
}
|
|
173
|
-
// @ts-expect-error - Annotation without reducer
|
|
174
|
-
return new last_value_js_1.LastValue();
|
|
175
|
-
}
|
|
176
150
|
class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
177
151
|
attachNode(key, node) {
|
|
178
152
|
const stateKeys = Object.keys(this.builder.channels);
|
|
@@ -209,7 +183,7 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
209
183
|
});
|
|
210
184
|
}
|
|
211
185
|
else {
|
|
212
|
-
this.channels[key] = new ephemeral_value_js_1.EphemeralValue();
|
|
186
|
+
this.channels[key] = new ephemeral_value_js_1.EphemeralValue(false);
|
|
213
187
|
this.nodes[key] = new read_js_1.PregelNode({
|
|
214
188
|
triggers: [],
|
|
215
189
|
// read state keys
|
|
@@ -266,10 +240,15 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
266
240
|
if (!filteredDests.length) {
|
|
267
241
|
return;
|
|
268
242
|
}
|
|
269
|
-
const writes = filteredDests.map((dest) =>
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
243
|
+
const writes = filteredDests.map((dest) => {
|
|
244
|
+
if ((0, constants_js_1._isSend)(dest)) {
|
|
245
|
+
return dest;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
channel: `branch:${start}:${name}:${dest}`,
|
|
249
|
+
value: start,
|
|
250
|
+
};
|
|
251
|
+
});
|
|
273
252
|
return new write_js_1.ChannelWrite(writes, [constants_js_1.TAG_HIDDEN]);
|
|
274
253
|
},
|
|
275
254
|
// reader
|
|
@@ -284,7 +263,7 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
284
263
|
}
|
|
285
264
|
const channelName = `branch:${start}:${name}:${end}`;
|
|
286
265
|
this.channels[channelName] =
|
|
287
|
-
new ephemeral_value_js_1.EphemeralValue();
|
|
266
|
+
new ephemeral_value_js_1.EphemeralValue(false);
|
|
288
267
|
this.nodes[end].triggers.push(channelName);
|
|
289
268
|
}
|
|
290
269
|
}
|
|
@@ -300,3 +279,9 @@ function isStateDefinition(obj) {
|
|
|
300
279
|
Object.keys(obj).length > 0 &&
|
|
301
280
|
Object.values(obj).every((v) => typeof v === "function" || isBaseChannel(v)));
|
|
302
281
|
}
|
|
282
|
+
function isAnnotationRoot(obj) {
|
|
283
|
+
return (typeof obj === "object" &&
|
|
284
|
+
obj !== null &&
|
|
285
|
+
"lc_graph_name" in obj &&
|
|
286
|
+
obj.lc_graph_name === "AnnotationRoot");
|
|
287
|
+
}
|
package/dist/graph/state.d.ts
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
import { Runnable, RunnableConfig, RunnableLike } from "@langchain/core/runnables";
|
|
2
2
|
import { BaseChannel } from "../channels/base.js";
|
|
3
|
-
import { BinaryOperator, BinaryOperatorAggregate } from "../channels/binop.js";
|
|
4
3
|
import { END, CompiledGraph, Graph, START, Branch } from "./graph.js";
|
|
5
|
-
import { LastValue } from "../channels/last_value.js";
|
|
6
4
|
import { BaseCheckpointSaver } from "../checkpoint/base.js";
|
|
7
5
|
import { All } from "../pregel/types.js";
|
|
8
|
-
|
|
9
|
-
export declare function Annotation<ValueType, UpdateType = ValueType>(annotation: SingleReducer<ValueType, UpdateType>): BinaryOperatorAggregate<ValueType, UpdateType>;
|
|
10
|
-
interface StateDefinition {
|
|
11
|
-
[key: string]: BaseChannel | (() => BaseChannel);
|
|
12
|
-
}
|
|
13
|
-
type ExtractValueType<C> = C extends BaseChannel ? C["ValueType"] : C extends () => BaseChannel ? ReturnType<C>["ValueType"] : never;
|
|
14
|
-
type ExtractUpdateType<C> = C extends BaseChannel ? C["UpdateType"] : C extends () => BaseChannel ? ReturnType<C>["UpdateType"] : never;
|
|
15
|
-
export type StateInterface<S extends StateDefinition> = {
|
|
16
|
-
[key in keyof S]: ExtractValueType<S[key]>;
|
|
17
|
-
};
|
|
18
|
-
export type UpdateInterface<S extends StateDefinition> = {
|
|
19
|
-
[key in keyof S]?: ExtractUpdateType<S[key]>;
|
|
20
|
-
};
|
|
21
|
-
type SingleReducer<ValueType, UpdateType = ValueType> = {
|
|
22
|
-
reducer: BinaryOperator<ValueType, UpdateType>;
|
|
23
|
-
default?: () => ValueType;
|
|
24
|
-
} | {
|
|
25
|
-
/**
|
|
26
|
-
* @deprecated Use `reducer` instead
|
|
27
|
-
*/
|
|
28
|
-
value: BinaryOperator<ValueType, UpdateType>;
|
|
29
|
-
default?: () => ValueType;
|
|
30
|
-
} | null;
|
|
6
|
+
import { AnnotationRoot, SingleReducer, StateDefinition, StateType, UpdateType } from "./annotation.js";
|
|
31
7
|
export type ChannelReducers<Channels extends object> = {
|
|
32
8
|
[K in keyof Channels]: SingleReducer<Channels[K], any>;
|
|
33
9
|
};
|
|
@@ -38,12 +14,12 @@ export interface StateGraphArgs<Channels extends object | unknown> {
|
|
|
38
14
|
__root__: Channels;
|
|
39
15
|
}>;
|
|
40
16
|
}
|
|
41
|
-
export declare class StateGraph<SD extends StateDefinition | unknown, S = SD extends StateDefinition ?
|
|
17
|
+
export declare class StateGraph<SD extends StateDefinition | unknown, S = SD extends StateDefinition ? StateType<SD> : SD, U = SD extends StateDefinition ? UpdateType<SD> : Partial<S>, N extends string = typeof START> extends Graph<N, S, U> {
|
|
42
18
|
channels: Record<string, BaseChannel>;
|
|
43
19
|
waitingEdges: Set<[N[], N]>;
|
|
44
|
-
constructor(fields: SD extends StateDefinition ? SD | StateGraphArgs<S> : StateGraphArgs<S>);
|
|
20
|
+
constructor(fields: SD extends StateDefinition ? SD | AnnotationRoot<SD> | StateGraphArgs<S> : StateGraphArgs<S>);
|
|
45
21
|
get allEdges(): Set<[string, string]>;
|
|
46
|
-
addNode<K extends string>(key: K, action: RunnableLike<
|
|
22
|
+
addNode<K extends string, NodeInput = S>(key: K, action: RunnableLike<NodeInput, U>): StateGraph<SD, S, U, N | K>;
|
|
47
23
|
addEdge(startKey: typeof START | N | N[], endKey: N | typeof END): this;
|
|
48
24
|
compile({ checkpointer, interruptBefore, interruptAfter, }?: {
|
|
49
25
|
checkpointer?: BaseCheckpointSaver;
|
|
@@ -58,4 +34,3 @@ export declare class CompiledStateGraph<S, U, N extends string = typeof START> e
|
|
|
58
34
|
attachEdge(start: N | N[] | "__start__", end: N | "__end__"): void;
|
|
59
35
|
attachBranch(start: N | typeof START, name: string, branch: Branch<S, N>): void;
|
|
60
36
|
}
|
|
61
|
-
export {};
|
package/dist/graph/state.js
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
|
-
import { BinaryOperatorAggregate } from "../channels/binop.js";
|
|
2
1
|
import { END, CompiledGraph, Graph, START } from "./graph.js";
|
|
3
|
-
import { LastValue } from "../channels/last_value.js";
|
|
4
2
|
import { ChannelWrite, PASSTHROUGH, SKIP_WRITE, } from "../pregel/write.js";
|
|
5
3
|
import { ChannelRead, PregelNode } from "../pregel/read.js";
|
|
6
4
|
import { NamedBarrierValue } from "../channels/named_barrier_value.js";
|
|
7
5
|
import { EphemeralValue } from "../channels/ephemeral_value.js";
|
|
8
6
|
import { RunnableCallable } from "../utils.js";
|
|
9
|
-
import { TAG_HIDDEN } from "../constants.js";
|
|
7
|
+
import { _isSend, TAG_HIDDEN } from "../constants.js";
|
|
10
8
|
import { InvalidUpdateError } from "../errors.js";
|
|
9
|
+
import { getChannel, } from "./annotation.js";
|
|
11
10
|
const ROOT = "__root__";
|
|
12
|
-
export function Annotation(annotation) {
|
|
13
|
-
if (annotation) {
|
|
14
|
-
return getChannel(annotation);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
// @ts-expect-error - Annotation without reducer
|
|
18
|
-
return new LastValue();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
11
|
export class StateGraph extends Graph {
|
|
22
12
|
constructor(fields) {
|
|
23
13
|
super();
|
|
@@ -34,9 +24,10 @@ export class StateGraph extends Graph {
|
|
|
34
24
|
writable: true,
|
|
35
25
|
value: new Set()
|
|
36
26
|
});
|
|
37
|
-
if (isStateDefinition(fields)) {
|
|
27
|
+
if (isStateDefinition(fields) || isAnnotationRoot(fields)) {
|
|
28
|
+
const spec = isAnnotationRoot(fields) ? fields.spec : fields;
|
|
38
29
|
this.channels = {};
|
|
39
|
-
for (const [key, val] of Object.entries(
|
|
30
|
+
for (const [key, val] of Object.entries(spec)) {
|
|
40
31
|
if (typeof val === "function") {
|
|
41
32
|
this.channels[key] = val();
|
|
42
33
|
}
|
|
@@ -152,22 +143,6 @@ function _getChannels(schema) {
|
|
|
152
143
|
}
|
|
153
144
|
return channels;
|
|
154
145
|
}
|
|
155
|
-
function getChannel(reducer) {
|
|
156
|
-
if (typeof reducer === "object" &&
|
|
157
|
-
reducer &&
|
|
158
|
-
"reducer" in reducer &&
|
|
159
|
-
reducer.reducer) {
|
|
160
|
-
return new BinaryOperatorAggregate(reducer.reducer, reducer.default);
|
|
161
|
-
}
|
|
162
|
-
if (typeof reducer === "object" &&
|
|
163
|
-
reducer &&
|
|
164
|
-
"value" in reducer &&
|
|
165
|
-
reducer.value) {
|
|
166
|
-
return new BinaryOperatorAggregate(reducer.value, reducer.default);
|
|
167
|
-
}
|
|
168
|
-
// @ts-expect-error - Annotation without reducer
|
|
169
|
-
return new LastValue();
|
|
170
|
-
}
|
|
171
146
|
export class CompiledStateGraph extends CompiledGraph {
|
|
172
147
|
attachNode(key, node) {
|
|
173
148
|
const stateKeys = Object.keys(this.builder.channels);
|
|
@@ -204,7 +179,7 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
204
179
|
});
|
|
205
180
|
}
|
|
206
181
|
else {
|
|
207
|
-
this.channels[key] = new EphemeralValue();
|
|
182
|
+
this.channels[key] = new EphemeralValue(false);
|
|
208
183
|
this.nodes[key] = new PregelNode({
|
|
209
184
|
triggers: [],
|
|
210
185
|
// read state keys
|
|
@@ -261,10 +236,15 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
261
236
|
if (!filteredDests.length) {
|
|
262
237
|
return;
|
|
263
238
|
}
|
|
264
|
-
const writes = filteredDests.map((dest) =>
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
239
|
+
const writes = filteredDests.map((dest) => {
|
|
240
|
+
if (_isSend(dest)) {
|
|
241
|
+
return dest;
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
channel: `branch:${start}:${name}:${dest}`,
|
|
245
|
+
value: start,
|
|
246
|
+
};
|
|
247
|
+
});
|
|
268
248
|
return new ChannelWrite(writes, [TAG_HIDDEN]);
|
|
269
249
|
},
|
|
270
250
|
// reader
|
|
@@ -279,7 +259,7 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
279
259
|
}
|
|
280
260
|
const channelName = `branch:${start}:${name}:${end}`;
|
|
281
261
|
this.channels[channelName] =
|
|
282
|
-
new EphemeralValue();
|
|
262
|
+
new EphemeralValue(false);
|
|
283
263
|
this.nodes[end].triggers.push(channelName);
|
|
284
264
|
}
|
|
285
265
|
}
|
|
@@ -294,3 +274,9 @@ function isStateDefinition(obj) {
|
|
|
294
274
|
Object.keys(obj).length > 0 &&
|
|
295
275
|
Object.values(obj).every((v) => typeof v === "function" || isBaseChannel(v)));
|
|
296
276
|
}
|
|
277
|
+
function isAnnotationRoot(obj) {
|
|
278
|
+
return (typeof obj === "object" &&
|
|
279
|
+
obj !== null &&
|
|
280
|
+
"lc_graph_name" in obj &&
|
|
281
|
+
obj.lc_graph_name === "AnnotationRoot");
|
|
282
|
+
}
|
package/dist/pregel/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports._prepareNextTasks = exports._applyWrites = exports._localRead = exports._shouldInterrupt = exports.Pregel = exports.Channel = void 0;
|
|
3
|
+
exports._prepareNextTasks = exports._applyWrites = exports._localWrite = exports._localRead = exports._shouldInterrupt = exports.Pregel = exports.Channel = void 0;
|
|
4
4
|
/* eslint-disable no-param-reassign */
|
|
5
5
|
const runnables_1 = require("@langchain/core/runnables");
|
|
6
6
|
const stream_1 = require("@langchain/core/utils/stream");
|
|
@@ -213,7 +213,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
213
213
|
const checkpoint = saved ? saved.checkpoint : (0, base_js_2.emptyCheckpoint)();
|
|
214
214
|
const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
|
|
215
215
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
216
|
-
const [_, nextTasks] = _prepareNextTasks(checkpoint, this.nodes, channels, false);
|
|
216
|
+
const [_, nextTasks] = _prepareNextTasks(checkpoint, this.nodes, channels, false, { step: -1 });
|
|
217
217
|
return {
|
|
218
218
|
values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
|
|
219
219
|
next: nextTasks.map((task) => task.name),
|
|
@@ -230,7 +230,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
230
230
|
for await (const saved of this.checkpointer.list(config, limit, before)) {
|
|
231
231
|
const channels = (0, base_js_1.emptyChannels)(this.channels, saved.checkpoint);
|
|
232
232
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
233
|
-
const [_, nextTasks] = _prepareNextTasks(saved.checkpoint, this.nodes, channels, false);
|
|
233
|
+
const [_, nextTasks] = _prepareNextTasks(saved.checkpoint, this.nodes, channels, false, { step: -1 });
|
|
234
234
|
yield {
|
|
235
235
|
values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
|
|
236
236
|
next: nextTasks.map((task) => task.name),
|
|
@@ -380,7 +380,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
380
380
|
}
|
|
381
381
|
if (inputPendingWrites.length) {
|
|
382
382
|
// discard any unfinished tasks from previous checkpoint
|
|
383
|
-
const discarded = _prepareNextTasks(checkpoint, processes, channels, true);
|
|
383
|
+
const discarded = _prepareNextTasks(checkpoint, processes, channels, true, { step: -1 });
|
|
384
384
|
checkpoint = discarded[0]; // eslint-disable-line prefer-destructuring
|
|
385
385
|
// apply input writes
|
|
386
386
|
_applyWrites(checkpoint, channels, inputPendingWrites);
|
|
@@ -419,7 +419,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
419
419
|
// with channel updates applied only at the transition between steps
|
|
420
420
|
const stop = start + (config.recursionLimit ?? DEFAULT_LOOP_LIMIT);
|
|
421
421
|
for (let step = start; step < stop + 1; step += 1) {
|
|
422
|
-
const [nextCheckpoint, nextTasks] = _prepareNextTasks(checkpoint, processes, channels, true);
|
|
422
|
+
const [nextCheckpoint, nextTasks] = _prepareNextTasks(checkpoint, processes, channels, true, { step });
|
|
423
423
|
// if no more tasks, we're done
|
|
424
424
|
if (nextTasks.length === 0 && step === start) {
|
|
425
425
|
throw new errors_js_1.GraphValueError(`No tasks to run in graph.`);
|
|
@@ -478,7 +478,10 @@ class Pregel extends runnables_1.Runnable {
|
|
|
478
478
|
yield* (0, io_js_1.mapOutputValues)(outputKeys, pendingWrites, channels);
|
|
479
479
|
}
|
|
480
480
|
else if (streamMode === "updates") {
|
|
481
|
-
|
|
481
|
+
// TODO: Refactor
|
|
482
|
+
for await (const task of nextTasks) {
|
|
483
|
+
yield* (0, io_js_1.mapOutputUpdates)(outputKeys, [task]);
|
|
484
|
+
}
|
|
482
485
|
}
|
|
483
486
|
// save end of step checkpoint
|
|
484
487
|
if (this.checkpointer) {
|
|
@@ -587,15 +590,47 @@ function _localRead(checkpoint, channels, writes, select, fresh = false) {
|
|
|
587
590
|
}
|
|
588
591
|
}
|
|
589
592
|
exports._localRead = _localRead;
|
|
593
|
+
function _localWrite(
|
|
594
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
595
|
+
commit, processes, channels,
|
|
596
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
597
|
+
writes) {
|
|
598
|
+
for (const [chan, value] of writes) {
|
|
599
|
+
if (chan === constants_js_1.TASKS) {
|
|
600
|
+
if (!(0, constants_js_1._isSend)(value)) {
|
|
601
|
+
throw new errors_js_1.InvalidUpdateError(`Invalid packet type, expected SendProtocol, got ${JSON.stringify(value)}`);
|
|
602
|
+
}
|
|
603
|
+
if (!(value.node in processes)) {
|
|
604
|
+
throw new errors_js_1.InvalidUpdateError(`Invalid node name ${value.node} in packet`);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
else if (!(chan in channels)) {
|
|
608
|
+
console.warn(`Skipping write for channel '${chan}' which has no readers`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
commit(writes);
|
|
612
|
+
}
|
|
613
|
+
exports._localWrite = _localWrite;
|
|
590
614
|
function _applyWrites(checkpoint, channels, pendingWrites) {
|
|
615
|
+
if (checkpoint.pending_sends) {
|
|
616
|
+
checkpoint.pending_sends = [];
|
|
617
|
+
}
|
|
591
618
|
const pendingWritesByChannel = {};
|
|
592
619
|
// Group writes by channel
|
|
593
620
|
for (const [chan, val] of pendingWrites) {
|
|
594
|
-
if (chan
|
|
595
|
-
|
|
621
|
+
if (chan === constants_js_1.TASKS) {
|
|
622
|
+
checkpoint.pending_sends.push({
|
|
623
|
+
node: val.node,
|
|
624
|
+
args: val.args,
|
|
625
|
+
});
|
|
596
626
|
}
|
|
597
627
|
else {
|
|
598
|
-
|
|
628
|
+
if (chan in pendingWritesByChannel) {
|
|
629
|
+
pendingWritesByChannel[chan].push(val);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
pendingWritesByChannel[chan] = [val];
|
|
633
|
+
}
|
|
599
634
|
}
|
|
600
635
|
}
|
|
601
636
|
// find the highest version of all channels
|
|
@@ -614,7 +649,7 @@ function _applyWrites(checkpoint, channels, pendingWrites) {
|
|
|
614
649
|
}
|
|
615
650
|
catch (e) {
|
|
616
651
|
if (e.name === errors_js_1.InvalidUpdateError.unminifiable_name) {
|
|
617
|
-
throw new errors_js_1.InvalidUpdateError(`Invalid update for channel ${chan}. Values: ${vals}`);
|
|
652
|
+
throw new errors_js_1.InvalidUpdateError(`Invalid update for channel ${chan}. Values: ${vals}\n\nError: ${e.message}`);
|
|
618
653
|
}
|
|
619
654
|
}
|
|
620
655
|
// side effect: update checkpoint channel versions
|
|
@@ -634,15 +669,60 @@ function _applyWrites(checkpoint, channels, pendingWrites) {
|
|
|
634
669
|
}
|
|
635
670
|
}
|
|
636
671
|
exports._applyWrites = _applyWrites;
|
|
637
|
-
function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
672
|
+
function _prepareNextTasks(checkpoint, processes, channels, forExecution, extra) {
|
|
638
673
|
const newCheckpoint = (0, base_js_2.copyCheckpoint)(checkpoint);
|
|
639
674
|
const tasks = [];
|
|
640
675
|
const taskDescriptions = [];
|
|
676
|
+
for (const packet of checkpoint.pending_sends) {
|
|
677
|
+
if (!(0, constants_js_1._isSendInterface)(packet)) {
|
|
678
|
+
console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
if (!(packet.node in processes)) {
|
|
682
|
+
console.warn(`Ignoring unknown node name ${packet.node} in pending sends.`);
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
if (forExecution) {
|
|
686
|
+
const proc = processes[packet.node];
|
|
687
|
+
const node = proc.getNode();
|
|
688
|
+
if (node !== undefined) {
|
|
689
|
+
const triggers = [constants_js_1.TASKS];
|
|
690
|
+
const metadata = {
|
|
691
|
+
langgraph_step: extra.step,
|
|
692
|
+
langgraph_node: packet.node,
|
|
693
|
+
langgraph_triggers: triggers,
|
|
694
|
+
langgraph_task_idx: tasks.length,
|
|
695
|
+
};
|
|
696
|
+
const writes = [];
|
|
697
|
+
tasks.push({
|
|
698
|
+
name: packet.node,
|
|
699
|
+
input: packet.args,
|
|
700
|
+
proc: node,
|
|
701
|
+
writes,
|
|
702
|
+
config: (0, runnables_1.patchConfig)((0, runnables_1.mergeConfigs)(proc.config, processes[packet.node].config, {
|
|
703
|
+
metadata,
|
|
704
|
+
}), {
|
|
705
|
+
runName: packet.node,
|
|
706
|
+
// callbacks:
|
|
707
|
+
configurable: {
|
|
708
|
+
[constants_js_1.CONFIG_KEY_SEND]: _localWrite.bind(undefined, (items) => writes.push(...items), processes, channels),
|
|
709
|
+
[constants_js_1.CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, writes),
|
|
710
|
+
},
|
|
711
|
+
}),
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
taskDescriptions.push({
|
|
717
|
+
name: packet.node,
|
|
718
|
+
input: packet.args,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
}
|
|
641
722
|
// Check if any processes should be run in next step
|
|
642
723
|
// If so, prepare the values to be passed to them
|
|
643
724
|
for (const [name, proc] of Object.entries(processes)) {
|
|
644
|
-
|
|
645
|
-
if (proc.triggers
|
|
725
|
+
const hasUpdatedChannels = proc.triggers
|
|
646
726
|
.filter((chan) => {
|
|
647
727
|
try {
|
|
648
728
|
(0, io_js_1.readChannel)(channels, chan, false);
|
|
@@ -653,7 +733,9 @@ function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
|
653
733
|
}
|
|
654
734
|
})
|
|
655
735
|
.some((chan) => (0, base_js_2.getChannelVersion)(newCheckpoint, chan) >
|
|
656
|
-
(0, base_js_2.getVersionSeen)(newCheckpoint, name, chan))
|
|
736
|
+
(0, base_js_2.getVersionSeen)(newCheckpoint, name, chan));
|
|
737
|
+
// If any of the channels read by this process were updated
|
|
738
|
+
if (hasUpdatedChannels) {
|
|
657
739
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
658
740
|
let val;
|
|
659
741
|
// If all trigger channels subscribed by this process are not empty
|
|
@@ -718,12 +800,25 @@ function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
|
718
800
|
});
|
|
719
801
|
const node = proc.getNode();
|
|
720
802
|
if (node !== undefined) {
|
|
803
|
+
const metadata = {
|
|
804
|
+
langgraph_step: extra.step,
|
|
805
|
+
langgraph_node: name,
|
|
806
|
+
langgraph_triggers: proc.triggers,
|
|
807
|
+
langgraph_task_idx: tasks.length,
|
|
808
|
+
};
|
|
809
|
+
const writes = [];
|
|
721
810
|
tasks.push({
|
|
722
811
|
name,
|
|
723
812
|
input: val,
|
|
724
813
|
proc: node,
|
|
725
|
-
writes
|
|
726
|
-
config: proc.config,
|
|
814
|
+
writes,
|
|
815
|
+
config: (0, runnables_1.patchConfig)((0, runnables_1.mergeConfigs)(proc.config, { metadata }), {
|
|
816
|
+
runName: name,
|
|
817
|
+
configurable: {
|
|
818
|
+
[constants_js_1.CONFIG_KEY_SEND]: _localWrite.bind(undefined, (items) => writes.push(...items), processes, channels),
|
|
819
|
+
[constants_js_1.CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, writes),
|
|
820
|
+
},
|
|
821
|
+
}),
|
|
727
822
|
});
|
|
728
823
|
}
|
|
729
824
|
}
|
package/dist/pregel/index.d.ts
CHANGED
|
@@ -108,7 +108,12 @@ export declare class Pregel<Nn extends StrRecord<string, PregelNode>, Cc extends
|
|
|
108
108
|
}
|
|
109
109
|
export declare function _shouldInterrupt<N extends PropertyKey, C extends PropertyKey>(checkpoint: ReadonlyCheckpoint, interruptNodes: All | Array<N>, snapshotChannels: Array<C>, tasks: Array<PregelExecutableTask<N, C>>): boolean;
|
|
110
110
|
export declare function _localRead<Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, channels: Cc, writes: Array<[keyof Cc, unknown]>, select: Array<keyof Cc> | keyof Cc, fresh?: boolean): Record<string, unknown> | unknown;
|
|
111
|
+
export declare function _localWrite(commit: (writes: [string, any][]) => void, processes: Record<string, PregelNode>, channels: Record<string, BaseChannel>, writes: [string, any][]): void;
|
|
111
112
|
export declare function _applyWrites<Cc extends Record<string, BaseChannel>>(checkpoint: Checkpoint, channels: Cc, pendingWrites: Array<[keyof Cc, unknown]>): void;
|
|
112
|
-
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, processes: Nn, channels: Cc, forExecution: false
|
|
113
|
-
|
|
113
|
+
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, processes: Nn, channels: Cc, forExecution: false, extra: {
|
|
114
|
+
step: number;
|
|
115
|
+
}): [Checkpoint, Array<PregelTaskDescription>];
|
|
116
|
+
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, processes: Nn, channels: Cc, forExecution: true, extra: {
|
|
117
|
+
step: number;
|
|
118
|
+
}): [Checkpoint, Array<PregelExecutableTask<keyof Nn, keyof Cc>>];
|
|
114
119
|
export {};
|