@ai.ntellect/core 0.7.8 → 1.0.0

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 (111) hide show
  1. package/README.md +158 -81
  2. package/index.ts +462 -22
  3. package/package copy.json +21 -0
  4. package/package.json +9 -44
  5. package/tsconfig.json +108 -22
  6. package/types.ts +62 -0
  7. package/utils/executor.ts +42 -0
  8. package/.mocharc.json +0 -5
  9. package/dist/graph/controller.d.ts +0 -31
  10. package/dist/graph/controller.d.ts.map +0 -1
  11. package/dist/graph/controller.js +0 -71
  12. package/dist/graph/controller.js.map +0 -1
  13. package/dist/graph/event-manager.d.ts +0 -93
  14. package/dist/graph/event-manager.d.ts.map +0 -1
  15. package/dist/graph/event-manager.js +0 -296
  16. package/dist/graph/event-manager.js.map +0 -1
  17. package/dist/graph/index.d.ts +0 -159
  18. package/dist/graph/index.d.ts.map +0 -1
  19. package/dist/graph/index.js +0 -303
  20. package/dist/graph/index.js.map +0 -1
  21. package/dist/graph/logger.d.ts +0 -46
  22. package/dist/graph/logger.d.ts.map +0 -1
  23. package/dist/graph/logger.js +0 -69
  24. package/dist/graph/logger.js.map +0 -1
  25. package/dist/graph/node.d.ts +0 -93
  26. package/dist/graph/node.d.ts.map +0 -1
  27. package/dist/graph/node.js +0 -259
  28. package/dist/graph/node.js.map +0 -1
  29. package/dist/graph/observer.d.ts +0 -115
  30. package/dist/graph/observer.d.ts.map +0 -1
  31. package/dist/graph/observer.js +0 -198
  32. package/dist/graph/observer.js.map +0 -1
  33. package/dist/index.d.ts +0 -26
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js +0 -42
  36. package/dist/index.js.map +0 -1
  37. package/dist/interfaces/index.d.ts +0 -447
  38. package/dist/interfaces/index.d.ts.map +0 -1
  39. package/dist/interfaces/index.js +0 -75
  40. package/dist/interfaces/index.js.map +0 -1
  41. package/dist/modules/agenda/adapters/node-cron/index.d.ts +0 -17
  42. package/dist/modules/agenda/adapters/node-cron/index.d.ts.map +0 -1
  43. package/dist/modules/agenda/adapters/node-cron/index.js +0 -30
  44. package/dist/modules/agenda/adapters/node-cron/index.js.map +0 -1
  45. package/dist/modules/agenda/index.d.ts +0 -63
  46. package/dist/modules/agenda/index.d.ts.map +0 -1
  47. package/dist/modules/agenda/index.js +0 -141
  48. package/dist/modules/agenda/index.js.map +0 -1
  49. package/dist/modules/embedding/adapters/ai/index.d.ts +0 -29
  50. package/dist/modules/embedding/adapters/ai/index.d.ts.map +0 -1
  51. package/dist/modules/embedding/adapters/ai/index.js +0 -58
  52. package/dist/modules/embedding/adapters/ai/index.js.map +0 -1
  53. package/dist/modules/embedding/index.d.ts +0 -36
  54. package/dist/modules/embedding/index.d.ts.map +0 -1
  55. package/dist/modules/embedding/index.js +0 -60
  56. package/dist/modules/embedding/index.js.map +0 -1
  57. package/dist/modules/memory/adapters/in-memory/index.d.ts +0 -120
  58. package/dist/modules/memory/adapters/in-memory/index.d.ts.map +0 -1
  59. package/dist/modules/memory/adapters/in-memory/index.js +0 -211
  60. package/dist/modules/memory/adapters/in-memory/index.js.map +0 -1
  61. package/dist/modules/memory/adapters/meilisearch/index.d.ts +0 -110
  62. package/dist/modules/memory/adapters/meilisearch/index.d.ts.map +0 -1
  63. package/dist/modules/memory/adapters/meilisearch/index.js +0 -321
  64. package/dist/modules/memory/adapters/meilisearch/index.js.map +0 -1
  65. package/dist/modules/memory/adapters/redis/index.d.ts +0 -82
  66. package/dist/modules/memory/adapters/redis/index.d.ts.map +0 -1
  67. package/dist/modules/memory/adapters/redis/index.js +0 -159
  68. package/dist/modules/memory/adapters/redis/index.js.map +0 -1
  69. package/dist/modules/memory/index.d.ts +0 -67
  70. package/dist/modules/memory/index.d.ts.map +0 -1
  71. package/dist/modules/memory/index.js +0 -104
  72. package/dist/modules/memory/index.js.map +0 -1
  73. package/dist/types/index.d.ts +0 -170
  74. package/dist/types/index.d.ts.map +0 -1
  75. package/dist/types/index.js +0 -3
  76. package/dist/types/index.js.map +0 -1
  77. package/dist/utils/generate-action-schema.d.ts +0 -5
  78. package/dist/utils/generate-action-schema.d.ts.map +0 -1
  79. package/dist/utils/generate-action-schema.js +0 -44
  80. package/dist/utils/generate-action-schema.js.map +0 -1
  81. package/dist/utils/header-builder.d.ts +0 -12
  82. package/dist/utils/header-builder.d.ts.map +0 -1
  83. package/dist/utils/header-builder.js +0 -35
  84. package/dist/utils/header-builder.js.map +0 -1
  85. package/graph/controller.ts +0 -74
  86. package/graph/event-manager.ts +0 -363
  87. package/graph/index.ts +0 -395
  88. package/graph/logger.ts +0 -70
  89. package/graph/node.ts +0 -327
  90. package/graph/observer.ts +0 -368
  91. package/interfaces/index.ts +0 -548
  92. package/modules/agenda/adapters/node-cron/index.ts +0 -25
  93. package/modules/agenda/index.ts +0 -146
  94. package/modules/embedding/adapters/ai/index.ts +0 -42
  95. package/modules/embedding/index.ts +0 -45
  96. package/modules/memory/adapters/in-memory/index.ts +0 -207
  97. package/modules/memory/adapters/meilisearch/index.ts +0 -361
  98. package/modules/memory/adapters/redis/index.ts +0 -164
  99. package/modules/memory/index.ts +0 -93
  100. package/test/graph/controller.test.ts +0 -187
  101. package/test/graph/event-manager.test.ts +0 -118
  102. package/test/graph/index.test.ts +0 -684
  103. package/test/graph/node.test.ts +0 -655
  104. package/test/graph/observer.test.ts +0 -398
  105. package/test/modules/agenda/node-cron.test.ts +0 -307
  106. package/test/modules/memory/adapters/in-memory.test.ts +0 -153
  107. package/test/modules/memory/adapters/meilisearch.test.ts +0 -287
  108. package/test/modules/memory/base.test.ts +0 -230
  109. package/types/index.ts +0 -190
  110. package/utils/generate-action-schema.ts +0 -46
  111. package/utils/header-builder.ts +0 -40
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSchemaString = exports.generateActionSchema = void 0;
4
- const zod_1 = require("zod");
5
- const generateActionSchema = (graphs) => {
6
- return graphs
7
- .map((graph) => {
8
- const rootNode = Array.from(graph.nodes.values())[0];
9
- const schemaStr = rootNode.params
10
- ? (0, exports.getSchemaString)(rootNode.params)
11
- : "No parameters";
12
- return `Workflow: ${graph.name}\nParameters: ${schemaStr}`;
13
- })
14
- .join("\n\n");
15
- };
16
- exports.generateActionSchema = generateActionSchema;
17
- const getSchemaString = (schema) => {
18
- if (schema instanceof zod_1.z.ZodObject) {
19
- const entries = Object.entries(schema.shape);
20
- const fields = entries.map(([key, value]) => {
21
- const description = value._def.description;
22
- const schemaStr = (0, exports.getSchemaString)(value);
23
- return description
24
- ? `${key}: ${schemaStr} // ${description}`
25
- : `${key}: ${schemaStr}`;
26
- });
27
- return `z.object({${fields.join(", ")}})`;
28
- }
29
- if (schema instanceof zod_1.z.ZodArray) {
30
- return `z.array(${(0, exports.getSchemaString)(schema.element)})`;
31
- }
32
- if (schema instanceof zod_1.z.ZodString) {
33
- return "z.string()";
34
- }
35
- if (schema instanceof zod_1.z.ZodNumber) {
36
- return "z.number()";
37
- }
38
- if (schema instanceof zod_1.z.ZodBoolean) {
39
- return "z.boolean()";
40
- }
41
- return `z.unknown()`;
42
- };
43
- exports.getSchemaString = getSchemaString;
44
- //# sourceMappingURL=generate-action-schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-action-schema.js","sourceRoot":"","sources":["../../utils/generate-action-schema.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAGjB,MAAM,oBAAoB,GAAG,CAAC,MAAwB,EAAE,EAAE;IAC/D,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM;YAC/B,CAAC,CAAC,IAAA,uBAAe,EAAC,QAAQ,CAAC,MAAM,CAAC;YAClC,CAAC,CAAC,eAAe,CAAC;QACpB,OAAO,aAAa,KAAK,CAAC,IAAI,iBAAiB,SAAS,EAAE,CAAC;IAC7D,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC,CAAC;AAVW,QAAA,oBAAoB,wBAU/B;AAEK,MAAM,eAAe,GAAG,CAAC,MAAiB,EAAU,EAAE;IAC3D,IAAI,MAAM,YAAY,OAAC,CAAC,SAAS,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC1C,MAAM,WAAW,GAAI,KAAa,CAAC,IAAI,CAAC,WAAW,CAAC;YACpD,MAAM,SAAS,GAAG,IAAA,uBAAe,EAAC,KAAkB,CAAC,CAAC;YACtD,OAAO,WAAW;gBAChB,CAAC,CAAC,GAAG,GAAG,KAAK,SAAS,OAAO,WAAW,EAAE;gBAC1C,CAAC,CAAC,GAAG,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,OAAO,aAAa,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5C,CAAC;IAED,IAAI,MAAM,YAAY,OAAC,CAAC,QAAQ,EAAE,CAAC;QACjC,OAAO,WAAW,IAAA,uBAAe,EAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;IACvD,CAAC;IAED,IAAI,MAAM,YAAY,OAAC,CAAC,SAAS,EAAE,CAAC;QAClC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,MAAM,YAAY,OAAC,CAAC,SAAS,EAAE,CAAC;QAClC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,MAAM,YAAY,OAAC,CAAC,UAAU,EAAE,CAAC;QACnC,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AA9BW,QAAA,eAAe,mBA8B1B"}
@@ -1,12 +0,0 @@
1
- type HeaderValue = string | string[] | undefined;
2
- export declare class LLMHeaderBuilder {
3
- private headers;
4
- private _result;
5
- constructor();
6
- addHeader(key: string, value: HeaderValue): LLMHeaderBuilder;
7
- valueOf(): string;
8
- toString(): string;
9
- static create(): LLMHeaderBuilder;
10
- }
11
- export {};
12
- //# sourceMappingURL=header-builder.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"header-builder.d.ts","sourceRoot":"","sources":["../../utils/header-builder.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAEjD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAAS;;IAOxB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,gBAAgB;IAiB5D,OAAO,IAAI,MAAM;IAIjB,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,MAAM,IAAI,gBAAgB;CAGlC"}
@@ -1,35 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LLMHeaderBuilder = void 0;
4
- class LLMHeaderBuilder {
5
- constructor() {
6
- this.headers = new Map();
7
- this._result = "";
8
- }
9
- addHeader(key, value) {
10
- if (Array.isArray(value)) {
11
- this.headers.set(key, value.join("\n"));
12
- }
13
- else {
14
- this.headers.set(key, value);
15
- }
16
- // Build result immediately
17
- this._result = Array.from(this.headers.entries())
18
- .filter(([_, value]) => value !== undefined)
19
- .map(([key, value]) => `# ${key}: ${value}`)
20
- .join("\n")
21
- .trim();
22
- return this;
23
- }
24
- valueOf() {
25
- return this._result;
26
- }
27
- toString() {
28
- return this._result;
29
- }
30
- static create() {
31
- return new LLMHeaderBuilder();
32
- }
33
- }
34
- exports.LLMHeaderBuilder = LLMHeaderBuilder;
35
- //# sourceMappingURL=header-builder.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"header-builder.js","sourceRoot":"","sources":["../../utils/header-builder.ts"],"names":[],"mappings":";;;AAEA,MAAa,gBAAgB;IAI3B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,SAAS,CAAC,GAAW,EAAE,KAAkB;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC9C,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;aAC3C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,KAAK,EAAE,CAAC;aAC3C,IAAI,CAAC,IAAI,CAAC;aACV,IAAI,EAAE,CAAC;QAEV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,gBAAgB,EAAE,CAAC;IAChC,CAAC;CACF;AArCD,4CAqCC"}
@@ -1,74 +0,0 @@
1
- import { ZodSchema } from "zod";
2
- import { GraphContext } from "../types";
3
- import { GraphFlow } from "./index";
4
- import { NodeParams } from "./node";
5
-
6
- /**
7
- * Controller class for managing the execution of graph flows
8
- * Handles both sequential and parallel execution of multiple graphs
9
- */
10
- export class GraphController {
11
- /**
12
- * Executes multiple graphs sequentially
13
- * @param graphs - Array of GraphFlow instances to execute
14
- * @param startNodes - Array of starting node identifiers for each graph
15
- * @param params - Optional array of node parameters for each graph
16
- * @returns Map containing results of each graph execution, keyed by graph name and index
17
- * @template T - Zod schema type for graph context validation
18
- */
19
- static async executeSequential<T extends ZodSchema>(
20
- graphs: GraphFlow<T>[],
21
- startNodes: string[],
22
- params?: NodeParams[]
23
- ): Promise<any[]> {
24
- const results = new Map<string, GraphContext<T>>();
25
- for (let i = 0; i < graphs.length; i++) {
26
- const result = await graphs[i].execute(startNodes[i], params?.[i]);
27
- results.set(`${graphs[i].name}-${i}`, result);
28
- }
29
- return Array.from(results.values());
30
- }
31
-
32
- private static async executeGraph<T extends ZodSchema>(
33
- graph: GraphFlow<T>,
34
- startNode: string,
35
- params?: NodeParams
36
- ): Promise<GraphContext<T>> {
37
- try {
38
- return await graph.execute(startNode, params);
39
- } catch (error) {
40
- throw error;
41
- }
42
- }
43
-
44
- /**
45
- * Executes multiple graphs in parallel with optional concurrency control
46
- * @param graphs - Array of GraphFlow instances to execute
47
- * @param startNodes - Array of starting node identifiers for each graph
48
- * @param concurrency - Optional limit on number of concurrent graph executions
49
- * @param params - Optional array of node parameters for each graph
50
- * @returns Map containing results of each graph execution, keyed by graph name
51
- * @template T - Zod schema type for graph context validation
52
- */
53
- static async executeParallel<T extends ZodSchema>(
54
- graphs: GraphFlow<T>[],
55
- startNodes: string[],
56
- concurrency: number,
57
- params?: NodeParams[]
58
- ): Promise<GraphContext<T>[]> {
59
- const results: GraphContext<T>[] = [];
60
-
61
- for (let i = 0; i < graphs.length; i += concurrency) {
62
- const batch = graphs.slice(i, i + concurrency);
63
- const batchResults = await Promise.all(
64
- batch.map((graph, idx) => {
65
- const param = params?.[i + idx];
66
- return this.executeGraph(graph, startNodes[i + idx], param);
67
- })
68
- );
69
- results.push(...batchResults);
70
- }
71
-
72
- return results;
73
- }
74
- }
@@ -1,363 +0,0 @@
1
- import { Observable, Subject, filter } from "rxjs";
2
- import { ZodSchema } from "zod";
3
- import { IEventEmitter } from "../interfaces";
4
- import { GraphContext, GraphEvent, Node } from "../types";
5
- import { GraphNode } from "./node";
6
-
7
- /**
8
- * Manages event handling and routing for a graph
9
- * Coordinates event emission, listening, and execution of event-driven nodes
10
- * @template T - The Zod schema type for validation
11
- */
12
- export class GraphEventManager<T extends ZodSchema> {
13
- private eventSubject: Subject<GraphEvent<T>> = new Subject();
14
- private nodeStreams: Map<string, Observable<GraphEvent<T>>> = new Map();
15
- private context: GraphContext<T>;
16
- private name: string;
17
- private graphEvents?: string[];
18
- private entryNode?: string;
19
- private globalErrorHandler?: (error: Error, context: GraphContext<T>) => void;
20
-
21
- /**
22
- * Creates a new GraphEventManager instance
23
- * @param eventEmitter - The event emitter implementation to use
24
- * @param nodes - Map of all nodes in the graph
25
- * @param name - Name of the graph
26
- * @param context - Initial graph context
27
- * @param graphEvents - List of events the graph should listen to
28
- * @param entryNode - Name of the entry node for graph events
29
- * @param globalErrorHandler - Global error handling function
30
- * @param nodeExecutor - GraphNode instance for executing nodes
31
- */
32
- constructor(
33
- private eventEmitter: IEventEmitter,
34
- private nodes: Map<string, Node<T, any>>,
35
- name: string,
36
- context: GraphContext<T>,
37
- graphEvents?: string[],
38
- entryNode?: string,
39
- globalErrorHandler?: (error: Error, context: GraphContext<T>) => void,
40
- private nodeExecutor?: GraphNode<T>
41
- ) {
42
- this.name = name;
43
- this.context = context;
44
- this.graphEvents = graphEvents;
45
- this.entryNode = entryNode;
46
- this.globalErrorHandler = globalErrorHandler;
47
- this.setupEventStreams();
48
- }
49
-
50
- /**
51
- * Sets up event streams for all nodes that listen to events
52
- */
53
- public setupEventStreams(): void {
54
- for (const [nodeName, node] of this.nodes.entries()) {
55
- if (node.events && node.events.length > 0) {
56
- const nodeStream = this.eventSubject.pipe(
57
- filter((event) => node.events!.includes(event.type))
58
- );
59
- this.nodeStreams.set(nodeName, nodeStream);
60
- }
61
- }
62
- }
63
-
64
- /**
65
- * Emits an event with optional payload and context
66
- * @param type - The type of event to emit
67
- * @param payload - Optional payload data
68
- * @param context - Optional graph context
69
- */
70
- public emitEvent<P = any>(
71
- type: string,
72
- payload?: P,
73
- context?: GraphContext<T>
74
- ): void {
75
- // Éviter la double imbrication des événements
76
- const event = {
77
- type,
78
- payload,
79
- timestamp: Date.now(),
80
- };
81
-
82
- // Émettre l'événement une seule fois
83
- this.eventSubject.next(event);
84
- this.eventEmitter.emit(type, payload);
85
- }
86
-
87
- /**
88
- * Sets up event listeners for all nodes in the graph
89
- * Handles cleanup and re-registration of event listeners
90
- */
91
- setupEventListeners(): void {
92
- // First remove only the existing node-based listeners that we might have created previously
93
- // We do NOT remove, for example, "nodeStarted" or "nodeCompleted" listeners that test code added.
94
- for (const [eventName, listener] of this.eventEmitter
95
- .rawListeners("*")
96
- .entries()) {
97
- // This can be tricky—EventEmitter doesn't directly let you remove by "type" of listener.
98
- // Alternatively, we can store references in a separate structure.
99
- // For simplicity, let's do a full removeAllListeners() on node-specified events (only),
100
- // then re-add them below, but keep the test-based events like "nodeStarted" or "nodeCompleted".
101
- }
102
-
103
- // The simplest approach: removeAllListeners for each event that is declared as a node event
104
- // so we don't stack up duplicates:
105
- const allEvents = new Set<string>();
106
- for (const node of this.nodes.values()) {
107
- if (node.events) {
108
- node.events.forEach((evt) => allEvents.add(evt));
109
- }
110
- }
111
- for (const evt of allEvents) {
112
- // remove only those events that are used by nodes
113
- this.eventEmitter.removeAllListeners(evt);
114
- }
115
-
116
- // Now re-add the node-based event triggers
117
- for (const node of this.nodes.values()) {
118
- if (node.events && node.events.length > 0) {
119
- node.events.forEach((event) => {
120
- this.eventEmitter.on(
121
- event,
122
- async (data?: Partial<GraphContext<T>>) => {
123
- const freshContext = structuredClone(this.context);
124
- if (data) Object.assign(freshContext, data);
125
-
126
- // If triggered by an event, we pass "true" so event-driven node will skip `next`.
127
- await this.executeNode(
128
- node.name,
129
- freshContext,
130
- undefined,
131
- /* triggeredByEvent= */ true
132
- );
133
- }
134
- );
135
- });
136
- }
137
- }
138
- }
139
-
140
- /**
141
- * Sets up listeners for graph-level events
142
- * Handles graph start, completion, and error events
143
- */
144
- setupGraphEventListeners(): void {
145
- if (this.graphEvents && this.graphEvents.length > 0) {
146
- this.graphEvents.forEach((event) => {
147
- this.eventEmitter.on(event, async (data?: Partial<GraphContext<T>>) => {
148
- const freshContext = this.createNewContext();
149
- if (data) Object.assign(freshContext, data);
150
-
151
- // Emit "graphStarted"
152
- this.eventEmitter.emit("graphStarted", { name: this.name });
153
-
154
- try {
155
- // Execute the graph starting from the entry node
156
- if (!this.entryNode) {
157
- throw new Error("No entry node defined for graph event handling");
158
- }
159
-
160
- await this.executeNode(
161
- this.entryNode,
162
- freshContext,
163
- undefined,
164
- false
165
- );
166
-
167
- // Emit "graphCompleted"
168
- this.eventEmitter.emit("graphCompleted", {
169
- name: this.name,
170
- context: this.context,
171
- });
172
- } catch (error) {
173
- // Emit "graphError"
174
- this.eventEmitter.emit("graphError", { name: this.name, error });
175
- this.globalErrorHandler?.(error as Error, freshContext);
176
- throw error;
177
- }
178
- });
179
- });
180
- }
181
- }
182
-
183
- /**
184
- * Waits for a set of events to occur within a timeout period
185
- * @param events - Array of event names to wait for
186
- * @param timeout - Maximum time to wait in milliseconds
187
- * @returns Promise that resolves with array of received events
188
- * @throws Error if timeout occurs before all events are received
189
- */
190
- async waitForEvents(
191
- events: string[],
192
- timeout: number = 30000
193
- ): Promise<any[]> {
194
- return new Promise((resolve, reject) => {
195
- const receivedEvents = new Map<string, any>();
196
- const eventHandlers = new Map();
197
- let isResolved = false;
198
-
199
- const cleanup = () => {
200
- events.forEach((event) => {
201
- const handler = eventHandlers.get(event);
202
- if (handler) {
203
- this.eventEmitter.removeListener(event, handler);
204
- }
205
- });
206
- };
207
-
208
- events.forEach((event) => {
209
- const handler = (eventData: any) => {
210
- if (!isResolved) {
211
- receivedEvents.set(event, eventData);
212
-
213
- if (events.every((e) => receivedEvents.has(e))) {
214
- isResolved = true;
215
- clearTimeout(timeoutId);
216
- cleanup();
217
- resolve(Array.from(receivedEvents.values()));
218
- }
219
- }
220
- };
221
-
222
- eventHandlers.set(event, handler);
223
- this.eventEmitter.on(event, handler);
224
- });
225
-
226
- const timeoutId = setTimeout(() => {
227
- if (!isResolved) {
228
- isResolved = true;
229
- cleanup();
230
- reject(new Error(`Timeout waiting for events: ${events.join(", ")}`));
231
- }
232
- }, timeout);
233
- });
234
- }
235
-
236
- /**
237
- * Registers an event handler
238
- * @param eventName - Name of the event to listen for
239
- * @param handler - Function to handle the event
240
- */
241
- on(eventName: string, handler: (...args: any[]) => void): void {
242
- this.eventEmitter.on(eventName, handler);
243
- }
244
-
245
- /**
246
- * Emits an event through the event emitter
247
- * @param eventName - Name of the event to emit
248
- * @param data - Optional data to include with the event
249
- */
250
- emit(eventName: string, data?: any): void {
251
- this.eventEmitter.emit(eventName, data);
252
- }
253
-
254
- /**
255
- * Creates a new context object by cloning the current context
256
- * @returns A new graph context instance
257
- * @private
258
- */
259
- private createNewContext(): GraphContext<T> {
260
- return structuredClone(this.context);
261
- }
262
-
263
- /**
264
- * Executes a node with the given parameters
265
- * @param nodeName - Name of the node to execute
266
- * @param context - Graph context for execution
267
- * @param inputs - Input data for the node
268
- * @param triggeredByEvent - Whether execution was triggered by an event
269
- * @returns Promise that resolves when execution is complete
270
- * @throws Error if nodeExecutor is not initialized
271
- * @private
272
- */
273
- private async executeNode(
274
- nodeName: string,
275
- context: GraphContext<T>,
276
- inputs: any,
277
- triggeredByEvent: boolean
278
- ): Promise<void> {
279
- if (!this.nodeExecutor) {
280
- throw new Error("NodeExecutor not initialized");
281
- }
282
-
283
- const node = this.nodes.get(nodeName);
284
- if (!node) {
285
- throw new Error(`Node "${nodeName}" not found`);
286
- }
287
-
288
- // Attendre les événements si waitForEvents est configuré
289
- if (node.waitForEvents) {
290
- try {
291
- await this.waitForEvents(
292
- node.waitForEvents.events,
293
- node.waitForEvents.timeout
294
- );
295
- } catch (error) {
296
- throw new Error(
297
- `Timeout waiting for events in node "${nodeName}": ${
298
- (error as Error).message
299
- }`
300
- );
301
- }
302
- }
303
-
304
- return this.nodeExecutor.executeNode(
305
- nodeName,
306
- context,
307
- inputs,
308
- triggeredByEvent
309
- );
310
- }
311
-
312
- async waitForCorrelatedEvents(
313
- eventTypes: string[],
314
- timeoutMs: number,
315
- correlationFn: (events: GraphEvent<T>[]) => boolean
316
- ): Promise<GraphEvent<T>[]> {
317
- return new Promise((resolve, reject) => {
318
- const receivedEvents = new Map<string, GraphEvent<T>>();
319
- let isResolved = false;
320
-
321
- const timeoutId = setTimeout(() => {
322
- if (!isResolved) {
323
- isResolved = true;
324
- eventTypes.forEach((type) => {
325
- this.eventEmitter.removeAllListeners(type);
326
- });
327
- reject(
328
- new Error(
329
- `Timeout waiting for correlated events: ${eventTypes.join(", ")}`
330
- )
331
- );
332
- }
333
- }, timeoutMs);
334
-
335
- const checkCorrelation = () => {
336
- if (eventTypes.every((type) => receivedEvents.has(type))) {
337
- const events = Array.from(receivedEvents.values());
338
- if (correlationFn(events)) {
339
- if (!isResolved) {
340
- isResolved = true;
341
- clearTimeout(timeoutId);
342
- eventTypes.forEach((type) => {
343
- this.eventEmitter.removeAllListeners(type);
344
- });
345
- resolve(events);
346
- }
347
- }
348
- }
349
- };
350
-
351
- eventTypes.forEach((eventType) => {
352
- this.eventEmitter.on(eventType, (eventData: any) => {
353
- receivedEvents.set(eventType, {
354
- type: eventType,
355
- payload: eventData,
356
- timestamp: Date.now(),
357
- });
358
- checkCorrelation();
359
- });
360
- });
361
- });
362
- }
363
- }