memories-lite 0.9.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 (101) hide show
  1. package/MEMORIES.md +39 -0
  2. package/README.md +221 -0
  3. package/TECHNICAL.md +135 -0
  4. package/dist/config/defaults.d.ts +2 -0
  5. package/dist/config/defaults.js +61 -0
  6. package/dist/config/manager.d.ts +4 -0
  7. package/dist/config/manager.js +121 -0
  8. package/dist/embeddings/base.d.ts +4 -0
  9. package/dist/embeddings/base.js +2 -0
  10. package/dist/embeddings/google.d.ts +10 -0
  11. package/dist/embeddings/google.js +28 -0
  12. package/dist/embeddings/openai.d.ts +10 -0
  13. package/dist/embeddings/openai.js +31 -0
  14. package/dist/graphs/configs.d.ts +14 -0
  15. package/dist/graphs/configs.js +19 -0
  16. package/dist/graphs/tools.d.ts +271 -0
  17. package/dist/graphs/tools.js +220 -0
  18. package/dist/graphs/utils.d.ts +9 -0
  19. package/dist/graphs/utils.js +105 -0
  20. package/dist/index.d.ts +14 -0
  21. package/dist/index.js +30 -0
  22. package/dist/llms/base.d.ts +16 -0
  23. package/dist/llms/base.js +2 -0
  24. package/dist/llms/google.d.ts +11 -0
  25. package/dist/llms/google.js +44 -0
  26. package/dist/llms/openai.d.ts +9 -0
  27. package/dist/llms/openai.js +73 -0
  28. package/dist/llms/openai_structured.d.ts +11 -0
  29. package/dist/llms/openai_structured.js +72 -0
  30. package/dist/memory/index.d.ts +42 -0
  31. package/dist/memory/index.js +499 -0
  32. package/dist/memory/memory.types.d.ts +23 -0
  33. package/dist/memory/memory.types.js +2 -0
  34. package/dist/prompts/index.d.ts +102 -0
  35. package/dist/prompts/index.js +233 -0
  36. package/dist/storage/DummyHistoryManager.d.ts +7 -0
  37. package/dist/storage/DummyHistoryManager.js +19 -0
  38. package/dist/storage/MemoryHistoryManager.d.ts +8 -0
  39. package/dist/storage/MemoryHistoryManager.js +36 -0
  40. package/dist/storage/base.d.ts +6 -0
  41. package/dist/storage/base.js +2 -0
  42. package/dist/storage/index.d.ts +3 -0
  43. package/dist/storage/index.js +19 -0
  44. package/dist/types/index.d.ts +1071 -0
  45. package/dist/types/index.js +100 -0
  46. package/dist/utils/bm25.d.ts +13 -0
  47. package/dist/utils/bm25.js +51 -0
  48. package/dist/utils/factory.d.ts +13 -0
  49. package/dist/utils/factory.js +49 -0
  50. package/dist/utils/logger.d.ts +7 -0
  51. package/dist/utils/logger.js +9 -0
  52. package/dist/utils/memory.d.ts +3 -0
  53. package/dist/utils/memory.js +44 -0
  54. package/dist/utils/telemetry.d.ts +11 -0
  55. package/dist/utils/telemetry.js +74 -0
  56. package/dist/utils/telemetry.types.d.ts +27 -0
  57. package/dist/utils/telemetry.types.js +2 -0
  58. package/dist/vectorstores/base.d.ts +11 -0
  59. package/dist/vectorstores/base.js +2 -0
  60. package/dist/vectorstores/lite.d.ts +40 -0
  61. package/dist/vectorstores/lite.js +319 -0
  62. package/dist/vectorstores/llm.d.ts +31 -0
  63. package/dist/vectorstores/llm.js +88 -0
  64. package/jest.config.js +22 -0
  65. package/memories-lite.db +0 -0
  66. package/package.json +38 -0
  67. package/src/config/defaults.ts +61 -0
  68. package/src/config/manager.ts +132 -0
  69. package/src/embeddings/base.ts +4 -0
  70. package/src/embeddings/google.ts +32 -0
  71. package/src/embeddings/openai.ts +33 -0
  72. package/src/graphs/configs.ts +30 -0
  73. package/src/graphs/tools.ts +267 -0
  74. package/src/graphs/utils.ts +114 -0
  75. package/src/index.ts +14 -0
  76. package/src/llms/base.ts +20 -0
  77. package/src/llms/google.ts +56 -0
  78. package/src/llms/openai.ts +85 -0
  79. package/src/llms/openai_structured.ts +82 -0
  80. package/src/memory/index.ts +723 -0
  81. package/src/memory/memory.types.ts +27 -0
  82. package/src/prompts/index.ts +268 -0
  83. package/src/storage/DummyHistoryManager.ts +27 -0
  84. package/src/storage/MemoryHistoryManager.ts +58 -0
  85. package/src/storage/base.ts +14 -0
  86. package/src/storage/index.ts +3 -0
  87. package/src/types/index.ts +243 -0
  88. package/src/utils/bm25.ts +64 -0
  89. package/src/utils/factory.ts +59 -0
  90. package/src/utils/logger.ts +13 -0
  91. package/src/utils/memory.ts +48 -0
  92. package/src/utils/telemetry.ts +98 -0
  93. package/src/utils/telemetry.types.ts +34 -0
  94. package/src/vectorstores/base.ts +27 -0
  95. package/src/vectorstores/lite.ts +402 -0
  96. package/src/vectorstores/llm.ts +126 -0
  97. package/tests/lite.spec.ts +158 -0
  98. package/tests/memory.facts.test.ts +211 -0
  99. package/tests/memory.test.ts +406 -0
  100. package/tsconfig.json +16 -0
  101. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,723 @@
1
+ import { v4 as uuidv4 } from "uuid";
2
+ import { createHash } from "crypto";
3
+ import {
4
+ MemoryConfig,
5
+ MemoryConfigSchema,
6
+ MemoryItem,
7
+ MemoryType,
8
+ Message,
9
+ SearchFilters,
10
+ SearchResult,
11
+ VectorStoreConfig,
12
+ } from "../types";
13
+ import {
14
+ EmbedderFactory,
15
+ LLMFactory,
16
+ HistoryManagerFactory,
17
+ } from "../utils/factory";
18
+ import {
19
+ FactRetrievalSchema_extended,
20
+ getFactRetrievalMessages,
21
+ getUpdateMemoryMessages,
22
+ MemoryUpdateSchema,
23
+ removeCodeBlocks,
24
+ } from "../prompts";
25
+ import { DummyHistoryManager } from "../storage/DummyHistoryManager";
26
+ import { Embedder } from "../embeddings/base";
27
+ import { LLM } from "../llms/base";
28
+ import { VectorStore } from "../vectorstores/base";
29
+ import { ConfigManager } from "../config/manager";
30
+ import {
31
+ AddMemoryOptions,
32
+ SearchMemoryOptions,
33
+ DeleteAllMemoryOptions,
34
+ GetAllMemoryOptions,
35
+ } from "./memory.types";
36
+ import { parse_vision_messages } from "../utils/memory";
37
+ import { HistoryManager } from "../storage/base";
38
+ import { captureClientEvent } from "../utils/telemetry";
39
+ import { LiteVectorStore } from "../vectorstores/lite";
40
+ import { zodResponseFormat } from "openai/helpers/zod";
41
+
42
+
43
+ export class MemoriesLite {
44
+ private config: MemoryConfig;
45
+ private customPrompt: string | undefined;
46
+ private embedder: Embedder;
47
+ private vectorStoreConfig: VectorStoreConfig;
48
+ private llm: LLM;
49
+ private db: HistoryManager;
50
+ private collectionName: string | undefined;
51
+ private apiVersion: string;
52
+ private graphMemory?: any;
53
+ private enableGraph: boolean;
54
+ telemetryId: string;
55
+
56
+ constructor(config: Partial<MemoryConfig> = {}) {
57
+ // Merge and validate config
58
+ this.config = ConfigManager.mergeConfig(config);
59
+
60
+ this.customPrompt = this.config.customPrompt;
61
+ this.embedder = EmbedderFactory.create(
62
+ this.config.embedder.provider,
63
+ this.config.embedder.config,
64
+ );
65
+ //
66
+ // vectorStore.provider is "lite"
67
+ this.vectorStoreConfig = this.config.vectorStore.config;
68
+ this.llm = LLMFactory.create(
69
+ this.config.llm.provider,
70
+ this.config.llm.config,
71
+ );
72
+ if (this.config.disableHistory) {
73
+ this.db = new DummyHistoryManager();
74
+ } else {
75
+ const defaultConfig = {
76
+ provider: "sqlite",
77
+ config: {
78
+ historyDbPath: this.config.historyDbPath || ":memory:",
79
+ },
80
+ };
81
+
82
+ this.db =
83
+ this.config.historyStore && !this.config.disableHistory
84
+ ? HistoryManagerFactory.create(
85
+ this.config.historyStore.provider,
86
+ this.config.historyStore,
87
+ )
88
+ : HistoryManagerFactory.create("sqlite", defaultConfig);
89
+ }
90
+
91
+ this.collectionName = this.config.vectorStore.config.collectionName;
92
+ this.apiVersion = this.config.version || "v1.0";
93
+ this.enableGraph = this.config.enableGraph || false;
94
+ this.telemetryId = "anonymous";
95
+
96
+ // Initialize graph memory if configured
97
+ if (this.enableGraph && this.config.graphStore) {
98
+ // this.graphMemory = new MemoryGraph(this.config);
99
+ }
100
+
101
+ // Initialize telemetry if vector store is initialized
102
+ // this._initializeTelemetry();
103
+ }
104
+
105
+ private async _initializeTelemetry() {
106
+ try {
107
+ await this._getTelemetryId();
108
+
109
+ // Capture initialization event
110
+ await captureClientEvent("init", this, {
111
+ api_version: this.apiVersion,
112
+ client_type: "Memory",
113
+ collection_name: this.collectionName,
114
+ enable_graph: this.enableGraph,
115
+ });
116
+ } catch (error) {}
117
+ }
118
+
119
+ private async _getTelemetryId() {
120
+ try {
121
+ if (
122
+ !this.telemetryId ||
123
+ this.telemetryId === "anonymous" ||
124
+ this.telemetryId === "anonymous-supabase"
125
+ ) {
126
+ // this.telemetryId = await this.vectorStore.getUserId();
127
+ throw new Error("Telemetry ID not found");
128
+ }
129
+ return this.telemetryId;
130
+ } catch (error) {
131
+ this.telemetryId = "anonymous";
132
+ return this.telemetryId;
133
+ }
134
+ }
135
+
136
+ private async _captureEvent(methodName: string, additionalData = {}) {
137
+ try {
138
+ await this._getTelemetryId();
139
+ await captureClientEvent(methodName, this, {
140
+ ...additionalData,
141
+ api_version: this.apiVersion,
142
+ collection_name: this.collectionName,
143
+ });
144
+ } catch (error) {
145
+ console.error(`Failed to capture ${methodName} event:`, error);
146
+ }
147
+ }
148
+
149
+ private $t(text:string) {
150
+ // return text.replace(/<thinking>[\s\S]*?(?:<\/thinking>)/g,'').replace(/^<step.*$/g,'');
151
+ return text.replace(/<thinking>[\s\S]*?<\/thinking>/g,'').replace(/^<step.*$/gm,'').replace(/<memories>[\s\S]*?<\/memories>/g, '');
152
+ }
153
+
154
+
155
+ private async addToVectorStore(
156
+ messages: Message[],
157
+ metadata: Record<string, any>,
158
+ userId: string,
159
+ filters: SearchFilters,
160
+ customFacts?: string,
161
+ ): Promise<MemoryItem[]> {
162
+
163
+ const $t = this.$t;
164
+ const vectorStore = await this.getVectorStore(userId);
165
+ const parsedMessages = messages.filter((m) => typeof m.content === 'string').map((m) => `${m.role=='user' ? '**USER**: ' : '**ASSISTANT**: '}${$t(m.content as string)}\n`).join("\n");
166
+
167
+ const [systemPrompt, userPrompt] = getFactRetrievalMessages(parsedMessages, customFacts||this.customPrompt);
168
+
169
+ const response = await this.llm.generateResponse(
170
+ [
171
+ { role: "system", content: systemPrompt },
172
+ { role: "user", content: userPrompt },
173
+ ],
174
+ {...zodResponseFormat(FactRetrievalSchema_extended,"FactRetrieval")},[],false
175
+ );
176
+ const parsedResponse = (response:any) => {
177
+ try {
178
+ // structured output
179
+ if(typeof response === 'object') {
180
+ return response;
181
+ }
182
+ const cleanResponse = removeCodeBlocks(response as string);
183
+ return JSON.parse(cleanResponse);
184
+ } catch (e) {
185
+ console.error(
186
+ "Failed to parse facts from LLM response:",
187
+ response,
188
+ e,
189
+ response
190
+ );
191
+ return [];
192
+ }
193
+ }
194
+ //
195
+ // can use native structured output
196
+ const facts = parsedResponse(response).facts?.filter((f:any) => !f.existing)||[];
197
+
198
+ // console.log("-- DBG extract:", userPrompt);
199
+ // console.log("-- DBG facts:", facts);
200
+
201
+ // Get embeddings for new facts
202
+ const newMessageEmbeddings: Record<string, number[]> = {};
203
+ const retrievedOldMemory: Array<{ id: string; text: string; type: string }> = [];
204
+
205
+ // Create embeddings and search for similar memories
206
+ for (const elem of facts) {
207
+ const fact = elem.fact;
208
+ const embedding = await this.embedder.embed(fact);
209
+ newMessageEmbeddings[fact] = embedding;
210
+
211
+ const existingMemories = await vectorStore.search(
212
+ embedding,
213
+ 5,
214
+ filters,
215
+ );
216
+ for (const mem of existingMemories) {
217
+ retrievedOldMemory.push({ id: mem.id, text: mem.payload.data,type: mem.payload.type });
218
+ }
219
+ }
220
+
221
+ // console.log("-- DBG old memories:", retrievedOldMemory);
222
+ // Remove duplicates from old memories
223
+ const uniqueOldMemories = retrievedOldMemory.filter(
224
+ (mem, index) =>
225
+ retrievedOldMemory.findIndex((m) => m.id === mem.id) === index,
226
+ );
227
+
228
+ // Create UUID mapping for handling UUID hallucinations
229
+ const tempUuidMapping: Record<string, string> = {};
230
+ uniqueOldMemories.forEach((item, idx) => {
231
+ tempUuidMapping[String(idx)] = item.id;
232
+ uniqueOldMemories[idx].id = String(idx);
233
+ });
234
+
235
+ // Get memory update decisions
236
+ const updatePrompt = getUpdateMemoryMessages(uniqueOldMemories, facts);
237
+
238
+ const updateResponse = await this.llm.generateResponse(
239
+ [{ role: "user", content: updatePrompt }],
240
+ {...zodResponseFormat(MemoryUpdateSchema,"Memory")},[],false,
241
+ );
242
+ // console.log("-- DBG merge:", updatePrompt);
243
+
244
+ const memoryActions: any[] = parsedResponse(updateResponse).memory || [];
245
+
246
+ // Process memory actions
247
+ const results: MemoryItem[] = [];
248
+ for (const action of memoryActions) {
249
+ if(action.reason === "undefined") {
250
+ console.log(`-- ⛔ LLM Error: ${action.event}, ${action.type}, "${action.text}"`);
251
+ continue;
252
+ }
253
+ console.log(`-- DBG memory action: ${action.event}, ${action.type}, "${action.text}", why: "${action.reason}"`);
254
+ try {
255
+ switch (action.event) {
256
+ case "ADD": {
257
+ if(!action.type) {
258
+ // log error
259
+ console.error("Type is mandatory to manage memories:", action);
260
+ continue;
261
+ }
262
+ metadata.type = action.type;
263
+ const memoryId = await this.createMemory(
264
+ action.text,
265
+ newMessageEmbeddings,
266
+ metadata,
267
+ userId,
268
+ );
269
+ results.push({
270
+ id: memoryId,
271
+ memory: action.text,
272
+ type: action.type,
273
+ metadata: { event: action.event },
274
+ });
275
+ break;
276
+ }
277
+ case "UPDATE": {
278
+ const realMemoryId = tempUuidMapping[action.id];
279
+ const type = uniqueOldMemories[action.id].type as MemoryType;
280
+ await this.updateMemory(
281
+ realMemoryId,
282
+ action.text,
283
+ newMessageEmbeddings,
284
+ metadata,
285
+ userId,
286
+ );
287
+ results.push({
288
+ id: realMemoryId,
289
+ memory: action.text,
290
+ type,
291
+ metadata: {
292
+ event: action.event,
293
+ previousMemory: action.old_memory,
294
+ },
295
+ });
296
+ break;
297
+ }
298
+ case "DELETE": {
299
+ const realMemoryId = tempUuidMapping[action.id];
300
+ await this.deleteMemory(realMemoryId, userId);
301
+ results.push({
302
+ id: realMemoryId,
303
+ memory: action.text,
304
+ type: action.type,
305
+ metadata: { event: action.event },
306
+ });
307
+ break;
308
+ }
309
+ }
310
+ } catch (error) {
311
+ console.error(`Error processing memory action: ${error}`);
312
+ }
313
+ }
314
+ return results;
315
+ }
316
+
317
+ static fromConfig(configDict: Record<string, any>): MemoriesLite {
318
+ try {
319
+ const config = MemoryConfigSchema.parse(configDict);
320
+ return new MemoriesLite(config);
321
+ } catch (e) {
322
+ console.error("Configuration validation error:", e);
323
+ throw e;
324
+ }
325
+ }
326
+
327
+ async getVectorStore(userId: string): Promise<VectorStore> {
328
+ return LiteVectorStore.from(userId, this.vectorStoreConfig);
329
+ }
330
+
331
+ async capture(
332
+ messages: string | Message[],
333
+ userId: string,
334
+ config: AddMemoryOptions,
335
+ ): Promise<SearchResult> {
336
+ // await this._captureEvent("add", {
337
+ // message_count: Array.isArray(messages) ? messages.length : 1,
338
+ // has_metadata: !!config.metadata,
339
+ // has_filters: !!config.filters,
340
+ // infer: config.infer,
341
+ // });
342
+ const {
343
+ agentId,
344
+ runId,
345
+ metadata = {},
346
+ filters = {},
347
+ infer = true,
348
+ customFacts
349
+ } = config;
350
+
351
+ if (agentId) filters.agentId = metadata.agentId = agentId;
352
+ if (runId) filters.runId = metadata.runId = runId;
353
+
354
+ if (!userId && !filters.agentId && !filters.runId) {
355
+ throw new Error(
356
+ "One of the filters: userId, agentId or runId is required!",
357
+ );
358
+ }
359
+
360
+ const parsedMessages = Array.isArray(messages)
361
+ ? (messages as Message[])
362
+ : [{ role: "user", content: messages }];
363
+
364
+ const final_parsedMessages = await parse_vision_messages(parsedMessages);
365
+
366
+ // Add to vector store
367
+ const vectorStoreResult = await this.addToVectorStore(
368
+ final_parsedMessages,
369
+ metadata,
370
+ userId,
371
+ filters,
372
+ customFacts,
373
+ );
374
+
375
+ // Add to graph store if available
376
+ let graphResult;
377
+ if (this.graphMemory) {
378
+ try {
379
+ graphResult = await this.graphMemory.add(
380
+ final_parsedMessages.map((m) => m.content).join("\n"),
381
+ filters,
382
+ );
383
+ } catch (error) {
384
+ console.error("Error adding to graph memory:", error);
385
+ }
386
+ }
387
+
388
+ return {
389
+ results: vectorStoreResult,
390
+ relations: graphResult?.relations,
391
+ };
392
+ }
393
+
394
+
395
+ async get(memoryId: string, userId: string): Promise<MemoryItem | null> {
396
+ const vectorStore = await this.getVectorStore(userId);
397
+
398
+ const memory = await vectorStore.get(memoryId);
399
+ if (!memory) return null;
400
+
401
+ const filters = {
402
+ ...(memory.payload.agentId && { agentId: memory.payload.agentId }),
403
+ ...(memory.payload.runId && { runId: memory.payload.runId }),
404
+ };
405
+
406
+ const memoryItem: MemoryItem = {
407
+ id: memory.id,
408
+ memory: memory.payload.data,
409
+ type: memory.payload.type,
410
+ hash: memory.payload.hash,
411
+ createdAt: memory.payload.createdAt,
412
+ updatedAt: memory.payload.updatedAt,
413
+ metadata: {},
414
+ };
415
+
416
+
417
+ // Add additional metadata
418
+ const excludedKeys = new Set([
419
+ "userId",
420
+ "agentId",
421
+ "runId",
422
+ "hash",
423
+ "data",
424
+ "createdAt",
425
+ "updatedAt",
426
+ ]);
427
+ for (const [key, value] of Object.entries(memory.payload)) {
428
+ if (!excludedKeys.has(key)) {
429
+ memoryItem.metadata![key] = value;
430
+ }
431
+ }
432
+
433
+ return { ...memoryItem, ...filters };
434
+ }
435
+
436
+ async retrieve(
437
+ query: string,
438
+ userId: string,
439
+ config: SearchMemoryOptions,
440
+ ): Promise<SearchResult> {
441
+ // await this._captureEvent("search", {
442
+ // query_length: query.length,
443
+ // limit: config.limit,
444
+ // has_filters: !!config.filters,
445
+ // });
446
+ const { agentId, runId, limit = 100, filters = {} } = config;
447
+
448
+ if (agentId) filters.agentId = agentId;
449
+ if (runId) filters.runId = runId;
450
+
451
+ if (!userId && !filters.agentId && !filters.runId) {
452
+ throw new Error(
453
+ "One of the filters: userId, agentId or runId is required!",
454
+ );
455
+ }
456
+
457
+ const vectorStore = await this.getVectorStore(userId);
458
+
459
+
460
+ // Search vector store
461
+ const queryEmbedding = await this.embedder.embed(query);
462
+ const memories = await vectorStore.search(
463
+ queryEmbedding,
464
+ limit,
465
+ filters,
466
+ );
467
+
468
+
469
+ // Search graph store if available
470
+ let graphResults =[];
471
+ if (this.graphMemory) {
472
+ try {
473
+ graphResults = await this.graphMemory.search(query, filters);
474
+ } catch (error) {
475
+ console.error("Error searching graph memory:", error);
476
+ }
477
+ }
478
+
479
+ const excludedKeys = new Set([
480
+ "userId",
481
+ "agentId",
482
+ "runId",
483
+ "hash",
484
+ "data",
485
+ "createdAt",
486
+ "updatedAt",
487
+ ]);
488
+ const results = memories.map((mem) => ({
489
+ id: mem.id,
490
+ memory: mem.payload.data,
491
+ hash: mem.payload.hash,
492
+ type: mem.payload.type,
493
+ createdAt: mem.payload.createdAt,
494
+ updatedAt: mem.payload.updatedAt,
495
+ score: mem.score,
496
+ metadata: Object.entries(mem.payload)
497
+ .filter(([key]) => !excludedKeys.has(key))
498
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
499
+ ...(mem.payload.agentId && { agentId: mem.payload.agentId }),
500
+ ...(mem.payload.runId && { runId: mem.payload.runId }),
501
+ }));
502
+
503
+ return {
504
+ results,
505
+ relations: graphResults,
506
+ };
507
+ }
508
+
509
+ async update(memoryId: string, data: string, userId: string): Promise<{ message: string }> {
510
+ // await this._captureEvent("update", { memory_id: memoryId });
511
+ const embedding = await this.embedder.embed(data);
512
+ await this.updateMemory(memoryId, data, { [data]: embedding }, {}, userId);
513
+ return { message: "Memory updated successfully!" };
514
+ }
515
+
516
+ async delete(memoryId: string, userId: string): Promise<{ message: string }> {
517
+ // await this._captureEvent("delete", { memory_id: memoryId });
518
+ await this.deleteMemory(memoryId, userId);
519
+ return { message: "Memory deleted successfully!" };
520
+ }
521
+
522
+ async deleteAll(
523
+ userId: string,
524
+ config: DeleteAllMemoryOptions,
525
+ ): Promise<{ message: string }> {
526
+ // await this._captureEvent("delete_all", {
527
+ // has_user_id: !!config.userId,
528
+ // has_agent_id: !!config.agentId,
529
+ // has_run_id: !!config.runId,
530
+ // });
531
+ const { agentId, runId } = config;
532
+ if (!userId) throw new Error("vector store instanceId is required");
533
+ const vectorStore = await this.getVectorStore(userId);
534
+
535
+ const filters: SearchFilters = {};
536
+ if (agentId) filters.agentId = agentId;
537
+ if (runId) filters.runId = runId;
538
+
539
+ if (!Object.keys(filters).length) {
540
+ throw new Error(
541
+ "At least one filter is required to delete all memories. If you want to delete all memories, use the `reset()` method.",
542
+ );
543
+ }
544
+
545
+ const [memories] = await vectorStore.list(filters);
546
+ for (const memory of memories) {
547
+ await this.deleteMemory(memory.id, userId!);
548
+ }
549
+
550
+ return { message: "Memories deleted successfully!" };
551
+ }
552
+
553
+ //
554
+ // DEPRECATED: history must be user specific
555
+ async history(memoryId: string): Promise<any[]> {
556
+ return this.db.getHistory(memoryId);
557
+ }
558
+
559
+ async reset(userId: string): Promise<void> {
560
+ // await this._captureEvent("reset");
561
+ const vectorStore = await this.getVectorStore(userId);
562
+ await this.db.reset();
563
+
564
+ // Check provider before attempting deleteCol
565
+ await vectorStore.deleteCol();
566
+
567
+ if (this.graphMemory) {
568
+ await this.graphMemory.deleteAll({ userId: "default" }); // Assuming this is okay, or needs similar check?
569
+ }
570
+
571
+ // Re-initialize factories/clients based on the original config
572
+ this.embedder = EmbedderFactory.create(
573
+ this.config.embedder.provider,
574
+ this.config.embedder.config,
575
+ );
576
+ this.llm = LLMFactory.create(
577
+ this.config.llm.provider,
578
+ this.config.llm.config,
579
+ );
580
+ // Re-init DB if needed (though db.reset() likely handles its state)
581
+ // Re-init Graph if needed
582
+
583
+ // Re-initialize telemetry
584
+ // this._initializeTelemetry();
585
+ }
586
+
587
+ async getAll(userId: string, config: GetAllMemoryOptions): Promise<SearchResult> {
588
+ // await this._captureEvent("get_all", {
589
+ // limit: config.limit,
590
+ // has_agent_id: !!config.agentId,
591
+ // has_run_id: !!config.runId,
592
+ // });
593
+ const { agentId, runId, limit = 10, type } = config;
594
+ const vectorStore = await this.getVectorStore(userId!);
595
+
596
+ const filters: SearchFilters = {};
597
+ if (agentId) filters.agentId = agentId;
598
+ if (runId) filters.runId = runId;
599
+ if (type) filters.type = type;
600
+ const [memories] = await vectorStore.list(filters, limit);
601
+
602
+ const excludedKeys = new Set([
603
+ "userId",
604
+ "agentId",
605
+ "runId",
606
+ "hash",
607
+ "data",
608
+ "createdAt",
609
+ "updatedAt",
610
+ ]);
611
+ const results = memories.map((mem) => ({
612
+ id: mem.id,
613
+ memory: mem.payload.data,
614
+ hash: mem.payload.hash,
615
+ type: mem.payload.type,
616
+ createdAt: mem.payload.createdAt,
617
+ updatedAt: mem.payload.updatedAt,
618
+ metadata: Object.entries(mem.payload)
619
+ .filter(([key]) => !excludedKeys.has(key))
620
+ .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
621
+ ...(mem.payload.agentId && { agentId: mem.payload.agentId }),
622
+ ...(mem.payload.runId && { runId: mem.payload.runId }),
623
+ }));
624
+
625
+ return { results };
626
+ }
627
+
628
+ private async createMemory(
629
+ data: string,
630
+ existingEmbeddings: Record<string, number[]>,
631
+ metadata: Record<string, any>,
632
+ userId: string,
633
+ ): Promise<string> {
634
+ const vectorStore = await this.getVectorStore(userId);
635
+ const memoryId = uuidv4();
636
+ const embedding =
637
+ existingEmbeddings[data] || (await this.embedder.embed(data));
638
+
639
+ const memoryMetadata = {
640
+ ...metadata,
641
+ data,
642
+ hash: createHash("md5").update(data).digest("hex"),
643
+ createdAt: new Date().toISOString(),
644
+ };
645
+
646
+ await vectorStore.insert([embedding], [memoryId], [memoryMetadata]);
647
+ await this.db.addHistory(
648
+ memoryId,
649
+ null,
650
+ data,
651
+ "ADD",
652
+ memoryMetadata.createdAt,
653
+ );
654
+
655
+ return memoryId;
656
+ }
657
+
658
+ private async updateMemory(
659
+ memoryId: string,
660
+ data: string,
661
+ existingEmbeddings: Record<string, number[]>,
662
+ metadata: Record<string, any> = {},
663
+ userId: string,
664
+ ): Promise<string> {
665
+ const vectorStore = await this.getVectorStore(userId);
666
+ const existingMemory = await vectorStore.get(memoryId);
667
+ if (!existingMemory) {
668
+ throw new Error(`Memory with ID ${memoryId} not found`);
669
+ }
670
+
671
+ const prevValue = existingMemory.payload.data;
672
+ const embedding =
673
+ existingEmbeddings[data] || (await this.embedder.embed(data));
674
+
675
+ const newMetadata = {
676
+ ...metadata,
677
+ data,
678
+ hash: createHash("md5").update(data).digest("hex"),
679
+ createdAt: existingMemory.payload.createdAt,
680
+ updatedAt: new Date().toISOString(),
681
+ ...(existingMemory.payload.agentId && {
682
+ agentId: existingMemory.payload.agentId,
683
+ }),
684
+ ...(existingMemory.payload.runId && {
685
+ runId: existingMemory.payload.runId,
686
+ }),
687
+ };
688
+
689
+ await vectorStore.update(memoryId, embedding, newMetadata);
690
+ await this.db.addHistory(
691
+ memoryId,
692
+ prevValue,
693
+ data,
694
+ "UPDATE",
695
+ newMetadata.createdAt,
696
+ newMetadata.updatedAt,
697
+ );
698
+
699
+ return memoryId;
700
+ }
701
+
702
+ private async deleteMemory(memoryId: string, userId: string): Promise<string> {
703
+ const vectorStore = await this.getVectorStore(userId);
704
+ const existingMemory = await vectorStore.get(memoryId);
705
+ if (!existingMemory) {
706
+ throw new Error(`Memory with ID ${memoryId} not found`);
707
+ }
708
+
709
+ const prevValue = existingMemory.payload.data;
710
+ await vectorStore.delete(memoryId);
711
+ await this.db.addHistory(
712
+ memoryId,
713
+ prevValue,
714
+ null,
715
+ "DELETE",
716
+ undefined,
717
+ undefined,
718
+ 1,
719
+ );
720
+
721
+ return memoryId;
722
+ }
723
+ }