@langchain/langgraph 0.2.46 → 0.2.47

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.
@@ -18,6 +18,13 @@ export declare function mapInput<C extends PropertyKey>(inputChannels: C | Array
18
18
  export declare function mapOutputValues<C extends PropertyKey>(outputChannels: C | Array<C>, pendingWrites: readonly PendingWrite<C>[] | true, channels: Record<C, BaseChannel>): Generator<Record<string, any>, any>;
19
19
  /**
20
20
  * Map pending writes (a sequence of tuples (channel, value)) to output chunk.
21
+ * @internal
22
+ *
23
+ * @param outputChannels - The channels to output.
24
+ * @param tasks - The tasks to output.
25
+ * @param cached - Whether the output is cached.
26
+ *
27
+ * @returns A generator that yields the output chunk (if any).
21
28
  */
22
- export declare function mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(outputChannels: C | Array<C>, tasks: readonly [PregelExecutableTask<N, C>, PendingWrite<C>[]][], cached?: boolean): Generator<Record<N, Record<string, any> | any>>;
29
+ export declare function mapOutputUpdates<N extends PropertyKey, C extends PropertyKey>(outputChannels: C | Array<C>, tasks: readonly [PregelExecutableTask<N, C>, PendingWrite<C>[]][], cached?: boolean): Generator<Record<N, Record<string, unknown> | unknown>>;
23
30
  export declare function single<T>(iter: IterableIterator<T>): T | null;
package/dist/pregel/io.js CHANGED
@@ -149,10 +149,15 @@ export function* mapOutputValues(outputChannels, pendingWrites, channels
149
149
  }
150
150
  /**
151
151
  * Map pending writes (a sequence of tuples (channel, value)) to output chunk.
152
+ * @internal
153
+ *
154
+ * @param outputChannels - The channels to output.
155
+ * @param tasks - The tasks to output.
156
+ * @param cached - Whether the output is cached.
157
+ *
158
+ * @returns A generator that yields the output chunk (if any).
152
159
  */
153
- export function* mapOutputUpdates(outputChannels, tasks, cached
154
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
- ) {
160
+ export function* mapOutputUpdates(outputChannels, tasks, cached) {
156
161
  const outputTasks = tasks.filter(([task, ww]) => {
157
162
  return ((task.config === undefined || !task.config.tags?.includes(TAG_HIDDEN)) &&
158
163
  ww[0][0] !== ERROR &&
@@ -161,47 +166,67 @@ export function* mapOutputUpdates(outputChannels, tasks, cached
161
166
  if (!outputTasks.length) {
162
167
  return;
163
168
  }
164
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
165
169
  let updated;
166
170
  if (outputTasks.some(([task]) => task.writes.some(([chan, _]) => chan === RETURN))) {
171
+ // TODO: probably should assert that RETURN is the only "non-special" channel (starts with "__")
167
172
  updated = outputTasks.flatMap(([task]) => task.writes
168
173
  .filter(([chan, _]) => chan === RETURN)
169
174
  .map(([_, value]) => [task.name, value]));
170
175
  }
171
176
  else if (!Array.isArray(outputChannels)) {
177
+ // special case where graph state is a single channel (MessageGraph)
178
+ // probably using this in functional API, too
172
179
  updated = outputTasks.flatMap(([task]) => task.writes
173
180
  .filter(([chan, _]) => chan === outputChannels)
174
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
181
  .map(([_, value]) => [task.name, value]));
176
182
  }
177
183
  else {
178
- updated = outputTasks
179
- .filter(([task]) => task.writes.some(([chan]) => outputChannels.includes(chan)))
180
- .map(([task]) => [
181
- task.name,
182
- Object.fromEntries(task.writes.filter(([chan]) => outputChannels.includes(chan))),
183
- ]);
184
- }
185
- const grouped = Object.fromEntries(outputTasks.map(([t]) => [t.name, []])
186
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
- );
184
+ updated = outputTasks.flatMap(([task]) => {
185
+ const { writes } = task;
186
+ const counts = {};
187
+ for (const [chan] of writes) {
188
+ if (outputChannels.includes(chan)) {
189
+ counts[chan] = (counts[chan] || 0) + 1;
190
+ }
191
+ }
192
+ if (Object.values(counts).some((count) => count > 1)) {
193
+ // Multiple writes to the same channel: create separate entries
194
+ return writes
195
+ .filter(([chan]) => outputChannels.includes(chan))
196
+ .map(([chan, value]) => [task.name, { [chan]: value }]);
197
+ }
198
+ else {
199
+ // Single write to each channel: create a single combined entry
200
+ return [
201
+ [
202
+ task.name,
203
+ Object.fromEntries(writes.filter(([chan]) => outputChannels.includes(chan))),
204
+ ],
205
+ ];
206
+ }
207
+ });
208
+ }
209
+ const grouped = {};
188
210
  for (const [node, value] of updated) {
211
+ if (!(node in grouped)) {
212
+ grouped[node] = [];
213
+ }
189
214
  grouped[node].push(value);
190
215
  }
191
- for (const [node, value] of Object.entries(grouped)) {
192
- if (value.length === 0) {
193
- delete grouped[node];
216
+ const flattened = {};
217
+ for (const node in grouped) {
218
+ if (grouped[node].length === 1) {
219
+ const [write] = grouped[node];
220
+ flattened[node] = write;
194
221
  }
195
- else if (value.length === 1) {
196
- // TODO: Fix incorrect cast here
197
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
- grouped[node] = value[0];
222
+ else {
223
+ flattened[node] = grouped[node];
199
224
  }
200
225
  }
201
226
  if (cached) {
202
- grouped["__metadata__"] = { cached };
227
+ flattened["__metadata__"] = { cached };
203
228
  }
204
- yield grouped;
229
+ yield flattened;
205
230
  }
206
231
  export function single(iter) {
207
232
  // eslint-disable-next-line no-unreachable-loop
@@ -527,6 +527,7 @@ class PregelLoop {
527
527
  return true;
528
528
  }
529
529
  async finishAndHandleError(error) {
530
+ this._syncStateOnParentCommand(error);
530
531
  const suppress = this._suppressInterrupt(error);
531
532
  if (suppress || error === undefined) {
532
533
  this.output = (0, io_js_1.readChannels)(this.channels, this.outputKeys);
@@ -751,5 +752,15 @@ class PregelLoop {
751
752
  }
752
753
  }
753
754
  }
755
+ _syncStateOnParentCommand(error) {
756
+ if ((0, errors_js_1.isParentCommand)(error)) {
757
+ const state = Object.entries((0, io_js_1.readChannels)(this.channels, typeof this.outputKeys === "string"
758
+ ? [this.outputKeys]
759
+ : this.outputKeys));
760
+ const update = [...state, ...error.command._updateAsTuples()];
761
+ // eslint-disable-next-line no-param-reassign
762
+ error.command.update = update;
763
+ }
764
+ }
754
765
  }
755
766
  exports.PregelLoop = PregelLoop;
@@ -116,5 +116,6 @@ export declare class PregelLoop {
116
116
  protected _emit(values: [StreamMode, unknown][]): void;
117
117
  protected _putCheckpoint(inputMetadata: Omit<CheckpointMetadata, "step" | "parents">): Promise<void>;
118
118
  protected _matchWrites(tasks: Record<string, PregelExecutableTask<string, string>>): void;
119
+ _syncStateOnParentCommand(error: unknown): void;
119
120
  }
120
121
  export {};
@@ -4,7 +4,7 @@ import { isCommand, CHECKPOINT_NAMESPACE_SEPARATOR, CONFIG_KEY_CHECKPOINT_MAP, C
4
4
  import { _applyWrites, _prepareNextTasks, _prepareSingleTask, increment, shouldInterrupt, } from "./algo.js";
5
5
  import { gatherIterator, gatherIteratorSync, prefixGenerator, } from "../utils.js";
6
6
  import { mapCommand, mapInput, mapOutputUpdates, mapOutputValues, readChannels, } from "./io.js";
7
- import { getSubgraphsSeenSet, EmptyInputError, GraphInterrupt, isGraphInterrupt, MultipleSubgraphsError, } from "../errors.js";
7
+ import { getSubgraphsSeenSet, EmptyInputError, GraphInterrupt, isGraphInterrupt, MultipleSubgraphsError, isParentCommand, } from "../errors.js";
8
8
  import { getNewChannelVersions, patchConfigurable } from "./utils/index.js";
9
9
  import { mapDebugTasks, mapDebugCheckpoint, mapDebugTaskResults, printStepTasks, } from "./debug.js";
10
10
  import { IterableReadableWritableStream } from "./stream.js";
@@ -524,6 +524,7 @@ export class PregelLoop {
524
524
  return true;
525
525
  }
526
526
  async finishAndHandleError(error) {
527
+ this._syncStateOnParentCommand(error);
527
528
  const suppress = this._suppressInterrupt(error);
528
529
  if (suppress || error === undefined) {
529
530
  this.output = readChannels(this.channels, this.outputKeys);
@@ -748,4 +749,14 @@ export class PregelLoop {
748
749
  }
749
750
  }
750
751
  }
752
+ _syncStateOnParentCommand(error) {
753
+ if (isParentCommand(error)) {
754
+ const state = Object.entries(readChannels(this.channels, typeof this.outputKeys === "string"
755
+ ? [this.outputKeys]
756
+ : this.outputKeys));
757
+ const update = [...state, ...error.command._updateAsTuples()];
758
+ // eslint-disable-next-line no-param-reassign
759
+ error.command.update = update;
760
+ }
761
+ }
751
762
  }
@@ -37,7 +37,7 @@ class PregelRunner {
37
37
  */
38
38
  async tick(options = {}) {
39
39
  const { timeout, signal, retryPolicy, onStepWrite } = options;
40
- let graphInterrupt;
40
+ let graphBubbleUp;
41
41
  // Start task execution
42
42
  const pendingTasks = Object.values(this.loop.tasks).filter((t) => t.writes.length === 0);
43
43
  const taskStream = this._executeTasksWithRetry(pendingTasks, {
@@ -46,13 +46,22 @@ class PregelRunner {
46
46
  retryPolicy,
47
47
  });
48
48
  for await (const { task, error } of taskStream) {
49
- graphInterrupt = this._commit(task, error) ?? graphInterrupt;
49
+ this._commit(task, error);
50
+ if ((0, errors_js_1.isGraphInterrupt)(error)) {
51
+ graphBubbleUp = error;
52
+ }
53
+ else if ((0, errors_js_1.isGraphBubbleUp)(error) && !(0, errors_js_1.isGraphInterrupt)(graphBubbleUp)) {
54
+ graphBubbleUp = error;
55
+ }
50
56
  }
51
57
  onStepWrite?.(this.loop.step, Object.values(this.loop.tasks)
52
58
  .map((task) => task.writes)
53
59
  .flat());
54
- if (graphInterrupt) {
55
- throw graphInterrupt;
60
+ if ((0, errors_js_1.isGraphInterrupt)(graphBubbleUp)) {
61
+ throw graphBubbleUp;
62
+ }
63
+ if ((0, errors_js_1.isGraphBubbleUp)(graphBubbleUp) && this.loop.isNested) {
64
+ throw graphBubbleUp;
56
65
  }
57
66
  }
58
67
  /**
@@ -225,35 +234,29 @@ class PregelRunner {
225
234
  *
226
235
  * Throws an error if the error is a {@link GraphBubbleUp} error and {@link PregelLoop}#isNested is true.
227
236
  *
228
- * Note that in the case of a {@link GraphBubbleUp} error that is not a {@link GraphInterrupt}, like a {@link Command}, this method does not apply any writes.
229
- *
230
237
  * @param task - The task to commit.
231
238
  * @param error - The error that occurred, if any.
232
- * @returns The {@link GraphInterrupt} that occurred, if the user's code threw one.
233
239
  */
234
240
  _commit(task, error) {
235
- let graphInterrupt;
236
241
  if (error !== undefined) {
237
- if ((0, errors_js_1.isGraphBubbleUp)(error)) {
238
- if (this.loop.isNested) {
239
- throw error;
240
- }
241
- if ((0, errors_js_1.isGraphInterrupt)(error)) {
242
- graphInterrupt = error;
243
- if (error.interrupts.length) {
244
- const interrupts = error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]);
245
- const resumes = task.writes.filter((w) => w[0] === constants_js_1.RESUME);
246
- if (resumes.length) {
247
- interrupts.push(...resumes);
248
- }
249
- this.loop.putWrites(task.id, interrupts);
242
+ if ((0, errors_js_1.isGraphInterrupt)(error)) {
243
+ if (error.interrupts.length) {
244
+ const interrupts = error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]);
245
+ const resumes = task.writes.filter((w) => w[0] === constants_js_1.RESUME);
246
+ if (resumes.length) {
247
+ interrupts.push(...resumes);
250
248
  }
249
+ this.loop.putWrites(task.id, interrupts);
251
250
  }
252
251
  }
252
+ else if ((0, errors_js_1.isGraphBubbleUp)(error) && task.writes.length) {
253
+ this.loop.putWrites(task.id, task.writes);
254
+ }
253
255
  else {
254
256
  this.loop.putWrites(task.id, [
255
257
  [constants_js_1.ERROR, { message: error.message, name: error.name }],
256
258
  ]);
259
+ // TODO: is throwing here safe? what about commits from other concurrent tasks?
257
260
  throw error;
258
261
  }
259
262
  }
@@ -269,7 +272,6 @@ class PregelRunner {
269
272
  // Save task writes to checkpointer
270
273
  this.loop.putWrites(task.id, task.writes);
271
274
  }
272
- return graphInterrupt;
273
275
  }
274
276
  }
275
277
  exports.PregelRunner = PregelRunner;
@@ -54,11 +54,8 @@ export declare class PregelRunner {
54
54
  *
55
55
  * Throws an error if the error is a {@link GraphBubbleUp} error and {@link PregelLoop}#isNested is true.
56
56
  *
57
- * Note that in the case of a {@link GraphBubbleUp} error that is not a {@link GraphInterrupt}, like a {@link Command}, this method does not apply any writes.
58
- *
59
57
  * @param task - The task to commit.
60
58
  * @param error - The error that occurred, if any.
61
- * @returns The {@link GraphInterrupt} that occurred, if the user's code threw one.
62
59
  */
63
60
  private _commit;
64
61
  }
@@ -1,6 +1,6 @@
1
1
  import { Call } from "./types.js";
2
2
  import { CONFIG_KEY_SEND, CONFIG_KEY_SCRATCHPAD, PUSH, ERROR, INTERRUPT, RESUME, NO_WRITES, TAG_HIDDEN, RETURN, CONFIG_KEY_CALL, } from "../constants.js";
3
- import { isGraphBubbleUp, isGraphInterrupt, } from "../errors.js";
3
+ import { isGraphBubbleUp, isGraphInterrupt } from "../errors.js";
4
4
  import { _runWithRetry } from "./retry.js";
5
5
  /**
6
6
  * Responsible for handling task execution on each tick of the {@link PregelLoop}.
@@ -34,7 +34,7 @@ export class PregelRunner {
34
34
  */
35
35
  async tick(options = {}) {
36
36
  const { timeout, signal, retryPolicy, onStepWrite } = options;
37
- let graphInterrupt;
37
+ let graphBubbleUp;
38
38
  // Start task execution
39
39
  const pendingTasks = Object.values(this.loop.tasks).filter((t) => t.writes.length === 0);
40
40
  const taskStream = this._executeTasksWithRetry(pendingTasks, {
@@ -43,13 +43,22 @@ export class PregelRunner {
43
43
  retryPolicy,
44
44
  });
45
45
  for await (const { task, error } of taskStream) {
46
- graphInterrupt = this._commit(task, error) ?? graphInterrupt;
46
+ this._commit(task, error);
47
+ if (isGraphInterrupt(error)) {
48
+ graphBubbleUp = error;
49
+ }
50
+ else if (isGraphBubbleUp(error) && !isGraphInterrupt(graphBubbleUp)) {
51
+ graphBubbleUp = error;
52
+ }
47
53
  }
48
54
  onStepWrite?.(this.loop.step, Object.values(this.loop.tasks)
49
55
  .map((task) => task.writes)
50
56
  .flat());
51
- if (graphInterrupt) {
52
- throw graphInterrupt;
57
+ if (isGraphInterrupt(graphBubbleUp)) {
58
+ throw graphBubbleUp;
59
+ }
60
+ if (isGraphBubbleUp(graphBubbleUp) && this.loop.isNested) {
61
+ throw graphBubbleUp;
53
62
  }
54
63
  }
55
64
  /**
@@ -222,35 +231,29 @@ export class PregelRunner {
222
231
  *
223
232
  * Throws an error if the error is a {@link GraphBubbleUp} error and {@link PregelLoop}#isNested is true.
224
233
  *
225
- * Note that in the case of a {@link GraphBubbleUp} error that is not a {@link GraphInterrupt}, like a {@link Command}, this method does not apply any writes.
226
- *
227
234
  * @param task - The task to commit.
228
235
  * @param error - The error that occurred, if any.
229
- * @returns The {@link GraphInterrupt} that occurred, if the user's code threw one.
230
236
  */
231
237
  _commit(task, error) {
232
- let graphInterrupt;
233
238
  if (error !== undefined) {
234
- if (isGraphBubbleUp(error)) {
235
- if (this.loop.isNested) {
236
- throw error;
237
- }
238
- if (isGraphInterrupt(error)) {
239
- graphInterrupt = error;
240
- if (error.interrupts.length) {
241
- const interrupts = error.interrupts.map((interrupt) => [INTERRUPT, interrupt]);
242
- const resumes = task.writes.filter((w) => w[0] === RESUME);
243
- if (resumes.length) {
244
- interrupts.push(...resumes);
245
- }
246
- this.loop.putWrites(task.id, interrupts);
239
+ if (isGraphInterrupt(error)) {
240
+ if (error.interrupts.length) {
241
+ const interrupts = error.interrupts.map((interrupt) => [INTERRUPT, interrupt]);
242
+ const resumes = task.writes.filter((w) => w[0] === RESUME);
243
+ if (resumes.length) {
244
+ interrupts.push(...resumes);
247
245
  }
246
+ this.loop.putWrites(task.id, interrupts);
248
247
  }
249
248
  }
249
+ else if (isGraphBubbleUp(error) && task.writes.length) {
250
+ this.loop.putWrites(task.id, task.writes);
251
+ }
250
252
  else {
251
253
  this.loop.putWrites(task.id, [
252
254
  [ERROR, { message: error.message, name: error.name }],
253
255
  ]);
256
+ // TODO: is throwing here safe? what about commits from other concurrent tasks?
254
257
  throw error;
255
258
  }
256
259
  }
@@ -266,6 +269,5 @@ export class PregelRunner {
266
269
  // Save task writes to checkpointer
267
270
  this.loop.putWrites(task.id, task.writes);
268
271
  }
269
- return graphInterrupt;
270
272
  }
271
273
  }
@@ -15,27 +15,112 @@ export type StreamMode = "values" | "updates" | "debug" | "messages" | "custom";
15
15
  export type PregelInputType = any;
16
16
  export type PregelOutputType = any;
17
17
  /**
18
- * Config for executing the graph.
18
+ * Configuration options for executing a Pregel graph.
19
+ * These options control how the graph executes, what data is streamed, and how interrupts are handled.
20
+ *
21
+ * @typeParam Nodes - Mapping of node names to their {@link PregelNode} implementations
22
+ * @typeParam Channels - Mapping of channel names to their {@link BaseChannel} or {@link ManagedValueSpec} implementations
23
+ * @typeParam ConfigurableFieldType - Type of configurable fields in the {@link RunnableConfig} that is passed to the graph
19
24
  */
20
- export interface PregelOptions<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel | ManagedValueSpec>, ConfigurableFieldType extends Record<string, any> = Record<string, any>> extends RunnableConfig<ConfigurableFieldType> {
25
+ export interface PregelOptions<Nodes extends StrRecord<string, PregelNode>, Channels extends StrRecord<string, BaseChannel | ManagedValueSpec>, ConfigurableFieldType extends Record<string, any> = Record<string, any>> extends RunnableConfig<ConfigurableFieldType> {
21
26
  /**
22
- * The stream mode for the graph run. See [Streaming](/langgraphjs/how-tos/#streaming) for more details.
27
+ * Controls what information is streamed during graph execution.
28
+ * Multiple modes can be enabled simultaneously.
29
+ *
30
+ * Supported modes:
31
+ * - "values": Streams complete state after each step
32
+ * - "updates": Streams only state changes after each step
33
+ * - "messages": Streams messages from within nodes
34
+ * - "custom": Streams custom events from within nodes
35
+ * - "debug": Streams detailed execution events for tracing & debugging
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // Stream only values
40
+ * streamMode: "values"
41
+ *
42
+ * // Stream both values and debug info
43
+ * streamMode: ["values", "debug"]
44
+ * ```
45
+ *
23
46
  * @default ["values"]
24
47
  */
25
48
  streamMode?: StreamMode | StreamMode[];
26
- /** The input keys to retrieve from the checkpoint on resume. You generally don't need to set this. */
27
- inputKeys?: keyof Cc | Array<keyof Cc>;
28
- /** The output keys to retrieve from the graph run. */
29
- outputKeys?: keyof Cc | Array<keyof Cc>;
30
- /** The nodes to interrupt the graph run before. */
31
- interruptBefore?: All | Array<keyof Nn>;
32
- /** The nodes to interrupt the graph run after. */
33
- interruptAfter?: All | Array<keyof Nn>;
34
- /** Enable debug mode for the graph run. */
49
+ /**
50
+ * Specifies which channel keys to retrieve from the checkpoint when resuming execution.
51
+ * This is an advanced option that you generally don't need to set manually.
52
+ * The graph will automatically determine the appropriate input keys based on its configuration.
53
+ */
54
+ inputKeys?: keyof Channels | Array<keyof Channels>;
55
+ /**
56
+ * Specifies which channel keys to include in the output stream and final result.
57
+ * Use this to filter which parts of the graph state you want to observe.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // Stream only the 'result' channel
62
+ * outputKeys: "result"
63
+ *
64
+ * // Stream multiple channels
65
+ * outputKeys: ["result", "intermediateState"]
66
+ * ```
67
+ */
68
+ outputKeys?: keyof Channels | Array<keyof Channels>;
69
+ /**
70
+ * List of nodes where execution should be interrupted BEFORE the node runs.
71
+ * Can be used for debugging and advanced state manipulation use cases. For
72
+ * human-in-the-loop workflows, developers should prefer the
73
+ * @link {interrupt} function instead.
74
+ *
75
+ * When interrupted, a resume @link {Command} must be provided to continue
76
+ * execution.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * // Interrupt before specific nodes
81
+ * interruptBefore: ["humanReview", "qualityCheck"]
82
+ *
83
+ * // Interrupt before all nodes
84
+ * interruptBefore: "all"
85
+ * ```
86
+ */
87
+ interruptBefore?: All | Array<keyof Nodes>;
88
+ /**
89
+ * List of nodes where execution should be interrupted AFTER the node runs.
90
+ * Similar to interruptBefore, but interrupts after node completion.
91
+ * Useful when the node's output needs to be reviewed before proceeding.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Interrupt after specific nodes
96
+ * interruptAfter: ["generateContent", "analyze"]
97
+ *
98
+ * // Interrupt after all nodes
99
+ * interruptAfter: "all"
100
+ * ```
101
+ */
102
+ interruptAfter?: All | Array<keyof Nodes>;
103
+ /**
104
+ * Enables detailed debug logging during graph execution.
105
+ * When enabled, prints information about:
106
+ * - Task execution
107
+ * - Channel updates
108
+ * - Checkpoint writes
109
+ *
110
+ * @default false
111
+ */
35
112
  debug?: boolean;
36
- /** Whether to stream subgraphs. */
113
+ /**
114
+ * Whether to include subgraph execution details in the stream.
115
+ * When true, state updates from nested graphs will also be streamed.
116
+ *
117
+ * @default false
118
+ */
37
119
  subgraphs?: boolean;
38
- /** The shared value store */
120
+ /**
121
+ * A shared value store that allows you to store and retrieve state across
122
+ * threads. Useful for implementing long-term memory patterns.
123
+ */
39
124
  store?: BaseStore;
40
125
  }
41
126
  /**
@@ -44,9 +129,9 @@ export interface PregelOptions<Nn extends StrRecord<string, PregelNode>, Cc exte
44
129
  type StrRecord<K extends string, T> = {
45
130
  [P in K]: T;
46
131
  };
47
- export interface PregelInterface<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel | ManagedValueSpec>, ConfigurableFieldType extends Record<string, any> = StrRecord<string, any>> {
132
+ export interface PregelInterface<Nodes extends StrRecord<string, PregelNode>, Channels extends StrRecord<string, BaseChannel | ManagedValueSpec>, ConfigurableFieldType extends Record<string, any> = StrRecord<string, any>> {
48
133
  lg_is_pregel: boolean;
49
- withConfig(config: RunnableConfig): PregelInterface<Nn, Cc>;
134
+ withConfig(config: RunnableConfig): PregelInterface<Nodes, Channels>;
50
135
  getGraphAsync(config: RunnableConfig & {
51
136
  xray?: boolean | number;
52
137
  }): Promise<DrawableGraph>;
@@ -57,15 +142,15 @@ export interface PregelInterface<Nn extends StrRecord<string, PregelNode>, Cc ex
57
142
  subgraphs?: boolean;
58
143
  }): Promise<StateSnapshot>;
59
144
  getStateHistory(config: RunnableConfig, options?: CheckpointListOptions): AsyncIterableIterator<StateSnapshot>;
60
- updateState(inputConfig: LangGraphRunnableConfig, values: Record<string, unknown> | unknown, asNode?: keyof Nn | string): Promise<RunnableConfig>;
61
- stream(input: PregelInputType, options?: Partial<PregelOptions<Nn, Cc, ConfigurableFieldType>>): Promise<IterableReadableStream<PregelOutputType>>;
62
- invoke(input: PregelInputType, options?: Partial<PregelOptions<Nn, Cc, ConfigurableFieldType>>): Promise<PregelOutputType>;
145
+ updateState(inputConfig: LangGraphRunnableConfig, values: Record<string, unknown> | unknown, asNode?: keyof Nodes | string): Promise<RunnableConfig>;
146
+ stream(input: PregelInputType, options?: Partial<PregelOptions<Nodes, Channels, ConfigurableFieldType>>): Promise<IterableReadableStream<PregelOutputType>>;
147
+ invoke(input: PregelInputType, options?: Partial<PregelOptions<Nodes, Channels, ConfigurableFieldType>>): Promise<PregelOutputType>;
63
148
  }
64
149
  /**
65
150
  * Parameters for creating a Pregel graph.
66
151
  * @internal
67
152
  */
68
- export type PregelParams<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel | ManagedValueSpec>> = {
153
+ export type PregelParams<Nodes extends StrRecord<string, PregelNode>, Channels extends StrRecord<string, BaseChannel | ManagedValueSpec>> = {
69
154
  /**
70
155
  * The name of the graph. @see {@link Runnable.name}
71
156
  */
@@ -73,11 +158,11 @@ export type PregelParams<Nn extends StrRecord<string, PregelNode>, Cc extends St
73
158
  /**
74
159
  * The nodes in the graph.
75
160
  */
76
- nodes: Nn;
161
+ nodes: Nodes;
77
162
  /**
78
163
  * The channels in the graph.
79
164
  */
80
- channels: Cc;
165
+ channels: Channels;
81
166
  /**
82
167
  * Whether to validate the graph.
83
168
  *
@@ -93,26 +178,26 @@ export type PregelParams<Nn extends StrRecord<string, PregelNode>, Cc extends St
93
178
  /**
94
179
  * The input channels for the graph run.
95
180
  */
96
- inputChannels: keyof Cc | Array<keyof Cc>;
181
+ inputChannels: keyof Channels | Array<keyof Channels>;
97
182
  /**
98
183
  * The output channels for the graph run.
99
184
  */
100
- outputChannels: keyof Cc | Array<keyof Cc>;
185
+ outputChannels: keyof Channels | Array<keyof Channels>;
101
186
  /**
102
187
  * After processing one of the nodes named in this list, the graph will be interrupted and a resume {@link Command} must be provided to proceed with the execution of this thread.
103
188
  * @default []
104
189
  */
105
- interruptAfter?: Array<keyof Nn> | All;
190
+ interruptAfter?: Array<keyof Nodes> | All;
106
191
  /**
107
192
  * Before processing one of the nodes named in this list, the graph will be interrupted and a resume {@link Command} must be provided to proceed with the execution of this thread.
108
193
  * @default []
109
194
  */
110
- interruptBefore?: Array<keyof Nn> | All;
195
+ interruptBefore?: Array<keyof Nodes> | All;
111
196
  /**
112
197
  * The channels to stream from the graph run.
113
198
  * @default []
114
199
  */
115
- streamChannels?: keyof Cc | Array<keyof Cc>;
200
+ streamChannels?: keyof Channels | Array<keyof Channels>;
116
201
  /**
117
202
  * @default undefined
118
203
  */
@@ -146,11 +231,11 @@ export interface PregelTaskDescription {
146
231
  readonly state?: LangGraphRunnableConfig | StateSnapshot;
147
232
  readonly path?: TaskPath;
148
233
  }
149
- export interface PregelExecutableTask<N extends PropertyKey, C extends PropertyKey> {
150
- readonly name: N;
234
+ export interface PregelExecutableTask<NodeKey extends PropertyKey, ChannelKey extends PropertyKey> {
235
+ readonly name: NodeKey;
151
236
  readonly input: unknown;
152
237
  readonly proc: Runnable<any, any, LangGraphRunnableConfig>;
153
- readonly writes: PendingWrite<C>[];
238
+ readonly writes: PendingWrite<ChannelKey>[];
154
239
  readonly config?: LangGraphRunnableConfig;
155
240
  readonly triggers: Array<string>;
156
241
  readonly retry_policy?: RetryPolicy;
@@ -190,6 +275,45 @@ export interface StateSnapshot {
190
275
  */
191
276
  readonly tasks: PregelTaskDescription[];
192
277
  }
278
+ /**
279
+ * Options for subscribing to multiple channels.
280
+ */
281
+ export type MultipleChannelSubscriptionOptions = {
282
+ /**
283
+ * Optional tags to associate with the subscription.
284
+ */
285
+ tags?: string[];
286
+ };
287
+ /**
288
+ * Options for subscribing to a single channel.
289
+ */
290
+ export type SingleChannelSubscriptionOptions = {
291
+ /**
292
+ * When specified, the channel mapping will be an object with this key pointing
293
+ * to the array of channels to subscribe to. Otherwise, the channel mapping
294
+ * will be an array of channels.
295
+ */
296
+ key?: string;
297
+ /**
298
+ * Optional tags to associate with the subscription.
299
+ */
300
+ tags?: string[];
301
+ };
302
+ /**
303
+ * Options for getting the state of the graph.
304
+ */
305
+ export type GetStateOptions = {
306
+ /**
307
+ * Whether to include subgraph states.
308
+ * @default false
309
+ */
310
+ subgraphs?: boolean;
311
+ };
312
+ /**
313
+ * Used for storing/retrieving internal execution state.
314
+ *
315
+ * @internal
316
+ */
193
317
  export type PregelScratchpad<Resume = unknown> = {
194
318
  /** Counter for tracking call invocations */
195
319
  callCounter: number;
package/dist/web.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { Graph, type StateGraphArgs, StateGraph, CompiledStateGraph, MessageGraph, messagesStateReducer, messagesStateReducer as addMessages, type Messages, Annotation, type StateType, type UpdateType, type NodeType, type StateDefinition, type SingleReducer, type CompiledGraph, } from "./graph/index.js";
2
- export type { StateSnapshot, StreamMode, PregelParams, PregelOptions, } from "./pregel/types.js";
2
+ export type { StateSnapshot, StreamMode, PregelParams, PregelOptions, SingleChannelSubscriptionOptions, MultipleChannelSubscriptionOptions, GetStateOptions, } from "./pregel/types.js";
3
3
  export type { PregelNode } from "./pregel/read.js";
4
4
  export type { Pregel } from "./pregel/index.js";
5
5
  export * from "./errors.js";