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,319 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LiteVectorStore = void 0;
7
+ // vector persistence
8
+ const path_1 = __importDefault(require("path"));
9
+ const sqlite3_1 = __importDefault(require("sqlite3"));
10
+ const crypto_1 = require("crypto");
11
+ /**
12
+ * LiteVectorStore provides a simple vector storage implementation.
13
+ *
14
+ * This class manages user-sensitive vector data, with each instance tied to a specific user.
15
+ * Data is stored in a local SQLite database with appropriate isolation between users.
16
+ * The user's identity is hashed for privacy and security purposes.
17
+ * ⚠️ User memories are typically small (usually <1000 vectors), therefore database optimization is not a priority.
18
+ *
19
+ * @implements {VectorStore}
20
+ */
21
+ class LiteVectorStore {
22
+ constructor(config, currentUserId) {
23
+ if (!config.scoring) {
24
+ throw new Error("Scoring configuration is missing in VectorStoreConfig");
25
+ }
26
+ this.dimension = config.dimension || 1536;
27
+ this.currentUserId = currentUserId;
28
+ this.isSecure = config.secure || false;
29
+ this.scoringConfig = config.scoring;
30
+ this.cleanupThreshold = config.recencyCleanupThreshold; // Store threshold
31
+ config.rootPath = config.rootPath || process.cwd();
32
+ const filename = this.isSecure ? `memories-lite-${currentUserId}.db` : `memories-lite-global.db`;
33
+ const dbPath = (config.rootPath == ':memory:') ? ':memory:' : path_1.default.join(config.rootPath, filename);
34
+ // Add error handling callback for the database connection
35
+ this.db = new sqlite3_1.default.Database(dbPath);
36
+ }
37
+ async init() {
38
+ await this.run(`
39
+ CREATE TABLE IF NOT EXISTS vectors (
40
+ id TEXT PRIMARY KEY,
41
+ vector BLOB NOT NULL,
42
+ payload TEXT NOT NULL
43
+ )
44
+ `);
45
+ await this.run(`
46
+ CREATE TABLE IF NOT EXISTS memory_migrations (
47
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
48
+ user_id TEXT NOT NULL UNIQUE
49
+ )
50
+ `);
51
+ }
52
+ async run(sql, params = []) {
53
+ return new Promise((resolve, reject) => {
54
+ this.db.run(sql, params, (err) => {
55
+ if (err)
56
+ reject(err);
57
+ else
58
+ resolve();
59
+ });
60
+ });
61
+ }
62
+ async all(sql, params = []) {
63
+ return new Promise((resolve, reject) => {
64
+ this.db.all(sql, params, (err, rows) => {
65
+ if (err)
66
+ reject(err);
67
+ else
68
+ resolve(rows);
69
+ });
70
+ });
71
+ }
72
+ async getOne(sql, params = []) {
73
+ return new Promise((resolve, reject) => {
74
+ this.db.get(sql, params, (err, row) => {
75
+ if (err)
76
+ reject(err);
77
+ else
78
+ resolve(row);
79
+ });
80
+ });
81
+ }
82
+ //
83
+ // TODO: Memory Decay & Hybrid Scoring (α·cosSim + β·when + γ·1 [+ δ·tag])
84
+ // scoreTotal = α·cos + β·recency + γ·1 + δ·tag
85
+ // https://chatgpt.com/g/g-p-677932764d20819181f8805995ddab8b-the-coder/c/68121341-7fdc-800b-8734-af49719eb5e1
86
+ cosineSimilarity(a, b) {
87
+ if (a.length !== b.length) {
88
+ throw new Error("Vectors must have the same dimension for cosine similarity.");
89
+ }
90
+ if (a.length === 0) {
91
+ return 0;
92
+ }
93
+ let dotProduct = 0;
94
+ let normA = 0;
95
+ let normB = 0;
96
+ for (let i = 0; i < a.length; i++) {
97
+ dotProduct += a[i] * b[i];
98
+ normA += a[i] * a[i];
99
+ normB += b[i] * b[i];
100
+ }
101
+ const magnitudeA = Math.sqrt(normA);
102
+ const magnitudeB = Math.sqrt(normB);
103
+ if (magnitudeA === 0 || magnitudeB === 0) {
104
+ return 0;
105
+ }
106
+ return dotProduct / (magnitudeA * magnitudeB);
107
+ }
108
+ filterVector(vector, filters) {
109
+ if (!filters)
110
+ return true;
111
+ return Object.entries(filters).every(([key, value]) => vector.payload && vector.payload[key] === value);
112
+ }
113
+ // by default, the userId is the SHA256 derivation
114
+ getInstanceId() {
115
+ return this.currentUserId;
116
+ }
117
+ static async from(userId, config) {
118
+ if (!userId) {
119
+ throw new Error("userId is required");
120
+ }
121
+ if (!config.scoring) {
122
+ throw new Error("Scoring configuration is missing in VectorStoreConfig");
123
+ }
124
+ const hashedUserId = (0, crypto_1.createHash)('sha256').update(userId).digest('hex');
125
+ if (!LiteVectorStore.cache) {
126
+ LiteVectorStore.cache = new Map();
127
+ }
128
+ const cachedStore = LiteVectorStore.cache.get(hashedUserId);
129
+ if (cachedStore) {
130
+ Object.setPrototypeOf(cachedStore, LiteVectorStore.prototype);
131
+ cachedStore.currentUserId = hashedUserId;
132
+ // Ensure scoring config and threshold are updated if config object changed
133
+ cachedStore.scoringConfig = config.scoring;
134
+ cachedStore.cleanupThreshold = config.recencyCleanupThreshold;
135
+ return cachedStore;
136
+ }
137
+ // Pass the full config (including scoring) to the constructor
138
+ const newStore = new LiteVectorStore(config, hashedUserId);
139
+ await newStore.init();
140
+ LiteVectorStore.cache.set(hashedUserId, newStore);
141
+ return newStore;
142
+ }
143
+ async insert(vectors, ids, payloads) {
144
+ for (let i = 0; i < vectors.length; i++) {
145
+ if (vectors[i].length !== this.dimension) {
146
+ throw new Error(`Vector dimension mismatch. Expected ${this.dimension}, got ${vectors[i].length}`);
147
+ }
148
+ //
149
+ // remove the userId from the payload as sensitive data
150
+ this.isSecure && delete payloads[i].userId;
151
+ const vectorBuffer = Buffer.from(new Float32Array(vectors[i]).buffer);
152
+ await this.run(`INSERT OR REPLACE INTO vectors (id, vector, payload) VALUES (?, ?, ?)`, [ids[i], vectorBuffer, JSON.stringify(payloads[i])]);
153
+ }
154
+ }
155
+ async search(query, limit = 10, filters) {
156
+ if (query.length !== this.dimension) {
157
+ throw new Error(`Query dimension mismatch. Expected ${this.dimension}, got ${query.length}`);
158
+ }
159
+ const results = [];
160
+ const rows = await this.all(`SELECT * FROM vectors`);
161
+ for (const row of rows) {
162
+ const vector = Array.from(new Float32Array(row.vector.buffer)); // Convert buffer to number array
163
+ const payload = JSON.parse(row.payload);
164
+ const memoryVector = {
165
+ id: row.id,
166
+ vector: vector,
167
+ payload,
168
+ };
169
+ if (this.filterVector(memoryVector, filters)) {
170
+ const cosineScore = this.cosineSimilarity(query, vector);
171
+ const hybridScore = this.calculateHybridScore(cosineScore, payload);
172
+ results.push({
173
+ id: memoryVector.id,
174
+ payload: memoryVector.payload,
175
+ score: hybridScore,
176
+ });
177
+ }
178
+ }
179
+ results.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
180
+ const finalResults = results.slice(0, limit);
181
+ // Trigger cleanup after search, if threshold is set
182
+ if (this.cleanupThreshold !== undefined && this.cleanupThreshold >= 0) {
183
+ // Run cleanup asynchronously in the background (fire and forget)
184
+ // to avoid delaying the search response.
185
+ // Consider adding mutex or debouncing in high-frequency scenarios.
186
+ this._cleanupByRecency(this.cleanupThreshold).catch(err => {
187
+ console.error("Error during background recency cleanup:", err);
188
+ });
189
+ }
190
+ return finalResults;
191
+ }
192
+ async get(vectorId) {
193
+ const row = await this.getOne(`SELECT * FROM vectors WHERE id = ?`, [
194
+ vectorId,
195
+ ]);
196
+ if (!row)
197
+ return null;
198
+ const payload = JSON.parse(row.payload);
199
+ return {
200
+ id: row.id,
201
+ payload,
202
+ };
203
+ }
204
+ async update(vectorId, vector, payload) {
205
+ if (vector.length !== this.dimension) {
206
+ throw new Error(`Vector dimension mismatch. Expected ${this.dimension}, got ${vector.length}`);
207
+ }
208
+ //
209
+ // remove the userId from the payload as sensitive data
210
+ this.isSecure && delete payload.userId;
211
+ const vectorBuffer = Buffer.from(new Float32Array(vector).buffer);
212
+ await this.run(`UPDATE vectors SET vector = ?, payload = ? WHERE id = ?`, [
213
+ vectorBuffer,
214
+ JSON.stringify(payload),
215
+ vectorId,
216
+ ]);
217
+ }
218
+ async delete(vectorId) {
219
+ await this.run(`DELETE FROM vectors WHERE id = ?`, [vectorId]);
220
+ }
221
+ async deleteCol() {
222
+ await this.run(`DROP TABLE IF EXISTS vectors`);
223
+ await this.init();
224
+ }
225
+ async list(filters, limit = 100) {
226
+ const rows = await this.all(`SELECT * FROM vectors`);
227
+ const results = [];
228
+ for (const row of rows) {
229
+ const memoryVector = {
230
+ id: row.id,
231
+ vector: Array.from(new Float32Array(row.vector.buffer)),
232
+ payload: {},
233
+ };
234
+ if (this.filterVector(memoryVector, filters)) {
235
+ // load payload at the end
236
+ results.push({
237
+ id: memoryVector.id,
238
+ payload: JSON.parse(row.payload),
239
+ });
240
+ }
241
+ }
242
+ return [results.slice(0, limit), results.length];
243
+ }
244
+ // Calculate recency score using exponential decay
245
+ calculateRecencyScore(createdAt, halfLifeDays) {
246
+ if (halfLifeDays === Infinity || !createdAt) {
247
+ return 1.0; // No decay or no date
248
+ }
249
+ if (halfLifeDays <= 0) {
250
+ return 0.0; // Instant decay
251
+ }
252
+ const createdAtDate = new Date(createdAt);
253
+ if (isNaN(createdAtDate.getTime())) {
254
+ console.warn('Invalid createdAt date format:', createdAt);
255
+ return 0.5; // Neutral score if date is invalid
256
+ }
257
+ const now = new Date();
258
+ const ageInMilliseconds = now.getTime() - createdAtDate.getTime();
259
+ const ageInDays = ageInMilliseconds / (1000 * 60 * 60 * 24);
260
+ if (ageInDays < 0) {
261
+ console.warn('createdAt date is in the future:', createdAt);
262
+ return 1.0; // Treat future dates as brand new
263
+ }
264
+ const lambda = Math.log(2) / halfLifeDays;
265
+ return Math.exp(-lambda * ageInDays);
266
+ }
267
+ // Hybrid Scoring: Combines Cosine Similarity, Recency, and Base Importance
268
+ calculateHybridScore(cosineScore, payload) {
269
+ const memoryType = payload.type;
270
+ const createdAt = payload.createdAt; // Expecting ISO string
271
+ // Get scoring parameters for the memory type or use default
272
+ const typeConfig = memoryType ? this.scoringConfig[memoryType] : this.scoringConfig.default;
273
+ const { alpha, beta, gamma, halfLifeDays } = typeConfig || this.scoringConfig.default;
274
+ const recencyScore = this.calculateRecencyScore(createdAt, halfLifeDays);
275
+ // Calculate final score
276
+ // scoreTotal = α * cosSim + β * recency + γ * baseImportance (using 1 as base)
277
+ const hybridScore = alpha * cosineScore + beta * recencyScore + gamma;
278
+ // Ensure score is within a reasonable range (e.g., 0 to alpha+beta+gamma)
279
+ return Math.max(0, hybridScore);
280
+ }
281
+ // Internal method to clean up vectors based on recency score threshold
282
+ async _cleanupByRecency(threshold) {
283
+ const rows = await this.all(`SELECT id, payload FROM vectors`);
284
+ let deletedCount = 0;
285
+ const idsToDelete = [];
286
+ for (const row of rows) {
287
+ try {
288
+ const payload = JSON.parse(row.payload);
289
+ const memoryType = payload.type;
290
+ const createdAt = payload.createdAt;
291
+ // Get halfLifeDays for the type or use default
292
+ const typeConfig = memoryType ? this.scoringConfig[memoryType] : this.scoringConfig.default;
293
+ const { halfLifeDays } = typeConfig || this.scoringConfig.default;
294
+ // Calculate current recency score
295
+ const recencyScore = this.calculateRecencyScore(createdAt, halfLifeDays);
296
+ // Mark for deletion if score is below threshold
297
+ // Add extra check for halfLifeDays > 0 to avoid deleting permanent items instantly if threshold is 0
298
+ if (recencyScore < threshold && halfLifeDays > 0) {
299
+ // Optional: Add type-specific exceptions (e.g., never delete 'factual')
300
+ // if (payload.type !== 'factual') {
301
+ idsToDelete.push(row.id);
302
+ // }
303
+ }
304
+ }
305
+ catch (error) {
306
+ console.error(`Error processing vector ${row.id} for cleanup:`, error);
307
+ // Optionally delete vectors with bad payload/date based on policy
308
+ }
309
+ }
310
+ if (idsToDelete.length > 0) {
311
+ const placeholders = idsToDelete.map(() => '?').join(',');
312
+ await this.run(`DELETE FROM vectors WHERE id IN (${placeholders})`, idsToDelete);
313
+ deletedCount = idsToDelete.length;
314
+ console.log(`Recency Cleanup: Removed ${deletedCount} vectors with score < ${threshold}.`);
315
+ }
316
+ return deletedCount;
317
+ }
318
+ }
319
+ exports.LiteVectorStore = LiteVectorStore;
@@ -0,0 +1,31 @@
1
+ import { VectorStore } from './base';
2
+ import { SearchFilters, VectorStoreConfig, VectorStoreResult } from '../types';
3
+ export interface FakeVectorStore extends VectorStore {
4
+ lookup(query: string, limit?: number, filters?: SearchFilters): Promise<VectorStoreResult[]>;
5
+ dump(filePath?: string, userId?: string): Promise<void>;
6
+ load(filePath?: string, userId?: string): Promise<void>;
7
+ }
8
+ interface MemoryVector {
9
+ id: string;
10
+ vector: number[];
11
+ payload: Record<string, any>;
12
+ }
13
+ export declare class LLMVectorStore implements FakeVectorStore {
14
+ constructor(config?: VectorStoreConfig);
15
+ dump(filePath?: string, userId?: string): Promise<void>;
16
+ load(filePath?: string, userId?: string): Promise<void>;
17
+ add(record: MemoryVector, userId?: string): Promise<string>;
18
+ search(query: number[], limit?: number, filters?: SearchFilters): Promise<VectorStoreResult[]>;
19
+ lookup(query: string, limit?: number, filters?: SearchFilters): Promise<VectorStoreResult[]>;
20
+ get(id: string, userId?: string): Promise<MemoryVector | null>;
21
+ update(vectorId: string, vector: number[], payload: Record<string, any>): Promise<void>;
22
+ delete(id: string, userId?: string): Promise<void>;
23
+ reset(userId?: string): Promise<void>;
24
+ insert(vectors: number[][], ids: string[], payloads: Record<string, any>[]): Promise<void>;
25
+ deleteCol(userId?: string): Promise<void>;
26
+ list(filters?: SearchFilters, limit?: number): Promise<[VectorStoreResult[], number]>;
27
+ getInstanceId(): string;
28
+ setUserId(userId: string): Promise<void>;
29
+ initialize(): Promise<void>;
30
+ }
31
+ export {};
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LLMVectorStore = void 0;
4
+ // Removed fs and path imports as they are not needed for empty methods
5
+ class LLMVectorStore {
6
+ constructor(config) {
7
+ console.log('LLMVectorStore initialized', config);
8
+ // Initialization logic based on config, if any
9
+ }
10
+ async dump(filePath, userId) {
11
+ // TODO: Implement LLMVectorStore dump logic
12
+ console.log('LLMVectorStore dump called for:', userId || 'all users', 'to path:', filePath);
13
+ // Placeholder implementation
14
+ }
15
+ async load(filePath, userId) {
16
+ // TODO: Implement LLMVectorStore load logic
17
+ console.log('LLMVectorStore load called for:', userId || 'all users', 'from path:', filePath);
18
+ // Placeholder implementation
19
+ }
20
+ async add(record, userId) {
21
+ // TODO: Implement LLMVectorStore add logic
22
+ console.log('LLMVectorStore add called with:', record, userId);
23
+ return 'placeholder-id'; // Placeholder return
24
+ }
25
+ async search(query, limit, filters) {
26
+ return [];
27
+ }
28
+ async lookup(query, limit, filters) {
29
+ // TODO: Implement LLMVectorStore search logic using query vector
30
+ // Note: userId parameter is removed as it's not in the base interface signature.
31
+ // If userId is needed, it might have to be passed via filters or managed differently.
32
+ console.log('LLMVectorStore search called with vector query:', query, 'limit:', limit, 'filters:', filters);
33
+ // Linter error on VectorStoreResult likely means its definition in ../types.ts needs checking/creation.
34
+ return []; // Placeholder return
35
+ }
36
+ async get(id, userId) {
37
+ // TODO: Implement LLMVectorStore get logic
38
+ console.log('LLMVectorStore get called with:', id, userId);
39
+ return null; // Placeholder return
40
+ }
41
+ async update(vectorId, vector, payload) {
42
+ // TODO: Implement LLMVectorStore update logic matching the base interface
43
+ console.log('LLMVectorStore update called with:', vectorId, vector, payload);
44
+ // Placeholder implementation
45
+ }
46
+ async delete(id, userId) {
47
+ // TODO: Implement LLMVectorStore delete logic
48
+ console.log('LLMVectorStore delete called with:', id, userId);
49
+ // Placeholder implementation
50
+ }
51
+ async reset(userId) {
52
+ // TODO: Implement LLMVectorStore reset logic
53
+ console.log('LLMVectorStore reset called for:', userId || 'all users');
54
+ // Placeholder implementation
55
+ }
56
+ // TODO: Implement other missing methods from base VectorStore interface if needed
57
+ // Placeholder for missing method from VectorStore interface
58
+ async insert(vectors, ids, payloads) {
59
+ // TODO: Implement LLMVectorStore insert logic
60
+ }
61
+ // Placeholder for missing method from VectorStore interface
62
+ async deleteCol(userId) {
63
+ // TODO: Implement LLMVectorStore deleteCol logic
64
+ console.log('LLMVectorStore deleteCol called for:', userId || 'default collection');
65
+ }
66
+ // Placeholder for missing method from VectorStore interface
67
+ async list(filters, limit) {
68
+ // TODO: Implement LLMVectorStore list logic
69
+ return [[], 0];
70
+ }
71
+ // Placeholder for missing method from VectorStore interface
72
+ getInstanceId() {
73
+ // TODO: Implement LLMVectorStore getUserId logic (if applicable to this store)
74
+ console.log('LLMVectorStore getUserId called');
75
+ return 'placeholder-user-id'; // Or null if not managed per-user this way
76
+ }
77
+ // Placeholder for missing method from VectorStore interface
78
+ async setUserId(userId) {
79
+ // TODO: Implement LLMVectorStore setUserId logic (if applicable)
80
+ console.log('LLMVectorStore setUserId called with:', userId);
81
+ }
82
+ // Placeholder for missing method from VectorStore interface
83
+ async initialize() {
84
+ // TODO: Implement LLMVectorStore initialize logic (if needed)
85
+ console.log('LLMVectorStore initialize called');
86
+ }
87
+ }
88
+ exports.LLMVectorStore = LLMVectorStore;
package/jest.config.js ADDED
@@ -0,0 +1,22 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} **/
2
+ module.exports = {
3
+ verbose: true,
4
+ testEnvironment: "node",
5
+ transform: {
6
+ "^.+.ts?$": ["ts-jest",{}],
7
+ },
8
+ // Désactiver l'exécution parallèle des tests
9
+ maxWorkers: 1,
10
+ // Exécuter un seul fichier de test à la fois
11
+ maxConcurrency: 1,
12
+ testTimeout: 100000,
13
+ collectCoverage: false,
14
+ coverageDirectory: 'coverage',
15
+ collectCoverageFrom: [
16
+ 'src/**/*.ts',
17
+ '!src/**/*.d.ts',
18
+ '!src/**/*.test.ts',
19
+ '!src/__tests__/**/*.ts'
20
+ ],
21
+
22
+ };
Binary file
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "memories-lite",
3
+ "version": "0.9.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "scripts": {
7
+ "build": "tsc -b",
8
+ "test": "jest"
9
+ },
10
+ "dependencies": {
11
+ "@anthropic-ai/sdk": "^0.18.0",
12
+ "@google/genai": "^0.7.0",
13
+ "@keyv/sqlite": "^4.0.3",
14
+ "@types/node": "^20.11.19",
15
+ "@types/uuid": "^9.0.8",
16
+ "cache-manager": "^6.4.2",
17
+ "dotenv": "^16.5.0",
18
+ "keyv": "^5.3.3",
19
+ "openai": "^4.96.0",
20
+ "sqlite3": "^5.1.7",
21
+ "uuid": "^9.0.1",
22
+ "zod": "^3.24.3"
23
+ },
24
+ "devDependencies": {
25
+ "@types/jest": "^29.5.12",
26
+ "jest": "^29.7.0",
27
+ "ts-jest": "^29.2.5",
28
+ "ts-node": "^10.9.2",
29
+ "typescript": "^5.4.0"
30
+ },
31
+ "keywords": [
32
+ "memory",
33
+ "openai",
34
+ "embeddings",
35
+ "vector-store",
36
+ "typescript"
37
+ ]
38
+ }
@@ -0,0 +1,61 @@
1
+ import { MemoryConfig, MemoryScoringConfig } from "../types";
2
+
3
+ const DEFAULT_SCORING_CONFIG: MemoryScoringConfig = {
4
+ // Values from memories-lite rule & user request
5
+ procedural: { alpha: 0.30, beta: 0.40, gamma: 0.05, halfLifeDays: 1 / 24 }, // ~1 hour
6
+ episodic: { alpha: 0.40, beta: 0.50, gamma: 0.10, halfLifeDays: 2 }, // ~2 days (user request 'temporary')
7
+ factual: { alpha: 0.70, beta: 0.20, gamma: 0.10, halfLifeDays: 365 },
8
+ semantic: { alpha: 0.50, beta: 0.25, gamma: 0.25, halfLifeDays: 120 },
9
+ assistant_preference: { alpha: 0.60, beta: 0.05, gamma: 0.35, halfLifeDays: Infinity },
10
+ default: { alpha: 0.5, beta: 0.3, gamma: 0.1, halfLifeDays: 30 } // Fallback default
11
+ };
12
+
13
+ export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
14
+ disableHistory: true,
15
+ enableGraph: false,
16
+ version: "v1.1",
17
+ embedder: {
18
+ provider: "openai",
19
+ config: {
20
+ dimension: 768,
21
+ apiKey: process.env.OPENAI_API_KEY || "",
22
+ model: "text-embedding-3-small",
23
+ },
24
+ },
25
+ vectorStore: {
26
+ provider: "lite",
27
+ config: {
28
+ collectionName: "memories",
29
+ dimension: 768,
30
+ scoring: DEFAULT_SCORING_CONFIG,
31
+ },
32
+ },
33
+ llm: {
34
+ provider: "openai",
35
+ config: {
36
+ apiKey: process.env.OPENAI_API_KEY || "",
37
+ model: "gpt-4o-mini",
38
+ modelProperties: undefined,
39
+ },
40
+ },
41
+ graphStore: {
42
+ provider: "neo4j",
43
+ config: {
44
+ url: process.env.NEO4J_URL || "neo4j://localhost:7687",
45
+ username: process.env.NEO4J_USERNAME || "neo4j",
46
+ password: process.env.NEO4J_PASSWORD || "password",
47
+ },
48
+ llm: {
49
+ provider: "openai",
50
+ config: {
51
+ model: "gpt-4o-mini",
52
+ },
53
+ },
54
+ },
55
+ historyStore: {
56
+ provider: "dummy",
57
+ config: {
58
+ historyDbPath: "memory.db",
59
+ },
60
+ },
61
+ };