@langchain/langgraph 0.2.61 → 0.2.63

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 (78) hide show
  1. package/README.md +14 -0
  2. package/dist/constants.cjs +2 -1
  3. package/dist/constants.d.ts +1 -0
  4. package/dist/constants.js +1 -0
  5. package/dist/constants.js.map +1 -1
  6. package/dist/prebuilt/react_agent_executor.cjs +34 -13
  7. package/dist/prebuilt/react_agent_executor.d.ts +3 -0
  8. package/dist/prebuilt/react_agent_executor.js +34 -15
  9. package/dist/prebuilt/react_agent_executor.js.map +1 -1
  10. package/dist/prebuilt/tool_node.cjs +26 -4
  11. package/dist/prebuilt/tool_node.js +27 -5
  12. package/dist/prebuilt/tool_node.js.map +1 -1
  13. package/dist/pregel/debug.cjs +9 -7
  14. package/dist/pregel/debug.d.ts +10 -0
  15. package/dist/pregel/debug.js +2 -2
  16. package/dist/pregel/debug.js.map +1 -1
  17. package/dist/pregel/debug.test.cjs +189 -0
  18. package/dist/pregel/debug.test.d.ts +1 -0
  19. package/dist/pregel/debug.test.js +187 -0
  20. package/dist/pregel/debug.test.js.map +1 -0
  21. package/dist/pregel/index.cjs +12 -4
  22. package/dist/pregel/index.d.ts +3 -0
  23. package/dist/pregel/index.js +14 -6
  24. package/dist/pregel/index.js.map +1 -1
  25. package/dist/pregel/io.mapCommand.test.cjs +151 -0
  26. package/dist/pregel/io.mapCommand.test.d.ts +1 -0
  27. package/dist/pregel/io.mapCommand.test.js +149 -0
  28. package/dist/pregel/io.mapCommand.test.js.map +1 -0
  29. package/dist/pregel/messages.test.cjs +351 -0
  30. package/dist/pregel/messages.test.d.ts +1 -0
  31. package/dist/pregel/messages.test.js +349 -0
  32. package/dist/pregel/messages.test.js.map +1 -0
  33. package/dist/pregel/read.cjs +1 -1
  34. package/dist/pregel/read.js +1 -1
  35. package/dist/pregel/read.js.map +1 -1
  36. package/dist/pregel/read.test.cjs +194 -0
  37. package/dist/pregel/read.test.d.ts +1 -0
  38. package/dist/pregel/read.test.js +192 -0
  39. package/dist/pregel/read.test.js.map +1 -0
  40. package/dist/pregel/retry.cjs +5 -0
  41. package/dist/pregel/retry.d.ts +2 -0
  42. package/dist/pregel/retry.js +5 -0
  43. package/dist/pregel/retry.js.map +1 -1
  44. package/dist/pregel/runner.cjs +95 -27
  45. package/dist/pregel/runner.d.ts +14 -0
  46. package/dist/pregel/runner.js +97 -29
  47. package/dist/pregel/runner.js.map +1 -1
  48. package/dist/pregel/runner.test.cjs +66 -0
  49. package/dist/pregel/runner.test.d.ts +1 -0
  50. package/dist/pregel/runner.test.js +64 -0
  51. package/dist/pregel/runner.test.js.map +1 -0
  52. package/dist/pregel/stream.cjs +62 -1
  53. package/dist/pregel/stream.d.ts +23 -0
  54. package/dist/pregel/stream.js +60 -0
  55. package/dist/pregel/stream.js.map +1 -1
  56. package/dist/pregel/types.d.ts +19 -0
  57. package/dist/pregel/types.js.map +1 -1
  58. package/dist/pregel/utils/config.test.cjs +214 -0
  59. package/dist/pregel/utils/config.test.d.ts +1 -0
  60. package/dist/pregel/utils/config.test.js +212 -0
  61. package/dist/pregel/utils/config.test.js.map +1 -0
  62. package/dist/pregel/utils/index.cjs +26 -1
  63. package/dist/pregel/utils/index.d.ts +6 -0
  64. package/dist/pregel/utils/index.js +24 -0
  65. package/dist/pregel/utils/index.js.map +1 -1
  66. package/dist/pregel/utils/subgraph.test.cjs +83 -0
  67. package/dist/pregel/utils/subgraph.test.d.ts +1 -0
  68. package/dist/pregel/utils/subgraph.test.js +81 -0
  69. package/dist/pregel/utils/subgraph.test.js.map +1 -0
  70. package/dist/pregel/validate.test.cjs +220 -0
  71. package/dist/pregel/validate.test.d.ts +1 -0
  72. package/dist/pregel/validate.test.js +218 -0
  73. package/dist/pregel/validate.test.js.map +1 -0
  74. package/dist/pregel/write.test.cjs +181 -0
  75. package/dist/pregel/write.test.d.ts +1 -0
  76. package/dist/pregel/write.test.js +179 -0
  77. package/dist/pregel/write.test.js.map +1 -0
  78. package/package.json +1 -1
@@ -0,0 +1,81 @@
1
+ import { describe, expect, it } from "@jest/globals";
2
+ import { isPregelLike, findSubgraphPregel } from "./subgraph.js";
3
+ describe("isPregelLike", () => {
4
+ it("should return true for objects with lg_is_pregel=true", () => {
5
+ const mockPregelObj = {
6
+ lg_is_pregel: true,
7
+ invoke: () => { },
8
+ someOtherProp: "value",
9
+ };
10
+ // Cast to any to test just the logic, not the type constraints
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ expect(isPregelLike(mockPregelObj)).toBe(true);
13
+ });
14
+ it("should return false for objects without lg_is_pregel property", () => {
15
+ const nonPregelObj = {
16
+ invoke: () => { },
17
+ someOtherProp: "value",
18
+ };
19
+ // Cast to any to test just the logic, not the type constraints
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ expect(isPregelLike(nonPregelObj)).toBe(false);
22
+ });
23
+ it("should return false for objects with lg_is_pregel=false", () => {
24
+ const nonPregelObj = {
25
+ lg_is_pregel: false,
26
+ invoke: () => { },
27
+ someOtherProp: "value",
28
+ };
29
+ // Cast to any to test just the logic, not the type constraints
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ expect(isPregelLike(nonPregelObj)).toBe(false);
32
+ });
33
+ });
34
+ describe("findSubgraphPregel", () => {
35
+ it("should find Pregel object at the top level", () => {
36
+ const mockPregelObj = {
37
+ lg_is_pregel: true,
38
+ invoke: () => { },
39
+ someOtherProp: "value",
40
+ };
41
+ // Cast to Runnable to test the behavior
42
+ expect(findSubgraphPregel(mockPregelObj)).toBe(mockPregelObj);
43
+ });
44
+ it("should find Pregel object in a RunnableSequence", () => {
45
+ const mockPregelObj = {
46
+ lg_is_pregel: true,
47
+ invoke: () => { },
48
+ someOtherProp: "value",
49
+ };
50
+ const mockSequence = {
51
+ steps: [{ someProperty: "value", invoke: () => { } }, mockPregelObj],
52
+ };
53
+ expect(findSubgraphPregel(mockSequence)).toBe(mockPregelObj);
54
+ });
55
+ it("should find Pregel object in a nested RunnableSequence", () => {
56
+ const mockPregelObj = {
57
+ lg_is_pregel: true,
58
+ invoke: () => { },
59
+ someOtherProp: "value",
60
+ };
61
+ const innerSequence = {
62
+ steps: [{ someProperty: "value", invoke: () => { } }, mockPregelObj],
63
+ };
64
+ const outerSequence = {
65
+ steps: [{ someProperty: "otherValue", invoke: () => { } }, innerSequence],
66
+ };
67
+ expect(findSubgraphPregel(outerSequence)).toBe(mockPregelObj);
68
+ });
69
+ it("should return undefined if no Pregel object is found", () => {
70
+ const nonPregelRunnable = {
71
+ someProperty: "value",
72
+ invoke: () => { },
73
+ };
74
+ const sequence = {
75
+ steps: [{ someProperty: "value1" }, { someProperty: "value2" }],
76
+ };
77
+ expect(findSubgraphPregel(nonPregelRunnable)).toBeUndefined();
78
+ expect(findSubgraphPregel(sequence)).toBeUndefined();
79
+ });
80
+ });
81
+ //# sourceMappingURL=subgraph.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subgraph.test.js","sourceRoot":"","sources":["../../../src/pregel/utils/subgraph.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const globals_1 = require("@jest/globals");
4
+ const validate_js_1 = require("./validate.cjs");
5
+ const read_js_1 = require("./read.cjs");
6
+ const constants_js_1 = require("../constants.cjs");
7
+ const last_value_js_1 = require("../channels/last_value.cjs");
8
+ // Common test setup
9
+ const setupValidGraph = () => {
10
+ // Create test channels
11
+ const inputChannel = new last_value_js_1.LastValue();
12
+ const outputChannel = new last_value_js_1.LastValue();
13
+ // Create test nodes
14
+ const testNode = new read_js_1.PregelNode({
15
+ channels: {},
16
+ triggers: ["input"],
17
+ });
18
+ return {
19
+ nodes: { testNode },
20
+ channels: {
21
+ input: inputChannel,
22
+ output: outputChannel,
23
+ },
24
+ inputChannels: "input",
25
+ outputChannels: "output",
26
+ };
27
+ };
28
+ (0, globals_1.describe)("GraphValidationError", () => {
29
+ (0, globals_1.it)("should be properly constructed with the right name", () => {
30
+ const error = new validate_js_1.GraphValidationError("Test error message");
31
+ (0, globals_1.expect)(error).toBeInstanceOf(Error);
32
+ (0, globals_1.expect)(error.name).toBe("GraphValidationError");
33
+ (0, globals_1.expect)(error.message).toBe("Test error message");
34
+ });
35
+ });
36
+ (0, globals_1.describe)("validateGraph", () => {
37
+ (0, globals_1.it)("should validate a correct graph without errors", () => {
38
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
39
+ // Act & Assert: Should not throw
40
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
41
+ nodes,
42
+ channels,
43
+ inputChannels,
44
+ outputChannels,
45
+ })).not.toThrow();
46
+ });
47
+ (0, globals_1.it)("should throw when channels are not provided", () => {
48
+ const { nodes, inputChannels, outputChannels } = setupValidGraph();
49
+ // Act & Assert: Should throw with specific message
50
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
51
+ nodes,
52
+ channels: null,
53
+ inputChannels,
54
+ outputChannels,
55
+ })).toThrow("Channels not provided");
56
+ });
57
+ (0, globals_1.it)("should throw when a node is named INTERRUPT", () => {
58
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
59
+ // Create a node with the reserved name
60
+ const badNode = new read_js_1.PregelNode({
61
+ channels: {},
62
+ triggers: ["input"],
63
+ });
64
+ // Create nodes object with the reserved name
65
+ const nodes = { [constants_js_1.INTERRUPT]: badNode };
66
+ // Act & Assert: Should throw specific error
67
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
68
+ nodes,
69
+ channels,
70
+ inputChannels,
71
+ outputChannels,
72
+ })).toThrow(`"Node name ${constants_js_1.INTERRUPT} is reserved"`);
73
+ });
74
+ (0, globals_1.it)("should throw when a node is not a PregelNode instance", () => {
75
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
76
+ // Create an invalid node (not a PregelNode)
77
+ const badNode = {
78
+ triggers: ["input"],
79
+ func: () => "not a pregel node",
80
+ };
81
+ // Create nodes object with invalid node
82
+ const nodes = {
83
+ badNode: badNode,
84
+ };
85
+ // Act & Assert: Should throw specific error
86
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
87
+ nodes,
88
+ channels,
89
+ inputChannels,
90
+ outputChannels,
91
+ })).toThrow("Invalid node type object, expected PregelNode");
92
+ });
93
+ (0, globals_1.it)("should throw when a subscribed channel is not in channels", () => {
94
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
95
+ // Create a node that subscribes to a non-existent channel
96
+ const badNode = new read_js_1.PregelNode({
97
+ channels: {},
98
+ triggers: ["nonexistent"],
99
+ });
100
+ const nodes = { badNode };
101
+ // Act & Assert: Should throw specific error
102
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
103
+ nodes,
104
+ channels,
105
+ inputChannels,
106
+ outputChannels,
107
+ })).toThrow("Subcribed channel 'nonexistent' not in channels");
108
+ });
109
+ (0, globals_1.it)("should throw when a singular input channel is not subscribed by any node", () => {
110
+ const { nodes, channels } = setupValidGraph();
111
+ // Act & Assert: Should throw specific error for an unused input
112
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
113
+ nodes,
114
+ channels,
115
+ inputChannels: "output",
116
+ outputChannels: "output",
117
+ })).toThrow("Input channel output is not subscribed to by any node");
118
+ });
119
+ (0, globals_1.it)("should throw when none of the array input channels are subscribed by any node", () => {
120
+ const { nodes, channels } = setupValidGraph();
121
+ // Act & Assert: Should throw specific error for unused inputs
122
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
123
+ nodes,
124
+ channels,
125
+ inputChannels: [
126
+ "output",
127
+ "nonexistent",
128
+ ],
129
+ outputChannels: "output",
130
+ })).toThrow("None of the input channels output,nonexistent are subscribed to by any node");
131
+ });
132
+ (0, globals_1.it)("should throw when an output channel is not in channels", () => {
133
+ const { nodes, channels, inputChannels } = setupValidGraph();
134
+ // Act & Assert: Should throw specific error
135
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
136
+ nodes,
137
+ channels,
138
+ inputChannels,
139
+ outputChannels: "nonexistent",
140
+ })).toThrow("Output channel 'nonexistent' not in channels");
141
+ });
142
+ (0, globals_1.it)("should throw when a stream channel is not in channels", () => {
143
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
144
+ // Act & Assert: Should throw specific error
145
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
146
+ nodes,
147
+ channels,
148
+ inputChannels,
149
+ outputChannels,
150
+ streamChannels: "nonexistent",
151
+ })).toThrow("Output channel 'nonexistent' not in channels");
152
+ });
153
+ (0, globals_1.it)("should throw when an interruptAfterNode is not in nodes", () => {
154
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
155
+ // Act & Assert: Should throw specific error
156
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
157
+ nodes,
158
+ channels,
159
+ inputChannels,
160
+ outputChannels,
161
+ interruptAfterNodes: [
162
+ "nonexistentNode",
163
+ ],
164
+ })).toThrow("Node nonexistentNode not in nodes");
165
+ });
166
+ (0, globals_1.it)("should throw when an interruptBeforeNode is not in nodes", () => {
167
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
168
+ // Act & Assert: Should throw specific error
169
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
170
+ nodes,
171
+ channels,
172
+ inputChannels,
173
+ outputChannels,
174
+ interruptBeforeNodes: [
175
+ "nonexistentNode",
176
+ ],
177
+ })).toThrow("Node nonexistentNode not in nodes");
178
+ });
179
+ (0, globals_1.it)("should accept '*' as a valid value for interruptAfterNodes", () => {
180
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
181
+ // Act & Assert: Should not throw
182
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
183
+ nodes,
184
+ channels,
185
+ inputChannels,
186
+ outputChannels,
187
+ interruptAfterNodes: "*",
188
+ })).not.toThrow();
189
+ });
190
+ (0, globals_1.it)("should accept '*' as a valid value for interruptBeforeNodes", () => {
191
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
192
+ // Act & Assert: Should not throw
193
+ (0, globals_1.expect)(() => (0, validate_js_1.validateGraph)({
194
+ nodes,
195
+ channels,
196
+ inputChannels,
197
+ outputChannels,
198
+ interruptBeforeNodes: "*",
199
+ })).not.toThrow();
200
+ });
201
+ });
202
+ (0, globals_1.describe)("validateKeys", () => {
203
+ (0, globals_1.it)("should validate keys that exist in channels", () => {
204
+ const { channels } = setupValidGraph();
205
+ // Act & Assert: Should not throw for valid keys
206
+ (0, globals_1.expect)(() => (0, validate_js_1.validateKeys)("input", channels)).not.toThrow();
207
+ (0, globals_1.expect)(() => (0, validate_js_1.validateKeys)(["input", "output"], channels)).not.toThrow();
208
+ });
209
+ (0, globals_1.it)("should throw when a single key doesn't exist in channels", () => {
210
+ const { channels } = setupValidGraph();
211
+ // Act & Assert: Should throw with specific message
212
+ (0, globals_1.expect)(() => (0, validate_js_1.validateKeys)("nonexistent", channels)).toThrow("Key nonexistent not found in channels");
213
+ });
214
+ (0, globals_1.it)("should throw when any key in an array doesn't exist in channels", () => {
215
+ const { channels } = setupValidGraph();
216
+ // Act & Assert: Should throw with specific message
217
+ (0, globals_1.expect)(() => (0, validate_js_1.validateKeys)(["input", "nonexistent"], channels)).toThrow("Key nonexistent not found in channels");
218
+ });
219
+ });
220
+ //# sourceMappingURL=validate.test.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,218 @@
1
+ import { describe, expect, it } from "@jest/globals";
2
+ import { GraphValidationError, validateGraph, validateKeys, } from "./validate.js";
3
+ import { PregelNode } from "./read.js";
4
+ import { INTERRUPT } from "../constants.js";
5
+ import { LastValue } from "../channels/last_value.js";
6
+ // Common test setup
7
+ const setupValidGraph = () => {
8
+ // Create test channels
9
+ const inputChannel = new LastValue();
10
+ const outputChannel = new LastValue();
11
+ // Create test nodes
12
+ const testNode = new PregelNode({
13
+ channels: {},
14
+ triggers: ["input"],
15
+ });
16
+ return {
17
+ nodes: { testNode },
18
+ channels: {
19
+ input: inputChannel,
20
+ output: outputChannel,
21
+ },
22
+ inputChannels: "input",
23
+ outputChannels: "output",
24
+ };
25
+ };
26
+ describe("GraphValidationError", () => {
27
+ it("should be properly constructed with the right name", () => {
28
+ const error = new GraphValidationError("Test error message");
29
+ expect(error).toBeInstanceOf(Error);
30
+ expect(error.name).toBe("GraphValidationError");
31
+ expect(error.message).toBe("Test error message");
32
+ });
33
+ });
34
+ describe("validateGraph", () => {
35
+ it("should validate a correct graph without errors", () => {
36
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
37
+ // Act & Assert: Should not throw
38
+ expect(() => validateGraph({
39
+ nodes,
40
+ channels,
41
+ inputChannels,
42
+ outputChannels,
43
+ })).not.toThrow();
44
+ });
45
+ it("should throw when channels are not provided", () => {
46
+ const { nodes, inputChannels, outputChannels } = setupValidGraph();
47
+ // Act & Assert: Should throw with specific message
48
+ expect(() => validateGraph({
49
+ nodes,
50
+ channels: null,
51
+ inputChannels,
52
+ outputChannels,
53
+ })).toThrow("Channels not provided");
54
+ });
55
+ it("should throw when a node is named INTERRUPT", () => {
56
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
57
+ // Create a node with the reserved name
58
+ const badNode = new PregelNode({
59
+ channels: {},
60
+ triggers: ["input"],
61
+ });
62
+ // Create nodes object with the reserved name
63
+ const nodes = { [INTERRUPT]: badNode };
64
+ // Act & Assert: Should throw specific error
65
+ expect(() => validateGraph({
66
+ nodes,
67
+ channels,
68
+ inputChannels,
69
+ outputChannels,
70
+ })).toThrow(`"Node name ${INTERRUPT} is reserved"`);
71
+ });
72
+ it("should throw when a node is not a PregelNode instance", () => {
73
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
74
+ // Create an invalid node (not a PregelNode)
75
+ const badNode = {
76
+ triggers: ["input"],
77
+ func: () => "not a pregel node",
78
+ };
79
+ // Create nodes object with invalid node
80
+ const nodes = {
81
+ badNode: badNode,
82
+ };
83
+ // Act & Assert: Should throw specific error
84
+ expect(() => validateGraph({
85
+ nodes,
86
+ channels,
87
+ inputChannels,
88
+ outputChannels,
89
+ })).toThrow("Invalid node type object, expected PregelNode");
90
+ });
91
+ it("should throw when a subscribed channel is not in channels", () => {
92
+ const { channels, inputChannels, outputChannels } = setupValidGraph();
93
+ // Create a node that subscribes to a non-existent channel
94
+ const badNode = new PregelNode({
95
+ channels: {},
96
+ triggers: ["nonexistent"],
97
+ });
98
+ const nodes = { badNode };
99
+ // Act & Assert: Should throw specific error
100
+ expect(() => validateGraph({
101
+ nodes,
102
+ channels,
103
+ inputChannels,
104
+ outputChannels,
105
+ })).toThrow("Subcribed channel 'nonexistent' not in channels");
106
+ });
107
+ it("should throw when a singular input channel is not subscribed by any node", () => {
108
+ const { nodes, channels } = setupValidGraph();
109
+ // Act & Assert: Should throw specific error for an unused input
110
+ expect(() => validateGraph({
111
+ nodes,
112
+ channels,
113
+ inputChannels: "output",
114
+ outputChannels: "output",
115
+ })).toThrow("Input channel output is not subscribed to by any node");
116
+ });
117
+ it("should throw when none of the array input channels are subscribed by any node", () => {
118
+ const { nodes, channels } = setupValidGraph();
119
+ // Act & Assert: Should throw specific error for unused inputs
120
+ expect(() => validateGraph({
121
+ nodes,
122
+ channels,
123
+ inputChannels: [
124
+ "output",
125
+ "nonexistent",
126
+ ],
127
+ outputChannels: "output",
128
+ })).toThrow("None of the input channels output,nonexistent are subscribed to by any node");
129
+ });
130
+ it("should throw when an output channel is not in channels", () => {
131
+ const { nodes, channels, inputChannels } = setupValidGraph();
132
+ // Act & Assert: Should throw specific error
133
+ expect(() => validateGraph({
134
+ nodes,
135
+ channels,
136
+ inputChannels,
137
+ outputChannels: "nonexistent",
138
+ })).toThrow("Output channel 'nonexistent' not in channels");
139
+ });
140
+ it("should throw when a stream channel is not in channels", () => {
141
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
142
+ // Act & Assert: Should throw specific error
143
+ expect(() => validateGraph({
144
+ nodes,
145
+ channels,
146
+ inputChannels,
147
+ outputChannels,
148
+ streamChannels: "nonexistent",
149
+ })).toThrow("Output channel 'nonexistent' not in channels");
150
+ });
151
+ it("should throw when an interruptAfterNode is not in nodes", () => {
152
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
153
+ // Act & Assert: Should throw specific error
154
+ expect(() => validateGraph({
155
+ nodes,
156
+ channels,
157
+ inputChannels,
158
+ outputChannels,
159
+ interruptAfterNodes: [
160
+ "nonexistentNode",
161
+ ],
162
+ })).toThrow("Node nonexistentNode not in nodes");
163
+ });
164
+ it("should throw when an interruptBeforeNode is not in nodes", () => {
165
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
166
+ // Act & Assert: Should throw specific error
167
+ expect(() => validateGraph({
168
+ nodes,
169
+ channels,
170
+ inputChannels,
171
+ outputChannels,
172
+ interruptBeforeNodes: [
173
+ "nonexistentNode",
174
+ ],
175
+ })).toThrow("Node nonexistentNode not in nodes");
176
+ });
177
+ it("should accept '*' as a valid value for interruptAfterNodes", () => {
178
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
179
+ // Act & Assert: Should not throw
180
+ expect(() => validateGraph({
181
+ nodes,
182
+ channels,
183
+ inputChannels,
184
+ outputChannels,
185
+ interruptAfterNodes: "*",
186
+ })).not.toThrow();
187
+ });
188
+ it("should accept '*' as a valid value for interruptBeforeNodes", () => {
189
+ const { nodes, channels, inputChannels, outputChannels } = setupValidGraph();
190
+ // Act & Assert: Should not throw
191
+ expect(() => validateGraph({
192
+ nodes,
193
+ channels,
194
+ inputChannels,
195
+ outputChannels,
196
+ interruptBeforeNodes: "*",
197
+ })).not.toThrow();
198
+ });
199
+ });
200
+ describe("validateKeys", () => {
201
+ it("should validate keys that exist in channels", () => {
202
+ const { channels } = setupValidGraph();
203
+ // Act & Assert: Should not throw for valid keys
204
+ expect(() => validateKeys("input", channels)).not.toThrow();
205
+ expect(() => validateKeys(["input", "output"], channels)).not.toThrow();
206
+ });
207
+ it("should throw when a single key doesn't exist in channels", () => {
208
+ const { channels } = setupValidGraph();
209
+ // Act & Assert: Should throw with specific message
210
+ expect(() => validateKeys("nonexistent", channels)).toThrow("Key nonexistent not found in channels");
211
+ });
212
+ it("should throw when any key in an array doesn't exist in channels", () => {
213
+ const { channels } = setupValidGraph();
214
+ // Act & Assert: Should throw with specific message
215
+ expect(() => validateKeys(["input", "nonexistent"], channels)).toThrow("Key nonexistent not found in channels");
216
+ });
217
+ });
218
+ //# sourceMappingURL=validate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../src/pregel/validate.test.ts"],"names":[],"mappings":"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"}