memories-lite 0.99.2 → 0.99.3

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.
@@ -33,7 +33,7 @@ export declare class MemoriesLite {
33
33
  capture(messages: string | Message[], userId: string, config: AddMemoryOptions): Promise<SearchResult>;
34
34
  get(memoryId: string, userId: string): Promise<MemoryItem | null>;
35
35
  retrieve(query: string, userId: string, config: SearchMemoryOptions): Promise<SearchResult>;
36
- update(memoryId: string, data: string, userId: string): Promise<{
36
+ update(memoryId: string, data: string, userId: string, metadata?: Record<string, any>): Promise<{
37
37
  message: string;
38
38
  }>;
39
39
  delete(memoryId: string, userId: string): Promise<{
@@ -271,10 +271,10 @@ class MemoriesLite {
271
271
  results,
272
272
  };
273
273
  }
274
- async update(memoryId, data, userId) {
274
+ async update(memoryId, data, userId, metadata = {}) {
275
275
  // await this._captureEvent("update", { memory_id: memoryId });
276
276
  const embedding = await this.embedder.embed(data);
277
- await this.updateMemory(memoryId, data, { [data]: embedding }, {}, userId);
277
+ await this.updateMemory(memoryId, data, { [data]: embedding }, metadata, userId);
278
278
  return { message: "Memory updated successfully!" };
279
279
  }
280
280
  async delete(memoryId, userId) {
@@ -388,20 +388,21 @@ class MemoriesLite {
388
388
  throw new Error(`Memory with ID ${memoryId} not found`);
389
389
  }
390
390
  const prevValue = existingMemory.payload.data;
391
+ const originalPayload = (existingMemory.payload ?? {});
391
392
  const embedding = existingEmbeddings[data] || (await this.embedder.embed(data));
393
+ //
394
+ // Preserve origin fields to avoid corrupting ownership/linkage (discussionId/userId/agentId).
395
+ // - title: keep original unless explicitly changed
396
+ // - discussionId, userId, agentId/runId: always keep original
397
+ const title = (typeof metadata.title === "string" && metadata.title.trim())
398
+ ? metadata.title.trim()
399
+ : originalPayload.title;
392
400
  const newMetadata = {
393
- ...metadata,
401
+ ...originalPayload,
394
402
  data,
395
403
  hash: (0, crypto_1.createHash)("md5").update(data).digest("hex"),
396
- type: existingMemory.payload.type,
397
- createdAt: existingMemory.payload.createdAt,
398
404
  updatedAt: new Date().toISOString(),
399
- ...(existingMemory.payload.agentId && {
400
- agentId: existingMemory.payload.agentId,
401
- }),
402
- ...(existingMemory.payload.runId && {
403
- runId: existingMemory.payload.runId,
404
- }),
405
+ title: title,
405
406
  };
406
407
  await vectorStore.update(memoryId, embedding, newMetadata);
407
408
  await this.db.addHistory(memoryId, prevValue, data, "UPDATE", newMetadata.createdAt, newMetadata.updatedAt);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memories-lite",
3
- "version": "0.99.2",
3
+ "version": "0.99.3",
4
4
  "description": "A lightweight memory system for LLM agents",
5
5
  "author": "olivier@evaletolab.ch",
6
6
  "main": "dist/index.js",
@@ -228,7 +228,7 @@ export class MemoriesLite {
228
228
  console.log(`-- 🧠 Memory created: "${title}" (${memoryType})`);
229
229
 
230
230
  return [{
231
- id: memoryId,
231
+ id: memoryId,
232
232
  memory: summary,
233
233
  type: memoryType,
234
234
  metadata: { title, event: "ADD" },
@@ -292,7 +292,7 @@ export class MemoriesLite {
292
292
  userId,
293
293
  filters,
294
294
  capturePrompt,
295
- );
295
+ );
296
296
 
297
297
  return {
298
298
  results: vectorStoreResult,
@@ -403,10 +403,15 @@ export class MemoriesLite {
403
403
  };
404
404
  }
405
405
 
406
- async update(memoryId: string, data: string, userId: string): Promise<{ message: string }> {
406
+ async update(
407
+ memoryId: string,
408
+ data: string,
409
+ userId: string,
410
+ metadata: Record<string, any> = {},
411
+ ): Promise<{ message: string }> {
407
412
  // await this._captureEvent("update", { memory_id: memoryId });
408
413
  const embedding = await this.embedder.embed(data);
409
- await this.updateMemory(memoryId, data, { [data]: embedding }, {}, userId);
414
+ await this.updateMemory(memoryId, data, { [data]: embedding }, metadata, userId);
410
415
  return { message: "Memory updated successfully!" };
411
416
  }
412
417
 
@@ -564,22 +569,24 @@ export class MemoriesLite {
564
569
  }
565
570
 
566
571
  const prevValue = existingMemory.payload.data;
572
+ const originalPayload: Record<string, any> = (existingMemory.payload ?? {}) as Record<string, any>;
567
573
  const embedding =
568
574
  existingEmbeddings[data] || (await this.embedder.embed(data));
569
575
 
570
- const newMetadata = {
571
- ...metadata,
576
+ //
577
+ // Preserve origin fields to avoid corrupting ownership/linkage (discussionId/userId/agentId).
578
+ // - title: keep original unless explicitly changed
579
+ // - discussionId, userId, agentId/runId: always keep original
580
+ const title =
581
+ (typeof metadata.title === "string" && metadata.title.trim())
582
+ ? metadata.title.trim()
583
+ : originalPayload.title;
584
+ const newMetadata: Record<string, any> = {
585
+ ...originalPayload,
572
586
  data,
573
587
  hash: createHash("md5").update(data).digest("hex"),
574
- type: existingMemory.payload.type,
575
- createdAt: existingMemory.payload.createdAt,
576
588
  updatedAt: new Date().toISOString(),
577
- ...(existingMemory.payload.agentId && {
578
- agentId: existingMemory.payload.agentId,
579
- }),
580
- ...(existingMemory.payload.runId && {
581
- runId: existingMemory.payload.runId,
582
- }),
589
+ title: title,
583
590
  };
584
591
 
585
592
  await vectorStore.update(memoryId, embedding, newMetadata);
@@ -132,35 +132,35 @@ describe('LiteVectorStore Private Methods', () => {
132
132
  //
133
133
  // discussion with Infinity halfLife → old memories have same score as new
134
134
  const payload: MemoryPayload = { memoryId: 'mem-d2', userId: userId, type: 'discussion', createdAt: veryOldDate };
135
- const cosineScore = 0.9;
135
+ const cosineScore = 0.9;
136
136
  const expectedRecency = 1.0; // Infinity halfLife → recency = 1 even for old dates
137
- const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
137
+ const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
138
138
  expect(hybridScore).toBe(1); // Score constant = 1
139
139
  });
140
140
 
141
141
  it('should handle assistant_preference with no decay (Infinity half-life)', () => {
142
- const payload: MemoryPayload = { memoryId: 'mem-a1', userId: userId, type: 'assistant_preference', createdAt: veryOldDate };
143
- const cosineScore = 0.7;
144
- const expectedRecency = 1.0;
145
- const expectedScore = scoring.assistant_preference.alpha * cosineScore + scoring.assistant_preference.beta * expectedRecency + scoring.assistant_preference.gamma;
146
- const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
147
- expect(hybridScore).toBeCloseTo(expectedScore, 5);
142
+ const payload: MemoryPayload = { memoryId: 'mem-a1', userId: userId, type: 'assistant_preference', createdAt: veryOldDate };
143
+ const cosineScore = 0.7;
144
+ const expectedRecency = 1.0;
145
+ const expectedScore = scoring.assistant_preference.alpha * cosineScore + scoring.assistant_preference.beta * expectedRecency + scoring.assistant_preference.gamma;
146
+ const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
147
+ expect(hybridScore).toBeCloseTo(expectedScore, 5);
148
148
  });
149
149
 
150
150
  it('should use default scoring if type is missing', () => {
151
151
  const payload: MemoryPayload = { memoryId: 'mem-def1', userId: userId, createdAt: sevenDaysAgo }; // No type specified
152
- const cosineScore = 0.8;
153
- const expectedRecency = (store as any).calculateRecencyScore(sevenDaysAgo, scoring.default.halfLifeDays);
154
- const expectedScore = scoring.default.alpha * cosineScore + scoring.default.beta * expectedRecency + scoring.default.gamma;
155
- const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
156
- expect(hybridScore).toBeCloseTo(expectedScore, 5);
152
+ const cosineScore = 0.8;
153
+ const expectedRecency = (store as any).calculateRecencyScore(sevenDaysAgo, scoring.default.halfLifeDays);
154
+ const expectedScore = scoring.default.alpha * cosineScore + scoring.default.beta * expectedRecency + scoring.default.gamma;
155
+ const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
156
+ expect(hybridScore).toBeCloseTo(expectedScore, 5);
157
157
  });
158
158
 
159
159
  it('should return score >= 0 even with negative cosine similarity', () => {
160
160
  const payload: MemoryPayload = { memoryId: 'mem-neg1', userId: userId, type: 'assistant_preference', createdAt: twoDaysAgo };
161
- const cosineScore = -0.5;
162
- const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
163
- expect(hybridScore).toBeGreaterThanOrEqual(0);
161
+ const cosineScore = -0.5;
162
+ const hybridScore = (store as any).calculateHybridScore(cosineScore, payload);
163
+ expect(hybridScore).toBeGreaterThanOrEqual(0);
164
164
  });
165
165
 
166
166
  });