@langchain/langgraph 0.3.11 → 0.4.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/CHANGELOG.md +27 -0
- package/dist/channels/base.cjs +1 -2
- package/dist/channels/base.js +1 -2
- package/dist/channels/base.js.map +1 -1
- package/dist/channels/topic.cjs +5 -5
- package/dist/channels/topic.js +5 -5
- package/dist/channels/topic.js.map +1 -1
- package/dist/constants.cjs +3 -3
- package/dist/constants.d.ts +2 -5
- package/dist/constants.js +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/graph/annotation.cjs +1 -5
- package/dist/graph/annotation.d.ts +4 -5
- package/dist/graph/annotation.js +1 -5
- package/dist/graph/annotation.js.map +1 -1
- package/dist/graph/graph.cjs +1 -3
- package/dist/graph/graph.d.ts +3 -3
- package/dist/graph/graph.js +1 -3
- package/dist/graph/graph.js.map +1 -1
- package/dist/graph/state.cjs +6 -10
- package/dist/graph/state.d.ts +8 -8
- package/dist/graph/state.js +7 -11
- package/dist/graph/state.js.map +1 -1
- package/dist/interrupt.cjs +2 -13
- package/dist/interrupt.js +2 -13
- package/dist/interrupt.js.map +1 -1
- package/dist/prebuilt/agent_executor.d.ts +22 -1
- package/dist/prebuilt/agent_executor.js.map +1 -1
- package/dist/pregel/algo.cjs +42 -71
- package/dist/pregel/algo.d.ts +9 -10
- package/dist/pregel/algo.js +42 -71
- package/dist/pregel/algo.js.map +1 -1
- package/dist/pregel/index.cjs +56 -92
- package/dist/pregel/index.d.ts +12 -30
- package/dist/pregel/index.js +57 -93
- package/dist/pregel/index.js.map +1 -1
- package/dist/pregel/loop.cjs +25 -86
- package/dist/pregel/loop.d.ts +5 -11
- package/dist/pregel/loop.js +25 -86
- package/dist/pregel/loop.js.map +1 -1
- package/dist/pregel/remote.cjs +5 -1
- package/dist/pregel/remote.d.ts +9 -12
- package/dist/pregel/remote.js +5 -1
- package/dist/pregel/remote.js.map +1 -1
- package/dist/pregel/runnable_types.d.ts +15 -2
- package/dist/pregel/types.d.ts +23 -10
- package/dist/pregel/types.js.map +1 -1
- package/dist/pregel/utils/config.cjs +2 -0
- package/dist/pregel/utils/config.js +2 -0
- package/dist/pregel/utils/config.js.map +1 -1
- package/dist/pregel/validate.d.ts +2 -3
- package/dist/pregel/validate.js.map +1 -1
- package/dist/web.cjs +0 -1
- package/dist/web.d.ts +1 -2
- package/dist/web.js +0 -1
- package/dist/web.js.map +1 -1
- package/package.json +7 -6
- package/dist/managed/base.cjs +0 -177
- package/dist/managed/base.d.ts +0 -38
- package/dist/managed/base.js +0 -168
- package/dist/managed/base.js.map +0 -1
- package/dist/managed/index.cjs +0 -20
- package/dist/managed/index.d.ts +0 -3
- package/dist/managed/index.js +0 -4
- package/dist/managed/index.js.map +0 -1
- package/dist/managed/is_last_step.cjs +0 -12
- package/dist/managed/is_last_step.d.ts +0 -4
- package/dist/managed/is_last_step.js +0 -8
- package/dist/managed/is_last_step.js.map +0 -1
- package/dist/managed/shared_value.cjs +0 -112
- package/dist/managed/shared_value.d.ts +0 -24
- package/dist/managed/shared_value.js +0 -108
- package/dist/managed/shared_value.js.map +0 -1
package/dist/pregel/algo.cjs
CHANGED
|
@@ -41,8 +41,7 @@ function shouldInterrupt(checkpoint, interruptNodes, tasks) {
|
|
|
41
41
|
: interruptNodes.includes(task.name));
|
|
42
42
|
return anyChannelUpdated && anyTriggeredNodeInInterruptNodes;
|
|
43
43
|
}
|
|
44
|
-
function _localRead(
|
|
45
|
-
let managedKeys = [];
|
|
44
|
+
function _localRead(checkpoint, channels, task, select, fresh = false) {
|
|
46
45
|
let updated = new Set();
|
|
47
46
|
if (!Array.isArray(select)) {
|
|
48
47
|
for (const [c] of task.writes) {
|
|
@@ -54,8 +53,6 @@ function _localRead(step, checkpoint, channels, managed, task, select, fresh = f
|
|
|
54
53
|
updated = updated || new Set();
|
|
55
54
|
}
|
|
56
55
|
else {
|
|
57
|
-
managedKeys = select.filter((k) => managed.get(k));
|
|
58
|
-
select = select.filter((k) => !managed.get(k));
|
|
59
56
|
updated = new Set(select.filter((c) => task.writes.some(([key, _]) => key === c)));
|
|
60
57
|
}
|
|
61
58
|
let values;
|
|
@@ -69,20 +66,11 @@ function _localRead(step, checkpoint, channels, managed, task, select, fresh = f
|
|
|
69
66
|
else {
|
|
70
67
|
values = (0, io_js_1.readChannels)(channels, select);
|
|
71
68
|
}
|
|
72
|
-
if (managedKeys.length > 0) {
|
|
73
|
-
for (const k of managedKeys) {
|
|
74
|
-
const managedValue = managed.get(k);
|
|
75
|
-
if (managedValue) {
|
|
76
|
-
const resultOfManagedCall = managedValue.call(step);
|
|
77
|
-
values[k] = resultOfManagedCall;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
69
|
return values;
|
|
82
70
|
}
|
|
83
|
-
function _localWrite(
|
|
71
|
+
function _localWrite(
|
|
84
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
-
commit, processes,
|
|
73
|
+
commit, processes,
|
|
86
74
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
75
|
writes) {
|
|
88
76
|
for (const [chan, value] of writes) {
|
|
@@ -93,8 +81,6 @@ writes) {
|
|
|
93
81
|
if (!(value.node in processes)) {
|
|
94
82
|
throw new errors_js_1.InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
|
|
95
83
|
}
|
|
96
|
-
// replace any runtime values with placeholders
|
|
97
|
-
managed.replaceRuntimeValues(step, value.args);
|
|
98
84
|
}
|
|
99
85
|
}
|
|
100
86
|
commit(writes);
|
|
@@ -152,47 +138,32 @@ getNextVersion, triggerToNodes) {
|
|
|
152
138
|
for (const chan of channelsToConsume) {
|
|
153
139
|
if (chan in onlyChannels && onlyChannels[chan].consume()) {
|
|
154
140
|
if (getNextVersion !== undefined) {
|
|
155
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
141
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
156
142
|
}
|
|
157
143
|
}
|
|
158
144
|
}
|
|
159
|
-
// Clear pending sends
|
|
160
|
-
if (checkpoint.pending_sends?.length && bumpStep) {
|
|
161
|
-
checkpoint.pending_sends = [];
|
|
162
|
-
}
|
|
163
145
|
// Group writes by channel
|
|
164
|
-
const
|
|
165
|
-
const pendingWritesByManaged = {};
|
|
146
|
+
const pendingWritesByChannel = {};
|
|
166
147
|
for (const task of tasks) {
|
|
167
148
|
for (const [chan, val] of task.writes) {
|
|
168
149
|
if (IGNORE.has(chan)) {
|
|
169
150
|
// do nothing
|
|
170
151
|
}
|
|
171
|
-
else if (chan === constants_js_1.TASKS) {
|
|
172
|
-
// TODO: remove branch in 1.0
|
|
173
|
-
checkpoint.pending_sends.push({
|
|
174
|
-
node: val.node,
|
|
175
|
-
args: val.args,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
152
|
else if (chan in onlyChannels) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
pendingWritesByManaged[chan] ??= [];
|
|
184
|
-
pendingWritesByManaged[chan].push(val);
|
|
153
|
+
pendingWritesByChannel[chan] ??= [];
|
|
154
|
+
pendingWritesByChannel[chan].push(val);
|
|
185
155
|
}
|
|
186
156
|
}
|
|
187
157
|
}
|
|
188
|
-
//
|
|
158
|
+
// Find the highest version of all channels
|
|
159
|
+
// TODO: figure out why we need to do this twice (Python only does this once)
|
|
189
160
|
maxVersion = undefined;
|
|
190
161
|
if (Object.keys(checkpoint.channel_versions).length > 0) {
|
|
191
162
|
maxVersion = (0, langgraph_checkpoint_1.maxChannelVersion)(...Object.values(checkpoint.channel_versions));
|
|
192
163
|
}
|
|
193
164
|
const updatedChannels = new Set();
|
|
194
165
|
// Apply writes to channels
|
|
195
|
-
for (const [chan, vals] of Object.entries(
|
|
166
|
+
for (const [chan, vals] of Object.entries(pendingWritesByChannel)) {
|
|
196
167
|
if (chan in onlyChannels) {
|
|
197
168
|
let updated;
|
|
198
169
|
try {
|
|
@@ -210,7 +181,7 @@ getNextVersion, triggerToNodes) {
|
|
|
210
181
|
}
|
|
211
182
|
}
|
|
212
183
|
if (updated && getNextVersion !== undefined) {
|
|
213
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
184
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
214
185
|
// unavailable channels can't trigger tasks, so don't add them
|
|
215
186
|
if (onlyChannels[chan].isAvailable()) {
|
|
216
187
|
updatedChannels.add(chan);
|
|
@@ -224,7 +195,7 @@ getNextVersion, triggerToNodes) {
|
|
|
224
195
|
if (onlyChannels[chan].isAvailable() && !updatedChannels.has(chan)) {
|
|
225
196
|
const updated = onlyChannels[chan].update([]);
|
|
226
197
|
if (updated && getNextVersion !== undefined) {
|
|
227
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
198
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
228
199
|
// unavailable channels can't trigger tasks, so don't add them
|
|
229
200
|
if (onlyChannels[chan].isAvailable()) {
|
|
230
201
|
updatedChannels.add(chan);
|
|
@@ -235,11 +206,10 @@ getNextVersion, triggerToNodes) {
|
|
|
235
206
|
}
|
|
236
207
|
// If this is (tentatively) the last superstep, notify all channels of finish
|
|
237
208
|
if (bumpStep &&
|
|
238
|
-
checkpoint.pending_sends.length === 0 &&
|
|
239
209
|
!Object.keys(triggerToNodes ?? {}).some((channel) => updatedChannels.has(channel))) {
|
|
240
210
|
for (const chan of Object.keys(onlyChannels)) {
|
|
241
211
|
if (onlyChannels[chan].finish() && getNextVersion !== undefined) {
|
|
242
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
212
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
243
213
|
// unavailable channels can't trigger tasks, so don't add them
|
|
244
214
|
if (onlyChannels[chan].isAvailable()) {
|
|
245
215
|
updatedChannels.add(chan);
|
|
@@ -247,27 +217,29 @@ getNextVersion, triggerToNodes) {
|
|
|
247
217
|
}
|
|
248
218
|
}
|
|
249
219
|
}
|
|
250
|
-
// Return managed values writes to be applied externally
|
|
251
|
-
return pendingWritesByManaged;
|
|
252
220
|
}
|
|
253
221
|
/**
|
|
254
222
|
* Prepare the set of tasks that will make up the next Pregel step.
|
|
255
223
|
* This is the union of all PUSH tasks (Sends) and PULL tasks (nodes triggered
|
|
256
224
|
* by edges).
|
|
257
225
|
*/
|
|
258
|
-
function _prepareNextTasks(checkpoint, pendingWrites, processes, channels,
|
|
226
|
+
function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
|
|
259
227
|
const tasks = {};
|
|
260
|
-
// Consume pending
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
228
|
+
// Consume pending tasks
|
|
229
|
+
const tasksChannel = channels[constants_js_1.TASKS];
|
|
230
|
+
if (tasksChannel?.isAvailable()) {
|
|
231
|
+
const len = tasksChannel.get().length;
|
|
232
|
+
for (let i = 0; i < len; i += 1) {
|
|
233
|
+
const task = _prepareSingleTask([constants_js_1.PUSH, i], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
|
|
234
|
+
if (task !== undefined) {
|
|
235
|
+
tasks[task.id] = task;
|
|
236
|
+
}
|
|
265
237
|
}
|
|
266
238
|
}
|
|
267
239
|
// Check if any processes should be run in next step
|
|
268
240
|
// If so, prepare the values to be passed to them
|
|
269
241
|
for (const name of Object.keys(processes)) {
|
|
270
|
-
const task = _prepareSingleTask([constants_js_1.PULL, name], checkpoint, pendingWrites, processes, channels,
|
|
242
|
+
const task = _prepareSingleTask([constants_js_1.PULL, name], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
|
|
271
243
|
if (task !== undefined) {
|
|
272
244
|
tasks[task.id] = task;
|
|
273
245
|
}
|
|
@@ -278,7 +250,7 @@ function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, manag
|
|
|
278
250
|
* Prepares a single task for the next Pregel step, given a task path, which
|
|
279
251
|
* uniquely identifies a PUSH or PULL task within the graph.
|
|
280
252
|
*/
|
|
281
|
-
function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels,
|
|
253
|
+
function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
|
|
282
254
|
const { step, checkpointer, manager } = extra;
|
|
283
255
|
const configurable = config.configurable ?? {};
|
|
284
256
|
const parentNamespace = configurable.checkpoint_ns ?? "";
|
|
@@ -324,8 +296,8 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
324
296
|
configurable: {
|
|
325
297
|
[constants_js_1.CONFIG_KEY_TASK_ID]: id,
|
|
326
298
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
|
-
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
328
|
-
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
299
|
+
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
|
|
300
|
+
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
329
301
|
name: call.name,
|
|
330
302
|
writes: writes,
|
|
331
303
|
triggers,
|
|
@@ -376,13 +348,16 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
376
348
|
const index = typeof taskPath[1] === "number"
|
|
377
349
|
? taskPath[1]
|
|
378
350
|
: parseInt(taskPath[1], 10);
|
|
379
|
-
if (
|
|
351
|
+
if (!channels[constants_js_1.TASKS]?.isAvailable()) {
|
|
380
352
|
return undefined;
|
|
381
353
|
}
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
354
|
+
const sends = channels[constants_js_1.TASKS].get();
|
|
355
|
+
if (index < 0 || index >= sends.length) {
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
const packet = (0, constants_js_1._isSendInterface)(sends[index]) && !(0, constants_js_1._isSend)(sends[index])
|
|
359
|
+
? new constants_js_1.Send(sends[index].node, sends[index].args)
|
|
360
|
+
: sends[index];
|
|
386
361
|
if (!(0, constants_js_1._isSendInterface)(packet)) {
|
|
387
362
|
console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
|
|
388
363
|
return undefined;
|
|
@@ -414,7 +389,6 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
414
389
|
const proc = processes[packet.node];
|
|
415
390
|
const node = proc.getNode();
|
|
416
391
|
if (node !== undefined) {
|
|
417
|
-
managed.replaceRuntimePlaceholders(step, packet.args);
|
|
418
392
|
if (proc.metadata !== undefined) {
|
|
419
393
|
metadata = { ...metadata, ...proc.metadata };
|
|
420
394
|
}
|
|
@@ -435,8 +409,8 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
435
409
|
configurable: {
|
|
436
410
|
[constants_js_1.CONFIG_KEY_TASK_ID]: taskId,
|
|
437
411
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
438
|
-
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
439
|
-
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
412
|
+
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
|
|
413
|
+
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
440
414
|
name: packet.node,
|
|
441
415
|
writes: writes,
|
|
442
416
|
triggers,
|
|
@@ -528,7 +502,7 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
528
502
|
.sort();
|
|
529
503
|
// If any of the channels read by this process were updated
|
|
530
504
|
if (triggers.length > 0) {
|
|
531
|
-
const val = _procInput(
|
|
505
|
+
const val = _procInput(proc, channels, forExecution);
|
|
532
506
|
if (val === undefined) {
|
|
533
507
|
return undefined;
|
|
534
508
|
}
|
|
@@ -573,10 +547,10 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
573
547
|
configurable: {
|
|
574
548
|
[constants_js_1.CONFIG_KEY_TASK_ID]: taskId,
|
|
575
549
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
576
|
-
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
550
|
+
[constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => {
|
|
577
551
|
writes.push(...items);
|
|
578
|
-
}, processes,
|
|
579
|
-
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
552
|
+
}, processes, writes_),
|
|
553
|
+
[constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
580
554
|
name,
|
|
581
555
|
writes: writes,
|
|
582
556
|
triggers,
|
|
@@ -633,7 +607,7 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
|
|
|
633
607
|
*
|
|
634
608
|
* @internal
|
|
635
609
|
*/
|
|
636
|
-
function _procInput(
|
|
610
|
+
function _procInput(proc, channels, forExecution) {
|
|
637
611
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
638
612
|
let val;
|
|
639
613
|
if (typeof proc.channels === "object" && !Array.isArray(proc.channels)) {
|
|
@@ -667,9 +641,6 @@ function _procInput(step, proc, managed, channels, forExecution) {
|
|
|
667
641
|
}
|
|
668
642
|
}
|
|
669
643
|
}
|
|
670
|
-
else {
|
|
671
|
-
val[k] = managed.get(k)?.call(step);
|
|
672
|
-
}
|
|
673
644
|
}
|
|
674
645
|
}
|
|
675
646
|
else if (Array.isArray(proc.channels)) {
|
package/dist/pregel/algo.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { RunnableConfig } from "@langchain/core/runnables";
|
|
2
2
|
import { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
|
|
3
|
-
import { All, BaseCheckpointSaver, Checkpoint, ReadonlyCheckpoint, type PendingWrite,
|
|
3
|
+
import { All, BaseCheckpointSaver, Checkpoint, ReadonlyCheckpoint, type PendingWrite, BaseStore, CheckpointPendingWrite } from "@langchain/langgraph-checkpoint";
|
|
4
4
|
import { BaseChannel } from "../channels/base.js";
|
|
5
5
|
import { PregelNode } from "./read.js";
|
|
6
6
|
import { PregelExecutableTask, PregelTaskDescription, SimpleTaskPath, TaskPath } from "./types.js";
|
|
7
|
-
import { ManagedValueMapping } from "../managed/base.js";
|
|
8
7
|
import { IterableReadableWritableStream } from "./stream.js";
|
|
9
8
|
/**
|
|
10
9
|
* Construct a type with a set of properties K of type T
|
|
@@ -20,9 +19,9 @@ export type WritesProtocol<C = string> = {
|
|
|
20
19
|
};
|
|
21
20
|
export declare const increment: (current?: number) => number;
|
|
22
21
|
export declare function shouldInterrupt<N extends PropertyKey, C extends PropertyKey>(checkpoint: Checkpoint, interruptNodes: All | N[], tasks: PregelExecutableTask<N, C>[]): boolean;
|
|
23
|
-
export declare function _localRead<Cc extends Record<string, BaseChannel>>(
|
|
24
|
-
export declare function _localWrite(
|
|
25
|
-
export declare function _applyWrites<Cc extends Record<string, BaseChannel>>(checkpoint: Checkpoint, channels: Cc, tasks: WritesProtocol<keyof Cc>[], getNextVersion: ((version: any
|
|
22
|
+
export declare function _localRead<Cc extends Record<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, channels: Cc, task: WritesProtocol<keyof Cc>, select: Array<keyof Cc> | keyof Cc, fresh?: boolean): Record<string, unknown> | unknown;
|
|
23
|
+
export declare function _localWrite(commit: (writes: [string, any][]) => any, processes: Record<string, PregelNode>, writes: [string, any][]): void;
|
|
24
|
+
export declare function _applyWrites<Cc extends Record<string, BaseChannel>>(checkpoint: Checkpoint, channels: Cc, tasks: WritesProtocol<keyof Cc>[], getNextVersion: ((version: any) => any) | undefined, triggerToNodes: Record<string, string[]> | undefined): void;
|
|
26
25
|
export type NextTaskExtraFields = {
|
|
27
26
|
step: number;
|
|
28
27
|
isResuming?: boolean;
|
|
@@ -37,8 +36,8 @@ export type NextTaskExtraFieldsWithStore = NextTaskExtraFields & {
|
|
|
37
36
|
export type NextTaskExtraFieldsWithoutStore = NextTaskExtraFields & {
|
|
38
37
|
store?: never;
|
|
39
38
|
};
|
|
40
|
-
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc,
|
|
41
|
-
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc,
|
|
42
|
-
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: SimpleTaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc,
|
|
43
|
-
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc,
|
|
44
|
-
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc,
|
|
39
|
+
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFieldsWithoutStore): Record<string, PregelTaskDescription>;
|
|
40
|
+
export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFieldsWithStore): Record<string, PregelExecutableTask<keyof Nn, keyof Cc>>;
|
|
41
|
+
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: SimpleTaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFields): PregelTaskDescription | undefined;
|
|
42
|
+
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFields): PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
|
|
43
|
+
export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: boolean, extra: NextTaskExtraFieldsWithStore): PregelTaskDescription | PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
|
package/dist/pregel/algo.js
CHANGED
|
@@ -31,8 +31,7 @@ export function shouldInterrupt(checkpoint, interruptNodes, tasks) {
|
|
|
31
31
|
: interruptNodes.includes(task.name));
|
|
32
32
|
return anyChannelUpdated && anyTriggeredNodeInInterruptNodes;
|
|
33
33
|
}
|
|
34
|
-
export function _localRead(
|
|
35
|
-
let managedKeys = [];
|
|
34
|
+
export function _localRead(checkpoint, channels, task, select, fresh = false) {
|
|
36
35
|
let updated = new Set();
|
|
37
36
|
if (!Array.isArray(select)) {
|
|
38
37
|
for (const [c] of task.writes) {
|
|
@@ -44,8 +43,6 @@ export function _localRead(step, checkpoint, channels, managed, task, select, fr
|
|
|
44
43
|
updated = updated || new Set();
|
|
45
44
|
}
|
|
46
45
|
else {
|
|
47
|
-
managedKeys = select.filter((k) => managed.get(k));
|
|
48
|
-
select = select.filter((k) => !managed.get(k));
|
|
49
46
|
updated = new Set(select.filter((c) => task.writes.some(([key, _]) => key === c)));
|
|
50
47
|
}
|
|
51
48
|
let values;
|
|
@@ -59,20 +56,11 @@ export function _localRead(step, checkpoint, channels, managed, task, select, fr
|
|
|
59
56
|
else {
|
|
60
57
|
values = readChannels(channels, select);
|
|
61
58
|
}
|
|
62
|
-
if (managedKeys.length > 0) {
|
|
63
|
-
for (const k of managedKeys) {
|
|
64
|
-
const managedValue = managed.get(k);
|
|
65
|
-
if (managedValue) {
|
|
66
|
-
const resultOfManagedCall = managedValue.call(step);
|
|
67
|
-
values[k] = resultOfManagedCall;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
59
|
return values;
|
|
72
60
|
}
|
|
73
|
-
export function _localWrite(
|
|
61
|
+
export function _localWrite(
|
|
74
62
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
-
commit, processes,
|
|
63
|
+
commit, processes,
|
|
76
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
65
|
writes) {
|
|
78
66
|
for (const [chan, value] of writes) {
|
|
@@ -83,8 +71,6 @@ writes) {
|
|
|
83
71
|
if (!(value.node in processes)) {
|
|
84
72
|
throw new InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
|
|
85
73
|
}
|
|
86
|
-
// replace any runtime values with placeholders
|
|
87
|
-
managed.replaceRuntimeValues(step, value.args);
|
|
88
74
|
}
|
|
89
75
|
}
|
|
90
76
|
commit(writes);
|
|
@@ -142,47 +128,32 @@ getNextVersion, triggerToNodes) {
|
|
|
142
128
|
for (const chan of channelsToConsume) {
|
|
143
129
|
if (chan in onlyChannels && onlyChannels[chan].consume()) {
|
|
144
130
|
if (getNextVersion !== undefined) {
|
|
145
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
131
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
146
132
|
}
|
|
147
133
|
}
|
|
148
134
|
}
|
|
149
|
-
// Clear pending sends
|
|
150
|
-
if (checkpoint.pending_sends?.length && bumpStep) {
|
|
151
|
-
checkpoint.pending_sends = [];
|
|
152
|
-
}
|
|
153
135
|
// Group writes by channel
|
|
154
|
-
const
|
|
155
|
-
const pendingWritesByManaged = {};
|
|
136
|
+
const pendingWritesByChannel = {};
|
|
156
137
|
for (const task of tasks) {
|
|
157
138
|
for (const [chan, val] of task.writes) {
|
|
158
139
|
if (IGNORE.has(chan)) {
|
|
159
140
|
// do nothing
|
|
160
141
|
}
|
|
161
|
-
else if (chan === TASKS) {
|
|
162
|
-
// TODO: remove branch in 1.0
|
|
163
|
-
checkpoint.pending_sends.push({
|
|
164
|
-
node: val.node,
|
|
165
|
-
args: val.args,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
142
|
else if (chan in onlyChannels) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
pendingWritesByManaged[chan] ??= [];
|
|
174
|
-
pendingWritesByManaged[chan].push(val);
|
|
143
|
+
pendingWritesByChannel[chan] ??= [];
|
|
144
|
+
pendingWritesByChannel[chan].push(val);
|
|
175
145
|
}
|
|
176
146
|
}
|
|
177
147
|
}
|
|
178
|
-
//
|
|
148
|
+
// Find the highest version of all channels
|
|
149
|
+
// TODO: figure out why we need to do this twice (Python only does this once)
|
|
179
150
|
maxVersion = undefined;
|
|
180
151
|
if (Object.keys(checkpoint.channel_versions).length > 0) {
|
|
181
152
|
maxVersion = maxChannelVersion(...Object.values(checkpoint.channel_versions));
|
|
182
153
|
}
|
|
183
154
|
const updatedChannels = new Set();
|
|
184
155
|
// Apply writes to channels
|
|
185
|
-
for (const [chan, vals] of Object.entries(
|
|
156
|
+
for (const [chan, vals] of Object.entries(pendingWritesByChannel)) {
|
|
186
157
|
if (chan in onlyChannels) {
|
|
187
158
|
let updated;
|
|
188
159
|
try {
|
|
@@ -200,7 +171,7 @@ getNextVersion, triggerToNodes) {
|
|
|
200
171
|
}
|
|
201
172
|
}
|
|
202
173
|
if (updated && getNextVersion !== undefined) {
|
|
203
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
174
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
204
175
|
// unavailable channels can't trigger tasks, so don't add them
|
|
205
176
|
if (onlyChannels[chan].isAvailable()) {
|
|
206
177
|
updatedChannels.add(chan);
|
|
@@ -214,7 +185,7 @@ getNextVersion, triggerToNodes) {
|
|
|
214
185
|
if (onlyChannels[chan].isAvailable() && !updatedChannels.has(chan)) {
|
|
215
186
|
const updated = onlyChannels[chan].update([]);
|
|
216
187
|
if (updated && getNextVersion !== undefined) {
|
|
217
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
188
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
218
189
|
// unavailable channels can't trigger tasks, so don't add them
|
|
219
190
|
if (onlyChannels[chan].isAvailable()) {
|
|
220
191
|
updatedChannels.add(chan);
|
|
@@ -225,11 +196,10 @@ getNextVersion, triggerToNodes) {
|
|
|
225
196
|
}
|
|
226
197
|
// If this is (tentatively) the last superstep, notify all channels of finish
|
|
227
198
|
if (bumpStep &&
|
|
228
|
-
checkpoint.pending_sends.length === 0 &&
|
|
229
199
|
!Object.keys(triggerToNodes ?? {}).some((channel) => updatedChannels.has(channel))) {
|
|
230
200
|
for (const chan of Object.keys(onlyChannels)) {
|
|
231
201
|
if (onlyChannels[chan].finish() && getNextVersion !== undefined) {
|
|
232
|
-
checkpoint.channel_versions[chan] = getNextVersion(maxVersion
|
|
202
|
+
checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
|
|
233
203
|
// unavailable channels can't trigger tasks, so don't add them
|
|
234
204
|
if (onlyChannels[chan].isAvailable()) {
|
|
235
205
|
updatedChannels.add(chan);
|
|
@@ -237,27 +207,29 @@ getNextVersion, triggerToNodes) {
|
|
|
237
207
|
}
|
|
238
208
|
}
|
|
239
209
|
}
|
|
240
|
-
// Return managed values writes to be applied externally
|
|
241
|
-
return pendingWritesByManaged;
|
|
242
210
|
}
|
|
243
211
|
/**
|
|
244
212
|
* Prepare the set of tasks that will make up the next Pregel step.
|
|
245
213
|
* This is the union of all PUSH tasks (Sends) and PULL tasks (nodes triggered
|
|
246
214
|
* by edges).
|
|
247
215
|
*/
|
|
248
|
-
export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels,
|
|
216
|
+
export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
|
|
249
217
|
const tasks = {};
|
|
250
|
-
// Consume pending
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
218
|
+
// Consume pending tasks
|
|
219
|
+
const tasksChannel = channels[TASKS];
|
|
220
|
+
if (tasksChannel?.isAvailable()) {
|
|
221
|
+
const len = tasksChannel.get().length;
|
|
222
|
+
for (let i = 0; i < len; i += 1) {
|
|
223
|
+
const task = _prepareSingleTask([PUSH, i], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
|
|
224
|
+
if (task !== undefined) {
|
|
225
|
+
tasks[task.id] = task;
|
|
226
|
+
}
|
|
255
227
|
}
|
|
256
228
|
}
|
|
257
229
|
// Check if any processes should be run in next step
|
|
258
230
|
// If so, prepare the values to be passed to them
|
|
259
231
|
for (const name of Object.keys(processes)) {
|
|
260
|
-
const task = _prepareSingleTask([PULL, name], checkpoint, pendingWrites, processes, channels,
|
|
232
|
+
const task = _prepareSingleTask([PULL, name], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
|
|
261
233
|
if (task !== undefined) {
|
|
262
234
|
tasks[task.id] = task;
|
|
263
235
|
}
|
|
@@ -268,7 +240,7 @@ export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels
|
|
|
268
240
|
* Prepares a single task for the next Pregel step, given a task path, which
|
|
269
241
|
* uniquely identifies a PUSH or PULL task within the graph.
|
|
270
242
|
*/
|
|
271
|
-
export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels,
|
|
243
|
+
export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
|
|
272
244
|
const { step, checkpointer, manager } = extra;
|
|
273
245
|
const configurable = config.configurable ?? {};
|
|
274
246
|
const parentNamespace = configurable.checkpoint_ns ?? "";
|
|
@@ -314,8 +286,8 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
314
286
|
configurable: {
|
|
315
287
|
[CONFIG_KEY_TASK_ID]: id,
|
|
316
288
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
317
|
-
[CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
318
|
-
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
289
|
+
[CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
|
|
290
|
+
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
319
291
|
name: call.name,
|
|
320
292
|
writes: writes,
|
|
321
293
|
triggers,
|
|
@@ -366,13 +338,16 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
366
338
|
const index = typeof taskPath[1] === "number"
|
|
367
339
|
? taskPath[1]
|
|
368
340
|
: parseInt(taskPath[1], 10);
|
|
369
|
-
if (
|
|
341
|
+
if (!channels[TASKS]?.isAvailable()) {
|
|
370
342
|
return undefined;
|
|
371
343
|
}
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
344
|
+
const sends = channels[TASKS].get();
|
|
345
|
+
if (index < 0 || index >= sends.length) {
|
|
346
|
+
return undefined;
|
|
347
|
+
}
|
|
348
|
+
const packet = _isSendInterface(sends[index]) && !_isSend(sends[index])
|
|
349
|
+
? new Send(sends[index].node, sends[index].args)
|
|
350
|
+
: sends[index];
|
|
376
351
|
if (!_isSendInterface(packet)) {
|
|
377
352
|
console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
|
|
378
353
|
return undefined;
|
|
@@ -404,7 +379,6 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
404
379
|
const proc = processes[packet.node];
|
|
405
380
|
const node = proc.getNode();
|
|
406
381
|
if (node !== undefined) {
|
|
407
|
-
managed.replaceRuntimePlaceholders(step, packet.args);
|
|
408
382
|
if (proc.metadata !== undefined) {
|
|
409
383
|
metadata = { ...metadata, ...proc.metadata };
|
|
410
384
|
}
|
|
@@ -425,8 +399,8 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
425
399
|
configurable: {
|
|
426
400
|
[CONFIG_KEY_TASK_ID]: taskId,
|
|
427
401
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
428
|
-
[CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
429
|
-
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
402
|
+
[CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
|
|
403
|
+
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
430
404
|
name: packet.node,
|
|
431
405
|
writes: writes,
|
|
432
406
|
triggers,
|
|
@@ -518,7 +492,7 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
518
492
|
.sort();
|
|
519
493
|
// If any of the channels read by this process were updated
|
|
520
494
|
if (triggers.length > 0) {
|
|
521
|
-
const val = _procInput(
|
|
495
|
+
const val = _procInput(proc, channels, forExecution);
|
|
522
496
|
if (val === undefined) {
|
|
523
497
|
return undefined;
|
|
524
498
|
}
|
|
@@ -563,10 +537,10 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
563
537
|
configurable: {
|
|
564
538
|
[CONFIG_KEY_TASK_ID]: taskId,
|
|
565
539
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
566
|
-
[CONFIG_KEY_SEND]: (writes_) => _localWrite(
|
|
540
|
+
[CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => {
|
|
567
541
|
writes.push(...items);
|
|
568
|
-
}, processes,
|
|
569
|
-
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(
|
|
542
|
+
}, processes, writes_),
|
|
543
|
+
[CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
|
|
570
544
|
name,
|
|
571
545
|
writes: writes,
|
|
572
546
|
triggers,
|
|
@@ -623,7 +597,7 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
|
|
|
623
597
|
*
|
|
624
598
|
* @internal
|
|
625
599
|
*/
|
|
626
|
-
function _procInput(
|
|
600
|
+
function _procInput(proc, channels, forExecution) {
|
|
627
601
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
628
602
|
let val;
|
|
629
603
|
if (typeof proc.channels === "object" && !Array.isArray(proc.channels)) {
|
|
@@ -657,9 +631,6 @@ function _procInput(step, proc, managed, channels, forExecution) {
|
|
|
657
631
|
}
|
|
658
632
|
}
|
|
659
633
|
}
|
|
660
|
-
else {
|
|
661
|
-
val[k] = managed.get(k)?.call(step);
|
|
662
|
-
}
|
|
663
634
|
}
|
|
664
635
|
}
|
|
665
636
|
else if (Array.isArray(proc.channels)) {
|