@ai.ntellect/core 0.6.17 → 0.6.20

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 (79) hide show
  1. package/.mocharc.json +1 -2
  2. package/README.md +123 -178
  3. package/dist/graph/controller.js +29 -6
  4. package/dist/graph/index.js +302 -62
  5. package/dist/index.js +21 -6
  6. package/dist/interfaces/index.js +15 -0
  7. package/dist/modules/agenda/adapters/node-cron/index.js +29 -0
  8. package/dist/modules/agenda/index.js +140 -0
  9. package/dist/{services/embedding.js → modules/embedding/adapters/ai/index.js} +24 -7
  10. package/dist/modules/embedding/index.js +59 -0
  11. package/dist/modules/memory/adapters/in-memory/index.js +210 -0
  12. package/dist/{memory → modules/memory}/adapters/meilisearch/index.js +97 -2
  13. package/dist/{memory → modules/memory}/adapters/redis/index.js +77 -15
  14. package/dist/modules/memory/index.js +103 -0
  15. package/dist/utils/{stringifiy-zod-schema.js → generate-action-schema.js} +5 -5
  16. package/graph/controller.ts +46 -35
  17. package/graph/index.ts +534 -102
  18. package/graph.ts +74 -0
  19. package/index.ts +25 -7
  20. package/interfaces/index.ts +353 -27
  21. package/modules/agenda/adapters/node-cron/index.ts +25 -0
  22. package/modules/agenda/index.ts +159 -0
  23. package/modules/embedding/adapters/ai/index.ts +42 -0
  24. package/modules/embedding/index.ts +45 -0
  25. package/modules/memory/adapters/in-memory/index.ts +203 -0
  26. package/{memory → modules/memory}/adapters/meilisearch/index.ts +114 -12
  27. package/modules/memory/adapters/redis/index.ts +164 -0
  28. package/modules/memory/index.ts +93 -0
  29. package/package.json +3 -1
  30. package/test/graph/index.test.ts +578 -0
  31. package/test/modules/agenda/node-cron.test.ts +286 -0
  32. package/test/modules/embedding/ai.test.ts +78 -0
  33. package/test/modules/memory/adapters/in-memory.test.ts +153 -0
  34. package/test/{memory → modules/memory}/adapters/meilisearch.test.ts +79 -75
  35. package/test/modules/memory/adapters/redis.test.ts +169 -0
  36. package/test/modules/memory/base.test.ts +230 -0
  37. package/test/services/agenda.test.ts +279 -280
  38. package/types/index.ts +93 -202
  39. package/utils/{stringifiy-zod-schema.ts → generate-action-schema.ts} +3 -3
  40. package/app/README.md +0 -36
  41. package/app/app/favicon.ico +0 -0
  42. package/app/app/globals.css +0 -21
  43. package/app/app/gun.ts +0 -0
  44. package/app/app/layout.tsx +0 -18
  45. package/app/app/page.tsx +0 -321
  46. package/app/eslint.config.mjs +0 -16
  47. package/app/next.config.ts +0 -7
  48. package/app/package-lock.json +0 -5912
  49. package/app/package.json +0 -31
  50. package/app/pnpm-lock.yaml +0 -4031
  51. package/app/postcss.config.mjs +0 -8
  52. package/app/public/file.svg +0 -1
  53. package/app/public/globe.svg +0 -1
  54. package/app/public/next.svg +0 -1
  55. package/app/public/vercel.svg +0 -1
  56. package/app/public/window.svg +0 -1
  57. package/app/tailwind.config.ts +0 -18
  58. package/app/tsconfig.json +0 -27
  59. package/dist/memory/index.js +0 -9
  60. package/dist/services/agenda.js +0 -115
  61. package/dist/services/queue.js +0 -142
  62. package/dist/utils/experimental-graph-rag.js +0 -152
  63. package/dist/utils/generate-object.js +0 -111
  64. package/dist/utils/inject-actions.js +0 -16
  65. package/dist/utils/queue-item-transformer.js +0 -24
  66. package/dist/utils/sanitize-results.js +0 -60
  67. package/memory/adapters/redis/index.ts +0 -103
  68. package/memory/index.ts +0 -22
  69. package/services/agenda.ts +0 -118
  70. package/services/embedding.ts +0 -26
  71. package/services/queue.ts +0 -145
  72. package/test/memory/adapters/redis.test.ts +0 -159
  73. package/test/memory/base.test.ts +0 -225
  74. package/test/services/queue.test.ts +0 -286
  75. package/utils/experimental-graph-rag.ts +0 -170
  76. package/utils/generate-object.ts +0 -117
  77. package/utils/inject-actions.ts +0 -19
  78. package/utils/queue-item-transformer.ts +0 -38
  79. package/utils/sanitize-results.ts +0 -66
package/graph.ts ADDED
@@ -0,0 +1,74 @@
1
+ import { Node } from "types";
2
+ import { z } from "zod";
3
+ import { GraphController, GraphFlow } from "./index";
4
+
5
+ // 🏗 Définition des schémas pour chaque graphe
6
+ const schemaA = z.object({
7
+ input: z.string(),
8
+ result: z.string().optional(),
9
+ });
10
+
11
+ const schemaB = z.object({
12
+ number: z.number(),
13
+ result: z.number().optional(),
14
+ });
15
+
16
+ // 🔹 **Graph A** : Convertit une chaîne en majuscules
17
+ const processText: Node<typeof schemaA> = {
18
+ name: "processText",
19
+ execute: async (context) => {
20
+ context.result = context.input.toUpperCase();
21
+ console.log("📢 Graphe A : Texte transformé →", context.result);
22
+ },
23
+ };
24
+
25
+ // 🔹 **Graph B** : Multiplie un nombre par 10
26
+ const multiplyNumber: Node<typeof schemaB> = {
27
+ name: "multiplyNumber",
28
+ execute: async (context) => {
29
+ context.result = context.number * 10;
30
+ console.log("🔢 Graphe B : Nombre multiplié →", context.result);
31
+ },
32
+ };
33
+
34
+ // 🔗 **Création des graphes**
35
+ const graphA = new GraphFlow("GraphA", {
36
+ name: "GraphA",
37
+ nodes: [processText],
38
+ context: { input: "" },
39
+ schema: schemaA,
40
+ });
41
+
42
+ const graphB = new GraphFlow("GraphB", {
43
+ name: "GraphB",
44
+ nodes: [multiplyNumber],
45
+ context: { number: 0 },
46
+ schema: schemaB,
47
+ });
48
+
49
+ (async () => {
50
+ try {
51
+ console.log("🚀 **Exécution Séquentielle** des graphes...");
52
+ const sequentialResults = await GraphController.executeSequential(
53
+ [graphA, graphB],
54
+ ["processText", "multiplyNumber"],
55
+ [{ input: "hello world" }, { number: 5 }]
56
+ );
57
+
58
+ console.log("🟢 **Résultats Séquentiels :**", sequentialResults);
59
+
60
+ console.log(
61
+ "\n⚡ **Exécution Parallèle** avec limitation de concurrence..."
62
+ );
63
+ const parallelResults = await GraphController.executeParallel(
64
+ [graphA, graphB],
65
+ ["processText", "multiplyNumber"],
66
+ 1, // ⚠️ Limite de concurrence (1 à la fois)
67
+ [{ input: "parallel execution" }, { number: 7 }]
68
+ );
69
+
70
+ console.log("🟢 **Résultats Parallèles :**", parallelResults);
71
+ } catch (error) {
72
+ console.error("❌ Erreur lors de l’exécution :", error);
73
+ }
74
+ })();
package/index.ts CHANGED
@@ -1,11 +1,29 @@
1
- export * from "./graph";
1
+ /**
2
+ * @module @ai.ntellect/core
3
+ * @description Core module with workflow functionality, providing graph management,
4
+ * memory storage, agenda scheduling, and embedding capabilities.
5
+ *
6
+ * This module exports various components:
7
+ * - Graph management and controller
8
+ * - Memory storage adapters (Meilisearch, Redis)
9
+ * - Agenda scheduling with node-cron adapter
10
+ * - Embedding functionality with AI adapter
11
+ * - Utility functions for action schema generation and header building
12
+ */
13
+
2
14
  export * from "./graph/controller";
3
- export * from "./memory";
4
- export * from "./memory/adapters/meilisearch";
5
- export * from "./memory/adapters/redis";
15
+ export * from "./graph/index";
16
+ export * from "./modules/memory";
17
+ export * from "./modules/memory/adapters/meilisearch";
18
+ export * from "./modules/memory/adapters/redis";
6
19
 
7
20
  export * from "./interfaces";
8
- export * from "./services/agenda";
9
- export * from "./services/embedding";
21
+ export * from "./modules/agenda";
22
+ export * from "./modules/agenda/adapters/node-cron";
23
+ export * from "./modules/embedding";
24
+ export * from "./modules/embedding/adapters/ai";
25
+
10
26
  export * from "./types";
11
- export * from "./utils/stringifiy-zod-schema";
27
+
28
+ export * from "./utils/generate-action-schema";
29
+ export * from "./utils/header-builder";
@@ -1,36 +1,11 @@
1
- import { BaseMemoryType, SharedState } from "../types";
2
-
3
- /* ======================== PERSISTENCE ======================== */
4
-
5
- /**
6
- * Interface for persisting graph execution state.
7
- */
8
- export interface Persistence<T> {
9
- saveState(
10
- graphName: string,
11
- state: SharedState<T>,
12
- currentNode: string
13
- ): Promise<void>;
14
- loadState(
15
- graphName: string
16
- ): Promise<{ state: SharedState<T>; currentNode: string } | null>;
17
- }
18
-
19
- /* ======================== REAL-TIME NOTIFICATIONS ======================== */
20
-
21
- /**
22
- * Interface for real-time notifications.
23
- */
24
- export interface RealTimeNotifier {
25
- notify(event: string, data: any): void;
26
- }
1
+ import { BaseMemoryType, CreateMemoryInput, ScheduledRequest } from "../types";
27
2
 
28
3
  /* ======================== EMBEDDING SERVICE ======================== */
29
4
 
30
5
  /**
31
6
  * Interface for an embedding service that processes text into vector representations.
32
7
  */
33
- export interface EmbeddingService {
8
+ export interface EmbeddingModule {
34
9
  /**
35
10
  * Generates an embedding for a single text.
36
11
  * @param {string} text - The input text to embed.
@@ -116,3 +91,354 @@ export interface BaseMemoryService {
116
91
  */
117
92
  clearAllMemories(): Promise<void>;
118
93
  }
94
+
95
+ /**
96
+ * Extended interface for memory service operations
97
+ * @interface
98
+ */
99
+ export interface IMemoryService {
100
+ /**
101
+ * Initializes the memory service
102
+ * @returns {Promise<void>}
103
+ */
104
+ init(): Promise<void>;
105
+
106
+ /**
107
+ * Creates a new memory entry with optional embedding
108
+ * @param {CreateMemoryInput & { embedding?: number[] }} input - Memory data with optional embedding
109
+ * @returns {Promise<BaseMemoryType | undefined>} Created memory or undefined
110
+ */
111
+ createMemory(
112
+ input: CreateMemoryInput & { embedding?: number[] }
113
+ ): Promise<BaseMemoryType | undefined>;
114
+
115
+ /**
116
+ * Retrieves a memory by ID and room ID
117
+ * @param {string} id - Memory identifier
118
+ * @param {string} roomId - Room identifier
119
+ * @returns {Promise<BaseMemoryType | null>} Memory entry or null if not found
120
+ */
121
+ getMemoryById(id: string, roomId: string): Promise<BaseMemoryType | null>;
122
+
123
+ /**
124
+ * Searches for memories based on query and options
125
+ * @param {string} query - Search query
126
+ * @param {Object} options - Search options
127
+ * @returns {Promise<BaseMemoryType[]>} Array of matching memories
128
+ */
129
+ getMemoryByIndex(
130
+ query: string,
131
+ options: { roomId: string; limit?: number }
132
+ ): Promise<BaseMemoryType[]>;
133
+
134
+ /**
135
+ * Retrieves all memories for a specific room
136
+ * @param {string} roomId - Room identifier
137
+ * @returns {Promise<BaseMemoryType[]>} Array of all memories
138
+ */
139
+ getAllMemories(roomId: string): Promise<BaseMemoryType[]>;
140
+
141
+ /**
142
+ * Deletes a specific memory
143
+ * @param {string} id - Memory identifier
144
+ * @param {string} roomId - Room identifier
145
+ * @returns {Promise<void>}
146
+ */
147
+ clearMemoryById(id: string, roomId: string): Promise<void>;
148
+
149
+ /**
150
+ * Clears all memories
151
+ * @returns {Promise<void>}
152
+ */
153
+ clearAllMemories(): Promise<void>;
154
+ }
155
+
156
+ /**
157
+ * Interface for memory adapter implementations
158
+ * @interface
159
+ */
160
+ export interface IMemoryAdapter {
161
+ /**
162
+ * Initializes the memory adapter for a specific room
163
+ * @param {string} roomId - Room identifier
164
+ * @returns {Promise<void>}
165
+ */
166
+ init(roomId?: string): Promise<void>;
167
+
168
+ /**
169
+ * Creates a new memory entry in the adapter
170
+ * @param {CreateMemoryInput & { embedding?: number[] }} input - Memory data with optional embedding
171
+ * @returns {Promise<BaseMemoryType | undefined>} Created memory or undefined
172
+ */
173
+ createMemory(
174
+ input: CreateMemoryInput & { embedding?: number[] }
175
+ ): Promise<BaseMemoryType | undefined>;
176
+
177
+ /**
178
+ * Stores a job in the adapter
179
+ * @param {string} id - Job identifier
180
+ * @param {ICronJob} job - Cron job instance
181
+ * @returns {Promise<void>}
182
+ */
183
+ saveJob?(id: string, job: ICronJob): Promise<void>;
184
+
185
+ /**
186
+ * Stores a scheduled request in the adapter
187
+ * @param {string} id - Request identifier
188
+ * @param {ScheduledRequest} request - Scheduled request data
189
+ * @returns {Promise<void>}
190
+ */
191
+ saveRequest?(id: string, request: ScheduledRequest): Promise<void>;
192
+
193
+ /**
194
+ * Retrieves a job by ID
195
+ * @param {string} id - Job identifier
196
+ * @returns {Promise<ICronJob | undefined>}
197
+ */
198
+ getJob?(id: string): Promise<ICronJob | undefined>;
199
+
200
+ /**
201
+ * Retrieves a scheduled request by ID
202
+ * @param {string} id - Request identifier
203
+ * @returns {Promise<ScheduledRequest | undefined>}
204
+ */
205
+ getRequest?(id: string): Promise<ScheduledRequest | undefined>;
206
+
207
+ /**
208
+ * Deletes a job by ID
209
+ * @param {string} id - Job identifier
210
+ * @returns {Promise<void>}
211
+ */
212
+ deleteJob?(id: string): Promise<void>;
213
+
214
+ /**
215
+ * Deletes a scheduled request by ID
216
+ * @param {string} id - Request identifier
217
+ * @returns {Promise<void>}
218
+ */
219
+ deleteRequest?(id: string): Promise<void>;
220
+
221
+ /**
222
+ * Retrieves all scheduled requests
223
+ * @returns {Promise<ScheduledRequest[]>}
224
+ */
225
+ getAllRequests?(): Promise<ScheduledRequest[]>;
226
+
227
+ /**
228
+ * Retrieves a memory by ID and room ID from the adapter
229
+ * @param {string} id - Memory identifier
230
+ * @param {string} roomId - Room identifier
231
+ * @returns {Promise<BaseMemoryType | null>} Memory entry or null if not found
232
+ */
233
+ getMemoryById(id: string, roomId: string): Promise<BaseMemoryType | null>;
234
+
235
+ /**
236
+ * Searches for memories in the adapter
237
+ * @param {string} query - Search query
238
+ * @param {Object} options - Search options
239
+ * @returns {Promise<BaseMemoryType[]>} Array of matching memories
240
+ */
241
+ getMemoryByIndex(
242
+ query: string,
243
+ options: { roomId: string; limit?: number }
244
+ ): Promise<BaseMemoryType[]>;
245
+
246
+ /**
247
+ * Retrieves all memories for a room from the adapter
248
+ * @param {string} roomId - Room identifier
249
+ * @returns {Promise<BaseMemoryType[]>} Array of all memories
250
+ */
251
+ getAllMemories(roomId: string): Promise<BaseMemoryType[]>;
252
+
253
+ /**
254
+ * Deletes a specific memory from the adapter
255
+ * @param {string} id - Memory identifier
256
+ * @param {string} roomId - Room identifier
257
+ * @returns {Promise<void>}
258
+ */
259
+ clearMemoryById(id: string, roomId: string): Promise<void>;
260
+
261
+ /**
262
+ * Clears all memories from the adapter
263
+ * @returns {Promise<void>}
264
+ */
265
+ clearAllMemories(): Promise<void>;
266
+
267
+ /**
268
+ * Clears all jobs and requests
269
+ * @returns {Promise<void>}
270
+ */
271
+ clear?(): Promise<void>;
272
+ }
273
+
274
+ /**
275
+ * Abstract base class for memory implementations
276
+ * @abstract
277
+ */
278
+ export abstract class BaseMemory implements IMemoryService {
279
+ /**
280
+ * Creates an instance of BaseMemory
281
+ * @param {IMemoryAdapter} adapter - Memory adapter implementation
282
+ */
283
+ constructor(protected readonly adapter: IMemoryAdapter) {}
284
+
285
+ abstract init(): Promise<void>;
286
+ abstract createMemory(
287
+ input: CreateMemoryInput & { embedding?: number[] }
288
+ ): Promise<BaseMemoryType | undefined>;
289
+ abstract getMemoryById(
290
+ id: string,
291
+ roomId: string
292
+ ): Promise<BaseMemoryType | null>;
293
+ abstract getMemoryByIndex(
294
+ query: string,
295
+ options: { roomId: string; limit?: number }
296
+ ): Promise<BaseMemoryType[]>;
297
+ abstract getAllMemories(roomId: string): Promise<BaseMemoryType[]>;
298
+ abstract clearMemoryById(id: string, roomId: string): Promise<void>;
299
+ abstract clearAllMemories(): Promise<void>;
300
+ }
301
+
302
+ /**
303
+ * Interface for event emitter functionality
304
+ * @interface
305
+ */
306
+ export interface IEventEmitter {
307
+ /**
308
+ * Emits an event with optional arguments
309
+ * @param {string} event - Event name
310
+ * @param {...any[]} args - Event arguments
311
+ * @returns {boolean} Whether the event had listeners
312
+ */
313
+ emit(event: string, ...args: any[]): boolean;
314
+
315
+ /**
316
+ * Registers an event listener
317
+ * @param {string} event - Event name
318
+ * @param {Function} listener - Event handler
319
+ */
320
+ on(event: string, listener: (...args: any[]) => void): void;
321
+
322
+ /**
323
+ * Removes all listeners for an event
324
+ * @param {string} [event] - Optional event name
325
+ */
326
+ removeAllListeners(event?: string): void;
327
+
328
+ /**
329
+ * Returns raw listeners for an event
330
+ * @param {string} event - Event name
331
+ * @returns {Function[]} Array of listener functions
332
+ */
333
+ rawListeners(event: string): Function[];
334
+
335
+ /**
336
+ * Registers an event listener that will be called only once
337
+ * @param {string} event - Event name
338
+ * @param {Function} listener - Event handler
339
+ */
340
+ once(event: string, listener: (...args: any[]) => void): void;
341
+ }
342
+
343
+ /**
344
+ * Interface for cron service functionality
345
+ * @interface
346
+ */
347
+ export interface ICronService {
348
+ /**
349
+ * Schedules a job using cron expression
350
+ * @param {string} expression - Cron expression
351
+ * @param {Function} callback - Job callback
352
+ * @returns {ICronJob} Cron job instance
353
+ */
354
+ schedule(expression: string, callback: () => void): ICronJob;
355
+ }
356
+
357
+ /**
358
+ * Interface for cron job control
359
+ * @interface
360
+ */
361
+ export interface ICronJob {
362
+ /**
363
+ * Starts the cron job
364
+ */
365
+ start(): void;
366
+
367
+ /**
368
+ * Stops the cron job
369
+ */
370
+ stop(): void;
371
+ }
372
+
373
+ /**
374
+ * Interface for embedding model operations
375
+ * @interface
376
+ */
377
+ export interface IEmbeddingModel {
378
+ /**
379
+ * Embeds a single text
380
+ * @param {string} text - Text to embed
381
+ * @returns {Promise<number[]>} Vector embedding
382
+ */
383
+ embed(text: string): Promise<number[]>;
384
+
385
+ /**
386
+ * Embeds multiple texts
387
+ * @param {string[]} texts - Array of texts to embed
388
+ * @returns {Promise<number[][]>} Array of vector embeddings
389
+ */
390
+ embedMany(texts: string[]): Promise<number[][]>;
391
+ }
392
+
393
+ /**
394
+ * Interface for similarity calculations
395
+ * @interface
396
+ */
397
+ export interface ISimilarityCalculator {
398
+ /**
399
+ * Calculates similarity between two embeddings
400
+ * @param {number[]} embedding1 - First embedding
401
+ * @param {number[]} embedding2 - Second embedding
402
+ * @returns {number} Similarity score
403
+ */
404
+ calculate(embedding1: number[], embedding2: number[]): number;
405
+ }
406
+
407
+ /**
408
+ * Interface for embedding module operations
409
+ * @interface
410
+ */
411
+ export interface IEmbeddingModule {
412
+ /**
413
+ * Embeds a single text
414
+ * @param {string} text - Text to embed
415
+ * @returns {Promise<number[]>} Vector embedding
416
+ */
417
+ embedText(text: string): Promise<number[]>;
418
+
419
+ /**
420
+ * Embeds multiple texts
421
+ * @param {string[]} texts - Array of texts to embed
422
+ * @returns {Promise<number[][]>} Array of vector embeddings
423
+ */
424
+ embedMany(texts: string[]): Promise<number[][]>;
425
+
426
+ /**
427
+ * Calculates similarity between two embeddings
428
+ * @param {number[]} embedding1 - First embedding
429
+ * @param {number[]} embedding2 - Second embedding
430
+ * @returns {number} Similarity score
431
+ */
432
+ calculateSimilarity(embedding1: number[], embedding2: number[]): number;
433
+ }
434
+
435
+ export interface IJobStorage {
436
+ saveJob(id: string, job: ICronJob): Promise<void>;
437
+ saveRequest(id: string, request: ScheduledRequest): Promise<void>;
438
+ getJob(id: string): Promise<ICronJob | undefined>;
439
+ getRequest(id: string): Promise<ScheduledRequest | undefined>;
440
+ deleteJob(id: string): Promise<void>;
441
+ deleteRequest(id: string): Promise<void>;
442
+ getAllRequests(): Promise<ScheduledRequest[]>;
443
+ clear(): Promise<void>;
444
+ }
@@ -0,0 +1,25 @@
1
+ import cron from "node-cron";
2
+ import { ICronJob, ICronService } from "../../../../interfaces";
3
+
4
+ /**
5
+ * @module NodeCronAdapter
6
+ * @description Adapter implementation for node-cron service.
7
+ * Provides a bridge between the application's scheduling interface and the node-cron library.
8
+ * @implements {ICronService}
9
+ */
10
+ export class NodeCronAdapter implements ICronService {
11
+ /**
12
+ * Schedules a new cron job
13
+ * @param {string} expression - Cron expression defining the schedule
14
+ * @param {Function} callback - Function to be executed when the schedule triggers
15
+ * @returns {ICronJob} Interface for controlling the scheduled job
16
+ */
17
+ schedule(expression: string, callback: () => void): ICronJob {
18
+ const job = cron.schedule(expression, callback);
19
+
20
+ return {
21
+ start: () => job.start(),
22
+ stop: () => job.stop(),
23
+ };
24
+ }
25
+ }
@@ -0,0 +1,159 @@
1
+ import { ICronService, IMemoryAdapter } from "../../interfaces";
2
+ import { ScheduledRequest } from "../../types";
3
+
4
+ /**
5
+ * @module Agenda
6
+ * @description A module for scheduling and managing cron-based tasks.
7
+ * Provides functionality for scheduling requests, managing their lifecycle,
8
+ * and handling recurring and one-time tasks.
9
+ */
10
+ export class Agenda {
11
+ /**
12
+ * Creates an instance of Agenda
13
+ * @param {ICronService} cronService - The cron service implementation
14
+ * @param {IMemoryAdapter} storage - The storage service for jobs and requests
15
+ */
16
+ constructor(
17
+ private readonly cronService: ICronService,
18
+ private readonly storage: IMemoryAdapter &
19
+ Required<
20
+ Pick<
21
+ IMemoryAdapter,
22
+ | "saveJob"
23
+ | "saveRequest"
24
+ | "getJob"
25
+ | "getRequest"
26
+ | "deleteJob"
27
+ | "deleteRequest"
28
+ | "getAllRequests"
29
+ | "clear"
30
+ >
31
+ >
32
+ ) {}
33
+
34
+ /**
35
+ * Schedule a new request to be processed later
36
+ * @param {Object} request - The request configuration
37
+ * @param {string} request.originalRequest - The original request to be executed
38
+ * @param {string} request.cronExpression - The cron expression for scheduling
39
+ * @param {Object} [callbacks] - Optional callback functions
40
+ * @param {Function} [callbacks.onScheduled] - Called when request is scheduled
41
+ * @param {Function} [callbacks.onExecuted] - Called when request is executed
42
+ * @returns {Promise<string>} The ID of the scheduled request
43
+ */
44
+ async scheduleRequest(
45
+ request: {
46
+ originalRequest: string;
47
+ cronExpression: string;
48
+ },
49
+ callbacks?: {
50
+ onScheduled?: (id: string) => void;
51
+ onExecuted?: (id: string, originalRequest: string) => void;
52
+ }
53
+ ): Promise<string> {
54
+ const id = crypto.randomUUID();
55
+
56
+ const scheduledRequest: ScheduledRequest = {
57
+ id,
58
+ originalRequest: request.originalRequest,
59
+ cronExpression: request.cronExpression,
60
+ isRecurring: false,
61
+ createdAt: new Date(),
62
+ };
63
+
64
+ // Create cron job using the injected service
65
+ const cronJob = this.cronService.schedule(
66
+ request.cronExpression,
67
+ async () => {
68
+ console.log(`🔄 Executing scheduled request: ${id}`);
69
+
70
+ if (callbacks?.onExecuted) {
71
+ callbacks.onExecuted(id, scheduledRequest.originalRequest);
72
+ }
73
+
74
+ console.log(`✅ Scheduled request executed successfully: ${id}`);
75
+
76
+ // Auto-stop for non-recurring tasks
77
+ if (!scheduledRequest.isRecurring) {
78
+ await this.cancelScheduledRequest(id);
79
+ }
80
+ }
81
+ );
82
+
83
+ // Start job in non-running mode
84
+ cronJob.stop();
85
+
86
+ // Store request and job using storage service
87
+ await this.storage.saveRequest(id, scheduledRequest);
88
+ await this.storage.saveJob(id, cronJob);
89
+
90
+ if (callbacks?.onScheduled) callbacks.onScheduled(id);
91
+
92
+ // Start the job after storing
93
+ cronJob.start();
94
+
95
+ return id;
96
+ }
97
+
98
+ /**
99
+ * Cancels a scheduled request by its ID
100
+ * @param {string} requestId - The ID of the request to cancel
101
+ * @returns {Promise<boolean>} True if the request was found and cancelled, false otherwise
102
+ */
103
+ async cancelScheduledRequest(requestId: string): Promise<boolean> {
104
+ const cronJob = await this.storage.getJob(requestId);
105
+ if (cronJob) {
106
+ try {
107
+ cronJob.stop();
108
+ await this.storage.deleteJob(requestId);
109
+ await this.storage.deleteRequest(requestId);
110
+ return true;
111
+ } catch (error) {
112
+ console.error(`Failed to stop cron job ${requestId}:`, error);
113
+ return false;
114
+ }
115
+ }
116
+ return false;
117
+ }
118
+
119
+ /**
120
+ * Retrieves all scheduled requests
121
+ * @returns {Promise<ScheduledRequest[]>} Array of all scheduled requests
122
+ */
123
+ async getScheduledRequests(): Promise<ScheduledRequest[]> {
124
+ return this.storage.getAllRequests();
125
+ }
126
+
127
+ /**
128
+ * Stops all scheduled jobs
129
+ * @returns {Promise<void>}
130
+ */
131
+ async stopAll(): Promise<void> {
132
+ const requests = await this.getScheduledRequests();
133
+
134
+ for (const request of requests) {
135
+ await this.cancelScheduledRequest(request.id);
136
+ }
137
+
138
+ await this.storage.clear();
139
+ }
140
+
141
+ /**
142
+ * Stops the agenda service
143
+ * @returns {Promise<void>}
144
+ */
145
+ public async stop(): Promise<void> {
146
+ await this.stopAll();
147
+ await new Promise((resolve) => setTimeout(resolve, 100));
148
+ }
149
+
150
+ /**
151
+ * Cancels requests matching the query
152
+ * @param {Object} query - Query to match requests against
153
+ * @returns {Promise<void>}
154
+ */
155
+ public async cancel(query: {}): Promise<void> {
156
+ await this.stopAll();
157
+ await new Promise((resolve) => setTimeout(resolve, 100));
158
+ }
159
+ }