@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.
- package/.mocharc.json +1 -2
- package/README.md +123 -178
- package/dist/graph/controller.js +29 -6
- package/dist/graph/index.js +402 -0
- package/dist/index.js +22 -7
- package/dist/interfaces/index.js +15 -0
- package/dist/modules/agenda/adapters/node-cron/index.js +29 -0
- package/dist/modules/agenda/index.js +140 -0
- package/dist/{services/embedding.js → modules/embedding/adapters/ai/index.js} +24 -7
- package/dist/modules/embedding/index.js +59 -0
- package/dist/modules/memory/adapters/in-memory/index.js +210 -0
- package/dist/{memory → modules/memory}/adapters/meilisearch/index.js +97 -2
- package/dist/{memory → modules/memory}/adapters/redis/index.js +77 -15
- package/dist/modules/memory/index.js +103 -0
- package/dist/utils/{stringifiy-zod-schema.js → generate-action-schema.js} +5 -5
- package/graph/controller.ts +38 -14
- package/graph/index.ts +468 -0
- package/index.ts +25 -7
- package/interfaces/index.ts +346 -28
- package/modules/agenda/adapters/node-cron/index.ts +25 -0
- package/modules/agenda/index.ts +159 -0
- package/modules/embedding/adapters/ai/index.ts +42 -0
- package/modules/embedding/index.ts +45 -0
- package/modules/memory/adapters/in-memory/index.ts +203 -0
- package/{memory → modules/memory}/adapters/meilisearch/index.ts +114 -8
- package/modules/memory/adapters/redis/index.ts +164 -0
- package/modules/memory/index.ts +93 -0
- package/package.json +4 -4
- package/test/graph/index.test.ts +646 -0
- package/test/modules/agenda/node-cron.test.ts +286 -0
- package/test/modules/embedding/ai.test.ts +78 -0
- package/test/modules/memory/adapters/in-memory.test.ts +153 -0
- package/test/{memory → modules/memory}/adapters/meilisearch.test.ts +80 -94
- package/test/modules/memory/adapters/redis.test.ts +169 -0
- package/test/modules/memory/base.test.ts +230 -0
- package/test/services/agenda.test.ts +279 -280
- package/tsconfig.json +0 -3
- package/types/index.ts +82 -203
- package/utils/{stringifiy-zod-schema.ts → generate-action-schema.ts} +3 -3
- package/app/README.md +0 -36
- package/app/app/favicon.ico +0 -0
- package/app/app/globals.css +0 -21
- package/app/app/gun.ts +0 -0
- package/app/app/layout.tsx +0 -18
- package/app/app/page.tsx +0 -321
- package/app/eslint.config.mjs +0 -16
- package/app/next.config.ts +0 -7
- package/app/package-lock.json +0 -5912
- package/app/package.json +0 -31
- package/app/pnpm-lock.yaml +0 -4031
- package/app/postcss.config.mjs +0 -8
- package/app/public/file.svg +0 -1
- package/app/public/globe.svg +0 -1
- package/app/public/next.svg +0 -1
- package/app/public/vercel.svg +0 -1
- package/app/public/window.svg +0 -1
- package/app/tailwind.config.ts +0 -18
- package/app/tsconfig.json +0 -27
- package/dist/graph/graph.js +0 -162
- package/dist/memory/index.js +0 -9
- package/dist/services/agenda.js +0 -115
- package/dist/services/queue.js +0 -142
- package/dist/utils/experimental-graph-rag.js +0 -152
- package/dist/utils/generate-object.js +0 -111
- package/dist/utils/inject-actions.js +0 -16
- package/dist/utils/queue-item-transformer.js +0 -24
- package/dist/utils/sanitize-results.js +0 -60
- package/graph/graph.ts +0 -193
- package/memory/adapters/redis/index.ts +0 -103
- package/memory/index.ts +0 -22
- package/services/agenda.ts +0 -118
- package/services/embedding.ts +0 -26
- package/services/queue.ts +0 -145
- package/test/.env.test +0 -4
- package/test/graph/engine.test.ts +0 -533
- package/test/memory/adapters/redis.test.ts +0 -160
- package/test/memory/base.test.ts +0 -229
- package/test/services/queue.test.ts +0 -286
- package/utils/experimental-graph-rag.ts +0 -170
- package/utils/generate-object.ts +0 -117
- package/utils/inject-actions.ts +0 -19
- package/utils/queue-item-transformer.ts +0 -38
- package/utils/sanitize-results.ts +0 -66
@@ -1,117 +1,72 @@
|
|
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();
|
9
8
|
|
10
9
|
describe("MeilisearchAdapter", () => {
|
11
10
|
let meilisearchAdapter: MeilisearchAdapter;
|
12
|
-
let mockBaseMemoryService: BaseMemoryService;
|
13
11
|
const TEST_ROOM_ID = "test-room";
|
14
12
|
|
15
13
|
const testMemory: BaseMemoryType = {
|
16
14
|
id: "test-id",
|
17
15
|
data: "test data",
|
18
|
-
query: "test query",
|
19
|
-
embedding: [0.1, 0.2, 0.3],
|
20
16
|
roomId: "test-room",
|
21
17
|
createdAt: new Date(),
|
22
18
|
};
|
23
19
|
|
24
|
-
beforeEach(()
|
25
|
-
//
|
26
|
-
if (process.env.MEILISEARCH_HOST && process.env.MEILISEARCH_API_KEY) {
|
27
|
-
// Real Meilisearch configuration
|
28
|
-
// console.log("Real Meilisearch configuration");
|
29
|
-
meilisearchAdapter = new MeilisearchAdapter(
|
30
|
-
{
|
31
|
-
host: process.env.MEILISEARCH_HOST,
|
32
|
-
apiKey: process.env.MEILISEARCH_API_KEY,
|
33
|
-
searchableAttributes: ["content"],
|
34
|
-
sortableAttributes: ["createdAt"],
|
35
|
-
},
|
36
|
-
mockBaseMemoryService
|
37
|
-
);
|
38
|
-
} else {
|
39
|
-
// Mock fetch implementation
|
40
|
-
// console.log("Mock Meilisearch configuration");
|
41
|
-
global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
|
42
|
-
const url = input.toString();
|
20
|
+
beforeEach(async function () {
|
21
|
+
this.timeout(10000); // Augmenter le timeout
|
43
22
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
return new Response(JSON.stringify({ taskUid: 1 }));
|
48
|
-
}
|
49
|
-
if (url.endsWith("/indexes")) {
|
50
|
-
return new Response(JSON.stringify({ results: [] }));
|
51
|
-
}
|
52
|
-
// Mock for specific index check
|
53
|
-
if (url.includes(`/indexes/${TEST_ROOM_ID}`)) {
|
54
|
-
return new Response(
|
55
|
-
JSON.stringify({
|
56
|
-
uid: TEST_ROOM_ID,
|
57
|
-
primaryKey: "id",
|
58
|
-
})
|
59
|
-
);
|
60
|
-
}
|
61
|
-
if (url.includes("/indexes/memories")) {
|
62
|
-
return new Response(
|
63
|
-
JSON.stringify({
|
64
|
-
uid: "memories",
|
65
|
-
primaryKey: "id",
|
66
|
-
})
|
67
|
-
);
|
68
|
-
}
|
69
|
-
}
|
23
|
+
// Mock fetch pour simuler l'existence de l'index
|
24
|
+
global.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
|
25
|
+
const url = input.toString();
|
70
26
|
|
71
|
-
|
72
|
-
|
73
|
-
|
27
|
+
// Mock pour index check/creation
|
28
|
+
if (url.includes("/indexes")) {
|
29
|
+
if (init?.method === "POST") {
|
30
|
+
return new Response(JSON.stringify({ taskUid: 1 }));
|
74
31
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
+
);
|
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
|
+
);
|
85
46
|
}
|
47
|
+
}
|
86
48
|
|
87
|
-
|
88
|
-
|
49
|
+
// Mock pour settings et autres endpoints
|
50
|
+
if (url.includes("/settings")) {
|
51
|
+
return new Response(JSON.stringify({ acknowledged: true }));
|
52
|
+
}
|
89
53
|
|
90
|
-
|
91
|
-
|
92
|
-
createMemory: async () => {},
|
93
|
-
getMemoryById: async () => testMemory,
|
94
|
-
getMemoryByIndex: async () => [testMemory],
|
95
|
-
getAllMemories: async () => [testMemory],
|
96
|
-
clearMemoryById: async () => {},
|
97
|
-
clearAllMemories: async () => {},
|
98
|
-
};
|
54
|
+
return new Response(JSON.stringify({}));
|
55
|
+
};
|
99
56
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
);
|
109
|
-
}
|
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);
|
110
65
|
});
|
111
66
|
|
112
67
|
describe("Initialization", () => {
|
113
68
|
it("should initialize storage", async () => {
|
114
|
-
await expect(meilisearchAdapter.init()).to.not.throw;
|
69
|
+
await expect(meilisearchAdapter.init("test-room")).to.not.throw;
|
115
70
|
});
|
116
71
|
});
|
117
72
|
|
@@ -170,7 +125,7 @@ describe("MeilisearchAdapter", () => {
|
|
170
125
|
}
|
171
126
|
|
172
127
|
try {
|
173
|
-
await meilisearchAdapter.init();
|
128
|
+
await meilisearchAdapter.init(TEST_ROOM_ID);
|
174
129
|
await meilisearchAdapter.initializeStorage(TEST_ROOM_ID);
|
175
130
|
} catch (error) {
|
176
131
|
console.error("Failed to initialize:", error);
|
@@ -181,7 +136,6 @@ describe("MeilisearchAdapter", () => {
|
|
181
136
|
it("should create memory", async () => {
|
182
137
|
const result = await meilisearchAdapter.createMemory({
|
183
138
|
data: "test data",
|
184
|
-
query: "test query",
|
185
139
|
roomId: TEST_ROOM_ID,
|
186
140
|
});
|
187
141
|
|
@@ -243,28 +197,60 @@ describe("MeilisearchAdapter", () => {
|
|
243
197
|
});
|
244
198
|
|
245
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);
|
246
202
|
await expect(meilisearchAdapter.clearAllMemories()).to.not.throw;
|
247
203
|
});
|
248
204
|
|
249
205
|
it("should not create duplicate memory with same data", async () => {
|
250
|
-
//
|
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
|
+
|
251
242
|
const firstMemory = await meilisearchAdapter.createMemory({
|
252
243
|
data: "test data",
|
253
|
-
query: "test query",
|
254
244
|
roomId: TEST_ROOM_ID,
|
255
245
|
});
|
256
246
|
|
257
|
-
// Try to create second memory with same data
|
258
247
|
const secondMemory = await meilisearchAdapter.createMemory({
|
259
248
|
data: "test data",
|
260
|
-
query: "test query",
|
261
249
|
roomId: TEST_ROOM_ID,
|
262
250
|
});
|
263
251
|
|
264
|
-
expect(secondMemory).to.exist;
|
265
252
|
expect(secondMemory?.id).to.equal(firstMemory?.id);
|
266
253
|
expect(secondMemory?.data).to.equal(firstMemory?.data);
|
267
|
-
expect(secondMemory?.query).to.equal(firstMemory?.query);
|
268
254
|
expect(secondMemory?.roomId).to.equal(firstMemory?.roomId);
|
269
255
|
});
|
270
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
|
+
});
|