@langchain/langgraph 0.2.27 → 0.2.29

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.
@@ -46,7 +46,34 @@ function readChannels(channels, select, skipEmpty = true
46
46
  }
47
47
  }
48
48
  exports.readChannels = readChannels;
49
+ /**
50
+ * Map input chunk to a sequence of pending writes in the form (channel, value).
51
+ */
49
52
  function* mapCommand(cmd) {
53
+ if (cmd.graph === constants_js_1.Command.PARENT) {
54
+ throw new errors_js_1.InvalidUpdateError("There is no parent graph.");
55
+ }
56
+ if (cmd.goto) {
57
+ let sends;
58
+ if (Array.isArray(cmd.goto)) {
59
+ sends = cmd.goto;
60
+ }
61
+ else {
62
+ sends = [cmd.goto];
63
+ }
64
+ for (const send of sends) {
65
+ if ((0, constants_js_1._isSend)(send)) {
66
+ yield [constants_js_1.NULL_TASK_ID, constants_js_1.TASKS, send];
67
+ }
68
+ else if (typeof send === "string") {
69
+ yield [constants_js_1.NULL_TASK_ID, `branch:__start__:${constants_js_1.SELF}:${send}`, "__start__"];
70
+ }
71
+ else {
72
+ throw new Error(`In Command.send, expected Send or string, got ${typeof send}`);
73
+ }
74
+ }
75
+ // TODO: handle goto str for state graph
76
+ }
50
77
  if (cmd.resume) {
51
78
  if (typeof cmd.resume === "object" &&
52
79
  !!cmd.resume &&
@@ -60,6 +87,14 @@ function* mapCommand(cmd) {
60
87
  yield [constants_js_1.NULL_TASK_ID, constants_js_1.RESUME, cmd.resume];
61
88
  }
62
89
  }
90
+ if (cmd.update) {
91
+ if (typeof cmd.update !== "object" || !cmd.update) {
92
+ throw new Error("Expected cmd.update to be a dict mapping channel names to update values");
93
+ }
94
+ for (const [k, v] of Object.entries(cmd.update)) {
95
+ yield [constants_js_1.NULL_TASK_ID, k, v];
96
+ }
97
+ }
63
98
  }
64
99
  exports.mapCommand = mapCommand;
65
100
  /**
@@ -4,6 +4,9 @@ import type { PregelExecutableTask } from "./types.js";
4
4
  import { Command } from "../constants.js";
5
5
  export declare function readChannel<C extends PropertyKey>(channels: Record<C, BaseChannel>, chan: C, catchErrors?: boolean, returnException?: boolean): unknown | null;
6
6
  export declare function readChannels<C extends PropertyKey>(channels: Record<C, BaseChannel>, select: C | Array<C>, skipEmpty?: boolean): Record<string, any> | any;
7
+ /**
8
+ * Map input chunk to a sequence of pending writes in the form (channel, value).
9
+ */
7
10
  export declare function mapCommand(cmd: Command): Generator<[string, string, unknown]>;
8
11
  /**
9
12
  * Map input chunk to a sequence of pending writes in the form [channel, value].
package/dist/pregel/io.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { validate } from "uuid";
2
- import { NULL_TASK_ID, RESUME, TAG_HIDDEN } from "../constants.js";
3
- import { EmptyChannelError } from "../errors.js";
2
+ import { _isSend, Command, NULL_TASK_ID, RESUME, SELF, TAG_HIDDEN, TASKS, } from "../constants.js";
3
+ import { EmptyChannelError, InvalidUpdateError } from "../errors.js";
4
4
  export function readChannel(channels, chan, catchErrors = true, returnException = false) {
5
5
  try {
6
6
  return channels[chan].get();
@@ -41,7 +41,34 @@ export function readChannels(channels, select, skipEmpty = true
41
41
  return readChannel(channels, select);
42
42
  }
43
43
  }
44
+ /**
45
+ * Map input chunk to a sequence of pending writes in the form (channel, value).
46
+ */
44
47
  export function* mapCommand(cmd) {
48
+ if (cmd.graph === Command.PARENT) {
49
+ throw new InvalidUpdateError("There is no parent graph.");
50
+ }
51
+ if (cmd.goto) {
52
+ let sends;
53
+ if (Array.isArray(cmd.goto)) {
54
+ sends = cmd.goto;
55
+ }
56
+ else {
57
+ sends = [cmd.goto];
58
+ }
59
+ for (const send of sends) {
60
+ if (_isSend(send)) {
61
+ yield [NULL_TASK_ID, TASKS, send];
62
+ }
63
+ else if (typeof send === "string") {
64
+ yield [NULL_TASK_ID, `branch:__start__:${SELF}:${send}`, "__start__"];
65
+ }
66
+ else {
67
+ throw new Error(`In Command.send, expected Send or string, got ${typeof send}`);
68
+ }
69
+ }
70
+ // TODO: handle goto str for state graph
71
+ }
45
72
  if (cmd.resume) {
46
73
  if (typeof cmd.resume === "object" &&
47
74
  !!cmd.resume &&
@@ -55,6 +82,14 @@ export function* mapCommand(cmd) {
55
82
  yield [NULL_TASK_ID, RESUME, cmd.resume];
56
83
  }
57
84
  }
85
+ if (cmd.update) {
86
+ if (typeof cmd.update !== "object" || !cmd.update) {
87
+ throw new Error("Expected cmd.update to be a dict mapping channel names to update values");
88
+ }
89
+ for (const [k, v] of Object.entries(cmd.update)) {
90
+ yield [NULL_TASK_ID, k, v];
91
+ }
92
+ }
58
93
  }
59
94
  /**
60
95
  * Map input chunk to a sequence of pending writes in the form [channel, value].
@@ -576,22 +576,9 @@ class PregelLoop {
576
576
  async _first(inputKeys) {
577
577
  const isResuming = Object.keys(this.checkpoint.channel_versions).length !== 0 &&
578
578
  (this.config.configurable?.[constants_js_1.CONFIG_KEY_RESUMING] !== undefined ||
579
- this.input === null);
580
- if (isResuming) {
581
- for (const channelName of Object.keys(this.channels)) {
582
- if (this.checkpoint.channel_versions[channelName] !== undefined) {
583
- const version = this.checkpoint.channel_versions[channelName];
584
- this.checkpoint.versions_seen[constants_js_1.INTERRUPT] = {
585
- ...this.checkpoint.versions_seen[constants_js_1.INTERRUPT],
586
- [channelName]: version,
587
- };
588
- }
589
- }
590
- // produce values output
591
- const valuesOutput = await (0, utils_js_1.gatherIterator)((0, utils_js_1.prefixGenerator)((0, io_js_1.mapOutputValues)(this.outputKeys, true, this.channels), "values"));
592
- this._emit(valuesOutput);
593
- }
594
- else if ((0, constants_js_1._isCommand)(this.input)) {
579
+ this.input === null ||
580
+ (0, constants_js_1._isCommand)(this.input));
581
+ if ((0, constants_js_1._isCommand)(this.input)) {
595
582
  const writes = {};
596
583
  // group writes by task id
597
584
  for (const [tid, key, value] of (0, io_js_1.mapCommand)(this.input)) {
@@ -608,6 +595,20 @@ class PregelLoop {
608
595
  this.putWrites(tid, ws);
609
596
  }
610
597
  }
598
+ if (isResuming) {
599
+ for (const channelName of Object.keys(this.channels)) {
600
+ if (this.checkpoint.channel_versions[channelName] !== undefined) {
601
+ const version = this.checkpoint.channel_versions[channelName];
602
+ this.checkpoint.versions_seen[constants_js_1.INTERRUPT] = {
603
+ ...this.checkpoint.versions_seen[constants_js_1.INTERRUPT],
604
+ [channelName]: version,
605
+ };
606
+ }
607
+ }
608
+ // produce values output
609
+ const valuesOutput = await (0, utils_js_1.gatherIterator)((0, utils_js_1.prefixGenerator)((0, io_js_1.mapOutputValues)(this.outputKeys, true, this.channels), "values"));
610
+ this._emit(valuesOutput);
611
+ }
611
612
  else {
612
613
  // map inputs to channel updates
613
614
  const inputWrites = await (0, utils_js_1.gatherIterator)((0, io_js_1.mapInput)(inputKeys, this.input));
@@ -572,22 +572,9 @@ export class PregelLoop {
572
572
  async _first(inputKeys) {
573
573
  const isResuming = Object.keys(this.checkpoint.channel_versions).length !== 0 &&
574
574
  (this.config.configurable?.[CONFIG_KEY_RESUMING] !== undefined ||
575
- this.input === null);
576
- if (isResuming) {
577
- for (const channelName of Object.keys(this.channels)) {
578
- if (this.checkpoint.channel_versions[channelName] !== undefined) {
579
- const version = this.checkpoint.channel_versions[channelName];
580
- this.checkpoint.versions_seen[INTERRUPT] = {
581
- ...this.checkpoint.versions_seen[INTERRUPT],
582
- [channelName]: version,
583
- };
584
- }
585
- }
586
- // produce values output
587
- const valuesOutput = await gatherIterator(prefixGenerator(mapOutputValues(this.outputKeys, true, this.channels), "values"));
588
- this._emit(valuesOutput);
589
- }
590
- else if (_isCommand(this.input)) {
575
+ this.input === null ||
576
+ _isCommand(this.input));
577
+ if (_isCommand(this.input)) {
591
578
  const writes = {};
592
579
  // group writes by task id
593
580
  for (const [tid, key, value] of mapCommand(this.input)) {
@@ -604,6 +591,20 @@ export class PregelLoop {
604
591
  this.putWrites(tid, ws);
605
592
  }
606
593
  }
594
+ if (isResuming) {
595
+ for (const channelName of Object.keys(this.channels)) {
596
+ if (this.checkpoint.channel_versions[channelName] !== undefined) {
597
+ const version = this.checkpoint.channel_versions[channelName];
598
+ this.checkpoint.versions_seen[INTERRUPT] = {
599
+ ...this.checkpoint.versions_seen[INTERRUPT],
600
+ [channelName]: version,
601
+ };
602
+ }
603
+ }
604
+ // produce values output
605
+ const valuesOutput = await gatherIterator(prefixGenerator(mapOutputValues(this.outputKeys, true, this.channels), "values"));
606
+ this._emit(valuesOutput);
607
+ }
607
608
  else {
608
609
  // map inputs to channel updates
609
610
  const inputWrites = await gatherIterator(mapInput(inputKeys, this.input));
@@ -63,7 +63,7 @@ const defaultRunnableBound =
63
63
  /* #__PURE__ */ new runnables_1.RunnablePassthrough();
64
64
  class PregelNode extends runnables_1.RunnableBinding {
65
65
  constructor(fields) {
66
- const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, } = fields;
66
+ const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, ends, } = fields;
67
67
  const mergedTags = [
68
68
  ...(fields.config?.tags ? fields.config.tags : []),
69
69
  ...(tags ?? []),
@@ -145,6 +145,12 @@ class PregelNode extends runnables_1.RunnableBinding {
145
145
  writable: true,
146
146
  value: void 0
147
147
  });
148
+ Object.defineProperty(this, "ends", {
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true,
152
+ value: void 0
153
+ });
148
154
  this.channels = channels;
149
155
  this.triggers = triggers;
150
156
  this.mapper = mapper;
@@ -155,6 +161,7 @@ class PregelNode extends runnables_1.RunnableBinding {
155
161
  this.tags = mergedTags;
156
162
  this.retryPolicy = retryPolicy;
157
163
  this.subgraphs = subgraphs;
164
+ this.ends = ends;
158
165
  }
159
166
  getWriters() {
160
167
  const newWriters = [...this.writers];
@@ -21,6 +21,7 @@ interface PregelNodeArgs<RunInput, RunOutput> extends Partial<RunnableBindingArg
21
21
  metadata?: Record<string, unknown>;
22
22
  retryPolicy?: RetryPolicy;
23
23
  subgraphs?: Runnable[];
24
+ ends?: string[];
24
25
  }
25
26
  export type PregelNodeInputType = any;
26
27
  export type PregelNodeOutputType = any;
@@ -36,6 +37,7 @@ export declare class PregelNode<RunInput = PregelNodeInputType, RunOutput = Preg
36
37
  tags: string[];
37
38
  retryPolicy?: RetryPolicy;
38
39
  subgraphs?: Runnable[];
40
+ ends?: string[];
39
41
  constructor(fields: PregelNodeArgs<RunInput, RunOutput>);
40
42
  getWriters(): Array<Runnable>;
41
43
  getNode(): Runnable<RunInput, RunOutput> | undefined;
@@ -59,7 +59,7 @@ const defaultRunnableBound =
59
59
  /* #__PURE__ */ new RunnablePassthrough();
60
60
  export class PregelNode extends RunnableBinding {
61
61
  constructor(fields) {
62
- const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, } = fields;
62
+ const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, ends, } = fields;
63
63
  const mergedTags = [
64
64
  ...(fields.config?.tags ? fields.config.tags : []),
65
65
  ...(tags ?? []),
@@ -141,6 +141,12 @@ export class PregelNode extends RunnableBinding {
141
141
  writable: true,
142
142
  value: void 0
143
143
  });
144
+ Object.defineProperty(this, "ends", {
145
+ enumerable: true,
146
+ configurable: true,
147
+ writable: true,
148
+ value: void 0
149
+ });
144
150
  this.channels = channels;
145
151
  this.triggers = triggers;
146
152
  this.mapper = mapper;
@@ -151,6 +157,7 @@ export class PregelNode extends RunnableBinding {
151
157
  this.tags = mergedTags;
152
158
  this.retryPolicy = retryPolicy;
153
159
  this.subgraphs = subgraphs;
160
+ this.ends = ends;
154
161
  }
155
162
  getWriters() {
156
163
  const newWriters = [...this.writers];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeTasksWithRetry = exports.DEFAULT_MAX_RETRIES = exports.DEFAULT_MAX_INTERVAL = exports.DEFAULT_BACKOFF_FACTOR = exports.DEFAULT_INITIAL_INTERVAL = void 0;
4
+ const constants_js_1 = require("../constants.cjs");
4
5
  const errors_js_1 = require("../errors.cjs");
5
6
  exports.DEFAULT_INITIAL_INTERVAL = 500;
6
7
  exports.DEFAULT_BACKOFF_FACTOR = 2;
@@ -103,6 +104,28 @@ pregelTask, retryPolicy) {
103
104
  catch (e) {
104
105
  error = e;
105
106
  error.pregelTaskId = pregelTask.id;
107
+ if ((0, errors_js_1.isParentCommand)(error)) {
108
+ const ns = pregelTask.config?.configurable?.checkpoint_ns;
109
+ const cmd = error.command;
110
+ if (cmd.graph === ns) {
111
+ // this command is for the current graph, handle it
112
+ for (const writer of pregelTask.writers) {
113
+ await writer.invoke(cmd, pregelTask.config);
114
+ }
115
+ break;
116
+ }
117
+ else if (cmd.graph === constants_js_1.Command.PARENT) {
118
+ // this command is for the parent graph, assign it to the parent
119
+ const parent_ns = ns
120
+ .split(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR)
121
+ .slice(0, -1)
122
+ .join(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR);
123
+ error.command = new constants_js_1.Command({
124
+ ...error.command,
125
+ graph: parent_ns,
126
+ });
127
+ }
128
+ }
106
129
  if ((0, errors_js_1.isGraphBubbleUp)(error)) {
107
130
  break;
108
131
  }
@@ -1,4 +1,5 @@
1
- import { getSubgraphsSeenSet, isGraphBubbleUp } from "../errors.js";
1
+ import { CHECKPOINT_NAMESPACE_SEPARATOR, Command } from "../constants.js";
2
+ import { getSubgraphsSeenSet, isGraphBubbleUp, isParentCommand, } from "../errors.js";
2
3
  export const DEFAULT_INITIAL_INTERVAL = 500;
3
4
  export const DEFAULT_BACKOFF_FACTOR = 2;
4
5
  export const DEFAULT_MAX_INTERVAL = 128000;
@@ -99,6 +100,28 @@ pregelTask, retryPolicy) {
99
100
  catch (e) {
100
101
  error = e;
101
102
  error.pregelTaskId = pregelTask.id;
103
+ if (isParentCommand(error)) {
104
+ const ns = pregelTask.config?.configurable?.checkpoint_ns;
105
+ const cmd = error.command;
106
+ if (cmd.graph === ns) {
107
+ // this command is for the current graph, handle it
108
+ for (const writer of pregelTask.writers) {
109
+ await writer.invoke(cmd, pregelTask.config);
110
+ }
111
+ break;
112
+ }
113
+ else if (cmd.graph === Command.PARENT) {
114
+ // this command is for the parent graph, assign it to the parent
115
+ const parent_ns = ns
116
+ .split(CHECKPOINT_NAMESPACE_SEPARATOR)
117
+ .slice(0, -1)
118
+ .join(CHECKPOINT_NAMESPACE_SEPARATOR);
119
+ error.command = new Command({
120
+ ...error.command,
121
+ graph: parent_ns,
122
+ });
123
+ }
124
+ }
102
125
  if (isGraphBubbleUp(error)) {
103
126
  break;
104
127
  }
@@ -111,6 +111,7 @@ export interface PregelExecutableTask<N extends PropertyKey, C extends PropertyK
111
111
  readonly id: string;
112
112
  readonly path?: [string, ...(string | number)[]];
113
113
  readonly subgraphs?: Runnable[];
114
+ readonly writers: Runnable[];
114
115
  }
115
116
  export interface StateSnapshot {
116
117
  /**
@@ -46,13 +46,29 @@ class ChannelWrite extends utils_js_1.RunnableCallable {
46
46
  });
47
47
  this.writes = writes;
48
48
  }
49
- async _getWriteValues(input, config) {
50
- const writes = this.writes
51
- .filter(constants_js_1._isSend)
52
- .map((packet) => {
49
+ async _write(input, config) {
50
+ const writes = this.writes.map((write) => {
51
+ if (_isChannelWriteEntry(write) && _isPassthrough(write.value)) {
52
+ return {
53
+ channel: write.channel,
54
+ value: input,
55
+ skipNone: write.skipNone,
56
+ mapper: write.mapper,
57
+ };
58
+ }
59
+ else {
60
+ return write;
61
+ }
62
+ });
63
+ await ChannelWrite.doWrite(config, writes);
64
+ return input;
65
+ }
66
+ // TODO: Support requireAtLeastOneOf
67
+ static async doWrite(config, writes) {
68
+ const sends = writes.filter(constants_js_1._isSend).map((packet) => {
53
69
  return [constants_js_1.TASKS, packet];
54
70
  });
55
- const entries = this.writes.filter((write) => {
71
+ const entries = writes.filter((write) => {
56
72
  return !(0, constants_js_1._isSend)(write);
57
73
  });
58
74
  const invalidEntry = entries.find((write) => {
@@ -62,16 +78,9 @@ class ChannelWrite extends utils_js_1.RunnableCallable {
62
78
  throw new errors_js_1.InvalidUpdateError(`Cannot write to the reserved channel ${constants_js_1.TASKS}`);
63
79
  }
64
80
  const values = await Promise.all(entries.map(async (write) => {
65
- let value;
66
- if (_isPassthrough(write.value)) {
67
- value = input;
68
- }
69
- else {
70
- value = write.value;
71
- }
72
81
  const mappedValue = write.mapper
73
- ? await write.mapper.invoke(value, config)
74
- : value;
82
+ ? await write.mapper.invoke(write.value, config)
83
+ : write.value;
75
84
  return {
76
85
  ...write,
77
86
  value: mappedValue,
@@ -83,18 +92,9 @@ class ChannelWrite extends utils_js_1.RunnableCallable {
83
92
  return [write.channel, write.value];
84
93
  });
85
94
  });
86
- return [...writes, ...values];
87
- }
88
- async _write(input, config) {
89
- const values = await this._getWriteValues(input, config);
90
- ChannelWrite.doWrite(config, values);
91
- return input;
92
- }
93
- // TODO: Support requireAtLeastOneOf
94
- static doWrite(config, values) {
95
95
  const write = config.configurable?.[constants_js_1.CONFIG_KEY_SEND];
96
96
  const filtered = values.filter(([_, value]) => !_isSkipWrite(value));
97
- write(filtered);
97
+ write([...sends, ...filtered]);
98
98
  }
99
99
  static isWriter(runnable) {
100
100
  return (
@@ -107,3 +107,6 @@ class ChannelWrite extends utils_js_1.RunnableCallable {
107
107
  }
108
108
  }
109
109
  exports.ChannelWrite = ChannelWrite;
110
+ function _isChannelWriteEntry(x) {
111
+ return (x !== undefined && typeof x.channel === "string");
112
+ }
@@ -14,9 +14,8 @@ export declare const PASSTHROUGH: {
14
14
  export declare class ChannelWrite<RunInput = any> extends RunnableCallable {
15
15
  writes: Array<ChannelWriteEntry | Send>;
16
16
  constructor(writes: Array<ChannelWriteEntry | Send>, tags?: string[]);
17
- _getWriteValues(input: unknown, config: RunnableConfig): Promise<[string, unknown][]>;
18
17
  _write(input: unknown, config: RunnableConfig): Promise<unknown>;
19
- static doWrite(config: RunnableConfig, values: [string, unknown][]): void;
18
+ static doWrite(config: RunnableConfig, writes: (ChannelWriteEntry | Send)[]): Promise<void>;
20
19
  static isWriter(runnable: RunnableLike): runnable is ChannelWrite;
21
20
  static registerWriter<T extends Runnable>(runnable: T): T;
22
21
  }
@@ -43,13 +43,29 @@ export class ChannelWrite extends RunnableCallable {
43
43
  });
44
44
  this.writes = writes;
45
45
  }
46
- async _getWriteValues(input, config) {
47
- const writes = this.writes
48
- .filter(_isSend)
49
- .map((packet) => {
46
+ async _write(input, config) {
47
+ const writes = this.writes.map((write) => {
48
+ if (_isChannelWriteEntry(write) && _isPassthrough(write.value)) {
49
+ return {
50
+ channel: write.channel,
51
+ value: input,
52
+ skipNone: write.skipNone,
53
+ mapper: write.mapper,
54
+ };
55
+ }
56
+ else {
57
+ return write;
58
+ }
59
+ });
60
+ await ChannelWrite.doWrite(config, writes);
61
+ return input;
62
+ }
63
+ // TODO: Support requireAtLeastOneOf
64
+ static async doWrite(config, writes) {
65
+ const sends = writes.filter(_isSend).map((packet) => {
50
66
  return [TASKS, packet];
51
67
  });
52
- const entries = this.writes.filter((write) => {
68
+ const entries = writes.filter((write) => {
53
69
  return !_isSend(write);
54
70
  });
55
71
  const invalidEntry = entries.find((write) => {
@@ -59,16 +75,9 @@ export class ChannelWrite extends RunnableCallable {
59
75
  throw new InvalidUpdateError(`Cannot write to the reserved channel ${TASKS}`);
60
76
  }
61
77
  const values = await Promise.all(entries.map(async (write) => {
62
- let value;
63
- if (_isPassthrough(write.value)) {
64
- value = input;
65
- }
66
- else {
67
- value = write.value;
68
- }
69
78
  const mappedValue = write.mapper
70
- ? await write.mapper.invoke(value, config)
71
- : value;
79
+ ? await write.mapper.invoke(write.value, config)
80
+ : write.value;
72
81
  return {
73
82
  ...write,
74
83
  value: mappedValue,
@@ -80,18 +89,9 @@ export class ChannelWrite extends RunnableCallable {
80
89
  return [write.channel, write.value];
81
90
  });
82
91
  });
83
- return [...writes, ...values];
84
- }
85
- async _write(input, config) {
86
- const values = await this._getWriteValues(input, config);
87
- ChannelWrite.doWrite(config, values);
88
- return input;
89
- }
90
- // TODO: Support requireAtLeastOneOf
91
- static doWrite(config, values) {
92
92
  const write = config.configurable?.[CONFIG_KEY_SEND];
93
93
  const filtered = values.filter(([_, value]) => !_isSkipWrite(value));
94
- write(filtered);
94
+ write([...sends, ...filtered]);
95
95
  }
96
96
  static isWriter(runnable) {
97
97
  return (
@@ -103,3 +103,6 @@ export class ChannelWrite extends RunnableCallable {
103
103
  return Object.defineProperty(runnable, IS_WRITER, { value: true });
104
104
  }
105
105
  }
106
+ function _isChannelWriteEntry(x) {
107
+ return (x !== undefined && typeof x.channel === "string");
108
+ }
package/dist/web.d.ts CHANGED
@@ -4,7 +4,7 @@ export * from "./errors.js";
4
4
  export { BaseChannel, type BinaryOperator, BinaryOperatorAggregate, type AnyValue, type WaitForNames, type DynamicBarrierValue, type LastValue, type NamedBarrierValue, type Topic, } from "./channels/index.js";
5
5
  export { type AnnotationRoot as _INTERNAL_ANNOTATION_ROOT } from "./graph/index.js";
6
6
  export { type RetryPolicy } from "./pregel/utils/index.js";
7
- export { Send, Command, type Interrupt } from "./constants.js";
7
+ export { Send, Command, type CommandParams, type Interrupt, } from "./constants.js";
8
8
  export { interrupt } from "./interrupt.js";
9
9
  export { MemorySaver, type Checkpoint, type CheckpointMetadata, type CheckpointTuple, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, type Item, type GetOperation, type SearchOperation, type PutOperation, type Operation, type OperationResults, BaseStore, AsyncBatchedStore, InMemoryStore, type NameSpacePath, type NamespaceMatchType, type MatchCondition, type ListNamespacesOperation, } from "@langchain/langgraph-checkpoint";
10
10
  export * from "./managed/index.js";
package/dist/web.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { END, Graph, START, StateGraph, CompiledStateGraph, MessageGraph, messagesStateReducer, Annotation, } from "./graph/index.js";
2
2
  export * from "./errors.js";
3
3
  export { BaseChannel, BinaryOperatorAggregate, } from "./channels/index.js";
4
- export { Send, Command } from "./constants.js";
4
+ export { Send, Command, } from "./constants.js";
5
5
  export { interrupt } from "./interrupt.js";
6
6
  export { MemorySaver, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, BaseStore, AsyncBatchedStore, InMemoryStore, } from "@langchain/langgraph-checkpoint";
7
7
  export * from "./managed/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph",
3
- "version": "0.2.27",
3
+ "version": "0.2.29",
4
4
  "description": "LangGraph",
5
5
  "type": "module",
6
6
  "engines": {