@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.
- package/README.md +158 -81
- package/index.ts +462 -22
- package/package copy.json +21 -0
- package/package.json +9 -44
- package/tsconfig.json +108 -22
- package/types.ts +62 -0
- package/utils/executor.ts +42 -0
- package/.mocharc.json +0 -5
- package/dist/graph/controller.d.ts +0 -31
- package/dist/graph/controller.d.ts.map +0 -1
- package/dist/graph/controller.js +0 -71
- package/dist/graph/controller.js.map +0 -1
- package/dist/graph/event-manager.d.ts +0 -93
- package/dist/graph/event-manager.d.ts.map +0 -1
- package/dist/graph/event-manager.js +0 -296
- package/dist/graph/event-manager.js.map +0 -1
- package/dist/graph/index.d.ts +0 -159
- package/dist/graph/index.d.ts.map +0 -1
- package/dist/graph/index.js +0 -303
- package/dist/graph/index.js.map +0 -1
- package/dist/graph/logger.d.ts +0 -46
- package/dist/graph/logger.d.ts.map +0 -1
- package/dist/graph/logger.js +0 -69
- package/dist/graph/logger.js.map +0 -1
- package/dist/graph/node.d.ts +0 -93
- package/dist/graph/node.d.ts.map +0 -1
- package/dist/graph/node.js +0 -259
- package/dist/graph/node.js.map +0 -1
- package/dist/graph/observer.d.ts +0 -115
- package/dist/graph/observer.d.ts.map +0 -1
- package/dist/graph/observer.js +0 -198
- package/dist/graph/observer.js.map +0 -1
- package/dist/index.d.ts +0 -26
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -42
- package/dist/index.js.map +0 -1
- package/dist/interfaces/index.d.ts +0 -447
- package/dist/interfaces/index.d.ts.map +0 -1
- package/dist/interfaces/index.js +0 -75
- package/dist/interfaces/index.js.map +0 -1
- package/dist/modules/agenda/adapters/node-cron/index.d.ts +0 -17
- package/dist/modules/agenda/adapters/node-cron/index.d.ts.map +0 -1
- package/dist/modules/agenda/adapters/node-cron/index.js +0 -30
- package/dist/modules/agenda/adapters/node-cron/index.js.map +0 -1
- package/dist/modules/agenda/index.d.ts +0 -63
- package/dist/modules/agenda/index.d.ts.map +0 -1
- package/dist/modules/agenda/index.js +0 -141
- package/dist/modules/agenda/index.js.map +0 -1
- package/dist/modules/embedding/adapters/ai/index.d.ts +0 -29
- package/dist/modules/embedding/adapters/ai/index.d.ts.map +0 -1
- package/dist/modules/embedding/adapters/ai/index.js +0 -58
- package/dist/modules/embedding/adapters/ai/index.js.map +0 -1
- package/dist/modules/embedding/index.d.ts +0 -36
- package/dist/modules/embedding/index.d.ts.map +0 -1
- package/dist/modules/embedding/index.js +0 -60
- package/dist/modules/embedding/index.js.map +0 -1
- package/dist/modules/memory/adapters/in-memory/index.d.ts +0 -120
- package/dist/modules/memory/adapters/in-memory/index.d.ts.map +0 -1
- package/dist/modules/memory/adapters/in-memory/index.js +0 -211
- package/dist/modules/memory/adapters/in-memory/index.js.map +0 -1
- package/dist/modules/memory/adapters/meilisearch/index.d.ts +0 -110
- package/dist/modules/memory/adapters/meilisearch/index.d.ts.map +0 -1
- package/dist/modules/memory/adapters/meilisearch/index.js +0 -321
- package/dist/modules/memory/adapters/meilisearch/index.js.map +0 -1
- package/dist/modules/memory/adapters/redis/index.d.ts +0 -82
- package/dist/modules/memory/adapters/redis/index.d.ts.map +0 -1
- package/dist/modules/memory/adapters/redis/index.js +0 -159
- package/dist/modules/memory/adapters/redis/index.js.map +0 -1
- package/dist/modules/memory/index.d.ts +0 -67
- package/dist/modules/memory/index.d.ts.map +0 -1
- package/dist/modules/memory/index.js +0 -104
- package/dist/modules/memory/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -170
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3
- package/dist/types/index.js.map +0 -1
- package/dist/utils/generate-action-schema.d.ts +0 -5
- package/dist/utils/generate-action-schema.d.ts.map +0 -1
- package/dist/utils/generate-action-schema.js +0 -44
- package/dist/utils/generate-action-schema.js.map +0 -1
- package/dist/utils/header-builder.d.ts +0 -12
- package/dist/utils/header-builder.d.ts.map +0 -1
- package/dist/utils/header-builder.js +0 -35
- package/dist/utils/header-builder.js.map +0 -1
- package/graph/controller.ts +0 -74
- package/graph/event-manager.ts +0 -363
- package/graph/index.ts +0 -395
- package/graph/logger.ts +0 -70
- package/graph/node.ts +0 -327
- package/graph/observer.ts +0 -368
- package/interfaces/index.ts +0 -548
- package/modules/agenda/adapters/node-cron/index.ts +0 -25
- package/modules/agenda/index.ts +0 -146
- package/modules/embedding/adapters/ai/index.ts +0 -42
- package/modules/embedding/index.ts +0 -45
- package/modules/memory/adapters/in-memory/index.ts +0 -207
- package/modules/memory/adapters/meilisearch/index.ts +0 -361
- package/modules/memory/adapters/redis/index.ts +0 -164
- package/modules/memory/index.ts +0 -93
- package/test/graph/controller.test.ts +0 -187
- package/test/graph/event-manager.test.ts +0 -118
- package/test/graph/index.test.ts +0 -684
- package/test/graph/node.test.ts +0 -655
- package/test/graph/observer.test.ts +0 -398
- package/test/modules/agenda/node-cron.test.ts +0 -307
- package/test/modules/memory/adapters/in-memory.test.ts +0 -153
- package/test/modules/memory/adapters/meilisearch.test.ts +0 -287
- package/test/modules/memory/base.test.ts +0 -230
- package/types/index.ts +0 -190
- package/utils/generate-action-schema.ts +0 -46
- package/utils/header-builder.ts +0 -40
@@ -1,164 +0,0 @@
|
|
1
|
-
import { createClient } from "redis";
|
2
|
-
import { IMemoryAdapter } from "../../../../interfaces";
|
3
|
-
import { BaseMemoryType, CreateMemoryInput } from "../../../../types";
|
4
|
-
|
5
|
-
/**
|
6
|
-
* @module RedisAdapter
|
7
|
-
* @description Adapter implementation for Redis as a memory storage solution.
|
8
|
-
* Provides integration with Redis for storing and retrieving memory entries with TTL support.
|
9
|
-
* @implements {IMemoryAdapter}
|
10
|
-
*/
|
11
|
-
export class RedisAdapter implements IMemoryAdapter {
|
12
|
-
private redis;
|
13
|
-
private readonly cachePrefix: string;
|
14
|
-
private readonly cacheTTL: number;
|
15
|
-
|
16
|
-
/**
|
17
|
-
* Creates an instance of RedisAdapter
|
18
|
-
* @param {string} redisUrl - Redis connection URL
|
19
|
-
* @param {Object} options - Configuration options
|
20
|
-
* @param {string} [options.cachePrefix="memory:"] - Prefix for Redis keys
|
21
|
-
* @param {number} [options.cacheTTL=3600] - Default TTL in seconds
|
22
|
-
*/
|
23
|
-
constructor(
|
24
|
-
private readonly redisUrl: string,
|
25
|
-
options: {
|
26
|
-
cachePrefix?: string;
|
27
|
-
cacheTTL?: number;
|
28
|
-
}
|
29
|
-
) {
|
30
|
-
this.cachePrefix = options.cachePrefix || "memory:";
|
31
|
-
this.cacheTTL = options.cacheTTL || 3600;
|
32
|
-
this.redis = createClient({
|
33
|
-
url: redisUrl,
|
34
|
-
socket: {
|
35
|
-
tls: true,
|
36
|
-
rejectUnauthorized: true,
|
37
|
-
},
|
38
|
-
});
|
39
|
-
}
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Initializes the Redis connection
|
43
|
-
* @param {string} roomId - Room identifier
|
44
|
-
* @returns {Promise<void>}
|
45
|
-
*/
|
46
|
-
async init(roomId: string): Promise<void> {
|
47
|
-
this.redis.on("error", (err) => console.error("Redis Client Error:", err));
|
48
|
-
await this.redis.connect();
|
49
|
-
}
|
50
|
-
|
51
|
-
/**
|
52
|
-
* Creates a new memory entry in Redis
|
53
|
-
* @param {CreateMemoryInput & { embedding?: number[] }} input - Memory data with optional embedding
|
54
|
-
* @returns {Promise<BaseMemoryType | undefined>} Created memory or undefined
|
55
|
-
*/
|
56
|
-
async createMemory(
|
57
|
-
input: CreateMemoryInput & { embedding?: number[] }
|
58
|
-
): Promise<BaseMemoryType | undefined> {
|
59
|
-
const memory: BaseMemoryType = {
|
60
|
-
id: input.id || crypto.randomUUID(),
|
61
|
-
data: input.data,
|
62
|
-
embedding: input.embedding,
|
63
|
-
roomId: input.roomId,
|
64
|
-
createdAt: new Date(),
|
65
|
-
};
|
66
|
-
|
67
|
-
const key = memory.roomId
|
68
|
-
? `${this.cachePrefix}${memory.roomId}:${memory.id}`
|
69
|
-
: `${this.cachePrefix}${memory.id}`;
|
70
|
-
|
71
|
-
await this.redis.set(key, JSON.stringify(memory), {
|
72
|
-
EX: this.cacheTTL,
|
73
|
-
});
|
74
|
-
|
75
|
-
return memory;
|
76
|
-
}
|
77
|
-
|
78
|
-
/**
|
79
|
-
* Retrieves a memory by ID and room ID from Redis
|
80
|
-
* @param {string} id - Memory identifier
|
81
|
-
* @param {string} roomId - Room identifier
|
82
|
-
* @returns {Promise<BaseMemoryType | null>} Memory entry or null if not found
|
83
|
-
*/
|
84
|
-
async getMemoryById(
|
85
|
-
id: string,
|
86
|
-
roomId: string
|
87
|
-
): Promise<BaseMemoryType | null> {
|
88
|
-
const key = `${this.cachePrefix}${roomId}:${id}`;
|
89
|
-
const data = await this.redis.get(key);
|
90
|
-
return data ? JSON.parse(data) : null;
|
91
|
-
}
|
92
|
-
|
93
|
-
/**
|
94
|
-
* Searches for memories in Redis based on pattern matching
|
95
|
-
* @param {string} query - Search query
|
96
|
-
* @param {Object} options - Search options
|
97
|
-
* @param {string} options.roomId - Room identifier
|
98
|
-
* @param {number} [options.limit] - Maximum number of results
|
99
|
-
* @returns {Promise<BaseMemoryType[]>} Array of matching memories
|
100
|
-
*/
|
101
|
-
async getMemoryByIndex(
|
102
|
-
query: string,
|
103
|
-
options: { roomId: string; limit?: number }
|
104
|
-
): Promise<BaseMemoryType[]> {
|
105
|
-
const pattern = `${this.cachePrefix}${options.roomId}:*`;
|
106
|
-
const keys = await this.redis.keys(pattern);
|
107
|
-
const memories = await Promise.all(
|
108
|
-
keys.map(async (key) => {
|
109
|
-
const data = await this.redis.get(key);
|
110
|
-
return data ? JSON.parse(data) : null;
|
111
|
-
})
|
112
|
-
);
|
113
|
-
return memories.filter(Boolean).slice(0, options.limit || 10);
|
114
|
-
}
|
115
|
-
|
116
|
-
/**
|
117
|
-
* Retrieves all memories for a room from Redis
|
118
|
-
* @param {string} roomId - Room identifier
|
119
|
-
* @returns {Promise<BaseMemoryType[]>} Array of all memories
|
120
|
-
*/
|
121
|
-
async getAllMemories(roomId: string): Promise<BaseMemoryType[]> {
|
122
|
-
const pattern = `${this.cachePrefix}${roomId}:*`;
|
123
|
-
const keys = await this.redis.keys(pattern);
|
124
|
-
const memories = await Promise.all(
|
125
|
-
keys.map(async (key) => {
|
126
|
-
const data = await this.redis.get(key);
|
127
|
-
return data ? JSON.parse(data) : null;
|
128
|
-
})
|
129
|
-
);
|
130
|
-
return memories.filter(Boolean);
|
131
|
-
}
|
132
|
-
|
133
|
-
/**
|
134
|
-
* Deletes a specific memory from Redis
|
135
|
-
* @param {string} id - Memory identifier
|
136
|
-
* @param {string} roomId - Room identifier
|
137
|
-
* @returns {Promise<void>}
|
138
|
-
*/
|
139
|
-
async clearMemoryById(id: string, roomId: string): Promise<void> {
|
140
|
-
const key = `${this.cachePrefix}${roomId}:${id}`;
|
141
|
-
await this.redis.del(key);
|
142
|
-
}
|
143
|
-
|
144
|
-
/**
|
145
|
-
* Clears all memories across all rooms from Redis
|
146
|
-
* @returns {Promise<void>}
|
147
|
-
*/
|
148
|
-
async clearAllMemories(): Promise<void> {
|
149
|
-
const keys = await this.redis.keys(`${this.cachePrefix}*`);
|
150
|
-
if (keys.length > 0) {
|
151
|
-
await this.redis.del(keys);
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
/**
|
156
|
-
* Closes the Redis connection
|
157
|
-
* @returns {Promise<void>}
|
158
|
-
*/
|
159
|
-
async quit(): Promise<void> {
|
160
|
-
if (this.redis) {
|
161
|
-
await this.redis.quit();
|
162
|
-
}
|
163
|
-
}
|
164
|
-
}
|
package/modules/memory/index.ts
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
import { BaseMemory, IMemoryAdapter } from "../../interfaces";
|
2
|
-
import { BaseMemoryType, CreateMemoryInput } from "../../types";
|
3
|
-
|
4
|
-
/**
|
5
|
-
* @module Memory
|
6
|
-
* @description A module for managing memory storage and retrieval operations.
|
7
|
-
* Implements the BaseMemory abstract class and provides concrete implementations
|
8
|
-
* for memory-related operations using the provided adapter.
|
9
|
-
* @extends {BaseMemory}
|
10
|
-
*/
|
11
|
-
export class Memory extends BaseMemory {
|
12
|
-
/**
|
13
|
-
* Creates an instance of Memory
|
14
|
-
* @param {IMemoryAdapter} adapter - The memory adapter implementation to use
|
15
|
-
*/
|
16
|
-
constructor(adapter: IMemoryAdapter) {
|
17
|
-
super(adapter);
|
18
|
-
}
|
19
|
-
|
20
|
-
/**
|
21
|
-
* Initializes the memory module with default room
|
22
|
-
* @returns {Promise<void>}
|
23
|
-
*/
|
24
|
-
async init(): Promise<void> {
|
25
|
-
await this.adapter.init("default");
|
26
|
-
}
|
27
|
-
|
28
|
-
/**
|
29
|
-
* Creates a new memory entry
|
30
|
-
* @param {CreateMemoryInput & { embedding?: number[] }} input - Memory data with optional embedding
|
31
|
-
* @returns {Promise<BaseMemoryType | undefined>} Created memory or undefined
|
32
|
-
*/
|
33
|
-
async createMemory(
|
34
|
-
input: CreateMemoryInput & { embedding?: number[] }
|
35
|
-
): Promise<BaseMemoryType | undefined> {
|
36
|
-
return this.adapter.createMemory(input);
|
37
|
-
}
|
38
|
-
|
39
|
-
/**
|
40
|
-
* Retrieves a memory by ID and room ID
|
41
|
-
* @param {string} id - Memory identifier
|
42
|
-
* @param {string} roomId - Room identifier
|
43
|
-
* @returns {Promise<BaseMemoryType | null>} Memory entry or null if not found
|
44
|
-
*/
|
45
|
-
async getMemoryById(
|
46
|
-
id: string,
|
47
|
-
roomId: string
|
48
|
-
): Promise<BaseMemoryType | null> {
|
49
|
-
return this.adapter.getMemoryById(id, roomId);
|
50
|
-
}
|
51
|
-
|
52
|
-
/**
|
53
|
-
* Searches for memories based on query and options
|
54
|
-
* @param {string} query - Search query
|
55
|
-
* @param {Object} options - Search options
|
56
|
-
* @param {string} options.roomId - Room identifier
|
57
|
-
* @param {number} [options.limit] - Maximum number of results to return
|
58
|
-
* @returns {Promise<BaseMemoryType[]>} Array of matching memories
|
59
|
-
*/
|
60
|
-
async getMemoryByIndex(
|
61
|
-
query: string,
|
62
|
-
options: { roomId: string; limit?: number }
|
63
|
-
): Promise<BaseMemoryType[]> {
|
64
|
-
return this.adapter.getMemoryByIndex(query, options);
|
65
|
-
}
|
66
|
-
|
67
|
-
/**
|
68
|
-
* Retrieves all memories for a specific room
|
69
|
-
* @param {string} roomId - Room identifier
|
70
|
-
* @returns {Promise<BaseMemoryType[]>} Array of all memories in the room
|
71
|
-
*/
|
72
|
-
async getAllMemories(roomId: string): Promise<BaseMemoryType[]> {
|
73
|
-
return this.adapter.getAllMemories(roomId);
|
74
|
-
}
|
75
|
-
|
76
|
-
/**
|
77
|
-
* Deletes a specific memory
|
78
|
-
* @param {string} id - Memory identifier
|
79
|
-
* @param {string} roomId - Room identifier
|
80
|
-
* @returns {Promise<void>}
|
81
|
-
*/
|
82
|
-
async clearMemoryById(id: string, roomId: string): Promise<void> {
|
83
|
-
await this.adapter.clearMemoryById(id, roomId);
|
84
|
-
}
|
85
|
-
|
86
|
-
/**
|
87
|
-
* Clears all memories across all rooms
|
88
|
-
* @returns {Promise<void>}
|
89
|
-
*/
|
90
|
-
async clearAllMemories(): Promise<void> {
|
91
|
-
await this.adapter.clearAllMemories();
|
92
|
-
}
|
93
|
-
}
|
@@ -1,187 +0,0 @@
|
|
1
|
-
import { expect } from "chai";
|
2
|
-
import { z } from "zod";
|
3
|
-
import { GraphController } from "../../graph/controller";
|
4
|
-
import { GraphFlow } from "../../graph/index";
|
5
|
-
import { Node } from "../../types";
|
6
|
-
|
7
|
-
describe("GraphController", () => {
|
8
|
-
const TestSchema = z.object({
|
9
|
-
counter: z.number(),
|
10
|
-
message: z.string(),
|
11
|
-
});
|
12
|
-
|
13
|
-
const createTestGraph = (name: string): GraphFlow<typeof TestSchema> => {
|
14
|
-
const nodes: Node<typeof TestSchema>[] = [
|
15
|
-
{
|
16
|
-
name: "start",
|
17
|
-
execute: async (context, params) => {
|
18
|
-
context.counter = params?.value ?? 0;
|
19
|
-
context.message = params?.prefix ? `${params.prefix}-${name}` : name;
|
20
|
-
},
|
21
|
-
},
|
22
|
-
{
|
23
|
-
name: "increment",
|
24
|
-
execute: async (context) => {
|
25
|
-
context.counter += 1;
|
26
|
-
},
|
27
|
-
},
|
28
|
-
];
|
29
|
-
|
30
|
-
return new GraphFlow(name, {
|
31
|
-
name,
|
32
|
-
nodes,
|
33
|
-
schema: TestSchema,
|
34
|
-
context: { counter: 0, message: "" },
|
35
|
-
});
|
36
|
-
};
|
37
|
-
|
38
|
-
describe("Sequential Execution", () => {
|
39
|
-
it("should execute graphs sequentially with different params and params", async () => {
|
40
|
-
const graph1 = createTestGraph("graph1");
|
41
|
-
const graph2 = createTestGraph("graph2");
|
42
|
-
const graph3 = createTestGraph("graph3");
|
43
|
-
|
44
|
-
const params = [{ value: 10 }, { value: 20 }, { value: 30 }];
|
45
|
-
|
46
|
-
const params2 = [
|
47
|
-
{ prefix: "test1" },
|
48
|
-
{ prefix: "test2" },
|
49
|
-
{ prefix: "test3" },
|
50
|
-
];
|
51
|
-
|
52
|
-
const results = await GraphController.executeSequential(
|
53
|
-
[graph1, graph2, graph3],
|
54
|
-
["start", "start", "start"],
|
55
|
-
params.map((value, i) => ({ ...value, prefix: params2[i].prefix }))
|
56
|
-
);
|
57
|
-
|
58
|
-
expect(results).to.have.length(3);
|
59
|
-
expect(results[0].counter).to.equal(10);
|
60
|
-
expect(results[1].counter).to.equal(20);
|
61
|
-
expect(results[2].counter).to.equal(30);
|
62
|
-
expect(results[0].message).to.equal("test1-graph1");
|
63
|
-
expect(results[1].message).to.equal("test2-graph2");
|
64
|
-
expect(results[2].message).to.equal("test3-graph3");
|
65
|
-
});
|
66
|
-
|
67
|
-
it("should handle missing params and params gracefully", async () => {
|
68
|
-
const graph1 = createTestGraph("graph1");
|
69
|
-
const graph2 = createTestGraph("graph2");
|
70
|
-
|
71
|
-
const results = await GraphController.executeSequential(
|
72
|
-
[graph1, graph2],
|
73
|
-
["start", "start"]
|
74
|
-
);
|
75
|
-
|
76
|
-
expect(results).to.have.length(2);
|
77
|
-
expect(results[0].counter).to.equal(0);
|
78
|
-
expect(results[1].counter).to.equal(0);
|
79
|
-
expect(results[0].message).to.equal("graph1");
|
80
|
-
expect(results[1].message).to.equal("graph2");
|
81
|
-
});
|
82
|
-
});
|
83
|
-
|
84
|
-
describe("Parallel Execution", () => {
|
85
|
-
it("should execute graphs in parallel with concurrency limit", async () => {
|
86
|
-
const graphs = Array.from({ length: 5 }, (_, i) =>
|
87
|
-
createTestGraph(`graph${i + 1}`)
|
88
|
-
);
|
89
|
-
|
90
|
-
const params = Array.from({ length: 5 }, (_, i) => ({
|
91
|
-
value: (i + 1) * 10,
|
92
|
-
prefix: `test${i + 1}`,
|
93
|
-
}));
|
94
|
-
|
95
|
-
// Ajouter un délai dans l'exécution
|
96
|
-
const originalExecute = graphs[0].execute;
|
97
|
-
graphs[0].execute = async (...args) => {
|
98
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
99
|
-
return originalExecute.apply(graphs[0], args);
|
100
|
-
};
|
101
|
-
|
102
|
-
const startTime = Date.now();
|
103
|
-
const results = await GraphController.executeParallel(
|
104
|
-
graphs,
|
105
|
-
Array(5).fill("start"),
|
106
|
-
2,
|
107
|
-
params
|
108
|
-
);
|
109
|
-
const executionTime = Date.now() - startTime;
|
110
|
-
|
111
|
-
expect(executionTime).to.be.greaterThan(0);
|
112
|
-
expect(results).to.have.length(5);
|
113
|
-
results.forEach((result, i) => {
|
114
|
-
expect(result.counter).to.equal((i + 1) * 10);
|
115
|
-
expect(result.message).to.equal(`test${i + 1}-graph${i + 1}`);
|
116
|
-
});
|
117
|
-
});
|
118
|
-
|
119
|
-
it("should handle errors in parallel execution", async () => {
|
120
|
-
const errorGraph = new GraphFlow("errorGraph", {
|
121
|
-
name: "errorGraph",
|
122
|
-
nodes: [
|
123
|
-
{
|
124
|
-
name: "start",
|
125
|
-
execute: async () => {
|
126
|
-
throw new Error("Test error");
|
127
|
-
},
|
128
|
-
},
|
129
|
-
],
|
130
|
-
schema: TestSchema,
|
131
|
-
context: { counter: 0, message: "" },
|
132
|
-
});
|
133
|
-
|
134
|
-
const successGraph = createTestGraph("successGraph");
|
135
|
-
|
136
|
-
try {
|
137
|
-
await GraphController.executeParallel(
|
138
|
-
[errorGraph, successGraph],
|
139
|
-
["start", "start"],
|
140
|
-
2
|
141
|
-
);
|
142
|
-
expect.fail("Should have thrown an error");
|
143
|
-
} catch (error: any) {
|
144
|
-
expect(error.message).to.equal("Test error");
|
145
|
-
}
|
146
|
-
});
|
147
|
-
});
|
148
|
-
|
149
|
-
describe("Complex Workflows", () => {
|
150
|
-
it("should handle mixed sequential and parallel execution", async () => {
|
151
|
-
const graphs = Array.from({ length: 4 }, (_, i) =>
|
152
|
-
createTestGraph(`graph${i + 1}`)
|
153
|
-
);
|
154
|
-
|
155
|
-
// Exécuter les deux premiers graphes en parallèle
|
156
|
-
const parallelResults = await GraphController.executeParallel(
|
157
|
-
graphs.slice(0, 2),
|
158
|
-
["start", "start"],
|
159
|
-
2,
|
160
|
-
[
|
161
|
-
{ value: 10, prefix: "parallel1" },
|
162
|
-
{ value: 20, prefix: "parallel2" },
|
163
|
-
]
|
164
|
-
);
|
165
|
-
|
166
|
-
// Puis exécuter les deux suivants séquentiellement
|
167
|
-
const sequentialResults = await GraphController.executeSequential(
|
168
|
-
graphs.slice(2),
|
169
|
-
["start", "start"],
|
170
|
-
[
|
171
|
-
{ value: 30, prefix: "seq1" },
|
172
|
-
{ value: 40, prefix: "seq2" },
|
173
|
-
]
|
174
|
-
);
|
175
|
-
|
176
|
-
const allResults = [...parallelResults, ...sequentialResults];
|
177
|
-
expect(allResults).to.have.length(4);
|
178
|
-
expect(allResults.map((r) => r.counter)).to.deep.equal([10, 20, 30, 40]);
|
179
|
-
expect(allResults.map((r) => r.message)).to.deep.equal([
|
180
|
-
"parallel1-graph1",
|
181
|
-
"parallel2-graph2",
|
182
|
-
"seq1-graph3",
|
183
|
-
"seq2-graph4",
|
184
|
-
]);
|
185
|
-
});
|
186
|
-
});
|
187
|
-
});
|
@@ -1,118 +0,0 @@
|
|
1
|
-
import { expect } from "chai";
|
2
|
-
import { EventEmitter } from "events";
|
3
|
-
import { z } from "zod";
|
4
|
-
import { GraphEventManager } from "../../graph/event-manager";
|
5
|
-
|
6
|
-
describe("GraphEventManager", () => {
|
7
|
-
const TestSchema = z.object({
|
8
|
-
counter: z.number(),
|
9
|
-
message: z.string(),
|
10
|
-
});
|
11
|
-
|
12
|
-
let eventManager: GraphEventManager<typeof TestSchema>;
|
13
|
-
let eventEmitter: EventEmitter;
|
14
|
-
let events: any[] = [];
|
15
|
-
|
16
|
-
beforeEach(() => {
|
17
|
-
events = [];
|
18
|
-
eventEmitter = new EventEmitter();
|
19
|
-
eventManager = new GraphEventManager(eventEmitter, new Map(), "test", {
|
20
|
-
counter: 0,
|
21
|
-
message: "Hello",
|
22
|
-
});
|
23
|
-
});
|
24
|
-
|
25
|
-
it("should emit events without duplication", () => {
|
26
|
-
const emittedEvents: any[] = [];
|
27
|
-
eventEmitter.on("test", (event) => emittedEvents.push(event));
|
28
|
-
|
29
|
-
eventManager.emitEvent("test", { data: "test" });
|
30
|
-
|
31
|
-
expect(emittedEvents).to.have.lengthOf(1);
|
32
|
-
expect(emittedEvents[0]).to.deep.equal({ data: "test" });
|
33
|
-
});
|
34
|
-
|
35
|
-
it("should handle nodeStateChanged events correctly", () => {
|
36
|
-
const stateChanges: any[] = [];
|
37
|
-
eventEmitter.on("nodeStateChanged", (event) => stateChanges.push(event));
|
38
|
-
|
39
|
-
eventManager.emitEvent("nodeStateChanged", {
|
40
|
-
nodeName: "test",
|
41
|
-
property: "counter",
|
42
|
-
oldValue: 0,
|
43
|
-
newValue: 1,
|
44
|
-
context: { counter: 1, message: "Hello" },
|
45
|
-
});
|
46
|
-
|
47
|
-
expect(stateChanges).to.have.lengthOf(1);
|
48
|
-
expect(stateChanges[0].nodeName).to.equal("test");
|
49
|
-
expect(stateChanges[0].context.counter).to.equal(1);
|
50
|
-
});
|
51
|
-
|
52
|
-
it("should setup and cleanup event listeners", () => {
|
53
|
-
const nodes = new Map();
|
54
|
-
nodes.set("test", {
|
55
|
-
name: "test",
|
56
|
-
events: ["customEvent"],
|
57
|
-
execute: async () => {},
|
58
|
-
});
|
59
|
-
|
60
|
-
eventManager = new GraphEventManager(eventEmitter, nodes, "test", {
|
61
|
-
counter: 0,
|
62
|
-
message: "Hello",
|
63
|
-
});
|
64
|
-
|
65
|
-
eventManager.setupEventListeners();
|
66
|
-
expect(eventEmitter.listenerCount("customEvent")).to.equal(1);
|
67
|
-
|
68
|
-
// Réinitialiser les listeners
|
69
|
-
eventManager.setupEventListeners();
|
70
|
-
expect(eventEmitter.listenerCount("customEvent")).to.equal(1);
|
71
|
-
});
|
72
|
-
|
73
|
-
it("should handle timeout for correlated events", async () => {
|
74
|
-
const timeout = 100;
|
75
|
-
|
76
|
-
try {
|
77
|
-
// N'émettre qu'un seul événement pour provoquer le timeout
|
78
|
-
eventManager.emitEvent("event1", { data: "test1" });
|
79
|
-
|
80
|
-
await eventManager.waitForCorrelatedEvents(
|
81
|
-
["event1", "event2"],
|
82
|
-
timeout,
|
83
|
-
() => false // La fonction de corrélation retourne toujours false pour forcer le timeout
|
84
|
-
);
|
85
|
-
throw new Error("Should have timed out");
|
86
|
-
} catch (error: any) {
|
87
|
-
expect(error.message).to.include("Timeout waiting for correlated events");
|
88
|
-
}
|
89
|
-
});
|
90
|
-
|
91
|
-
it("should wait for multiple events before continuing", async () => {
|
92
|
-
let receivedEvents = 0;
|
93
|
-
let resolvePromise: (value: unknown) => void;
|
94
|
-
const eventPromise = new Promise((resolve) => {
|
95
|
-
resolvePromise = resolve;
|
96
|
-
});
|
97
|
-
|
98
|
-
// Configurer les écouteurs d'événements AVANT d'émettre
|
99
|
-
eventEmitter.on("event1", () => {
|
100
|
-
receivedEvents++;
|
101
|
-
if (receivedEvents === 2) resolvePromise(true);
|
102
|
-
});
|
103
|
-
eventEmitter.on("event2", () => {
|
104
|
-
receivedEvents++;
|
105
|
-
if (receivedEvents === 2) resolvePromise(true);
|
106
|
-
});
|
107
|
-
|
108
|
-
// Émettre les événements AVANT de démarrer l'attente
|
109
|
-
eventManager.emitEvent("event1", { data: "test1" });
|
110
|
-
eventManager.emitEvent("event2", { data: "test2" });
|
111
|
-
|
112
|
-
// Démarrer l'attente
|
113
|
-
const waitPromise = eventManager.waitForEvents(["event1", "event2"], 1000);
|
114
|
-
|
115
|
-
await Promise.race([waitPromise, eventPromise]);
|
116
|
-
expect(receivedEvents).to.equal(2);
|
117
|
-
});
|
118
|
-
});
|