@ai.ntellect/core 0.6.8 → 0.6.10
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/graph/engine.ts +1 -1
- package/package.json +1 -1
- package/test/graph/engine.test.ts +40 -53
- package/test/graph/controller.test.ts +0 -186
package/graph/engine.ts
CHANGED
package/package.json
CHANGED
@@ -33,9 +33,9 @@ describe("Graph", () => {
|
|
33
33
|
start: {
|
34
34
|
name: "start",
|
35
35
|
description: "Starting node",
|
36
|
-
execute: async (
|
36
|
+
execute: async (state: SharedState<TestState>) => {
|
37
37
|
return graph.updateState({
|
38
|
-
...state
|
38
|
+
...state,
|
39
39
|
status: "started",
|
40
40
|
step: 1,
|
41
41
|
});
|
@@ -45,22 +45,22 @@ describe("Graph", () => {
|
|
45
45
|
process: {
|
46
46
|
name: "process",
|
47
47
|
description: "Processing node",
|
48
|
-
execute: async (
|
48
|
+
execute: async (state: SharedState<TestState>) => {
|
49
49
|
return graph.updateState({
|
50
|
-
...state
|
50
|
+
...state,
|
51
51
|
status: "processing",
|
52
52
|
step: 2,
|
53
53
|
});
|
54
54
|
},
|
55
|
-
condition: (state) => state.
|
55
|
+
condition: (state) => state.step === 1,
|
56
56
|
relationships: [{ name: "end" }],
|
57
57
|
},
|
58
58
|
end: {
|
59
59
|
name: "end",
|
60
60
|
description: "End node",
|
61
|
-
execute: async (
|
61
|
+
execute: async (state: SharedState<TestState>) => {
|
62
62
|
return graph.updateState({
|
63
|
-
...state
|
63
|
+
...state,
|
64
64
|
status: "completed",
|
65
65
|
step: 3,
|
66
66
|
});
|
@@ -82,10 +82,8 @@ describe("Graph", () => {
|
|
82
82
|
*/
|
83
83
|
it("should execute the complete workflow sequence", async () => {
|
84
84
|
const initialState: SharedState<TestState> = {
|
85
|
-
|
86
|
-
|
87
|
-
step: 0,
|
88
|
-
},
|
85
|
+
status: "init",
|
86
|
+
step: 0,
|
89
87
|
};
|
90
88
|
|
91
89
|
// Initialiser le graph avec l'état initial
|
@@ -98,7 +96,7 @@ describe("Graph", () => {
|
|
98
96
|
await graph.execute(initialState, "start");
|
99
97
|
const result = graph.getState();
|
100
98
|
|
101
|
-
expect(result
|
99
|
+
expect(result).to.deep.equal({
|
102
100
|
status: "completed",
|
103
101
|
step: 3,
|
104
102
|
});
|
@@ -110,10 +108,8 @@ describe("Graph", () => {
|
|
110
108
|
*/
|
111
109
|
it("should respect conditions in workflow", async () => {
|
112
110
|
const initialState: SharedState<TestState> = {
|
113
|
-
|
114
|
-
|
115
|
-
step: 2,
|
116
|
-
},
|
111
|
+
status: "init",
|
112
|
+
step: 2,
|
117
113
|
};
|
118
114
|
|
119
115
|
// Initialiser le graph avec l'état initial
|
@@ -125,7 +121,7 @@ describe("Graph", () => {
|
|
125
121
|
await graph.execute(initialState, "process");
|
126
122
|
const result = graph.getState();
|
127
123
|
|
128
|
-
expect(result
|
124
|
+
expect(result).to.deep.equal({
|
129
125
|
status: "init",
|
130
126
|
step: 2,
|
131
127
|
});
|
@@ -137,9 +133,9 @@ describe("Graph", () => {
|
|
137
133
|
const newNode = {
|
138
134
|
name: "new-node",
|
139
135
|
description: "A new test node",
|
140
|
-
execute: async (
|
136
|
+
execute: async (state: SharedState<TestState>) => {
|
141
137
|
return graph.updateState({
|
142
|
-
...state
|
138
|
+
...state,
|
143
139
|
status: "new",
|
144
140
|
step: 4,
|
145
141
|
});
|
@@ -163,9 +159,9 @@ describe("Graph", () => {
|
|
163
159
|
"new-step": {
|
164
160
|
name: "new-step",
|
165
161
|
description: "New step node",
|
166
|
-
execute: async (
|
162
|
+
execute: async (state: SharedState<TestState>) => {
|
167
163
|
return graph.updateState({
|
168
|
-
...state
|
164
|
+
...state,
|
169
165
|
status: "new-step",
|
170
166
|
step: 4,
|
171
167
|
});
|
@@ -184,24 +180,20 @@ describe("Graph", () => {
|
|
184
180
|
describe("State Management", () => {
|
185
181
|
it("should properly update and retrieve state", async () => {
|
186
182
|
const newState: SharedState<TestState> = {
|
187
|
-
|
188
|
-
|
189
|
-
step: 5,
|
190
|
-
},
|
183
|
+
status: "test",
|
184
|
+
step: 5,
|
191
185
|
};
|
192
186
|
|
193
187
|
graph.setState(newState);
|
194
188
|
const retrievedState = graph.getState();
|
195
189
|
|
196
|
-
expect(retrievedState
|
190
|
+
expect(retrievedState).to.deep.equal(newState);
|
197
191
|
});
|
198
192
|
|
199
193
|
it("should merge states correctly when updating partially", () => {
|
200
194
|
const initialState: SharedState<TestState> = {
|
201
|
-
|
202
|
-
|
203
|
-
step: 1,
|
204
|
-
},
|
195
|
+
status: "initial",
|
196
|
+
step: 1,
|
205
197
|
};
|
206
198
|
|
207
199
|
graph.setState(initialState);
|
@@ -212,7 +204,7 @@ describe("Graph", () => {
|
|
212
204
|
|
213
205
|
const updatedState = graph.updateState(partialUpdate);
|
214
206
|
|
215
|
-
expect(updatedState
|
207
|
+
expect(updatedState).to.deep.equal({
|
216
208
|
status: "updated",
|
217
209
|
step: 1,
|
218
210
|
});
|
@@ -233,7 +225,7 @@ describe("Graph", () => {
|
|
233
225
|
let errorCaught = false;
|
234
226
|
try {
|
235
227
|
await graph.execute(
|
236
|
-
{
|
228
|
+
{ status: "test", step: 1 },
|
237
229
|
"error-node",
|
238
230
|
undefined,
|
239
231
|
(error) => {
|
@@ -254,10 +246,8 @@ describe("Graph", () => {
|
|
254
246
|
const strictGraph = new GraphEngine(testDefinition, {
|
255
247
|
schema: TestSchema,
|
256
248
|
initialState: {
|
257
|
-
|
258
|
-
|
259
|
-
step: 0,
|
260
|
-
},
|
249
|
+
status: "init",
|
250
|
+
step: 0,
|
261
251
|
},
|
262
252
|
});
|
263
253
|
|
@@ -295,7 +285,7 @@ describe("Graph", () => {
|
|
295
285
|
|
296
286
|
const parallelNodes = ["node1", "node2", "node3"].map((name) => ({
|
297
287
|
name,
|
298
|
-
execute: async (
|
288
|
+
execute: async (state: SharedState<TestState>) => {
|
299
289
|
executionOrder.push(name);
|
300
290
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
301
291
|
return state;
|
@@ -307,7 +297,7 @@ describe("Graph", () => {
|
|
307
297
|
});
|
308
298
|
|
309
299
|
await graph.executeParallel(
|
310
|
-
{
|
300
|
+
{ status: "test", step: 1 },
|
311
301
|
["node1", "node2", "node3"],
|
312
302
|
2
|
313
303
|
);
|
@@ -326,9 +316,9 @@ describe("Graph", () => {
|
|
326
316
|
it("should emit and handle events correctly", async () => {
|
327
317
|
const eventNode = {
|
328
318
|
name: "event-node",
|
329
|
-
execute: async (
|
319
|
+
execute: async (state: SharedState<TestState>) => {
|
330
320
|
return graph.updateState({
|
331
|
-
...state
|
321
|
+
...state,
|
332
322
|
status: "event-triggered",
|
333
323
|
step: 10,
|
334
324
|
});
|
@@ -347,8 +337,7 @@ describe("Graph", () => {
|
|
347
337
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
348
338
|
|
349
339
|
const state = graph.getState();
|
350
|
-
expect(state.
|
351
|
-
expect(state.context.status).to.equal("event-triggered");
|
340
|
+
expect(state.status).to.equal("event-triggered");
|
352
341
|
});
|
353
342
|
});
|
354
343
|
|
@@ -365,9 +354,9 @@ describe("Graph", () => {
|
|
365
354
|
nodes: {
|
366
355
|
"sub-start": {
|
367
356
|
name: "sub-start",
|
368
|
-
execute: async (
|
357
|
+
execute: async (state: SharedState<TestState>) => {
|
369
358
|
return graph.updateState({
|
370
|
-
...state
|
359
|
+
...state,
|
371
360
|
status: "sub-completed",
|
372
361
|
step: 100,
|
373
362
|
});
|
@@ -382,17 +371,15 @@ describe("Graph", () => {
|
|
382
371
|
graph.addSubGraph(subGraph, "sub-start", "sub-workflow");
|
383
372
|
|
384
373
|
const initialState: SharedState<TestState> = {
|
385
|
-
|
386
|
-
|
387
|
-
step: 0,
|
388
|
-
},
|
374
|
+
status: "init",
|
375
|
+
step: 0,
|
389
376
|
};
|
390
377
|
|
391
378
|
await graph.execute(initialState, "sub-workflow");
|
392
379
|
const state = graph.getState();
|
393
380
|
|
394
|
-
expect(state.
|
395
|
-
expect(state.
|
381
|
+
expect(state.status).to.equal("sub-completed");
|
382
|
+
expect(state.step).to.equal(100);
|
396
383
|
});
|
397
384
|
});
|
398
385
|
|
@@ -463,14 +450,14 @@ describe("Graph", () => {
|
|
463
450
|
const mockPersistence: Persistence<TestState> = {
|
464
451
|
saveState: async (graphName, state, currentNode) => {
|
465
452
|
expect(graphName).to.equal("simple-workflow");
|
466
|
-
expect(state
|
453
|
+
expect(state).to.exist;
|
467
454
|
expect(currentNode).to.exist;
|
468
455
|
},
|
469
456
|
loadState: async () => null,
|
470
457
|
};
|
471
458
|
|
472
459
|
graph.setPersistence(mockPersistence);
|
473
|
-
await graph.execute({
|
460
|
+
await graph.execute({ status: "init", step: 0 }, "start");
|
474
461
|
});
|
475
462
|
});
|
476
463
|
|
@@ -492,7 +479,7 @@ describe("Graph", () => {
|
|
492
479
|
};
|
493
480
|
|
494
481
|
graph.setNotifier(mockNotifier);
|
495
|
-
await graph.execute({
|
482
|
+
await graph.execute({ status: "init", step: 0 }, "start");
|
496
483
|
|
497
484
|
expect(notifications).to.have.length.greaterThan(0);
|
498
485
|
expect(notifications[0].event).to.equal("nodeExecutionStarted");
|
@@ -1,186 +0,0 @@
|
|
1
|
-
import { GraphController } from "@/graph/controller";
|
2
|
-
import { GraphDefinition } from "@/types";
|
3
|
-
import { expect } from "chai";
|
4
|
-
import { z } from "zod";
|
5
|
-
|
6
|
-
describe("Controller", () => {
|
7
|
-
// Define test schema
|
8
|
-
const TestSchema = z.object({
|
9
|
-
status: z.string(),
|
10
|
-
count: z.number(),
|
11
|
-
});
|
12
|
-
|
13
|
-
type TestState = z.infer<typeof TestSchema>;
|
14
|
-
|
15
|
-
// Sample workflow definitions
|
16
|
-
const simpleWorkflow: GraphDefinition<TestState> = {
|
17
|
-
name: "simple-workflow",
|
18
|
-
entryNode: "start",
|
19
|
-
nodes: {
|
20
|
-
start: {
|
21
|
-
name: "start",
|
22
|
-
execute: async (_params: any, state: any) => ({
|
23
|
-
context: {
|
24
|
-
...state.context,
|
25
|
-
status: "completed",
|
26
|
-
count: state.context.count + 1,
|
27
|
-
},
|
28
|
-
}),
|
29
|
-
relationships: [],
|
30
|
-
},
|
31
|
-
},
|
32
|
-
schema: TestSchema,
|
33
|
-
};
|
34
|
-
|
35
|
-
const complexWorkflow: GraphDefinition<TestState> = {
|
36
|
-
name: "complex-workflow",
|
37
|
-
entryNode: "first",
|
38
|
-
nodes: {
|
39
|
-
first: {
|
40
|
-
name: "first",
|
41
|
-
execute: async (_params: any, state: any) => ({
|
42
|
-
context: {
|
43
|
-
...state.context,
|
44
|
-
status: "step1",
|
45
|
-
count: state.context.count + 2,
|
46
|
-
},
|
47
|
-
}),
|
48
|
-
relationships: [],
|
49
|
-
},
|
50
|
-
},
|
51
|
-
schema: TestSchema,
|
52
|
-
};
|
53
|
-
|
54
|
-
let controller: GraphController<TestState>;
|
55
|
-
|
56
|
-
beforeEach(() => {
|
57
|
-
controller = new GraphController<TestState>();
|
58
|
-
});
|
59
|
-
|
60
|
-
describe("Basic Execution", () => {
|
61
|
-
it("should execute a single workflow successfully", async () => {
|
62
|
-
const actions = [
|
63
|
-
{
|
64
|
-
name: "simple-workflow",
|
65
|
-
parameters: [
|
66
|
-
{ name: "status", value: "initial" },
|
67
|
-
{ name: "count", value: 0 },
|
68
|
-
],
|
69
|
-
},
|
70
|
-
];
|
71
|
-
|
72
|
-
const result = await controller.run(actions, [simpleWorkflow]);
|
73
|
-
|
74
|
-
expect(result.context).to.deep.equal({
|
75
|
-
status: "completed",
|
76
|
-
count: 1,
|
77
|
-
});
|
78
|
-
});
|
79
|
-
|
80
|
-
it("should handle multiple workflows", async () => {
|
81
|
-
const actions = [
|
82
|
-
{
|
83
|
-
name: "complex-workflow",
|
84
|
-
parameters: [
|
85
|
-
{ name: "status", value: "initial" },
|
86
|
-
{ name: "count", value: 0 },
|
87
|
-
],
|
88
|
-
},
|
89
|
-
];
|
90
|
-
|
91
|
-
const result = await controller.run(actions, [
|
92
|
-
simpleWorkflow,
|
93
|
-
complexWorkflow,
|
94
|
-
]);
|
95
|
-
|
96
|
-
expect(result.context).to.deep.equal({
|
97
|
-
status: "step1",
|
98
|
-
count: 2,
|
99
|
-
});
|
100
|
-
});
|
101
|
-
});
|
102
|
-
|
103
|
-
describe("Error Handling", () => {
|
104
|
-
it("should throw error when no actions provided", async () => {
|
105
|
-
try {
|
106
|
-
await controller.run([], [simpleWorkflow]);
|
107
|
-
expect.fail("Should have thrown an error");
|
108
|
-
} catch (error) {
|
109
|
-
expect((error as Error).message).to.equal("No actions provided");
|
110
|
-
}
|
111
|
-
});
|
112
|
-
|
113
|
-
it("should throw error when workflow not found", async () => {
|
114
|
-
const actions = [
|
115
|
-
{
|
116
|
-
name: "non-existent-workflow",
|
117
|
-
parameters: [
|
118
|
-
{ name: "status", value: "initial" },
|
119
|
-
{ name: "count", value: 0 },
|
120
|
-
],
|
121
|
-
},
|
122
|
-
];
|
123
|
-
|
124
|
-
try {
|
125
|
-
await controller.run(actions, [simpleWorkflow]);
|
126
|
-
expect.fail("Should have thrown an error");
|
127
|
-
} catch (error) {
|
128
|
-
expect((error as Error).message).to.equal(
|
129
|
-
"Graph not found: non-existent-workflow"
|
130
|
-
);
|
131
|
-
}
|
132
|
-
});
|
133
|
-
});
|
134
|
-
|
135
|
-
describe("Parameter Handling", () => {
|
136
|
-
it("should correctly process workflow parameters", async () => {
|
137
|
-
const actions = [
|
138
|
-
{
|
139
|
-
name: "simple-workflow",
|
140
|
-
parameters: [
|
141
|
-
{ name: "status", value: "custom-initial" },
|
142
|
-
{ name: "count", value: 10 },
|
143
|
-
],
|
144
|
-
},
|
145
|
-
];
|
146
|
-
|
147
|
-
const result = await controller.run(actions, [simpleWorkflow]);
|
148
|
-
|
149
|
-
expect(result.context).to.deep.equal({
|
150
|
-
status: "completed",
|
151
|
-
count: 11,
|
152
|
-
});
|
153
|
-
});
|
154
|
-
});
|
155
|
-
|
156
|
-
describe("Multiple Actions", () => {
|
157
|
-
it("should process the first action only", async () => {
|
158
|
-
const actions = [
|
159
|
-
{
|
160
|
-
name: "simple-workflow",
|
161
|
-
parameters: [
|
162
|
-
{ name: "status", value: "initial" },
|
163
|
-
{ name: "count", value: 0 },
|
164
|
-
],
|
165
|
-
},
|
166
|
-
{
|
167
|
-
name: "complex-workflow",
|
168
|
-
parameters: [
|
169
|
-
{ name: "status", value: "initial" },
|
170
|
-
{ name: "count", value: 5 },
|
171
|
-
],
|
172
|
-
},
|
173
|
-
];
|
174
|
-
|
175
|
-
const result = await controller.run(actions, [
|
176
|
-
simpleWorkflow,
|
177
|
-
complexWorkflow,
|
178
|
-
]);
|
179
|
-
|
180
|
-
expect(result.context).to.deep.equal({
|
181
|
-
status: "completed",
|
182
|
-
count: 1,
|
183
|
-
});
|
184
|
-
});
|
185
|
-
});
|
186
|
-
});
|