@langchain/langgraph 0.2.27 → 0.2.28

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.
@@ -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));
@@ -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.28",
4
4
  "description": "LangGraph",
5
5
  "type": "module",
6
6
  "engines": {