@langchain/langgraph 0.0.1

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +588 -0
  3. package/dist/channels/base.cjs +58 -0
  4. package/dist/channels/base.d.ts +46 -0
  5. package/dist/channels/base.js +50 -0
  6. package/dist/channels/binop.cjs +70 -0
  7. package/dist/channels/binop.d.ts +16 -0
  8. package/dist/channels/binop.js +66 -0
  9. package/dist/channels/index.cjs +9 -0
  10. package/dist/channels/index.d.ts +1 -0
  11. package/dist/channels/index.js +1 -0
  12. package/dist/channels/last_value.cjs +53 -0
  13. package/dist/channels/last_value.d.ts +12 -0
  14. package/dist/channels/last_value.js +49 -0
  15. package/dist/channels/topic.cjs +90 -0
  16. package/dist/channels/topic.d.ts +19 -0
  17. package/dist/channels/topic.js +86 -0
  18. package/dist/checkpoint/base.cjs +32 -0
  19. package/dist/checkpoint/base.d.ts +47 -0
  20. package/dist/checkpoint/base.js +27 -0
  21. package/dist/checkpoint/index.cjs +8 -0
  22. package/dist/checkpoint/index.d.ts +2 -0
  23. package/dist/checkpoint/index.js +2 -0
  24. package/dist/checkpoint/memory.cjs +35 -0
  25. package/dist/checkpoint/memory.d.ts +8 -0
  26. package/dist/checkpoint/memory.js +31 -0
  27. package/dist/constants.cjs +5 -0
  28. package/dist/constants.d.ts +2 -0
  29. package/dist/constants.js +2 -0
  30. package/dist/graph/graph.cjs +175 -0
  31. package/dist/graph/graph.d.ts +30 -0
  32. package/dist/graph/graph.js +171 -0
  33. package/dist/graph/index.cjs +9 -0
  34. package/dist/graph/index.d.ts +2 -0
  35. package/dist/graph/index.js +2 -0
  36. package/dist/graph/state.cjs +108 -0
  37. package/dist/graph/state.d.ts +17 -0
  38. package/dist/graph/state.js +104 -0
  39. package/dist/index.cjs +8 -0
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.js +1 -0
  42. package/dist/prebuilt/agent_executor.cjs +96 -0
  43. package/dist/prebuilt/agent_executor.d.ts +12 -0
  44. package/dist/prebuilt/agent_executor.js +92 -0
  45. package/dist/prebuilt/chat_agent_executor.cjs +130 -0
  46. package/dist/prebuilt/chat_agent_executor.d.ts +6 -0
  47. package/dist/prebuilt/chat_agent_executor.js +126 -0
  48. package/dist/prebuilt/index.cjs +9 -0
  49. package/dist/prebuilt/index.d.ts +3 -0
  50. package/dist/prebuilt/index.js +3 -0
  51. package/dist/prebuilt/tool_executor.cjs +63 -0
  52. package/dist/prebuilt/tool_executor.d.ts +27 -0
  53. package/dist/prebuilt/tool_executor.js +59 -0
  54. package/dist/pregel/debug.cjs +46 -0
  55. package/dist/pregel/debug.d.ts +4 -0
  56. package/dist/pregel/debug.js +41 -0
  57. package/dist/pregel/index.cjs +475 -0
  58. package/dist/pregel/index.d.ts +75 -0
  59. package/dist/pregel/index.js +469 -0
  60. package/dist/pregel/io.cjs +57 -0
  61. package/dist/pregel/io.d.ts +9 -0
  62. package/dist/pregel/io.js +52 -0
  63. package/dist/pregel/read.cjs +217 -0
  64. package/dist/pregel/read.d.ts +43 -0
  65. package/dist/pregel/read.js +211 -0
  66. package/dist/pregel/reserved.cjs +7 -0
  67. package/dist/pregel/reserved.d.ts +3 -0
  68. package/dist/pregel/reserved.js +4 -0
  69. package/dist/pregel/validate.cjs +90 -0
  70. package/dist/pregel/validate.d.ts +15 -0
  71. package/dist/pregel/validate.js +85 -0
  72. package/dist/pregel/write.cjs +54 -0
  73. package/dist/pregel/write.d.ts +13 -0
  74. package/dist/pregel/write.js +50 -0
  75. package/index.cjs +1 -0
  76. package/index.d.ts +1 -0
  77. package/index.js +1 -0
  78. package/package.json +100 -0
  79. package/prebuilt.cjs +1 -0
  80. package/prebuilt.d.ts +1 -0
  81. package/prebuilt.js +1 -0
  82. package/pregel.cjs +1 -0
  83. package/pregel.d.ts +1 -0
  84. package/pregel.js +1 -0
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChannelBatch = exports.ChannelInvoke = exports.ChannelRead = void 0;
4
+ const runnables_1 = require("@langchain/core/runnables");
5
+ const constants_js_1 = require("../constants.cjs");
6
+ class ChannelRead extends runnables_1.RunnableLambda {
7
+ constructor(channel) {
8
+ super({
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ func: (input, options) => {
11
+ if ("config" in options) {
12
+ return this._read(input, options.config);
13
+ }
14
+ return this._read(input, options ?? {});
15
+ },
16
+ });
17
+ Object.defineProperty(this, "lc_graph_name", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: "ChannelRead"
22
+ });
23
+ Object.defineProperty(this, "channel", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ this.channel = channel;
30
+ this.name = `ChannelRead<${channel}>`;
31
+ }
32
+ get configSpecs() {
33
+ return [
34
+ {
35
+ id: constants_js_1.CONFIG_KEY_READ,
36
+ name: constants_js_1.CONFIG_KEY_READ,
37
+ description: null,
38
+ default: null,
39
+ // TODO FIX THIS
40
+ annotation: "Callable[[BaseChannel], Any]",
41
+ isShared: true,
42
+ dependencies: null,
43
+ },
44
+ ];
45
+ }
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ _read(_, config) {
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ const read = config.configurable?.[constants_js_1.CONFIG_KEY_READ];
50
+ if (!read) {
51
+ throw new Error(`Runnable ${this} is not configured with a read function. Make sure to call in the context of a Pregel process`);
52
+ }
53
+ if (Array.isArray(this.channel)) {
54
+ const results = Object.fromEntries(this.channel.map((chan) => [chan, read(chan)]));
55
+ return results;
56
+ }
57
+ return read(this.channel);
58
+ }
59
+ }
60
+ exports.ChannelRead = ChannelRead;
61
+ const defaultRunnableBound = new runnables_1.RunnablePassthrough();
62
+ class ChannelInvoke extends runnables_1.RunnableBinding {
63
+ constructor(fields) {
64
+ const { channels, triggers, when } = fields;
65
+ const mergedTags = [
66
+ ...(fields.config?.tags ? fields.config.tags : []),
67
+ ...(fields.tags ? fields.tags : []),
68
+ ];
69
+ super({
70
+ ...fields,
71
+ bound: fields.bound ??
72
+ defaultRunnableBound,
73
+ config: {
74
+ ...(fields.config ? fields.config : {}),
75
+ tags: mergedTags,
76
+ },
77
+ });
78
+ Object.defineProperty(this, "lc_graph_name", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: "ChannelInvoke"
83
+ });
84
+ Object.defineProperty(this, "channels", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: void 0
89
+ });
90
+ Object.defineProperty(this, "triggers", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: []
95
+ });
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ Object.defineProperty(this, "when", {
98
+ enumerable: true,
99
+ configurable: true,
100
+ writable: true,
101
+ value: void 0
102
+ });
103
+ this.channels = channels;
104
+ this.triggers = triggers;
105
+ this.when = when;
106
+ }
107
+ join(channels) {
108
+ if (typeof this.channels !== "object") {
109
+ throw new Error("all channels must be named when using .join()");
110
+ }
111
+ return new ChannelInvoke({
112
+ channels: {
113
+ ...this.channels,
114
+ ...Object.fromEntries(channels.map((chan) => [chan, chan])),
115
+ },
116
+ triggers: this.triggers,
117
+ when: this.when,
118
+ bound: this.bound,
119
+ kwargs: this.kwargs,
120
+ config: this.config,
121
+ });
122
+ }
123
+ pipe(coerceable) {
124
+ if (this.bound === defaultRunnableBound) {
125
+ return new ChannelInvoke({
126
+ channels: this.channels,
127
+ triggers: this.triggers,
128
+ when: this.when,
129
+ bound: (0, runnables_1._coerceToRunnable)(coerceable),
130
+ config: this.config,
131
+ kwargs: this.kwargs,
132
+ });
133
+ }
134
+ else {
135
+ return new ChannelInvoke({
136
+ channels: this.channels,
137
+ triggers: this.triggers,
138
+ when: this.when,
139
+ bound: this.bound.pipe(coerceable),
140
+ config: this.config,
141
+ kwargs: this.kwargs,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ exports.ChannelInvoke = ChannelInvoke;
147
+ class ChannelBatch extends runnables_1.RunnableEach {
148
+ constructor(fields) {
149
+ super({
150
+ ...fields,
151
+ bound: fields.bound ?? defaultRunnableBound,
152
+ });
153
+ Object.defineProperty(this, "lc_graph_name", {
154
+ enumerable: true,
155
+ configurable: true,
156
+ writable: true,
157
+ value: "ChannelBatch"
158
+ });
159
+ Object.defineProperty(this, "channel", {
160
+ enumerable: true,
161
+ configurable: true,
162
+ writable: true,
163
+ value: void 0
164
+ });
165
+ Object.defineProperty(this, "key", {
166
+ enumerable: true,
167
+ configurable: true,
168
+ writable: true,
169
+ value: void 0
170
+ });
171
+ this.channel = fields.channel;
172
+ this.key = fields.key;
173
+ }
174
+ join(channels) {
175
+ if (!this.key) {
176
+ throw new Error(`Cannot join() additional channels without a key.\nPass a key arg to Channel.subscribeToEach().`);
177
+ }
178
+ const channelsMap = {};
179
+ for (const chan of channels) {
180
+ channelsMap[chan] = new ChannelRead(chan);
181
+ }
182
+ const joiner = runnables_1.RunnablePassthrough.assign({ ...channelsMap });
183
+ if (this.bound === defaultRunnableBound) {
184
+ return new ChannelBatch({
185
+ channel: this.channel,
186
+ key: this.key,
187
+ bound: joiner,
188
+ });
189
+ }
190
+ else {
191
+ return new ChannelBatch({
192
+ channel: this.channel,
193
+ key: this.key,
194
+ bound: this.bound.pipe(joiner),
195
+ });
196
+ }
197
+ }
198
+ // @ts-expect-error @TODO: fix later
199
+ pipe(coerceable) {
200
+ if (this.bound === defaultRunnableBound) {
201
+ return new ChannelBatch({
202
+ channel: this.channel,
203
+ key: this.key,
204
+ bound: (0, runnables_1._coerceToRunnable)(coerceable),
205
+ });
206
+ }
207
+ else {
208
+ // Delegate to `or` in `this.bound`
209
+ return new ChannelBatch({
210
+ channel: this.channel,
211
+ key: this.key,
212
+ bound: this.bound.pipe(coerceable),
213
+ });
214
+ }
215
+ }
216
+ }
217
+ exports.ChannelBatch = ChannelBatch;
@@ -0,0 +1,43 @@
1
+ import { Runnable, RunnableBinding, RunnableBindingArgs, RunnableConfig, RunnableEach, RunnableLambda, RunnableLike } from "@langchain/core/runnables";
2
+ import { ConfigurableFieldSpec } from "../checkpoint/index.js";
3
+ export declare class ChannelRead<RunInput = any, RunOutput = any> extends RunnableLambda<RunInput, RunOutput> {
4
+ lc_graph_name: string;
5
+ channel: string | Array<string>;
6
+ constructor(channel: string | Array<string>);
7
+ get configSpecs(): ConfigurableFieldSpec[];
8
+ _read(_: any, config: RunnableConfig): any;
9
+ }
10
+ interface ChannelInvokeArgs<RunInput, RunOutput> extends Partial<RunnableBindingArgs<RunInput, RunOutput>> {
11
+ channels: Record<string, string> | string;
12
+ triggers: Array<string>;
13
+ when?: (args: any) => boolean;
14
+ config?: RunnableConfig;
15
+ tags?: string[];
16
+ }
17
+ export type ChannelInvokeInputType = any;
18
+ export type ChannelInvokeOutputType = any;
19
+ export declare class ChannelInvoke<RunInput = ChannelInvokeInputType, RunOutput = ChannelInvokeOutputType> extends RunnableBinding<RunInput, RunOutput, RunnableConfig> {
20
+ lc_graph_name: string;
21
+ channels: Record<string, string> | string;
22
+ triggers: string[];
23
+ when?: (args: any) => boolean;
24
+ constructor(fields: ChannelInvokeArgs<RunInput, RunOutput>);
25
+ join(channels: Array<string>): ChannelInvoke<RunInput, RunOutput>;
26
+ pipe<NewRunOutput>(coerceable: RunnableLike): ChannelInvoke<RunInput, Exclude<NewRunOutput, Error>>;
27
+ }
28
+ interface ChannelBatchArgs {
29
+ channel: string;
30
+ key?: string;
31
+ bound?: Runnable;
32
+ }
33
+ export type ChannelBatchInputType = any;
34
+ export type ChannelBatchOutputType = any;
35
+ export declare class ChannelBatch extends RunnableEach<ChannelBatchInputType, ChannelBatchOutputType, RunnableConfig> {
36
+ lc_graph_name: string;
37
+ channel: string;
38
+ key?: string;
39
+ constructor(fields: ChannelBatchArgs);
40
+ join(channels: Array<string>): ChannelBatch;
41
+ pipe(coerceable: RunnableLike): ChannelBatch;
42
+ }
43
+ export {};
@@ -0,0 +1,211 @@
1
+ import { RunnableBinding, RunnableEach, RunnableLambda, RunnablePassthrough, _coerceToRunnable, } from "@langchain/core/runnables";
2
+ import { CONFIG_KEY_READ } from "../constants.js";
3
+ export class ChannelRead extends RunnableLambda {
4
+ constructor(channel) {
5
+ super({
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ func: (input, options) => {
8
+ if ("config" in options) {
9
+ return this._read(input, options.config);
10
+ }
11
+ return this._read(input, options ?? {});
12
+ },
13
+ });
14
+ Object.defineProperty(this, "lc_graph_name", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: "ChannelRead"
19
+ });
20
+ Object.defineProperty(this, "channel", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: void 0
25
+ });
26
+ this.channel = channel;
27
+ this.name = `ChannelRead<${channel}>`;
28
+ }
29
+ get configSpecs() {
30
+ return [
31
+ {
32
+ id: CONFIG_KEY_READ,
33
+ name: CONFIG_KEY_READ,
34
+ description: null,
35
+ default: null,
36
+ // TODO FIX THIS
37
+ annotation: "Callable[[BaseChannel], Any]",
38
+ isShared: true,
39
+ dependencies: null,
40
+ },
41
+ ];
42
+ }
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ _read(_, config) {
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const read = config.configurable?.[CONFIG_KEY_READ];
47
+ if (!read) {
48
+ throw new Error(`Runnable ${this} is not configured with a read function. Make sure to call in the context of a Pregel process`);
49
+ }
50
+ if (Array.isArray(this.channel)) {
51
+ const results = Object.fromEntries(this.channel.map((chan) => [chan, read(chan)]));
52
+ return results;
53
+ }
54
+ return read(this.channel);
55
+ }
56
+ }
57
+ const defaultRunnableBound = new RunnablePassthrough();
58
+ export class ChannelInvoke extends RunnableBinding {
59
+ constructor(fields) {
60
+ const { channels, triggers, when } = fields;
61
+ const mergedTags = [
62
+ ...(fields.config?.tags ? fields.config.tags : []),
63
+ ...(fields.tags ? fields.tags : []),
64
+ ];
65
+ super({
66
+ ...fields,
67
+ bound: fields.bound ??
68
+ defaultRunnableBound,
69
+ config: {
70
+ ...(fields.config ? fields.config : {}),
71
+ tags: mergedTags,
72
+ },
73
+ });
74
+ Object.defineProperty(this, "lc_graph_name", {
75
+ enumerable: true,
76
+ configurable: true,
77
+ writable: true,
78
+ value: "ChannelInvoke"
79
+ });
80
+ Object.defineProperty(this, "channels", {
81
+ enumerable: true,
82
+ configurable: true,
83
+ writable: true,
84
+ value: void 0
85
+ });
86
+ Object.defineProperty(this, "triggers", {
87
+ enumerable: true,
88
+ configurable: true,
89
+ writable: true,
90
+ value: []
91
+ });
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ Object.defineProperty(this, "when", {
94
+ enumerable: true,
95
+ configurable: true,
96
+ writable: true,
97
+ value: void 0
98
+ });
99
+ this.channels = channels;
100
+ this.triggers = triggers;
101
+ this.when = when;
102
+ }
103
+ join(channels) {
104
+ if (typeof this.channels !== "object") {
105
+ throw new Error("all channels must be named when using .join()");
106
+ }
107
+ return new ChannelInvoke({
108
+ channels: {
109
+ ...this.channels,
110
+ ...Object.fromEntries(channels.map((chan) => [chan, chan])),
111
+ },
112
+ triggers: this.triggers,
113
+ when: this.when,
114
+ bound: this.bound,
115
+ kwargs: this.kwargs,
116
+ config: this.config,
117
+ });
118
+ }
119
+ pipe(coerceable) {
120
+ if (this.bound === defaultRunnableBound) {
121
+ return new ChannelInvoke({
122
+ channels: this.channels,
123
+ triggers: this.triggers,
124
+ when: this.when,
125
+ bound: _coerceToRunnable(coerceable),
126
+ config: this.config,
127
+ kwargs: this.kwargs,
128
+ });
129
+ }
130
+ else {
131
+ return new ChannelInvoke({
132
+ channels: this.channels,
133
+ triggers: this.triggers,
134
+ when: this.when,
135
+ bound: this.bound.pipe(coerceable),
136
+ config: this.config,
137
+ kwargs: this.kwargs,
138
+ });
139
+ }
140
+ }
141
+ }
142
+ export class ChannelBatch extends RunnableEach {
143
+ constructor(fields) {
144
+ super({
145
+ ...fields,
146
+ bound: fields.bound ?? defaultRunnableBound,
147
+ });
148
+ Object.defineProperty(this, "lc_graph_name", {
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true,
152
+ value: "ChannelBatch"
153
+ });
154
+ Object.defineProperty(this, "channel", {
155
+ enumerable: true,
156
+ configurable: true,
157
+ writable: true,
158
+ value: void 0
159
+ });
160
+ Object.defineProperty(this, "key", {
161
+ enumerable: true,
162
+ configurable: true,
163
+ writable: true,
164
+ value: void 0
165
+ });
166
+ this.channel = fields.channel;
167
+ this.key = fields.key;
168
+ }
169
+ join(channels) {
170
+ if (!this.key) {
171
+ throw new Error(`Cannot join() additional channels without a key.\nPass a key arg to Channel.subscribeToEach().`);
172
+ }
173
+ const channelsMap = {};
174
+ for (const chan of channels) {
175
+ channelsMap[chan] = new ChannelRead(chan);
176
+ }
177
+ const joiner = RunnablePassthrough.assign({ ...channelsMap });
178
+ if (this.bound === defaultRunnableBound) {
179
+ return new ChannelBatch({
180
+ channel: this.channel,
181
+ key: this.key,
182
+ bound: joiner,
183
+ });
184
+ }
185
+ else {
186
+ return new ChannelBatch({
187
+ channel: this.channel,
188
+ key: this.key,
189
+ bound: this.bound.pipe(joiner),
190
+ });
191
+ }
192
+ }
193
+ // @ts-expect-error @TODO: fix later
194
+ pipe(coerceable) {
195
+ if (this.bound === defaultRunnableBound) {
196
+ return new ChannelBatch({
197
+ channel: this.channel,
198
+ key: this.key,
199
+ bound: _coerceToRunnable(coerceable),
200
+ });
201
+ }
202
+ else {
203
+ // Delegate to `or` in `this.bound`
204
+ return new ChannelBatch({
205
+ channel: this.channel,
206
+ key: this.key,
207
+ bound: this.bound.pipe(coerceable),
208
+ });
209
+ }
210
+ }
211
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReservedChannels = void 0;
4
+ var ReservedChannels;
5
+ (function (ReservedChannels) {
6
+ ReservedChannels["isLastStep"] = "isLastStep";
7
+ })(ReservedChannels || (exports.ReservedChannels = ReservedChannels = {}));
@@ -0,0 +1,3 @@
1
+ export declare enum ReservedChannels {
2
+ isLastStep = "isLastStep"
3
+ }
@@ -0,0 +1,4 @@
1
+ export var ReservedChannels;
2
+ (function (ReservedChannels) {
3
+ ReservedChannels["isLastStep"] = "isLastStep";
4
+ })(ReservedChannels || (ReservedChannels = {}));
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateKeys = exports.validateGraph = void 0;
4
+ const last_value_js_1 = require("../channels/last_value.cjs");
5
+ const reserved_js_1 = require("./reserved.cjs");
6
+ function validateGraph({ nodes, channels, input, output, hidden, interrupt, }) {
7
+ const newChannels = channels;
8
+ const subscribedChannels = new Set();
9
+ for (const node of Object.values(nodes)) {
10
+ if (node.lc_graph_name === "ChannelInvoke" && "channels" in node) {
11
+ if (typeof node.channels === "string") {
12
+ subscribedChannels.add(node.channels);
13
+ }
14
+ else {
15
+ Object.values(node.channels).map((channel) => subscribedChannels.add(channel));
16
+ }
17
+ }
18
+ else if (node.lc_graph_name === "ChannelBatch" && "channel" in node) {
19
+ subscribedChannels.add(node.channel);
20
+ }
21
+ else {
22
+ console.error(node);
23
+ throw new Error(`Invalid node type: ${JSON.stringify(node, null, 2)}, expected Channel.subscribeTo() or Channel.subscribe_to_each()`);
24
+ }
25
+ }
26
+ for (const chan of [...subscribedChannels]) {
27
+ if (!(chan in newChannels)) {
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ newChannels[chan] = new last_value_js_1.LastValue();
30
+ }
31
+ }
32
+ if (typeof input === "string") {
33
+ if (!(input in newChannels)) {
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ newChannels[input] = new last_value_js_1.LastValue();
36
+ }
37
+ if (!subscribedChannels.has(input)) {
38
+ throw new Error(`Input channel ${input} is not subscribed to by any node.`);
39
+ }
40
+ }
41
+ else {
42
+ for (const chan of input) {
43
+ if (!(chan in newChannels)) {
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ newChannels[chan] = new last_value_js_1.LastValue();
46
+ }
47
+ }
48
+ if (input.every((chan) => !subscribedChannels.has(chan))) {
49
+ throw new Error(`None of the input channels ${input} are subscribed to by any node`);
50
+ }
51
+ }
52
+ if (typeof output === "string") {
53
+ if (!(output in newChannels)) {
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ newChannels[output] = new last_value_js_1.LastValue();
56
+ }
57
+ }
58
+ else {
59
+ for (const chan of output) {
60
+ if (!(chan in newChannels)) {
61
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+ newChannels[chan] = new last_value_js_1.LastValue();
63
+ }
64
+ }
65
+ }
66
+ for (const chan in reserved_js_1.ReservedChannels) {
67
+ if (!(chan in newChannels)) {
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ newChannels[chan] = new last_value_js_1.LastValue();
70
+ }
71
+ }
72
+ validateKeys(hidden, newChannels);
73
+ validateKeys(interrupt, newChannels);
74
+ }
75
+ exports.validateGraph = validateGraph;
76
+ function validateKeys(keys, channels) {
77
+ if (Array.isArray(keys)) {
78
+ for (const key of keys) {
79
+ if (!(key in channels)) {
80
+ throw new Error(`Key ${key} not found in channels`);
81
+ }
82
+ }
83
+ }
84
+ else {
85
+ if (!(keys in channels)) {
86
+ throw new Error(`Key ${keys} not found in channels`);
87
+ }
88
+ }
89
+ }
90
+ exports.validateKeys = validateKeys;
@@ -0,0 +1,15 @@
1
+ import { BaseChannel } from "../channels/index.js";
2
+ import { ChannelBatch, ChannelInvoke } from "./read.js";
3
+ export declare function validateGraph({ nodes, channels, input, output, hidden, interrupt, }: {
4
+ nodes: Record<string, ChannelInvoke | ChannelBatch>;
5
+ channels: {
6
+ [key: string]: BaseChannel;
7
+ };
8
+ input: string | Array<string>;
9
+ output: string | Array<string>;
10
+ hidden: Array<string>;
11
+ interrupt: Array<string>;
12
+ }): void;
13
+ export declare function validateKeys(keys: string | Array<string>, channels: {
14
+ [key: string]: BaseChannel;
15
+ }): void;
@@ -0,0 +1,85 @@
1
+ import { LastValue } from "../channels/last_value.js";
2
+ import { ReservedChannels } from "./reserved.js";
3
+ export function validateGraph({ nodes, channels, input, output, hidden, interrupt, }) {
4
+ const newChannels = channels;
5
+ const subscribedChannels = new Set();
6
+ for (const node of Object.values(nodes)) {
7
+ if (node.lc_graph_name === "ChannelInvoke" && "channels" in node) {
8
+ if (typeof node.channels === "string") {
9
+ subscribedChannels.add(node.channels);
10
+ }
11
+ else {
12
+ Object.values(node.channels).map((channel) => subscribedChannels.add(channel));
13
+ }
14
+ }
15
+ else if (node.lc_graph_name === "ChannelBatch" && "channel" in node) {
16
+ subscribedChannels.add(node.channel);
17
+ }
18
+ else {
19
+ console.error(node);
20
+ throw new Error(`Invalid node type: ${JSON.stringify(node, null, 2)}, expected Channel.subscribeTo() or Channel.subscribe_to_each()`);
21
+ }
22
+ }
23
+ for (const chan of [...subscribedChannels]) {
24
+ if (!(chan in newChannels)) {
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ newChannels[chan] = new LastValue();
27
+ }
28
+ }
29
+ if (typeof input === "string") {
30
+ if (!(input in newChannels)) {
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ newChannels[input] = new LastValue();
33
+ }
34
+ if (!subscribedChannels.has(input)) {
35
+ throw new Error(`Input channel ${input} is not subscribed to by any node.`);
36
+ }
37
+ }
38
+ else {
39
+ for (const chan of input) {
40
+ if (!(chan in newChannels)) {
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ newChannels[chan] = new LastValue();
43
+ }
44
+ }
45
+ if (input.every((chan) => !subscribedChannels.has(chan))) {
46
+ throw new Error(`None of the input channels ${input} are subscribed to by any node`);
47
+ }
48
+ }
49
+ if (typeof output === "string") {
50
+ if (!(output in newChannels)) {
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ newChannels[output] = new LastValue();
53
+ }
54
+ }
55
+ else {
56
+ for (const chan of output) {
57
+ if (!(chan in newChannels)) {
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ newChannels[chan] = new LastValue();
60
+ }
61
+ }
62
+ }
63
+ for (const chan in ReservedChannels) {
64
+ if (!(chan in newChannels)) {
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ newChannels[chan] = new LastValue();
67
+ }
68
+ }
69
+ validateKeys(hidden, newChannels);
70
+ validateKeys(interrupt, newChannels);
71
+ }
72
+ export function validateKeys(keys, channels) {
73
+ if (Array.isArray(keys)) {
74
+ for (const key of keys) {
75
+ if (!(key in channels)) {
76
+ throw new Error(`Key ${key} not found in channels`);
77
+ }
78
+ }
79
+ }
80
+ else {
81
+ if (!(keys in channels)) {
82
+ throw new Error(`Key ${keys} not found in channels`);
83
+ }
84
+ }
85
+ }