@ai.ntellect/core 0.6.20 → 0.6.21

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.
@@ -2,8 +2,10 @@ import { expect } from "chai";
2
2
  import EventEmitter from "events";
3
3
  import sinon from "sinon";
4
4
  import { z } from "zod";
5
+ import { GraphController } from "../../graph/controller";
5
6
  import { GraphFlow } from "../../graph/index";
6
7
  import { GraphDefinition, Node } from "../../types";
8
+
7
9
  /**
8
10
  * ✅ Define a valid schema using Zod.
9
11
  */
@@ -389,7 +391,7 @@ describe("Graph", function () {
389
391
  /**
390
392
  * ✅ Test complex workflow with multiple branches
391
393
  */
392
- it("should execute a complex workflow with multiple branches", async function () {
394
+ it("should execute a complex workflow with multiple nodes and accumulate the value", async function () {
393
395
  const nodeA: Node<TestSchema> = {
394
396
  name: "nodeA",
395
397
  execute: async (context) => {
@@ -417,16 +419,14 @@ describe("Graph", function () {
417
419
  const nodeC: Node<TestSchema> = {
418
420
  name: "nodeC",
419
421
  execute: async (context) => {
420
- // Créer une copie du contexte pour éviter les modifications concurrentes
421
- const newValue = (context.value ?? 0) + 5;
422
- context.value = newValue;
422
+ context.value = (context.value ?? 0) + 5;
423
423
  },
424
424
  };
425
425
 
426
426
  [nodeA, nodeB1, nodeB2, nodeC].forEach((node) => graph.addNode(node));
427
427
 
428
428
  await graph.execute("nodeA");
429
- expect(graph.getContext().value).to.equal(9);
429
+ expect(graph.getContext().value).to.equal(15);
430
430
  });
431
431
 
432
432
  /**
@@ -438,141 +438,152 @@ describe("Graph", function () {
438
438
  execute: async (context) => {
439
439
  context.value = (context.value ?? 0) + 5;
440
440
  },
441
- next: ["branchA", "branchB"],
442
- };
443
-
444
- const branchA: Node<TestSchema> = {
445
- name: "branchA",
446
- condition: (context) => (context.value ?? 0) < 10,
447
- execute: async (context) => {
448
- context.value = (context.value ?? 0) * 2;
449
- },
450
- next: ["end"],
451
- };
452
-
453
- const branchB: Node<TestSchema> = {
454
- name: "branchB",
455
- condition: (context) => (context.value ?? 0) >= 10,
456
- execute: async (context) => {
457
- context.value = (context.value ?? 0) + 10;
458
- },
459
441
  next: ["end"],
460
442
  };
461
443
 
462
444
  const endNode: Node<TestSchema> = {
463
445
  name: "end",
464
446
  execute: async (context) => {
465
- context.value = (context.value ?? 0) + 1;
447
+ if ((context.value ?? 0) < 10) {
448
+ context.value = (context.value ?? 0) * 2;
449
+ } else {
450
+ context.value = (context.value ?? 0) + 1;
451
+ }
466
452
  },
467
453
  };
468
454
 
469
- [startNode, branchA, branchB, endNode].forEach((node) =>
470
- graph.addNode(node)
471
- );
472
-
473
- await graph.load({
474
- name: "TestGraph",
475
- nodes: [startNode, branchA, branchB, endNode],
476
- context: { value: 0 },
477
- schema: TestSchema,
478
- });
455
+ [startNode, endNode].forEach((node) => graph.addNode(node));
479
456
 
480
457
  await graph.execute("start");
481
- expect(graph.getContext().value).to.equal(11);
458
+ expect(graph.getContext().value).to.equal(10);
482
459
  });
483
460
 
484
461
  /**
485
- * ✅ Test complex event-driven workflow
462
+ * ✅ Test parallel workflow using GraphController
486
463
  */
487
- it("should handle complex event-driven workflows", async function () {
488
- this.timeout(5000); // Augmenter le timeout pour les tests asynchrones
489
- const eventCounter = { count: 0 };
464
+ it("should handle parallel workflows using GraphController", async function () {
465
+ // Graph 1
466
+ const graph1 = new GraphFlow(
467
+ "Graph1",
468
+ {
469
+ name: "Graph1",
470
+ nodes: [],
471
+ context: { value: 0 },
472
+ schema: TestSchema,
473
+ },
474
+ { verbose: true }
475
+ );
490
476
 
491
- const startNode: Node<TestSchema> = {
492
- name: "start",
493
- events: ["startWorkflow"],
477
+ const processNode1: Node<TestSchema> = {
478
+ name: "process1",
494
479
  execute: async (context) => {
495
480
  context.value = 1;
496
481
  },
497
- next: ["process"],
482
+ next: ["finalize1"],
498
483
  };
499
484
 
500
- const processNode: Node<TestSchema> = {
501
- name: "process",
502
- events: ["processData"],
485
+ const finalizeNode1: Node<TestSchema> = {
486
+ name: "finalize1",
503
487
  execute: async (context) => {
504
488
  context.value = (context.value ?? 0) * 2;
505
489
  },
506
- next: ["finalize"],
507
490
  };
508
491
 
509
- const finalizeNode: Node<TestSchema> = {
510
- name: "finalize",
511
- events: ["complete"],
512
- execute: async (context) => {
513
- context.value = (context.value ?? 0) + 3;
514
- eventCounter.count++;
492
+ // Graph 2
493
+ const graph2 = new GraphFlow(
494
+ "Graph2",
495
+ {
496
+ name: "Graph2",
497
+ nodes: [],
498
+ context: { value: 0 },
499
+ schema: TestSchema,
515
500
  },
516
- };
517
-
518
- [startNode, processNode, finalizeNode].forEach((node) =>
519
- graph.addNode(node)
501
+ { verbose: true }
520
502
  );
521
503
 
522
- // Test sequential event triggering
523
- await graph.emit("startWorkflow");
524
- await graph.emit("processData");
525
- await graph.emit("complete");
504
+ const processNode2: Node<TestSchema> = {
505
+ name: "process2",
506
+ execute: async (context) => {
507
+ context.value = 2;
508
+ },
509
+ next: ["finalize2"],
510
+ };
526
511
 
527
- expect(graph.getContext().value).to.equal(5); // (1 * 2) + 3
528
- expect(eventCounter.count).to.equal(1);
512
+ const finalizeNode2: Node<TestSchema> = {
513
+ name: "finalize2",
514
+ execute: async (context) => {
515
+ context.value = (context.value ?? 0) + 3;
516
+ },
517
+ };
529
518
 
530
- // Reset context for concurrent test
531
- graph.load({
532
- name: "TestGraph",
533
- nodes: [startNode, processNode, finalizeNode],
534
- context: { value: 0 },
535
- schema: TestSchema,
536
- });
519
+ graph1.addNode(processNode1);
520
+ graph1.addNode(finalizeNode1);
521
+ graph2.addNode(processNode2);
522
+ graph2.addNode(finalizeNode2);
537
523
 
538
- // Test concurrent event handling
539
- await Promise.all([
540
- graph.emit("startWorkflow"),
541
- graph.emit("processData"),
542
- graph.emit("complete"),
543
- ]);
524
+ const results = await GraphController.executeParallel(
525
+ [graph1, graph2],
526
+ ["process1", "process2"],
527
+ 2,
528
+ [{}, {}]
529
+ );
544
530
 
545
- expect(eventCounter.count).to.equal(2);
531
+ expect(results[0].value).to.equal(2); // Graph1: 1 * 2
532
+ expect(results[1].value).to.equal(5); // Graph2: 2 + 3
546
533
  });
547
534
 
548
535
  /**
549
- * ✅ Test cyclic workflow with conditional exit
536
+ * ✅ Test sequential workflow using GraphController
550
537
  */
551
- it("should handle cyclic workflows with conditional exit", async function () {
552
- const iterationCount = { count: 0 };
538
+ it("should handle sequential workflows using GraphController", async function () {
539
+ // Graph 1
540
+ const graph1 = new GraphFlow(
541
+ "Graph1",
542
+ {
543
+ name: "Graph1",
544
+ nodes: [],
545
+ context: { value: 1 },
546
+ schema: TestSchema,
547
+ },
548
+ { verbose: true }
549
+ );
553
550
 
554
- const cycleNode: Node<TestSchema> = {
555
- name: "cycle",
551
+ const startNode1: Node<TestSchema> = {
552
+ name: "start1",
556
553
  execute: async (context) => {
557
- context.value = (context.value ?? 0) + 1;
558
- iterationCount.count++;
554
+ context.value = (context.value ?? 0) * 2;
559
555
  },
560
- next: ["checkExit"],
561
556
  };
562
557
 
563
- const checkExitNode: Node<TestSchema> = {
564
- name: "checkExit",
565
- execute: async () => {},
566
- next: (context) => {
567
- return (context.value ?? 0) < 5 ? ["cycle"] : [];
558
+ // Graph 2
559
+ const graph2 = new GraphFlow(
560
+ "Graph2",
561
+ {
562
+ name: "Graph2",
563
+ nodes: [],
564
+ context: { value: 3 },
565
+ schema: TestSchema,
566
+ },
567
+ { verbose: true }
568
+ );
569
+
570
+ const startNode2: Node<TestSchema> = {
571
+ name: "start2",
572
+ execute: async (context) => {
573
+ context.value = (context.value ?? 0) + 2;
568
574
  },
569
575
  };
570
576
 
571
- [cycleNode, checkExitNode].forEach((node) => graph.addNode(node));
577
+ graph1.addNode(startNode1);
578
+ graph2.addNode(startNode2);
572
579
 
573
- await graph.execute("cycle");
580
+ const results = await GraphController.executeSequential(
581
+ [graph1, graph2],
582
+ ["start1", "start2"],
583
+ [{}, {}]
584
+ );
574
585
 
575
- expect(graph.getContext().value).to.equal(5);
576
- expect(iterationCount.count).to.equal(5);
586
+ expect(results[0].value).to.equal(2); // Graph1: 1 * 2
587
+ expect(results[1].value).to.equal(5); // Graph2: 3 + 2
577
588
  });
578
589
  });
@@ -1,13 +1,14 @@
1
1
  import { z } from "zod";
2
- import { Node } from "../types";
2
+ import { GraphFlow } from "../graph/index";
3
3
 
4
- export const generateActionSchema = (nodes: Node<any>[]) => {
5
- return nodes
6
- .map((node) => {
7
- const schemaStr = node.inputs
8
- ? getSchemaString(node.inputs)
4
+ export const generateActionSchema = (graphs: GraphFlow<any>[]) => {
5
+ return graphs
6
+ .map((graph) => {
7
+ const rootNode = Array.from(graph.nodes.values())[0];
8
+ const schemaStr = rootNode.inputs
9
+ ? getSchemaString(rootNode.inputs)
9
10
  : "No parameters";
10
- return `Workflow: ${node.name}\nParameters: ${schemaStr}`;
11
+ return `Workflow: ${graph.name}\nParameters: ${schemaStr}`;
11
12
  })
12
13
  .join("\n\n");
13
14
  };
package/.env.example DELETED
@@ -1,2 +0,0 @@
1
- OPENAI_API_KEY=
2
- REDIS_URL=
package/graph.ts DELETED
@@ -1,74 +0,0 @@
1
- import { Node } from "types";
2
- import { z } from "zod";
3
- import { GraphController, GraphFlow } from "./index";
4
-
5
- // 🏗 Définition des schémas pour chaque graphe
6
- const schemaA = z.object({
7
- input: z.string(),
8
- result: z.string().optional(),
9
- });
10
-
11
- const schemaB = z.object({
12
- number: z.number(),
13
- result: z.number().optional(),
14
- });
15
-
16
- // 🔹 **Graph A** : Convertit une chaîne en majuscules
17
- const processText: Node<typeof schemaA> = {
18
- name: "processText",
19
- execute: async (context) => {
20
- context.result = context.input.toUpperCase();
21
- console.log("📢 Graphe A : Texte transformé →", context.result);
22
- },
23
- };
24
-
25
- // 🔹 **Graph B** : Multiplie un nombre par 10
26
- const multiplyNumber: Node<typeof schemaB> = {
27
- name: "multiplyNumber",
28
- execute: async (context) => {
29
- context.result = context.number * 10;
30
- console.log("🔢 Graphe B : Nombre multiplié →", context.result);
31
- },
32
- };
33
-
34
- // 🔗 **Création des graphes**
35
- const graphA = new GraphFlow("GraphA", {
36
- name: "GraphA",
37
- nodes: [processText],
38
- context: { input: "" },
39
- schema: schemaA,
40
- });
41
-
42
- const graphB = new GraphFlow("GraphB", {
43
- name: "GraphB",
44
- nodes: [multiplyNumber],
45
- context: { number: 0 },
46
- schema: schemaB,
47
- });
48
-
49
- (async () => {
50
- try {
51
- console.log("🚀 **Exécution Séquentielle** des graphes...");
52
- const sequentialResults = await GraphController.executeSequential(
53
- [graphA, graphB],
54
- ["processText", "multiplyNumber"],
55
- [{ input: "hello world" }, { number: 5 }]
56
- );
57
-
58
- console.log("🟢 **Résultats Séquentiels :**", sequentialResults);
59
-
60
- console.log(
61
- "\n⚡ **Exécution Parallèle** avec limitation de concurrence..."
62
- );
63
- const parallelResults = await GraphController.executeParallel(
64
- [graphA, graphB],
65
- ["processText", "multiplyNumber"],
66
- 1, // ⚠️ Limite de concurrence (1 à la fois)
67
- [{ input: "parallel execution" }, { number: 7 }]
68
- );
69
-
70
- console.log("🟢 **Résultats Parallèles :**", parallelResults);
71
- } catch (error) {
72
- console.error("❌ Erreur lors de l’exécution :", error);
73
- }
74
- })();