@langchain/langgraph 0.2.72 → 0.2.74
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 +1 -1
- package/dist/channels/any_value.js +1 -1
- package/dist/channels/any_value.js.map +1 -1
- package/dist/channels/base.cjs +4 -4
- package/dist/channels/base.js.map +1 -1
- package/dist/channels/binop.cjs +1 -1
- package/dist/channels/binop.js +1 -1
- package/dist/channels/binop.js.map +1 -1
- package/dist/channels/dynamic_barrier_value.cjs +1 -1
- package/dist/channels/dynamic_barrier_value.js +1 -1
- package/dist/channels/dynamic_barrier_value.js.map +1 -1
- package/dist/channels/ephemeral_value.cjs +1 -1
- package/dist/channels/ephemeral_value.js +1 -1
- package/dist/channels/ephemeral_value.js.map +1 -1
- package/dist/channels/last_value.cjs +1 -1
- package/dist/channels/last_value.js +1 -1
- package/dist/channels/last_value.js.map +1 -1
- package/dist/channels/named_barrier_value.cjs +1 -1
- package/dist/channels/named_barrier_value.js +1 -1
- package/dist/channels/named_barrier_value.js.map +1 -1
- package/dist/channels/topic.cjs +1 -1
- package/dist/channels/topic.js +1 -1
- package/dist/channels/topic.js.map +1 -1
- package/dist/constants.cjs +5 -5
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/errors.cjs +5 -5
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/func/index.cjs +3 -3
- package/dist/func/index.js.map +1 -1
- package/dist/func/types.cjs +1 -2
- package/dist/graph/annotation.cjs +2 -2
- package/dist/graph/annotation.js.map +1 -1
- package/dist/graph/graph.cjs +46 -40
- package/dist/graph/graph.d.ts +10 -2
- package/dist/graph/graph.js +46 -40
- package/dist/graph/graph.js.map +1 -1
- package/dist/graph/index.cjs +2 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/index.js +1 -1
- package/dist/graph/index.js.map +1 -1
- package/dist/graph/message.cjs +43 -5
- package/dist/graph/message.d.ts +5 -0
- package/dist/graph/message.js +40 -3
- package/dist/graph/message.js.map +1 -1
- package/dist/graph/message.test.cjs +196 -0
- package/dist/graph/message.test.d.ts +1 -0
- package/dist/graph/message.test.js +194 -0
- package/dist/graph/message.test.js.map +1 -0
- package/dist/graph/messages_annotation.cjs +51 -1
- package/dist/graph/messages_annotation.d.ts +47 -0
- package/dist/graph/messages_annotation.js +50 -0
- package/dist/graph/messages_annotation.js.map +1 -1
- package/dist/graph/state.cjs +102 -89
- package/dist/graph/state.d.ts +16 -3
- package/dist/graph/state.js +102 -89
- package/dist/graph/state.js.map +1 -1
- package/dist/graph/zod/plugin.js.map +1 -1
- package/dist/graph/zod/schema.cjs +5 -6
- package/dist/graph/zod/schema.js.map +1 -1
- package/dist/graph/zod/state.cjs +6 -7
- package/dist/graph/zod/state.js.map +1 -1
- package/dist/interrupt.cjs +1 -2
- package/dist/interrupt.js.map +1 -1
- package/dist/managed/base.cjs +3 -3
- package/dist/managed/base.js.map +1 -1
- package/dist/managed/shared_value.js.map +1 -1
- package/dist/prebuilt/agentName.cjs +3 -4
- package/dist/prebuilt/agentName.js.map +1 -1
- package/dist/prebuilt/agent_executor.cjs +1 -2
- package/dist/prebuilt/agent_executor.d.ts +1 -1
- package/dist/prebuilt/agent_executor.js.map +1 -1
- package/dist/prebuilt/chat_agent_executor.cjs +1 -2
- package/dist/prebuilt/chat_agent_executor.js.map +1 -1
- package/dist/prebuilt/react_agent_executor.cjs +4 -4
- package/dist/prebuilt/react_agent_executor.d.ts +2 -2
- package/dist/prebuilt/react_agent_executor.js.map +1 -1
- package/dist/prebuilt/tool_executor.js.map +1 -1
- package/dist/prebuilt/tool_node.cjs +2 -2
- package/dist/prebuilt/tool_node.js.map +1 -1
- package/dist/pregel/algo.cjs +8 -7
- package/dist/pregel/algo.js +1 -0
- package/dist/pregel/algo.js.map +1 -1
- package/dist/pregel/call.cjs +3 -4
- package/dist/pregel/call.js.map +1 -1
- package/dist/pregel/debug.cjs +10 -10
- package/dist/pregel/debug.d.ts +3 -3
- package/dist/pregel/debug.js.map +1 -1
- package/dist/pregel/debug.test.cjs +31 -31
- package/dist/pregel/debug.test.js +12 -12
- package/dist/pregel/debug.test.js.map +1 -1
- package/dist/pregel/index.js.map +1 -1
- package/dist/pregel/io.cjs +8 -9
- package/dist/pregel/io.js +2 -2
- package/dist/pregel/io.js.map +1 -1
- package/dist/pregel/io.mapCommand.test.cjs +29 -29
- package/dist/pregel/io.mapCommand.test.js +5 -5
- package/dist/pregel/io.mapCommand.test.js.map +1 -1
- package/dist/pregel/loop.js.map +1 -1
- package/dist/pregel/messages.cjs +15 -13
- package/dist/pregel/messages.d.ts +1 -1
- package/dist/pregel/messages.js +15 -13
- package/dist/pregel/messages.js.map +1 -1
- package/dist/pregel/messages.test.cjs +105 -105
- package/dist/pregel/messages.test.js +31 -31
- package/dist/pregel/messages.test.js.map +1 -1
- package/dist/pregel/read.js.map +1 -1
- package/dist/pregel/read.test.cjs +35 -35
- package/dist/pregel/read.test.js +4 -4
- package/dist/pregel/read.test.js.map +1 -1
- package/dist/pregel/remote.js.map +1 -1
- package/dist/pregel/retry.cjs +10 -10
- package/dist/pregel/retry.js +8 -8
- package/dist/pregel/retry.js.map +1 -1
- package/dist/pregel/runner.cjs +91 -118
- package/dist/pregel/runner.js +92 -119
- package/dist/pregel/runner.js.map +1 -1
- package/dist/pregel/runner.test.cjs +14 -14
- package/dist/pregel/runner.test.js +4 -4
- package/dist/pregel/runner.test.js.map +1 -1
- package/dist/pregel/stream.js.map +1 -1
- package/dist/pregel/types.cjs +2 -2
- package/dist/pregel/types.js.map +1 -1
- package/dist/pregel/utils/config.cjs +40 -22
- package/dist/pregel/utils/config.d.ts +8 -5
- package/dist/pregel/utils/config.js +33 -14
- package/dist/pregel/utils/config.js.map +1 -1
- package/dist/pregel/utils/config.test.cjs +58 -58
- package/dist/pregel/utils/config.test.js +12 -12
- package/dist/pregel/utils/config.test.js.map +1 -1
- package/dist/pregel/utils/index.cjs +12 -11
- package/dist/pregel/utils/index.js +6 -4
- package/dist/pregel/utils/index.js.map +1 -1
- package/dist/pregel/utils/subgraph.cjs +2 -3
- package/dist/pregel/utils/subgraph.js.map +1 -1
- package/dist/pregel/utils/subgraph.test.cjs +18 -18
- package/dist/pregel/utils/subgraph.test.js +1 -1
- package/dist/pregel/utils/subgraph.test.js.map +1 -1
- package/dist/pregel/validate.cjs +3 -3
- package/dist/pregel/validate.js.map +1 -1
- package/dist/pregel/validate.test.cjs +43 -43
- package/dist/pregel/validate.test.js +3 -3
- package/dist/pregel/validate.test.js.map +1 -1
- package/dist/pregel/write.js.map +1 -1
- package/dist/pregel/write.test.cjs +30 -30
- package/dist/pregel/write.test.js +8 -8
- package/dist/pregel/write.test.js.map +1 -1
- package/dist/setup/async_local_storage.cjs +1 -2
- package/dist/utils.cjs +7 -7
- package/dist/utils.js.map +1 -1
- package/dist/web.cjs +3 -1
- package/dist/web.d.ts +2 -2
- package/dist/web.js +2 -2
- package/dist/web.js.map +1 -1
- package/package.json +11 -11
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
import { Annotation } from "./annotation.js";
|
|
3
4
|
import { messagesStateReducer } from "./message.js";
|
|
5
|
+
import { withLangGraph } from "./zod/state.js";
|
|
4
6
|
/**
|
|
5
7
|
* Prebuilt state annotation that combines returned messages.
|
|
6
8
|
* Can handle standard messages and special modifiers like {@link RemoveMessage}
|
|
@@ -42,4 +44,52 @@ export const MessagesAnnotation = Annotation.Root({
|
|
|
42
44
|
default: () => [],
|
|
43
45
|
}),
|
|
44
46
|
});
|
|
47
|
+
/**
|
|
48
|
+
* Prebuilt state object that uses Zod to combine returned messages.
|
|
49
|
+
* This utility is synonymous with the `MessagesAnnotation` annotation,
|
|
50
|
+
* but uses Zod as the way to express messages state.
|
|
51
|
+
*
|
|
52
|
+
* You can use import and use this prebuilt schema like this:
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { MessagesZodState, StateGraph } from "@langchain/langgraph";
|
|
57
|
+
*
|
|
58
|
+
* const graph = new StateGraph(MessagesZodState)
|
|
59
|
+
* .addNode(...)
|
|
60
|
+
* ...
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* Which is equivalent to initializing the schema object manually like this:
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { z } from "zod";
|
|
68
|
+
* import type { BaseMessage, BaseMessageLike } from "@langchain/core/messages";
|
|
69
|
+
* import { StateGraph, messagesStateReducer } from "@langchain/langgraph";
|
|
70
|
+
* import "@langchain/langgraph/zod";
|
|
71
|
+
*
|
|
72
|
+
* const AgentState = z.object({
|
|
73
|
+
* messages: z
|
|
74
|
+
* .custom<BaseMessage[]>()
|
|
75
|
+
* .default(() => [])
|
|
76
|
+
* .langgraph.reducer(
|
|
77
|
+
* messagesStateReducer,
|
|
78
|
+
* z.custom<BaseMessageLike | BaseMessageLike[]>()
|
|
79
|
+
* ),
|
|
80
|
+
* });
|
|
81
|
+
* const graph = new StateGraph(AgentState)
|
|
82
|
+
* .addNode(...)
|
|
83
|
+
* ...
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const MessagesZodState = z.object({
|
|
87
|
+
messages: withLangGraph(z.custom(), {
|
|
88
|
+
reducer: {
|
|
89
|
+
schema: z.custom(),
|
|
90
|
+
fn: messagesStateReducer,
|
|
91
|
+
},
|
|
92
|
+
default: () => [],
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
45
95
|
//# sourceMappingURL=messages_annotation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages_annotation.js","sourceRoot":"","sources":["../../src/graph/messages_annotation.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAG1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAY,oBAAoB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"messages_annotation.js","sourceRoot":"","sources":["../../src/graph/messages_annotation.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAG1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAY,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC,IAAI,CAAC;IAChD,QAAQ,EAAE,UAAU,CAA0B;QAC5C,OAAO,EAAE,oBAAoB;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;CACH,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,MAAM,EAAiB,EAAE;QACjD,OAAO,EAAE;YACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAY;YAC5B,EAAE,EAAE,oBAAoB;SACzB;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;KAClB,CAAC;CACH,CAAC,CAAC"}
|
package/dist/graph/state.cjs
CHANGED
|
@@ -246,54 +246,76 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
-
addNode(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
249
|
+
addNode(...args) {
|
|
250
|
+
function isMultipleNodes(args) {
|
|
251
|
+
return args.length >= 1 && typeof args[0] !== "string";
|
|
252
|
+
}
|
|
253
|
+
const nodes = (isMultipleNodes(args) // eslint-disable-line no-nested-ternary
|
|
254
|
+
? Array.isArray(args[0])
|
|
255
|
+
? args[0]
|
|
256
|
+
: Object.entries(args[0])
|
|
257
|
+
: [[args[0], args[1], args[2]]]);
|
|
258
|
+
if (nodes.length === 0) {
|
|
259
|
+
throw new Error("No nodes provided in `addNode`");
|
|
260
|
+
}
|
|
261
|
+
for (const [key, action, options] of nodes) {
|
|
262
|
+
if (key in this.channels) {
|
|
263
|
+
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.`);
|
|
259
264
|
}
|
|
265
|
+
for (const reservedChar of [
|
|
266
|
+
constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR,
|
|
267
|
+
constants_js_1.CHECKPOINT_NAMESPACE_END,
|
|
268
|
+
]) {
|
|
269
|
+
if (key.includes(reservedChar)) {
|
|
270
|
+
throw new Error(`"${reservedChar}" is a reserved character and is not allowed in node names.`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
274
|
+
if (key in this.nodes) {
|
|
275
|
+
throw new Error(`Node \`${key}\` already present.`);
|
|
276
|
+
}
|
|
277
|
+
if (key === constants_js_1.END || key === constants_js_1.START) {
|
|
278
|
+
throw new Error(`Node \`${key}\` is reserved.`);
|
|
279
|
+
}
|
|
280
|
+
let inputSpec = this._schemaDefinition;
|
|
281
|
+
if (options?.input !== undefined) {
|
|
282
|
+
if ((0, state_js_1.isAnyZodObject)(options.input)) {
|
|
283
|
+
inputSpec = (0, state_js_1.getChannelsFromZod)(options.input);
|
|
284
|
+
}
|
|
285
|
+
else if (options.input.spec !== undefined) {
|
|
286
|
+
inputSpec = options.input.spec;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (inputSpec !== undefined) {
|
|
290
|
+
this._addSchema(inputSpec);
|
|
291
|
+
}
|
|
292
|
+
let runnable;
|
|
293
|
+
if (runnables_1.Runnable.isRunnable(action)) {
|
|
294
|
+
runnable = action;
|
|
295
|
+
}
|
|
296
|
+
else if (typeof action === "function") {
|
|
297
|
+
runnable = new utils_js_1.RunnableCallable({
|
|
298
|
+
func: action,
|
|
299
|
+
name: key,
|
|
300
|
+
trace: false,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
runnable = (0, runnables_1._coerceToRunnable)(action);
|
|
305
|
+
}
|
|
306
|
+
const nodeSpec = {
|
|
307
|
+
runnable: runnable,
|
|
308
|
+
retryPolicy: options?.retryPolicy,
|
|
309
|
+
metadata: options?.metadata,
|
|
310
|
+
input: inputSpec ?? this._schemaDefinition,
|
|
311
|
+
subgraphs: (0, subgraph_js_1.isPregelLike)(runnable)
|
|
312
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
313
|
+
[runnable]
|
|
314
|
+
: options?.subgraphs,
|
|
315
|
+
ends: options?.ends,
|
|
316
|
+
};
|
|
317
|
+
this.nodes[key] = nodeSpec;
|
|
260
318
|
}
|
|
261
|
-
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
262
|
-
if (key in this.nodes) {
|
|
263
|
-
throw new Error(`Node \`${key}\` already present.`);
|
|
264
|
-
}
|
|
265
|
-
if (key === constants_js_1.END || key === constants_js_1.START) {
|
|
266
|
-
throw new Error(`Node \`${key}\` is reserved.`);
|
|
267
|
-
}
|
|
268
|
-
if (options?.input !== undefined) {
|
|
269
|
-
this._addSchema(options.input.spec);
|
|
270
|
-
}
|
|
271
|
-
let runnable;
|
|
272
|
-
if (runnables_1.Runnable.isRunnable(action)) {
|
|
273
|
-
runnable = action;
|
|
274
|
-
}
|
|
275
|
-
else if (typeof action === "function") {
|
|
276
|
-
runnable = new utils_js_1.RunnableCallable({
|
|
277
|
-
func: action,
|
|
278
|
-
name: key,
|
|
279
|
-
trace: false,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
runnable = (0, runnables_1._coerceToRunnable)(action);
|
|
284
|
-
}
|
|
285
|
-
const nodeSpec = {
|
|
286
|
-
runnable: runnable,
|
|
287
|
-
retryPolicy: options?.retryPolicy,
|
|
288
|
-
metadata: options?.metadata,
|
|
289
|
-
input: options?.input?.spec ?? this._schemaDefinition,
|
|
290
|
-
subgraphs: (0, subgraph_js_1.isPregelLike)(runnable)
|
|
291
|
-
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
|
-
[runnable]
|
|
293
|
-
: options?.subgraphs,
|
|
294
|
-
ends: options?.ends,
|
|
295
|
-
};
|
|
296
|
-
this.nodes[key] = nodeSpec;
|
|
297
319
|
return this;
|
|
298
320
|
}
|
|
299
321
|
addEdge(startKey, endKey) {
|
|
@@ -321,6 +343,27 @@ class StateGraph extends graph_js_1.Graph {
|
|
|
321
343
|
this.waitingEdges.add([startKey, endKey]);
|
|
322
344
|
return this;
|
|
323
345
|
}
|
|
346
|
+
addSequence(nodes) {
|
|
347
|
+
const parsedNodes = Array.isArray(nodes)
|
|
348
|
+
? nodes
|
|
349
|
+
: Object.entries(nodes);
|
|
350
|
+
if (parsedNodes.length === 0) {
|
|
351
|
+
throw new Error("Sequence requires at least one node.");
|
|
352
|
+
}
|
|
353
|
+
let previousNode;
|
|
354
|
+
for (const [key, action, options] of parsedNodes) {
|
|
355
|
+
if (key in this.nodes) {
|
|
356
|
+
throw new Error(`Node names must be unique: node with the name "${key}" already exists.`);
|
|
357
|
+
}
|
|
358
|
+
const validKey = key;
|
|
359
|
+
this.addNode(validKey, action, options);
|
|
360
|
+
if (previousNode != null) {
|
|
361
|
+
this.addEdge(previousNode, validKey);
|
|
362
|
+
}
|
|
363
|
+
previousNode = validKey;
|
|
364
|
+
}
|
|
365
|
+
return this;
|
|
366
|
+
}
|
|
324
367
|
compile({ checkpointer, store, interruptBefore, interruptAfter, name, } = {}) {
|
|
325
368
|
// validate the graph
|
|
326
369
|
this.validate([
|
|
@@ -507,15 +550,14 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
507
550
|
const inputDefinition = node?.input ?? this.builder._schemaDefinition;
|
|
508
551
|
const inputValues = Object.fromEntries(Object.keys(this.builder._schemaDefinitions.get(inputDefinition)).map((k) => [k, k]));
|
|
509
552
|
const isSingleInput = Object.keys(inputValues).length === 1 && ROOT in inputValues;
|
|
510
|
-
|
|
553
|
+
const branchChannel = `branch:to:${key}`;
|
|
554
|
+
this.channels[branchChannel] = new ephemeral_value_js_1.EphemeralValue(false);
|
|
511
555
|
this.nodes[key] = new read_js_1.PregelNode({
|
|
512
|
-
triggers: [],
|
|
556
|
+
triggers: [branchChannel],
|
|
513
557
|
// read state keys
|
|
514
558
|
channels: isSingleInput ? Object.keys(inputValues) : inputValues,
|
|
515
|
-
// publish to
|
|
516
|
-
writers: [
|
|
517
|
-
new write_js_1.ChannelWrite(stateWriteEntries.concat({ channel: key, value: key }), [constants_js_1.TAG_HIDDEN]),
|
|
518
|
-
],
|
|
559
|
+
// publish to state keys
|
|
560
|
+
writers: [new write_js_1.ChannelWrite(stateWriteEntries, [constants_js_1.TAG_HIDDEN])],
|
|
519
561
|
mapper: isSingleInput
|
|
520
562
|
? undefined
|
|
521
563
|
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -531,10 +573,12 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
531
573
|
}
|
|
532
574
|
}
|
|
533
575
|
attachEdge(start, end) {
|
|
534
|
-
if (end === constants_js_1.END)
|
|
576
|
+
if (end === constants_js_1.END)
|
|
535
577
|
return;
|
|
578
|
+
if (typeof start === "string") {
|
|
579
|
+
this.nodes[start].writers.push(new write_js_1.ChannelWrite([{ channel: `branch:to:${end}`, value: null }], [constants_js_1.TAG_HIDDEN]));
|
|
536
580
|
}
|
|
537
|
-
if (Array.isArray(start)) {
|
|
581
|
+
else if (Array.isArray(start)) {
|
|
538
582
|
const channelName = `join:${start.join("+")}:${end}`;
|
|
539
583
|
// register channel
|
|
540
584
|
this.channels[channelName] =
|
|
@@ -546,34 +590,16 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
546
590
|
this.nodes[s].writers.push(new write_js_1.ChannelWrite([{ channel: channelName, value: s }], [constants_js_1.TAG_HIDDEN]));
|
|
547
591
|
}
|
|
548
592
|
}
|
|
549
|
-
else if (start === constants_js_1.START) {
|
|
550
|
-
const channelName = `${constants_js_1.START}:${end}`;
|
|
551
|
-
// register channel
|
|
552
|
-
this.channels[channelName] =
|
|
553
|
-
new ephemeral_value_js_1.EphemeralValue();
|
|
554
|
-
// subscribe to channel
|
|
555
|
-
this.nodes[end].triggers.push(channelName);
|
|
556
|
-
// publish to channel
|
|
557
|
-
this.nodes[constants_js_1.START].writers.push(new write_js_1.ChannelWrite([{ channel: channelName, value: constants_js_1.START }], [constants_js_1.TAG_HIDDEN]));
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
this.nodes[end].triggers.push(start);
|
|
561
|
-
}
|
|
562
593
|
}
|
|
563
|
-
attachBranch(start,
|
|
594
|
+
attachBranch(start, _, branch, options = { withReader: true }) {
|
|
564
595
|
const branchWriter = async (packets, config) => {
|
|
565
596
|
const filteredPackets = packets.filter((p) => p !== constants_js_1.END);
|
|
566
|
-
if (!filteredPackets.length)
|
|
597
|
+
if (!filteredPackets.length)
|
|
567
598
|
return;
|
|
568
|
-
}
|
|
569
599
|
const writes = filteredPackets.map((p) => {
|
|
570
|
-
if ((0, constants_js_1._isSend)(p))
|
|
600
|
+
if ((0, constants_js_1._isSend)(p))
|
|
571
601
|
return p;
|
|
572
|
-
}
|
|
573
|
-
return {
|
|
574
|
-
channel: `branch:${start}:${name}:${p}`,
|
|
575
|
-
value: start,
|
|
576
|
-
};
|
|
602
|
+
return { channel: `branch:to:${p}`, value: start };
|
|
577
603
|
});
|
|
578
604
|
await write_js_1.ChannelWrite.doWrite({ ...config, tags: (config.tags ?? []).concat([constants_js_1.TAG_HIDDEN]) }, writes);
|
|
579
605
|
};
|
|
@@ -583,19 +609,6 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
|
|
|
583
609
|
options.withReader
|
|
584
610
|
? (config) => read_js_1.ChannelRead.doRead(config, this.streamChannels ?? this.outputChannels, true)
|
|
585
611
|
: undefined));
|
|
586
|
-
// attach branch subscribers
|
|
587
|
-
const ends = branch.ends
|
|
588
|
-
? Object.values(branch.ends)
|
|
589
|
-
: Object.keys(this.builder.nodes);
|
|
590
|
-
for (const end of ends) {
|
|
591
|
-
if (end === constants_js_1.END) {
|
|
592
|
-
continue;
|
|
593
|
-
}
|
|
594
|
-
const channelName = `branch:${start}:${name}:${end}`;
|
|
595
|
-
this.channels[channelName] =
|
|
596
|
-
new ephemeral_value_js_1.EphemeralValue(false);
|
|
597
|
-
this.nodes[end].triggers.push(channelName);
|
|
598
|
-
}
|
|
599
612
|
}
|
|
600
613
|
async _validateInput(input) {
|
|
601
614
|
const inputSchema = this.builder._inputRuntimeDefinition;
|
package/dist/graph/state.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type StateGraphNodeSpec<RunInput, RunOutput> = NodeSpec<RunInput, RunOutp
|
|
|
24
24
|
};
|
|
25
25
|
export type StateGraphAddNodeOptions = {
|
|
26
26
|
retryPolicy?: RetryPolicy;
|
|
27
|
-
input?: AnnotationRoot<any
|
|
27
|
+
input?: AnnotationRoot<any> | AnyZodObject;
|
|
28
28
|
} & AddNodeOptions;
|
|
29
29
|
export type StateGraphArgsWithStateSchema<SD extends StateDefinition, I extends StateDefinition, O extends StateDefinition> = {
|
|
30
30
|
stateSchema: AnnotationRoot<SD>;
|
|
@@ -42,6 +42,8 @@ type ZodStateGraphArgsWithStateSchema<SD extends AnyZodObject, I extends SDZod,
|
|
|
42
42
|
};
|
|
43
43
|
type SDZod = StateDefinition | AnyZodObject;
|
|
44
44
|
type ToStateDefinition<T> = T extends AnyZodObject ? ZodToStateDefinition<T> : T extends StateDefinition ? T : never;
|
|
45
|
+
type NodeAction<S, U, C extends SDZod> = RunnableLike<S, U extends object ? U & Record<string, any> : U, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
46
|
+
LangGraphRunnableConfig<StateType<ToStateDefinition<C>>>>;
|
|
45
47
|
/**
|
|
46
48
|
* A graph whose nodes communicate by reading and writing to a shared state.
|
|
47
49
|
* Each node takes a defined `State` as input and returns a `Partial<State>`.
|
|
@@ -133,8 +135,19 @@ export declare class StateGraph<SD extends SDZod | unknown, S = SD extends SDZod
|
|
|
133
135
|
constructor(fields: SD extends AnyZodObject ? SD | ZodStateGraphArgsWithStateSchema<SD, I, O> : never, configSchema?: C | AnnotationRoot<ToStateDefinition<C>>);
|
|
134
136
|
get allEdges(): Set<[string, string]>;
|
|
135
137
|
_addSchema(stateDefinition: SDZod): void;
|
|
136
|
-
addNode<K extends string
|
|
138
|
+
addNode<K extends string>(nodes: Record<K, NodeAction<S, U, C>> | [
|
|
139
|
+
key: K,
|
|
140
|
+
action: NodeAction<S, U, C>,
|
|
141
|
+
options?: StateGraphAddNodeOptions
|
|
142
|
+
][]): StateGraph<SD, S, U, N | K, I, O, C>;
|
|
143
|
+
addNode<K extends string, NodeInput = S>(key: K, action: NodeAction<NodeInput, U, C>, options?: StateGraphAddNodeOptions): StateGraph<SD, S, U, N | K, I, O, C>;
|
|
137
144
|
addEdge(startKey: typeof START | N | N[], endKey: N | typeof END): this;
|
|
145
|
+
addSequence<K extends string>(nodes: [
|
|
146
|
+
key: K,
|
|
147
|
+
action: NodeAction<S, U, C>,
|
|
148
|
+
options?: StateGraphAddNodeOptions
|
|
149
|
+
][]): StateGraph<SD, S, U, N | K, I, O, C>;
|
|
150
|
+
addSequence<K extends string>(nodes: Record<K, NodeAction<S, U, C>>): StateGraph<SD, S, U, N | K, I, O, C>;
|
|
138
151
|
compile({ checkpointer, store, interruptBefore, interruptAfter, name, }?: {
|
|
139
152
|
checkpointer?: BaseCheckpointSaver | false;
|
|
140
153
|
store?: BaseStore;
|
|
@@ -153,7 +166,7 @@ export declare class CompiledStateGraph<S, U, N extends string = typeof START, I
|
|
|
153
166
|
attachNode(key: typeof START, node?: never): void;
|
|
154
167
|
attachNode(key: N, node: StateGraphNodeSpec<S, U>): void;
|
|
155
168
|
attachEdge(start: N | N[] | "__start__", end: N | "__end__"): void;
|
|
156
|
-
attachBranch(start: N | typeof START,
|
|
169
|
+
attachBranch(start: N | typeof START, _: string, branch: Branch<S, N>, options?: {
|
|
157
170
|
withReader?: boolean;
|
|
158
171
|
}): void;
|
|
159
172
|
protected _validateInput(input: UpdateType<ToStateDefinition<I>>): Promise<UpdateType<ToStateDefinition<I>>>;
|
package/dist/graph/state.js
CHANGED
|
@@ -243,54 +243,76 @@ export class StateGraph extends Graph {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
|
-
addNode(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
246
|
+
addNode(...args) {
|
|
247
|
+
function isMultipleNodes(args) {
|
|
248
|
+
return args.length >= 1 && typeof args[0] !== "string";
|
|
249
|
+
}
|
|
250
|
+
const nodes = (isMultipleNodes(args) // eslint-disable-line no-nested-ternary
|
|
251
|
+
? Array.isArray(args[0])
|
|
252
|
+
? args[0]
|
|
253
|
+
: Object.entries(args[0])
|
|
254
|
+
: [[args[0], args[1], args[2]]]);
|
|
255
|
+
if (nodes.length === 0) {
|
|
256
|
+
throw new Error("No nodes provided in `addNode`");
|
|
257
|
+
}
|
|
258
|
+
for (const [key, action, options] of nodes) {
|
|
259
|
+
if (key in this.channels) {
|
|
260
|
+
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.`);
|
|
256
261
|
}
|
|
262
|
+
for (const reservedChar of [
|
|
263
|
+
CHECKPOINT_NAMESPACE_SEPARATOR,
|
|
264
|
+
CHECKPOINT_NAMESPACE_END,
|
|
265
|
+
]) {
|
|
266
|
+
if (key.includes(reservedChar)) {
|
|
267
|
+
throw new Error(`"${reservedChar}" is a reserved character and is not allowed in node names.`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
271
|
+
if (key in this.nodes) {
|
|
272
|
+
throw new Error(`Node \`${key}\` already present.`);
|
|
273
|
+
}
|
|
274
|
+
if (key === END || key === START) {
|
|
275
|
+
throw new Error(`Node \`${key}\` is reserved.`);
|
|
276
|
+
}
|
|
277
|
+
let inputSpec = this._schemaDefinition;
|
|
278
|
+
if (options?.input !== undefined) {
|
|
279
|
+
if (isAnyZodObject(options.input)) {
|
|
280
|
+
inputSpec = getChannelsFromZod(options.input);
|
|
281
|
+
}
|
|
282
|
+
else if (options.input.spec !== undefined) {
|
|
283
|
+
inputSpec = options.input.spec;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (inputSpec !== undefined) {
|
|
287
|
+
this._addSchema(inputSpec);
|
|
288
|
+
}
|
|
289
|
+
let runnable;
|
|
290
|
+
if (Runnable.isRunnable(action)) {
|
|
291
|
+
runnable = action;
|
|
292
|
+
}
|
|
293
|
+
else if (typeof action === "function") {
|
|
294
|
+
runnable = new RunnableCallable({
|
|
295
|
+
func: action,
|
|
296
|
+
name: key,
|
|
297
|
+
trace: false,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
runnable = _coerceToRunnable(action);
|
|
302
|
+
}
|
|
303
|
+
const nodeSpec = {
|
|
304
|
+
runnable: runnable,
|
|
305
|
+
retryPolicy: options?.retryPolicy,
|
|
306
|
+
metadata: options?.metadata,
|
|
307
|
+
input: inputSpec ?? this._schemaDefinition,
|
|
308
|
+
subgraphs: isPregelLike(runnable)
|
|
309
|
+
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
310
|
+
[runnable]
|
|
311
|
+
: options?.subgraphs,
|
|
312
|
+
ends: options?.ends,
|
|
313
|
+
};
|
|
314
|
+
this.nodes[key] = nodeSpec;
|
|
257
315
|
}
|
|
258
|
-
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
259
|
-
if (key in this.nodes) {
|
|
260
|
-
throw new Error(`Node \`${key}\` already present.`);
|
|
261
|
-
}
|
|
262
|
-
if (key === END || key === START) {
|
|
263
|
-
throw new Error(`Node \`${key}\` is reserved.`);
|
|
264
|
-
}
|
|
265
|
-
if (options?.input !== undefined) {
|
|
266
|
-
this._addSchema(options.input.spec);
|
|
267
|
-
}
|
|
268
|
-
let runnable;
|
|
269
|
-
if (Runnable.isRunnable(action)) {
|
|
270
|
-
runnable = action;
|
|
271
|
-
}
|
|
272
|
-
else if (typeof action === "function") {
|
|
273
|
-
runnable = new RunnableCallable({
|
|
274
|
-
func: action,
|
|
275
|
-
name: key,
|
|
276
|
-
trace: false,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
runnable = _coerceToRunnable(action);
|
|
281
|
-
}
|
|
282
|
-
const nodeSpec = {
|
|
283
|
-
runnable: runnable,
|
|
284
|
-
retryPolicy: options?.retryPolicy,
|
|
285
|
-
metadata: options?.metadata,
|
|
286
|
-
input: options?.input?.spec ?? this._schemaDefinition,
|
|
287
|
-
subgraphs: isPregelLike(runnable)
|
|
288
|
-
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
289
|
-
[runnable]
|
|
290
|
-
: options?.subgraphs,
|
|
291
|
-
ends: options?.ends,
|
|
292
|
-
};
|
|
293
|
-
this.nodes[key] = nodeSpec;
|
|
294
316
|
return this;
|
|
295
317
|
}
|
|
296
318
|
addEdge(startKey, endKey) {
|
|
@@ -318,6 +340,27 @@ export class StateGraph extends Graph {
|
|
|
318
340
|
this.waitingEdges.add([startKey, endKey]);
|
|
319
341
|
return this;
|
|
320
342
|
}
|
|
343
|
+
addSequence(nodes) {
|
|
344
|
+
const parsedNodes = Array.isArray(nodes)
|
|
345
|
+
? nodes
|
|
346
|
+
: Object.entries(nodes);
|
|
347
|
+
if (parsedNodes.length === 0) {
|
|
348
|
+
throw new Error("Sequence requires at least one node.");
|
|
349
|
+
}
|
|
350
|
+
let previousNode;
|
|
351
|
+
for (const [key, action, options] of parsedNodes) {
|
|
352
|
+
if (key in this.nodes) {
|
|
353
|
+
throw new Error(`Node names must be unique: node with the name "${key}" already exists.`);
|
|
354
|
+
}
|
|
355
|
+
const validKey = key;
|
|
356
|
+
this.addNode(validKey, action, options);
|
|
357
|
+
if (previousNode != null) {
|
|
358
|
+
this.addEdge(previousNode, validKey);
|
|
359
|
+
}
|
|
360
|
+
previousNode = validKey;
|
|
361
|
+
}
|
|
362
|
+
return this;
|
|
363
|
+
}
|
|
321
364
|
compile({ checkpointer, store, interruptBefore, interruptAfter, name, } = {}) {
|
|
322
365
|
// validate the graph
|
|
323
366
|
this.validate([
|
|
@@ -503,15 +546,14 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
503
546
|
const inputDefinition = node?.input ?? this.builder._schemaDefinition;
|
|
504
547
|
const inputValues = Object.fromEntries(Object.keys(this.builder._schemaDefinitions.get(inputDefinition)).map((k) => [k, k]));
|
|
505
548
|
const isSingleInput = Object.keys(inputValues).length === 1 && ROOT in inputValues;
|
|
506
|
-
|
|
549
|
+
const branchChannel = `branch:to:${key}`;
|
|
550
|
+
this.channels[branchChannel] = new EphemeralValue(false);
|
|
507
551
|
this.nodes[key] = new PregelNode({
|
|
508
|
-
triggers: [],
|
|
552
|
+
triggers: [branchChannel],
|
|
509
553
|
// read state keys
|
|
510
554
|
channels: isSingleInput ? Object.keys(inputValues) : inputValues,
|
|
511
|
-
// publish to
|
|
512
|
-
writers: [
|
|
513
|
-
new ChannelWrite(stateWriteEntries.concat({ channel: key, value: key }), [TAG_HIDDEN]),
|
|
514
|
-
],
|
|
555
|
+
// publish to state keys
|
|
556
|
+
writers: [new ChannelWrite(stateWriteEntries, [TAG_HIDDEN])],
|
|
515
557
|
mapper: isSingleInput
|
|
516
558
|
? undefined
|
|
517
559
|
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -527,10 +569,12 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
527
569
|
}
|
|
528
570
|
}
|
|
529
571
|
attachEdge(start, end) {
|
|
530
|
-
if (end === END)
|
|
572
|
+
if (end === END)
|
|
531
573
|
return;
|
|
574
|
+
if (typeof start === "string") {
|
|
575
|
+
this.nodes[start].writers.push(new ChannelWrite([{ channel: `branch:to:${end}`, value: null }], [TAG_HIDDEN]));
|
|
532
576
|
}
|
|
533
|
-
if (Array.isArray(start)) {
|
|
577
|
+
else if (Array.isArray(start)) {
|
|
534
578
|
const channelName = `join:${start.join("+")}:${end}`;
|
|
535
579
|
// register channel
|
|
536
580
|
this.channels[channelName] =
|
|
@@ -542,34 +586,16 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
542
586
|
this.nodes[s].writers.push(new ChannelWrite([{ channel: channelName, value: s }], [TAG_HIDDEN]));
|
|
543
587
|
}
|
|
544
588
|
}
|
|
545
|
-
else if (start === START) {
|
|
546
|
-
const channelName = `${START}:${end}`;
|
|
547
|
-
// register channel
|
|
548
|
-
this.channels[channelName] =
|
|
549
|
-
new EphemeralValue();
|
|
550
|
-
// subscribe to channel
|
|
551
|
-
this.nodes[end].triggers.push(channelName);
|
|
552
|
-
// publish to channel
|
|
553
|
-
this.nodes[START].writers.push(new ChannelWrite([{ channel: channelName, value: START }], [TAG_HIDDEN]));
|
|
554
|
-
}
|
|
555
|
-
else {
|
|
556
|
-
this.nodes[end].triggers.push(start);
|
|
557
|
-
}
|
|
558
589
|
}
|
|
559
|
-
attachBranch(start,
|
|
590
|
+
attachBranch(start, _, branch, options = { withReader: true }) {
|
|
560
591
|
const branchWriter = async (packets, config) => {
|
|
561
592
|
const filteredPackets = packets.filter((p) => p !== END);
|
|
562
|
-
if (!filteredPackets.length)
|
|
593
|
+
if (!filteredPackets.length)
|
|
563
594
|
return;
|
|
564
|
-
}
|
|
565
595
|
const writes = filteredPackets.map((p) => {
|
|
566
|
-
if (_isSend(p))
|
|
596
|
+
if (_isSend(p))
|
|
567
597
|
return p;
|
|
568
|
-
}
|
|
569
|
-
return {
|
|
570
|
-
channel: `branch:${start}:${name}:${p}`,
|
|
571
|
-
value: start,
|
|
572
|
-
};
|
|
598
|
+
return { channel: `branch:to:${p}`, value: start };
|
|
573
599
|
});
|
|
574
600
|
await ChannelWrite.doWrite({ ...config, tags: (config.tags ?? []).concat([TAG_HIDDEN]) }, writes);
|
|
575
601
|
};
|
|
@@ -579,19 +605,6 @@ export class CompiledStateGraph extends CompiledGraph {
|
|
|
579
605
|
options.withReader
|
|
580
606
|
? (config) => ChannelRead.doRead(config, this.streamChannels ?? this.outputChannels, true)
|
|
581
607
|
: undefined));
|
|
582
|
-
// attach branch subscribers
|
|
583
|
-
const ends = branch.ends
|
|
584
|
-
? Object.values(branch.ends)
|
|
585
|
-
: Object.keys(this.builder.nodes);
|
|
586
|
-
for (const end of ends) {
|
|
587
|
-
if (end === END) {
|
|
588
|
-
continue;
|
|
589
|
-
}
|
|
590
|
-
const channelName = `branch:${start}:${name}:${end}`;
|
|
591
|
-
this.channels[channelName] =
|
|
592
|
-
new EphemeralValue(false);
|
|
593
|
-
this.nodes[end].triggers.push(channelName);
|
|
594
|
-
}
|
|
595
608
|
}
|
|
596
609
|
async _validateInput(input) {
|
|
597
610
|
const inputSchema = this.builder._inputRuntimeDefinition;
|