@langchain/langgraph 0.2.41 → 0.2.43-rc.0

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.
Files changed (86) hide show
  1. package/README.md +237 -154
  2. package/dist/channels/any_value.cjs +10 -10
  3. package/dist/channels/any_value.d.ts +1 -1
  4. package/dist/channels/any_value.js +10 -10
  5. package/dist/channels/ephemeral_value.cjs +10 -9
  6. package/dist/channels/ephemeral_value.d.ts +1 -1
  7. package/dist/channels/ephemeral_value.js +10 -9
  8. package/dist/channels/last_value.cjs +8 -7
  9. package/dist/channels/last_value.d.ts +1 -1
  10. package/dist/channels/last_value.js +8 -7
  11. package/dist/constants.cjs +33 -6
  12. package/dist/constants.d.ts +17 -2
  13. package/dist/constants.js +32 -5
  14. package/dist/errors.d.ts +3 -3
  15. package/dist/func/index.cjs +272 -0
  16. package/dist/func/index.d.ts +310 -0
  17. package/dist/func/index.js +267 -0
  18. package/dist/func/types.cjs +15 -0
  19. package/dist/func/types.d.ts +59 -0
  20. package/dist/func/types.js +11 -0
  21. package/dist/graph/graph.cjs +31 -35
  22. package/dist/graph/graph.d.ts +1 -5
  23. package/dist/graph/graph.js +1 -5
  24. package/dist/graph/index.cjs +1 -3
  25. package/dist/graph/index.d.ts +1 -1
  26. package/dist/graph/index.js +1 -1
  27. package/dist/graph/message.d.ts +1 -1
  28. package/dist/graph/state.cjs +17 -17
  29. package/dist/graph/state.d.ts +2 -1
  30. package/dist/graph/state.js +2 -2
  31. package/dist/index.cjs +8 -0
  32. package/dist/index.d.ts +3 -0
  33. package/dist/index.js +3 -0
  34. package/dist/interrupt.cjs +21 -34
  35. package/dist/interrupt.d.ts +1 -1
  36. package/dist/interrupt.js +22 -35
  37. package/dist/prebuilt/agent_executor.cjs +3 -3
  38. package/dist/prebuilt/agent_executor.d.ts +1 -1
  39. package/dist/prebuilt/agent_executor.js +1 -1
  40. package/dist/prebuilt/chat_agent_executor.cjs +3 -3
  41. package/dist/prebuilt/chat_agent_executor.d.ts +1 -1
  42. package/dist/prebuilt/chat_agent_executor.js +1 -1
  43. package/dist/prebuilt/react_agent_executor.cjs +33 -8
  44. package/dist/prebuilt/react_agent_executor.d.ts +4 -1
  45. package/dist/prebuilt/react_agent_executor.js +31 -6
  46. package/dist/prebuilt/tool_node.cjs +1 -2
  47. package/dist/prebuilt/tool_node.d.ts +1 -1
  48. package/dist/prebuilt/tool_node.js +1 -2
  49. package/dist/pregel/algo.cjs +121 -12
  50. package/dist/pregel/algo.d.ts +8 -6
  51. package/dist/pregel/algo.js +122 -13
  52. package/dist/pregel/call.cjs +77 -0
  53. package/dist/pregel/call.d.ts +15 -0
  54. package/dist/pregel/call.js +71 -0
  55. package/dist/pregel/index.cjs +59 -96
  56. package/dist/pregel/index.d.ts +1 -10
  57. package/dist/pregel/index.js +61 -98
  58. package/dist/pregel/io.cjs +6 -1
  59. package/dist/pregel/io.js +7 -2
  60. package/dist/pregel/loop.cjs +109 -75
  61. package/dist/pregel/loop.d.ts +17 -23
  62. package/dist/pregel/loop.js +110 -75
  63. package/dist/pregel/messages.d.ts +1 -1
  64. package/dist/pregel/retry.cjs +22 -50
  65. package/dist/pregel/retry.d.ts +6 -6
  66. package/dist/pregel/retry.js +22 -50
  67. package/dist/pregel/runner.cjs +275 -0
  68. package/dist/pregel/runner.d.ts +64 -0
  69. package/dist/pregel/runner.js +271 -0
  70. package/dist/pregel/stream.cjs +71 -0
  71. package/dist/pregel/stream.d.ts +17 -0
  72. package/dist/pregel/stream.js +67 -0
  73. package/dist/pregel/types.cjs +54 -0
  74. package/dist/pregel/types.d.ts +78 -6
  75. package/dist/pregel/types.js +51 -1
  76. package/dist/pregel/utils/config.cjs +26 -1
  77. package/dist/pregel/utils/config.d.ts +14 -0
  78. package/dist/pregel/utils/config.js +22 -0
  79. package/dist/pregel/write.d.ts +1 -1
  80. package/dist/utils.cjs +15 -1
  81. package/dist/utils.d.ts +3 -1
  82. package/dist/utils.js +12 -0
  83. package/dist/web.cjs +7 -5
  84. package/dist/web.d.ts +4 -4
  85. package/dist/web.js +3 -3
  86. package/package.json +8 -8
@@ -0,0 +1,310 @@
1
+ import { BaseCheckpointSaver, BaseStore } from "@langchain/langgraph-checkpoint";
2
+ import { Pregel } from "../pregel/index.js";
3
+ import { PregelNode } from "../pregel/read.js";
4
+ import { END, PREVIOUS, START } from "../constants.js";
5
+ import { EphemeralValue } from "../channels/ephemeral_value.js";
6
+ import { RetryPolicy } from "../pregel/utils/index.js";
7
+ import { LastValue } from "../channels/last_value.js";
8
+ import { EntrypointFinal, EntrypointReturnT, EntrypointFinalSaveT, EntrypointFunc, TaskFunc } from "./types.js";
9
+ /**
10
+ * Options for the {@link task} function
11
+ *
12
+ * !!! warning "Beta"
13
+ * The Functional API is currently in beta and is subject to change.
14
+ *
15
+ * @beta
16
+ */
17
+ export type TaskOptions = {
18
+ /**
19
+ * The name of the task, analogous to the node name in {@link StateGraph}.
20
+ *
21
+ * @beta
22
+ */
23
+ name: string;
24
+ /**
25
+ * The retry policy for the task. Configures how many times and under what conditions
26
+ * the task should be retried if it fails.
27
+ *
28
+ * @beta
29
+ */
30
+ retry?: RetryPolicy;
31
+ };
32
+ /**
33
+ * Define a LangGraph task using the `task` function.
34
+ *
35
+ * !!! warning "Beta"
36
+ * The Functional API is currently in beta and is subject to change.
37
+ *
38
+ * @beta
39
+ *
40
+ * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.
41
+ * A task can be called like a regular function with the following differences:
42
+ *
43
+ * - When a checkpointer is enabled, the function inputs and outputs must be serializable.
44
+ * - The wrapped function can only be called from within an entrypoint or StateGraph.
45
+ * - Calling the function produces a promise. This makes it easy to parallelize tasks.
46
+ *
47
+ * @typeParam ArgsT - The type of arguments the task function accepts
48
+ * @typeParam OutputT - The type of value the task function returns
49
+ * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task
50
+ * @param func - The function that executes this task
51
+ * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise
52
+ *
53
+ * @example basic example
54
+ * ```typescript
55
+ * const addOne = task("add", async (a: number) => a + 1);
56
+ *
57
+ * const workflow = entrypoint("example", async (numbers: number[]) => {
58
+ * const promises = numbers.map(n => addOne(n));
59
+ * const results = await Promise.all(promises);
60
+ * return results;
61
+ * });
62
+ *
63
+ * // Call the entrypoint
64
+ * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]
65
+ * ```
66
+ *
67
+ * @example using a retry policy
68
+ * ```typescript
69
+ * const addOne = task({
70
+ * name: "add",
71
+ * retry: { maxAttempts: 3 }
72
+ * },
73
+ * async (a: number) => a + 1
74
+ * );
75
+ *
76
+ * const workflow = entrypoint("example", async (numbers: number[]) => {
77
+ * const promises = numbers.map(n => addOne(n));
78
+ * const results = await Promise.all(promises);
79
+ * return results;
80
+ * });
81
+ * ```
82
+ */
83
+ export declare function task<ArgsT extends unknown[], OutputT>(optionsOrName: TaskOptions | string, func: TaskFunc<ArgsT, OutputT>): (...args: ArgsT) => Promise<OutputT>;
84
+ /**
85
+ * Options for the {@link entrypoint} function
86
+ *
87
+ * !!! warning "Beta"
88
+ * The Functional API is currently in beta and is subject to change.
89
+ *
90
+ * @beta
91
+ */
92
+ export type EntrypointOptions = {
93
+ /**
94
+ * The name of the {@link entrypoint}, analogous to the node name in {@link StateGraph}.
95
+ * This name is used for logging, debugging, and checkpoint identification.
96
+ *
97
+ * @beta
98
+ */
99
+ name: string;
100
+ /**
101
+ * The checkpointer for the {@link entrypoint}. Used to save and restore state between
102
+ * invocations of the workflow.
103
+ *
104
+ * @beta
105
+ */
106
+ checkpointer?: BaseCheckpointSaver;
107
+ /**
108
+ * The store for the {@link entrypoint}. Used to persist data across workflow runs.
109
+ *
110
+ * @beta
111
+ */
112
+ store?: BaseStore;
113
+ };
114
+ /**
115
+ * Type declaration for the entrypoint function with its properties
116
+ */
117
+ export interface EntrypointFunction {
118
+ <InputT, OutputT>(optionsOrName: EntrypointOptions | string, func: EntrypointFunc<InputT, OutputT>): Pregel<Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>, {
119
+ [START]: EphemeralValue<InputT>;
120
+ [END]: LastValue<EntrypointReturnT<OutputT>>;
121
+ [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;
122
+ }, Record<string, unknown>, InputT, EntrypointReturnT<OutputT>>;
123
+ /**
124
+ * A helper utility for use with the functional API that returns a value to the caller,
125
+ * as well as a separate state value to persist to the checkpoint. This allows workflows
126
+ * to maintain state between runs while returning different values to the caller.
127
+ *
128
+ * !!! warning "Beta"
129
+ * The Functional API is currently in beta and is subject to change.
130
+ *
131
+ * @beta
132
+ *
133
+ * @typeParam ValueT - The type of the value to return to the caller
134
+ * @typeParam SaveT - The type of the state to save to the checkpoint
135
+ * @param value - The value to return to the caller
136
+ * @param save - The value to save to the checkpoint
137
+ * @returns An object with the value and save properties
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * return entrypoint.final({
142
+ * value: "result for caller",
143
+ * save: { counter: currentCount + 1 }
144
+ * });
145
+ * ```
146
+ */
147
+ final<ValueT, SaveT>(options: {
148
+ value?: ValueT;
149
+ save?: SaveT;
150
+ }): EntrypointFinal<ValueT, SaveT>;
151
+ }
152
+ /**
153
+ * Define a LangGraph workflow using the `entrypoint` function.
154
+ *
155
+ * !!! warning "Beta"
156
+ * The Functional API is currently in beta and is subject to change.
157
+ *
158
+ * @beta
159
+ *
160
+ * ### Function signature
161
+ *
162
+ * The wrapped function must accept at most **two parameters**. The first parameter
163
+ * is the input to the function. The second (optional) parameter is a
164
+ * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to
165
+ * the function, you can pass them as an object.
166
+ *
167
+ * ### Helper functions
168
+ *
169
+ * #### Streaming
170
+ * To write data to the "custom" stream, use the {@link getWriter} function, or the
171
+ * {@link LangGraphRunnableConfig.writer} property.
172
+ *
173
+ * #### State management
174
+ * The {@link getPreviousState} function can be used to access the previous state
175
+ * that was returned from the last invocation of the entrypoint on the same thread id.
176
+ *
177
+ * If you wish to save state other than the return value, you can use the
178
+ * {@link entrypoint.final} function.
179
+ *
180
+ * @typeParam InputT - The type of input the entrypoint accepts
181
+ * @typeParam OutputT - The type of output the entrypoint produces
182
+ * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint
183
+ * @param func - The function that executes this entrypoint
184
+ * @returns A {@link Pregel} instance that can be run to execute the workflow
185
+ *
186
+ * @example Using entrypoint and tasks
187
+ * ```typescript
188
+ * import { task, entrypoint } from "@langchain/langgraph";
189
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
190
+ * import { interrupt, Command } from "@langchain/langgraph";
191
+ *
192
+ * const composeEssay = task("compose", async (topic: string) => {
193
+ * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation
194
+ * return `An essay about ${topic}`;
195
+ * });
196
+ *
197
+ * const reviewWorkflow = entrypoint({
198
+ * name: "review",
199
+ * checkpointer: new MemorySaver()
200
+ * }, async (topic: string) => {
201
+ * const essay = await composeEssay(topic);
202
+ * const humanReview = await interrupt({
203
+ * question: "Please provide a review",
204
+ * essay
205
+ * });
206
+ * return {
207
+ * essay,
208
+ * review: humanReview
209
+ * };
210
+ * });
211
+ *
212
+ * // Example configuration for the workflow
213
+ * const config = {
214
+ * configurable: {
215
+ * thread_id: "some_thread"
216
+ * }
217
+ * };
218
+ *
219
+ * // Topic for the essay
220
+ * const topic = "cats";
221
+ *
222
+ * // Stream the workflow to generate the essay and await human review
223
+ * for await (const result of reviewWorkflow.stream(topic, config)) {
224
+ * console.log(result);
225
+ * }
226
+ *
227
+ * // Example human review provided after the interrupt
228
+ * const humanReview = "This essay is great.";
229
+ *
230
+ * // Resume the workflow with the provided human review
231
+ * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {
232
+ * console.log(result);
233
+ * }
234
+ * ```
235
+ *
236
+ * @example Accessing the previous return value
237
+ * ```typescript
238
+ * import { entrypoint, getPreviousState } from "@langchain/langgraph";
239
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
240
+ *
241
+ * const accumulator = entrypoint({
242
+ * name: "accumulator",
243
+ * checkpointer: new MemorySaver()
244
+ * }, async (input: string) => {
245
+ * const previous = getPreviousState<number>();
246
+ * return previous !== undefined ? `${previous } ${input}` : input;
247
+ * });
248
+ *
249
+ * const config = {
250
+ * configurable: {
251
+ * thread_id: "some_thread"
252
+ * }
253
+ * };
254
+ * await accumulator.invoke("hello", config); // returns "hello"
255
+ * await accumulator.invoke("world", config); // returns "hello world"
256
+ * ```
257
+ *
258
+ * @example Using entrypoint.final to save a value
259
+ * ```typescript
260
+ * import { entrypoint, getPreviousState } from "@langchain/langgraph";
261
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
262
+ *
263
+ * const myWorkflow = entrypoint({
264
+ * name: "accumulator",
265
+ * checkpointer: new MemorySaver()
266
+ * }, async (num: number) => {
267
+ * const previous = getPreviousState<number>();
268
+ *
269
+ * // This will return the previous value to the caller, saving
270
+ * // 2 * num to the checkpoint, which will be used in the next invocation
271
+ * // for the `previous` parameter.
272
+ * return entrypoint.final({
273
+ * value: previous ?? 0,
274
+ * save: 2 * num
275
+ * });
276
+ * });
277
+ *
278
+ * const config = {
279
+ * configurable: {
280
+ * thread_id: "some_thread"
281
+ * }
282
+ * };
283
+ *
284
+ * await myWorkflow.invoke(3, config); // 0 (previous was undefined)
285
+ * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)
286
+ * ```
287
+ */
288
+ export declare const entrypoint: EntrypointFunction;
289
+ /**
290
+ * A helper utility function for use with the functional API that returns the previous
291
+ * state from the checkpoint from the last invocation of the current thread.
292
+ *
293
+ * This function allows workflows to access state that was saved in previous runs
294
+ * using {@link entrypoint.final}.
295
+ *
296
+ * !!! warning "Beta"
297
+ * The Functional API is currently in beta and is subject to change.
298
+ *
299
+ * @beta
300
+ *
301
+ * @typeParam StateT - The type of the state that was previously saved
302
+ * @returns The previous saved state from the last invocation of the current thread
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * const previousState = getPreviousState<{ counter: number }>();
307
+ * const newCount = (previousState?.counter ?? 0) + 1;
308
+ * ```
309
+ */
310
+ export declare function getPreviousState<StateT>(): StateT;
@@ -0,0 +1,267 @@
1
+ import { AsyncLocalStorageProviderSingleton } from "@langchain/core/singletons";
2
+ import { Pregel } from "../pregel/index.js";
3
+ import { PregelNode } from "../pregel/read.js";
4
+ import { CONFIG_KEY_PREVIOUS_STATE, END, PREVIOUS, START, } from "../constants.js";
5
+ import { EphemeralValue } from "../channels/ephemeral_value.js";
6
+ import { call, getRunnableForEntrypoint } from "../pregel/call.js";
7
+ import { LastValue } from "../channels/last_value.js";
8
+ import { isAsyncGeneratorFunction, isGeneratorFunction } from "../utils.js";
9
+ /**
10
+ * Define a LangGraph task using the `task` function.
11
+ *
12
+ * !!! warning "Beta"
13
+ * The Functional API is currently in beta and is subject to change.
14
+ *
15
+ * @beta
16
+ *
17
+ * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.
18
+ * A task can be called like a regular function with the following differences:
19
+ *
20
+ * - When a checkpointer is enabled, the function inputs and outputs must be serializable.
21
+ * - The wrapped function can only be called from within an entrypoint or StateGraph.
22
+ * - Calling the function produces a promise. This makes it easy to parallelize tasks.
23
+ *
24
+ * @typeParam ArgsT - The type of arguments the task function accepts
25
+ * @typeParam OutputT - The type of value the task function returns
26
+ * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task
27
+ * @param func - The function that executes this task
28
+ * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise
29
+ *
30
+ * @example basic example
31
+ * ```typescript
32
+ * const addOne = task("add", async (a: number) => a + 1);
33
+ *
34
+ * const workflow = entrypoint("example", async (numbers: number[]) => {
35
+ * const promises = numbers.map(n => addOne(n));
36
+ * const results = await Promise.all(promises);
37
+ * return results;
38
+ * });
39
+ *
40
+ * // Call the entrypoint
41
+ * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]
42
+ * ```
43
+ *
44
+ * @example using a retry policy
45
+ * ```typescript
46
+ * const addOne = task({
47
+ * name: "add",
48
+ * retry: { maxAttempts: 3 }
49
+ * },
50
+ * async (a: number) => a + 1
51
+ * );
52
+ *
53
+ * const workflow = entrypoint("example", async (numbers: number[]) => {
54
+ * const promises = numbers.map(n => addOne(n));
55
+ * const results = await Promise.all(promises);
56
+ * return results;
57
+ * });
58
+ * ```
59
+ */
60
+ export function task(optionsOrName, func) {
61
+ const { name, retry } = typeof optionsOrName === "string"
62
+ ? { name: optionsOrName, retry: undefined }
63
+ : optionsOrName;
64
+ if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {
65
+ throw new Error("Generators are disallowed as tasks. For streaming responses, use config.write.");
66
+ }
67
+ return (...args) => {
68
+ return call({ func, name, retry }, ...args);
69
+ };
70
+ }
71
+ /**
72
+ * Define a LangGraph workflow using the `entrypoint` function.
73
+ *
74
+ * !!! warning "Beta"
75
+ * The Functional API is currently in beta and is subject to change.
76
+ *
77
+ * @beta
78
+ *
79
+ * ### Function signature
80
+ *
81
+ * The wrapped function must accept at most **two parameters**. The first parameter
82
+ * is the input to the function. The second (optional) parameter is a
83
+ * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to
84
+ * the function, you can pass them as an object.
85
+ *
86
+ * ### Helper functions
87
+ *
88
+ * #### Streaming
89
+ * To write data to the "custom" stream, use the {@link getWriter} function, or the
90
+ * {@link LangGraphRunnableConfig.writer} property.
91
+ *
92
+ * #### State management
93
+ * The {@link getPreviousState} function can be used to access the previous state
94
+ * that was returned from the last invocation of the entrypoint on the same thread id.
95
+ *
96
+ * If you wish to save state other than the return value, you can use the
97
+ * {@link entrypoint.final} function.
98
+ *
99
+ * @typeParam InputT - The type of input the entrypoint accepts
100
+ * @typeParam OutputT - The type of output the entrypoint produces
101
+ * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint
102
+ * @param func - The function that executes this entrypoint
103
+ * @returns A {@link Pregel} instance that can be run to execute the workflow
104
+ *
105
+ * @example Using entrypoint and tasks
106
+ * ```typescript
107
+ * import { task, entrypoint } from "@langchain/langgraph";
108
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
109
+ * import { interrupt, Command } from "@langchain/langgraph";
110
+ *
111
+ * const composeEssay = task("compose", async (topic: string) => {
112
+ * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation
113
+ * return `An essay about ${topic}`;
114
+ * });
115
+ *
116
+ * const reviewWorkflow = entrypoint({
117
+ * name: "review",
118
+ * checkpointer: new MemorySaver()
119
+ * }, async (topic: string) => {
120
+ * const essay = await composeEssay(topic);
121
+ * const humanReview = await interrupt({
122
+ * question: "Please provide a review",
123
+ * essay
124
+ * });
125
+ * return {
126
+ * essay,
127
+ * review: humanReview
128
+ * };
129
+ * });
130
+ *
131
+ * // Example configuration for the workflow
132
+ * const config = {
133
+ * configurable: {
134
+ * thread_id: "some_thread"
135
+ * }
136
+ * };
137
+ *
138
+ * // Topic for the essay
139
+ * const topic = "cats";
140
+ *
141
+ * // Stream the workflow to generate the essay and await human review
142
+ * for await (const result of reviewWorkflow.stream(topic, config)) {
143
+ * console.log(result);
144
+ * }
145
+ *
146
+ * // Example human review provided after the interrupt
147
+ * const humanReview = "This essay is great.";
148
+ *
149
+ * // Resume the workflow with the provided human review
150
+ * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {
151
+ * console.log(result);
152
+ * }
153
+ * ```
154
+ *
155
+ * @example Accessing the previous return value
156
+ * ```typescript
157
+ * import { entrypoint, getPreviousState } from "@langchain/langgraph";
158
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
159
+ *
160
+ * const accumulator = entrypoint({
161
+ * name: "accumulator",
162
+ * checkpointer: new MemorySaver()
163
+ * }, async (input: string) => {
164
+ * const previous = getPreviousState<number>();
165
+ * return previous !== undefined ? `${previous } ${input}` : input;
166
+ * });
167
+ *
168
+ * const config = {
169
+ * configurable: {
170
+ * thread_id: "some_thread"
171
+ * }
172
+ * };
173
+ * await accumulator.invoke("hello", config); // returns "hello"
174
+ * await accumulator.invoke("world", config); // returns "hello world"
175
+ * ```
176
+ *
177
+ * @example Using entrypoint.final to save a value
178
+ * ```typescript
179
+ * import { entrypoint, getPreviousState } from "@langchain/langgraph";
180
+ * import { MemorySaver } from "@langchain/langgraph-checkpoint";
181
+ *
182
+ * const myWorkflow = entrypoint({
183
+ * name: "accumulator",
184
+ * checkpointer: new MemorySaver()
185
+ * }, async (num: number) => {
186
+ * const previous = getPreviousState<number>();
187
+ *
188
+ * // This will return the previous value to the caller, saving
189
+ * // 2 * num to the checkpoint, which will be used in the next invocation
190
+ * // for the `previous` parameter.
191
+ * return entrypoint.final({
192
+ * value: previous ?? 0,
193
+ * save: 2 * num
194
+ * });
195
+ * });
196
+ *
197
+ * const config = {
198
+ * configurable: {
199
+ * thread_id: "some_thread"
200
+ * }
201
+ * };
202
+ *
203
+ * await myWorkflow.invoke(3, config); // 0 (previous was undefined)
204
+ * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)
205
+ * ```
206
+ */
207
+ export const entrypoint = function entrypoint(optionsOrName, func) {
208
+ const { name, checkpointer, store } = typeof optionsOrName === "string"
209
+ ? { name: optionsOrName, checkpointer: undefined, store: undefined }
210
+ : optionsOrName;
211
+ if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {
212
+ throw new Error("Generators are disallowed as entrypoints. For streaming responses, use config.write.");
213
+ }
214
+ const streamMode = "updates";
215
+ const bound = getRunnableForEntrypoint(name, func);
216
+ return new Pregel({
217
+ name,
218
+ checkpointer,
219
+ nodes: {
220
+ [name]: new PregelNode({
221
+ bound,
222
+ triggers: [START],
223
+ channels: [START],
224
+ writers: [],
225
+ }),
226
+ },
227
+ channels: {
228
+ [START]: new EphemeralValue(),
229
+ [END]: new LastValue(),
230
+ [PREVIOUS]: new LastValue(),
231
+ },
232
+ inputChannels: START,
233
+ outputChannels: END,
234
+ streamChannels: END,
235
+ streamMode,
236
+ store,
237
+ });
238
+ };
239
+ // documented by the EntrypointFunction interface
240
+ entrypoint.final = function final({ value, save, }) {
241
+ return { value, save, __lg_type: "__pregel_final" };
242
+ };
243
+ /**
244
+ * A helper utility function for use with the functional API that returns the previous
245
+ * state from the checkpoint from the last invocation of the current thread.
246
+ *
247
+ * This function allows workflows to access state that was saved in previous runs
248
+ * using {@link entrypoint.final}.
249
+ *
250
+ * !!! warning "Beta"
251
+ * The Functional API is currently in beta and is subject to change.
252
+ *
253
+ * @beta
254
+ *
255
+ * @typeParam StateT - The type of the state that was previously saved
256
+ * @returns The previous saved state from the last invocation of the current thread
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * const previousState = getPreviousState<{ counter: number }>();
261
+ * const newCount = (previousState?.counter ?? 0) + 1;
262
+ * ```
263
+ */
264
+ export function getPreviousState() {
265
+ const config = AsyncLocalStorageProviderSingleton.getRunnableConfig();
266
+ return config.configurable?.[CONFIG_KEY_PREVIOUS_STATE];
267
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEntrypointFinal = void 0;
4
+ /**
5
+ * Checks if a value is an EntrypointFinal - use this instead of `instanceof`, as value may have been deserialized
6
+ * @param value The value to check
7
+ * @returns Whether the value is an EntrypointFinal
8
+ */
9
+ function isEntrypointFinal(value) {
10
+ return (typeof value === "object" &&
11
+ value !== null &&
12
+ "__lg_type" in value &&
13
+ value.__lg_type === "__pregel_final");
14
+ }
15
+ exports.isEntrypointFinal = isEntrypointFinal;
@@ -0,0 +1,59 @@
1
+ import { LangGraphRunnableConfig } from "../pregel/runnable_types.js";
2
+ /**
3
+ * Allows the entrypoint function to return a value to the caller, as well as a separate state value to persist to the checkpoint
4
+ */
5
+ export type EntrypointFinal<ValueT, SaveT> = {
6
+ /**
7
+ * The value to return to the caller
8
+ */
9
+ value?: ValueT;
10
+ /**
11
+ * The value to save to the checkpoint
12
+ */
13
+ save?: SaveT;
14
+ __lg_type: "__pregel_final";
15
+ };
16
+ /**
17
+ * Checks if a value is an EntrypointFinal - use this instead of `instanceof`, as value may have been deserialized
18
+ * @param value The value to check
19
+ * @returns Whether the value is an EntrypointFinal
20
+ */
21
+ export declare function isEntrypointFinal<ValueT, SaveT>(value: unknown): value is EntrypointFinal<ValueT, SaveT>;
22
+ /**
23
+ * The return type of an entrypoint function.
24
+ */
25
+ export type EntrypointReturnT<OutputT> = OutputT extends EntrypointFinal<infer ValueT, unknown> | Promise<EntrypointFinal<infer ValueT, unknown>> ? ValueT : OutputT;
26
+ /**
27
+ * The value to be saved when a function returns an EntrypointFinal.
28
+ */
29
+ export type EntrypointFinalSaveT<OutputT> = OutputT extends EntrypointFinal<unknown, infer SaveT> | Promise<EntrypointFinal<unknown, infer SaveT>> ? SaveT : OutputT;
30
+ /**
31
+ * The value to be returned when a function returns an EntrypointFinal.
32
+ */
33
+ export type EntrypointFinalValueT<OutputT> = OutputT extends EntrypointFinal<infer ValueT, infer SaveT> | Promise<EntrypointFinal<infer ValueT, infer SaveT>> ? EntrypointFinal<ValueT, SaveT> : OutputT;
34
+ /**
35
+ * Checks if an AsyncGenerator exists in the ES target/lib that we're compiling to.
36
+ *
37
+ * This is necessary because `tsc --init` targets ES2016 by default, which doesn't include AsyncGenerators.
38
+ *
39
+ * This works because when `skipLibCheck` is true (and it is in the default `tsconfig.json` created by `tsc --init`),
40
+ * TypeScript will replace any unresolved libary types with `any`. So, when `AsyncGenerator` doesn't exist, this checks
41
+ * if `any` extends `object`, which it doesn't. When that happens, this type resolves to the `false` literal, and we can
42
+ * use it in the type predicates below to skip over the AsyncGenerator-specific logic.
43
+ *
44
+ * If we didn't have this, then the types below would be checking if the user's function extends `any` in place of the
45
+ * `AsyncGenerator` type, and the type predicate would branch to `never`, disallowing any valid function from being passed
46
+ * to `task` or `entrypoint`.
47
+ */
48
+ type AsyncGeneratorExists = AsyncGenerator<unknown, unknown, unknown> extends object ? true : false;
49
+ /**
50
+ * Matches valid function signatures for entrypoints. Disallows generator functions.
51
+ */
52
+ export type EntrypointFunc<InputT, OutputT> = [OutputT] extends never ? (input: InputT, config: LangGraphRunnableConfig) => never : AsyncGeneratorExists extends true ? OutputT extends AsyncGenerator<unknown, unknown, unknown> ? never : OutputT extends Generator<unknown, unknown, unknown> ? never : (input: InputT, config: LangGraphRunnableConfig) => OutputT : OutputT extends Generator<unknown, unknown, unknown> ? never : (input: InputT, config: LangGraphRunnableConfig) => OutputT;
53
+ /**
54
+ * Matches valid function signatures for tasks. Disallows generator functions.
55
+ */
56
+ export type TaskFunc<ArgsT extends unknown[], OutputT> = [OutputT] extends [
57
+ never
58
+ ] ? (...args: ArgsT) => never : AsyncGeneratorExists extends true ? OutputT extends AsyncGenerator<unknown, unknown, unknown> ? never : OutputT extends Generator<unknown, unknown, unknown> ? never : (...args: ArgsT) => OutputT : OutputT extends Generator<unknown, unknown, unknown> ? never : (...args: ArgsT) => OutputT;
59
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Checks if a value is an EntrypointFinal - use this instead of `instanceof`, as value may have been deserialized
3
+ * @param value The value to check
4
+ * @returns Whether the value is an EntrypointFinal
5
+ */
6
+ export function isEntrypointFinal(value) {
7
+ return (typeof value === "object" &&
8
+ value !== null &&
9
+ "__lg_type" in value &&
10
+ value.__lg_type === "__pregel_final");
11
+ }