@langchain/langgraph 0.2.32 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._isCommand = exports.Command = exports._isSend = exports.Send = exports._isSendInterface = exports.CHECKPOINT_NAMESPACE_END = exports.CHECKPOINT_NAMESPACE_SEPARATOR = exports.RESERVED = exports.NULL_TASK_ID = exports.TASK_NAMESPACE = exports.PULL = exports.PUSH = exports.TASKS = exports.SELF = exports.TAG_NOSTREAM = exports.TAG_HIDDEN = exports.RECURSION_LIMIT_DEFAULT = exports.RUNTIME_PLACEHOLDER = exports.RESUME = exports.INTERRUPT = exports.CONFIG_KEY_CHECKPOINT_MAP = exports.CONFIG_KEY_CHECKPOINT_NS = exports.CONFIG_KEY_SCRATCHPAD = exports.CONFIG_KEY_WRITES = exports.CONFIG_KEY_RESUME_VALUE = exports.CONFIG_KEY_STREAM = exports.CONFIG_KEY_TASK_ID = exports.CONFIG_KEY_RESUMING = exports.CONFIG_KEY_CHECKPOINTER = exports.CONFIG_KEY_READ = exports.CONFIG_KEY_SEND = exports.ERROR = exports.INPUT = exports.MISSING = void 0;
3
+ exports.isCommand = exports.Command = exports._isSend = exports.Send = exports._isSendInterface = exports.CHECKPOINT_NAMESPACE_END = exports.CHECKPOINT_NAMESPACE_SEPARATOR = exports.RESERVED = exports.NULL_TASK_ID = exports.TASK_NAMESPACE = exports.PULL = exports.PUSH = exports.TASKS = exports.SELF = exports.TAG_NOSTREAM = exports.TAG_HIDDEN = exports.RECURSION_LIMIT_DEFAULT = exports.RUNTIME_PLACEHOLDER = exports.RESUME = exports.INTERRUPT = exports.CONFIG_KEY_CHECKPOINT_MAP = exports.CONFIG_KEY_CHECKPOINT_NS = exports.CONFIG_KEY_SCRATCHPAD = exports.CONFIG_KEY_WRITES = exports.CONFIG_KEY_RESUME_VALUE = exports.CONFIG_KEY_STREAM = exports.CONFIG_KEY_TASK_ID = exports.CONFIG_KEY_RESUMING = exports.CONFIG_KEY_CHECKPOINTER = exports.CONFIG_KEY_READ = exports.CONFIG_KEY_SEND = exports.ERROR = exports.INPUT = exports.MISSING = void 0;
4
4
  exports.MISSING = Symbol.for("__missing__");
5
5
  exports.INPUT = "__input__";
6
6
  exports.ERROR = "__error__";
@@ -126,6 +126,65 @@ function _isSend(x) {
126
126
  exports._isSend = _isSend;
127
127
  /**
128
128
  * One or more commands to update the graph's state and send messages to nodes.
129
+ * Can be used to combine routing logic with state updates in lieu of conditional edges
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * import { Annotation, Command } from "@langchain/langgraph";
134
+ *
135
+ * // Define graph state
136
+ * const StateAnnotation = Annotation.Root({
137
+ * foo: Annotation<string>,
138
+ * });
139
+ *
140
+ * // Define the nodes
141
+ * const nodeA = async (_state: typeof StateAnnotation.State) => {
142
+ * console.log("Called A");
143
+ * // this is a replacement for a real conditional edge function
144
+ * const goto = Math.random() > .5 ? "nodeB" : "nodeC";
145
+ * // note how Command allows you to BOTH update the graph state AND route to the next node
146
+ * return new Command({
147
+ * // this is the state update
148
+ * update: {
149
+ * foo: "a",
150
+ * },
151
+ * // this is a replacement for an edge
152
+ * goto,
153
+ * });
154
+ * };
155
+ *
156
+ * // Nodes B and C are unchanged
157
+ * const nodeB = async (state: typeof StateAnnotation.State) => {
158
+ * console.log("Called B");
159
+ * return {
160
+ * foo: state.foo + "|b",
161
+ * };
162
+ * }
163
+ *
164
+ * const nodeC = async (state: typeof StateAnnotation.State) => {
165
+ * console.log("Called C");
166
+ * return {
167
+ * foo: state.foo + "|c",
168
+ * };
169
+ * }
170
+ *
171
+ * import { StateGraph } from "@langchain/langgraph";
172
+
173
+ * // NOTE: there are no edges between nodes A, B and C!
174
+ * const graph = new StateGraph(StateAnnotation)
175
+ * .addNode("nodeA", nodeA, {
176
+ * ends: ["nodeB", "nodeC"],
177
+ * })
178
+ * .addNode("nodeB", nodeB)
179
+ * .addNode("nodeC", nodeC)
180
+ * .addEdge("__start__", "nodeA")
181
+ * .compile();
182
+ *
183
+ * await graph.invoke({ foo: "" });
184
+ *
185
+ * // Randomly oscillates between
186
+ * // { foo: 'a|c' } and { foo: 'a|b' }
187
+ * ```
129
188
  */
130
189
  class Command {
131
190
  constructor(args) {
@@ -135,11 +194,11 @@ class Command {
135
194
  writable: true,
136
195
  value: "Command"
137
196
  });
138
- Object.defineProperty(this, "resume", {
197
+ Object.defineProperty(this, "lc_direct_tool_output", {
139
198
  enumerable: true,
140
199
  configurable: true,
141
200
  writable: true,
142
- value: void 0
201
+ value: true
143
202
  });
144
203
  Object.defineProperty(this, "graph", {
145
204
  enumerable: true,
@@ -149,6 +208,12 @@ class Command {
149
208
  });
150
209
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
151
210
  Object.defineProperty(this, "update", {
211
+ enumerable: true,
212
+ configurable: true,
213
+ writable: true,
214
+ value: []
215
+ });
216
+ Object.defineProperty(this, "resume", {
152
217
  enumerable: true,
153
218
  configurable: true,
154
219
  writable: true,
@@ -167,6 +232,20 @@ class Command {
167
232
  this.goto = Array.isArray(args.goto) ? args.goto : [args.goto];
168
233
  }
169
234
  }
235
+ _updateAsTuples() {
236
+ if (this.update &&
237
+ typeof this.update === "object" &&
238
+ !Array.isArray(this.update)) {
239
+ return Object.entries(this.update);
240
+ }
241
+ else if (Array.isArray(this.update) &&
242
+ this.update.every((t) => Array.isArray(t) && t.length === 2 && typeof t[0] === "string")) {
243
+ return this.update;
244
+ }
245
+ else {
246
+ return [["__root__", this.update]];
247
+ }
248
+ }
170
249
  }
171
250
  exports.Command = Command;
172
251
  Object.defineProperty(Command, "PARENT", {
@@ -175,7 +254,7 @@ Object.defineProperty(Command, "PARENT", {
175
254
  writable: true,
176
255
  value: "__parent__"
177
256
  });
178
- function _isCommand(x) {
257
+ function isCommand(x) {
179
258
  return typeof x === "object" && !!x && x.lg_name === "Command";
180
259
  }
181
- exports._isCommand = _isCommand;
260
+ exports.isCommand = isCommand;
@@ -117,14 +117,75 @@ export type CommandParams<R> = {
117
117
  };
118
118
  /**
119
119
  * One or more commands to update the graph's state and send messages to nodes.
120
+ * Can be used to combine routing logic with state updates in lieu of conditional edges
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * import { Annotation, Command } from "@langchain/langgraph";
125
+ *
126
+ * // Define graph state
127
+ * const StateAnnotation = Annotation.Root({
128
+ * foo: Annotation<string>,
129
+ * });
130
+ *
131
+ * // Define the nodes
132
+ * const nodeA = async (_state: typeof StateAnnotation.State) => {
133
+ * console.log("Called A");
134
+ * // this is a replacement for a real conditional edge function
135
+ * const goto = Math.random() > .5 ? "nodeB" : "nodeC";
136
+ * // note how Command allows you to BOTH update the graph state AND route to the next node
137
+ * return new Command({
138
+ * // this is the state update
139
+ * update: {
140
+ * foo: "a",
141
+ * },
142
+ * // this is a replacement for an edge
143
+ * goto,
144
+ * });
145
+ * };
146
+ *
147
+ * // Nodes B and C are unchanged
148
+ * const nodeB = async (state: typeof StateAnnotation.State) => {
149
+ * console.log("Called B");
150
+ * return {
151
+ * foo: state.foo + "|b",
152
+ * };
153
+ * }
154
+ *
155
+ * const nodeC = async (state: typeof StateAnnotation.State) => {
156
+ * console.log("Called C");
157
+ * return {
158
+ * foo: state.foo + "|c",
159
+ * };
160
+ * }
161
+ *
162
+ * import { StateGraph } from "@langchain/langgraph";
163
+
164
+ * // NOTE: there are no edges between nodes A, B and C!
165
+ * const graph = new StateGraph(StateAnnotation)
166
+ * .addNode("nodeA", nodeA, {
167
+ * ends: ["nodeB", "nodeC"],
168
+ * })
169
+ * .addNode("nodeB", nodeB)
170
+ * .addNode("nodeC", nodeC)
171
+ * .addEdge("__start__", "nodeA")
172
+ * .compile();
173
+ *
174
+ * await graph.invoke({ foo: "" });
175
+ *
176
+ * // Randomly oscillates between
177
+ * // { foo: 'a|c' } and { foo: 'a|b' }
178
+ * ```
120
179
  */
121
180
  export declare class Command<R = unknown> {
122
181
  lg_name: string;
123
- resume?: R;
182
+ lc_direct_tool_output: boolean;
124
183
  graph?: string;
125
- update?: Record<string, any>;
184
+ update?: Record<string, any> | [string, any][];
185
+ resume?: R;
126
186
  goto: string | Send | (string | Send)[];
127
187
  static PARENT: string;
128
188
  constructor(args: CommandParams<R>);
189
+ _updateAsTuples(): [string, unknown][];
129
190
  }
130
- export declare function _isCommand(x: unknown): x is Command;
191
+ export declare function isCommand(x: unknown): x is Command;
package/dist/constants.js CHANGED
@@ -120,6 +120,65 @@ export function _isSend(x) {
120
120
  }
121
121
  /**
122
122
  * One or more commands to update the graph's state and send messages to nodes.
123
+ * Can be used to combine routing logic with state updates in lieu of conditional edges
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * import { Annotation, Command } from "@langchain/langgraph";
128
+ *
129
+ * // Define graph state
130
+ * const StateAnnotation = Annotation.Root({
131
+ * foo: Annotation<string>,
132
+ * });
133
+ *
134
+ * // Define the nodes
135
+ * const nodeA = async (_state: typeof StateAnnotation.State) => {
136
+ * console.log("Called A");
137
+ * // this is a replacement for a real conditional edge function
138
+ * const goto = Math.random() > .5 ? "nodeB" : "nodeC";
139
+ * // note how Command allows you to BOTH update the graph state AND route to the next node
140
+ * return new Command({
141
+ * // this is the state update
142
+ * update: {
143
+ * foo: "a",
144
+ * },
145
+ * // this is a replacement for an edge
146
+ * goto,
147
+ * });
148
+ * };
149
+ *
150
+ * // Nodes B and C are unchanged
151
+ * const nodeB = async (state: typeof StateAnnotation.State) => {
152
+ * console.log("Called B");
153
+ * return {
154
+ * foo: state.foo + "|b",
155
+ * };
156
+ * }
157
+ *
158
+ * const nodeC = async (state: typeof StateAnnotation.State) => {
159
+ * console.log("Called C");
160
+ * return {
161
+ * foo: state.foo + "|c",
162
+ * };
163
+ * }
164
+ *
165
+ * import { StateGraph } from "@langchain/langgraph";
166
+
167
+ * // NOTE: there are no edges between nodes A, B and C!
168
+ * const graph = new StateGraph(StateAnnotation)
169
+ * .addNode("nodeA", nodeA, {
170
+ * ends: ["nodeB", "nodeC"],
171
+ * })
172
+ * .addNode("nodeB", nodeB)
173
+ * .addNode("nodeC", nodeC)
174
+ * .addEdge("__start__", "nodeA")
175
+ * .compile();
176
+ *
177
+ * await graph.invoke({ foo: "" });
178
+ *
179
+ * // Randomly oscillates between
180
+ * // { foo: 'a|c' } and { foo: 'a|b' }
181
+ * ```
123
182
  */
124
183
  export class Command {
125
184
  constructor(args) {
@@ -129,11 +188,11 @@ export class Command {
129
188
  writable: true,
130
189
  value: "Command"
131
190
  });
132
- Object.defineProperty(this, "resume", {
191
+ Object.defineProperty(this, "lc_direct_tool_output", {
133
192
  enumerable: true,
134
193
  configurable: true,
135
194
  writable: true,
136
- value: void 0
195
+ value: true
137
196
  });
138
197
  Object.defineProperty(this, "graph", {
139
198
  enumerable: true,
@@ -143,6 +202,12 @@ export class Command {
143
202
  });
144
203
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
204
  Object.defineProperty(this, "update", {
205
+ enumerable: true,
206
+ configurable: true,
207
+ writable: true,
208
+ value: []
209
+ });
210
+ Object.defineProperty(this, "resume", {
146
211
  enumerable: true,
147
212
  configurable: true,
148
213
  writable: true,
@@ -161,6 +226,20 @@ export class Command {
161
226
  this.goto = Array.isArray(args.goto) ? args.goto : [args.goto];
162
227
  }
163
228
  }
229
+ _updateAsTuples() {
230
+ if (this.update &&
231
+ typeof this.update === "object" &&
232
+ !Array.isArray(this.update)) {
233
+ return Object.entries(this.update);
234
+ }
235
+ else if (Array.isArray(this.update) &&
236
+ this.update.every((t) => Array.isArray(t) && t.length === 2 && typeof t[0] === "string")) {
237
+ return this.update;
238
+ }
239
+ else {
240
+ return [["__root__", this.update]];
241
+ }
242
+ }
164
243
  }
165
244
  Object.defineProperty(Command, "PARENT", {
166
245
  enumerable: true,
@@ -168,6 +247,6 @@ Object.defineProperty(Command, "PARENT", {
168
247
  writable: true,
169
248
  value: "__parent__"
170
249
  });
171
- export function _isCommand(x) {
250
+ export function isCommand(x) {
172
251
  return typeof x === "object" && !!x && x.lg_name === "Command";
173
252
  }
package/dist/errors.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSubgraphsSeenSet = exports.RemoteException = exports.MultipleSubgraphsError = exports.InvalidUpdateError = exports.EmptyChannelError = exports.EmptyInputError = exports.isGraphInterrupt = exports.isGraphBubbleUp = exports.isParentCommand = exports.ParentCommand = exports.NodeInterrupt = exports.GraphInterrupt = exports.GraphValueError = exports.GraphRecursionError = exports.GraphBubbleUp = exports.BaseLangGraphError = void 0;
3
+ exports.getSubgraphsSeenSet = exports.RemoteException = exports.UnreachableNodeError = exports.MultipleSubgraphsError = exports.InvalidUpdateError = exports.EmptyChannelError = exports.EmptyInputError = exports.isGraphInterrupt = exports.isGraphBubbleUp = exports.isParentCommand = exports.ParentCommand = exports.NodeInterrupt = exports.GraphInterrupt = exports.GraphValueError = exports.GraphRecursionError = exports.GraphBubbleUp = exports.BaseLangGraphError = void 0;
4
4
  // TODO: Merge with base LangChain error class when we drop support for core@0.2.0
5
5
  class BaseLangGraphError extends Error {
6
6
  constructor(message, fields) {
@@ -153,6 +153,16 @@ class MultipleSubgraphsError extends BaseLangGraphError {
153
153
  }
154
154
  }
155
155
  exports.MultipleSubgraphsError = MultipleSubgraphsError;
156
+ class UnreachableNodeError extends BaseLangGraphError {
157
+ constructor(message, fields) {
158
+ super(message, fields);
159
+ this.name = "UnreachableNodeError";
160
+ }
161
+ static get unminifiable_name() {
162
+ return "UnreachableNodeError";
163
+ }
164
+ }
165
+ exports.UnreachableNodeError = UnreachableNodeError;
156
166
  /**
157
167
  * Exception raised when an error occurs in the remote graph.
158
168
  */
package/dist/errors.d.ts CHANGED
@@ -51,6 +51,10 @@ export declare class MultipleSubgraphsError extends BaseLangGraphError {
51
51
  constructor(message?: string, fields?: BaseLangGraphErrorFields);
52
52
  static get unminifiable_name(): string;
53
53
  }
54
+ export declare class UnreachableNodeError extends BaseLangGraphError {
55
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
56
+ static get unminifiable_name(): string;
57
+ }
54
58
  /**
55
59
  * Exception raised when an error occurs in the remote graph.
56
60
  */
package/dist/errors.js CHANGED
@@ -136,6 +136,15 @@ export class MultipleSubgraphsError extends BaseLangGraphError {
136
136
  return "MultipleSubgraphError";
137
137
  }
138
138
  }
139
+ export class UnreachableNodeError extends BaseLangGraphError {
140
+ constructor(message, fields) {
141
+ super(message, fields);
142
+ this.name = "UnreachableNodeError";
143
+ }
144
+ static get unminifiable_name() {
145
+ return "UnreachableNodeError";
146
+ }
147
+ }
139
148
  /**
140
149
  * Exception raised when an error occurs in the remote graph.
141
150
  */
@@ -299,7 +299,15 @@ class Graph {
299
299
  // validate targets
300
300
  for (const node of Object.keys(this.nodes)) {
301
301
  if (!allTargets.has(node)) {
302
- throw new Error(`Node \`${node}\` is not reachable`);
302
+ throw new errors_js_1.UnreachableNodeError([
303
+ `Node \`${node}\` is not reachable.`,
304
+ "",
305
+ "If you are returning Command objects from your node,",
306
+ 'make sure you are passing names of potential destination nodes as an "ends" array',
307
+ 'into ".addNode(..., { ends: ["node1", "node2"] })".',
308
+ ].join("\n"), {
309
+ lc_error_code: "UNREACHABLE_NODE",
310
+ });
303
311
  }
304
312
  }
305
313
  for (const target of allTargets) {
@@ -9,7 +9,7 @@ import { EphemeralValue } from "../channels/ephemeral_value.js";
9
9
  import { ChannelWrite, PASSTHROUGH } from "../pregel/write.js";
10
10
  import { _isSend, CHECKPOINT_NAMESPACE_END, CHECKPOINT_NAMESPACE_SEPARATOR, TAG_HIDDEN, } from "../constants.js";
11
11
  import { gatherIterator, gatherIteratorSync, RunnableCallable, } from "../utils.js";
12
- import { InvalidUpdateError, NodeInterrupt } from "../errors.js";
12
+ import { InvalidUpdateError, NodeInterrupt, UnreachableNodeError, } from "../errors.js";
13
13
  import { isPregelLike } from "../pregel/utils/subgraph.js";
14
14
  /** Special reserved node name denoting the start of a graph. */
15
15
  export const START = "__start__";
@@ -295,7 +295,15 @@ export class Graph {
295
295
  // validate targets
296
296
  for (const node of Object.keys(this.nodes)) {
297
297
  if (!allTargets.has(node)) {
298
- throw new Error(`Node \`${node}\` is not reachable`);
298
+ throw new UnreachableNodeError([
299
+ `Node \`${node}\` is not reachable.`,
300
+ "",
301
+ "If you are returning Command objects from your node,",
302
+ 'make sure you are passing names of potential destination nodes as an "ends" array',
303
+ 'into ".addNode(..., { ends: ["node1", "node2"] })".',
304
+ ].join("\n"), {
305
+ lc_error_code: "UNREACHABLE_NODE",
306
+ });
299
307
  }
300
308
  }
301
309
  for (const target of allTargets) {
@@ -347,59 +347,101 @@ function _getChannels(schema) {
347
347
  */
348
348
  class CompiledStateGraph extends graph_js_1.CompiledGraph {
349
349
  attachNode(key, node) {
350
- const stateKeys = Object.keys(this.builder.channels);
350
+ let outputKeys;
351
+ if (key === graph_js_1.START) {
352
+ // Get input schema keys excluding managed values
353
+ outputKeys = Object.entries(this.builder._schemaDefinitions.get(this.builder._inputDefinition))
354
+ .filter(([_, v]) => !(0, base_js_2.isConfiguredManagedValue)(v))
355
+ .map(([k]) => k);
356
+ }
357
+ else {
358
+ outputKeys = Object.keys(this.builder.channels);
359
+ }
360
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
351
361
  function _getRoot(input) {
352
- if ((0, constants_js_1._isCommand)(input)) {
362
+ if ((0, constants_js_1.isCommand)(input)) {
353
363
  if (input.graph === constants_js_1.Command.PARENT) {
354
- return write_js_1.SKIP_WRITE;
364
+ return null;
365
+ }
366
+ return input._updateAsTuples();
367
+ }
368
+ else if (Array.isArray(input) &&
369
+ input.length > 0 &&
370
+ input.some((i) => (0, constants_js_1.isCommand)(i))) {
371
+ const updates = [];
372
+ for (const i of input) {
373
+ if ((0, constants_js_1.isCommand)(i)) {
374
+ if (i.graph === constants_js_1.Command.PARENT) {
375
+ continue;
376
+ }
377
+ updates.push(...i._updateAsTuples());
378
+ }
379
+ else {
380
+ updates.push([ROOT, i]);
381
+ }
355
382
  }
356
- return input.update;
383
+ return updates;
357
384
  }
358
- return input;
385
+ else if (input != null) {
386
+ return [[ROOT, input]];
387
+ }
388
+ return null;
359
389
  }
360
390
  // to avoid name collision below
361
391
  const nodeKey = key;
362
- function getStateKey(key, input) {
392
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
393
+ function _getUpdates(input) {
363
394
  if (!input) {
364
- return write_js_1.SKIP_WRITE;
395
+ return null;
365
396
  }
366
- else if ((0, constants_js_1._isCommand)(input)) {
397
+ else if ((0, constants_js_1.isCommand)(input)) {
367
398
  if (input.graph === constants_js_1.Command.PARENT) {
368
- return write_js_1.SKIP_WRITE;
399
+ return null;
369
400
  }
370
- return getStateKey(key, input.update);
401
+ return input._updateAsTuples();
371
402
  }
372
- else if (typeof input !== "object" || Array.isArray(input)) {
403
+ else if (Array.isArray(input) &&
404
+ input.length > 0 &&
405
+ input.some(constants_js_1.isCommand)) {
406
+ const updates = [];
407
+ for (const item of input) {
408
+ if ((0, constants_js_1.isCommand)(item)) {
409
+ if (item.graph === constants_js_1.Command.PARENT) {
410
+ continue;
411
+ }
412
+ updates.push(...item._updateAsTuples());
413
+ }
414
+ else {
415
+ const itemUpdates = _getUpdates(item);
416
+ if (itemUpdates) {
417
+ updates.push(...(itemUpdates ?? []));
418
+ }
419
+ }
420
+ }
421
+ return updates;
422
+ }
423
+ else if (typeof input === "object" && !Array.isArray(input)) {
424
+ return Object.entries(input).filter(([k]) => outputKeys.includes(k));
425
+ }
426
+ else {
373
427
  const typeofInput = Array.isArray(input) ? "array" : typeof input;
374
428
  throw new errors_js_1.InvalidUpdateError(`Expected node "${nodeKey.toString()}" to return an object, received ${typeofInput}`, {
375
429
  lc_error_code: "INVALID_GRAPH_NODE_RETURN_VALUE",
376
430
  });
377
431
  }
378
- else {
379
- return key in input ? input[key] : write_js_1.SKIP_WRITE;
380
- }
381
432
  }
382
- // state updaters
383
- const stateWriteEntries = stateKeys.map((key) => key === ROOT
384
- ? {
385
- channel: key,
433
+ const stateWriteEntries = [
434
+ {
386
435
  value: write_js_1.PASSTHROUGH,
387
- skipNone: true,
388
436
  mapper: new utils_js_1.RunnableCallable({
389
- func: _getRoot,
437
+ func: outputKeys.length && outputKeys[0] === ROOT
438
+ ? _getRoot
439
+ : _getUpdates,
390
440
  trace: false,
391
441
  recurse: false,
392
442
  }),
393
- }
394
- : {
395
- channel: key,
396
- value: write_js_1.PASSTHROUGH,
397
- mapper: new utils_js_1.RunnableCallable({
398
- func: getStateKey.bind(null, key),
399
- trace: false,
400
- recurse: false,
401
- }),
402
- });
443
+ },
444
+ ];
403
445
  // add node and output channel
404
446
  if (key === graph_js_1.START) {
405
447
  this.nodes[key] = new read_js_1.PregelNode({
@@ -541,7 +583,7 @@ function _controlBranch(value) {
541
583
  if ((0, constants_js_1._isSend)(value)) {
542
584
  return [value];
543
585
  }
544
- if (!(0, constants_js_1._isCommand)(value)) {
586
+ if (!(0, constants_js_1.isCommand)(value)) {
545
587
  return [];
546
588
  }
547
589
  if (value.graph === constants_js_1.Command.PARENT) {