@langchain/langgraph 0.0.12 → 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 +235 -95
- package/dist/graph/graph.d.ts +52 -23
- package/dist/graph/graph.js +234 -96
- 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 +11 -7
- 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,23 +25,42 @@ class Branch {
|
|
|
18
25
|
writable: true,
|
|
19
26
|
value: void 0
|
|
20
27
|
});
|
|
21
|
-
this
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
+
}));
|
|
47
|
+
}
|
|
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;
|
|
29
54
|
if (this.ends) {
|
|
30
|
-
|
|
55
|
+
destinations = result.map((r) => this.ends[r]);
|
|
31
56
|
}
|
|
32
57
|
else {
|
|
33
|
-
|
|
58
|
+
destinations = result;
|
|
34
59
|
}
|
|
35
|
-
return
|
|
60
|
+
return writer(destinations);
|
|
36
61
|
}
|
|
37
62
|
}
|
|
63
|
+
exports.Branch = Branch;
|
|
38
64
|
class Graph {
|
|
39
65
|
constructor() {
|
|
40
66
|
Object.defineProperty(this, "nodes", {
|
|
@@ -67,6 +93,12 @@ class Graph {
|
|
|
67
93
|
writable: true,
|
|
68
94
|
value: false
|
|
69
95
|
});
|
|
96
|
+
Object.defineProperty(this, "supportMultipleEdges", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
writable: true,
|
|
100
|
+
value: false
|
|
101
|
+
});
|
|
70
102
|
this.nodes = {};
|
|
71
103
|
this.edges = new Set();
|
|
72
104
|
this.branches = {};
|
|
@@ -76,126 +108,175 @@ class Graph {
|
|
|
76
108
|
console.warn(message);
|
|
77
109
|
}
|
|
78
110
|
}
|
|
111
|
+
get allEdges() {
|
|
112
|
+
return this.edges;
|
|
113
|
+
}
|
|
79
114
|
addNode(key, action) {
|
|
80
115
|
this.warnIfCompiled(`Adding a node to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
81
|
-
if (this.nodes
|
|
116
|
+
if (key in this.nodes) {
|
|
82
117
|
throw new Error(`Node \`${key}\` already present.`);
|
|
83
118
|
}
|
|
84
119
|
if (key === exports.END) {
|
|
85
120
|
throw new Error(`Node \`${key}\` is reserved.`);
|
|
86
121
|
}
|
|
87
122
|
this.nodes[key] = (0, runnables_1._coerceToRunnable)(action);
|
|
123
|
+
return this;
|
|
88
124
|
}
|
|
89
125
|
addEdge(startKey, endKey) {
|
|
90
126
|
this.warnIfCompiled(`Adding an edge to a graph that has already been compiled. This will not be reflected in the compiled graph.`);
|
|
91
127
|
if (startKey === exports.END) {
|
|
92
128
|
throw new Error("END cannot be a start node");
|
|
93
129
|
}
|
|
94
|
-
if (
|
|
95
|
-
throw new Error(
|
|
96
|
-
}
|
|
97
|
-
if (!this.nodes[endKey] && endKey !== exports.END) {
|
|
98
|
-
throw new Error(`Need to addNode \`${endKey}\` first`);
|
|
130
|
+
if (endKey === exports.START) {
|
|
131
|
+
throw new Error("START cannot be an end node");
|
|
99
132
|
}
|
|
100
|
-
|
|
101
|
-
|
|
133
|
+
if (!this.supportMultipleEdges &&
|
|
134
|
+
Array.from(this.edges).some(([start]) => start === startKey)) {
|
|
102
135
|
throw new Error(`Already found path for ${startKey}`);
|
|
103
136
|
}
|
|
104
137
|
this.edges.add([startKey, endKey]);
|
|
138
|
+
return this;
|
|
105
139
|
}
|
|
106
|
-
addConditionalEdges(
|
|
140
|
+
addConditionalEdges(source, path, pathMap) {
|
|
141
|
+
const options = typeof source === "object" ? source : { source, path: path, pathMap };
|
|
107
142
|
this.warnIfCompiled("Adding an edge to a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
const nodesValues = Object.keys(this.nodes);
|
|
114
|
-
const endExcluded = mappingValues.filter((value) => value !== exports.END);
|
|
115
|
-
const difference = endExcluded.filter((value) => !nodesValues.some((nv) => nv === value));
|
|
116
|
-
if (difference.length > 0) {
|
|
117
|
-
throw new Error(`Missing nodes which are in conditional edge mapping.\nMapping contains possible destinations: ${mappingValues.join(", ")}.\nPossible nodes are ${nodesValues.join(", ")}.`);
|
|
118
|
-
}
|
|
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}\``);
|
|
119
148
|
}
|
|
120
|
-
|
|
121
|
-
|
|
149
|
+
// save it
|
|
150
|
+
if (!this.branches[options.source]) {
|
|
151
|
+
this.branches[options.source] = {};
|
|
122
152
|
}
|
|
123
|
-
this.branches[
|
|
153
|
+
this.branches[options.source][name] = new Branch(options);
|
|
154
|
+
return this;
|
|
124
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* @deprecated use `addEdge(START, key)` instead
|
|
158
|
+
*/
|
|
125
159
|
setEntryPoint(key) {
|
|
126
160
|
this.warnIfCompiled("Setting the entry point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
127
|
-
|
|
128
|
-
throw new Error(`Need to addNode \`${key}\` first`);
|
|
129
|
-
}
|
|
130
|
-
this.entryPoint = key;
|
|
161
|
+
return this.addEdge(exports.START, key);
|
|
131
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* @deprecated use `addEdge(key, END)` instead
|
|
165
|
+
*/
|
|
132
166
|
setFinishPoint(key) {
|
|
133
167
|
this.warnIfCompiled("Setting a finish point of a graph that has already been compiled. This will not be reflected in the compiled graph.");
|
|
134
|
-
this.addEdge(key, exports.END);
|
|
135
|
-
}
|
|
136
|
-
compile(checkpointer) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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",
|
|
144
192
|
});
|
|
145
|
-
|
|
193
|
+
// attach nodes, edges and branches
|
|
146
194
|
for (const [key, node] of Object.entries(this.nodes)) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
nodes[edgesKey] = index_js_1.Channel.subscribeTo(key, {
|
|
156
|
-
tags: ["langsmith:hidden"],
|
|
157
|
-
});
|
|
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);
|
|
158
203
|
}
|
|
159
|
-
|
|
160
|
-
|
|
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
|
+
}
|
|
161
229
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
nodes[edgesKey] = nodes[edgesKey].pipe(runnableLambda);
|
|
168
|
-
});
|
|
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`);
|
|
169
235
|
}
|
|
170
236
|
}
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
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}\``);
|
|
240
|
+
}
|
|
174
241
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// validate targets
|
|
185
265
|
for (const node of Object.keys(this.nodes)) {
|
|
186
|
-
if (!
|
|
187
|
-
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}\``);
|
|
188
273
|
}
|
|
189
274
|
}
|
|
190
|
-
|
|
191
|
-
if (
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
.concat(this.entryPoint ? [this.entryPoint] : []));
|
|
196
|
-
for (const node of Object.keys(this.nodes)) {
|
|
197
|
-
if (!allEnds.has(node)) {
|
|
198
|
-
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`);
|
|
199
280
|
}
|
|
200
281
|
}
|
|
201
282
|
}
|
|
@@ -203,3 +284,62 @@ class Graph {
|
|
|
203
284
|
}
|
|
204
285
|
}
|
|
205
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;
|