@ai.ntellect/core 0.5.0 → 0.6.1
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 -1
- package/README.md +311 -272
- package/create-llm-to-select-multiple-graph copy.ts +243 -0
- package/create-llm-to-select-multiple-graph.ts +148 -0
- package/dist/graph/controller.js +63 -0
- package/dist/graph/engine.js +563 -0
- package/dist/index.js +6 -6
- package/dist/memory/adapters/meilisearch/index.js +249 -0
- package/dist/memory/adapters/redis/index.js +96 -0
- package/dist/memory/index.js +9 -0
- package/dist/services/agenda.js +115 -0
- package/dist/services/embedding.js +40 -0
- package/dist/services/queue.js +99 -103
- package/dist/test/graph/controller.test.js +170 -0
- package/dist/test/graph/engine.test.js +465 -0
- package/dist/test/memory/adapters/meilisearch.test.js +250 -0
- package/dist/test/memory/adapters/redis.test.js +143 -0
- package/dist/test/memory/base.test.js +209 -0
- package/dist/test/services/agenda.test.js +230 -0
- package/dist/test/services/queue.test.js +258 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/generate-object.js +32 -11
- package/dist/utils/inject-actions.js +2 -2
- package/dist/utils/queue-item-transformer.js +2 -2
- package/dist/utils/state-manager.js +20 -0
- package/graph/controller.ts +64 -0
- package/graph/engine.ts +790 -0
- package/index copy.ts +81 -0
- package/index.ts +7 -7
- package/interfaces/index.ts +119 -0
- package/memory/adapters/meilisearch/index.ts +286 -0
- package/memory/adapters/redis/index.ts +103 -0
- package/memory/index.ts +22 -0
- package/package.json +7 -2
- package/services/agenda.ts +48 -43
- package/services/embedding.ts +26 -0
- package/services/queue.ts +2 -29
- package/test/.env.test +4 -0
- package/test/graph/controller.test.ts +186 -0
- package/test/graph/engine.test.ts +546 -0
- package/test/memory/adapters/meilisearch.test.ts +297 -0
- package/test/memory/adapters/redis.test.ts +160 -0
- package/test/memory/base.test.ts +229 -0
- package/test/services/agenda.test.ts +280 -0
- package/test/services/queue.test.ts +286 -44
- package/tsconfig.json +10 -10
- package/types/index.ts +278 -0
- package/utils/queue-item-transformer.ts +8 -11
- package/utils/setup-graphs.ts +45 -0
- package/utils/stringifiy-zod-schema.ts +45 -0
- package/.nvmrc +0 -1
- package/README.FR.md +0 -916
- package/agent/index.ts +0 -151
- package/agent/workflow/conditions.ts +0 -16
- package/agent/workflow/handlers/interpreter.handler.ts +0 -48
- package/agent/workflow/handlers/memory.handler.ts +0 -106
- package/agent/workflow/handlers/orchestrator.handler.ts +0 -23
- package/agent/workflow/handlers/queue.handler.ts +0 -34
- package/agent/workflow/handlers/scheduler.handler.ts +0 -61
- package/agent/workflow/index.ts +0 -62
- package/dist/agent/index.d.ts +0 -38
- package/dist/agent/index.js +0 -143
- package/dist/agent/tools/get-rss.d.ts +0 -16
- package/dist/agent/tools/get-rss.js +0 -62
- package/dist/bull.d.ts +0 -1
- package/dist/bull.js +0 -9
- package/dist/examples/index.d.ts +0 -2
- package/dist/examples/index.js +0 -89
- package/dist/index.d.ts +0 -7
- package/dist/llm/interpreter/context.d.ts +0 -15
- package/dist/llm/interpreter/context.js +0 -89
- package/dist/llm/interpreter/index.d.ts +0 -21
- package/dist/llm/interpreter/index.js +0 -87
- package/dist/llm/memory-manager/context.d.ts +0 -2
- package/dist/llm/memory-manager/context.js +0 -22
- package/dist/llm/memory-manager/index.d.ts +0 -17
- package/dist/llm/memory-manager/index.js +0 -107
- package/dist/llm/orchestrator/context.d.ts +0 -2
- package/dist/llm/orchestrator/context.js +0 -23
- package/dist/llm/orchestrator/index.d.ts +0 -44
- package/dist/llm/orchestrator/index.js +0 -139
- package/dist/llm/orchestrator/types.d.ts +0 -12
- package/dist/memory/cache.d.ts +0 -22
- package/dist/memory/cache.js +0 -165
- package/dist/memory/persistent.d.ts +0 -57
- package/dist/memory/persistent.js +0 -189
- package/dist/services/queue.d.ts +0 -13
- package/dist/services/redis-cache.d.ts +0 -37
- package/dist/services/redis-cache.js +0 -93
- package/dist/services/scheduler.d.ts +0 -40
- package/dist/services/scheduler.js +0 -99
- package/dist/services/telegram-monitor.d.ts +0 -0
- package/dist/services/telegram-monitor.js +0 -118
- package/dist/t.d.ts +0 -46
- package/dist/t.js +0 -102
- package/dist/test.d.ts +0 -0
- package/dist/test.js +0 -438
- package/dist/types.d.ts +0 -258
- package/dist/types.js +0 -22
- package/dist/utils/generate-object.d.ts +0 -12
- package/dist/utils/header-builder.d.ts +0 -11
- package/dist/utils/inject-actions.d.ts +0 -2
- package/dist/utils/queue-item-transformer.d.ts +0 -7
- package/dist/utils/sanitize-results.d.ts +0 -17
- package/dist/utils/schema-generator.d.ts +0 -16
- package/examples/actions/get-rss.ts +0 -71
- package/examples/index.ts +0 -98
- package/index.html +0 -42
- package/llm/dynamic-condition/example.ts +0 -36
- package/llm/dynamic-condition/index.ts +0 -108
- package/llm/interpreter/context.ts +0 -94
- package/llm/interpreter/index.ts +0 -140
- package/llm/memory-manager/context.ts +0 -19
- package/llm/memory-manager/index.ts +0 -115
- package/llm/orchestrator/context.ts +0 -19
- package/llm/orchestrator/index.ts +0 -192
- package/llm/orchestrator/types.ts +0 -14
- package/memory/cache.ts +0 -221
- package/memory/persistent.ts +0 -265
- package/script.js +0 -167
- package/services/cache.ts +0 -298
- package/services/telegram-monitor.ts +0 -138
- package/services/workflow.ts +0 -491
- package/t.py +0 -79
- package/t.ts +0 -25
- package/test/llm/orchestrator.test.ts +0 -47
- package/test/llm/synthesizer.test.ts +0 -31
- package/types.ts +0 -367
- package/utils/schema-generator.ts +0 -73
- package/utils/state-manager.ts +0 -25
- /package/dist/{llm/orchestrator/types.js → interfaces/index.js} +0 -0
@@ -0,0 +1,280 @@
|
|
1
|
+
// import { expect } from "chai";
|
2
|
+
// import sinon from "sinon";
|
3
|
+
// import { Agenda } from "../../services/agenda";
|
4
|
+
|
5
|
+
// before(function () {
|
6
|
+
// this.timeout(10000);
|
7
|
+
// });
|
8
|
+
|
9
|
+
// describe("Agenda Service", () => {
|
10
|
+
// let agenda: Agenda;
|
11
|
+
// const scheduledIds: string[] = []; // Track all scheduled request IDs
|
12
|
+
|
13
|
+
// beforeEach(() => {
|
14
|
+
// agenda = new Agenda();
|
15
|
+
// });
|
16
|
+
|
17
|
+
// afterEach(async () => {
|
18
|
+
// // Cancel all scheduled requests by their IDs
|
19
|
+
// scheduledIds.forEach((id) => agenda.cancelScheduledRequest(id));
|
20
|
+
// scheduledIds.length = 0; // Clear the array
|
21
|
+
|
22
|
+
// // Ensure all tasks are stopped
|
23
|
+
// await agenda.stop();
|
24
|
+
|
25
|
+
// // Vider la file d'attente
|
26
|
+
// await agenda.cancel({});
|
27
|
+
|
28
|
+
// // Attendre un peu pour s'assurer que tout est arrêté
|
29
|
+
// await new Promise((resolve) => setTimeout(resolve, 100));
|
30
|
+
// });
|
31
|
+
|
32
|
+
// describe("Request Scheduling", () => {
|
33
|
+
// it("should schedule a new request and return an id", async () => {
|
34
|
+
// const request = {
|
35
|
+
// originalRequest: "test request",
|
36
|
+
// cronExpression: "0 0 * * *",
|
37
|
+
// };
|
38
|
+
|
39
|
+
// const id = await agenda.scheduleRequest(request);
|
40
|
+
// scheduledIds.push(id); // Track the ID
|
41
|
+
|
42
|
+
// expect(id).to.be.a("string");
|
43
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(1);
|
44
|
+
|
45
|
+
// const scheduledRequest = agenda.getScheduledRequests()[0];
|
46
|
+
// expect(scheduledRequest.originalRequest).to.equal(
|
47
|
+
// request.originalRequest
|
48
|
+
// );
|
49
|
+
// expect(scheduledRequest.cronExpression).to.equal(request.cronExpression);
|
50
|
+
// expect(scheduledRequest.isRecurring).to.be.false;
|
51
|
+
|
52
|
+
// agenda.cancelScheduledRequest(id);
|
53
|
+
// });
|
54
|
+
|
55
|
+
// it("should execute callbacks when scheduling and executing", async function () {
|
56
|
+
// this.timeout(5000);
|
57
|
+
|
58
|
+
// const onScheduledSpy = sinon.spy();
|
59
|
+
// const onExecutedSpy = sinon.spy();
|
60
|
+
|
61
|
+
// const request = {
|
62
|
+
// originalRequest: "test request",
|
63
|
+
// cronExpression: `${(new Date().getSeconds() + 1) % 60} * * * * *`,
|
64
|
+
// };
|
65
|
+
|
66
|
+
// const id = await agenda.scheduleRequest(request, {
|
67
|
+
// onScheduled: onScheduledSpy,
|
68
|
+
// onExecuted: onExecutedSpy,
|
69
|
+
// });
|
70
|
+
// scheduledIds.push(id); // Track the ID
|
71
|
+
|
72
|
+
// expect(onScheduledSpy.calledOnce).to.be.true;
|
73
|
+
|
74
|
+
// await new Promise<void>((resolve, reject) => {
|
75
|
+
// const timeout = setTimeout(() => {
|
76
|
+
// reject(new Error("Callback execution timeout"));
|
77
|
+
// }, 4000);
|
78
|
+
|
79
|
+
// const checkExecution = () => {
|
80
|
+
// if (onExecutedSpy.calledOnce) {
|
81
|
+
// clearTimeout(timeout);
|
82
|
+
// agenda.cancelScheduledRequest(id);
|
83
|
+
// resolve();
|
84
|
+
// return;
|
85
|
+
// }
|
86
|
+
// setTimeout(checkExecution, 100);
|
87
|
+
// };
|
88
|
+
// checkExecution();
|
89
|
+
// });
|
90
|
+
|
91
|
+
// expect(onExecutedSpy.calledOnce).to.be.true;
|
92
|
+
// });
|
93
|
+
// });
|
94
|
+
|
95
|
+
// describe("Request Management", () => {
|
96
|
+
// it("should cancel a scheduled request", async () => {
|
97
|
+
// const request = {
|
98
|
+
// originalRequest: "test request",
|
99
|
+
// cronExpression: "*/1 * * * *",
|
100
|
+
// };
|
101
|
+
|
102
|
+
// const id = await agenda.scheduleRequest(request);
|
103
|
+
// scheduledIds.push(id); // Track the ID
|
104
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(1);
|
105
|
+
|
106
|
+
// const cancelled = agenda.cancelScheduledRequest(id);
|
107
|
+
// expect(cancelled).to.be.true;
|
108
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(0);
|
109
|
+
// });
|
110
|
+
|
111
|
+
// it("should return false when cancelling non-existent request", () => {
|
112
|
+
// const cancelled = agenda.cancelScheduledRequest("non-existent-id");
|
113
|
+
// expect(cancelled).to.be.false;
|
114
|
+
// });
|
115
|
+
|
116
|
+
// it("should get all scheduled requests", async () => {
|
117
|
+
// const requests = [
|
118
|
+
// {
|
119
|
+
// originalRequest: "request 1",
|
120
|
+
// cronExpression: "*/1 * * * *",
|
121
|
+
// },
|
122
|
+
// {
|
123
|
+
// originalRequest: "request 2",
|
124
|
+
// cronExpression: "*/5 * * * *",
|
125
|
+
// },
|
126
|
+
// ];
|
127
|
+
|
128
|
+
// for (const request of requests) {
|
129
|
+
// const id = await agenda.scheduleRequest(request);
|
130
|
+
// scheduledIds.push(id); // Track the ID
|
131
|
+
// }
|
132
|
+
|
133
|
+
// const scheduledRequests = agenda.getScheduledRequests();
|
134
|
+
// expect(scheduledRequests).to.have.lengthOf(2);
|
135
|
+
// expect(scheduledRequests[0].originalRequest).to.equal("request 1");
|
136
|
+
// expect(scheduledRequests[1].originalRequest).to.equal("request 2");
|
137
|
+
// });
|
138
|
+
// });
|
139
|
+
|
140
|
+
// describe("Global Management", () => {
|
141
|
+
// it("should stop all scheduled requests", async () => {
|
142
|
+
// const requests = [
|
143
|
+
// {
|
144
|
+
// originalRequest: "request 1",
|
145
|
+
// cronExpression: "*/1 * * * *",
|
146
|
+
// },
|
147
|
+
// {
|
148
|
+
// originalRequest: "request 2",
|
149
|
+
// cronExpression: "*/5 * * * *",
|
150
|
+
// },
|
151
|
+
// ];
|
152
|
+
|
153
|
+
// for (const request of requests) {
|
154
|
+
// await agenda.scheduleRequest(request);
|
155
|
+
// }
|
156
|
+
|
157
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(2);
|
158
|
+
|
159
|
+
// agenda.stopAll();
|
160
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(0);
|
161
|
+
// });
|
162
|
+
// });
|
163
|
+
|
164
|
+
// describe("Error Handling", () => {
|
165
|
+
// it("should handle execution errors gracefully", async () => {
|
166
|
+
// const consoleSpy = sinon.spy(console, "error");
|
167
|
+
|
168
|
+
// const request = {
|
169
|
+
// originalRequest: "error request",
|
170
|
+
// cronExpression: "0 0 * * *",
|
171
|
+
// };
|
172
|
+
|
173
|
+
// const id = await agenda.scheduleRequest(request);
|
174
|
+
|
175
|
+
// // Wait for execution
|
176
|
+
// await new Promise((resolve) => setTimeout(resolve, 1100));
|
177
|
+
|
178
|
+
// expect(consoleSpy.called).to.be.false;
|
179
|
+
|
180
|
+
// agenda.cancelScheduledRequest(id);
|
181
|
+
// consoleSpy.restore();
|
182
|
+
// });
|
183
|
+
// });
|
184
|
+
|
185
|
+
// describe("Request Execution", () => {
|
186
|
+
// it("should execute non-recurring requests only once", async function () {
|
187
|
+
// this.timeout(5000);
|
188
|
+
// const onExecutedSpy = sinon.spy();
|
189
|
+
|
190
|
+
// const request = {
|
191
|
+
// originalRequest: "single execution",
|
192
|
+
// cronExpression: `${new Date().getSeconds() + 1} * * * * *`,
|
193
|
+
// };
|
194
|
+
|
195
|
+
// const id = await agenda.scheduleRequest(request, {
|
196
|
+
// onExecuted: onExecutedSpy,
|
197
|
+
// });
|
198
|
+
|
199
|
+
// try {
|
200
|
+
// await new Promise<void>((resolve, reject) => {
|
201
|
+
// const timeout = setTimeout(
|
202
|
+
// () => reject(new Error("Test timeout")),
|
203
|
+
// 4000
|
204
|
+
// );
|
205
|
+
// const checkExecution = () => {
|
206
|
+
// if (onExecutedSpy.calledOnce) {
|
207
|
+
// clearTimeout(timeout);
|
208
|
+
// resolve();
|
209
|
+
// return;
|
210
|
+
// }
|
211
|
+
// setTimeout(checkExecution, 100);
|
212
|
+
// };
|
213
|
+
// checkExecution();
|
214
|
+
// });
|
215
|
+
// } finally {
|
216
|
+
// agenda.cancelScheduledRequest(id);
|
217
|
+
// }
|
218
|
+
|
219
|
+
// expect(onExecutedSpy.calledOnce).to.be.true;
|
220
|
+
// expect(agenda.getScheduledRequests()).to.have.lengthOf(0);
|
221
|
+
// });
|
222
|
+
|
223
|
+
// it("should log execution status", async function () {
|
224
|
+
// this.timeout(10000);
|
225
|
+
// const consoleLogSpy = sinon.spy(console, "log");
|
226
|
+
|
227
|
+
// const request = {
|
228
|
+
// originalRequest: "test request",
|
229
|
+
// cronExpression: `${new Date().getSeconds() + 1} * * * * *`,
|
230
|
+
// };
|
231
|
+
|
232
|
+
// const id = await agenda.scheduleRequest(request);
|
233
|
+
|
234
|
+
// await new Promise<void>((resolve) => {
|
235
|
+
// const checkExecution = () => {
|
236
|
+
// if (
|
237
|
+
// consoleLogSpy.calledWith(`🔄 Executing scheduled request: ${id}`) &&
|
238
|
+
// consoleLogSpy.calledWith(
|
239
|
+
// `✅ Scheduled request executed successfully: ${id}`
|
240
|
+
// )
|
241
|
+
// ) {
|
242
|
+
// agenda.cancelScheduledRequest(id);
|
243
|
+
// resolve();
|
244
|
+
// return;
|
245
|
+
// }
|
246
|
+
// setTimeout(checkExecution, 100);
|
247
|
+
// };
|
248
|
+
// checkExecution();
|
249
|
+
// });
|
250
|
+
|
251
|
+
// expect(consoleLogSpy.calledWith(`🔄 Executing scheduled request: ${id}`))
|
252
|
+
// .to.be.true;
|
253
|
+
// expect(
|
254
|
+
// consoleLogSpy.calledWith(
|
255
|
+
// `✅ Scheduled request executed successfully: ${id}`
|
256
|
+
// )
|
257
|
+
// ).to.be.true;
|
258
|
+
|
259
|
+
// consoleLogSpy.restore();
|
260
|
+
// });
|
261
|
+
// });
|
262
|
+
// });
|
263
|
+
|
264
|
+
// // Déplacer la variable agenda en dehors du describe pour la rendre accessible
|
265
|
+
// let globalAgenda: Agenda;
|
266
|
+
// before(() => {
|
267
|
+
// globalAgenda = new Agenda();
|
268
|
+
// });
|
269
|
+
|
270
|
+
// after(async () => {
|
271
|
+
// if (globalAgenda) {
|
272
|
+
// globalAgenda.stopAll();
|
273
|
+
// await new Promise((resolve) => setTimeout(resolve, 100));
|
274
|
+
// }
|
275
|
+
|
276
|
+
// // Nettoyage final
|
277
|
+
// await globalAgenda.stop();
|
278
|
+
// await globalAgenda.cancel({});
|
279
|
+
// await new Promise((resolve) => setTimeout(resolve, 100));
|
280
|
+
// });
|
@@ -1,44 +1,286 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
//
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
//
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
+
});
|
package/tsconfig.json
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
{
|
2
2
|
"compilerOptions": {
|
3
|
-
"target": "
|
4
|
-
"module": "
|
5
|
-
"moduleResolution": "node",
|
6
|
-
"lib": ["ES2020"],
|
7
|
-
"declaration": true,
|
8
|
-
"outDir": "./dist",
|
9
|
-
"strict": true,
|
3
|
+
"target": "es2016",
|
4
|
+
"module": "commonjs",
|
10
5
|
"esModuleInterop": true,
|
11
|
-
"skipLibCheck": true,
|
12
6
|
"forceConsistentCasingInFileNames": true,
|
13
|
-
"
|
7
|
+
"strict": true,
|
8
|
+
"skipLibCheck": true,
|
9
|
+
"baseUrl": ".",
|
10
|
+
"paths": {
|
11
|
+
"@/*": ["./*"]
|
12
|
+
},
|
13
|
+
"outDir": "./dist"
|
14
14
|
},
|
15
|
-
"exclude": ["node_modules", "
|
15
|
+
"exclude": ["node_modules", "examples", "test"]
|
16
16
|
}
|