@ai.ntellect/core 0.6.17 → 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 (78) 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 +37 -13
  17. package/graph/index.ts +348 -73
  18. package/index.ts +24 -6
  19. package/interfaces/index.ts +346 -27
  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 -12
  26. package/modules/memory/adapters/redis/index.ts +164 -0
  27. package/modules/memory/index.ts +93 -0
  28. package/package.json +3 -1
  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 +79 -75
  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/types/index.ts +82 -203
  38. package/utils/{stringifiy-zod-schema.ts → generate-action-schema.ts} +3 -3
  39. package/app/README.md +0 -36
  40. package/app/app/favicon.ico +0 -0
  41. package/app/app/globals.css +0 -21
  42. package/app/app/gun.ts +0 -0
  43. package/app/app/layout.tsx +0 -18
  44. package/app/app/page.tsx +0 -321
  45. package/app/eslint.config.mjs +0 -16
  46. package/app/next.config.ts +0 -7
  47. package/app/package-lock.json +0 -5912
  48. package/app/package.json +0 -31
  49. package/app/pnpm-lock.yaml +0 -4031
  50. package/app/postcss.config.mjs +0 -8
  51. package/app/public/file.svg +0 -1
  52. package/app/public/globe.svg +0 -1
  53. package/app/public/next.svg +0 -1
  54. package/app/public/vercel.svg +0 -1
  55. package/app/public/window.svg +0 -1
  56. package/app/tailwind.config.ts +0 -18
  57. package/app/tsconfig.json +0 -27
  58. package/dist/memory/index.js +0 -9
  59. package/dist/services/agenda.js +0 -115
  60. package/dist/services/queue.js +0 -142
  61. package/dist/utils/experimental-graph-rag.js +0 -152
  62. package/dist/utils/generate-object.js +0 -111
  63. package/dist/utils/inject-actions.js +0 -16
  64. package/dist/utils/queue-item-transformer.js +0 -24
  65. package/dist/utils/sanitize-results.js +0 -60
  66. package/memory/adapters/redis/index.ts +0 -103
  67. package/memory/index.ts +0 -22
  68. package/services/agenda.ts +0 -118
  69. package/services/embedding.ts +0 -26
  70. package/services/queue.ts +0 -145
  71. package/test/memory/adapters/redis.test.ts +0 -159
  72. package/test/memory/base.test.ts +0 -225
  73. package/test/services/queue.test.ts +0 -286
  74. package/utils/experimental-graph-rag.ts +0 -170
  75. package/utils/generate-object.ts +0 -117
  76. package/utils/inject-actions.ts +0 -19
  77. package/utils/queue-item-transformer.ts +0 -38
  78. package/utils/sanitize-results.ts +0 -66
@@ -1,8 +1,7 @@
1
- import { BaseMemoryService } from "../../../interfaces";
2
- import { MeilisearchAdapter } from "../../../memory/adapters/meilisearch";
3
- import { BaseMemoryType } from "../../../types";
4
1
  import { expect } from "chai";
5
2
  import dotenv from "dotenv";
3
+ import { MeilisearchAdapter } from "../../../memory/adapters/meilisearch";
4
+ import { BaseMemoryType } from "../../../types";
6
5
 
7
6
  // Load environment variables
8
7
  dotenv.config();
@@ -14,81 +13,55 @@ describe("MeilisearchAdapter", () => {
14
13
  const testMemory: BaseMemoryType = {
15
14
  id: "test-id",
16
15
  data: "test data",
17
- embedding: [0.1, 0.2, 0.3],
18
16
  roomId: "test-room",
19
17
  createdAt: new Date(),
20
18
  };
21
19
 
22
- beforeEach(() => {
23
- // Use real Meilisearch if environment variables are set, otherwise mock
24
- if (process.env.MEILISEARCH_HOST && process.env.MEILISEARCH_API_KEY) {
25
- // Real Meilisearch configuration
26
- // console.log("Real Meilisearch configuration");
27
- meilisearchAdapter = new MeilisearchAdapter({
28
- host: process.env.MEILISEARCH_HOST,
29
- apiKey: process.env.MEILISEARCH_API_KEY,
30
- searchableAttributes: ["content"],
31
- sortableAttributes: ["createdAt"],
32
- });
33
- } else {
34
- // Mock fetch implementation
35
- // console.log("Mock Meilisearch configuration");
36
- global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
37
- const url = input.toString();
20
+ beforeEach(async function () {
21
+ this.timeout(10000); // Augmenter le timeout
38
22
 
39
- // Mock for index check/creation
40
- if (url.includes("/indexes")) {
41
- if (init?.method === "POST") {
42
- return new Response(JSON.stringify({ taskUid: 1 }));
43
- }
44
- if (url.endsWith("/indexes")) {
45
- return new Response(JSON.stringify({ results: [] }));
46
- }
47
- // Mock for specific index check
48
- if (url.includes(`/indexes/${TEST_ROOM_ID}`)) {
49
- return new Response(
50
- JSON.stringify({
51
- uid: TEST_ROOM_ID,
52
- primaryKey: "id",
53
- })
54
- );
55
- }
56
- if (url.includes("/indexes/memories")) {
57
- return new Response(
58
- JSON.stringify({
59
- uid: "memories",
60
- primaryKey: "id",
61
- })
62
- );
63
- }
64
- }
23
+ // Mock fetch pour simuler l'existence de l'index
24
+ global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
25
+ const url = input.toString();
65
26
 
66
- // Mock for settings
67
- if (url.includes("/settings")) {
68
- return new Response(JSON.stringify({ acknowledged: true }));
27
+ // Mock pour index check/creation
28
+ if (url.includes("/indexes")) {
29
+ if (init?.method === "POST") {
30
+ return new Response(JSON.stringify({ taskUid: 1 }));
69
31
  }
70
-
71
- // Mock for documents
72
- if (url.includes("/documents")) {
73
- if (init?.method === "POST") {
74
- return new Response(JSON.stringify({ taskUid: 2 }));
75
- }
76
- if (init?.method === "DELETE") {
77
- return new Response(JSON.stringify({ taskUid: 3 }));
78
- }
79
- return new Response(JSON.stringify([testMemory]));
32
+ if (url.endsWith("/indexes")) {
33
+ return new Response(
34
+ JSON.stringify({
35
+ results: [{ uid: TEST_ROOM_ID }], // Simuler l'existence de l'index
36
+ })
37
+ );
80
38
  }
39
+ if (url.includes(`/indexes/${TEST_ROOM_ID}`)) {
40
+ return new Response(
41
+ JSON.stringify({
42
+ uid: TEST_ROOM_ID,
43
+ primaryKey: "id",
44
+ })
45
+ );
46
+ }
47
+ }
81
48
 
82
- return new Response(JSON.stringify({}));
83
- };
49
+ // Mock pour settings et autres endpoints
50
+ if (url.includes("/settings")) {
51
+ return new Response(JSON.stringify({ acknowledged: true }));
52
+ }
84
53
 
85
- meilisearchAdapter = new MeilisearchAdapter({
86
- host: "http://localhost:7700",
87
- apiKey: "aSampleMasterKey",
88
- searchableAttributes: ["content"],
89
- sortableAttributes: ["createdAt"],
90
- });
91
- }
54
+ return new Response(JSON.stringify({}));
55
+ };
56
+
57
+ meilisearchAdapter = new MeilisearchAdapter({
58
+ host: "http://localhost:7700",
59
+ apiKey: "test_key",
60
+ searchableAttributes: ["content"],
61
+ sortableAttributes: ["createdAt"],
62
+ });
63
+
64
+ await meilisearchAdapter.init(TEST_ROOM_ID);
92
65
  });
93
66
 
94
67
  describe("Initialization", () => {
@@ -163,7 +136,6 @@ describe("MeilisearchAdapter", () => {
163
136
  it("should create memory", async () => {
164
137
  const result = await meilisearchAdapter.createMemory({
165
138
  data: "test data",
166
- query: "test query",
167
139
  roomId: TEST_ROOM_ID,
168
140
  });
169
141
 
@@ -225,28 +197,60 @@ describe("MeilisearchAdapter", () => {
225
197
  });
226
198
 
227
199
  it("should clear all memories", async () => {
200
+ // S'assurer que l'index existe avant de le supprimer
201
+ await meilisearchAdapter.init(TEST_ROOM_ID);
228
202
  await expect(meilisearchAdapter.clearAllMemories()).to.not.throw;
229
203
  });
230
204
 
231
205
  it("should not create duplicate memory with same data", async () => {
232
- // Create first memory
206
+ // Override fetch mock for this test
207
+ const firstMemoryId = "test-memory-id";
208
+ const mockMemory = {
209
+ id: firstMemoryId,
210
+ data: "test data",
211
+ roomId: TEST_ROOM_ID,
212
+ embedding: null,
213
+ createdAt: new Date().toISOString(),
214
+ };
215
+
216
+ global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
217
+ const url = input.toString();
218
+
219
+ if (url.includes("/search")) {
220
+ return new Response(
221
+ JSON.stringify({
222
+ hits: [{ ...mockMemory }],
223
+ })
224
+ );
225
+ }
226
+
227
+ if (url.includes("/indexes")) {
228
+ if (init?.method === "POST") {
229
+ return new Response(JSON.stringify({ taskUid: 1 }));
230
+ }
231
+ return new Response(
232
+ JSON.stringify({
233
+ uid: TEST_ROOM_ID,
234
+ primaryKey: "id",
235
+ })
236
+ );
237
+ }
238
+
239
+ return new Response(JSON.stringify({}));
240
+ };
241
+
233
242
  const firstMemory = await meilisearchAdapter.createMemory({
234
243
  data: "test data",
235
- query: "test query",
236
244
  roomId: TEST_ROOM_ID,
237
245
  });
238
246
 
239
- // Try to create second memory with same data
240
247
  const secondMemory = await meilisearchAdapter.createMemory({
241
248
  data: "test data",
242
- query: "test query",
243
249
  roomId: TEST_ROOM_ID,
244
250
  });
245
251
 
246
- expect(secondMemory).to.exist;
247
252
  expect(secondMemory?.id).to.equal(firstMemory?.id);
248
253
  expect(secondMemory?.data).to.equal(firstMemory?.data);
249
- expect(secondMemory?.query).to.equal(firstMemory?.query);
250
254
  expect(secondMemory?.roomId).to.equal(firstMemory?.roomId);
251
255
  });
252
256
 
@@ -0,0 +1,169 @@
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
+ });
@@ -0,0 +1,230 @@
1
+ import { expect } from "chai";
2
+ import { IMemoryAdapter } from "../../../interfaces";
3
+ import { Memory } from "../../../modules/memory";
4
+ import { BaseMemoryType, CreateMemoryInput } from "../../../types";
5
+
6
+ /**
7
+ * @module MemoryTests
8
+ * @description Test suite for the Memory service implementation.
9
+ * Tests the core functionality of memory management including:
10
+ * - Initialization
11
+ * - Memory creation
12
+ * - Memory retrieval
13
+ * - Memory deletion
14
+ */
15
+
16
+ describe("Memory", () => {
17
+ let memory: Memory;
18
+ let mockAdapter: IMemoryAdapter;
19
+ const TEST_ROOM_ID = "test-room";
20
+
21
+ /**
22
+ * Test data fixture
23
+ * @type {BaseMemoryType}
24
+ */
25
+ const testMemory: BaseMemoryType = {
26
+ id: "test-id",
27
+ data: "test data",
28
+ embedding: [0.1, 0.2, 0.3],
29
+ roomId: TEST_ROOM_ID,
30
+ createdAt: new Date(),
31
+ };
32
+
33
+ /**
34
+ * Set up test environment before each test
35
+ * Creates a mock adapter and initializes the memory service
36
+ */
37
+ beforeEach(() => {
38
+ // Create mock implementation of IMemoryAdapter
39
+ mockAdapter = {
40
+ init: async () => Promise.resolve(),
41
+ createMemory: async (input: CreateMemoryInput) => ({
42
+ ...testMemory,
43
+ data: input.data,
44
+ embedding: input.embedding,
45
+ }),
46
+ getMemoryById: async () => testMemory,
47
+ getMemoryByIndex: async () => [testMemory],
48
+ getAllMemories: async () => [testMemory],
49
+ clearMemoryById: async () => Promise.resolve(),
50
+ clearAllMemories: async () => Promise.resolve(),
51
+ };
52
+
53
+ memory = new Memory(mockAdapter);
54
+ });
55
+
56
+ /**
57
+ * Test suite for initialization functionality
58
+ */
59
+ describe("Initialization", () => {
60
+ /**
61
+ * Test case: Verify adapter initialization
62
+ */
63
+ it("should initialize the memory adapter", async () => {
64
+ let initCalled = false;
65
+ mockAdapter.init = async () => {
66
+ initCalled = true;
67
+ };
68
+
69
+ await memory.init();
70
+ expect(initCalled).to.be.true;
71
+ });
72
+ });
73
+
74
+ /**
75
+ * Test suite for memory creation functionality
76
+ */
77
+ describe("Memory Creation", () => {
78
+ /**
79
+ * Test case: Verify memory creation with valid input
80
+ */
81
+ it("should create a new memory entry", async () => {
82
+ const input = {
83
+ data: "test data",
84
+ roomId: TEST_ROOM_ID,
85
+ };
86
+
87
+ const result = await memory.createMemory(input);
88
+ expect(result).to.deep.include(input);
89
+ });
90
+
91
+ /**
92
+ * Test case: Verify memory creation with embedding
93
+ */
94
+ it("should create a memory entry with embedding", async () => {
95
+ const input = {
96
+ data: "test data",
97
+ roomId: TEST_ROOM_ID,
98
+ embedding: [0.1, 0.2, 0.3],
99
+ };
100
+
101
+ const result = await memory.createMemory(input);
102
+ expect(result).to.deep.include(input);
103
+ });
104
+ });
105
+
106
+ /**
107
+ * Test suite for memory retrieval functionality
108
+ */
109
+ describe("Memory Retrieval", () => {
110
+ /**
111
+ * Test case: Verify memory retrieval by ID
112
+ */
113
+ it("should retrieve a memory by ID", async () => {
114
+ const result = await memory.getMemoryById("test-id", TEST_ROOM_ID);
115
+ expect(result).to.deep.equal(testMemory);
116
+ });
117
+
118
+ /**
119
+ * Test case: Verify memory retrieval by index
120
+ */
121
+ it("should retrieve memories by index", async () => {
122
+ const result = await memory.getMemoryByIndex("test", {
123
+ roomId: TEST_ROOM_ID,
124
+ });
125
+ expect(result).to.deep.equal([testMemory]);
126
+ });
127
+
128
+ /**
129
+ * Test case: Verify retrieval of all memories
130
+ */
131
+ it("should retrieve all memories", async () => {
132
+ const result = await memory.getAllMemories(TEST_ROOM_ID);
133
+ expect(result).to.deep.equal([testMemory]);
134
+ });
135
+ });
136
+
137
+ /**
138
+ * Test suite for memory deletion functionality
139
+ */
140
+ describe("Memory Deletion", () => {
141
+ /**
142
+ * Test case: Verify memory deletion by ID
143
+ */
144
+ it("should delete a memory by ID", async () => {
145
+ let deleteCalled = false;
146
+ mockAdapter.clearMemoryById = async () => {
147
+ deleteCalled = true;
148
+ };
149
+
150
+ await memory.clearMemoryById("test-id", TEST_ROOM_ID);
151
+ expect(deleteCalled).to.be.true;
152
+ });
153
+
154
+ /**
155
+ * Test case: Verify deletion of all memories
156
+ */
157
+ it("should clear all memories", async () => {
158
+ let clearAllCalled = false;
159
+ mockAdapter.clearAllMemories = async () => {
160
+ clearAllCalled = true;
161
+ };
162
+
163
+ await memory.clearAllMemories();
164
+ expect(clearAllCalled).to.be.true;
165
+ });
166
+ });
167
+
168
+ describe("Error Handling", () => {
169
+ it("should handle errors during memory creation", async () => {
170
+ mockAdapter.createMemory = async () => {
171
+ throw new Error("Creation failed");
172
+ };
173
+
174
+ try {
175
+ await memory.createMemory({
176
+ data: "test",
177
+ roomId: TEST_ROOM_ID,
178
+ });
179
+ expect.fail("Should have thrown an error");
180
+ } catch (error) {
181
+ expect(error).to.be.instanceOf(Error);
182
+ expect((error as Error).message).to.equal("Creation failed");
183
+ }
184
+ });
185
+
186
+ it("should handle errors during memory retrieval", async () => {
187
+ mockAdapter.getMemoryById = async () => {
188
+ throw new Error("Retrieval failed");
189
+ };
190
+
191
+ try {
192
+ await memory.getMemoryById("test-id", TEST_ROOM_ID);
193
+ expect.fail("Should have thrown an error");
194
+ } catch (error) {
195
+ expect(error).to.be.instanceOf(Error);
196
+ expect((error as Error).message).to.equal("Retrieval failed");
197
+ }
198
+ });
199
+ });
200
+
201
+ describe("Edge Cases", () => {
202
+ it("should handle undefined embedding", async () => {
203
+ const input = {
204
+ data: "test data",
205
+ query: "test query",
206
+ roomId: "test-room",
207
+ embedding: undefined,
208
+ };
209
+
210
+ const result = await memory.createMemory(input);
211
+ expect(result?.embedding).to.be.null;
212
+ });
213
+
214
+ it("should handle empty query results", async () => {
215
+ mockAdapter.getMemoryByIndex = async () => [];
216
+
217
+ const results = await memory.getMemoryByIndex("nonexistent", {
218
+ roomId: "test-room",
219
+ });
220
+ expect(results).to.be.an("array").that.is.empty;
221
+ });
222
+
223
+ it("should handle non-existent memory ID", async () => {
224
+ mockAdapter.getMemoryById = async () => null;
225
+
226
+ const result = await memory.getMemoryById("nonexistent", TEST_ROOM_ID);
227
+ expect(result).to.be.null;
228
+ });
229
+ });
230
+ });