@ai.ntellect/core 0.6.16 → 0.6.19
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/.mocharc.json +1 -2
- package/README.md +123 -178
- package/dist/graph/controller.js +29 -6
- package/dist/graph/index.js +402 -0
- package/dist/index.js +22 -7
- package/dist/interfaces/index.js +15 -0
- package/dist/modules/agenda/adapters/node-cron/index.js +29 -0
- package/dist/modules/agenda/index.js +140 -0
- package/dist/{services/embedding.js → modules/embedding/adapters/ai/index.js} +24 -7
- package/dist/modules/embedding/index.js +59 -0
- package/dist/modules/memory/adapters/in-memory/index.js +210 -0
- package/dist/{memory → modules/memory}/adapters/meilisearch/index.js +97 -2
- package/dist/{memory → modules/memory}/adapters/redis/index.js +77 -15
- package/dist/modules/memory/index.js +103 -0
- package/dist/utils/{stringifiy-zod-schema.js → generate-action-schema.js} +5 -5
- package/graph/controller.ts +38 -14
- package/graph/index.ts +468 -0
- package/index.ts +25 -7
- package/interfaces/index.ts +346 -28
- package/modules/agenda/adapters/node-cron/index.ts +25 -0
- package/modules/agenda/index.ts +159 -0
- package/modules/embedding/adapters/ai/index.ts +42 -0
- package/modules/embedding/index.ts +45 -0
- package/modules/memory/adapters/in-memory/index.ts +203 -0
- package/{memory → modules/memory}/adapters/meilisearch/index.ts +114 -8
- package/modules/memory/adapters/redis/index.ts +164 -0
- package/modules/memory/index.ts +93 -0
- package/package.json +4 -4
- package/test/graph/index.test.ts +646 -0
- package/test/modules/agenda/node-cron.test.ts +286 -0
- package/test/modules/embedding/ai.test.ts +78 -0
- package/test/modules/memory/adapters/in-memory.test.ts +153 -0
- package/test/{memory → modules/memory}/adapters/meilisearch.test.ts +80 -94
- package/test/modules/memory/adapters/redis.test.ts +169 -0
- package/test/modules/memory/base.test.ts +230 -0
- package/test/services/agenda.test.ts +279 -280
- package/tsconfig.json +0 -3
- package/types/index.ts +82 -203
- package/utils/{stringifiy-zod-schema.ts → generate-action-schema.ts} +3 -3
- package/app/README.md +0 -36
- package/app/app/favicon.ico +0 -0
- package/app/app/globals.css +0 -21
- package/app/app/gun.ts +0 -0
- package/app/app/layout.tsx +0 -18
- package/app/app/page.tsx +0 -321
- package/app/eslint.config.mjs +0 -16
- package/app/next.config.ts +0 -7
- package/app/package-lock.json +0 -5912
- package/app/package.json +0 -31
- package/app/pnpm-lock.yaml +0 -4031
- package/app/postcss.config.mjs +0 -8
- package/app/public/file.svg +0 -1
- package/app/public/globe.svg +0 -1
- package/app/public/next.svg +0 -1
- package/app/public/vercel.svg +0 -1
- package/app/public/window.svg +0 -1
- package/app/tailwind.config.ts +0 -18
- package/app/tsconfig.json +0 -27
- package/dist/graph/graph.js +0 -162
- package/dist/memory/index.js +0 -9
- package/dist/services/agenda.js +0 -115
- package/dist/services/queue.js +0 -142
- package/dist/utils/experimental-graph-rag.js +0 -152
- package/dist/utils/generate-object.js +0 -111
- package/dist/utils/inject-actions.js +0 -16
- package/dist/utils/queue-item-transformer.js +0 -24
- package/dist/utils/sanitize-results.js +0 -60
- package/graph/graph.ts +0 -193
- package/memory/adapters/redis/index.ts +0 -103
- package/memory/index.ts +0 -22
- package/services/agenda.ts +0 -118
- package/services/embedding.ts +0 -26
- package/services/queue.ts +0 -145
- package/test/.env.test +0 -4
- package/test/graph/engine.test.ts +0 -533
- package/test/memory/adapters/redis.test.ts +0 -160
- package/test/memory/base.test.ts +0 -229
- package/test/services/queue.test.ts +0 -286
- package/utils/experimental-graph-rag.ts +0 -170
- package/utils/generate-object.ts +0 -117
- package/utils/inject-actions.ts +0 -19
- package/utils/queue-item-transformer.ts +0 -38
- package/utils/sanitize-results.ts +0 -66
@@ -1,160 +0,0 @@
|
|
1
|
-
import { BaseMemoryService } from "@/interfaces";
|
2
|
-
import { RedisAdapter } from "@/memory/adapters/redis";
|
3
|
-
import { BaseMemoryType } from "@/types";
|
4
|
-
import { expect } from "chai";
|
5
|
-
import dotenv from "dotenv";
|
6
|
-
import Redis from "ioredis";
|
7
|
-
|
8
|
-
// Load environment variables
|
9
|
-
dotenv.config();
|
10
|
-
|
11
|
-
describe("RedisAdapter", () => {
|
12
|
-
before(function () {
|
13
|
-
this.timeout(15000);
|
14
|
-
});
|
15
|
-
|
16
|
-
let redisAdapter: RedisAdapter;
|
17
|
-
let mockBaseMemoryService: BaseMemoryService;
|
18
|
-
let redisClient: Redis | null = null;
|
19
|
-
const fixedDate = new Date("2025-01-30T07:43:50.626Z");
|
20
|
-
|
21
|
-
const testMemory: BaseMemoryType = {
|
22
|
-
id: "test-id",
|
23
|
-
data: "test data",
|
24
|
-
query: "test query",
|
25
|
-
embedding: [0.1, 0.2, 0.3],
|
26
|
-
roomId: "test-room",
|
27
|
-
createdAt: fixedDate,
|
28
|
-
};
|
29
|
-
|
30
|
-
beforeEach(async () => {
|
31
|
-
mockBaseMemoryService = {
|
32
|
-
initializeConnection: async () => {},
|
33
|
-
createMemory: async () => {},
|
34
|
-
getMemoryById: async () => testMemory,
|
35
|
-
getMemoryByIndex: async () => [testMemory],
|
36
|
-
getAllMemories: async () => [testMemory],
|
37
|
-
clearMemoryById: async () => {},
|
38
|
-
clearAllMemories: async () => {},
|
39
|
-
};
|
40
|
-
|
41
|
-
// Use real Redis if environment variables are set, otherwise mock
|
42
|
-
if (process.env.REDIS_URL) {
|
43
|
-
redisClient = new Redis(process.env.REDIS_URL);
|
44
|
-
redisAdapter = new RedisAdapter(process.env.REDIS_URL, {
|
45
|
-
cachePrefix: "test-prefix",
|
46
|
-
cacheTTL: 3600,
|
47
|
-
});
|
48
|
-
} else {
|
49
|
-
// Mock Redis implementation
|
50
|
-
const mockRedis = {
|
51
|
-
connect: async () => {},
|
52
|
-
disconnect: async () => {},
|
53
|
-
set: async (key: string, value: string) => "OK",
|
54
|
-
get: async (key: string) => {
|
55
|
-
if (key.includes("test-id")) {
|
56
|
-
return JSON.stringify({
|
57
|
-
...testMemory,
|
58
|
-
createdAt: fixedDate.toISOString(),
|
59
|
-
});
|
60
|
-
}
|
61
|
-
return null;
|
62
|
-
},
|
63
|
-
keys: async (pattern: string) => {
|
64
|
-
return [`${pattern}test-id`];
|
65
|
-
},
|
66
|
-
mget: async (keys: string[]) => {
|
67
|
-
return keys.map(() =>
|
68
|
-
JSON.stringify({
|
69
|
-
...testMemory,
|
70
|
-
createdAt: fixedDate.toISOString(),
|
71
|
-
})
|
72
|
-
);
|
73
|
-
},
|
74
|
-
del: async () => 1,
|
75
|
-
flushall: async () => "OK",
|
76
|
-
quit: async () => {},
|
77
|
-
};
|
78
|
-
|
79
|
-
redisAdapter = new RedisAdapter(mockRedis as any, {
|
80
|
-
cachePrefix: "test-prefix",
|
81
|
-
cacheTTL: 3600,
|
82
|
-
});
|
83
|
-
}
|
84
|
-
|
85
|
-
await redisAdapter.initializeConnection();
|
86
|
-
});
|
87
|
-
|
88
|
-
afterEach(async () => {
|
89
|
-
if (redisClient) {
|
90
|
-
await redisClient.quit();
|
91
|
-
redisClient = null;
|
92
|
-
}
|
93
|
-
// @ts-ignore pour éviter l'erreur de typage
|
94
|
-
await redisAdapter?.quit?.();
|
95
|
-
});
|
96
|
-
|
97
|
-
describe("Initialization", () => {
|
98
|
-
it("should initialize storage", async () => {
|
99
|
-
await expect(redisAdapter.initializeConnection()).to.not.throw;
|
100
|
-
});
|
101
|
-
});
|
102
|
-
|
103
|
-
describe("Memory Operations", () => {
|
104
|
-
const TEST_ROOM_ID = "test-room";
|
105
|
-
|
106
|
-
it("should create memory", async () => {
|
107
|
-
await expect(
|
108
|
-
redisAdapter.createMemory({
|
109
|
-
data: "test data",
|
110
|
-
query: "test query",
|
111
|
-
roomId: TEST_ROOM_ID,
|
112
|
-
id: "test-id",
|
113
|
-
embedding: [0.1, 0.2, 0.3],
|
114
|
-
createdAt: fixedDate,
|
115
|
-
})
|
116
|
-
).to.not.throw;
|
117
|
-
});
|
118
|
-
|
119
|
-
it("should get memory by ID", async () => {
|
120
|
-
const result = await redisAdapter.getMemoryById("test-id", TEST_ROOM_ID);
|
121
|
-
if (result) {
|
122
|
-
result.createdAt = new Date(result.createdAt);
|
123
|
-
}
|
124
|
-
expect(result).to.deep.equal({
|
125
|
-
...testMemory,
|
126
|
-
createdAt: testMemory.createdAt,
|
127
|
-
});
|
128
|
-
});
|
129
|
-
|
130
|
-
it("should get memories by index", async () => {
|
131
|
-
const results = await redisAdapter.getMemoryByIndex("test", {
|
132
|
-
roomId: TEST_ROOM_ID,
|
133
|
-
limit: 10,
|
134
|
-
});
|
135
|
-
|
136
|
-
expect(results).to.be.an("array");
|
137
|
-
if (results[0]) {
|
138
|
-
results[0].createdAt = new Date(results[0].createdAt);
|
139
|
-
}
|
140
|
-
expect(results[0]).to.deep.equal(testMemory);
|
141
|
-
});
|
142
|
-
|
143
|
-
it("should get all memories", async () => {
|
144
|
-
const results = await redisAdapter.getAllMemories();
|
145
|
-
expect(results).to.be.an("array");
|
146
|
-
if (results[0]) {
|
147
|
-
results[0].createdAt = new Date(results[0].createdAt);
|
148
|
-
}
|
149
|
-
expect(results[0]).to.deep.equal(testMemory);
|
150
|
-
});
|
151
|
-
|
152
|
-
it("should clear memory by ID", async () => {
|
153
|
-
await expect(redisAdapter.clearMemoryById("test-id")).to.not.throw;
|
154
|
-
});
|
155
|
-
|
156
|
-
it("should clear all memories", async () => {
|
157
|
-
await expect(redisAdapter.clearAllMemories()).to.not.throw;
|
158
|
-
});
|
159
|
-
});
|
160
|
-
});
|
package/test/memory/base.test.ts
DELETED
@@ -1,229 +0,0 @@
|
|
1
|
-
import { BaseMemoryService } from "@/interfaces";
|
2
|
-
import { BaseMemory } from "@/memory";
|
3
|
-
import { BaseMemoryType, CreateMemoryInput } from "@/types";
|
4
|
-
import { expect } from "chai";
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Test suite for the BaseMemory service
|
8
|
-
* This suite tests the memory management system that handles storage and retrieval of memory entries
|
9
|
-
*/
|
10
|
-
|
11
|
-
// Classe concrète pour tester BaseMemory
|
12
|
-
class TestMemory extends BaseMemory {
|
13
|
-
async init(): Promise<void> {
|
14
|
-
await this.cacheService.initializeConnection();
|
15
|
-
}
|
16
|
-
|
17
|
-
async createMemory(
|
18
|
-
input: CreateMemoryInput & { embedding?: number[] }
|
19
|
-
): Promise<BaseMemoryType | undefined> {
|
20
|
-
const memory: BaseMemoryType = {
|
21
|
-
id: crypto.randomUUID(),
|
22
|
-
data: input.data,
|
23
|
-
query: input.query,
|
24
|
-
embedding: input.embedding || null,
|
25
|
-
roomId: input.roomId,
|
26
|
-
createdAt: new Date(),
|
27
|
-
};
|
28
|
-
await this.cacheService.createMemory(memory, input.ttl);
|
29
|
-
return memory;
|
30
|
-
}
|
31
|
-
|
32
|
-
async getMemoryById(
|
33
|
-
id: string,
|
34
|
-
roomId: string
|
35
|
-
): Promise<BaseMemoryType | null> {
|
36
|
-
return this.cacheService.getMemoryById(id);
|
37
|
-
}
|
38
|
-
|
39
|
-
async getMemoryByIndex(
|
40
|
-
query: string,
|
41
|
-
options: { roomId: string; limit?: number }
|
42
|
-
): Promise<BaseMemoryType[]> {
|
43
|
-
return this.cacheService.getMemoryByIndex(query, options);
|
44
|
-
}
|
45
|
-
|
46
|
-
async getAllMemories(roomId: string): Promise<BaseMemoryType[]> {
|
47
|
-
return this.cacheService.getAllMemories();
|
48
|
-
}
|
49
|
-
|
50
|
-
async clearMemoryById(id: string, roomId: string): Promise<void> {
|
51
|
-
await this.cacheService.clearMemoryById(id);
|
52
|
-
}
|
53
|
-
|
54
|
-
async clearAllMemories(): Promise<void> {
|
55
|
-
await this.cacheService.clearAllMemories();
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
describe("BaseMemory", () => {
|
60
|
-
let memory: TestMemory;
|
61
|
-
let mockMemoryService: BaseMemoryService;
|
62
|
-
const TEST_ROOM_ID = "test-room";
|
63
|
-
|
64
|
-
// Mock data for testing
|
65
|
-
const testMemory: BaseMemoryType = {
|
66
|
-
id: "test-id",
|
67
|
-
data: "test data",
|
68
|
-
query: "test query",
|
69
|
-
embedding: [0.1, 0.2, 0.3],
|
70
|
-
roomId: "test-room",
|
71
|
-
createdAt: new Date(),
|
72
|
-
};
|
73
|
-
|
74
|
-
beforeEach(() => {
|
75
|
-
// Create mock implementation of BaseMemoryService
|
76
|
-
mockMemoryService = {
|
77
|
-
initializeConnection: async () => Promise.resolve(),
|
78
|
-
createMemory: async (memory: BaseMemoryType) => Promise.resolve(),
|
79
|
-
getMemoryById: async (id: string) => Promise.resolve(testMemory),
|
80
|
-
getMemoryByIndex: async (query: string, options: any) =>
|
81
|
-
Promise.resolve([testMemory]),
|
82
|
-
getAllMemories: async () => Promise.resolve([testMemory]),
|
83
|
-
clearMemoryById: async (id: string) => Promise.resolve(),
|
84
|
-
clearAllMemories: async () => Promise.resolve(),
|
85
|
-
};
|
86
|
-
|
87
|
-
memory = new TestMemory(mockMemoryService);
|
88
|
-
});
|
89
|
-
|
90
|
-
describe("Initialization", () => {
|
91
|
-
it("should initialize the memory service", async () => {
|
92
|
-
let initCalled = false;
|
93
|
-
mockMemoryService.initializeConnection = async () => {
|
94
|
-
initCalled = true;
|
95
|
-
};
|
96
|
-
|
97
|
-
await memory.init();
|
98
|
-
expect(initCalled).to.be.true;
|
99
|
-
});
|
100
|
-
});
|
101
|
-
|
102
|
-
describe("Memory Creation", () => {
|
103
|
-
it("should create a new memory entry", async () => {
|
104
|
-
const input = {
|
105
|
-
data: "test data",
|
106
|
-
query: "test query",
|
107
|
-
roomId: "test-room",
|
108
|
-
ttl: 3600,
|
109
|
-
};
|
110
|
-
|
111
|
-
const result = await memory.createMemory(input);
|
112
|
-
|
113
|
-
expect(result).to.exist;
|
114
|
-
expect(result?.data).to.equal(input.data);
|
115
|
-
expect(result?.query).to.equal(input.query);
|
116
|
-
expect(result?.roomId).to.equal(input.roomId);
|
117
|
-
expect(result?.id).to.be.a("string");
|
118
|
-
});
|
119
|
-
|
120
|
-
it("should create memory with embedding", async () => {
|
121
|
-
const input = {
|
122
|
-
data: "test data",
|
123
|
-
query: "test query",
|
124
|
-
roomId: "test-room",
|
125
|
-
embedding: [0.1, 0.2, 0.3],
|
126
|
-
};
|
127
|
-
|
128
|
-
const result = await memory.createMemory(input);
|
129
|
-
|
130
|
-
expect(result?.embedding).to.deep.equal(input.embedding);
|
131
|
-
});
|
132
|
-
});
|
133
|
-
|
134
|
-
describe("Memory Retrieval", () => {
|
135
|
-
it("should retrieve memory by ID", async () => {
|
136
|
-
const result = await memory.getMemoryById("test-id", TEST_ROOM_ID);
|
137
|
-
expect(result).to.deep.equal(testMemory);
|
138
|
-
});
|
139
|
-
|
140
|
-
it("should retrieve memories by index", async () => {
|
141
|
-
const results = await memory.getMemoryByIndex("test query", {
|
142
|
-
roomId: "test-room",
|
143
|
-
limit: 10,
|
144
|
-
});
|
145
|
-
|
146
|
-
expect(results).to.be.an("array");
|
147
|
-
expect(results[0]).to.deep.equal(testMemory);
|
148
|
-
});
|
149
|
-
|
150
|
-
it("should retrieve all memories", async () => {
|
151
|
-
const results = await memory.getAllMemories(TEST_ROOM_ID);
|
152
|
-
expect(results).to.be.an("array");
|
153
|
-
});
|
154
|
-
});
|
155
|
-
|
156
|
-
describe("Memory Clearing", () => {
|
157
|
-
it("should clear memory by ID", async () => {
|
158
|
-
await memory.clearMemoryById("test-id", TEST_ROOM_ID);
|
159
|
-
});
|
160
|
-
|
161
|
-
it("should clear all memories", async () => {
|
162
|
-
await memory.clearAllMemories();
|
163
|
-
});
|
164
|
-
});
|
165
|
-
|
166
|
-
describe("Error Handling", () => {
|
167
|
-
it("should handle errors during memory creation", async () => {
|
168
|
-
mockMemoryService.createMemory = async () => {
|
169
|
-
throw new Error("Creation failed");
|
170
|
-
};
|
171
|
-
|
172
|
-
try {
|
173
|
-
await memory.createMemory({
|
174
|
-
data: "test",
|
175
|
-
query: "test",
|
176
|
-
roomId: "test",
|
177
|
-
});
|
178
|
-
expect.fail("Should have thrown an error");
|
179
|
-
} catch (error) {
|
180
|
-
expect(error).to.be.instanceOf(Error);
|
181
|
-
expect((error as Error).message).to.equal("Creation failed");
|
182
|
-
}
|
183
|
-
});
|
184
|
-
|
185
|
-
it("should handle errors during memory retrieval", async () => {
|
186
|
-
mockMemoryService.getMemoryById = async () => {
|
187
|
-
throw new Error("Retrieval failed");
|
188
|
-
};
|
189
|
-
|
190
|
-
try {
|
191
|
-
await memory.getMemoryById("test-id", TEST_ROOM_ID);
|
192
|
-
expect.fail("Should have thrown an error");
|
193
|
-
} catch (error) {
|
194
|
-
expect(error).to.be.instanceOf(Error);
|
195
|
-
expect((error as Error).message).to.equal("Retrieval failed");
|
196
|
-
}
|
197
|
-
});
|
198
|
-
});
|
199
|
-
|
200
|
-
describe("Edge Cases", () => {
|
201
|
-
it("should handle undefined embedding", async () => {
|
202
|
-
const input = {
|
203
|
-
data: "test data",
|
204
|
-
query: "test query",
|
205
|
-
roomId: "test-room",
|
206
|
-
embedding: undefined,
|
207
|
-
};
|
208
|
-
|
209
|
-
const result = await memory.createMemory(input);
|
210
|
-
expect(result?.embedding).to.be.null;
|
211
|
-
});
|
212
|
-
|
213
|
-
it("should handle empty query results", async () => {
|
214
|
-
mockMemoryService.getMemoryByIndex = async () => [];
|
215
|
-
|
216
|
-
const results = await memory.getMemoryByIndex("nonexistent", {
|
217
|
-
roomId: "test-room",
|
218
|
-
});
|
219
|
-
expect(results).to.be.an("array").that.is.empty;
|
220
|
-
});
|
221
|
-
|
222
|
-
it("should handle non-existent memory ID", async () => {
|
223
|
-
mockMemoryService.getMemoryById = async () => null;
|
224
|
-
|
225
|
-
const result = await memory.getMemoryById("nonexistent", TEST_ROOM_ID);
|
226
|
-
expect(result).to.be.null;
|
227
|
-
});
|
228
|
-
});
|
229
|
-
});
|
@@ -1,286 +0,0 @@
|
|
1
|
-
import { Queue } from "@/services/queue";
|
2
|
-
import { ActionSchema, QueueCallbacks, QueueItem } from "@/types";
|
3
|
-
import { expect } from "chai";
|
4
|
-
import { z } from "zod";
|
5
|
-
|
6
|
-
describe("Queue", () => {
|
7
|
-
// Test actions setup
|
8
|
-
const testActions: ActionSchema[] = [
|
9
|
-
{
|
10
|
-
name: "action1",
|
11
|
-
description: "Test action 1",
|
12
|
-
parameters: z.object({}),
|
13
|
-
execute: async (params) => ({ success: true, params }),
|
14
|
-
},
|
15
|
-
{
|
16
|
-
name: "action2",
|
17
|
-
description: "Test action 2",
|
18
|
-
parameters: z.object({}),
|
19
|
-
execute: async (params) => ({ success: true, params }),
|
20
|
-
confirmation: {
|
21
|
-
requireConfirmation: true,
|
22
|
-
message: "Confirm action2?",
|
23
|
-
},
|
24
|
-
},
|
25
|
-
{
|
26
|
-
name: "actionWithError",
|
27
|
-
description: "Test error action",
|
28
|
-
parameters: z.object({}),
|
29
|
-
execute: async () => {
|
30
|
-
throw new Error("Test error");
|
31
|
-
},
|
32
|
-
},
|
33
|
-
];
|
34
|
-
|
35
|
-
let queue: Queue;
|
36
|
-
let callbacks: QueueCallbacks;
|
37
|
-
|
38
|
-
beforeEach(() => {
|
39
|
-
// Reset callbacks for each test
|
40
|
-
callbacks = {
|
41
|
-
onActionStart: () => {},
|
42
|
-
onActionComplete: () => {},
|
43
|
-
onQueueComplete: () => {},
|
44
|
-
onConfirmationRequired: async () => true,
|
45
|
-
};
|
46
|
-
queue = new Queue(testActions, callbacks);
|
47
|
-
});
|
48
|
-
|
49
|
-
describe("Queue Management", () => {
|
50
|
-
it("should add a single action to the queue", () => {
|
51
|
-
const action: QueueItem = {
|
52
|
-
name: "action1",
|
53
|
-
parameters: [{ name: "param1", value: "value1" }],
|
54
|
-
};
|
55
|
-
|
56
|
-
queue.add(action);
|
57
|
-
expect(queue["queue"]).to.have.lengthOf(1);
|
58
|
-
expect(queue["queue"][0]).to.deep.equal(action);
|
59
|
-
});
|
60
|
-
|
61
|
-
it("should add multiple actions to the queue", () => {
|
62
|
-
const actions: QueueItem[] = [
|
63
|
-
{
|
64
|
-
name: "action1",
|
65
|
-
parameters: [{ name: "param1", value: "value1" }],
|
66
|
-
},
|
67
|
-
{
|
68
|
-
name: "action2",
|
69
|
-
parameters: [{ name: "param2", value: "value2" }],
|
70
|
-
},
|
71
|
-
];
|
72
|
-
|
73
|
-
queue.add(actions);
|
74
|
-
expect(queue["queue"]).to.have.lengthOf(2);
|
75
|
-
expect(queue["queue"]).to.deep.equal(actions);
|
76
|
-
});
|
77
|
-
});
|
78
|
-
|
79
|
-
describe("Action Execution", () => {
|
80
|
-
it("should execute a single action successfully", async () => {
|
81
|
-
const action: QueueItem = {
|
82
|
-
name: "action1",
|
83
|
-
parameters: [{ name: "param1", value: "value1" }],
|
84
|
-
};
|
85
|
-
|
86
|
-
queue.add(action);
|
87
|
-
const results = await queue.execute();
|
88
|
-
if (!results) {
|
89
|
-
throw new Error("Results are undefined");
|
90
|
-
}
|
91
|
-
expect(results).to.not.be.undefined;
|
92
|
-
expect(results).to.have.lengthOf(1);
|
93
|
-
expect(results[0].name).to.equal("action1");
|
94
|
-
expect(results[0].error).to.be.null;
|
95
|
-
expect(results[0].result).to.deep.include({ success: true });
|
96
|
-
});
|
97
|
-
|
98
|
-
it("should handle action execution errors", async () => {
|
99
|
-
const action: QueueItem = {
|
100
|
-
name: "actionWithError",
|
101
|
-
parameters: [],
|
102
|
-
};
|
103
|
-
|
104
|
-
queue.add(action);
|
105
|
-
const results = await queue.execute();
|
106
|
-
if (!results) {
|
107
|
-
throw new Error("Results are undefined");
|
108
|
-
}
|
109
|
-
expect(results).to.not.be.undefined;
|
110
|
-
expect(results).to.have.lengthOf(1);
|
111
|
-
expect(results[0].name).to.equal("actionWithError");
|
112
|
-
expect(results[0].error).to.equal("Test error");
|
113
|
-
expect(results[0].result).to.be.null;
|
114
|
-
});
|
115
|
-
|
116
|
-
it("should respect confirmation requirements", async () => {
|
117
|
-
let confirmationCalled = false;
|
118
|
-
callbacks.onConfirmationRequired = async () => {
|
119
|
-
confirmationCalled = true;
|
120
|
-
return false; // Reject the confirmation
|
121
|
-
};
|
122
|
-
|
123
|
-
queue = new Queue(testActions, callbacks);
|
124
|
-
const action: QueueItem = {
|
125
|
-
name: "action2", // Action requiring confirmation
|
126
|
-
parameters: [],
|
127
|
-
};
|
128
|
-
|
129
|
-
queue.add(action);
|
130
|
-
const results = await queue.execute();
|
131
|
-
if (!results) {
|
132
|
-
throw new Error("Results are undefined");
|
133
|
-
}
|
134
|
-
expect(results).to.not.be.undefined;
|
135
|
-
expect(confirmationCalled).to.be.true;
|
136
|
-
expect(results[0].cancelled).to.be.true;
|
137
|
-
expect(results[0].error).to.equal("Action cancelled by user");
|
138
|
-
});
|
139
|
-
});
|
140
|
-
|
141
|
-
describe("Parameter Handling", () => {
|
142
|
-
it("should correctly format simple parameters", async () => {
|
143
|
-
const action: QueueItem = {
|
144
|
-
name: "action1",
|
145
|
-
parameters: [
|
146
|
-
{ name: "param1", value: "value1" },
|
147
|
-
{ name: "param2", value: "value2" },
|
148
|
-
],
|
149
|
-
};
|
150
|
-
|
151
|
-
queue.add(action);
|
152
|
-
const results = await queue.execute();
|
153
|
-
if (!results) {
|
154
|
-
throw new Error("Results are undefined");
|
155
|
-
}
|
156
|
-
expect(results).to.not.be.undefined;
|
157
|
-
expect(results[0].parameters).to.deep.equal({
|
158
|
-
param1: "value1",
|
159
|
-
param2: "value2",
|
160
|
-
});
|
161
|
-
});
|
162
|
-
|
163
|
-
it("should handle JSON stringified parameters", async () => {
|
164
|
-
const action: QueueItem = {
|
165
|
-
name: "action1",
|
166
|
-
parameters: [
|
167
|
-
{
|
168
|
-
name: "jsonParam",
|
169
|
-
value: JSON.stringify({ name: "test", value: "value" }),
|
170
|
-
},
|
171
|
-
],
|
172
|
-
};
|
173
|
-
|
174
|
-
queue.add(action);
|
175
|
-
const results = await queue.execute();
|
176
|
-
if (!results) {
|
177
|
-
throw new Error("Results are undefined");
|
178
|
-
}
|
179
|
-
expect(results).to.not.be.undefined;
|
180
|
-
expect(results[0].parameters).to.deep.equal({
|
181
|
-
test: "value",
|
182
|
-
});
|
183
|
-
});
|
184
|
-
});
|
185
|
-
|
186
|
-
describe("Queue Processing State", () => {
|
187
|
-
it("should prevent concurrent queue processing", async () => {
|
188
|
-
const action: QueueItem = {
|
189
|
-
name: "action1",
|
190
|
-
parameters: [],
|
191
|
-
};
|
192
|
-
|
193
|
-
queue.add(action);
|
194
|
-
|
195
|
-
// Start first execution
|
196
|
-
const firstExecution = queue.execute();
|
197
|
-
// Try to execute again while first execution is running
|
198
|
-
const secondExecution = queue.execute();
|
199
|
-
|
200
|
-
const [firstResults, secondResults] = await Promise.all([
|
201
|
-
firstExecution,
|
202
|
-
secondExecution,
|
203
|
-
]);
|
204
|
-
|
205
|
-
expect(firstResults).to.not.be.undefined;
|
206
|
-
expect(firstResults).to.have.lengthOf(1);
|
207
|
-
expect(secondResults).to.be.undefined;
|
208
|
-
});
|
209
|
-
|
210
|
-
it("should reset processing state after completion", async () => {
|
211
|
-
const action: QueueItem = {
|
212
|
-
name: "action1",
|
213
|
-
parameters: [],
|
214
|
-
};
|
215
|
-
|
216
|
-
queue.add(action);
|
217
|
-
const results = await queue.execute();
|
218
|
-
|
219
|
-
if (!results) {
|
220
|
-
throw new Error("Results are undefined");
|
221
|
-
}
|
222
|
-
expect(results).to.have.lengthOf(1);
|
223
|
-
|
224
|
-
// Verify that isProcessing is reset
|
225
|
-
expect(queue["isProcessing"]).to.be.false;
|
226
|
-
|
227
|
-
// Clear both queue and results before adding new action
|
228
|
-
queue["queue"] = [];
|
229
|
-
queue["results"] = [];
|
230
|
-
|
231
|
-
// Should be able to execute again
|
232
|
-
queue.add(action);
|
233
|
-
const secondResults = await queue.execute();
|
234
|
-
|
235
|
-
if (!secondResults) {
|
236
|
-
throw new Error("Second results are undefined");
|
237
|
-
}
|
238
|
-
expect(secondResults).to.have.lengthOf(1);
|
239
|
-
});
|
240
|
-
});
|
241
|
-
|
242
|
-
describe("Callback Handling", () => {
|
243
|
-
it("should trigger all callbacks in correct order", async () => {
|
244
|
-
const callbackOrder: string[] = [];
|
245
|
-
|
246
|
-
callbacks = {
|
247
|
-
onActionStart: () => callbackOrder.push("start"),
|
248
|
-
onActionComplete: () => callbackOrder.push("complete"),
|
249
|
-
onQueueComplete: () => callbackOrder.push("queueComplete"),
|
250
|
-
};
|
251
|
-
|
252
|
-
queue = new Queue(testActions, callbacks);
|
253
|
-
const action: QueueItem = {
|
254
|
-
name: "action1",
|
255
|
-
parameters: [],
|
256
|
-
};
|
257
|
-
|
258
|
-
queue.add(action);
|
259
|
-
await queue.execute();
|
260
|
-
|
261
|
-
expect(callbackOrder).to.deep.equal([
|
262
|
-
"start",
|
263
|
-
"complete",
|
264
|
-
"queueComplete",
|
265
|
-
]);
|
266
|
-
});
|
267
|
-
|
268
|
-
it("should handle missing callbacks gracefully", async () => {
|
269
|
-
queue = new Queue(testActions, {}); // No callbacks provided
|
270
|
-
const action: QueueItem = {
|
271
|
-
name: "action1",
|
272
|
-
parameters: [],
|
273
|
-
};
|
274
|
-
|
275
|
-
queue.add(action);
|
276
|
-
const results = await queue.execute();
|
277
|
-
|
278
|
-
if (!results) {
|
279
|
-
throw new Error("Results are undefined");
|
280
|
-
}
|
281
|
-
expect(results).to.not.be.undefined;
|
282
|
-
expect(results).to.have.lengthOf(1);
|
283
|
-
expect(results[0].error).to.be.null;
|
284
|
-
});
|
285
|
-
});
|
286
|
-
});
|