@langchain/langgraph 0.0.12 → 0.0.14
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/checkpoint/sqlite.cjs +1 -0
- package/checkpoint/sqlite.d.cts +1 -0
- package/checkpoint/sqlite.d.ts +1 -0
- package/checkpoint/sqlite.js +1 -0
- package/dist/channels/any_value.cjs +57 -0
- package/dist/channels/any_value.d.ts +16 -0
- package/dist/channels/any_value.js +53 -0
- package/dist/channels/base.cjs +19 -28
- package/dist/channels/base.d.ts +13 -19
- package/dist/channels/base.js +17 -24
- package/dist/channels/binop.cjs +4 -3
- package/dist/channels/binop.d.ts +1 -1
- package/dist/channels/binop.js +3 -2
- package/dist/channels/dynamic_barrier_value.cjs +88 -0
- package/dist/channels/dynamic_barrier_value.d.ts +26 -0
- package/dist/channels/dynamic_barrier_value.js +84 -0
- package/dist/channels/ephemeral_value.cjs +64 -0
- package/dist/channels/ephemeral_value.d.ts +14 -0
- package/dist/channels/ephemeral_value.js +60 -0
- package/dist/channels/index.cjs +1 -3
- package/dist/channels/index.d.ts +1 -1
- package/dist/channels/index.js +1 -1
- package/dist/channels/last_value.cjs +11 -5
- package/dist/channels/last_value.d.ts +5 -1
- package/dist/channels/last_value.js +9 -3
- package/dist/channels/named_barrier_value.cjs +71 -0
- package/dist/channels/named_barrier_value.d.ts +18 -0
- package/dist/channels/named_barrier_value.js +66 -0
- package/dist/channels/topic.cjs +5 -3
- package/dist/channels/topic.d.ts +3 -3
- package/dist/channels/topic.js +5 -3
- package/dist/checkpoint/base.cjs +30 -12
- package/dist/checkpoint/base.d.ts +39 -22
- package/dist/checkpoint/base.js +28 -11
- package/dist/checkpoint/id.cjs +40 -0
- package/dist/checkpoint/id.d.ts +2 -0
- package/dist/checkpoint/id.js +35 -0
- package/dist/checkpoint/index.cjs +2 -2
- package/dist/checkpoint/index.d.ts +2 -2
- package/dist/checkpoint/index.js +2 -2
- package/dist/checkpoint/memory.cjs +66 -49
- package/dist/checkpoint/memory.d.ts +7 -10
- package/dist/checkpoint/memory.js +65 -47
- package/dist/checkpoint/sqlite.cjs +173 -0
- package/dist/checkpoint/sqlite.d.ts +14 -0
- package/dist/checkpoint/sqlite.js +166 -0
- package/dist/constants.cjs +3 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/errors.cjs +31 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +24 -0
- package/dist/graph/graph.cjs +235 -95
- package/dist/graph/graph.d.ts +52 -23
- package/dist/graph/graph.js +234 -96
- package/dist/graph/index.cjs +2 -2
- package/dist/graph/index.d.ts +2 -2
- package/dist/graph/index.js +2 -2
- package/dist/graph/message.cjs +4 -3
- package/dist/graph/message.d.ts +4 -1
- package/dist/graph/message.js +4 -3
- package/dist/graph/state.cjs +237 -102
- package/dist/graph/state.d.ts +41 -18
- package/dist/graph/state.js +238 -104
- package/dist/index.cjs +12 -7
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/prebuilt/agent_executor.cjs +22 -36
- package/dist/prebuilt/agent_executor.d.ts +7 -10
- package/dist/prebuilt/agent_executor.js +23 -37
- package/dist/prebuilt/chat_agent_executor.cjs +13 -13
- package/dist/prebuilt/chat_agent_executor.d.ts +3 -1
- package/dist/prebuilt/chat_agent_executor.js +15 -15
- package/dist/prebuilt/index.cjs +4 -1
- package/dist/prebuilt/index.d.ts +1 -0
- package/dist/prebuilt/index.js +1 -0
- package/dist/prebuilt/tool_node.cjs +59 -0
- package/dist/prebuilt/tool_node.d.ts +17 -0
- package/dist/prebuilt/tool_node.js +54 -0
- package/dist/pregel/debug.cjs +6 -8
- package/dist/pregel/debug.d.ts +2 -2
- package/dist/pregel/debug.js +5 -7
- package/dist/pregel/index.cjs +504 -232
- package/dist/pregel/index.d.ts +80 -41
- package/dist/pregel/index.js +507 -238
- package/dist/pregel/io.cjs +117 -30
- package/dist/pregel/io.d.ts +11 -3
- package/dist/pregel/io.js +111 -28
- package/dist/pregel/read.cjs +126 -46
- package/dist/pregel/read.d.ts +27 -18
- package/dist/pregel/read.js +125 -45
- package/dist/pregel/types.cjs +2 -0
- package/dist/pregel/types.d.ts +37 -0
- package/dist/pregel/types.js +1 -0
- package/dist/pregel/validate.cjs +58 -51
- package/dist/pregel/validate.d.ts +14 -13
- package/dist/pregel/validate.js +56 -50
- package/dist/pregel/write.cjs +46 -30
- package/dist/pregel/write.d.ts +18 -8
- package/dist/pregel/write.js +45 -29
- package/dist/serde/base.cjs +2 -0
- package/dist/serde/base.d.ts +4 -0
- package/dist/serde/base.js +1 -0
- package/dist/setup/async_local_storage.cjs +2 -2
- package/dist/setup/async_local_storage.js +1 -1
- package/dist/tests/channels.test.d.ts +1 -0
- package/dist/tests/channels.test.js +151 -0
- package/dist/tests/chatbot.int.test.d.ts +1 -0
- package/dist/tests/chatbot.int.test.js +61 -0
- package/dist/tests/checkpoints.test.d.ts +1 -0
- package/dist/tests/checkpoints.test.js +190 -0
- package/dist/tests/graph.test.d.ts +1 -0
- package/dist/tests/graph.test.js +15 -0
- package/dist/tests/prebuilt.int.test.d.ts +1 -0
- package/dist/tests/prebuilt.int.test.js +101 -0
- package/dist/tests/prebuilt.test.d.ts +1 -0
- package/dist/tests/prebuilt.test.js +195 -0
- package/dist/tests/pregel.io.test.d.ts +1 -0
- package/dist/tests/pregel.io.test.js +332 -0
- package/dist/tests/pregel.read.test.d.ts +1 -0
- package/dist/tests/pregel.read.test.js +109 -0
- package/dist/tests/pregel.test.d.ts +1 -0
- package/dist/tests/pregel.test.js +1879 -0
- package/dist/tests/pregel.validate.test.d.ts +1 -0
- package/dist/tests/pregel.validate.test.js +198 -0
- package/dist/tests/pregel.write.test.d.ts +1 -0
- package/dist/tests/pregel.write.test.js +44 -0
- package/dist/tests/tracing.int.test.d.ts +1 -0
- package/dist/tests/tracing.int.test.js +449 -0
- package/dist/tests/utils.d.ts +22 -0
- package/dist/tests/utils.js +76 -0
- package/dist/utils.cjs +74 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +70 -0
- package/package.json +33 -8
- package/dist/pregel/reserved.cjs +0 -6
- package/dist/pregel/reserved.d.ts +0 -3
- package/dist/pregel/reserved.js +0 -3
package/dist/pregel/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports._prepareNextTasks = exports._applyWrites = 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");
|
|
@@ -8,80 +8,67 @@ const base_js_1 = require("../channels/base.cjs");
|
|
|
8
8
|
const base_js_2 = require("../checkpoint/base.cjs");
|
|
9
9
|
const read_js_1 = require("./read.cjs");
|
|
10
10
|
const validate_js_1 = require("./validate.cjs");
|
|
11
|
-
const reserved_js_1 = require("./reserved.cjs");
|
|
12
11
|
const io_js_1 = require("./io.cjs");
|
|
13
12
|
const write_js_1 = require("./write.cjs");
|
|
14
13
|
const constants_js_1 = require("../constants.cjs");
|
|
15
14
|
const async_local_storage_js_1 = require("../setup/async_local_storage.cjs");
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
constructor(message) {
|
|
19
|
-
super(message);
|
|
20
|
-
this.name = "GraphRecursionError";
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.GraphRecursionError = GraphRecursionError;
|
|
24
|
-
function _coerceWriteValue(value) {
|
|
25
|
-
if (!runnables_1.Runnable.isRunnable(value) && typeof value !== "function") {
|
|
26
|
-
return (0, runnables_1._coerceToRunnable)(() => value);
|
|
27
|
-
}
|
|
28
|
-
return (0, runnables_1._coerceToRunnable)(value);
|
|
29
|
-
}
|
|
15
|
+
const errors_js_1 = require("../errors.cjs");
|
|
16
|
+
const DEFAULT_LOOP_LIMIT = 25;
|
|
30
17
|
function isString(value) {
|
|
31
18
|
return typeof value === "string";
|
|
32
19
|
}
|
|
33
20
|
class Channel {
|
|
34
21
|
static subscribeTo(channels, options) {
|
|
35
|
-
const { key,
|
|
22
|
+
const { key, tags } = options ?? {};
|
|
36
23
|
if (Array.isArray(channels) && key !== undefined) {
|
|
37
24
|
throw new Error("Can't specify a key when subscribing to multiple channels");
|
|
38
25
|
}
|
|
39
|
-
let
|
|
26
|
+
let channelMappingOrArray;
|
|
40
27
|
if (isString(channels)) {
|
|
41
28
|
if (key) {
|
|
42
|
-
|
|
29
|
+
channelMappingOrArray = { [key]: channels };
|
|
43
30
|
}
|
|
44
31
|
else {
|
|
45
|
-
|
|
32
|
+
channelMappingOrArray = [channels];
|
|
46
33
|
}
|
|
47
34
|
}
|
|
48
35
|
else {
|
|
49
|
-
|
|
36
|
+
channelMappingOrArray = Object.fromEntries(channels.map((chan) => [chan, chan]));
|
|
50
37
|
}
|
|
51
38
|
const triggers = Array.isArray(channels) ? channels : [channels];
|
|
52
|
-
return new read_js_1.
|
|
53
|
-
channels:
|
|
39
|
+
return new read_js_1.PregelNode({
|
|
40
|
+
channels: channelMappingOrArray,
|
|
54
41
|
triggers,
|
|
55
|
-
when,
|
|
56
42
|
tags,
|
|
57
43
|
});
|
|
58
44
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Handle the case where named arguments are passed as an object
|
|
67
|
-
const additionalArgs = args[0];
|
|
68
|
-
Object.entries(additionalArgs).forEach(([key, value]) => {
|
|
69
|
-
channelPairs.push([key, _coerceWriteValue(value)]);
|
|
45
|
+
static writeTo(channels, kwargs) {
|
|
46
|
+
const channelWriteEntries = [];
|
|
47
|
+
for (const channel of channels) {
|
|
48
|
+
channelWriteEntries.push({
|
|
49
|
+
channel,
|
|
50
|
+
value: write_js_1.PASSTHROUGH,
|
|
51
|
+
skipNone: false,
|
|
70
52
|
});
|
|
71
53
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
54
|
+
for (const [key, value] of Object.entries(kwargs ?? {})) {
|
|
55
|
+
if (runnables_1.Runnable.isRunnable(value) || typeof value === "function") {
|
|
56
|
+
channelWriteEntries.push({
|
|
57
|
+
channel: key,
|
|
58
|
+
value: write_js_1.PASSTHROUGH,
|
|
59
|
+
skipNone: true,
|
|
60
|
+
mapper: (0, runnables_1._coerceToRunnable)(value),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
channelWriteEntries.push({
|
|
65
|
+
channel: key,
|
|
66
|
+
value,
|
|
67
|
+
skipNone: false,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
83
70
|
}
|
|
84
|
-
return new write_js_1.ChannelWrite(
|
|
71
|
+
return new write_js_1.ChannelWrite(channelWriteEntries);
|
|
85
72
|
}
|
|
86
73
|
}
|
|
87
74
|
exports.Channel = Channel;
|
|
@@ -98,43 +85,55 @@ class Pregel extends runnables_1.Runnable {
|
|
|
98
85
|
writable: true,
|
|
99
86
|
value: ["langgraph", "pregel"]
|
|
100
87
|
});
|
|
88
|
+
Object.defineProperty(this, "nodes", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
configurable: true,
|
|
91
|
+
writable: true,
|
|
92
|
+
value: void 0
|
|
93
|
+
});
|
|
101
94
|
Object.defineProperty(this, "channels", {
|
|
102
95
|
enumerable: true,
|
|
103
96
|
configurable: true,
|
|
104
97
|
writable: true,
|
|
105
|
-
value:
|
|
98
|
+
value: void 0
|
|
106
99
|
});
|
|
107
|
-
Object.defineProperty(this, "
|
|
100
|
+
Object.defineProperty(this, "inputs", {
|
|
108
101
|
enumerable: true,
|
|
109
102
|
configurable: true,
|
|
110
103
|
writable: true,
|
|
111
|
-
value:
|
|
104
|
+
value: void 0
|
|
112
105
|
});
|
|
113
|
-
Object.defineProperty(this, "
|
|
106
|
+
Object.defineProperty(this, "outputs", {
|
|
114
107
|
enumerable: true,
|
|
115
108
|
configurable: true,
|
|
116
109
|
writable: true,
|
|
117
|
-
value:
|
|
110
|
+
value: void 0
|
|
118
111
|
});
|
|
119
|
-
Object.defineProperty(this, "
|
|
112
|
+
Object.defineProperty(this, "autoValidate", {
|
|
120
113
|
enumerable: true,
|
|
121
114
|
configurable: true,
|
|
122
115
|
writable: true,
|
|
123
|
-
value:
|
|
116
|
+
value: true
|
|
124
117
|
});
|
|
125
|
-
Object.defineProperty(this, "
|
|
118
|
+
Object.defineProperty(this, "streamMode", {
|
|
126
119
|
enumerable: true,
|
|
127
120
|
configurable: true,
|
|
128
121
|
writable: true,
|
|
129
|
-
value:
|
|
122
|
+
value: "values"
|
|
130
123
|
});
|
|
131
|
-
Object.defineProperty(this, "
|
|
124
|
+
Object.defineProperty(this, "streamChannels", {
|
|
132
125
|
enumerable: true,
|
|
133
126
|
configurable: true,
|
|
134
127
|
writable: true,
|
|
135
128
|
value: void 0
|
|
136
129
|
});
|
|
137
|
-
Object.defineProperty(this, "
|
|
130
|
+
Object.defineProperty(this, "interruptAfter", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true,
|
|
134
|
+
value: void 0
|
|
135
|
+
});
|
|
136
|
+
Object.defineProperty(this, "interruptBefore", {
|
|
138
137
|
enumerable: true,
|
|
139
138
|
configurable: true,
|
|
140
139
|
writable: true,
|
|
@@ -146,135 +145,365 @@ class Pregel extends runnables_1.Runnable {
|
|
|
146
145
|
writable: true,
|
|
147
146
|
value: void 0
|
|
148
147
|
});
|
|
149
|
-
Object.defineProperty(this, "
|
|
148
|
+
Object.defineProperty(this, "debug", {
|
|
150
149
|
enumerable: true,
|
|
151
150
|
configurable: true,
|
|
152
151
|
writable: true,
|
|
153
|
-
value:
|
|
152
|
+
value: false
|
|
153
|
+
});
|
|
154
|
+
Object.defineProperty(this, "checkpointer", {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
configurable: true,
|
|
157
|
+
writable: true,
|
|
158
|
+
value: void 0
|
|
154
159
|
});
|
|
155
160
|
// Initialize global async local storage instance for tracing
|
|
156
161
|
(0, async_local_storage_js_1.initializeAsyncLocalStorageSingleton)();
|
|
157
|
-
this.channels = fields.channels ?? this.channels;
|
|
158
|
-
this.output = fields.output ?? this.output;
|
|
159
|
-
this.input = fields.input ?? this.input;
|
|
160
|
-
this.hidden = fields.hidden ?? this.hidden;
|
|
161
|
-
this.debug = fields.debug ?? this.debug;
|
|
162
162
|
this.nodes = fields.nodes;
|
|
163
|
+
this.channels = fields.channels;
|
|
164
|
+
this.autoValidate = fields.autoValidate ?? this.autoValidate;
|
|
165
|
+
this.streamMode = fields.streamMode ?? this.streamMode;
|
|
166
|
+
this.outputs = fields.outputs;
|
|
167
|
+
this.streamChannels = fields.streamChannels ?? this.streamChannels;
|
|
168
|
+
this.interruptAfter = fields.interruptAfter;
|
|
169
|
+
this.interruptBefore = fields.interruptBefore;
|
|
170
|
+
this.inputs = fields.inputs;
|
|
171
|
+
this.stepTimeout = fields.stepTimeout ?? this.stepTimeout;
|
|
172
|
+
this.debug = fields.debug ?? this.debug;
|
|
163
173
|
this.checkpointer = fields.checkpointer;
|
|
164
|
-
this.stepTimeout = fields.stepTimeout;
|
|
165
|
-
this.interrupt = fields.interrupt ?? this.interrupt;
|
|
166
174
|
// Bind the method to the instance
|
|
167
175
|
this._transform = this._transform.bind(this);
|
|
176
|
+
if (this.autoValidate) {
|
|
177
|
+
this.validate();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
validate() {
|
|
168
181
|
(0, validate_js_1.validateGraph)({
|
|
169
182
|
nodes: this.nodes,
|
|
170
183
|
channels: this.channels,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
184
|
+
outputChannels: this.outputs,
|
|
185
|
+
inputChannels: this.inputs,
|
|
186
|
+
streamChannels: this.streamChannels,
|
|
187
|
+
interruptAfterNodes: this.interruptAfter,
|
|
188
|
+
interruptBeforeNodes: this.interruptBefore,
|
|
175
189
|
});
|
|
190
|
+
return this;
|
|
176
191
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
get streamChannelsList() {
|
|
193
|
+
if (Array.isArray(this.streamChannels)) {
|
|
194
|
+
return this.streamChannels;
|
|
195
|
+
}
|
|
196
|
+
else if (this.streamChannels) {
|
|
197
|
+
return [this.streamChannels];
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
return Object.keys(this.channels);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
get streamChannelsAsIs() {
|
|
204
|
+
if (this.streamChannels) {
|
|
205
|
+
return this.streamChannels;
|
|
183
206
|
}
|
|
184
207
|
else {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
208
|
+
return Object.keys(this.channels);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async getState(config) {
|
|
212
|
+
if (!this.checkpointer) {
|
|
213
|
+
throw new errors_js_1.GraphValueError("No checkpointer set");
|
|
214
|
+
}
|
|
215
|
+
const saved = await this.checkpointer.getTuple(config);
|
|
216
|
+
const checkpoint = saved ? saved.checkpoint : (0, base_js_2.emptyCheckpoint)();
|
|
217
|
+
const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
|
|
218
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
219
|
+
const [_, nextTasks] = _prepareNextTasks(checkpoint, this.nodes, channels, false);
|
|
220
|
+
return {
|
|
221
|
+
values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
|
|
222
|
+
next: nextTasks.map((task) => task.name),
|
|
223
|
+
metadata: saved?.metadata,
|
|
224
|
+
config: saved ? saved.config : config,
|
|
225
|
+
parentConfig: saved?.parentConfig,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async *getStateHistory(config, limit, before) {
|
|
229
|
+
if (!this.checkpointer) {
|
|
230
|
+
throw new errors_js_1.GraphValueError("No checkpointer set");
|
|
231
|
+
}
|
|
232
|
+
for await (const saved of this.checkpointer.list(config, limit, before)) {
|
|
233
|
+
const channels = (0, base_js_1.emptyChannels)(this.channels, saved.checkpoint);
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
235
|
+
const [_, nextTasks] = _prepareNextTasks(saved.checkpoint, this.nodes, channels, false);
|
|
236
|
+
yield {
|
|
237
|
+
values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
|
|
238
|
+
next: nextTasks.map((task) => task.name),
|
|
239
|
+
metadata: saved.metadata,
|
|
240
|
+
config: saved.config,
|
|
241
|
+
parentConfig: saved.parentConfig,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async updateState(config, values, asNode) {
|
|
246
|
+
if (!this.checkpointer) {
|
|
247
|
+
throw new errors_js_1.GraphValueError("No checkpointer set");
|
|
248
|
+
}
|
|
249
|
+
// Get the latest checkpoint
|
|
250
|
+
const saved = await this.checkpointer.getTuple(config);
|
|
251
|
+
const checkpoint = saved
|
|
252
|
+
? (0, base_js_2.copyCheckpoint)(saved.checkpoint)
|
|
253
|
+
: (0, base_js_2.emptyCheckpoint)();
|
|
254
|
+
// Find last that updated the state, if not provided
|
|
255
|
+
const maxSeens = Object.entries(checkpoint.versions_seen).reduce((acc, [node, versions]) => {
|
|
256
|
+
const maxSeen = Math.max(...Object.values(versions));
|
|
257
|
+
if (maxSeen) {
|
|
258
|
+
if (!acc[maxSeen]) {
|
|
259
|
+
acc[maxSeen] = [];
|
|
188
260
|
}
|
|
261
|
+
acc[maxSeen].push(node);
|
|
262
|
+
}
|
|
263
|
+
return acc;
|
|
264
|
+
}, {});
|
|
265
|
+
if (!asNode && !Object.keys(maxSeens).length) {
|
|
266
|
+
if (!Array.isArray(this.inputs) && this.inputs in this.nodes) {
|
|
267
|
+
asNode = this.inputs;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else if (!asNode) {
|
|
271
|
+
const maxSeen = Math.max(...Object.keys(maxSeens).map(Number));
|
|
272
|
+
const nodes = maxSeens[maxSeen];
|
|
273
|
+
if (nodes.length === 1) {
|
|
274
|
+
asNode = nodes[0];
|
|
189
275
|
}
|
|
190
276
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// get checkpoint, or create an empty one
|
|
194
|
-
let checkpoint;
|
|
195
|
-
if (this.checkpointer) {
|
|
196
|
-
checkpoint = this.checkpointer.get(config);
|
|
277
|
+
if (!asNode) {
|
|
278
|
+
throw new errors_js_1.InvalidUpdateError("Ambiguous update, specify as_node");
|
|
197
279
|
}
|
|
198
|
-
|
|
199
|
-
// create channels from checkpoint
|
|
280
|
+
// update channels
|
|
200
281
|
const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
|
|
201
|
-
//
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
282
|
+
// create task to run all writers of the chosen node
|
|
283
|
+
const writers = this.nodes[asNode].getWriters();
|
|
284
|
+
if (!writers.length) {
|
|
285
|
+
throw new errors_js_1.InvalidUpdateError(`No writers found for node ${asNode}`);
|
|
286
|
+
}
|
|
287
|
+
const task = {
|
|
288
|
+
name: asNode,
|
|
289
|
+
input: values,
|
|
290
|
+
proc:
|
|
291
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
|
+
writers.length > 1 ? runnables_1.RunnableSequence.from(writers) : writers[0],
|
|
293
|
+
writes: [],
|
|
294
|
+
config: undefined,
|
|
295
|
+
};
|
|
296
|
+
// execute task
|
|
297
|
+
await task.proc.invoke(task.input, (0, runnables_1.patchConfig)(config, {
|
|
298
|
+
runName: `${this.name}UpdateState`,
|
|
299
|
+
configurable: {
|
|
300
|
+
[constants_js_1.CONFIG_KEY_SEND]: (items) => task.writes.push(...items),
|
|
301
|
+
[constants_js_1.CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, task.writes),
|
|
302
|
+
},
|
|
303
|
+
}));
|
|
304
|
+
// apply to checkpoint and save
|
|
305
|
+
_applyWrites(checkpoint, channels, task.writes);
|
|
306
|
+
const step = (saved?.metadata?.step ?? -2) + 1;
|
|
307
|
+
return await this.checkpointer.put(saved?.config ?? config, (0, base_js_1.createCheckpoint)(checkpoint, channels, step), {
|
|
308
|
+
source: "update",
|
|
309
|
+
step,
|
|
310
|
+
writes: { [asNode]: values },
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
_defaults(config) {
|
|
314
|
+
const { debug, streamMode, inputKeys, outputKeys, interruptAfter, interruptBefore, ...rest } = config;
|
|
315
|
+
const defaultDebug = debug !== undefined ? debug : this.debug;
|
|
316
|
+
let defaultOutputKeys = outputKeys;
|
|
317
|
+
if (defaultOutputKeys === undefined) {
|
|
318
|
+
defaultOutputKeys = this.streamChannelsAsIs;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
(0, validate_js_1.validateKeys)(defaultOutputKeys, this.channels);
|
|
322
|
+
}
|
|
323
|
+
let defaultInputKeys = inputKeys;
|
|
324
|
+
if (defaultInputKeys === undefined) {
|
|
325
|
+
defaultInputKeys = this.inputs;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
(0, validate_js_1.validateKeys)(defaultInputKeys, this.channels);
|
|
329
|
+
}
|
|
330
|
+
const defaultInterruptBefore = interruptBefore ?? this.interruptBefore ?? [];
|
|
331
|
+
const defaultInterruptAfter = interruptAfter ?? this.interruptAfter ?? [];
|
|
332
|
+
let defaultStreamMode;
|
|
333
|
+
if (streamMode !== undefined) {
|
|
334
|
+
defaultStreamMode = streamMode;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
defaultStreamMode = this.streamMode;
|
|
338
|
+
}
|
|
339
|
+
if (config.configurable !== undefined &&
|
|
340
|
+
config.configurable[constants_js_1.CONFIG_KEY_READ] !== undefined) {
|
|
341
|
+
defaultStreamMode = "values";
|
|
209
342
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
343
|
+
return [
|
|
344
|
+
defaultDebug,
|
|
345
|
+
defaultStreamMode,
|
|
346
|
+
defaultInputKeys,
|
|
347
|
+
defaultOutputKeys,
|
|
348
|
+
rest,
|
|
349
|
+
defaultInterruptBefore,
|
|
350
|
+
defaultInterruptAfter,
|
|
351
|
+
];
|
|
352
|
+
}
|
|
353
|
+
async *_transform(input, runManager, config = {}) {
|
|
354
|
+
const bg = [];
|
|
355
|
+
try {
|
|
356
|
+
if (config.recursionLimit && config.recursionLimit < 1) {
|
|
357
|
+
throw new errors_js_1.GraphValueError(`Recursion limit must be greater than 0, got ${config.recursionLimit}`);
|
|
223
358
|
}
|
|
224
|
-
|
|
225
|
-
throw new
|
|
359
|
+
if (this.checkpointer && !config.configurable) {
|
|
360
|
+
throw new errors_js_1.GraphValueError(`Checkpointer requires one or more of the following 'configurable' keys: thread_id, checkpoint_id`);
|
|
226
361
|
}
|
|
227
|
-
//
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const tasks = tasksWithConfig.map(([proc, input, updatedConfig]) => () => proc.invoke(input, updatedConfig));
|
|
246
|
-
await executeTasks(tasks, this.stepTimeout);
|
|
247
|
-
// apply writes to channels
|
|
248
|
-
_applyWrites(checkpoint, channels, pendingWrites, config, step + 1);
|
|
249
|
-
// yield current value and checkpoint view
|
|
250
|
-
const stepOutput = (0, io_js_1.mapOutput)(outputKeys, pendingWrites, channels);
|
|
251
|
-
if (stepOutput) {
|
|
252
|
-
yield stepOutput;
|
|
253
|
-
if (typeof outputKeys !== "string") {
|
|
254
|
-
_applyWritesFromView(checkpoint, channels, stepOutput);
|
|
362
|
+
// assign defaults
|
|
363
|
+
const [debug, streamMode, inputKeys, outputKeys, restConfig, interruptBefore, interruptAfter,] = this._defaults(config);
|
|
364
|
+
// copy nodes to ignore mutations during execution
|
|
365
|
+
const processes = { ...this.nodes };
|
|
366
|
+
// get checkpoint, or create an empty one
|
|
367
|
+
const saved = this.checkpointer
|
|
368
|
+
? await this.checkpointer.getTuple(config)
|
|
369
|
+
: null;
|
|
370
|
+
let checkpoint = saved ? saved.checkpoint : (0, base_js_2.emptyCheckpoint)();
|
|
371
|
+
let checkpointConfig = saved ? saved.config : config;
|
|
372
|
+
let start = (saved?.metadata?.step ?? -2) + 1;
|
|
373
|
+
// create channels from checkpoint
|
|
374
|
+
const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
|
|
375
|
+
// map inputs to channel updates
|
|
376
|
+
const inputPendingWrites = [];
|
|
377
|
+
for await (const c of input) {
|
|
378
|
+
for (const value of (0, io_js_1.mapInput)(inputKeys, c)) {
|
|
379
|
+
inputPendingWrites.push(value);
|
|
255
380
|
}
|
|
256
381
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
checkpoint =
|
|
261
|
-
|
|
382
|
+
if (inputPendingWrites.length) {
|
|
383
|
+
// discard any unfinished tasks from previous checkpoint
|
|
384
|
+
const discarded = _prepareNextTasks(checkpoint, processes, channels, true);
|
|
385
|
+
checkpoint = discarded[0]; // eslint-disable-line prefer-destructuring
|
|
386
|
+
// apply input writes
|
|
387
|
+
_applyWrites(checkpoint, channels, inputPendingWrites);
|
|
388
|
+
// save input checkpoint
|
|
389
|
+
if (this.checkpointer) {
|
|
390
|
+
checkpoint = (0, base_js_1.createCheckpoint)(checkpoint, channels, start);
|
|
391
|
+
bg.push(this.checkpointer.put(checkpointConfig, checkpoint, {
|
|
392
|
+
source: "input",
|
|
393
|
+
step: start,
|
|
394
|
+
writes: Object.fromEntries(inputPendingWrites),
|
|
395
|
+
}));
|
|
396
|
+
checkpointConfig = {
|
|
397
|
+
configurable: {
|
|
398
|
+
...checkpointConfig.configurable,
|
|
399
|
+
checkpoint_id: checkpoint.id,
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
// increment start to 0
|
|
404
|
+
start += 1;
|
|
262
405
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
406
|
+
else {
|
|
407
|
+
checkpoint = (0, base_js_2.copyCheckpoint)(checkpoint);
|
|
408
|
+
for (const k of this.streamChannelsList) {
|
|
409
|
+
const version = checkpoint.channel_versions[k];
|
|
410
|
+
checkpoint.versions_seen[constants_js_1.INTERRUPT][k] = version;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Similarly to Bulk Synchronous Parallel / Pregel model
|
|
414
|
+
// computation proceeds in steps, while there are channel updates
|
|
415
|
+
// channel updates from step N are only visible in step N+1
|
|
416
|
+
// channels are guaranteed to be immutable for the duration of the step,
|
|
417
|
+
// with channel updates applied only at the transition between steps
|
|
418
|
+
const stop = start + (config.recursionLimit ?? DEFAULT_LOOP_LIMIT);
|
|
419
|
+
for (let step = start; step < stop + 1; step += 1) {
|
|
420
|
+
const [nextCheckpoint, nextTasks] = _prepareNextTasks(checkpoint, processes, channels, true);
|
|
421
|
+
// if no more tasks, we're done
|
|
422
|
+
if (nextTasks.length === 0 && step === start) {
|
|
423
|
+
throw new errors_js_1.GraphValueError(`No tasks to run in graph.`);
|
|
424
|
+
}
|
|
425
|
+
else if (nextTasks.length === 0) {
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
else if (step === stop) {
|
|
429
|
+
throw new errors_js_1.GraphRecursionError(`Recursion limit of ${config.recursionLimit} reached without hitting a stop condition. You can increase the limit by setting the "recursionLimit" config key.`);
|
|
430
|
+
}
|
|
431
|
+
// before execution, check if we should interrupt
|
|
432
|
+
if (_shouldInterrupt(checkpoint, interruptBefore, this.streamChannelsList, nextTasks)) {
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
checkpoint = nextCheckpoint;
|
|
437
|
+
}
|
|
438
|
+
if (debug) {
|
|
439
|
+
console.log(nextTasks);
|
|
440
|
+
}
|
|
441
|
+
const tasksWithConfig = nextTasks.map(
|
|
442
|
+
// eslint-disable-next-line no-loop-func
|
|
443
|
+
(task) => [
|
|
444
|
+
task.proc,
|
|
445
|
+
task.input,
|
|
446
|
+
(0, runnables_1.patchConfig)(restConfig, {
|
|
447
|
+
callbacks: runManager?.getChild(`graph:step:${step}`),
|
|
448
|
+
runName: task.name,
|
|
449
|
+
configurable: {
|
|
450
|
+
...config.configurable,
|
|
451
|
+
[constants_js_1.CONFIG_KEY_SEND]: (items) => task.writes.push(...items),
|
|
452
|
+
[constants_js_1.CONFIG_KEY_READ]: _localRead.bind(undefined, checkpoint, channels, task.writes),
|
|
453
|
+
},
|
|
454
|
+
}),
|
|
455
|
+
]);
|
|
456
|
+
// execute tasks, and wait for one to fail or all to finish.
|
|
457
|
+
// each task is independent from all other concurrent tasks
|
|
458
|
+
const tasks = tasksWithConfig.map(([proc, input, updatedConfig]) => () => proc.invoke(input, updatedConfig));
|
|
459
|
+
await executeTasks(tasks, this.stepTimeout);
|
|
460
|
+
// combine pending writes from all tasks
|
|
461
|
+
const pendingWrites = [];
|
|
462
|
+
for (const task of nextTasks) {
|
|
463
|
+
pendingWrites.push(...task.writes);
|
|
464
|
+
}
|
|
465
|
+
// apply writes to channels
|
|
466
|
+
_applyWrites(checkpoint, channels, pendingWrites);
|
|
467
|
+
// yield current value and checkpoint view
|
|
468
|
+
if (streamMode === "values") {
|
|
469
|
+
yield* (0, io_js_1.mapOutputValues)(outputKeys, pendingWrites, channels);
|
|
470
|
+
}
|
|
471
|
+
else if (streamMode === "updates") {
|
|
472
|
+
yield* (0, io_js_1.mapOutputUpdates)(outputKeys, nextTasks);
|
|
473
|
+
}
|
|
474
|
+
// save end of step checkpoint
|
|
475
|
+
if (this.checkpointer) {
|
|
476
|
+
checkpoint = (0, base_js_1.createCheckpoint)(checkpoint, channels, step);
|
|
477
|
+
bg.push(this.checkpointer.put(checkpointConfig, checkpoint, {
|
|
478
|
+
source: "loop",
|
|
479
|
+
step,
|
|
480
|
+
writes: (0, io_js_1.single)(streamMode === "values"
|
|
481
|
+
? (0, io_js_1.mapOutputValues)(outputKeys, pendingWrites, channels)
|
|
482
|
+
: (0, io_js_1.mapOutputUpdates)(outputKeys, nextTasks)),
|
|
483
|
+
}));
|
|
484
|
+
checkpointConfig = {
|
|
485
|
+
configurable: {
|
|
486
|
+
...checkpointConfig.configurable,
|
|
487
|
+
checkpoint_id: checkpoint.id,
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
if (_shouldInterrupt(checkpoint, interruptAfter, this.streamChannelsList, nextTasks)) {
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
266
494
|
}
|
|
267
495
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
checkpoint = await (0, base_js_1.createCheckpoint)(checkpoint, channels);
|
|
271
|
-
this.checkpointer.put(config, checkpoint);
|
|
496
|
+
finally {
|
|
497
|
+
await Promise.all(bg);
|
|
272
498
|
}
|
|
273
499
|
}
|
|
274
500
|
async invoke(input, options) {
|
|
275
501
|
const config = (0, runnables_1.ensureConfig)(options);
|
|
276
502
|
if (!config?.outputKeys) {
|
|
277
|
-
config.outputKeys = this.
|
|
503
|
+
config.outputKeys = this.outputs;
|
|
504
|
+
}
|
|
505
|
+
if (!config?.streamMode) {
|
|
506
|
+
config.streamMode = "values";
|
|
278
507
|
}
|
|
279
508
|
let latest;
|
|
280
509
|
for await (const chunk of await this.stream(input, config)) {
|
|
@@ -321,30 +550,33 @@ async function executeTasks(tasks, stepTimeout) {
|
|
|
321
550
|
}
|
|
322
551
|
}
|
|
323
552
|
}
|
|
324
|
-
function
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
553
|
+
function _shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, tasks) {
|
|
554
|
+
const seen = checkpoint.versions_seen[constants_js_1.INTERRUPT];
|
|
555
|
+
const anySnapshotChannelUpdated = snapshotChannels.some((chan) => checkpoint.channel_versions[chan] > seen?.[chan]);
|
|
556
|
+
const anyTaskNodeInInterruptNodes = tasks.some((task) => interruptNodes === "*"
|
|
557
|
+
? !task.config?.tags?.includes(constants_js_1.TAG_HIDDEN)
|
|
558
|
+
: interruptNodes.includes(task.name));
|
|
559
|
+
return anySnapshotChannelUpdated && anyTaskNodeInInterruptNodes;
|
|
560
|
+
}
|
|
561
|
+
exports._shouldInterrupt = _shouldInterrupt;
|
|
562
|
+
function _localRead(checkpoint, channels, writes, select, fresh = false) {
|
|
563
|
+
if (fresh) {
|
|
564
|
+
const newCheckpoint = (0, base_js_1.createCheckpoint)(checkpoint, channels, -1);
|
|
565
|
+
// create a new copy of channels
|
|
566
|
+
const newChannels = (0, base_js_1.emptyChannels)(channels, newCheckpoint);
|
|
567
|
+
// Note: _applyWrites contains side effects
|
|
568
|
+
_applyWrites((0, base_js_2.copyCheckpoint)(newCheckpoint), newChannels, writes);
|
|
569
|
+
return (0, io_js_1.readChannels)(newChannels, select);
|
|
328
570
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
throw e;
|
|
571
|
+
else {
|
|
572
|
+
return (0, io_js_1.readChannels)(channels, select);
|
|
334
573
|
}
|
|
335
574
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
pendingWrites, config, forStep) {
|
|
339
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
575
|
+
exports._localRead = _localRead;
|
|
576
|
+
function _applyWrites(checkpoint, channels, pendingWrites) {
|
|
340
577
|
const pendingWritesByChannel = {};
|
|
341
578
|
// Group writes by channel
|
|
342
579
|
for (const [chan, val] of pendingWrites) {
|
|
343
|
-
for (const c in reserved_js_1.ReservedChannelsMap) {
|
|
344
|
-
if (chan === c) {
|
|
345
|
-
throw new Error(`Can't write to reserved channel ${chan}`);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
580
|
if (chan in pendingWritesByChannel) {
|
|
349
581
|
pendingWritesByChannel[chan].push(val);
|
|
350
582
|
}
|
|
@@ -352,104 +584,144 @@ pendingWrites, config, forStep) {
|
|
|
352
584
|
pendingWritesByChannel[chan] = [val];
|
|
353
585
|
}
|
|
354
586
|
}
|
|
355
|
-
//
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
587
|
+
// find the highest version of all channels
|
|
588
|
+
let maxVersion = 0;
|
|
589
|
+
if (Object.keys(checkpoint.channel_versions).length > 0) {
|
|
590
|
+
maxVersion = Math.max(...Object.values(checkpoint.channel_versions));
|
|
591
|
+
}
|
|
359
592
|
const updatedChannels = new Set();
|
|
360
593
|
// Apply writes to channels
|
|
361
|
-
for (const chan
|
|
362
|
-
if (chan in
|
|
363
|
-
|
|
364
|
-
|
|
594
|
+
for (const [chan, vals] of Object.entries(pendingWritesByChannel)) {
|
|
595
|
+
if (chan in channels) {
|
|
596
|
+
// side effect: update channels
|
|
597
|
+
try {
|
|
365
598
|
channels[chan].update(vals);
|
|
366
|
-
|
|
367
|
-
checkpoint.channelVersions[chan] = 1;
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
checkpoint.channelVersions[chan] += 1;
|
|
371
|
-
}
|
|
372
|
-
updatedChannels.add(chan);
|
|
599
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
373
600
|
}
|
|
374
|
-
|
|
375
|
-
|
|
601
|
+
catch (e) {
|
|
602
|
+
if (e.name === errors_js_1.InvalidUpdateError.name) {
|
|
603
|
+
throw new errors_js_1.InvalidUpdateError(`Invalid update for channel ${chan}. Values: ${vals}`);
|
|
604
|
+
}
|
|
376
605
|
}
|
|
606
|
+
// side effect: update checkpoint channel versions
|
|
607
|
+
checkpoint.channel_versions[chan] = maxVersion + 1;
|
|
608
|
+
updatedChannels.add(chan);
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
console.warn(`Skipping write for channel ${chan} which has no readers`);
|
|
377
612
|
}
|
|
378
613
|
}
|
|
379
614
|
// Channels that weren't updated in this step are notified of a new step
|
|
380
615
|
for (const chan in channels) {
|
|
381
616
|
if (!updatedChannels.has(chan)) {
|
|
617
|
+
// side effect: update channels
|
|
382
618
|
channels[chan].update([]);
|
|
383
619
|
}
|
|
384
620
|
}
|
|
385
621
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
continue;
|
|
390
|
-
}
|
|
391
|
-
if (channels[chan].lc_graph_name === "LastValue") {
|
|
392
|
-
throw new Error(`Can't modify channel ${chan} with LastValue`);
|
|
393
|
-
}
|
|
394
|
-
checkpoint.channelVersions[chan] += 1;
|
|
395
|
-
channels[chan].update([values[chan]]);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
function _prepareNextTasks(checkpoint, processes, channels) {
|
|
622
|
+
exports._applyWrites = _applyWrites;
|
|
623
|
+
function _prepareNextTasks(checkpoint, processes, channels, forExecution) {
|
|
624
|
+
const newCheckpoint = (0, base_js_2.copyCheckpoint)(checkpoint);
|
|
399
625
|
const tasks = [];
|
|
626
|
+
const taskDescriptions = [];
|
|
400
627
|
// Check if any processes should be run in next step
|
|
401
628
|
// If so, prepare the values to be passed to them
|
|
402
629
|
for (const [name, proc] of Object.entries(processes)) {
|
|
403
|
-
let seen =
|
|
630
|
+
let seen = newCheckpoint.versions_seen[name];
|
|
404
631
|
if (!seen) {
|
|
405
|
-
|
|
406
|
-
seen =
|
|
632
|
+
newCheckpoint.versions_seen[name] = {};
|
|
633
|
+
seen = newCheckpoint.versions_seen[name];
|
|
407
634
|
}
|
|
408
635
|
// If any of the channels read by this process were updated
|
|
409
|
-
if (proc.triggers
|
|
410
|
-
|
|
636
|
+
if (proc.triggers
|
|
637
|
+
.filter((chan) => {
|
|
411
638
|
try {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
639
|
+
(0, io_js_1.readChannel)(channels, chan, false);
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
catch (e) {
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
})
|
|
646
|
+
.some((chan) => newCheckpoint.channel_versions[chan] > (seen[chan] ?? 0))) {
|
|
647
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
648
|
+
let val;
|
|
649
|
+
// If all trigger channels subscribed by this process are not empty
|
|
650
|
+
// then invoke the process with the values of all non-empty channels
|
|
651
|
+
if (Array.isArray(proc.channels)) {
|
|
652
|
+
let emptyChannels = 0;
|
|
653
|
+
for (const chan of proc.channels) {
|
|
654
|
+
try {
|
|
655
|
+
val = (0, io_js_1.readChannel)(channels, chan, false);
|
|
656
|
+
break;
|
|
657
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
658
|
+
}
|
|
659
|
+
catch (e) {
|
|
660
|
+
if (e.name === errors_js_1.EmptyChannelError.name) {
|
|
661
|
+
emptyChannels += 1;
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
throw e;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
416
668
|
}
|
|
417
|
-
|
|
669
|
+
if (emptyChannels === proc.channels.length) {
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
else if (typeof proc.channels === "object") {
|
|
674
|
+
val = {};
|
|
675
|
+
try {
|
|
418
676
|
for (const [k, chan] of Object.entries(proc.channels)) {
|
|
419
|
-
val[k] =
|
|
677
|
+
val[k] = (0, io_js_1.readChannel)(channels, chan, !proc.triggers.includes(chan));
|
|
420
678
|
}
|
|
679
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
421
680
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
val = val[Object.keys(proc.channels)[0]];
|
|
681
|
+
catch (e) {
|
|
682
|
+
if (e.name === errors_js_1.EmptyChannelError.name) {
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
throw e;
|
|
687
|
+
}
|
|
430
688
|
}
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
throw new Error(`Invalid channels type, expected list or dict, got ${proc.channels}`);
|
|
692
|
+
}
|
|
693
|
+
// If the process has a mapper, apply it to the value
|
|
694
|
+
if (proc.mapper !== undefined) {
|
|
695
|
+
val = proc.mapper(val);
|
|
696
|
+
}
|
|
697
|
+
if (forExecution) {
|
|
431
698
|
// Update seen versions
|
|
432
699
|
proc.triggers.forEach((chan) => {
|
|
433
|
-
const version =
|
|
700
|
+
const version = newCheckpoint.channel_versions[chan];
|
|
434
701
|
if (version !== undefined) {
|
|
702
|
+
// side effect: updates newCheckpoint
|
|
435
703
|
seen[chan] = version;
|
|
436
704
|
}
|
|
437
705
|
});
|
|
438
|
-
|
|
439
|
-
if (
|
|
440
|
-
tasks.push(
|
|
706
|
+
const node = proc.getNode();
|
|
707
|
+
if (node !== undefined) {
|
|
708
|
+
tasks.push({
|
|
709
|
+
name,
|
|
710
|
+
input: val,
|
|
711
|
+
proc: node,
|
|
712
|
+
writes: [],
|
|
713
|
+
config: proc.config,
|
|
714
|
+
});
|
|
441
715
|
}
|
|
442
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
443
716
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
throw error;
|
|
450
|
-
}
|
|
717
|
+
else {
|
|
718
|
+
taskDescriptions.push({
|
|
719
|
+
name,
|
|
720
|
+
input: val,
|
|
721
|
+
});
|
|
451
722
|
}
|
|
452
723
|
}
|
|
453
724
|
}
|
|
454
|
-
return tasks;
|
|
725
|
+
return [newCheckpoint, forExecution ? tasks : taskDescriptions];
|
|
455
726
|
}
|
|
727
|
+
exports._prepareNextTasks = _prepareNextTasks;
|