@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.
Files changed (83) 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 +402 -0
  5. package/dist/index.js +22 -7
  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 +38 -14
  17. package/graph/index.ts +468 -0
  18. package/index.ts +25 -7
  19. package/interfaces/index.ts +346 -28
  20. package/modules/agenda/adapters/node-cron/index.ts +25 -0
  21. package/modules/agenda/index.ts +159 -0
  22. package/modules/embedding/adapters/ai/index.ts +42 -0
  23. package/modules/embedding/index.ts +45 -0
  24. package/modules/memory/adapters/in-memory/index.ts +203 -0
  25. package/{memory → modules/memory}/adapters/meilisearch/index.ts +114 -8
  26. package/modules/memory/adapters/redis/index.ts +164 -0
  27. package/modules/memory/index.ts +93 -0
  28. package/package.json +4 -4
  29. package/test/graph/index.test.ts +646 -0
  30. package/test/modules/agenda/node-cron.test.ts +286 -0
  31. package/test/modules/embedding/ai.test.ts +78 -0
  32. package/test/modules/memory/adapters/in-memory.test.ts +153 -0
  33. package/test/{memory → modules/memory}/adapters/meilisearch.test.ts +80 -94
  34. package/test/modules/memory/adapters/redis.test.ts +169 -0
  35. package/test/modules/memory/base.test.ts +230 -0
  36. package/test/services/agenda.test.ts +279 -280
  37. package/tsconfig.json +0 -3
  38. package/types/index.ts +82 -203
  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/graph/graph.js +0 -162
  60. package/dist/memory/index.js +0 -9
  61. package/dist/services/agenda.js +0 -115
  62. package/dist/services/queue.js +0 -142
  63. package/dist/utils/experimental-graph-rag.js +0 -152
  64. package/dist/utils/generate-object.js +0 -111
  65. package/dist/utils/inject-actions.js +0 -16
  66. package/dist/utils/queue-item-transformer.js +0 -24
  67. package/dist/utils/sanitize-results.js +0 -60
  68. package/graph/graph.ts +0 -193
  69. package/memory/adapters/redis/index.ts +0 -103
  70. package/memory/index.ts +0 -22
  71. package/services/agenda.ts +0 -118
  72. package/services/embedding.ts +0 -26
  73. package/services/queue.ts +0 -145
  74. package/test/.env.test +0 -4
  75. package/test/graph/engine.test.ts +0 -533
  76. package/test/memory/adapters/redis.test.ts +0 -160
  77. package/test/memory/base.test.ts +0 -229
  78. package/test/services/queue.test.ts +0 -286
  79. package/utils/experimental-graph-rag.ts +0 -170
  80. package/utils/generate-object.ts +0 -117
  81. package/utils/inject-actions.ts +0 -19
  82. package/utils/queue-item-transformer.ts +0 -38
  83. package/utils/sanitize-results.ts +0 -66
@@ -0,0 +1,286 @@
1
+ import { expect } from "chai";
2
+ import sinon from "sinon";
3
+ import { Agenda } from "../../../modules/agenda";
4
+ import { NodeCronAdapter } from "../../../modules/agenda/adapters/cron/node-cron";
5
+ import { InMemoryAdapter } from "../../../modules/memory/adapters/in-memory";
6
+
7
+ before(function () {
8
+ this.timeout(10000);
9
+ });
10
+
11
+ describe("Agenda Service", () => {
12
+ let agenda: Agenda;
13
+ const scheduledIds: string[] = []; // Track all scheduled request IDs
14
+
15
+ beforeEach(() => {
16
+ const cronService = new NodeCronAdapter();
17
+ const jobStorage = new InMemoryAdapter();
18
+ agenda = new Agenda(cronService, jobStorage);
19
+ });
20
+
21
+ afterEach(async () => {
22
+ // Cancel all scheduled requests by their IDs
23
+ scheduledIds.forEach((id) => agenda.cancelScheduledRequest(id));
24
+ scheduledIds.length = 0; // Clear the array
25
+
26
+ // Ensure all tasks are stopped
27
+ await agenda.stop();
28
+
29
+ await agenda.cancel({});
30
+
31
+ await new Promise((resolve) => setTimeout(resolve, 100));
32
+ });
33
+
34
+ describe("Request Scheduling", () => {
35
+ it("should schedule a new request and return an id", async () => {
36
+ const request = {
37
+ originalRequest: "test request",
38
+ cronExpression: "0 0 * * *",
39
+ };
40
+
41
+ const id = await agenda.scheduleRequest(request);
42
+ scheduledIds.push(id); // Track the ID
43
+
44
+ expect(id).to.be.a("string");
45
+ expect(agenda.getScheduledRequests()).to.have.lengthOf(1);
46
+
47
+ const scheduledRequest = agenda.getScheduledRequests()[0];
48
+ expect(scheduledRequest.originalRequest).to.equal(
49
+ request.originalRequest
50
+ );
51
+ expect(scheduledRequest.cronExpression).to.equal(request.cronExpression);
52
+ expect(scheduledRequest.isRecurring).to.be.false;
53
+
54
+ agenda.cancelScheduledRequest(id);
55
+ });
56
+
57
+ it("should execute callbacks when scheduling and executing", async function () {
58
+ this.timeout(5000);
59
+
60
+ const onScheduledSpy = sinon.spy();
61
+ const onExecutedSpy = sinon.spy();
62
+
63
+ const request = {
64
+ originalRequest: "test request",
65
+ cronExpression: `${(new Date().getSeconds() + 1) % 60} * * * * *`,
66
+ };
67
+
68
+ const id = await agenda.scheduleRequest(request, {
69
+ onScheduled: onScheduledSpy,
70
+ onExecuted: onExecutedSpy,
71
+ });
72
+ scheduledIds.push(id);
73
+
74
+ expect(onScheduledSpy.calledOnce).to.be.true;
75
+
76
+ await new Promise<void>((resolve, reject) => {
77
+ const timeout = setTimeout(() => {
78
+ reject(new Error("Callback execution timeout"));
79
+ }, 4000);
80
+
81
+ const checkExecution = () => {
82
+ if (onExecutedSpy.calledOnce) {
83
+ clearTimeout(timeout);
84
+ agenda.cancelScheduledRequest(id);
85
+ resolve();
86
+ return;
87
+ }
88
+ setTimeout(checkExecution, 100);
89
+ };
90
+ checkExecution();
91
+ });
92
+
93
+ expect(onExecutedSpy.calledOnce).to.be.true;
94
+ });
95
+ });
96
+
97
+ describe("Request Management", () => {
98
+ it("should cancel a scheduled request", async () => {
99
+ const request = {
100
+ originalRequest: "test request",
101
+ cronExpression: "*/1 * * * *",
102
+ };
103
+
104
+ const id = await agenda.scheduleRequest(request);
105
+ scheduledIds.push(id);
106
+ const requests = await agenda.getScheduledRequests();
107
+ expect(requests).to.have.lengthOf(1);
108
+
109
+ const cancelled = await agenda.cancelScheduledRequest(id);
110
+ expect(cancelled).to.be.true;
111
+ const remainingRequests = await agenda.getScheduledRequests();
112
+ expect(remainingRequests).to.have.lengthOf(0);
113
+ });
114
+
115
+ it("should return false when cancelling non-existent request", async () => {
116
+ const cancelled = await agenda.cancelScheduledRequest("non-existent-id");
117
+ expect(cancelled).to.be.false;
118
+ });
119
+
120
+ it("should get all scheduled requests", async () => {
121
+ const requests = [
122
+ {
123
+ originalRequest: "request 1",
124
+ cronExpression: "*/1 * * * *",
125
+ },
126
+ {
127
+ originalRequest: "request 2",
128
+ cronExpression: "*/5 * * * *",
129
+ },
130
+ ];
131
+
132
+ for (const request of requests) {
133
+ const id = await agenda.scheduleRequest(request);
134
+ scheduledIds.push(id);
135
+ }
136
+
137
+ const scheduledRequests = await agenda.getScheduledRequests();
138
+ expect(scheduledRequests).to.have.lengthOf(2);
139
+ expect(scheduledRequests[0].originalRequest).to.equal("request 1");
140
+ expect(scheduledRequests[1].originalRequest).to.equal("request 2");
141
+ });
142
+ });
143
+
144
+ describe("Global Management", () => {
145
+ it("should stop all scheduled requests", async () => {
146
+ const requests = [
147
+ {
148
+ originalRequest: "request 1",
149
+ cronExpression: "*/1 * * * *",
150
+ },
151
+ {
152
+ originalRequest: "request 2",
153
+ cronExpression: "*/5 * * * *",
154
+ },
155
+ ];
156
+
157
+ for (const request of requests) {
158
+ await agenda.scheduleRequest(request);
159
+ }
160
+
161
+ const initialRequests = await agenda.getScheduledRequests();
162
+ expect(initialRequests).to.have.lengthOf(2);
163
+
164
+ await agenda.stopAll();
165
+ const remainingRequests = await agenda.getScheduledRequests();
166
+ expect(remainingRequests).to.have.lengthOf(0);
167
+ });
168
+ });
169
+
170
+ describe("Error Handling", () => {
171
+ it("should handle execution errors gracefully", async () => {
172
+ const consoleSpy = sinon.spy(console, "error");
173
+
174
+ const request = {
175
+ originalRequest: "error request",
176
+ cronExpression: "0 0 * * *",
177
+ };
178
+
179
+ const id = await agenda.scheduleRequest(request);
180
+
181
+ // Wait for execution
182
+ await new Promise((resolve) => setTimeout(resolve, 1100));
183
+
184
+ expect(consoleSpy.called).to.be.false;
185
+
186
+ agenda.cancelScheduledRequest(id);
187
+ consoleSpy.restore();
188
+ });
189
+ });
190
+
191
+ describe("Request Execution", () => {
192
+ it("should execute non-recurring requests only once", async function () {
193
+ this.timeout(5000);
194
+ const onExecutedSpy = sinon.spy();
195
+
196
+ const request = {
197
+ originalRequest: "single execution",
198
+ cronExpression: `${new Date().getSeconds() + 1} * * * * *`,
199
+ };
200
+
201
+ const id = await agenda.scheduleRequest(request, {
202
+ onExecuted: onExecutedSpy,
203
+ });
204
+
205
+ try {
206
+ await new Promise<void>((resolve, reject) => {
207
+ const timeout = setTimeout(
208
+ () => reject(new Error("Test timeout")),
209
+ 4000
210
+ );
211
+ const checkExecution = () => {
212
+ if (onExecutedSpy.calledOnce) {
213
+ clearTimeout(timeout);
214
+ resolve();
215
+ return;
216
+ }
217
+ setTimeout(checkExecution, 100);
218
+ };
219
+ checkExecution();
220
+ });
221
+ } finally {
222
+ agenda.cancelScheduledRequest(id);
223
+ }
224
+
225
+ expect(onExecutedSpy.calledOnce).to.be.true;
226
+ expect(agenda.getScheduledRequests()).to.have.lengthOf(0);
227
+ });
228
+
229
+ it("should log execution status", async function () {
230
+ this.timeout(10000);
231
+ const consoleLogSpy = sinon.spy(console, "log");
232
+
233
+ const request = {
234
+ originalRequest: "test request",
235
+ cronExpression: `${new Date().getSeconds() + 1} * * * * *`,
236
+ };
237
+
238
+ const id = await agenda.scheduleRequest(request);
239
+
240
+ await new Promise<void>((resolve) => {
241
+ const checkExecution = () => {
242
+ if (
243
+ consoleLogSpy.calledWith(`🔄 Executing scheduled request: ${id}`) &&
244
+ consoleLogSpy.calledWith(
245
+ `✅ Scheduled request executed successfully: ${id}`
246
+ )
247
+ ) {
248
+ agenda.cancelScheduledRequest(id);
249
+ resolve();
250
+ return;
251
+ }
252
+ setTimeout(checkExecution, 100);
253
+ };
254
+ checkExecution();
255
+ });
256
+
257
+ expect(consoleLogSpy.calledWith(`🔄 Executing scheduled request: ${id}`))
258
+ .to.be.true;
259
+ expect(
260
+ consoleLogSpy.calledWith(
261
+ `✅ Scheduled request executed successfully: ${id}`
262
+ )
263
+ ).to.be.true;
264
+
265
+ consoleLogSpy.restore();
266
+ });
267
+ });
268
+ });
269
+
270
+ let globalAgenda: Agenda;
271
+ before(() => {
272
+ const cronService = new NodeCronAdapter();
273
+ const jobStorage = new InMemoryAdapter();
274
+ globalAgenda = new Agenda(cronService, jobStorage);
275
+ });
276
+
277
+ after(async () => {
278
+ if (globalAgenda) {
279
+ globalAgenda.stopAll();
280
+ await new Promise((resolve) => setTimeout(resolve, 100));
281
+ }
282
+
283
+ await globalAgenda.stop();
284
+ await globalAgenda.cancel({});
285
+ await new Promise((resolve) => setTimeout(resolve, 100));
286
+ });
@@ -0,0 +1,78 @@
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
+ });
@@ -0,0 +1,153 @@
1
+ import { expect } from "chai";
2
+ import { InMemoryAdapter } from "../../../memory/adapters/in-memory";
3
+ import { BaseMemoryType } from "../../../types";
4
+
5
+ describe("InMemoryAdapter", () => {
6
+ let inMemoryAdapter: InMemoryAdapter;
7
+ const fixedDate = new Date("2025-01-30T07:43:50.626Z");
8
+ const TEST_ROOM_ID = "test-room";
9
+
10
+ const testMemory: BaseMemoryType = {
11
+ id: "test-id",
12
+ data: "test data",
13
+ roomId: TEST_ROOM_ID,
14
+ createdAt: fixedDate,
15
+ };
16
+
17
+ beforeEach(async () => {
18
+ inMemoryAdapter = new InMemoryAdapter();
19
+ await inMemoryAdapter.init(TEST_ROOM_ID);
20
+ });
21
+
22
+ describe("Initialization", () => {
23
+ it("should initialize storage", async () => {
24
+ await expect(inMemoryAdapter.init("new-room")).to.not.throw;
25
+ const memories = await inMemoryAdapter.getAllMemories("new-room");
26
+ expect(memories).to.be.an("array").that.is.empty;
27
+ });
28
+ });
29
+
30
+ describe("Memory Operations", () => {
31
+ it("should create memory", async () => {
32
+ const memory = await inMemoryAdapter.createMemory({
33
+ data: "test data",
34
+ roomId: TEST_ROOM_ID,
35
+ id: "test-id",
36
+ embedding: [0.1, 0.2, 0.3],
37
+ });
38
+
39
+ expect(memory).to.have.property("id");
40
+ expect(memory?.data).to.equal("test data");
41
+ expect(memory?.roomId).to.equal(TEST_ROOM_ID);
42
+ });
43
+
44
+ it("should not create duplicate memory", async () => {
45
+ // Create first memory
46
+ const memory1 = await inMemoryAdapter.createMemory({
47
+ data: "test data",
48
+ roomId: TEST_ROOM_ID,
49
+ id: "test-id",
50
+ });
51
+
52
+ // Try to create duplicate
53
+ const memory2 = await inMemoryAdapter.createMemory({
54
+ data: "test data",
55
+ roomId: TEST_ROOM_ID,
56
+ id: "another-id",
57
+ });
58
+
59
+ expect(memory2?.id).to.equal(memory1?.id);
60
+ });
61
+
62
+ it("should get memory by ID", async () => {
63
+ await inMemoryAdapter.createMemory({
64
+ data: testMemory.data,
65
+ roomId: testMemory.roomId,
66
+ id: testMemory.id,
67
+ embedding: testMemory.embedding,
68
+ });
69
+
70
+ const result = await inMemoryAdapter.getMemoryById(
71
+ "test-id",
72
+ TEST_ROOM_ID
73
+ );
74
+ expect(result).to.have.property("id", "test-id");
75
+ });
76
+
77
+ it("should get memories by index", async () => {
78
+ // Create test memories
79
+ await inMemoryAdapter.createMemory({
80
+ data: "test data one",
81
+ roomId: TEST_ROOM_ID,
82
+ id: "test-id-1",
83
+ });
84
+ await inMemoryAdapter.createMemory({
85
+ data: "test data two",
86
+ roomId: TEST_ROOM_ID,
87
+ id: "test-id-2",
88
+ });
89
+
90
+ const results = await inMemoryAdapter.getMemoryByIndex("one", {
91
+ roomId: TEST_ROOM_ID,
92
+ limit: 10,
93
+ });
94
+
95
+ expect(results).to.be.an("array");
96
+ expect(results).to.have.lengthOf(1);
97
+ expect(results[0].data).to.include("one");
98
+ });
99
+
100
+ it("should get all memories", async () => {
101
+ // Create multiple memories
102
+ await inMemoryAdapter.createMemory({
103
+ data: "test data 1",
104
+ roomId: TEST_ROOM_ID,
105
+ id: "test-id-1",
106
+ });
107
+ await inMemoryAdapter.createMemory({
108
+ data: "test data 2",
109
+ roomId: TEST_ROOM_ID,
110
+ id: "test-id-2",
111
+ });
112
+
113
+ const results = await inMemoryAdapter.getAllMemories(TEST_ROOM_ID);
114
+ expect(results).to.be.an("array");
115
+ expect(results).to.have.lengthOf(2);
116
+ });
117
+
118
+ it("should clear memory by ID", async () => {
119
+ // Create a memory
120
+ await inMemoryAdapter.createMemory({
121
+ data: "test data",
122
+ roomId: TEST_ROOM_ID,
123
+ id: "test-id",
124
+ });
125
+
126
+ await inMemoryAdapter.clearMemoryById("test-id", TEST_ROOM_ID);
127
+ const result = await inMemoryAdapter.getMemoryById(
128
+ "test-id",
129
+ TEST_ROOM_ID
130
+ );
131
+ expect(result).to.be.null;
132
+ });
133
+
134
+ it("should clear all memories", async () => {
135
+ // Create multiple memories
136
+ await inMemoryAdapter.createMemory({
137
+ data: "test data 1",
138
+ roomId: TEST_ROOM_ID,
139
+ id: "test-id-1",
140
+ });
141
+ await inMemoryAdapter.createMemory({
142
+ data: "test data 2",
143
+ roomId: TEST_ROOM_ID,
144
+ id: "test-id-2",
145
+ });
146
+
147
+ await inMemoryAdapter.clearAllMemories();
148
+ const results = await inMemoryAdapter.getAllMemories(TEST_ROOM_ID);
149
+ expect(results).to.be.an("array");
150
+ expect(results).to.have.lengthOf(0);
151
+ });
152
+ });
153
+ });