@langchain/langgraph 0.0.11 → 0.0.13
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/dist/channels/any_value.cjs +57 -0
- package/dist/channels/any_value.d.ts +16 -0
- package/dist/channels/any_value.js +53 -0
- package/dist/channels/base.cjs +19 -28
- package/dist/channels/base.d.ts +13 -19
- package/dist/channels/base.js +17 -24
- package/dist/channels/binop.cjs +4 -3
- package/dist/channels/binop.d.ts +1 -1
- package/dist/channels/binop.js +3 -2
- package/dist/channels/dynamic_barrier_value.cjs +88 -0
- package/dist/channels/dynamic_barrier_value.d.ts +26 -0
- package/dist/channels/dynamic_barrier_value.js +84 -0
- package/dist/channels/ephemeral_value.cjs +64 -0
- package/dist/channels/ephemeral_value.d.ts +14 -0
- package/dist/channels/ephemeral_value.js +60 -0
- package/dist/channels/index.cjs +1 -3
- package/dist/channels/index.d.ts +1 -1
- package/dist/channels/index.js +1 -1
- package/dist/channels/last_value.cjs +11 -5
- package/dist/channels/last_value.d.ts +5 -1
- package/dist/channels/last_value.js +9 -3
- package/dist/channels/named_barrier_value.cjs +71 -0
- package/dist/channels/named_barrier_value.d.ts +18 -0
- package/dist/channels/named_barrier_value.js +66 -0
- package/dist/channels/topic.cjs +5 -3
- package/dist/channels/topic.d.ts +3 -3
- package/dist/channels/topic.js +5 -3
- package/dist/checkpoint/base.cjs +30 -12
- package/dist/checkpoint/base.d.ts +39 -22
- package/dist/checkpoint/base.js +28 -11
- package/dist/checkpoint/id.cjs +40 -0
- package/dist/checkpoint/id.d.ts +2 -0
- package/dist/checkpoint/id.js +35 -0
- package/dist/checkpoint/index.cjs +2 -2
- package/dist/checkpoint/index.d.ts +2 -2
- package/dist/checkpoint/index.js +2 -2
- package/dist/checkpoint/memory.cjs +63 -49
- package/dist/checkpoint/memory.d.ts +7 -10
- package/dist/checkpoint/memory.js +62 -47
- package/dist/checkpoint/sqlite.cjs +170 -0
- package/dist/checkpoint/sqlite.d.ts +14 -0
- package/dist/checkpoint/sqlite.js +163 -0
- package/dist/constants.cjs +3 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/errors.cjs +31 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +24 -0
- package/dist/graph/graph.cjs +234 -96
- package/dist/graph/graph.d.ts +52 -23
- package/dist/graph/graph.js +233 -97
- package/dist/graph/index.cjs +2 -2
- package/dist/graph/index.d.ts +2 -2
- package/dist/graph/index.js +2 -2
- package/dist/graph/message.cjs +4 -3
- package/dist/graph/message.d.ts +4 -1
- package/dist/graph/message.js +4 -3
- package/dist/graph/state.cjs +237 -102
- package/dist/graph/state.d.ts +41 -18
- package/dist/graph/state.js +238 -104
- package/dist/index.cjs +6 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/prebuilt/agent_executor.cjs +22 -36
- package/dist/prebuilt/agent_executor.d.ts +7 -10
- package/dist/prebuilt/agent_executor.js +23 -37
- package/dist/prebuilt/chat_agent_executor.cjs +13 -13
- package/dist/prebuilt/chat_agent_executor.d.ts +3 -1
- package/dist/prebuilt/chat_agent_executor.js +15 -15
- package/dist/prebuilt/index.cjs +4 -1
- package/dist/prebuilt/index.d.ts +1 -0
- package/dist/prebuilt/index.js +1 -0
- package/dist/prebuilt/tool_node.cjs +59 -0
- package/dist/prebuilt/tool_node.d.ts +17 -0
- package/dist/prebuilt/tool_node.js +54 -0
- package/dist/pregel/debug.cjs +6 -8
- package/dist/pregel/debug.d.ts +2 -2
- package/dist/pregel/debug.js +5 -7
- package/dist/pregel/index.cjs +406 -236
- package/dist/pregel/index.d.ts +77 -41
- package/dist/pregel/index.js +408 -241
- package/dist/pregel/io.cjs +117 -30
- package/dist/pregel/io.d.ts +11 -3
- package/dist/pregel/io.js +111 -28
- package/dist/pregel/read.cjs +126 -46
- package/dist/pregel/read.d.ts +27 -18
- package/dist/pregel/read.js +125 -45
- package/dist/pregel/types.cjs +2 -0
- package/dist/pregel/types.d.ts +32 -0
- package/dist/pregel/types.js +1 -0
- package/dist/pregel/validate.cjs +58 -51
- package/dist/pregel/validate.d.ts +14 -13
- package/dist/pregel/validate.js +56 -50
- package/dist/pregel/write.cjs +46 -30
- package/dist/pregel/write.d.ts +18 -8
- package/dist/pregel/write.js +45 -29
- package/dist/serde/base.cjs +2 -0
- package/dist/serde/base.d.ts +4 -0
- package/dist/serde/base.js +1 -0
- package/dist/setup/async_local_storage.cjs +2 -2
- package/dist/setup/async_local_storage.js +1 -1
- package/dist/tests/channels.test.d.ts +1 -0
- package/dist/tests/channels.test.js +151 -0
- package/dist/tests/chatbot.int.test.d.ts +1 -0
- package/dist/tests/chatbot.int.test.js +61 -0
- package/dist/tests/checkpoints.test.d.ts +1 -0
- package/dist/tests/checkpoints.test.js +190 -0
- package/dist/tests/graph.test.d.ts +1 -0
- package/dist/tests/graph.test.js +15 -0
- package/dist/tests/prebuilt.int.test.d.ts +1 -0
- package/dist/tests/prebuilt.int.test.js +101 -0
- package/dist/tests/prebuilt.test.d.ts +1 -0
- package/dist/tests/prebuilt.test.js +195 -0
- package/dist/tests/pregel.io.test.d.ts +1 -0
- package/dist/tests/pregel.io.test.js +332 -0
- package/dist/tests/pregel.read.test.d.ts +1 -0
- package/dist/tests/pregel.read.test.js +109 -0
- package/dist/tests/pregel.test.d.ts +1 -0
- package/dist/tests/pregel.test.js +1879 -0
- package/dist/tests/pregel.validate.test.d.ts +1 -0
- package/dist/tests/pregel.validate.test.js +198 -0
- package/dist/tests/pregel.write.test.d.ts +1 -0
- package/dist/tests/pregel.write.test.js +44 -0
- package/dist/tests/tracing.int.test.d.ts +1 -0
- package/dist/tests/tracing.int.test.js +449 -0
- package/dist/tests/utils.d.ts +22 -0
- package/dist/tests/utils.js +76 -0
- package/dist/utils.cjs +74 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +70 -0
- package/package.json +12 -8
- package/dist/pregel/reserved.cjs +0 -6
- package/dist/pregel/reserved.d.ts +0 -3
- package/dist/pregel/reserved.js +0 -3
package/dist/graph/state.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { RunnableLambda, } from "@langchain/core/runnables";
|
|
2
1
|
import { BinaryOperatorAggregate } from "../channels/binop.js";
|
|
3
|
-
import { END, Graph } from "./graph.js";
|
|
2
|
+
import { END, CompiledGraph, Graph, START } from "./graph.js";
|
|
4
3
|
import { LastValue } from "../channels/last_value.js";
|
|
5
|
-
import { ChannelWrite } from "../pregel/write.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
4
|
+
import { ChannelWrite, PASSTHROUGH, SKIP_WRITE, } from "../pregel/write.js";
|
|
5
|
+
import { ChannelRead, PregelNode } from "../pregel/read.js";
|
|
6
|
+
import { NamedBarrierValue } from "../channels/named_barrier_value.js";
|
|
7
|
+
import { EphemeralValue } from "../channels/ephemeral_value.js";
|
|
8
|
+
import { RunnableCallable } from "../utils.js";
|
|
9
|
+
import { TAG_HIDDEN } from "../constants.js";
|
|
10
|
+
import { InvalidUpdateError } from "../errors.js";
|
|
11
|
+
import { DynamicBarrierValue } from "../channels/dynamic_barrier_value.js";
|
|
12
|
+
const ROOT = "__root__";
|
|
9
13
|
export class StateGraph extends Graph {
|
|
10
14
|
constructor(fields) {
|
|
11
15
|
super();
|
|
@@ -15,128 +19,258 @@ export class StateGraph extends Graph {
|
|
|
15
19
|
writable: true,
|
|
16
20
|
value: void 0
|
|
17
21
|
});
|
|
22
|
+
// TODO: this doesn't dedupe edges as in py, so worth fixing at some point
|
|
23
|
+
Object.defineProperty(this, "waitingEdges", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: new Set()
|
|
28
|
+
});
|
|
18
29
|
this.channels = _getChannels(fields.channels);
|
|
30
|
+
for (const c of Object.values(this.channels)) {
|
|
31
|
+
if (c.lc_graph_name === "BinaryOperatorAggregate") {
|
|
32
|
+
this.supportMultipleEdges = true;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
get allEdges() {
|
|
38
|
+
return new Set([
|
|
39
|
+
...this.edges,
|
|
40
|
+
...Array.from(this.waitingEdges).flatMap(([starts, end]) => starts.map((start) => [start, end])),
|
|
41
|
+
]);
|
|
19
42
|
}
|
|
20
43
|
addNode(key, action) {
|
|
21
|
-
if (
|
|
44
|
+
if (key in this.channels) {
|
|
22
45
|
throw new Error(`${key} is already being used as a state attribute (a.k.a. a channel), cannot also be used as a node name.`);
|
|
23
46
|
}
|
|
24
|
-
super.addNode(key, action);
|
|
47
|
+
return super.addNode(key, action);
|
|
25
48
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
throw new Error("Cannot use channel names as node names");
|
|
49
|
+
addEdge(startKey, endKey) {
|
|
50
|
+
if (typeof startKey === "string") {
|
|
51
|
+
return super.addEdge(startKey, endKey);
|
|
30
52
|
}
|
|
53
|
+
if (this.compiled) {
|
|
54
|
+
console.warn("Adding an edge to a graph that has already been compiled. This will " +
|
|
55
|
+
"not be reflected in the compiled graph.");
|
|
56
|
+
}
|
|
57
|
+
for (const start of startKey) {
|
|
58
|
+
if (start === END) {
|
|
59
|
+
throw new Error("END cannot be a start node");
|
|
60
|
+
}
|
|
61
|
+
if (!Object.keys(this.nodes).some((node) => node === start)) {
|
|
62
|
+
throw new Error(`Need to add_node ${start} first`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (endKey === END) {
|
|
66
|
+
throw new Error("END cannot be an end node");
|
|
67
|
+
}
|
|
68
|
+
if (!Object.keys(this.nodes).some((node) => node === endKey)) {
|
|
69
|
+
throw new Error(`Need to add_node ${endKey} first`);
|
|
70
|
+
}
|
|
71
|
+
this.waitingEdges.add([startKey, endKey]);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
compile({ checkpointer, interruptBefore, interruptAfter, } = {}) {
|
|
75
|
+
// validate the graph
|
|
76
|
+
this.validate([
|
|
77
|
+
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
78
|
+
...(Array.isArray(interruptAfter) ? interruptAfter : []),
|
|
79
|
+
]);
|
|
80
|
+
// prepare output channels
|
|
31
81
|
const stateKeys = Object.keys(this.channels);
|
|
32
|
-
const
|
|
82
|
+
const outputs = stateKeys.length === 1 && stateKeys[0] === ROOT
|
|
33
83
|
? stateKeys[0]
|
|
34
84
|
: stateKeys;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
85
|
+
// create empty compiled graph
|
|
86
|
+
const compiled = new CompiledStateGraph({
|
|
87
|
+
builder: this,
|
|
88
|
+
checkpointer,
|
|
89
|
+
interruptAfter,
|
|
90
|
+
interruptBefore,
|
|
91
|
+
autoValidate: false,
|
|
92
|
+
nodes: {},
|
|
93
|
+
channels: {
|
|
94
|
+
...this.channels,
|
|
95
|
+
[START]: new EphemeralValue(),
|
|
96
|
+
},
|
|
97
|
+
inputs: START,
|
|
98
|
+
outputs,
|
|
99
|
+
streamChannels: outputs,
|
|
100
|
+
streamMode: "updates",
|
|
101
|
+
});
|
|
102
|
+
// attach nodes, edges and branches
|
|
103
|
+
compiled.attachNode(START);
|
|
104
|
+
for (const [key, node] of Object.entries(this.nodes)) {
|
|
105
|
+
compiled.attachNode(key, node);
|
|
106
|
+
}
|
|
41
107
|
for (const [start, end] of this.edges) {
|
|
42
|
-
|
|
43
|
-
outgoingEdges[start] = [];
|
|
44
|
-
}
|
|
45
|
-
outgoingEdges[start].push(end !== END ? `${end}:inbox` : END);
|
|
108
|
+
compiled.attachEdge(start, end);
|
|
46
109
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
-
input, options) => updateState(key, input, options))
|
|
55
|
-
.pipe(Channel.writeTo(key));
|
|
56
|
-
}
|
|
57
|
-
for (const key of Object.keys(this.nodes)) {
|
|
58
|
-
const outgoing = outgoingEdges[key];
|
|
59
|
-
const edgesKey = `${key}:edges`;
|
|
60
|
-
if (outgoing || this.branches[key]) {
|
|
61
|
-
nodes[edgesKey] = Channel.subscribeTo(key, {
|
|
62
|
-
tags: ["langsmith:hidden"],
|
|
63
|
-
}).pipe(new ChannelRead(stateKeysRead));
|
|
64
|
-
}
|
|
65
|
-
if (outgoing) {
|
|
66
|
-
nodes[edgesKey] = nodes[edgesKey].pipe(Channel.writeTo(...outgoing));
|
|
67
|
-
}
|
|
68
|
-
if (this.branches[key]) {
|
|
69
|
-
for (const branch of this.branches[key]) {
|
|
70
|
-
nodes[edgesKey] = nodes[edgesKey].pipe(new RunnableLambda({
|
|
71
|
-
func: (i, c) => branch.runnable(i, c),
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
110
|
+
for (const [starts, end] of this.waitingEdges) {
|
|
111
|
+
compiled.attachEdge(starts, end);
|
|
112
|
+
}
|
|
113
|
+
for (const [start, branches] of Object.entries(this.branches)) {
|
|
114
|
+
for (const [name, branch] of Object.entries(branches)) {
|
|
115
|
+
compiled.attachBranch(start, name, branch);
|
|
74
116
|
}
|
|
75
117
|
}
|
|
76
|
-
|
|
77
|
-
tags: ["langsmith:hidden"],
|
|
78
|
-
})
|
|
79
|
-
.pipe((
|
|
80
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
|
-
input, options) => updateState(START, input, options))
|
|
82
|
-
.pipe(Channel.writeTo(START));
|
|
83
|
-
nodes[`${START}:edges`] = Channel.subscribeTo(START, {
|
|
84
|
-
tags: ["langsmith:hidden"],
|
|
85
|
-
})
|
|
86
|
-
.pipe(new ChannelRead(stateKeysRead))
|
|
87
|
-
.pipe(Channel.writeTo(`${this.entryPoint}:inbox`));
|
|
88
|
-
return new Pregel({
|
|
89
|
-
nodes,
|
|
90
|
-
channels: this.channels,
|
|
91
|
-
input: `${START}:inbox`,
|
|
92
|
-
output: END,
|
|
93
|
-
hidden: Object.keys(this.nodes)
|
|
94
|
-
.map((node) => `${node}:inbox`)
|
|
95
|
-
.concat(START, stateKeys),
|
|
96
|
-
checkpointer,
|
|
97
|
-
});
|
|
118
|
+
return compiled.validate();
|
|
98
119
|
}
|
|
99
120
|
}
|
|
100
|
-
function
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
121
|
+
function _getChannels(schema) {
|
|
122
|
+
const channels = {};
|
|
123
|
+
for (const [name, val] of Object.entries(schema)) {
|
|
124
|
+
if (name === ROOT) {
|
|
125
|
+
channels[name] = getChannel(val);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
const key = name;
|
|
129
|
+
channels[name] = getChannel(val);
|
|
130
|
+
}
|
|
110
131
|
}
|
|
111
|
-
|
|
112
|
-
return input;
|
|
132
|
+
return channels;
|
|
113
133
|
}
|
|
114
|
-
function
|
|
115
|
-
if (
|
|
116
|
-
|
|
134
|
+
function getChannel(reducer) {
|
|
135
|
+
if (reducer && "reducer" in reducer && reducer.reducer) {
|
|
136
|
+
return new BinaryOperatorAggregate(reducer.reducer, reducer.default);
|
|
137
|
+
}
|
|
138
|
+
if (reducer && "value" in reducer && reducer.value) {
|
|
139
|
+
return new BinaryOperatorAggregate(reducer.value, reducer.default);
|
|
117
140
|
}
|
|
118
|
-
|
|
119
|
-
__root__: input,
|
|
120
|
-
});
|
|
121
|
-
return input;
|
|
141
|
+
return new LastValue();
|
|
122
142
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
export class CompiledStateGraph extends CompiledGraph {
|
|
144
|
+
attachNode(key, node) {
|
|
145
|
+
const stateKeys = Object.keys(this.builder.channels);
|
|
146
|
+
function getStateKey(key, input) {
|
|
147
|
+
if (!input) {
|
|
148
|
+
return SKIP_WRITE;
|
|
149
|
+
}
|
|
150
|
+
else if (typeof input !== "object" || Array.isArray(input)) {
|
|
151
|
+
throw new InvalidUpdateError(`Expected dict, got ${typeof input}`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
return key in input ? input[key] : SKIP_WRITE;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// state updaters
|
|
158
|
+
const stateWriteEntries = stateKeys.map((key) => key === ROOT
|
|
159
|
+
? { channel: key, value: PASSTHROUGH, skipNone: true }
|
|
160
|
+
: {
|
|
161
|
+
channel: key,
|
|
162
|
+
value: PASSTHROUGH,
|
|
163
|
+
mapper: new RunnableCallable({
|
|
164
|
+
func: getStateKey.bind(null, key),
|
|
165
|
+
trace: false,
|
|
166
|
+
recurse: false,
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
// add node and output channel
|
|
170
|
+
if (key === START) {
|
|
171
|
+
this.nodes[key] = new PregelNode({
|
|
172
|
+
tags: [TAG_HIDDEN],
|
|
173
|
+
triggers: [START],
|
|
174
|
+
channels: [START],
|
|
175
|
+
writers: [new ChannelWrite(stateWriteEntries, [TAG_HIDDEN])],
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.channels[key] = new EphemeralValue();
|
|
180
|
+
this.nodes[key] = new PregelNode({
|
|
181
|
+
triggers: [],
|
|
182
|
+
// read state keys
|
|
183
|
+
channels: stateKeys.length === 1 && stateKeys[0] === ROOT
|
|
184
|
+
? stateKeys
|
|
185
|
+
: stateKeys.reduce((acc, k) => {
|
|
186
|
+
acc[k] = k;
|
|
187
|
+
return acc;
|
|
188
|
+
}, {}),
|
|
189
|
+
// publish to this channel and state keys
|
|
190
|
+
writers: [
|
|
191
|
+
new ChannelWrite(stateWriteEntries.concat({ channel: key, value: key }), [TAG_HIDDEN]),
|
|
192
|
+
],
|
|
193
|
+
bound: node,
|
|
194
|
+
});
|
|
127
195
|
}
|
|
128
|
-
return {
|
|
129
|
-
__root__: new BinaryOperatorAggregate(schema.value, schema.default),
|
|
130
|
-
};
|
|
131
196
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
197
|
+
attachEdge(start, end) {
|
|
198
|
+
if (end === END) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (Array.isArray(start)) {
|
|
202
|
+
const channelName = `join:${start.join("+")}:${end}`;
|
|
203
|
+
// register channel
|
|
204
|
+
this.channels[channelName] =
|
|
205
|
+
new NamedBarrierValue(new Set(start));
|
|
206
|
+
// subscribe to channel
|
|
207
|
+
this.nodes[end].triggers.push(channelName);
|
|
208
|
+
// publish to channel
|
|
209
|
+
for (const s of start) {
|
|
210
|
+
this.nodes[s].writers.push(new ChannelWrite([{ channel: channelName, value: s }], [TAG_HIDDEN]));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (start === START) {
|
|
214
|
+
const channelName = `start:${end}`;
|
|
215
|
+
// register channel
|
|
216
|
+
this.channels[channelName] =
|
|
217
|
+
new EphemeralValue();
|
|
218
|
+
// subscribe to channel
|
|
219
|
+
this.nodes[end].triggers.push(channelName);
|
|
220
|
+
// publish to channel
|
|
221
|
+
this.nodes[START].writers.push(new ChannelWrite([{ channel: channelName, value: START }], [TAG_HIDDEN]));
|
|
136
222
|
}
|
|
137
223
|
else {
|
|
138
|
-
|
|
224
|
+
this.nodes[end].triggers.push(start);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
attachBranch(start, name, branch) {
|
|
228
|
+
// attach branch publisher
|
|
229
|
+
this.nodes[start].writers.push(branch.compile(
|
|
230
|
+
// writer
|
|
231
|
+
(dests) => {
|
|
232
|
+
const filteredDests = dests.filter((dest) => dest !== END);
|
|
233
|
+
if (!filteredDests.length) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const writes = filteredDests.map((dest) => ({
|
|
237
|
+
channel: `branch:${start}:${name}:${dest}`,
|
|
238
|
+
value: start,
|
|
239
|
+
}));
|
|
240
|
+
if (branch.then && branch.then !== END) {
|
|
241
|
+
writes.push({
|
|
242
|
+
channel: `branch:${start}:${name}:then`,
|
|
243
|
+
value: { __names: filteredDests },
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
return new ChannelWrite(writes, [TAG_HIDDEN]);
|
|
247
|
+
},
|
|
248
|
+
// reader
|
|
249
|
+
(config) => ChannelRead.doRead(config, this.outputs, true)));
|
|
250
|
+
// attach branch subscribers
|
|
251
|
+
const ends = branch.ends
|
|
252
|
+
? Object.values(branch.ends)
|
|
253
|
+
: Object.keys(this.builder.nodes).filter((n) => n !== branch.then);
|
|
254
|
+
for (const end of ends) {
|
|
255
|
+
if (end === END) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const channelName = `branch:${start}:${name}:${end}`;
|
|
259
|
+
this.channels[channelName] =
|
|
260
|
+
new EphemeralValue();
|
|
261
|
+
this.nodes[end].triggers.push(channelName);
|
|
262
|
+
}
|
|
263
|
+
if (branch.then && branch.then !== END) {
|
|
264
|
+
const channelName = `branch:${start}:${name}:then`;
|
|
265
|
+
this.channels[channelName] =
|
|
266
|
+
new DynamicBarrierValue();
|
|
267
|
+
this.nodes[branch.then].triggers.push(channelName);
|
|
268
|
+
for (const end of ends) {
|
|
269
|
+
if (end === END) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
this.nodes[end].writers.push(new ChannelWrite([{ channel: channelName, value: end }], [TAG_HIDDEN]));
|
|
273
|
+
}
|
|
139
274
|
}
|
|
140
275
|
}
|
|
141
|
-
return channels;
|
|
142
276
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.EmptyChannelError = exports.InvalidUpdateError = exports.GraphValueError = exports.GraphRecursionError = exports.BaseCheckpointSaver = exports.emptyCheckpoint = exports.MemorySaver = exports.MessageGraph = exports.StateGraph = exports.START = exports.Graph = exports.END = void 0;
|
|
4
4
|
var index_js_1 = require("./graph/index.cjs");
|
|
5
5
|
Object.defineProperty(exports, "END", { enumerable: true, get: function () { return index_js_1.END; } });
|
|
6
6
|
Object.defineProperty(exports, "Graph", { enumerable: true, get: function () { return index_js_1.Graph; } });
|
|
@@ -9,7 +9,11 @@ Object.defineProperty(exports, "StateGraph", { enumerable: true, get: function (
|
|
|
9
9
|
Object.defineProperty(exports, "MessageGraph", { enumerable: true, get: function () { return index_js_1.MessageGraph; } });
|
|
10
10
|
var index_js_2 = require("./checkpoint/index.cjs");
|
|
11
11
|
Object.defineProperty(exports, "MemorySaver", { enumerable: true, get: function () { return index_js_2.MemorySaver; } });
|
|
12
|
-
Object.defineProperty(exports, "MemorySaverAssertImmutable", { enumerable: true, get: function () { return index_js_2.MemorySaverAssertImmutable; } });
|
|
13
12
|
var index_js_3 = require("./checkpoint/index.cjs");
|
|
14
13
|
Object.defineProperty(exports, "emptyCheckpoint", { enumerable: true, get: function () { return index_js_3.emptyCheckpoint; } });
|
|
15
14
|
Object.defineProperty(exports, "BaseCheckpointSaver", { enumerable: true, get: function () { return index_js_3.BaseCheckpointSaver; } });
|
|
15
|
+
var errors_js_1 = require("./errors.cjs");
|
|
16
|
+
Object.defineProperty(exports, "GraphRecursionError", { enumerable: true, get: function () { return errors_js_1.GraphRecursionError; } });
|
|
17
|
+
Object.defineProperty(exports, "GraphValueError", { enumerable: true, get: function () { return errors_js_1.GraphValueError; } });
|
|
18
|
+
Object.defineProperty(exports, "InvalidUpdateError", { enumerable: true, get: function () { return errors_js_1.InvalidUpdateError; } });
|
|
19
|
+
Object.defineProperty(exports, "EmptyChannelError", { enumerable: true, get: function () { return errors_js_1.EmptyChannelError; } });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { END, Graph, type StateGraphArgs, START, StateGraph, MessageGraph, } from "./graph/index.js";
|
|
2
|
-
export { MemorySaver
|
|
3
|
-
export { type
|
|
2
|
+
export { MemorySaver } from "./checkpoint/index.js";
|
|
3
|
+
export { type Checkpoint, emptyCheckpoint, BaseCheckpointSaver, } from "./checkpoint/index.js";
|
|
4
|
+
export { GraphRecursionError, GraphValueError, InvalidUpdateError, EmptyChannelError, } from "./errors.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { END, Graph, START, StateGraph, MessageGraph, } from "./graph/index.js";
|
|
2
|
-
export { MemorySaver
|
|
2
|
+
export { MemorySaver } from "./checkpoint/index.js";
|
|
3
3
|
export { emptyCheckpoint, BaseCheckpointSaver, } from "./checkpoint/index.js";
|
|
4
|
+
export { GraphRecursionError, GraphValueError, InvalidUpdateError, EmptyChannelError, } from "./errors.js";
|
|
@@ -4,27 +4,7 @@ exports.createAgentExecutor = void 0;
|
|
|
4
4
|
const tool_executor_js_1 = require("./tool_executor.cjs");
|
|
5
5
|
const state_js_1 = require("../graph/state.cjs");
|
|
6
6
|
const index_js_1 = require("../index.cjs");
|
|
7
|
-
|
|
8
|
-
function _getAgentState(inputSchema) {
|
|
9
|
-
if (!inputSchema) {
|
|
10
|
-
return {
|
|
11
|
-
input: {
|
|
12
|
-
value: null,
|
|
13
|
-
},
|
|
14
|
-
agentOutcome: {
|
|
15
|
-
value: null,
|
|
16
|
-
},
|
|
17
|
-
steps: {
|
|
18
|
-
value: (x, y) => x.concat(y),
|
|
19
|
-
default: () => [],
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
return inputSchema;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
7
|
+
function createAgentExecutor({ agentRunnable, tools, }) {
|
|
28
8
|
let toolExecutor;
|
|
29
9
|
if (!Array.isArray(tools)) {
|
|
30
10
|
toolExecutor = tools;
|
|
@@ -34,7 +14,6 @@ function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
34
14
|
tools,
|
|
35
15
|
});
|
|
36
16
|
}
|
|
37
|
-
const state = _getAgentState(inputSchema);
|
|
38
17
|
// Define logic that will be used to determine which conditional edge to go down
|
|
39
18
|
const shouldContinue = (data) => {
|
|
40
19
|
if (data.agentOutcome && "returnValues" in data.agentOutcome) {
|
|
@@ -60,16 +39,23 @@ function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
60
39
|
};
|
|
61
40
|
// Define a new graph
|
|
62
41
|
const workflow = new state_js_1.StateGraph({
|
|
63
|
-
channels:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
42
|
+
channels: {
|
|
43
|
+
input: null,
|
|
44
|
+
agentOutcome: null,
|
|
45
|
+
steps: {
|
|
46
|
+
reducer: (x, y) => x.concat(y),
|
|
47
|
+
default: () => [],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
// Define the two nodes we will cycle between
|
|
52
|
+
.addNode("agent", runAgent)
|
|
53
|
+
.addNode("action", executeTools)
|
|
54
|
+
// Set the entrypoint as `agent`
|
|
55
|
+
// This means that this node is the first one called
|
|
56
|
+
.addEdge(index_js_1.START, "agent")
|
|
57
|
+
// We now add a conditional edge
|
|
58
|
+
.addConditionalEdges(
|
|
73
59
|
// First, we define the start node. We use `agent`.
|
|
74
60
|
// This means these are the edges taken after the `agent` node is called.
|
|
75
61
|
"agent",
|
|
@@ -86,10 +72,10 @@ function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
86
72
|
continue: "action",
|
|
87
73
|
// Otherwise we finish.
|
|
88
74
|
end: index_js_1.END,
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
})
|
|
76
|
+
// We now add a normal edge from `tools` to `agent`.
|
|
77
|
+
// This means that after `tools` is called, `agent` node is called next.
|
|
78
|
+
.addEdge("action", "agent");
|
|
93
79
|
return workflow.compile();
|
|
94
80
|
}
|
|
95
81
|
exports.createAgentExecutor = createAgentExecutor;
|
|
@@ -3,21 +3,18 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
3
3
|
import { Runnable } from "@langchain/core/runnables";
|
|
4
4
|
import { Tool } from "@langchain/core/tools";
|
|
5
5
|
import { ToolExecutor } from "./tool_executor.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
interface Step {
|
|
7
|
+
action: AgentAction | AgentFinish;
|
|
8
|
+
observation: unknown;
|
|
9
|
+
}
|
|
10
|
+
export interface AgentExecutorState {
|
|
10
11
|
agentOutcome?: AgentAction | AgentFinish;
|
|
11
12
|
steps: Array<Step>;
|
|
12
|
-
}
|
|
13
|
-
export interface AgentExecutorState extends AgentStateBase {
|
|
14
13
|
input: string;
|
|
15
14
|
chatHistory?: BaseMessage[];
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
export declare function createAgentExecutor<T extends AgentExecutorState>({ agentRunnable, tools, inputSchema, }: {
|
|
16
|
+
export declare function createAgentExecutor({ agentRunnable, tools, }: {
|
|
19
17
|
agentRunnable: Runnable;
|
|
20
18
|
tools: Array<Tool> | ToolExecutor;
|
|
21
|
-
|
|
22
|
-
}): Pregel;
|
|
19
|
+
}): import("../graph/state.js").CompiledStateGraph<AgentExecutorState, Partial<AgentExecutorState>, "__start__" | "agent" | "action">;
|
|
23
20
|
export {};
|
|
@@ -1,27 +1,7 @@
|
|
|
1
1
|
import { ToolExecutor } from "./tool_executor.js";
|
|
2
2
|
import { StateGraph } from "../graph/state.js";
|
|
3
|
-
import { END } from "../index.js";
|
|
4
|
-
|
|
5
|
-
function _getAgentState(inputSchema) {
|
|
6
|
-
if (!inputSchema) {
|
|
7
|
-
return {
|
|
8
|
-
input: {
|
|
9
|
-
value: null,
|
|
10
|
-
},
|
|
11
|
-
agentOutcome: {
|
|
12
|
-
value: null,
|
|
13
|
-
},
|
|
14
|
-
steps: {
|
|
15
|
-
value: (x, y) => x.concat(y),
|
|
16
|
-
default: () => [],
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
return inputSchema;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
export function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
3
|
+
import { END, START } from "../index.js";
|
|
4
|
+
export function createAgentExecutor({ agentRunnable, tools, }) {
|
|
25
5
|
let toolExecutor;
|
|
26
6
|
if (!Array.isArray(tools)) {
|
|
27
7
|
toolExecutor = tools;
|
|
@@ -31,7 +11,6 @@ export function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
31
11
|
tools,
|
|
32
12
|
});
|
|
33
13
|
}
|
|
34
|
-
const state = _getAgentState(inputSchema);
|
|
35
14
|
// Define logic that will be used to determine which conditional edge to go down
|
|
36
15
|
const shouldContinue = (data) => {
|
|
37
16
|
if (data.agentOutcome && "returnValues" in data.agentOutcome) {
|
|
@@ -57,16 +36,23 @@ export function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
57
36
|
};
|
|
58
37
|
// Define a new graph
|
|
59
38
|
const workflow = new StateGraph({
|
|
60
|
-
channels:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
39
|
+
channels: {
|
|
40
|
+
input: null,
|
|
41
|
+
agentOutcome: null,
|
|
42
|
+
steps: {
|
|
43
|
+
reducer: (x, y) => x.concat(y),
|
|
44
|
+
default: () => [],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
// Define the two nodes we will cycle between
|
|
49
|
+
.addNode("agent", runAgent)
|
|
50
|
+
.addNode("action", executeTools)
|
|
51
|
+
// Set the entrypoint as `agent`
|
|
52
|
+
// This means that this node is the first one called
|
|
53
|
+
.addEdge(START, "agent")
|
|
54
|
+
// We now add a conditional edge
|
|
55
|
+
.addConditionalEdges(
|
|
70
56
|
// First, we define the start node. We use `agent`.
|
|
71
57
|
// This means these are the edges taken after the `agent` node is called.
|
|
72
58
|
"agent",
|
|
@@ -83,9 +69,9 @@ export function createAgentExecutor({ agentRunnable, tools, inputSchema, }) {
|
|
|
83
69
|
continue: "action",
|
|
84
70
|
// Otherwise we finish.
|
|
85
71
|
end: END,
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
})
|
|
73
|
+
// We now add a normal edge from `tools` to `agent`.
|
|
74
|
+
// This means that after `tools` is called, `agent` node is called next.
|
|
75
|
+
.addEdge("action", "agent");
|
|
90
76
|
return workflow.compile();
|
|
91
77
|
}
|
|
@@ -93,15 +93,15 @@ function createFunctionCallingExecutor({ model, tools, }) {
|
|
|
93
93
|
// Define a new graph
|
|
94
94
|
const workflow = new state_js_1.StateGraph({
|
|
95
95
|
channels: schema,
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
})
|
|
97
|
+
// Define the two nodes we will cycle between
|
|
98
|
+
.addNode("agent", new runnables_1.RunnableLambda({ func: callModel }))
|
|
99
|
+
.addNode("action", new runnables_1.RunnableLambda({ func: callTool }))
|
|
100
|
+
// Set the entrypoint as `agent`
|
|
101
|
+
// This means that this node is the first one called
|
|
102
|
+
.addEdge(index_js_1.START, "agent")
|
|
103
|
+
// We now add a conditional edge
|
|
104
|
+
.addConditionalEdges(
|
|
105
105
|
// First, we define the start node. We use `agent`.
|
|
106
106
|
// This means these are the edges taken after the `agent` node is called.
|
|
107
107
|
"agent",
|
|
@@ -118,10 +118,10 @@ function createFunctionCallingExecutor({ model, tools, }) {
|
|
|
118
118
|
continue: "action",
|
|
119
119
|
// Otherwise we finish.
|
|
120
120
|
end: index_js_1.END,
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
})
|
|
122
|
+
// We now add a normal edge from `tools` to `agent`.
|
|
123
|
+
// This means that after `tools` is called, `agent` node is called next.
|
|
124
|
+
.addEdge("action", "agent");
|
|
125
125
|
// Finally, we compile it!
|
|
126
126
|
// This compiles it into a LangChain Runnable,
|
|
127
127
|
// meaning you can use it as you would any other runnable
|