@ai.ntellect/core 0.6.7 → 0.6.9
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/create-llm-to-select-multiple-graph copy.ts +34 -40
- package/dist/create-llm-to-select-multiple-graph copy.js +20 -50
- package/dist/graph/engine.js +17 -9
- package/graph/engine.ts +20 -14
- package/package.json +1 -1
- package/test/graph/controller.test.ts +8 -12
- package/test/graph/engine.test.ts +40 -53
- package/types/index.ts +1 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
import { openai } from "@ai-sdk/openai";
|
2
|
-
import {
|
2
|
+
import { generateObject } from "ai";
|
3
3
|
import { parseEther } from "ethers";
|
4
4
|
import { z } from "zod";
|
5
5
|
import { GraphEngine } from "./graph/engine";
|
@@ -10,8 +10,7 @@ import { stringifyZodSchema } from "./utils/stringifiy-zod-schema";
|
|
10
10
|
// ---- I. Create a simple workflow ----
|
11
11
|
// 1. Define the context
|
12
12
|
type MainContext = {
|
13
|
-
|
14
|
-
reasoning?: boolean;
|
13
|
+
results?: Record<string, CombinedContext>[];
|
15
14
|
actions?: Action[];
|
16
15
|
};
|
17
16
|
|
@@ -25,9 +24,7 @@ type ContextA = {
|
|
25
24
|
type: string;
|
26
25
|
};
|
27
26
|
|
28
|
-
type ContextB = {
|
29
|
-
messages: string;
|
30
|
-
};
|
27
|
+
type ContextB = {};
|
31
28
|
|
32
29
|
// // 2. Define the graph
|
33
30
|
|
@@ -52,17 +49,18 @@ const graphDefinitionA: GraphDefinition<ContextA> = {
|
|
52
49
|
"Examples networks: ethereum, arbitrum, base. IMPORTANT: You must respect the network name."
|
53
50
|
),
|
54
51
|
}),
|
55
|
-
execute: async (
|
56
|
-
console.log("💰 Prepare transaction", {
|
57
|
-
const networkConfig =
|
52
|
+
execute: async (state) => {
|
53
|
+
console.log("💰 Prepare transaction", { state });
|
54
|
+
const networkConfig =
|
55
|
+
networkConfigs[(state.chain as any).toLowerCase()];
|
58
56
|
|
59
57
|
if (!networkConfig) {
|
60
|
-
throw new Error(`Network ${
|
58
|
+
throw new Error(`Network ${state.chain} not found`);
|
61
59
|
}
|
62
60
|
|
63
61
|
return {
|
64
|
-
to:
|
65
|
-
value: parseEther(
|
62
|
+
to: state.to,
|
63
|
+
value: parseEther(state.value).toString(),
|
66
64
|
chain: {
|
67
65
|
id: networkConfig.id || 0,
|
68
66
|
rpc: networkConfig.rpc,
|
@@ -99,10 +97,7 @@ const graphDefinitionB: GraphDefinition<ContextB> = {
|
|
99
97
|
},
|
100
98
|
};
|
101
99
|
// 3. Define the initial state
|
102
|
-
const initialState: SharedState<MainContext> = {
|
103
|
-
messages: "",
|
104
|
-
reasoning: true,
|
105
|
-
};
|
100
|
+
const initialState: SharedState<MainContext> = {};
|
106
101
|
type CombinedContext = ContextA | ContextB;
|
107
102
|
|
108
103
|
const graphMaps: GraphDefinition<CombinedContext>[] = [
|
@@ -123,8 +118,8 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
123
118
|
reasoning: {
|
124
119
|
name: "reasoning",
|
125
120
|
description: "Reasoning",
|
126
|
-
execute: async (
|
127
|
-
console.log("Reasoning", {
|
121
|
+
execute: async (state) => {
|
122
|
+
console.log("Reasoning", { state });
|
128
123
|
const startNodesSchema = graphMaps.map(
|
129
124
|
(graphDefinition) =>
|
130
125
|
graphDefinition.nodes[graphDefinition.entryNode]
|
@@ -137,7 +132,7 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
137
132
|
workflows:${stringifyZodSchema(startNodesSchema)}`;
|
138
133
|
console.log(system);
|
139
134
|
|
140
|
-
const llm = await
|
135
|
+
const llm = await generateObject({
|
141
136
|
model: openai("gpt-4o"),
|
142
137
|
prompt,
|
143
138
|
schema: z.object({
|
@@ -158,12 +153,6 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
158
153
|
});
|
159
154
|
console.dir(llm.object, { depth: null });
|
160
155
|
|
161
|
-
for await (const chunk of llm.partialObjectStream) {
|
162
|
-
if (chunk.response) {
|
163
|
-
// console.log(chunk.response);
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
156
|
const actions = (await llm.object).actions;
|
168
157
|
console.log({ actions });
|
169
158
|
|
@@ -173,15 +162,12 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
173
162
|
actions: selectedWorkflows,
|
174
163
|
};
|
175
164
|
},
|
176
|
-
condition: (state) => {
|
177
|
-
return state.reasoning === true;
|
178
|
-
},
|
179
165
|
relationships: [{ name: "actions" }],
|
180
166
|
},
|
181
167
|
actions: {
|
182
168
|
name: "actions",
|
183
169
|
description: "Actions",
|
184
|
-
execute: async (
|
170
|
+
execute: async (state) => {
|
185
171
|
if (!state.actions) {
|
186
172
|
throw new Error("No actions found");
|
187
173
|
}
|
@@ -209,27 +195,25 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
209
195
|
selectedGraphs,
|
210
196
|
startNodes,
|
211
197
|
initialStates,
|
198
|
+
state.actions,
|
212
199
|
(graph) => {
|
213
200
|
console.log(`Graph ${graph.name} updated`, graph.getState());
|
214
201
|
},
|
215
|
-
(
|
202
|
+
(
|
203
|
+
error: Error,
|
204
|
+
nodeName: string,
|
205
|
+
state: SharedState<CombinedContext>
|
206
|
+
) => {
|
216
207
|
console.error(`Erreur dans ${nodeName}`, error, state);
|
217
208
|
}
|
218
209
|
);
|
219
210
|
|
220
|
-
console.log({ results });
|
221
|
-
|
222
211
|
return {
|
223
|
-
|
224
|
-
results,
|
212
|
+
actions: results,
|
225
213
|
};
|
226
214
|
},
|
227
215
|
condition: (state) => {
|
228
|
-
if (
|
229
|
-
state.reasoning === true &&
|
230
|
-
state.actions &&
|
231
|
-
state.actions.length > 0
|
232
|
-
) {
|
216
|
+
if (state.actions && state.actions.length > 0) {
|
233
217
|
return true;
|
234
218
|
}
|
235
219
|
return false;
|
@@ -239,5 +223,15 @@ const graphMaps: GraphDefinition<CombinedContext>[] = [
|
|
239
223
|
};
|
240
224
|
|
241
225
|
const reasoningGraph = new GraphEngine(reasoningGraphDefinition);
|
242
|
-
await reasoningGraph.execute(
|
226
|
+
await reasoningGraph.execute(
|
227
|
+
initialState,
|
228
|
+
"reasoning",
|
229
|
+
(graph) => {
|
230
|
+
console.log("Main graph updated", graph.name);
|
231
|
+
console.dir(graph.getState(), { depth: null });
|
232
|
+
},
|
233
|
+
(error, nodeName, state) => {
|
234
|
+
console.error(`Erreur dans ${nodeName}`, error, state);
|
235
|
+
}
|
236
|
+
);
|
243
237
|
})();
|
@@ -8,13 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
9
|
});
|
10
10
|
};
|
11
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
12
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
13
|
-
var m = o[Symbol.asyncIterator], i;
|
14
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
15
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
16
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
17
|
-
};
|
18
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
19
12
|
const openai_1 = require("@ai-sdk/openai");
|
20
13
|
const ai_1 = require("ai");
|
@@ -43,15 +36,15 @@ const graphDefinitionA = {
|
|
43
36
|
.string()
|
44
37
|
.describe("Examples networks: ethereum, arbitrum, base. IMPORTANT: You must respect the network name."),
|
45
38
|
}),
|
46
|
-
execute: (
|
47
|
-
console.log("💰 Prepare transaction", {
|
48
|
-
const networkConfig = index_copy_1.networkConfigs[
|
39
|
+
execute: (state) => __awaiter(void 0, void 0, void 0, function* () {
|
40
|
+
console.log("💰 Prepare transaction", { state });
|
41
|
+
const networkConfig = index_copy_1.networkConfigs[state.chain.toLowerCase()];
|
49
42
|
if (!networkConfig) {
|
50
|
-
throw new Error(`Network ${
|
43
|
+
throw new Error(`Network ${state.chain} not found`);
|
51
44
|
}
|
52
45
|
return {
|
53
|
-
to:
|
54
|
-
value: (0, ethers_1.parseEther)(
|
46
|
+
to: state.to,
|
47
|
+
value: (0, ethers_1.parseEther)(state.value).toString(),
|
55
48
|
chain: {
|
56
49
|
id: networkConfig.id || 0,
|
57
50
|
rpc: networkConfig.rpc,
|
@@ -86,10 +79,7 @@ const graphDefinitionB = {
|
|
86
79
|
},
|
87
80
|
};
|
88
81
|
// 3. Define the initial state
|
89
|
-
const initialState = {
|
90
|
-
messages: "",
|
91
|
-
reasoning: true,
|
92
|
-
};
|
82
|
+
const initialState = {};
|
93
83
|
const graphMaps = [
|
94
84
|
graphDefinitionA,
|
95
85
|
graphDefinitionB,
|
@@ -106,16 +96,15 @@ const graphMaps = [
|
|
106
96
|
reasoning: {
|
107
97
|
name: "reasoning",
|
108
98
|
description: "Reasoning",
|
109
|
-
execute: (
|
110
|
-
|
111
|
-
console.log("Reasoning", { params, state });
|
99
|
+
execute: (state) => __awaiter(void 0, void 0, void 0, function* () {
|
100
|
+
console.log("Reasoning", { state });
|
112
101
|
const startNodesSchema = graphMaps.map((graphDefinition) => graphDefinition.nodes[graphDefinition.entryNode]);
|
113
102
|
// Pass the start nodes into stringifyZodSchema
|
114
103
|
const system = `You are a wallet assistant. Don't reuse the same workflow multiple times.
|
115
104
|
Here the available workflows and parameters:
|
116
105
|
workflows:${(0, stringifiy_zod_schema_1.stringifyZodSchema)(startNodesSchema)}`;
|
117
106
|
console.log(system);
|
118
|
-
const llm = yield (0, ai_1.
|
107
|
+
const llm = yield (0, ai_1.generateObject)({
|
119
108
|
model: (0, openai_1.openai)("gpt-4o"),
|
120
109
|
prompt,
|
121
110
|
schema: zod_1.z.object({
|
@@ -131,23 +120,6 @@ const graphMaps = [
|
|
131
120
|
system,
|
132
121
|
});
|
133
122
|
console.dir(llm.object, { depth: null });
|
134
|
-
try {
|
135
|
-
for (var _d = true, _e = __asyncValues(llm.partialObjectStream), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
136
|
-
_c = _f.value;
|
137
|
-
_d = false;
|
138
|
-
const chunk = _c;
|
139
|
-
if (chunk.response) {
|
140
|
-
// console.log(chunk.response);
|
141
|
-
}
|
142
|
-
}
|
143
|
-
}
|
144
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
145
|
-
finally {
|
146
|
-
try {
|
147
|
-
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
148
|
-
}
|
149
|
-
finally { if (e_1) throw e_1.error; }
|
150
|
-
}
|
151
123
|
const actions = (yield llm.object).actions;
|
152
124
|
console.log({ actions });
|
153
125
|
const selectedWorkflows = (yield llm.object).actions;
|
@@ -156,15 +128,12 @@ const graphMaps = [
|
|
156
128
|
actions: selectedWorkflows,
|
157
129
|
};
|
158
130
|
}),
|
159
|
-
condition: (state) => {
|
160
|
-
return state.reasoning === true;
|
161
|
-
},
|
162
131
|
relationships: [{ name: "actions" }],
|
163
132
|
},
|
164
133
|
actions: {
|
165
134
|
name: "actions",
|
166
135
|
description: "Actions",
|
167
|
-
execute: (
|
136
|
+
execute: (state) => __awaiter(void 0, void 0, void 0, function* () {
|
168
137
|
if (!state.actions) {
|
169
138
|
throw new Error("No actions found");
|
170
139
|
}
|
@@ -174,21 +143,17 @@ const graphMaps = [
|
|
174
143
|
};
|
175
144
|
const { initialStates, graphs: selectedGraphs, startNodes, } = (0, setup_graphs_1.setupGraphsWithActions)(state.actions, baseStateMapping, graphMaps);
|
176
145
|
// Execute graphs with dynamically determined initial states
|
177
|
-
const results = yield engine_1.GraphEngine.executeGraphsInSequence(selectedGraphs, startNodes, initialStates, (graph) => {
|
146
|
+
const results = yield engine_1.GraphEngine.executeGraphsInSequence(selectedGraphs, startNodes, initialStates, state.actions, (graph) => {
|
178
147
|
console.log(`Graph ${graph.name} updated`, graph.getState());
|
179
148
|
}, (error, nodeName, state) => {
|
180
149
|
console.error(`Erreur dans ${nodeName}`, error, state);
|
181
150
|
});
|
182
|
-
console.log({ results });
|
183
151
|
return {
|
184
|
-
|
185
|
-
results,
|
152
|
+
actions: results,
|
186
153
|
};
|
187
154
|
}),
|
188
155
|
condition: (state) => {
|
189
|
-
if (state.
|
190
|
-
state.actions &&
|
191
|
-
state.actions.length > 0) {
|
156
|
+
if (state.actions && state.actions.length > 0) {
|
192
157
|
return true;
|
193
158
|
}
|
194
159
|
return false;
|
@@ -197,5 +162,10 @@ const graphMaps = [
|
|
197
162
|
},
|
198
163
|
};
|
199
164
|
const reasoningGraph = new engine_1.GraphEngine(reasoningGraphDefinition);
|
200
|
-
yield reasoningGraph.execute(initialState, "reasoning")
|
165
|
+
yield reasoningGraph.execute(initialState, "reasoning", (graph) => {
|
166
|
+
console.log("Main graph updated", graph.name);
|
167
|
+
console.dir(graph.getState(), { depth: null });
|
168
|
+
}, (error, nodeName, state) => {
|
169
|
+
console.error(`Erreur dans ${nodeName}`, error, state);
|
170
|
+
});
|
201
171
|
}))();
|
package/dist/graph/engine.js
CHANGED
@@ -44,7 +44,7 @@ class GraphEngine {
|
|
44
44
|
throw new Error("Cycle détecté dans le workflow");
|
45
45
|
}
|
46
46
|
if (options === null || options === void 0 ? void 0 : options.initialState) {
|
47
|
-
this.setState(options.initialState);
|
47
|
+
// this.setState(options.initialState);
|
48
48
|
}
|
49
49
|
}
|
50
50
|
/**
|
@@ -189,7 +189,7 @@ class GraphEngine {
|
|
189
189
|
*/
|
190
190
|
execute(state, startNode, onStream, onError) {
|
191
191
|
return __awaiter(this, void 0, void 0, function* () {
|
192
|
-
var _a
|
192
|
+
var _a;
|
193
193
|
try {
|
194
194
|
// Valide l'état initial via le schéma global (si défini)
|
195
195
|
if (this.schema) {
|
@@ -209,7 +209,7 @@ class GraphEngine {
|
|
209
209
|
this.executedNodes.add(currentNodeName);
|
210
210
|
const currentNode = this.nodes.get(currentNodeName);
|
211
211
|
if (!currentNode) {
|
212
|
-
throw new Error(`
|
212
|
+
throw new Error(`Node ${currentNodeName} introuvable.`);
|
213
213
|
}
|
214
214
|
// Vérification de condition (si présente)
|
215
215
|
if (currentNode.condition &&
|
@@ -224,8 +224,7 @@ class GraphEngine {
|
|
224
224
|
node: currentNodeName,
|
225
225
|
});
|
226
226
|
}
|
227
|
-
const
|
228
|
-
const newState = yield currentNode.execute(params || {}, this.currentState);
|
227
|
+
const newState = yield currentNode.execute(this.currentState);
|
229
228
|
if (newState) {
|
230
229
|
this.setState(newState);
|
231
230
|
if (onStream)
|
@@ -268,7 +267,7 @@ class GraphEngine {
|
|
268
267
|
}
|
269
268
|
else {
|
270
269
|
// Cas normal : un seul chemin
|
271
|
-
currentNodeName = ((
|
270
|
+
currentNodeName = ((_a = relationsNodes[0]) === null || _a === void 0 ? void 0 : _a.name) || "";
|
272
271
|
}
|
273
272
|
}
|
274
273
|
return this.getState();
|
@@ -568,17 +567,26 @@ class GraphEngine {
|
|
568
567
|
* @param onError Callback d'erreur
|
569
568
|
* @returns Tableau des états finaux de chaque graphe
|
570
569
|
*/
|
571
|
-
static executeGraphsInSequence(graphs, startNodes, initialStates,
|
570
|
+
static executeGraphsInSequence(graphs, startNodes, initialStates, actions, // Pass actions here
|
571
|
+
onStream, onError) {
|
572
572
|
return __awaiter(this, void 0, void 0, function* () {
|
573
|
+
// Return updated actions directly
|
573
574
|
const finalStates = [];
|
574
575
|
for (let i = 0; i < graphs.length; i++) {
|
575
576
|
const graph = graphs[i];
|
576
577
|
const startNode = startNodes[i];
|
577
578
|
const initialState = initialStates[i];
|
578
579
|
const result = yield graph.execute(initialState, startNode, onStream, onError);
|
579
|
-
finalStates.push(
|
580
|
+
finalStates.push({
|
581
|
+
name: graph.name,
|
582
|
+
result,
|
583
|
+
});
|
580
584
|
}
|
581
|
-
|
585
|
+
// Map results to actions
|
586
|
+
return actions.map((action) => {
|
587
|
+
const result = finalStates.find((state) => state.name === action.name);
|
588
|
+
return Object.assign(Object.assign({}, action), { result: result ? result.result : null });
|
589
|
+
});
|
582
590
|
});
|
583
591
|
}
|
584
592
|
/**
|
package/graph/engine.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Persistence, RealTimeNotifier } from "@/interfaces";
|
2
|
-
import { GraphDefinition, Node, SharedState } from "@/types";
|
2
|
+
import { Action, GraphDefinition, Node, SharedState } from "@/types";
|
3
3
|
import EventEmitter from "events";
|
4
4
|
import { z } from "zod";
|
5
5
|
|
@@ -68,7 +68,7 @@ export class GraphEngine<T> {
|
|
68
68
|
}
|
69
69
|
|
70
70
|
if (options?.initialState) {
|
71
|
-
this.setState(options.initialState);
|
71
|
+
// this.setState(options.initialState);
|
72
72
|
}
|
73
73
|
}
|
74
74
|
|
@@ -112,7 +112,6 @@ export class GraphEngine<T> {
|
|
112
112
|
setNotifier(notifier: RealTimeNotifier): void {
|
113
113
|
this.notifier = notifier;
|
114
114
|
}
|
115
|
-
|
116
115
|
/**
|
117
116
|
* Charge un workflow à partir d'une définition.
|
118
117
|
* @private
|
@@ -260,7 +259,7 @@ export class GraphEngine<T> {
|
|
260
259
|
this.executedNodes.add(currentNodeName);
|
261
260
|
const currentNode = this.nodes.get(currentNodeName);
|
262
261
|
if (!currentNode) {
|
263
|
-
throw new Error(`
|
262
|
+
throw new Error(`Node ${currentNodeName} introuvable.`);
|
264
263
|
}
|
265
264
|
|
266
265
|
// Vérification de condition (si présente)
|
@@ -280,12 +279,7 @@ export class GraphEngine<T> {
|
|
280
279
|
});
|
281
280
|
}
|
282
281
|
|
283
|
-
const
|
284
|
-
const newState = await currentNode.execute(
|
285
|
-
params || {},
|
286
|
-
this.currentState
|
287
|
-
);
|
288
|
-
|
282
|
+
const newState = await currentNode.execute(this.currentState);
|
289
283
|
if (newState) {
|
290
284
|
this.setState(newState);
|
291
285
|
if (onStream) onStream(this);
|
@@ -702,10 +696,12 @@ export class GraphEngine<T> {
|
|
702
696
|
graphs: GraphEngine<U>[],
|
703
697
|
startNodes: string[],
|
704
698
|
initialStates: SharedState<U>[],
|
699
|
+
actions: Action[], // Pass actions here
|
705
700
|
onStream?: (graph: GraphEngine<U>) => void,
|
706
701
|
onError?: (error: Error, nodeName: string, state: SharedState<U>) => void
|
707
|
-
): Promise<
|
708
|
-
|
702
|
+
): Promise<Action[]> {
|
703
|
+
// Return updated actions directly
|
704
|
+
const finalStates: { name: string; result: SharedState<U> }[] = [];
|
709
705
|
|
710
706
|
for (let i = 0; i < graphs.length; i++) {
|
711
707
|
const graph = graphs[i];
|
@@ -717,10 +713,20 @@ export class GraphEngine<T> {
|
|
717
713
|
onStream,
|
718
714
|
onError
|
719
715
|
);
|
720
|
-
finalStates.push(
|
716
|
+
finalStates.push({
|
717
|
+
name: graph.name,
|
718
|
+
result,
|
719
|
+
});
|
721
720
|
}
|
722
721
|
|
723
|
-
|
722
|
+
// Map results to actions
|
723
|
+
return actions.map((action) => {
|
724
|
+
const result = finalStates.find((state) => state.name === action.name);
|
725
|
+
return {
|
726
|
+
...action,
|
727
|
+
result: result ? result.result : null,
|
728
|
+
};
|
729
|
+
});
|
724
730
|
}
|
725
731
|
|
726
732
|
/**
|
package/package.json
CHANGED
@@ -19,12 +19,10 @@ describe("Controller", () => {
|
|
19
19
|
nodes: {
|
20
20
|
start: {
|
21
21
|
name: "start",
|
22
|
-
execute: async (
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
count: state.context.count + 1,
|
27
|
-
},
|
22
|
+
execute: async (state: any) => ({
|
23
|
+
...state,
|
24
|
+
status: "completed",
|
25
|
+
count: state.count + 1,
|
28
26
|
}),
|
29
27
|
relationships: [],
|
30
28
|
},
|
@@ -38,12 +36,10 @@ describe("Controller", () => {
|
|
38
36
|
nodes: {
|
39
37
|
first: {
|
40
38
|
name: "first",
|
41
|
-
execute: async (
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
count: state.context.count + 2,
|
46
|
-
},
|
39
|
+
execute: async (state: any) => ({
|
40
|
+
...state,
|
41
|
+
status: "step1",
|
42
|
+
count: state.count + 2,
|
47
43
|
}),
|
48
44
|
relationships: [],
|
49
45
|
},
|
@@ -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");
|
package/types/index.ts
CHANGED
@@ -209,7 +209,7 @@ export type SharedState<T> = T;
|
|
209
209
|
export type Node<T, P = any> = {
|
210
210
|
name: string;
|
211
211
|
description?: string;
|
212
|
-
execute: (
|
212
|
+
execute: (state: SharedState<T>) => Promise<SharedState<T> | void>;
|
213
213
|
condition?: (state: SharedState<T>) => boolean;
|
214
214
|
relationships?: NodeRelationship[];
|
215
215
|
schema?: z.ZodSchema<P>;
|