@langchain/langgraph 0.0.31 → 0.0.33
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.
- package/README.md +75 -28
- package/dist/channels/base.cjs +14 -0
- package/dist/channels/base.d.ts +2 -0
- package/dist/channels/base.js +14 -0
- package/dist/graph/message.d.ts +1 -1
- package/dist/graph/state.cjs +36 -2
- package/dist/graph/state.d.ts +23 -9
- package/dist/graph/state.js +34 -1
- package/dist/prebuilt/agent_executor.d.ts +1 -1
- package/dist/pregel/index.cjs +26 -21
- package/dist/pregel/index.js +26 -21
- package/package.json +9 -16
- package/dist/tests/channels.test.d.ts +0 -1
- package/dist/tests/channels.test.js +0 -151
- package/dist/tests/chatbot.int.test.d.ts +0 -1
- package/dist/tests/chatbot.int.test.js +0 -66
- package/dist/tests/checkpoints.test.d.ts +0 -1
- package/dist/tests/checkpoints.test.js +0 -178
- package/dist/tests/diagrams.test.d.ts +0 -1
- package/dist/tests/diagrams.test.js +0 -25
- package/dist/tests/graph.test.d.ts +0 -1
- package/dist/tests/graph.test.js +0 -33
- package/dist/tests/prebuilt.int.test.d.ts +0 -1
- package/dist/tests/prebuilt.int.test.js +0 -207
- package/dist/tests/prebuilt.test.d.ts +0 -1
- package/dist/tests/prebuilt.test.js +0 -427
- package/dist/tests/pregel.io.test.d.ts +0 -1
- package/dist/tests/pregel.io.test.js +0 -332
- package/dist/tests/pregel.read.test.d.ts +0 -1
- package/dist/tests/pregel.read.test.js +0 -109
- package/dist/tests/pregel.test.d.ts +0 -1
- package/dist/tests/pregel.test.js +0 -1882
- package/dist/tests/pregel.validate.test.d.ts +0 -1
- package/dist/tests/pregel.validate.test.js +0 -198
- package/dist/tests/pregel.write.test.d.ts +0 -1
- package/dist/tests/pregel.write.test.js +0 -44
- package/dist/tests/tracing.int.test.d.ts +0 -1
- package/dist/tests/tracing.int.test.js +0 -450
- package/dist/tests/tracing.test.d.ts +0 -1
- package/dist/tests/tracing.test.js +0 -332
- package/dist/tests/utils.d.ts +0 -53
- package/dist/tests/utils.js +0 -167
package/README.md
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|

|
|
5
5
|
[](https://www.npmjs.com/package/@langchain/langgraph)
|
|
6
6
|
[](https://github.com/langchain-ai/langgraphjs/issues)
|
|
7
|
-
[](https://discord.com/channels/1038097195422978059/1170024642245832774)
|
|
8
7
|
|
|
9
8
|
⚡ Building language agents as graphs ⚡
|
|
10
9
|
|
|
@@ -56,55 +55,52 @@ export LANGCHAIN_API_KEY=ls__...
|
|
|
56
55
|
Now let's define our agent:
|
|
57
56
|
|
|
58
57
|
```typescript
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
58
|
+
import { AIMessage, BaseMessage, HumanMessage } from "@langchain/core/messages";
|
|
59
|
+
import { tool } from "@langchain/core/tools";
|
|
61
60
|
import { z } from "zod";
|
|
62
61
|
import { ChatAnthropic } from "@langchain/anthropic";
|
|
63
|
-
import {
|
|
62
|
+
import { StateGraph, StateGraphArgs } from "@langchain/langgraph";
|
|
64
63
|
import { MemorySaver } from "@langchain/langgraph";
|
|
65
64
|
import { ToolNode } from "@langchain/langgraph/prebuilt";
|
|
66
65
|
|
|
67
66
|
// Define the state interface
|
|
68
67
|
interface AgentState {
|
|
69
|
-
messages:
|
|
68
|
+
messages: BaseMessage[];
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// Define the graph state
|
|
73
72
|
const graphState: StateGraphArgs<AgentState>["channels"] = {
|
|
74
73
|
messages: {
|
|
75
|
-
|
|
76
|
-
default: () => [],
|
|
74
|
+
reducer: (x: BaseMessage[], y: BaseMessage[]) => x.concat(y),
|
|
77
75
|
},
|
|
78
76
|
};
|
|
79
77
|
|
|
80
78
|
// Define the tools for the agent to use
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const weatherTool = tool(async ({ query }) => {
|
|
80
|
+
// This is a placeholder for the actual implementation
|
|
81
|
+
if (query.toLowerCase().includes("sf") || query.toLowerCase().includes("san francisco")) {
|
|
82
|
+
return "It's 60 degrees and foggy."
|
|
83
|
+
}
|
|
84
|
+
return "It's 90 degrees and sunny."
|
|
85
|
+
}, {
|
|
86
|
+
name: "weather",
|
|
84
87
|
description:
|
|
85
|
-
"Call to
|
|
88
|
+
"Call to get the current weather for a location.",
|
|
86
89
|
schema: z.object({
|
|
87
90
|
query: z.string().describe("The query to use in your search."),
|
|
88
91
|
}),
|
|
89
|
-
func: async ({ query }: { query: string }) => {
|
|
90
|
-
// This is a placeholder for the actual implementation
|
|
91
|
-
if (query.toLowerCase().includes("sf") || query.toLowerCase().includes("san francisco")) {
|
|
92
|
-
return "It's 60 degrees and foggy."
|
|
93
|
-
}
|
|
94
|
-
return "It's 90 degrees and sunny."
|
|
95
|
-
},
|
|
96
92
|
});
|
|
97
93
|
|
|
98
|
-
const tools = [
|
|
94
|
+
const tools = [weatherTool];
|
|
99
95
|
const toolNode = new ToolNode<AgentState>(tools);
|
|
100
96
|
|
|
101
97
|
const model = new ChatAnthropic({
|
|
102
|
-
model: "claude-3-sonnet-
|
|
98
|
+
model: "claude-3-5-sonnet-20240620",
|
|
103
99
|
temperature: 0,
|
|
104
100
|
}).bindTools(tools);
|
|
105
101
|
|
|
106
102
|
// Define the function that determines whether to continue or not
|
|
107
|
-
function shouldContinue(state: AgentState)
|
|
103
|
+
function shouldContinue(state: AgentState) {
|
|
108
104
|
const messages = state.messages;
|
|
109
105
|
const lastMessage = messages[messages.length - 1] as AIMessage;
|
|
110
106
|
|
|
@@ -113,7 +109,7 @@ function shouldContinue(state: AgentState): "tools" | typeof END {
|
|
|
113
109
|
return "tools";
|
|
114
110
|
}
|
|
115
111
|
// Otherwise, we stop (reply to the user)
|
|
116
|
-
return
|
|
112
|
+
return "__end__";
|
|
117
113
|
}
|
|
118
114
|
|
|
119
115
|
// Define the function that calls the model
|
|
@@ -129,7 +125,7 @@ async function callModel(state: AgentState) {
|
|
|
129
125
|
const workflow = new StateGraph<AgentState>({ channels: graphState })
|
|
130
126
|
.addNode("agent", callModel)
|
|
131
127
|
.addNode("tools", toolNode)
|
|
132
|
-
.addEdge(
|
|
128
|
+
.addEdge("__start__", "agent")
|
|
133
129
|
.addConditionalEdges("agent", shouldContinue)
|
|
134
130
|
.addEdge("tools", "agent");
|
|
135
131
|
|
|
@@ -146,13 +142,21 @@ const finalState = await app.invoke(
|
|
|
146
142
|
{ messages: [new HumanMessage("what is the weather in sf")] },
|
|
147
143
|
{ configurable: { thread_id: "42" } }
|
|
148
144
|
);
|
|
145
|
+
|
|
149
146
|
console.log(finalState.messages[finalState.messages.length - 1].content);
|
|
150
147
|
```
|
|
151
148
|
|
|
152
149
|
This will output:
|
|
153
150
|
|
|
154
151
|
```
|
|
155
|
-
Based on the
|
|
152
|
+
Based on the information I received, the current weather in San Francisco is:
|
|
153
|
+
|
|
154
|
+
Temperature: 60 degrees Fahrenheit
|
|
155
|
+
Conditions: Foggy
|
|
156
|
+
|
|
157
|
+
San Francisco is known for its foggy weather, especially during certain times of the year. The moderate temperature of 60°F (about 15.5°C) is quite typical for the city, which generally has mild weather year-round due to its coastal location.
|
|
158
|
+
|
|
159
|
+
Is there anything else you'd like to know about the weather in San Francisco or any other location?
|
|
156
160
|
```
|
|
157
161
|
|
|
158
162
|
Now when we pass the same `"thread_id"`, the conversation context is retained via the saved state (i.e. stored list of messages):
|
|
@@ -166,7 +170,16 @@ console.log(nextState.messages[nextState.messages.length - 1].content);
|
|
|
166
170
|
```
|
|
167
171
|
|
|
168
172
|
```
|
|
169
|
-
Based on the
|
|
173
|
+
Based on the information I received, the current weather in New York is:
|
|
174
|
+
|
|
175
|
+
Temperature: 90 degrees Fahrenheit (approximately 32.2 degrees Celsius)
|
|
176
|
+
Conditions: Sunny
|
|
177
|
+
|
|
178
|
+
New York is experiencing quite warm weather today. A temperature of 90°F is considered hot for most people, and it's significantly warmer than the San Francisco weather we just checked. The sunny conditions suggest it's a clear day without cloud cover, which can make it feel even warmer.
|
|
179
|
+
|
|
180
|
+
On a day like this in New York, it would be advisable for people to stay hydrated, seek shade when possible, and use sun protection if spending time outdoors.
|
|
181
|
+
|
|
182
|
+
Is there anything else you'd like to know about the weather in New York or any other location?
|
|
170
183
|
```
|
|
171
184
|
|
|
172
185
|
### Step-by-step Breakdown
|
|
@@ -175,7 +188,7 @@ Based on the search results, I can tell you that the current weather in New York
|
|
|
175
188
|
<summary>Initialize the model and tools.</summary>
|
|
176
189
|
|
|
177
190
|
- We use `ChatAnthropic` as our LLM. **NOTE:** We need make sure the model knows that it has these tools available to call. We can do this by converting the LangChain tools into the format for Anthropic tool calling using the `.bindTools()` method.
|
|
178
|
-
- We define the tools we want to use -- a
|
|
191
|
+
- We define the tools we want to use -- a weather tool in our case. See the documentation [here](https://js.langchain.com/docs/modules/agents/tools/dynamic) on how to create your own tools.
|
|
179
192
|
</details>
|
|
180
193
|
|
|
181
194
|
2. <details>
|
|
@@ -197,7 +210,7 @@ Based on the search results, I can tell you that the current weather in New York
|
|
|
197
210
|
4. <details>
|
|
198
211
|
<summary>Define entry point and graph edges.</summary>
|
|
199
212
|
|
|
200
|
-
First, we need to set the entry point for graph execution - `agent` node.
|
|
213
|
+
First, we need to set the entry point for graph execution - the `agent` node.
|
|
201
214
|
|
|
202
215
|
Then we define one normal and one conditional edge. A conditional edge means that the destination depends on the contents of the graph's state (`AgentState`). In our case, the destination is not known until the agent (LLM) decides.
|
|
203
216
|
|
|
@@ -225,7 +238,7 @@ Based on the search results, I can tell you that the current weather in New York
|
|
|
225
238
|
- If `AIMessage` has `tool_calls`, the `"tools"` node executes.
|
|
226
239
|
- The `"agent"` node executes again and returns an `AIMessage`.
|
|
227
240
|
|
|
228
|
-
5. Execution progresses to the special `
|
|
241
|
+
5. Execution progresses to the special `__end__` value and outputs the final state.
|
|
229
242
|
As a result, we get a list of all our chat messages as output.
|
|
230
243
|
</details>
|
|
231
244
|
|
|
@@ -235,3 +248,37 @@ Based on the search results, I can tell you that the current weather in New York
|
|
|
235
248
|
- [How-to Guides](https://langchain-ai.github.io/langgraphjs/how-tos/): Accomplish specific things within LangGraph, from streaming, to adding memory & persistence, to common design patterns (branching, subgraphs, etc.). These are the place to go if you want to copy and run a specific code snippet.
|
|
236
249
|
- [Conceptual Guides](https://langchain-ai.github.io/langgraphjs/concepts/): In-depth explanations of the key concepts and principles behind LangGraph, such as nodes, edges, state and more.
|
|
237
250
|
- [API Reference](https://langchain-ai.github.io/langgraphjs/reference/graphs/): Review important classes and methods, simple examples of how to use the graph and checkpointing APIs, higher-level prebuilt components and more.
|
|
251
|
+
|
|
252
|
+
## Running Example Juypter Notebooks
|
|
253
|
+
|
|
254
|
+
Please note that the *.ipynb notebooks in the `examples/` folder require [tslab](https://github.com/yunabe/tslab?tab=readme-ov-file) to be installed. In order to run these notebooks in VSCode, you will also need the [Jupyter](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter) VSCode Extension installed. After cloning this repository, you can run `yarn build` in the root. You should then be all set!
|
|
255
|
+
|
|
256
|
+
If you are still having trouble, try adding the following `tsconfig.json` file to the `examples/` directory:
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
{
|
|
260
|
+
"compilerOptions": {
|
|
261
|
+
"esModuleInterop": true,
|
|
262
|
+
"moduleResolution": "node",
|
|
263
|
+
"target": "ES2020",
|
|
264
|
+
"module": "ES2020",
|
|
265
|
+
"lib": [
|
|
266
|
+
"ES2020"
|
|
267
|
+
],
|
|
268
|
+
"strict": true,
|
|
269
|
+
"baseUrl": ".",
|
|
270
|
+
"paths": {
|
|
271
|
+
"@langchain/langgraph": [
|
|
272
|
+
"../langgraph/src"
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
"include": [
|
|
277
|
+
"./**/*.ts",
|
|
278
|
+
"./**/*.tsx"
|
|
279
|
+
],
|
|
280
|
+
"exclude": [
|
|
281
|
+
"node_modules"
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
```
|
package/dist/channels/base.cjs
CHANGED
|
@@ -5,6 +5,20 @@ const base_js_1 = require("../checkpoint/base.cjs");
|
|
|
5
5
|
const id_js_1 = require("../checkpoint/id.cjs");
|
|
6
6
|
const errors_js_1 = require("../errors.cjs");
|
|
7
7
|
class BaseChannel {
|
|
8
|
+
constructor() {
|
|
9
|
+
Object.defineProperty(this, "ValueType", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: void 0
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(this, "UpdateType", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: void 0
|
|
20
|
+
});
|
|
21
|
+
}
|
|
8
22
|
}
|
|
9
23
|
exports.BaseChannel = BaseChannel;
|
|
10
24
|
function emptyChannels(channels, checkpoint) {
|
package/dist/channels/base.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ReadonlyCheckpoint } from "../checkpoint/base.js";
|
|
2
2
|
import { Checkpoint } from "../checkpoint/index.js";
|
|
3
3
|
export declare abstract class BaseChannel<ValueType = unknown, UpdateType = unknown, CheckpointType = unknown> {
|
|
4
|
+
ValueType: ValueType;
|
|
5
|
+
UpdateType: UpdateType;
|
|
4
6
|
/**
|
|
5
7
|
* The name of the channel.
|
|
6
8
|
*/
|
package/dist/channels/base.js
CHANGED
|
@@ -2,6 +2,20 @@ import { deepCopy } from "../checkpoint/base.js";
|
|
|
2
2
|
import { uuid6 } from "../checkpoint/id.js";
|
|
3
3
|
import { EmptyChannelError } from "../errors.js";
|
|
4
4
|
export class BaseChannel {
|
|
5
|
+
constructor() {
|
|
6
|
+
Object.defineProperty(this, "ValueType", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "UpdateType", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
}
|
|
5
19
|
}
|
|
6
20
|
export function emptyChannels(channels, checkpoint) {
|
|
7
21
|
const newChannels = {};
|
package/dist/graph/message.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { BaseMessage, BaseMessageLike } from "@langchain/core/messages";
|
|
|
2
2
|
import { StateGraph } from "./state.js";
|
|
3
3
|
type Messages = Array<BaseMessage | BaseMessageLike> | BaseMessage | BaseMessageLike;
|
|
4
4
|
export declare function messagesStateReducer(left: Messages, right: Messages): BaseMessage[];
|
|
5
|
-
export declare class MessageGraph extends StateGraph<BaseMessage[], Messages> {
|
|
5
|
+
export declare class MessageGraph extends StateGraph<BaseMessage[], BaseMessage[], Messages> {
|
|
6
6
|
constructor();
|
|
7
7
|
}
|
|
8
8
|
export interface MessagesState {
|
package/dist/graph/state.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CompiledStateGraph = exports.StateGraph = void 0;
|
|
3
|
+
exports.CompiledStateGraph = exports.StateGraph = exports.Annotation = void 0;
|
|
4
4
|
const binop_js_1 = require("../channels/binop.cjs");
|
|
5
5
|
const graph_js_1 = require("./graph.cjs");
|
|
6
6
|
const last_value_js_1 = require("../channels/last_value.cjs");
|
|
@@ -12,6 +12,16 @@ const utils_js_1 = require("../utils.cjs");
|
|
|
12
12
|
const constants_js_1 = require("../constants.cjs");
|
|
13
13
|
const errors_js_1 = require("../errors.cjs");
|
|
14
14
|
const ROOT = "__root__";
|
|
15
|
+
function Annotation(annotation) {
|
|
16
|
+
if (annotation) {
|
|
17
|
+
return getChannel(annotation);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// @ts-expect-error - Annotation without reducer
|
|
21
|
+
return new last_value_js_1.LastValue();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.Annotation = Annotation;
|
|
15
25
|
class StateGraph extends graph_js_1.Graph {
|
|
16
26
|
constructor(fields) {
|
|
17
27
|
super();
|
|
@@ -28,7 +38,20 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
28
38
|
writable: true,
|
|
29
39
|
value: new Set()
|
|
30
40
|
});
|
|
31
|
-
|
|
41
|
+
if (isStateDefinition(fields)) {
|
|
42
|
+
this.channels = {};
|
|
43
|
+
for (const [key, val] of Object.entries(fields)) {
|
|
44
|
+
if (typeof val === "function") {
|
|
45
|
+
this.channels[key] = val();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.channels[key] = val;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this.channels = _getChannels(fields.channels);
|
|
54
|
+
}
|
|
32
55
|
for (const c of Object.values(this.channels)) {
|
|
33
56
|
if (c.lc_graph_name === "BinaryOperatorAggregate") {
|
|
34
57
|
this.supportMultipleEdges = true;
|
|
@@ -147,6 +170,7 @@ function getChannel(reducer) {
|
|
|
147
170
|
reducer.value) {
|
|
148
171
|
return new binop_js_1.BinaryOperatorAggregate(reducer.value, reducer.default);
|
|
149
172
|
}
|
|
173
|
+
// @ts-expect-error - Annotation without reducer
|
|
150
174
|
return new last_value_js_1.LastValue();
|
|
151
175
|
}
|
|
152
176
|
class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
@@ -266,3 +290,13 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
266
290
|
}
|
|
267
291
|
}
|
|
268
292
|
exports.CompiledStateGraph = CompiledStateGraph;
|
|
293
|
+
function isBaseChannel(obj) {
|
|
294
|
+
return obj != null && typeof obj.lc_graph_name === "string";
|
|
295
|
+
}
|
|
296
|
+
function isStateDefinition(obj) {
|
|
297
|
+
return (typeof obj === "object" &&
|
|
298
|
+
obj !== null &&
|
|
299
|
+
!Array.isArray(obj) &&
|
|
300
|
+
Object.keys(obj).length > 0 &&
|
|
301
|
+
Object.values(obj).every((v) => typeof v === "function" || isBaseChannel(v)));
|
|
302
|
+
}
|
package/dist/graph/state.d.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { Runnable, RunnableConfig, RunnableLike } from "@langchain/core/runnables";
|
|
2
2
|
import { BaseChannel } from "../channels/base.js";
|
|
3
|
-
import { BinaryOperator } from "../channels/binop.js";
|
|
3
|
+
import { BinaryOperator, BinaryOperatorAggregate } from "../channels/binop.js";
|
|
4
4
|
import { END, CompiledGraph, Graph, START, Branch } from "./graph.js";
|
|
5
|
+
import { LastValue } from "../channels/last_value.js";
|
|
5
6
|
import { BaseCheckpointSaver } from "../checkpoint/base.js";
|
|
6
7
|
import { All } from "../pregel/types.js";
|
|
8
|
+
export declare function Annotation<ValueType>(): LastValue<ValueType>;
|
|
9
|
+
export declare function Annotation<ValueType, UpdateType = ValueType>(annotation: SingleReducer<ValueType, UpdateType>): BinaryOperatorAggregate<ValueType, UpdateType>;
|
|
10
|
+
interface StateDefinition {
|
|
11
|
+
[key: string]: BaseChannel | (() => BaseChannel);
|
|
12
|
+
}
|
|
13
|
+
type ExtractValueType<C> = C extends BaseChannel ? C["ValueType"] : C extends () => BaseChannel ? ReturnType<C>["ValueType"] : never;
|
|
14
|
+
type ExtractUpdateType<C> = C extends BaseChannel ? C["UpdateType"] : C extends () => BaseChannel ? ReturnType<C>["UpdateType"] : never;
|
|
15
|
+
export type StateInterface<S extends StateDefinition> = {
|
|
16
|
+
[key in keyof S]: ExtractValueType<S[key]>;
|
|
17
|
+
};
|
|
18
|
+
export type UpdateInterface<S extends StateDefinition> = {
|
|
19
|
+
[key in keyof S]?: ExtractUpdateType<S[key]>;
|
|
20
|
+
};
|
|
7
21
|
type SingleReducer<ValueType, UpdateType = ValueType> = {
|
|
8
22
|
reducer: BinaryOperator<ValueType, UpdateType>;
|
|
9
23
|
default?: () => ValueType;
|
|
@@ -24,24 +38,24 @@ export interface StateGraphArgs<Channels extends object | unknown> {
|
|
|
24
38
|
__root__: Channels;
|
|
25
39
|
}>;
|
|
26
40
|
}
|
|
27
|
-
export declare class StateGraph<
|
|
41
|
+
export declare class StateGraph<SD extends StateDefinition | unknown, S = SD extends StateDefinition ? StateInterface<SD> : SD, U = SD extends StateDefinition ? UpdateInterface<SD> : Partial<S>, N extends string = typeof START> extends Graph<N, S, U> {
|
|
28
42
|
channels: Record<string, BaseChannel>;
|
|
29
43
|
waitingEdges: Set<[N[], N]>;
|
|
30
|
-
constructor(fields: StateGraphArgs<
|
|
44
|
+
constructor(fields: SD extends StateDefinition ? SD | StateGraphArgs<S> : StateGraphArgs<S>);
|
|
31
45
|
get allEdges(): Set<[string, string]>;
|
|
32
|
-
addNode<K extends string>(key: K, action: RunnableLike<
|
|
46
|
+
addNode<K extends string>(key: K, action: RunnableLike<S, U>): StateGraph<SD, S, U, N | K>;
|
|
33
47
|
addEdge(startKey: typeof START | N | N[], endKey: N | typeof END): this;
|
|
34
48
|
compile({ checkpointer, interruptBefore, interruptAfter, }?: {
|
|
35
49
|
checkpointer?: BaseCheckpointSaver;
|
|
36
50
|
interruptBefore?: N[] | All;
|
|
37
51
|
interruptAfter?: N[] | All;
|
|
38
|
-
}): CompiledStateGraph<
|
|
52
|
+
}): CompiledStateGraph<S, U, N>;
|
|
39
53
|
}
|
|
40
|
-
export declare class CompiledStateGraph<
|
|
41
|
-
builder: StateGraph<
|
|
54
|
+
export declare class CompiledStateGraph<S, U, N extends string = typeof START> extends CompiledGraph<N, S, U> {
|
|
55
|
+
builder: StateGraph<unknown, S, U, N>;
|
|
42
56
|
attachNode(key: typeof START, node?: never): void;
|
|
43
|
-
attachNode(key: N, node: Runnable<
|
|
57
|
+
attachNode(key: N, node: Runnable<S, U, RunnableConfig>): void;
|
|
44
58
|
attachEdge(start: N | N[] | "__start__", end: N | "__end__"): void;
|
|
45
|
-
attachBranch(start: N | typeof START, name: string, branch: Branch<
|
|
59
|
+
attachBranch(start: N | typeof START, name: string, branch: Branch<S, N>): void;
|
|
46
60
|
}
|
|
47
61
|
export {};
|
package/dist/graph/state.js
CHANGED
|
@@ -9,6 +9,15 @@ import { RunnableCallable } from "../utils.js";
|
|
|
9
9
|
import { TAG_HIDDEN } from "../constants.js";
|
|
10
10
|
import { InvalidUpdateError } from "../errors.js";
|
|
11
11
|
const ROOT = "__root__";
|
|
12
|
+
export function Annotation(annotation) {
|
|
13
|
+
if (annotation) {
|
|
14
|
+
return getChannel(annotation);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// @ts-expect-error - Annotation without reducer
|
|
18
|
+
return new LastValue();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
12
21
|
export class StateGraph extends Graph {
|
|
13
22
|
constructor(fields) {
|
|
14
23
|
super();
|
|
@@ -25,7 +34,20 @@ export class StateGraph extends Graph {
|
|
|
25
34
|
writable: true,
|
|
26
35
|
value: new Set()
|
|
27
36
|
});
|
|
28
|
-
|
|
37
|
+
if (isStateDefinition(fields)) {
|
|
38
|
+
this.channels = {};
|
|
39
|
+
for (const [key, val] of Object.entries(fields)) {
|
|
40
|
+
if (typeof val === "function") {
|
|
41
|
+
this.channels[key] = val();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.channels[key] = val;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.channels = _getChannels(fields.channels);
|
|
50
|
+
}
|
|
29
51
|
for (const c of Object.values(this.channels)) {
|
|
30
52
|
if (c.lc_graph_name === "BinaryOperatorAggregate") {
|
|
31
53
|
this.supportMultipleEdges = true;
|
|
@@ -143,6 +165,7 @@ function getChannel(reducer) {
|
|
|
143
165
|
reducer.value) {
|
|
144
166
|
return new BinaryOperatorAggregate(reducer.value, reducer.default);
|
|
145
167
|
}
|
|
168
|
+
// @ts-expect-error - Annotation without reducer
|
|
146
169
|
return new LastValue();
|
|
147
170
|
}
|
|
148
171
|
export class CompiledStateGraph extends CompiledGraph {
|
|
@@ -261,3 +284,13 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
261
284
|
}
|
|
262
285
|
}
|
|
263
286
|
}
|
|
287
|
+
function isBaseChannel(obj) {
|
|
288
|
+
return obj != null && typeof obj.lc_graph_name === "string";
|
|
289
|
+
}
|
|
290
|
+
function isStateDefinition(obj) {
|
|
291
|
+
return (typeof obj === "object" &&
|
|
292
|
+
obj !== null &&
|
|
293
|
+
!Array.isArray(obj) &&
|
|
294
|
+
Object.keys(obj).length > 0 &&
|
|
295
|
+
Object.values(obj).every((v) => typeof v === "function" || isBaseChannel(v)));
|
|
296
|
+
}
|
|
@@ -16,5 +16,5 @@ export interface AgentExecutorState {
|
|
|
16
16
|
export declare function createAgentExecutor({ agentRunnable, tools, }: {
|
|
17
17
|
agentRunnable: Runnable;
|
|
18
18
|
tools: Array<Tool> | ToolExecutor;
|
|
19
|
-
}): import("../graph/state.js").CompiledStateGraph<AgentExecutorState, Partial<
|
|
19
|
+
}): import("../graph/state.js").CompiledStateGraph<AgentExecutorState, Partial<AgentExecutorState>, "__start__" | "agent" | "action">;
|
|
20
20
|
export {};
|
package/dist/pregel/index.cjs
CHANGED
|
@@ -465,7 +465,7 @@ class Pregel extends runnables_1.Runnable {
|
|
|
465
465
|
// execute tasks, and wait for one to fail or all to finish.
|
|
466
466
|
// each task is independent from all other concurrent tasks
|
|
467
467
|
const tasks = tasksWithConfig.map(([proc, input, updatedConfig]) => () => proc.invoke(input, updatedConfig));
|
|
468
|
-
await executeTasks(tasks, this.stepTimeout);
|
|
468
|
+
await executeTasks(tasks, this.stepTimeout, config.signal);
|
|
469
469
|
// combine pending writes from all tasks
|
|
470
470
|
const pendingWrites = [];
|
|
471
471
|
for (const task of nextTasks) {
|
|
@@ -536,28 +536,33 @@ class Pregel extends runnables_1.Runnable {
|
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
538
|
exports.Pregel = Pregel;
|
|
539
|
-
function
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
? Promise.race([
|
|
548
|
-
task(),
|
|
549
|
-
stepTimeout ? timeout(stepTimeout) : Promise.resolve(),
|
|
550
|
-
])
|
|
551
|
-
: task());
|
|
552
|
-
// Wait for all tasks to settle
|
|
553
|
-
const results = await Promise.allSettled(wrappedTasks);
|
|
554
|
-
// Process the results
|
|
555
|
-
for (const result of results) {
|
|
556
|
-
if (result.status === "rejected") {
|
|
557
|
-
// If any task failed, cancel all pending tasks and throw the error
|
|
558
|
-
throw result.reason;
|
|
539
|
+
async function executeTasks(tasks, stepTimeout, signal) {
|
|
540
|
+
if (stepTimeout && signal) {
|
|
541
|
+
if ("any" in AbortSignal) {
|
|
542
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
543
|
+
signal = AbortSignal.any([
|
|
544
|
+
signal,
|
|
545
|
+
AbortSignal.timeout(stepTimeout),
|
|
546
|
+
]);
|
|
559
547
|
}
|
|
560
548
|
}
|
|
549
|
+
else if (stepTimeout) {
|
|
550
|
+
signal = AbortSignal.timeout(stepTimeout);
|
|
551
|
+
}
|
|
552
|
+
// Abort if signal is aborted
|
|
553
|
+
signal?.throwIfAborted();
|
|
554
|
+
// Start all tasks
|
|
555
|
+
const started = tasks.map((task) => task());
|
|
556
|
+
// Wait for all tasks to settle
|
|
557
|
+
// If any tasks fail, or signal is aborted, the promise will reject
|
|
558
|
+
await Promise.all(signal
|
|
559
|
+
? [
|
|
560
|
+
...started,
|
|
561
|
+
new Promise((_resolve, reject) => {
|
|
562
|
+
signal?.addEventListener("abort", () => reject(new Error("Abort")));
|
|
563
|
+
}),
|
|
564
|
+
]
|
|
565
|
+
: started);
|
|
561
566
|
}
|
|
562
567
|
function _shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, tasks) {
|
|
563
568
|
const anySnapshotChannelUpdated = snapshotChannels.some((chan) => (0, base_js_2.getChannelVersion)(checkpoint, chan) >
|
package/dist/pregel/index.js
CHANGED
|
@@ -461,7 +461,7 @@ export class Pregel extends Runnable {
|
|
|
461
461
|
// execute tasks, and wait for one to fail or all to finish.
|
|
462
462
|
// each task is independent from all other concurrent tasks
|
|
463
463
|
const tasks = tasksWithConfig.map(([proc, input, updatedConfig]) => () => proc.invoke(input, updatedConfig));
|
|
464
|
-
await executeTasks(tasks, this.stepTimeout);
|
|
464
|
+
await executeTasks(tasks, this.stepTimeout, config.signal);
|
|
465
465
|
// combine pending writes from all tasks
|
|
466
466
|
const pendingWrites = [];
|
|
467
467
|
for (const task of nextTasks) {
|
|
@@ -531,28 +531,33 @@ export class Pregel extends Runnable {
|
|
|
531
531
|
}
|
|
532
532
|
}
|
|
533
533
|
}
|
|
534
|
-
function
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
? Promise.race([
|
|
543
|
-
task(),
|
|
544
|
-
stepTimeout ? timeout(stepTimeout) : Promise.resolve(),
|
|
545
|
-
])
|
|
546
|
-
: task());
|
|
547
|
-
// Wait for all tasks to settle
|
|
548
|
-
const results = await Promise.allSettled(wrappedTasks);
|
|
549
|
-
// Process the results
|
|
550
|
-
for (const result of results) {
|
|
551
|
-
if (result.status === "rejected") {
|
|
552
|
-
// If any task failed, cancel all pending tasks and throw the error
|
|
553
|
-
throw result.reason;
|
|
534
|
+
async function executeTasks(tasks, stepTimeout, signal) {
|
|
535
|
+
if (stepTimeout && signal) {
|
|
536
|
+
if ("any" in AbortSignal) {
|
|
537
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
538
|
+
signal = AbortSignal.any([
|
|
539
|
+
signal,
|
|
540
|
+
AbortSignal.timeout(stepTimeout),
|
|
541
|
+
]);
|
|
554
542
|
}
|
|
555
543
|
}
|
|
544
|
+
else if (stepTimeout) {
|
|
545
|
+
signal = AbortSignal.timeout(stepTimeout);
|
|
546
|
+
}
|
|
547
|
+
// Abort if signal is aborted
|
|
548
|
+
signal?.throwIfAborted();
|
|
549
|
+
// Start all tasks
|
|
550
|
+
const started = tasks.map((task) => task());
|
|
551
|
+
// Wait for all tasks to settle
|
|
552
|
+
// If any tasks fail, or signal is aborted, the promise will reject
|
|
553
|
+
await Promise.all(signal
|
|
554
|
+
? [
|
|
555
|
+
...started,
|
|
556
|
+
new Promise((_resolve, reject) => {
|
|
557
|
+
signal?.addEventListener("abort", () => reject(new Error("Abort")));
|
|
558
|
+
}),
|
|
559
|
+
]
|
|
560
|
+
: started);
|
|
556
561
|
}
|
|
557
562
|
export function _shouldInterrupt(checkpoint, interruptNodes, snapshotChannels, tasks) {
|
|
558
563
|
const anySnapshotChannelUpdated = snapshotChannels.some((chan) => getChannelVersion(checkpoint, chan) >
|