@ai.ntellect/core 0.6.21 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/.mocharc.json +2 -1
  2. package/README.md +61 -85
  3. package/graph/controller.ts +1 -1
  4. package/graph/event-manager.ts +288 -0
  5. package/graph/index.ts +153 -367
  6. package/graph/logger.ts +70 -0
  7. package/graph/node.ts +398 -0
  8. package/graph/observer.ts +361 -0
  9. package/interfaces/index.ts +102 -1
  10. package/modules/agenda/index.ts +3 -16
  11. package/package.json +10 -5
  12. package/test/graph/index.test.ts +244 -113
  13. package/test/graph/observer.test.ts +398 -0
  14. package/test/modules/agenda/node-cron.test.ts +37 -16
  15. package/test/modules/memory/adapters/in-memory.test.ts +2 -2
  16. package/test/modules/memory/adapters/meilisearch.test.ts +28 -24
  17. package/test/modules/memory/base.test.ts +3 -3
  18. package/tsconfig.json +4 -2
  19. package/types/index.ts +23 -2
  20. package/dist/graph/controller.js +0 -72
  21. package/dist/graph/index.js +0 -501
  22. package/dist/index.js +0 -41
  23. package/dist/interfaces/index.js +0 -17
  24. package/dist/modules/agenda/adapters/node-cron/index.js +0 -29
  25. package/dist/modules/agenda/index.js +0 -140
  26. package/dist/modules/embedding/adapters/ai/index.js +0 -57
  27. package/dist/modules/embedding/index.js +0 -59
  28. package/dist/modules/memory/adapters/in-memory/index.js +0 -210
  29. package/dist/modules/memory/adapters/meilisearch/index.js +0 -320
  30. package/dist/modules/memory/adapters/redis/index.js +0 -158
  31. package/dist/modules/memory/index.js +0 -103
  32. package/dist/types/index.js +0 -2
  33. package/dist/utils/generate-action-schema.js +0 -43
  34. package/dist/utils/header-builder.js +0 -34
  35. package/test/modules/embedding/ai.test.ts +0 -78
  36. package/test/modules/memory/adapters/redis.test.ts +0 -169
  37. package/test/services/agenda.test.ts +0 -279
@@ -1,78 +0,0 @@
1
- import { openai } from "@ai-sdk/openai";
2
- import { expect } from "chai";
3
- import { Embedding } from "../../../modules/embedding";
4
- import { AIEmbeddingAdapter } from "../../../modules/embedding/adapters/ai";
5
-
6
- describe("EmbeddingModule", () => {
7
- let embeddingModule: Embedding;
8
-
9
- before(function () {
10
- this.timeout(10000);
11
- });
12
-
13
- beforeEach(() => {
14
- const model = openai.embedding("text-embedding-3-small");
15
- const embeddingModel = new AIEmbeddingAdapter(model);
16
- embeddingModule = new Embedding(embeddingModel);
17
- });
18
-
19
- it("should embed text", async function () {
20
- try {
21
- const embedding = await embeddingModule.embedText("Hello, world!");
22
- expect(embedding).to.be.an("array");
23
- expect(embedding.length).to.be.greaterThan(0);
24
- expect(embedding[0]).to.be.a("number");
25
- } catch (error) {
26
- console.error("Error in embedText:", error);
27
- throw error;
28
- }
29
- });
30
-
31
- it("should embed many texts", async function () {
32
- try {
33
- const embeddings = await embeddingModule.embedMany([
34
- "Hello, world!",
35
- "Another test text",
36
- ]);
37
- expect(embeddings).to.be.an("array");
38
- expect(embeddings.length).to.equal(2);
39
- expect(embeddings[0]).to.be.an("array");
40
- expect(embeddings[0][0]).to.be.a("number");
41
- } catch (error) {
42
- console.error("Error in embedMany:", error);
43
- throw error;
44
- }
45
- });
46
-
47
- it("should calculate similarity between two embeddings", () => {
48
- const embedding1 = [1, 2, 3];
49
- const embedding2 = [4, 5, 6];
50
- const similarity = embeddingModule.calculateSimilarity(
51
- embedding1,
52
- embedding2
53
- );
54
- expect(similarity).to.be.a("number");
55
- expect(similarity).to.be.within(0, 100);
56
- });
57
-
58
- it("should handle embedding errors gracefully", async function () {
59
- const mockEmbeddingAdapter = {
60
- embed: async () => {
61
- throw new Error("Mock embedding error");
62
- },
63
- embedMany: async () => {
64
- throw new Error("Mock embedding error");
65
- },
66
- };
67
-
68
- const mockEmbeddingModule = new Embedding(mockEmbeddingAdapter);
69
-
70
- try {
71
- await mockEmbeddingModule.embedText("test");
72
- expect.fail("Should have thrown an error");
73
- } catch (error) {
74
- expect(error).to.exist;
75
- expect((error as Error).message).to.equal("Mock embedding error");
76
- }
77
- });
78
- });
@@ -1,169 +0,0 @@
1
- import { expect } from "chai";
2
- import dotenv from "dotenv";
3
- import Redis from "ioredis";
4
- import { IMemoryAdapter } from "../../../interfaces";
5
- import { RedisAdapter } from "../../../memory/adapters/redis";
6
- import { BaseMemoryType } from "../../../types";
7
-
8
- // Load environment variables
9
- dotenv.config();
10
-
11
- describe("RedisAdapter", () => {
12
- before(function () {
13
- this.timeout(30000);
14
- });
15
-
16
- let redisAdapter: RedisAdapter;
17
- let mockAdapter: IMemoryAdapter;
18
- let redisClient: Redis | null = null;
19
- const fixedDate = new Date("2025-01-30T07:43:50.626Z");
20
- const fixedDateString = fixedDate.toISOString();
21
-
22
- const testMemory: BaseMemoryType = {
23
- id: "test-id",
24
- data: "test data",
25
- roomId: "test-room",
26
- createdAt: new Date(fixedDateString),
27
- };
28
-
29
- beforeEach(async function () {
30
- this.timeout(10000);
31
-
32
- try {
33
- mockAdapter = {
34
- init: async () => {},
35
- createMemory: async (input) => testMemory,
36
- getMemoryById: async () => testMemory,
37
- getMemoryByIndex: async () => [testMemory],
38
- getAllMemories: async () => [testMemory],
39
- clearMemoryById: async () => {},
40
- clearAllMemories: async () => {},
41
- };
42
-
43
- if (process.env.REDIS_URL) {
44
- redisClient = new Redis(process.env.REDIS_URL);
45
- redisAdapter = new RedisAdapter(process.env.REDIS_URL, {
46
- cachePrefix: "test-prefix",
47
- cacheTTL: 3600,
48
- });
49
- } else {
50
- const mockRedis = {
51
- connect: async () => Promise.resolve(),
52
- disconnect: async () => Promise.resolve(),
53
- set: async () => "OK",
54
- get: async (key: string) => {
55
- if (key.includes("test-id")) {
56
- return JSON.stringify({
57
- id: "test-id",
58
- data: "test data",
59
- embedding: null,
60
- roomId: "test-room",
61
- createdAt: fixedDateString,
62
- });
63
- }
64
- return null;
65
- },
66
- keys: async () => [`test-id`],
67
- mget: async (keys: string[]) =>
68
- keys.map(() =>
69
- JSON.stringify({
70
- id: "test-id",
71
- data: "test data",
72
- embedding: null,
73
- roomId: "test-room",
74
- createdAt: fixedDateString,
75
- })
76
- ),
77
- del: async () => 1,
78
- flushall: async () => "OK",
79
- quit: async () => Promise.resolve(),
80
- };
81
-
82
- redisAdapter = new RedisAdapter(mockRedis as any, {
83
- cachePrefix: "test-prefix",
84
- cacheTTL: 3600,
85
- });
86
- }
87
-
88
- await redisAdapter.init("test-room");
89
- } catch (error) {
90
- console.error("Error in beforeEach:", error);
91
- throw error;
92
- }
93
- });
94
-
95
- afterEach(async function () {
96
- this.timeout(5000);
97
- try {
98
- if (redisClient) {
99
- await redisClient.quit();
100
- redisClient = null;
101
- }
102
- if (redisAdapter) {
103
- await redisAdapter.quit();
104
- }
105
- } catch (error) {
106
- console.error("Error in afterEach:", error);
107
- }
108
- });
109
-
110
- describe("Initialization", () => {
111
- it("should initialize storage", async () => {
112
- await expect(redisAdapter.init("test-room")).to.not.throw;
113
- });
114
- });
115
-
116
- describe("Memory Operations", () => {
117
- const TEST_ROOM_ID = "test-room";
118
-
119
- it("should create memory", async () => {
120
- await expect(
121
- redisAdapter.createMemory({
122
- data: "test data",
123
- roomId: TEST_ROOM_ID,
124
- id: "test-id",
125
- embedding: [0.1, 0.2, 0.3],
126
- })
127
- ).to.not.throw;
128
- });
129
-
130
- it("should get memory by ID", async () => {
131
- const result = await redisAdapter.getMemoryById("test-id", TEST_ROOM_ID);
132
- if (result) {
133
- result.createdAt = new Date(fixedDateString);
134
- }
135
- expect(result).to.deep.equal(testMemory);
136
- });
137
-
138
- it("should get memories by index", async () => {
139
- const results = await redisAdapter.getMemoryByIndex("test", {
140
- roomId: TEST_ROOM_ID,
141
- limit: 10,
142
- });
143
-
144
- expect(results).to.be.an("array");
145
- if (results[0]) {
146
- results[0].createdAt = new Date(fixedDateString);
147
- }
148
- expect(results[0]).to.deep.equal(testMemory);
149
- });
150
-
151
- it("should get all memories", async () => {
152
- const results = await redisAdapter.getAllMemories(TEST_ROOM_ID);
153
- expect(results).to.be.an("array");
154
- if (results[0]) {
155
- results[0].createdAt = new Date(fixedDateString);
156
- }
157
- expect(results[0]).to.deep.equal(testMemory);
158
- });
159
-
160
- it("should clear memory by ID", async () => {
161
- await expect(redisAdapter.clearMemoryById("test-id", TEST_ROOM_ID)).to.not
162
- .throw;
163
- });
164
-
165
- it("should clear all memories", async () => {
166
- await expect(redisAdapter.clearAllMemories()).to.not.throw;
167
- });
168
- });
169
- });
@@ -1,279 +0,0 @@
1
- import { expect } from "chai";
2
- import sinon from "sinon";
3
- import { NodeCronAdapter } from "../../modules/agenda/adapters/cron/node-cron";
4
- import { Agenda } from "../../modules/agenda/agenda";
5
-
6
- before(function () {
7
- this.timeout(10000);
8
- });
9
-
10
- describe("Agenda Service", () => {
11
- let agenda: Agenda;
12
- const scheduledIds: string[] = []; // Track all scheduled request IDs
13
-
14
- beforeEach(() => {
15
- const cronService = new NodeCronAdapter();
16
- agenda = new Agenda(cronService);
17
- });
18
-
19
- afterEach(async () => {
20
- // Cancel all scheduled requests by their IDs
21
- scheduledIds.forEach((id) => agenda.cancelScheduledRequest(id));
22
- scheduledIds.length = 0; // Clear the array
23
-
24
- // Ensure all tasks are stopped
25
- await agenda.stop();
26
-
27
- await agenda.cancel({});
28
-
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);
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);
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);
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
- let globalAgenda: Agenda;
265
- before(() => {
266
- const cronService = new NodeCronAdapter();
267
- globalAgenda = new Agenda(cronService);
268
- });
269
-
270
- after(async () => {
271
- if (globalAgenda) {
272
- globalAgenda.stopAll();
273
- await new Promise((resolve) => setTimeout(resolve, 100));
274
- }
275
-
276
- await globalAgenda.stop();
277
- await globalAgenda.cancel({});
278
- await new Promise((resolve) => setTimeout(resolve, 100));
279
- });