@hasna/mementos 0.10.9 → 0.10.11

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/dist/cli/index.js CHANGED
@@ -2584,12 +2584,23 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_resource_locks_exclusive
2584
2584
  CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
2585
2585
  CREATE INDEX IF NOT EXISTS idx_resource_locks_expires ON resource_locks(expires_at);
2586
2586
  INSERT OR IGNORE INTO _migrations (id) VALUES (14);
2587
+ `,
2588
+ `
2589
+ CREATE TABLE IF NOT EXISTS memory_embeddings (
2590
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
2591
+ embedding TEXT NOT NULL,
2592
+ model TEXT NOT NULL DEFAULT 'tfidf-512',
2593
+ dimensions INTEGER NOT NULL DEFAULT 512,
2594
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
2595
+ );
2596
+ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(model);
2597
+ INSERT OR IGNORE INTO _migrations (id) VALUES (15);
2587
2598
  `
2588
2599
  ];
2589
2600
  });
2590
2601
 
2591
2602
  // src/types/index.ts
2592
- var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, VersionConflictError;
2603
+ var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, VersionConflictError, MemoryConflictError;
2593
2604
  var init_types = __esm(() => {
2594
2605
  AgentConflictError = class AgentConflictError extends Error {
2595
2606
  conflict = true;
@@ -2631,8 +2642,92 @@ var init_types = __esm(() => {
2631
2642
  this.actual = actual;
2632
2643
  }
2633
2644
  };
2645
+ MemoryConflictError = class MemoryConflictError extends Error {
2646
+ existingId;
2647
+ existingAgentId;
2648
+ existingUpdatedAt;
2649
+ constructor(key, existing) {
2650
+ super(`Memory conflict: key "${key}" already exists (last written by ${existing.agent_id ?? "unknown"} at ${existing.updated_at}). Use conflict:"overwrite" to replace it.`);
2651
+ this.name = "MemoryConflictError";
2652
+ this.existingId = existing.id;
2653
+ this.existingAgentId = existing.agent_id;
2654
+ this.existingUpdatedAt = existing.updated_at;
2655
+ }
2656
+ };
2634
2657
  });
2635
2658
 
2659
+ // src/lib/embeddings.ts
2660
+ function cosineSimilarity(a, b) {
2661
+ if (a.length !== b.length || a.length === 0)
2662
+ return 0;
2663
+ let dot = 0, magA = 0, magB = 0;
2664
+ for (let i = 0;i < a.length; i++) {
2665
+ dot += a[i] * b[i];
2666
+ magA += a[i] * a[i];
2667
+ magB += b[i] * b[i];
2668
+ }
2669
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
2670
+ return denom === 0 ? 0 : dot / denom;
2671
+ }
2672
+ async function openAIEmbed(text, apiKey) {
2673
+ const res = await fetch(OPENAI_EMBED_URL, {
2674
+ method: "POST",
2675
+ headers: {
2676
+ "Content-Type": "application/json",
2677
+ Authorization: `Bearer ${apiKey}`
2678
+ },
2679
+ body: JSON.stringify({
2680
+ model: EMBED_MODEL,
2681
+ input: text.slice(0, 8192)
2682
+ }),
2683
+ signal: AbortSignal.timeout(1e4)
2684
+ });
2685
+ if (!res.ok) {
2686
+ throw new Error(`OpenAI embedding API ${res.status}: ${await res.text()}`);
2687
+ }
2688
+ const data = await res.json();
2689
+ return data.data[0].embedding;
2690
+ }
2691
+ function tfidfVector(text) {
2692
+ const DIMS = 512;
2693
+ const vec = new Float32Array(DIMS);
2694
+ const tokens = text.toLowerCase().match(/\b\w+\b/g) ?? [];
2695
+ for (const token of tokens) {
2696
+ let hash = 2166136261;
2697
+ for (let i = 0;i < token.length; i++) {
2698
+ hash ^= token.charCodeAt(i);
2699
+ hash = hash * 16777619 >>> 0;
2700
+ }
2701
+ vec[hash % DIMS] += 1;
2702
+ }
2703
+ let norm = 0;
2704
+ for (let i = 0;i < DIMS; i++)
2705
+ norm += vec[i] * vec[i];
2706
+ norm = Math.sqrt(norm);
2707
+ if (norm > 0)
2708
+ for (let i = 0;i < DIMS; i++)
2709
+ vec[i] /= norm;
2710
+ return Array.from(vec);
2711
+ }
2712
+ async function generateEmbedding(text) {
2713
+ const apiKey = process.env["OPENAI_API_KEY"];
2714
+ if (apiKey) {
2715
+ try {
2716
+ const embedding2 = await openAIEmbed(text, apiKey);
2717
+ return { embedding: embedding2, model: EMBED_MODEL, dimensions: EMBED_DIMENSIONS };
2718
+ } catch {}
2719
+ }
2720
+ const embedding = tfidfVector(text);
2721
+ return { embedding, model: "tfidf-512", dimensions: 512 };
2722
+ }
2723
+ function serializeEmbedding(embedding) {
2724
+ return JSON.stringify(embedding);
2725
+ }
2726
+ function deserializeEmbedding(raw) {
2727
+ return JSON.parse(raw);
2728
+ }
2729
+ var OPENAI_EMBED_URL = "https://api.openai.com/v1/embeddings", EMBED_MODEL = "text-embedding-3-small", EMBED_DIMENSIONS = 1536;
2730
+
2636
2731
  // src/lib/redact.ts
2637
2732
  function redactSecrets(text) {
2638
2733
  let result = text;
@@ -2809,8 +2904,10 @@ var exports_memories = {};
2809
2904
  __export(exports_memories, {
2810
2905
  updateMemory: () => updateMemory,
2811
2906
  touchMemory: () => touchMemory,
2907
+ semanticSearch: () => semanticSearch,
2812
2908
  parseMemoryRow: () => parseMemoryRow,
2813
2909
  listMemories: () => listMemories,
2910
+ indexMemoryEmbedding: () => indexMemoryEmbedding,
2814
2911
  incrementRecallCount: () => incrementRecallCount,
2815
2912
  getMemoryVersions: () => getMemoryVersions,
2816
2913
  getMemoryByKey: () => getMemoryByKey,
@@ -2866,7 +2963,16 @@ function createMemory(input, dedupeMode = "merge", db) {
2866
2963
  const metadataJson = JSON.stringify(input.metadata || {});
2867
2964
  const safeValue = redactSecrets(input.value);
2868
2965
  const safeSummary = input.summary ? redactSecrets(input.summary) : null;
2869
- if (dedupeMode === "merge") {
2966
+ const effectiveMode = dedupeMode === "overwrite" ? "merge" : dedupeMode === "version-fork" ? "create" : dedupeMode;
2967
+ if (effectiveMode === "error") {
2968
+ const existing = d.query(`SELECT id, agent_id, updated_at FROM memories
2969
+ WHERE key = ? AND scope = ? AND COALESCE(project_id, '') = ? AND status = 'active'
2970
+ LIMIT 1`).get(input.key, input.scope || "private", input.project_id || "");
2971
+ if (existing) {
2972
+ throw new MemoryConflictError(input.key, existing);
2973
+ }
2974
+ }
2975
+ if (effectiveMode === "merge") {
2870
2976
  const existing = d.query(`SELECT id, version FROM memories
2871
2977
  WHERE key = ? AND scope = ?
2872
2978
  AND COALESCE(agent_id, '') = ?
@@ -3252,6 +3358,52 @@ function getMemoryVersions(memoryId, db) {
3252
3358
  return [];
3253
3359
  }
3254
3360
  }
3361
+ async function indexMemoryEmbedding(memoryId, text, db) {
3362
+ try {
3363
+ const d = db || getDatabase();
3364
+ const { embedding, model, dimensions } = await generateEmbedding(text);
3365
+ const serialized = serializeEmbedding(embedding);
3366
+ d.run(`INSERT INTO memory_embeddings (memory_id, embedding, model, dimensions)
3367
+ VALUES (?, ?, ?, ?)
3368
+ ON CONFLICT(memory_id) DO UPDATE SET embedding=excluded.embedding, model=excluded.model, dimensions=excluded.dimensions, created_at=datetime('now')`, [memoryId, serialized, model, dimensions]);
3369
+ } catch {}
3370
+ }
3371
+ async function semanticSearch(queryText, options = {}, db) {
3372
+ const d = db || getDatabase();
3373
+ const { threshold = 0.5, limit = 10, scope, agent_id, project_id } = options;
3374
+ const { embedding: queryEmbedding } = await generateEmbedding(queryText);
3375
+ const conditions = ["m.status = 'active'", "e.embedding IS NOT NULL"];
3376
+ const params = [];
3377
+ if (scope) {
3378
+ conditions.push("m.scope = ?");
3379
+ params.push(scope);
3380
+ }
3381
+ if (agent_id) {
3382
+ conditions.push("m.agent_id = ?");
3383
+ params.push(agent_id);
3384
+ }
3385
+ if (project_id) {
3386
+ conditions.push("m.project_id = ?");
3387
+ params.push(project_id);
3388
+ }
3389
+ const where = conditions.join(" AND ");
3390
+ const rows = d.prepare(`SELECT m.*, e.embedding FROM memories m
3391
+ JOIN memory_embeddings e ON e.memory_id = m.id
3392
+ WHERE ${where}`).all(...params);
3393
+ const scored = [];
3394
+ for (const row of rows) {
3395
+ try {
3396
+ const docEmbedding = deserializeEmbedding(row.embedding);
3397
+ const score = cosineSimilarity(queryEmbedding, docEmbedding);
3398
+ if (score >= threshold) {
3399
+ const { embedding: _, ...memRow } = row;
3400
+ scored.push({ memory: parseMemoryRow(memRow), score: Math.round(score * 1000) / 1000 });
3401
+ }
3402
+ } catch {}
3403
+ }
3404
+ scored.sort((a, b) => b.score - a.score);
3405
+ return scored.slice(0, limit);
3406
+ }
3255
3407
  var RECALL_PROMOTE_THRESHOLD = 3;
3256
3408
  var init_memories = __esm(() => {
3257
3409
  init_types();
@@ -5473,6 +5625,18 @@ var init_built_in_hooks = __esm(() => {
5473
5625
  });
5474
5626
  }
5475
5627
  });
5628
+ hookRegistry.register({
5629
+ type: "PostMemorySave",
5630
+ blocking: false,
5631
+ builtin: true,
5632
+ priority: 300,
5633
+ description: "Generate and store vector embedding for semantic memory search",
5634
+ handler: async (ctx) => {
5635
+ const { indexMemoryEmbedding: indexMemoryEmbedding2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
5636
+ const text = [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
5637
+ indexMemoryEmbedding2(ctx.memory.id, text);
5638
+ }
5639
+ });
5476
5640
  hookRegistry.register({
5477
5641
  type: "PostMemoryInject",
5478
5642
  blocking: false,
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmCtC,wBAAgB,SAAS,IAAI,MAAM,CAkBlC;AA6ZD,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAerD;AA+BD,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,IAAI,IAAI,MAAM,CAE7B;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAef"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmCtC,wBAAgB,SAAS,IAAI,MAAM,CAkBlC;AA0aD,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAerD;AA+BD,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,IAAI,IAAI,MAAM,CAE7B;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAef"}
@@ -17,4 +17,24 @@ export declare function touchMemory(id: string, db?: Database): void;
17
17
  export declare function incrementRecallCount(id: string, db?: Database): void;
18
18
  export declare function cleanExpiredMemories(db?: Database): number;
19
19
  export declare function getMemoryVersions(memoryId: string, db?: Database): MemoryVersion[];
20
+ export interface SemanticSearchResult {
21
+ memory: Memory;
22
+ score: number;
23
+ }
24
+ /**
25
+ * Store or update the embedding for a memory. Called asynchronously after saves.
26
+ * Non-blocking: failures are silently ignored.
27
+ */
28
+ export declare function indexMemoryEmbedding(memoryId: string, text: string, db?: Database): Promise<void>;
29
+ /**
30
+ * Semantic search across memories using cosine similarity.
31
+ * Falls back gracefully if no embeddings exist yet.
32
+ */
33
+ export declare function semanticSearch(queryText: string, options?: {
34
+ threshold?: number;
35
+ limit?: number;
36
+ scope?: string;
37
+ agent_id?: string;
38
+ project_id?: string;
39
+ }, db?: Database): Promise<SemanticSearchResult[]>;
20
40
  //# sourceMappingURL=memories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/db/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAyB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AA6B3B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAwBnE;AAMD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,UAAoB,EAChC,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CA8IR;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,GAAG,IAAI,CA4Bf;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,EAAE,CAuBV;AAMD,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CA4G3E;AAMD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAiHR;AAMD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAW/D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAmBvE;AAMD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAM3D;AAUD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAsBpE;AAMD,wBAAgB,oBAAoB,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAiB1D;AAMD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,aAAa,EAAE,CAwBlF"}
1
+ {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/db/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAyB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,YAAY,EACZ,aAAa,EACb,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AA+B3B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAwBnE;AAMD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,UAAoB,EAChC,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAqKR;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,GAAG,IAAI,CA4Bf;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,EAAE,CAuBV;AAMD,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CA4G3E;AAMD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAiHR;AAMD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAW/D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAmBvE;AAMD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAM3D;AAUD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAsBpE;AAMD,wBAAgB,oBAAoB,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAiB1D;AAMD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,aAAa,EAAE,CAwBlF;AAMD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAcvG;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAuCjC"}
package/dist/index.js CHANGED
@@ -63,6 +63,19 @@ class VersionConflictError extends Error {
63
63
  this.actual = actual;
64
64
  }
65
65
  }
66
+
67
+ class MemoryConflictError extends Error {
68
+ existingId;
69
+ existingAgentId;
70
+ existingUpdatedAt;
71
+ constructor(key, existing) {
72
+ super(`Memory conflict: key "${key}" already exists (last written by ${existing.agent_id ?? "unknown"} at ${existing.updated_at}). Use conflict:"overwrite" to replace it.`);
73
+ this.name = "MemoryConflictError";
74
+ this.existingId = existing.id;
75
+ this.existingAgentId = existing.agent_id;
76
+ this.existingUpdatedAt = existing.updated_at;
77
+ }
78
+ }
66
79
  // src/db/database.ts
67
80
  import { Database } from "bun:sqlite";
68
81
  import { existsSync, mkdirSync } from "fs";
@@ -477,6 +490,17 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_resource_locks_exclusive
477
490
  CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
478
491
  CREATE INDEX IF NOT EXISTS idx_resource_locks_expires ON resource_locks(expires_at);
479
492
  INSERT OR IGNORE INTO _migrations (id) VALUES (14);
493
+ `,
494
+ `
495
+ CREATE TABLE IF NOT EXISTS memory_embeddings (
496
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
497
+ embedding TEXT NOT NULL,
498
+ model TEXT NOT NULL DEFAULT 'tfidf-512',
499
+ dimensions INTEGER NOT NULL DEFAULT 512,
500
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
501
+ );
502
+ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(model);
503
+ INSERT OR IGNORE INTO _migrations (id) VALUES (15);
480
504
  `
481
505
  ];
482
506
  var _db = null;
@@ -783,7 +807,16 @@ function createMemory(input, dedupeMode = "merge", db) {
783
807
  const metadataJson = JSON.stringify(input.metadata || {});
784
808
  const safeValue = redactSecrets(input.value);
785
809
  const safeSummary = input.summary ? redactSecrets(input.summary) : null;
786
- if (dedupeMode === "merge") {
810
+ const effectiveMode = dedupeMode === "overwrite" ? "merge" : dedupeMode === "version-fork" ? "create" : dedupeMode;
811
+ if (effectiveMode === "error") {
812
+ const existing = d.query(`SELECT id, agent_id, updated_at FROM memories
813
+ WHERE key = ? AND scope = ? AND COALESCE(project_id, '') = ? AND status = 'active'
814
+ LIMIT 1`).get(input.key, input.scope || "private", input.project_id || "");
815
+ if (existing) {
816
+ throw new MemoryConflictError(input.key, existing);
817
+ }
818
+ }
819
+ if (effectiveMode === "merge") {
787
820
  const existing = d.query(`SELECT id, version FROM memories
788
821
  WHERE key = ? AND scope = ?
789
822
  AND COALESCE(agent_id, '') = ?
@@ -1 +1 @@
1
- {"version":3,"file":"built-in-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/built-in-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAwHlD,wBAAgB,kBAAkB,IAAI,IAAI,CAyBzC;AAuBD,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAGD,YAAY,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"built-in-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/built-in-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAyIlD,wBAAgB,kBAAkB,IAAI,IAAI,CAyBzC;AAuBD,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAGD,YAAY,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Embedding generation and cosine similarity for semantic memory search.
3
+ *
4
+ * Uses OpenAI text-embedding-3-small if OPENAI_API_KEY is set,
5
+ * falls back to a simple TF-IDF term frequency vector otherwise.
6
+ */
7
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
8
+ export interface EmbeddingResult {
9
+ embedding: number[];
10
+ model: string;
11
+ dimensions: number;
12
+ }
13
+ /**
14
+ * Generate an embedding for a text string.
15
+ * Uses OpenAI if OPENAI_API_KEY is available, otherwise uses TF-IDF hash trick.
16
+ */
17
+ export declare function generateEmbedding(text: string): Promise<EmbeddingResult>;
18
+ export declare function serializeEmbedding(embedding: number[]): string;
19
+ export declare function deserializeEmbedding(raw: string): number[];
20
+ //# sourceMappingURL=embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/lib/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAUjE;AAwDD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAY9E;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAE9D;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1D"}
package/dist/mcp/index.js CHANGED
@@ -17,7 +17,7 @@ var __export = (target, all) => {
17
17
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
18
18
 
19
19
  // src/types/index.ts
20
- var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, DuplicateMemoryError, InvalidScopeError, VersionConflictError;
20
+ var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, DuplicateMemoryError, InvalidScopeError, VersionConflictError, MemoryConflictError;
21
21
  var init_types = __esm(() => {
22
22
  AgentConflictError = class AgentConflictError extends Error {
23
23
  conflict = true;
@@ -71,6 +71,18 @@ var init_types = __esm(() => {
71
71
  this.actual = actual;
72
72
  }
73
73
  };
74
+ MemoryConflictError = class MemoryConflictError extends Error {
75
+ existingId;
76
+ existingAgentId;
77
+ existingUpdatedAt;
78
+ constructor(key, existing) {
79
+ super(`Memory conflict: key "${key}" already exists (last written by ${existing.agent_id ?? "unknown"} at ${existing.updated_at}). Use conflict:"overwrite" to replace it.`);
80
+ this.name = "MemoryConflictError";
81
+ this.existingId = existing.id;
82
+ this.existingAgentId = existing.agent_id;
83
+ this.existingUpdatedAt = existing.updated_at;
84
+ }
85
+ };
74
86
  });
75
87
 
76
88
  // src/db/database.ts
@@ -538,10 +550,93 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_resource_locks_exclusive
538
550
  CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
539
551
  CREATE INDEX IF NOT EXISTS idx_resource_locks_expires ON resource_locks(expires_at);
540
552
  INSERT OR IGNORE INTO _migrations (id) VALUES (14);
553
+ `,
554
+ `
555
+ CREATE TABLE IF NOT EXISTS memory_embeddings (
556
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
557
+ embedding TEXT NOT NULL,
558
+ model TEXT NOT NULL DEFAULT 'tfidf-512',
559
+ dimensions INTEGER NOT NULL DEFAULT 512,
560
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
561
+ );
562
+ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(model);
563
+ INSERT OR IGNORE INTO _migrations (id) VALUES (15);
541
564
  `
542
565
  ];
543
566
  });
544
567
 
568
+ // src/lib/embeddings.ts
569
+ function cosineSimilarity(a, b) {
570
+ if (a.length !== b.length || a.length === 0)
571
+ return 0;
572
+ let dot = 0, magA = 0, magB = 0;
573
+ for (let i = 0;i < a.length; i++) {
574
+ dot += a[i] * b[i];
575
+ magA += a[i] * a[i];
576
+ magB += b[i] * b[i];
577
+ }
578
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
579
+ return denom === 0 ? 0 : dot / denom;
580
+ }
581
+ async function openAIEmbed(text, apiKey) {
582
+ const res = await fetch(OPENAI_EMBED_URL, {
583
+ method: "POST",
584
+ headers: {
585
+ "Content-Type": "application/json",
586
+ Authorization: `Bearer ${apiKey}`
587
+ },
588
+ body: JSON.stringify({
589
+ model: EMBED_MODEL,
590
+ input: text.slice(0, 8192)
591
+ }),
592
+ signal: AbortSignal.timeout(1e4)
593
+ });
594
+ if (!res.ok) {
595
+ throw new Error(`OpenAI embedding API ${res.status}: ${await res.text()}`);
596
+ }
597
+ const data = await res.json();
598
+ return data.data[0].embedding;
599
+ }
600
+ function tfidfVector(text) {
601
+ const DIMS = 512;
602
+ const vec = new Float32Array(DIMS);
603
+ const tokens = text.toLowerCase().match(/\b\w+\b/g) ?? [];
604
+ for (const token of tokens) {
605
+ let hash = 2166136261;
606
+ for (let i = 0;i < token.length; i++) {
607
+ hash ^= token.charCodeAt(i);
608
+ hash = hash * 16777619 >>> 0;
609
+ }
610
+ vec[hash % DIMS] += 1;
611
+ }
612
+ let norm = 0;
613
+ for (let i = 0;i < DIMS; i++)
614
+ norm += vec[i] * vec[i];
615
+ norm = Math.sqrt(norm);
616
+ if (norm > 0)
617
+ for (let i = 0;i < DIMS; i++)
618
+ vec[i] /= norm;
619
+ return Array.from(vec);
620
+ }
621
+ async function generateEmbedding(text) {
622
+ const apiKey = process.env["OPENAI_API_KEY"];
623
+ if (apiKey) {
624
+ try {
625
+ const embedding2 = await openAIEmbed(text, apiKey);
626
+ return { embedding: embedding2, model: EMBED_MODEL, dimensions: EMBED_DIMENSIONS };
627
+ } catch {}
628
+ }
629
+ const embedding = tfidfVector(text);
630
+ return { embedding, model: "tfidf-512", dimensions: 512 };
631
+ }
632
+ function serializeEmbedding(embedding) {
633
+ return JSON.stringify(embedding);
634
+ }
635
+ function deserializeEmbedding(raw) {
636
+ return JSON.parse(raw);
637
+ }
638
+ var OPENAI_EMBED_URL = "https://api.openai.com/v1/embeddings", EMBED_MODEL = "text-embedding-3-small", EMBED_DIMENSIONS = 1536;
639
+
545
640
  // src/lib/redact.ts
546
641
  function redactSecrets(text) {
547
642
  let result = text;
@@ -714,8 +809,10 @@ var exports_memories = {};
714
809
  __export(exports_memories, {
715
810
  updateMemory: () => updateMemory,
716
811
  touchMemory: () => touchMemory,
812
+ semanticSearch: () => semanticSearch,
717
813
  parseMemoryRow: () => parseMemoryRow,
718
814
  listMemories: () => listMemories,
815
+ indexMemoryEmbedding: () => indexMemoryEmbedding,
719
816
  incrementRecallCount: () => incrementRecallCount,
720
817
  getMemoryVersions: () => getMemoryVersions,
721
818
  getMemoryByKey: () => getMemoryByKey,
@@ -771,7 +868,16 @@ function createMemory(input, dedupeMode = "merge", db) {
771
868
  const metadataJson = JSON.stringify(input.metadata || {});
772
869
  const safeValue = redactSecrets(input.value);
773
870
  const safeSummary = input.summary ? redactSecrets(input.summary) : null;
774
- if (dedupeMode === "merge") {
871
+ const effectiveMode = dedupeMode === "overwrite" ? "merge" : dedupeMode === "version-fork" ? "create" : dedupeMode;
872
+ if (effectiveMode === "error") {
873
+ const existing = d.query(`SELECT id, agent_id, updated_at FROM memories
874
+ WHERE key = ? AND scope = ? AND COALESCE(project_id, '') = ? AND status = 'active'
875
+ LIMIT 1`).get(input.key, input.scope || "private", input.project_id || "");
876
+ if (existing) {
877
+ throw new MemoryConflictError(input.key, existing);
878
+ }
879
+ }
880
+ if (effectiveMode === "merge") {
775
881
  const existing = d.query(`SELECT id, version FROM memories
776
882
  WHERE key = ? AND scope = ?
777
883
  AND COALESCE(agent_id, '') = ?
@@ -1157,6 +1263,52 @@ function getMemoryVersions(memoryId, db) {
1157
1263
  return [];
1158
1264
  }
1159
1265
  }
1266
+ async function indexMemoryEmbedding(memoryId, text, db) {
1267
+ try {
1268
+ const d = db || getDatabase();
1269
+ const { embedding, model, dimensions } = await generateEmbedding(text);
1270
+ const serialized = serializeEmbedding(embedding);
1271
+ d.run(`INSERT INTO memory_embeddings (memory_id, embedding, model, dimensions)
1272
+ VALUES (?, ?, ?, ?)
1273
+ ON CONFLICT(memory_id) DO UPDATE SET embedding=excluded.embedding, model=excluded.model, dimensions=excluded.dimensions, created_at=datetime('now')`, [memoryId, serialized, model, dimensions]);
1274
+ } catch {}
1275
+ }
1276
+ async function semanticSearch(queryText, options = {}, db) {
1277
+ const d = db || getDatabase();
1278
+ const { threshold = 0.5, limit = 10, scope, agent_id, project_id } = options;
1279
+ const { embedding: queryEmbedding } = await generateEmbedding(queryText);
1280
+ const conditions = ["m.status = 'active'", "e.embedding IS NOT NULL"];
1281
+ const params = [];
1282
+ if (scope) {
1283
+ conditions.push("m.scope = ?");
1284
+ params.push(scope);
1285
+ }
1286
+ if (agent_id) {
1287
+ conditions.push("m.agent_id = ?");
1288
+ params.push(agent_id);
1289
+ }
1290
+ if (project_id) {
1291
+ conditions.push("m.project_id = ?");
1292
+ params.push(project_id);
1293
+ }
1294
+ const where = conditions.join(" AND ");
1295
+ const rows = d.prepare(`SELECT m.*, e.embedding FROM memories m
1296
+ JOIN memory_embeddings e ON e.memory_id = m.id
1297
+ WHERE ${where}`).all(...params);
1298
+ const scored = [];
1299
+ for (const row of rows) {
1300
+ try {
1301
+ const docEmbedding = deserializeEmbedding(row.embedding);
1302
+ const score = cosineSimilarity(queryEmbedding, docEmbedding);
1303
+ if (score >= threshold) {
1304
+ const { embedding: _, ...memRow } = row;
1305
+ scored.push({ memory: parseMemoryRow(memRow), score: Math.round(score * 1000) / 1000 });
1306
+ }
1307
+ } catch {}
1308
+ }
1309
+ scored.sort((a, b) => b.score - a.score);
1310
+ return scored.slice(0, limit);
1311
+ }
1160
1312
  var RECALL_PROMOTE_THRESHOLD = 3;
1161
1313
  var init_memories = __esm(() => {
1162
1314
  init_types();
@@ -3244,6 +3396,18 @@ var init_built_in_hooks = __esm(() => {
3244
3396
  });
3245
3397
  }
3246
3398
  });
3399
+ hookRegistry.register({
3400
+ type: "PostMemorySave",
3401
+ blocking: false,
3402
+ builtin: true,
3403
+ priority: 300,
3404
+ description: "Generate and store vector embedding for semantic memory search",
3405
+ handler: async (ctx) => {
3406
+ const { indexMemoryEmbedding: indexMemoryEmbedding2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
3407
+ const text = [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
3408
+ indexMemoryEmbedding2(ctx.memory.id, text);
3409
+ }
3410
+ });
3247
3411
  hookRegistry.register({
3248
3412
  type: "PostMemoryInject",
3249
3413
  blocking: false,
@@ -9179,7 +9343,7 @@ function formatMemory(m) {
9179
9343
  return parts.join(`
9180
9344
  `);
9181
9345
  }
9182
- server.tool("memory_save", "Save/upsert a memory. scope: global=all agents, shared=project, private=single agent.", {
9346
+ server.tool("memory_save", "Save/upsert a memory. scope: global=all agents, shared=project, private=single agent. conflict controls what happens when key already exists.", {
9183
9347
  key: exports_external.string(),
9184
9348
  value: exports_external.string(),
9185
9349
  scope: exports_external.enum(["global", "shared", "private"]).optional(),
@@ -9192,20 +9356,23 @@ server.tool("memory_save", "Save/upsert a memory. scope: global=all agents, shar
9192
9356
  session_id: exports_external.string().optional(),
9193
9357
  ttl_ms: exports_external.union([exports_external.string(), exports_external.number()]).optional(),
9194
9358
  source: exports_external.enum(["user", "agent", "system", "auto", "imported"]).optional(),
9195
- metadata: exports_external.record(exports_external.unknown()).optional()
9359
+ metadata: exports_external.record(exports_external.unknown()).optional(),
9360
+ conflict: exports_external.enum(["merge", "overwrite", "error", "version-fork"]).optional().describe("Conflict strategy: merge=upsert(default), overwrite=same as merge, error=fail if key exists, version-fork=always create new")
9196
9361
  }, async (args) => {
9197
9362
  try {
9198
9363
  ensureAutoProject();
9199
- const input = { ...args };
9200
- if (args.ttl_ms !== undefined) {
9201
- input.ttl_ms = parseDuration(args.ttl_ms);
9364
+ const { conflict, ...restArgs } = args;
9365
+ const input = { ...restArgs };
9366
+ if (restArgs.ttl_ms !== undefined) {
9367
+ input.ttl_ms = parseDuration(restArgs.ttl_ms);
9202
9368
  }
9203
9369
  if (!input.project_id && input.agent_id) {
9204
9370
  const focusedProject = resolveProjectId(input.agent_id, null);
9205
9371
  if (focusedProject)
9206
9372
  input.project_id = focusedProject;
9207
9373
  }
9208
- const memory = createMemory(input);
9374
+ const dedupeMode = conflict ?? "merge";
9375
+ const memory = createMemory(input, dedupeMode);
9209
9376
  if (args.agent_id)
9210
9377
  touchAgent(args.agent_id);
9211
9378
  if (memory.scope === "shared" && memory.project_id && args.agent_id) {
@@ -9214,7 +9381,12 @@ server.tool("memory_save", "Save/upsert a memory. scope: global=all agents, shar
9214
9381
  broadcastSharedMemory2(memory, args.agent_id).catch(() => {});
9215
9382
  } catch {}
9216
9383
  }
9217
- return { content: [{ type: "text", text: `Saved: ${memory.key} (${memory.id.slice(0, 8)})` }] };
9384
+ return { content: [{ type: "text", text: JSON.stringify({
9385
+ saved: memory.key,
9386
+ id: memory.id.slice(0, 8),
9387
+ version: memory.version,
9388
+ conflict_mode: dedupeMode
9389
+ }) }] };
9218
9390
  } catch (e) {
9219
9391
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
9220
9392
  }
@@ -9521,6 +9693,46 @@ ${lines.join(`
9521
9693
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
9522
9694
  }
9523
9695
  });
9696
+ server.tool("memory_search_semantic", "Semantic (meaning-based) memory search using vector embeddings. Finds memories by conceptual similarity, not keyword match. Uses OpenAI embeddings if OPENAI_API_KEY is set, otherwise TF-IDF.", {
9697
+ query: exports_external.string().describe("Natural language query"),
9698
+ threshold: exports_external.coerce.number().min(0).max(1).optional().describe("Minimum cosine similarity score (default: 0.5)"),
9699
+ limit: exports_external.coerce.number().optional().describe("Max results (default: 10)"),
9700
+ scope: exports_external.enum(["global", "shared", "private"]).optional(),
9701
+ agent_id: exports_external.string().optional(),
9702
+ project_id: exports_external.string().optional(),
9703
+ index_missing: exports_external.coerce.boolean().optional().describe("If true, index any memories that lack embeddings before searching")
9704
+ }, async (args) => {
9705
+ try {
9706
+ ensureAutoProject();
9707
+ if (args.index_missing) {
9708
+ const db = getDatabase();
9709
+ const unindexed = db.prepare(`SELECT id, value, summary FROM memories
9710
+ WHERE status = 'active' AND id NOT IN (SELECT memory_id FROM memory_embeddings)
9711
+ LIMIT 100`).all();
9712
+ await Promise.all(unindexed.map((m) => indexMemoryEmbedding(m.id, [m.value, m.summary].filter(Boolean).join(" "))));
9713
+ }
9714
+ let effectiveProjectId = args.project_id;
9715
+ if (!args.project_id && args.agent_id) {
9716
+ effectiveProjectId = resolveProjectId(args.agent_id, null) ?? undefined;
9717
+ }
9718
+ const results = await semanticSearch(args.query, {
9719
+ threshold: args.threshold,
9720
+ limit: args.limit,
9721
+ scope: args.scope,
9722
+ agent_id: args.agent_id,
9723
+ project_id: effectiveProjectId
9724
+ });
9725
+ if (results.length === 0) {
9726
+ return { content: [{ type: "text", text: `No semantically similar memories found for: "${args.query}". Try a lower threshold or call with index_missing:true to generate embeddings first.` }] };
9727
+ }
9728
+ const lines = results.map((r, i) => `${i + 1}. [score:${r.score}] [${r.memory.scope}/${r.memory.category}] ${r.memory.key} = ${r.memory.value.slice(0, 120)}${r.memory.value.length > 120 ? "..." : ""}`);
9729
+ return { content: [{ type: "text", text: `${results.length} semantic result(s) for "${args.query}":
9730
+ ${lines.join(`
9731
+ `)}` }] };
9732
+ } catch (e) {
9733
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
9734
+ }
9735
+ });
9524
9736
  server.tool("memory_stats", "Get aggregate statistics about stored memories", {}, async () => {
9525
9737
  try {
9526
9738
  const db = getDatabase();
@@ -18,7 +18,7 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
18
18
  var __require = import.meta.require;
19
19
 
20
20
  // src/types/index.ts
21
- var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, DuplicateMemoryError, VersionConflictError;
21
+ var AgentConflictError, EntityNotFoundError, MemoryNotFoundError, DuplicateMemoryError, VersionConflictError, MemoryConflictError;
22
22
  var init_types = __esm(() => {
23
23
  AgentConflictError = class AgentConflictError extends Error {
24
24
  conflict = true;
@@ -66,6 +66,18 @@ var init_types = __esm(() => {
66
66
  this.actual = actual;
67
67
  }
68
68
  };
69
+ MemoryConflictError = class MemoryConflictError extends Error {
70
+ existingId;
71
+ existingAgentId;
72
+ existingUpdatedAt;
73
+ constructor(key, existing) {
74
+ super(`Memory conflict: key "${key}" already exists (last written by ${existing.agent_id ?? "unknown"} at ${existing.updated_at}). Use conflict:"overwrite" to replace it.`);
75
+ this.name = "MemoryConflictError";
76
+ this.existingId = existing.id;
77
+ this.existingAgentId = existing.agent_id;
78
+ this.existingUpdatedAt = existing.updated_at;
79
+ }
80
+ };
69
81
  });
70
82
 
71
83
  // src/db/database.ts
@@ -533,10 +545,93 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_resource_locks_exclusive
533
545
  CREATE INDEX IF NOT EXISTS idx_resource_locks_agent ON resource_locks(agent_id);
534
546
  CREATE INDEX IF NOT EXISTS idx_resource_locks_expires ON resource_locks(expires_at);
535
547
  INSERT OR IGNORE INTO _migrations (id) VALUES (14);
548
+ `,
549
+ `
550
+ CREATE TABLE IF NOT EXISTS memory_embeddings (
551
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
552
+ embedding TEXT NOT NULL,
553
+ model TEXT NOT NULL DEFAULT 'tfidf-512',
554
+ dimensions INTEGER NOT NULL DEFAULT 512,
555
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
556
+ );
557
+ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(model);
558
+ INSERT OR IGNORE INTO _migrations (id) VALUES (15);
536
559
  `
537
560
  ];
538
561
  });
539
562
 
563
+ // src/lib/embeddings.ts
564
+ function cosineSimilarity(a, b) {
565
+ if (a.length !== b.length || a.length === 0)
566
+ return 0;
567
+ let dot = 0, magA = 0, magB = 0;
568
+ for (let i = 0;i < a.length; i++) {
569
+ dot += a[i] * b[i];
570
+ magA += a[i] * a[i];
571
+ magB += b[i] * b[i];
572
+ }
573
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
574
+ return denom === 0 ? 0 : dot / denom;
575
+ }
576
+ async function openAIEmbed(text, apiKey) {
577
+ const res = await fetch(OPENAI_EMBED_URL, {
578
+ method: "POST",
579
+ headers: {
580
+ "Content-Type": "application/json",
581
+ Authorization: `Bearer ${apiKey}`
582
+ },
583
+ body: JSON.stringify({
584
+ model: EMBED_MODEL,
585
+ input: text.slice(0, 8192)
586
+ }),
587
+ signal: AbortSignal.timeout(1e4)
588
+ });
589
+ if (!res.ok) {
590
+ throw new Error(`OpenAI embedding API ${res.status}: ${await res.text()}`);
591
+ }
592
+ const data = await res.json();
593
+ return data.data[0].embedding;
594
+ }
595
+ function tfidfVector(text) {
596
+ const DIMS = 512;
597
+ const vec = new Float32Array(DIMS);
598
+ const tokens = text.toLowerCase().match(/\b\w+\b/g) ?? [];
599
+ for (const token of tokens) {
600
+ let hash = 2166136261;
601
+ for (let i = 0;i < token.length; i++) {
602
+ hash ^= token.charCodeAt(i);
603
+ hash = hash * 16777619 >>> 0;
604
+ }
605
+ vec[hash % DIMS] += 1;
606
+ }
607
+ let norm = 0;
608
+ for (let i = 0;i < DIMS; i++)
609
+ norm += vec[i] * vec[i];
610
+ norm = Math.sqrt(norm);
611
+ if (norm > 0)
612
+ for (let i = 0;i < DIMS; i++)
613
+ vec[i] /= norm;
614
+ return Array.from(vec);
615
+ }
616
+ async function generateEmbedding(text) {
617
+ const apiKey = process.env["OPENAI_API_KEY"];
618
+ if (apiKey) {
619
+ try {
620
+ const embedding2 = await openAIEmbed(text, apiKey);
621
+ return { embedding: embedding2, model: EMBED_MODEL, dimensions: EMBED_DIMENSIONS };
622
+ } catch {}
623
+ }
624
+ const embedding = tfidfVector(text);
625
+ return { embedding, model: "tfidf-512", dimensions: 512 };
626
+ }
627
+ function serializeEmbedding(embedding) {
628
+ return JSON.stringify(embedding);
629
+ }
630
+ function deserializeEmbedding(raw) {
631
+ return JSON.parse(raw);
632
+ }
633
+ var OPENAI_EMBED_URL = "https://api.openai.com/v1/embeddings", EMBED_MODEL = "text-embedding-3-small", EMBED_DIMENSIONS = 1536;
634
+
540
635
  // src/lib/redact.ts
541
636
  function redactSecrets(text) {
542
637
  let result = text;
@@ -709,8 +804,10 @@ var exports_memories = {};
709
804
  __export(exports_memories, {
710
805
  updateMemory: () => updateMemory,
711
806
  touchMemory: () => touchMemory,
807
+ semanticSearch: () => semanticSearch,
712
808
  parseMemoryRow: () => parseMemoryRow,
713
809
  listMemories: () => listMemories,
810
+ indexMemoryEmbedding: () => indexMemoryEmbedding,
714
811
  incrementRecallCount: () => incrementRecallCount,
715
812
  getMemoryVersions: () => getMemoryVersions,
716
813
  getMemoryByKey: () => getMemoryByKey,
@@ -766,7 +863,16 @@ function createMemory(input, dedupeMode = "merge", db) {
766
863
  const metadataJson = JSON.stringify(input.metadata || {});
767
864
  const safeValue = redactSecrets(input.value);
768
865
  const safeSummary = input.summary ? redactSecrets(input.summary) : null;
769
- if (dedupeMode === "merge") {
866
+ const effectiveMode = dedupeMode === "overwrite" ? "merge" : dedupeMode === "version-fork" ? "create" : dedupeMode;
867
+ if (effectiveMode === "error") {
868
+ const existing = d.query(`SELECT id, agent_id, updated_at FROM memories
869
+ WHERE key = ? AND scope = ? AND COALESCE(project_id, '') = ? AND status = 'active'
870
+ LIMIT 1`).get(input.key, input.scope || "private", input.project_id || "");
871
+ if (existing) {
872
+ throw new MemoryConflictError(input.key, existing);
873
+ }
874
+ }
875
+ if (effectiveMode === "merge") {
770
876
  const existing = d.query(`SELECT id, version FROM memories
771
877
  WHERE key = ? AND scope = ?
772
878
  AND COALESCE(agent_id, '') = ?
@@ -1152,6 +1258,52 @@ function getMemoryVersions(memoryId, db) {
1152
1258
  return [];
1153
1259
  }
1154
1260
  }
1261
+ async function indexMemoryEmbedding(memoryId, text, db) {
1262
+ try {
1263
+ const d = db || getDatabase();
1264
+ const { embedding, model, dimensions } = await generateEmbedding(text);
1265
+ const serialized = serializeEmbedding(embedding);
1266
+ d.run(`INSERT INTO memory_embeddings (memory_id, embedding, model, dimensions)
1267
+ VALUES (?, ?, ?, ?)
1268
+ ON CONFLICT(memory_id) DO UPDATE SET embedding=excluded.embedding, model=excluded.model, dimensions=excluded.dimensions, created_at=datetime('now')`, [memoryId, serialized, model, dimensions]);
1269
+ } catch {}
1270
+ }
1271
+ async function semanticSearch(queryText, options = {}, db) {
1272
+ const d = db || getDatabase();
1273
+ const { threshold = 0.5, limit = 10, scope, agent_id, project_id } = options;
1274
+ const { embedding: queryEmbedding } = await generateEmbedding(queryText);
1275
+ const conditions = ["m.status = 'active'", "e.embedding IS NOT NULL"];
1276
+ const params = [];
1277
+ if (scope) {
1278
+ conditions.push("m.scope = ?");
1279
+ params.push(scope);
1280
+ }
1281
+ if (agent_id) {
1282
+ conditions.push("m.agent_id = ?");
1283
+ params.push(agent_id);
1284
+ }
1285
+ if (project_id) {
1286
+ conditions.push("m.project_id = ?");
1287
+ params.push(project_id);
1288
+ }
1289
+ const where = conditions.join(" AND ");
1290
+ const rows = d.prepare(`SELECT m.*, e.embedding FROM memories m
1291
+ JOIN memory_embeddings e ON e.memory_id = m.id
1292
+ WHERE ${where}`).all(...params);
1293
+ const scored = [];
1294
+ for (const row of rows) {
1295
+ try {
1296
+ const docEmbedding = deserializeEmbedding(row.embedding);
1297
+ const score = cosineSimilarity(queryEmbedding, docEmbedding);
1298
+ if (score >= threshold) {
1299
+ const { embedding: _, ...memRow } = row;
1300
+ scored.push({ memory: parseMemoryRow(memRow), score: Math.round(score * 1000) / 1000 });
1301
+ }
1302
+ } catch {}
1303
+ }
1304
+ scored.sort((a, b) => b.score - a.score);
1305
+ return scored.slice(0, limit);
1306
+ }
1155
1307
  var RECALL_PROMOTE_THRESHOLD = 3;
1156
1308
  var init_memories = __esm(() => {
1157
1309
  init_types();
@@ -3599,6 +3751,18 @@ hookRegistry.register({
3599
3751
  });
3600
3752
  }
3601
3753
  });
3754
+ hookRegistry.register({
3755
+ type: "PostMemorySave",
3756
+ blocking: false,
3757
+ builtin: true,
3758
+ priority: 300,
3759
+ description: "Generate and store vector embedding for semantic memory search",
3760
+ handler: async (ctx) => {
3761
+ const { indexMemoryEmbedding: indexMemoryEmbedding2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
3762
+ const text = [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
3763
+ indexMemoryEmbedding2(ctx.memory.id, text);
3764
+ }
3765
+ });
3602
3766
  hookRegistry.register({
3603
3767
  type: "PostMemoryInject",
3604
3768
  blocking: false,
@@ -158,7 +158,7 @@ export interface MementosConfig {
158
158
  stale_deprioritize_days: number;
159
159
  };
160
160
  }
161
- export type DedupeMode = "merge" | "create";
161
+ export type DedupeMode = "merge" | "create" | "overwrite" | "error" | "version-fork";
162
162
  export type SyncDirection = "push" | "pull" | "both";
163
163
  export type ConflictResolution = "prefer-local" | "prefer-remote" | "prefer-newer";
164
164
  export interface SyncOptions {
@@ -259,4 +259,14 @@ export declare class VersionConflictError extends Error {
259
259
  actual: number;
260
260
  constructor(id: string, expected: number, actual: number);
261
261
  }
262
+ export declare class MemoryConflictError extends Error {
263
+ existingId: string;
264
+ existingAgentId: string | null;
265
+ existingUpdatedAt: string;
266
+ constructor(key: string, existing: {
267
+ id: string;
268
+ agent_id: string | null;
269
+ updated_at: string;
270
+ });
271
+ }
262
272
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.10.9",
3
+ "version": "0.10.11",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",