@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
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { BaseCheckpointSaver, } from "./base.js";
|
|
3
|
+
export class SqliteSaver extends BaseCheckpointSaver {
|
|
4
|
+
constructor(db, serde) {
|
|
5
|
+
super(serde);
|
|
6
|
+
Object.defineProperty(this, "db", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "isSetup", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
this.db = db;
|
|
19
|
+
this.isSetup = false;
|
|
20
|
+
}
|
|
21
|
+
static fromConnString(connStringOrLocalPath) {
|
|
22
|
+
return new SqliteSaver(new Database(connStringOrLocalPath));
|
|
23
|
+
}
|
|
24
|
+
setup() {
|
|
25
|
+
if (this.isSetup) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
this.db.pragma("journal_mode=WAL");
|
|
30
|
+
this.db.exec(`
|
|
31
|
+
CREATE TABLE IF NOT EXISTS checkpoints (
|
|
32
|
+
thread_id TEXT NOT NULL,
|
|
33
|
+
checkpoint_id TEXT NOT NULL,
|
|
34
|
+
parent_id TEXT,
|
|
35
|
+
checkpoint BLOB,
|
|
36
|
+
metadata BLOB,
|
|
37
|
+
PRIMARY KEY (thread_id, checkpoint_id)
|
|
38
|
+
);`);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.log("Error creating checkpoints table", error);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
this.isSetup = true;
|
|
45
|
+
}
|
|
46
|
+
async getTuple(config) {
|
|
47
|
+
this.setup();
|
|
48
|
+
const thread_id = config.configurable?.thread_id;
|
|
49
|
+
const checkpoint_id = config.configurable?.checkpoint_id;
|
|
50
|
+
if (checkpoint_id) {
|
|
51
|
+
try {
|
|
52
|
+
const row = this.db
|
|
53
|
+
.prepare(`SELECT checkpoint, parent_id, metadata FROM checkpoints WHERE thread_id = ? AND checkpoint_id = ?`)
|
|
54
|
+
.get(thread_id, checkpoint_id);
|
|
55
|
+
if (row) {
|
|
56
|
+
return {
|
|
57
|
+
config,
|
|
58
|
+
checkpoint: this.serde.parse(row.checkpoint),
|
|
59
|
+
metadata: this.serde.parse(row.metadata),
|
|
60
|
+
parentConfig: row.parent_id
|
|
61
|
+
? {
|
|
62
|
+
configurable: {
|
|
63
|
+
thread_id,
|
|
64
|
+
checkpoint_id: row.parent_id,
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
: undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.log("Error retrieving checkpoint", error);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const row = this.db
|
|
78
|
+
.prepare(`SELECT thread_id, checkpoint_id, parent_id, checkpoint, metadata FROM checkpoints WHERE thread_id = ? ORDER BY checkpoint_id DESC LIMIT 1`)
|
|
79
|
+
.get(thread_id);
|
|
80
|
+
if (row) {
|
|
81
|
+
return {
|
|
82
|
+
config: {
|
|
83
|
+
configurable: {
|
|
84
|
+
thread_id: row.thread_id,
|
|
85
|
+
checkpoint_id: row.checkpoint_id,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
checkpoint: this.serde.parse(row.checkpoint),
|
|
89
|
+
metadata: this.serde.parse(row.metadata),
|
|
90
|
+
parentConfig: row.parent_id
|
|
91
|
+
? {
|
|
92
|
+
configurable: {
|
|
93
|
+
thread_id: row.thread_id,
|
|
94
|
+
checkpoint_id: row.parent_id,
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
: undefined,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
async *list(config) {
|
|
104
|
+
this.setup();
|
|
105
|
+
const thread_id = config.configurable?.thread_id;
|
|
106
|
+
try {
|
|
107
|
+
const rows = this.db
|
|
108
|
+
.prepare(`SELECT thread_id, checkpoint_id, parent_id, checkpoint, metadata FROM checkpoints WHERE thread_id = ? ORDER BY checkpoint_id DESC`)
|
|
109
|
+
.all(thread_id);
|
|
110
|
+
if (rows) {
|
|
111
|
+
for (const row of rows) {
|
|
112
|
+
yield {
|
|
113
|
+
config: {
|
|
114
|
+
configurable: {
|
|
115
|
+
thread_id: row.thread_id,
|
|
116
|
+
checkpoint_id: row.checkpoint_id,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
checkpoint: this.serde.parse(row.checkpoint),
|
|
120
|
+
metadata: this.serde.parse(row.metadata),
|
|
121
|
+
parentConfig: row.parent_id
|
|
122
|
+
? {
|
|
123
|
+
configurable: {
|
|
124
|
+
thread_id: row.thread_id,
|
|
125
|
+
checkpoint_id: row.parent_id,
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
: undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.log("Error listing checkpoints", error);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async put(config, checkpoint, metadata) {
|
|
139
|
+
this.setup();
|
|
140
|
+
try {
|
|
141
|
+
const row = [
|
|
142
|
+
config.configurable?.thread_id,
|
|
143
|
+
checkpoint.id,
|
|
144
|
+
config.configurable?.checkpoint_id,
|
|
145
|
+
this.serde.stringify(checkpoint),
|
|
146
|
+
this.serde.stringify(metadata),
|
|
147
|
+
];
|
|
148
|
+
this.db
|
|
149
|
+
.prepare(`INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_id, parent_id, checkpoint, metadata) VALUES (?, ?, ?, ?, ?)`)
|
|
150
|
+
.run(...row);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.log("Error saving checkpoint", error);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
configurable: {
|
|
158
|
+
thread_id: config.configurable?.thread_id,
|
|
159
|
+
checkpoint_id: checkpoint.id,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
package/dist/constants.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONFIG_KEY_READ = exports.CONFIG_KEY_SEND = void 0;
|
|
3
|
+
exports.TAG_HIDDEN = exports.INTERRUPT = exports.CONFIG_KEY_READ = exports.CONFIG_KEY_SEND = void 0;
|
|
4
4
|
exports.CONFIG_KEY_SEND = "__pregel_send";
|
|
5
5
|
exports.CONFIG_KEY_READ = "__pregel_read";
|
|
6
|
+
exports.INTERRUPT = "__interrupt__";
|
|
7
|
+
exports.TAG_HIDDEN = "langsmith:hidden";
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
package/dist/errors.cjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidUpdateError = exports.EmptyChannelError = exports.GraphValueError = exports.GraphRecursionError = void 0;
|
|
4
|
+
class GraphRecursionError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "GraphRecursionError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.GraphRecursionError = GraphRecursionError;
|
|
11
|
+
class GraphValueError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "GraphValueError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.GraphValueError = GraphValueError;
|
|
18
|
+
class EmptyChannelError extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "EmptyChannelError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.EmptyChannelError = EmptyChannelError;
|
|
25
|
+
class InvalidUpdateError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "InvalidUpdateError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.InvalidUpdateError = InvalidUpdateError;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class GraphRecursionError extends Error {
|
|
2
|
+
constructor(message?: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class GraphValueError extends Error {
|
|
5
|
+
constructor(message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class EmptyChannelError extends Error {
|
|
8
|
+
constructor(message?: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class InvalidUpdateError extends Error {
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class GraphRecursionError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "GraphRecursionError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class GraphValueError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "GraphValueError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class EmptyChannelError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "EmptyChannelError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class InvalidUpdateError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "InvalidUpdateError";
|
|
23
|
+
}
|
|
24
|
+
}
|
package/dist/graph/graph.cjs
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Graph = exports.END = void 0;
|
|
3
|
+
exports.CompiledGraph = exports.Graph = exports.Branch = exports.END = exports.START = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
4
5
|
const runnables_1 = require("@langchain/core/runnables");
|
|
6
|
+
const read_js_1 = require("../pregel/read.cjs");
|
|
5
7
|
const index_js_1 = require("../pregel/index.cjs");
|
|
8
|
+
const ephemeral_value_js_1 = require("../channels/ephemeral_value.cjs");
|
|
9
|
+
const write_js_1 = require("../pregel/write.cjs");
|
|
10
|
+
const constants_js_1 = require("../constants.cjs");
|
|
11
|
+
const utils_js_1 = require("../utils.cjs");
|
|
12
|
+
exports.START = "__start__";
|
|
6
13
|
exports.END = "__end__";
|
|
7
14
|
class Branch {
|
|
8
|
-
constructor(
|
|
15
|
+
constructor(options) {
|
|
9
16
|
Object.defineProperty(this, "condition", {
|
|
10
17
|
enumerable: true,
|
|
11
18
|
configurable: true,
|
|
@@ -18,22 +25,42 @@ class Branch {
|
|
|
18
25
|
writable: true,
|
|
19
26
|
value: void 0
|
|
20
27
|
});
|
|
21
|
-
this
|
|
22
|
-
|
|
28
|
+
Object.defineProperty(this, "then", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
this.condition = options.path;
|
|
35
|
+
this.ends = Array.isArray(options.pathMap)
|
|
36
|
+
? options.pathMap.reduce((acc, n) => {
|
|
37
|
+
acc[n] = n;
|
|
38
|
+
return acc;
|
|
39
|
+
}, {})
|
|
40
|
+
: options.pathMap;
|
|
41
|
+
this.then = options.then;
|
|
42
|
+
}
|
|
43
|
+
compile(writer, reader) {
|
|
44
|
+
return write_js_1.ChannelWrite.registerWriter(new utils_js_1.RunnableCallable({
|
|
45
|
+
func: (input, config) => this._route(input, config, writer, reader),
|
|
46
|
+
}));
|
|
23
47
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
48
|
+
async _route(input, config, writer, reader) {
|
|
49
|
+
let result = await this.condition(reader ? reader(config) : input, config);
|
|
50
|
+
if (!Array.isArray(result)) {
|
|
51
|
+
result = [result];
|
|
52
|
+
}
|
|
53
|
+
let destinations;
|
|
28
54
|
if (this.ends) {
|
|
29
|
-
|
|
55
|
+
destinations = result.map((r) => this.ends[r]);
|
|
30
56
|
}
|
|
31
57
|
else {
|
|
32
|
-
|
|
58
|
+
destinations = result;
|
|
33
59
|
}
|
|
34
|
-
return
|
|
60
|
+
return writer(destinations);
|
|
35
61
|
}
|
|
36
62
|
}
|
|
63
|
+
exports.Branch = Branch;
|
|
37
64
|
class Graph {
|
|
38
65
|
constructor() {
|
|
39
66
|
Object.defineProperty(this, "nodes", {
|
|
@@ -66,6 +93,12 @@ class Graph {
|
|
|
66
93
|
writable: true,
|
|
67
94
|
value: false
|
|
68
95
|
});
|
|
96
|
+
Object.defineProperty(this, "supportMultipleEdges", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
writable: true,
|
|
100
|
+
value: false
|
|
101
|
+
});
|
|
69
102
|
this.nodes = {};
|
|
70
103
|
this.edges = new Set();
|
|
71
104
|
this.branches = {};
|
|
@@ -75,129 +108,175 @@ class Graph {
|
|
|
75
108
|
console.warn(message);
|
|
76
109
|
}
|
|
77
110
|
}
|
|
111
|
+
get allEdges() {
|
|
112
|
+
return this.edges;
|
|
113
|
+
}
|
|
78
114
|
addNode(key, action) {
|
|
79
115
|
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
80
|
-
if (this.nodes
|
|
116
|
+
if (key in this.nodes) {
|
|
81
117
|
throw new Error(`Node \`${key}\` already present.`);
|
|
82
118
|
}
|
|
83
119
|
if (key === exports.END) {
|
|
84
120
|
throw new Error(`Node \`${key}\` is reserved.`);
|
|
85
121
|
}
|
|
86
122
|
this.nodes[key] = (0, runnables_1._coerceToRunnable)(action);
|
|
123
|
+
return this;
|
|
87
124
|
}
|
|
88
125
|
addEdge(startKey, endKey) {
|
|
89
126
|
this.warnIfCompiled(`Adding an edge to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
90
127
|
if (startKey === exports.END) {
|
|
91
128
|
throw new Error("END cannot be a start node");
|
|
92
129
|
}
|
|
93
|
-
if (
|
|
94
|
-
throw new Error(
|
|
95
|
-
}
|
|
96
|
-
if (!this.nodes[endKey] && endKey !== exports.END) {
|
|
97
|
-
throw new Error(`Need to addNode \`${endKey}\` first`);
|
|
130
|
+
if (endKey === exports.START) {
|
|
131
|
+
throw new Error("START cannot be an end node");
|
|
98
132
|
}
|
|
99
|
-
|
|
100
|
-
|
|
133
|
+
if (!this.supportMultipleEdges &&
|
|
134
|
+
Array.from(this.edges).some(([start]) => start === startKey)) {
|
|
101
135
|
throw new Error(`Already found path for ${startKey}`);
|
|
102
136
|
}
|
|
103
137
|
this.edges.add([startKey, endKey]);
|
|
138
|
+
return this;
|
|
104
139
|
}
|
|
105
|
-
addConditionalEdges(
|
|
140
|
+
addConditionalEdges(source, path, pathMap) {
|
|
141
|
+
const options = typeof source === "object" ? source : { source, path: path, pathMap };
|
|
106
142
|
this.warnIfCompiled("Adding an edge to a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
throw new Error(
|
|
112
|
-
}
|
|
113
|
-
if (conditionalEdgeMapping) {
|
|
114
|
-
const mappingValues = Array.from(Object.values(conditionalEdgeMapping));
|
|
115
|
-
const nodesValues = Object.keys(this.nodes);
|
|
116
|
-
const endExcluded = mappingValues.filter((value) => value !== exports.END);
|
|
117
|
-
const difference = endExcluded.filter((value) => !nodesValues.some((nv) => nv === value));
|
|
118
|
-
if (difference.length > 0) {
|
|
119
|
-
throw new Error(`Missing nodes which are in conditional edge mapping.\nMapping contains possible destinations: ${mappingValues.join(", ")}.\nPossible nodes are ${nodesValues.join(", ")}.`);
|
|
120
|
-
}
|
|
143
|
+
// find a name for condition
|
|
144
|
+
const name = options.path.name || "condition";
|
|
145
|
+
// validate condition
|
|
146
|
+
if (this.branches[options.source] && this.branches[options.source][name]) {
|
|
147
|
+
throw new Error(`Condition \`${name}\` already present for node \`${source}\``);
|
|
121
148
|
}
|
|
122
|
-
|
|
123
|
-
|
|
149
|
+
// save it
|
|
150
|
+
if (!this.branches[options.source]) {
|
|
151
|
+
this.branches[options.source] = {};
|
|
124
152
|
}
|
|
125
|
-
this.branches[
|
|
153
|
+
this.branches[options.source][name] = new Branch(options);
|
|
154
|
+
return this;
|
|
126
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* @deprecated use `addEdge(START, key)` instead
|
|
158
|
+
*/
|
|
127
159
|
setEntryPoint(key) {
|
|
128
160
|
this.warnIfCompiled("Setting the entry point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
129
|
-
|
|
130
|
-
throw new Error(`Need to addNode \`${key}\` first`);
|
|
131
|
-
}
|
|
132
|
-
this.entryPoint = key;
|
|
161
|
+
return this.addEdge(exports.START, key);
|
|
133
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* @deprecated use `addEdge(key, END)` instead
|
|
165
|
+
*/
|
|
134
166
|
setFinishPoint(key) {
|
|
135
167
|
this.warnIfCompiled("Setting a finish point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
136
|
-
this.addEdge(key, exports.END);
|
|
137
|
-
}
|
|
138
|
-
compile(checkpointer) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
168
|
+
return this.addEdge(key, exports.END);
|
|
169
|
+
}
|
|
170
|
+
compile({ checkpointer, interruptBefore, interruptAfter, } = {}) {
|
|
171
|
+
// validate the graph
|
|
172
|
+
this.validate([
|
|
173
|
+
...(Array.isArray(interruptBefore) ? interruptBefore : []),
|
|
174
|
+
...(Array.isArray(interruptAfter) ? interruptAfter : []),
|
|
175
|
+
]);
|
|
176
|
+
// create empty compiled graph
|
|
177
|
+
const compiled = new CompiledGraph({
|
|
178
|
+
builder: this,
|
|
179
|
+
checkpointer,
|
|
180
|
+
interruptAfter,
|
|
181
|
+
interruptBefore,
|
|
182
|
+
autoValidate: false,
|
|
183
|
+
nodes: {},
|
|
184
|
+
channels: {
|
|
185
|
+
[exports.START]: new ephemeral_value_js_1.EphemeralValue(),
|
|
186
|
+
[exports.END]: new ephemeral_value_js_1.EphemeralValue(),
|
|
187
|
+
},
|
|
188
|
+
inputs: exports.START,
|
|
189
|
+
outputs: exports.END,
|
|
190
|
+
streamChannels: [],
|
|
191
|
+
streamMode: "values",
|
|
146
192
|
});
|
|
147
|
-
|
|
193
|
+
// attach nodes, edges and branches
|
|
148
194
|
for (const [key, node] of Object.entries(this.nodes)) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
nodes[edgesKey] = index_js_1.Channel.subscribeTo(key, {
|
|
158
|
-
tags: ["langsmith:hidden"],
|
|
159
|
-
});
|
|
195
|
+
compiled.attachNode(key, node);
|
|
196
|
+
}
|
|
197
|
+
for (const [start, end] of this.edges) {
|
|
198
|
+
compiled.attachEdge(start, end);
|
|
199
|
+
}
|
|
200
|
+
for (const [start, branches] of Object.entries(this.branches)) {
|
|
201
|
+
for (const [name, branch] of Object.entries(branches)) {
|
|
202
|
+
compiled.attachBranch(start, name, branch);
|
|
160
203
|
}
|
|
161
|
-
|
|
162
|
-
|
|
204
|
+
}
|
|
205
|
+
return compiled.validate();
|
|
206
|
+
}
|
|
207
|
+
validate(interrupt) {
|
|
208
|
+
// assemble sources
|
|
209
|
+
const allSources = new Set([...this.allEdges].map(([src, _]) => src));
|
|
210
|
+
for (const [start, branches] of Object.entries(this.branches)) {
|
|
211
|
+
allSources.add(start);
|
|
212
|
+
for (const branch of Object.values(branches)) {
|
|
213
|
+
if (branch.then) {
|
|
214
|
+
if (branch.ends) {
|
|
215
|
+
for (const end of Object.values(branch.ends)) {
|
|
216
|
+
if (end !== exports.END) {
|
|
217
|
+
allSources.add(end);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
for (const node of Object.keys(this.nodes)) {
|
|
223
|
+
if (node !== start) {
|
|
224
|
+
allSources.add(node);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// validate sources
|
|
232
|
+
for (const node of Object.keys(this.nodes)) {
|
|
233
|
+
if (!allSources.has(node)) {
|
|
234
|
+
throw new Error(`Node \`${node}\` is a dead-end`);
|
|
163
235
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
});
|
|
169
|
-
nodes[edgesKey] = nodes[edgesKey].pipe(runnableLambda);
|
|
170
|
-
});
|
|
236
|
+
}
|
|
237
|
+
for (const source of allSources) {
|
|
238
|
+
if (source !== exports.START && !(source in this.nodes)) {
|
|
239
|
+
throw new Error(`Found edge starting at unknown node \`${source}\``);
|
|
171
240
|
}
|
|
172
241
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
242
|
+
// assemble targets
|
|
243
|
+
const allTargets = new Set([...this.allEdges].map(([_, target]) => target));
|
|
244
|
+
for (const [start, branches] of Object.entries(this.branches)) {
|
|
245
|
+
for (const branch of Object.values(branches)) {
|
|
246
|
+
if (branch.then) {
|
|
247
|
+
allTargets.add(branch.then);
|
|
248
|
+
}
|
|
249
|
+
if (branch.ends) {
|
|
250
|
+
for (const end of Object.values(branch.ends)) {
|
|
251
|
+
allTargets.add(end);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
allTargets.add(exports.END);
|
|
256
|
+
for (const node of Object.keys(this.nodes)) {
|
|
257
|
+
if (node !== start && node !== branch.then) {
|
|
258
|
+
allTargets.add(node);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
176
263
|
}
|
|
177
|
-
|
|
178
|
-
nodes,
|
|
179
|
-
input: `${this.entryPoint}:inbox`,
|
|
180
|
-
output: exports.END,
|
|
181
|
-
hidden,
|
|
182
|
-
checkpointer,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
validate() {
|
|
186
|
-
const allStarts = new Set([...this.edges].map(([src, _]) => src).concat(Object.keys(this.branches)));
|
|
264
|
+
// validate targets
|
|
187
265
|
for (const node of Object.keys(this.nodes)) {
|
|
188
|
-
if (!
|
|
189
|
-
throw new Error(`Node \`${node}\` is
|
|
266
|
+
if (!allTargets.has(node)) {
|
|
267
|
+
throw new Error(`Node \`${node}\` is not reachable`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
for (const target of allTargets) {
|
|
271
|
+
if (target !== exports.END && !(target in this.nodes)) {
|
|
272
|
+
throw new Error(`Found edge ending at unknown node \`${target}\``);
|
|
190
273
|
}
|
|
191
274
|
}
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
.concat(this.entryPoint ? [this.entryPoint] : []));
|
|
198
|
-
for (const node of Object.keys(this.nodes)) {
|
|
199
|
-
if (!allEnds.has(node)) {
|
|
200
|
-
throw new Error(`Node \`${node}\` is not reachable`);
|
|
275
|
+
// validate interrupts
|
|
276
|
+
if (interrupt) {
|
|
277
|
+
for (const node of interrupt) {
|
|
278
|
+
if (!(node in this.nodes)) {
|
|
279
|
+
throw new Error(`Interrupt node \`${node}\` is not present`);
|
|
201
280
|
}
|
|
202
281
|
}
|
|
203
282
|
}
|
|
@@ -205,3 +284,62 @@ class Graph {
|
|
|
205
284
|
}
|
|
206
285
|
}
|
|
207
286
|
exports.Graph = Graph;
|
|
287
|
+
class CompiledGraph extends index_js_1.Pregel {
|
|
288
|
+
constructor({ builder, ...rest }) {
|
|
289
|
+
super(rest);
|
|
290
|
+
Object.defineProperty(this, "builder", {
|
|
291
|
+
enumerable: true,
|
|
292
|
+
configurable: true,
|
|
293
|
+
writable: true,
|
|
294
|
+
value: void 0
|
|
295
|
+
});
|
|
296
|
+
this.builder = builder;
|
|
297
|
+
}
|
|
298
|
+
attachNode(key, node) {
|
|
299
|
+
this.channels[key] = new ephemeral_value_js_1.EphemeralValue();
|
|
300
|
+
this.nodes[key] = new read_js_1.PregelNode({
|
|
301
|
+
channels: [],
|
|
302
|
+
triggers: [],
|
|
303
|
+
})
|
|
304
|
+
.pipe(node)
|
|
305
|
+
.pipe(new write_js_1.ChannelWrite([{ channel: key, value: write_js_1.PASSTHROUGH }], [constants_js_1.TAG_HIDDEN]));
|
|
306
|
+
this.streamChannels.push(key);
|
|
307
|
+
}
|
|
308
|
+
attachEdge(start, end) {
|
|
309
|
+
if (end === exports.END) {
|
|
310
|
+
if (start === exports.START) {
|
|
311
|
+
throw new Error("Cannot have an edge from START to END");
|
|
312
|
+
}
|
|
313
|
+
this.nodes[start].writers.push(new write_js_1.ChannelWrite([{ channel: exports.END, value: write_js_1.PASSTHROUGH }], [constants_js_1.TAG_HIDDEN]));
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
this.nodes[end].triggers.push(start);
|
|
317
|
+
this.nodes[end].channels.push(start);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
attachBranch(start, name, branch) {
|
|
321
|
+
// add hidden start node
|
|
322
|
+
if (start === exports.START && this.nodes[exports.START]) {
|
|
323
|
+
this.nodes[exports.START] = index_js_1.Channel.subscribeTo(exports.START, { tags: [constants_js_1.TAG_HIDDEN] });
|
|
324
|
+
}
|
|
325
|
+
// attach branch writer
|
|
326
|
+
this.nodes[start].pipe(branch.compile((dests) => {
|
|
327
|
+
const channels = dests.map((dest) => dest === exports.END ? exports.END : `branch:${start}:${name}:${dest}`);
|
|
328
|
+
return new write_js_1.ChannelWrite(channels.map((channel) => ({ channel, value: write_js_1.PASSTHROUGH })), [constants_js_1.TAG_HIDDEN]);
|
|
329
|
+
}));
|
|
330
|
+
// attach branch readers
|
|
331
|
+
const ends = branch.ends
|
|
332
|
+
? Object.values(branch.ends)
|
|
333
|
+
: Object.keys(this.nodes);
|
|
334
|
+
for (const end of ends) {
|
|
335
|
+
if (end !== exports.END) {
|
|
336
|
+
const channelName = `branch:${start}:${name}:${end}`;
|
|
337
|
+
this.channels[channelName] =
|
|
338
|
+
new ephemeral_value_js_1.EphemeralValue();
|
|
339
|
+
this.nodes[end].triggers.push(channelName);
|
|
340
|
+
this.nodes[end].channels.push(channelName);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
exports.CompiledGraph = CompiledGraph;
|