claude-memory-layer 1.0.9 → 1.0.10

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.
@@ -1039,6 +1039,28 @@ var SQLiteEventStore = class {
1039
1039
  CREATE INDEX IF NOT EXISTS idx_consolidated_confidence ON consolidated_memories(confidence);
1040
1040
  CREATE INDEX IF NOT EXISTS idx_continuity_created ON continuity_log(created_at);
1041
1041
  CREATE INDEX IF NOT EXISTS idx_embedding_outbox_status ON embedding_outbox(status);
1042
+
1043
+ -- FTS5 Full-Text Search for fast keyword search
1044
+ CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(
1045
+ content,
1046
+ event_id UNINDEXED,
1047
+ content='events',
1048
+ content_rowid='rowid'
1049
+ );
1050
+
1051
+ -- Triggers to keep FTS in sync with events table
1052
+ CREATE TRIGGER IF NOT EXISTS events_fts_insert AFTER INSERT ON events BEGIN
1053
+ INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
1054
+ END;
1055
+
1056
+ CREATE TRIGGER IF NOT EXISTS events_fts_delete AFTER DELETE ON events BEGIN
1057
+ INSERT INTO events_fts(events_fts, rowid, content, event_id) VALUES('delete', OLD.rowid, OLD.content, OLD.id);
1058
+ END;
1059
+
1060
+ CREATE TRIGGER IF NOT EXISTS events_fts_update AFTER UPDATE ON events BEGIN
1061
+ INSERT INTO events_fts(events_fts, rowid, content, event_id) VALUES('delete', OLD.rowid, OLD.content, OLD.id);
1062
+ INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
1063
+ END;
1042
1064
  `);
1043
1065
  const tableInfo = sqliteAll(this.db, "PRAGMA table_info(events)", []);
1044
1066
  const columnNames = tableInfo.map((col) => col.name);
@@ -1479,6 +1501,62 @@ var SQLiteEventStore = class {
1479
1501
  );
1480
1502
  return rows.map((row) => this.rowToEvent(row));
1481
1503
  }
1504
+ /**
1505
+ * Fast keyword search using FTS5
1506
+ * Returns events matching the search query, ranked by relevance
1507
+ */
1508
+ async keywordSearch(query, limit = 10) {
1509
+ await this.initialize();
1510
+ const searchTerms = query.replace(/['"(){}[\]^~*?:\\/-]/g, " ").split(/\s+/).filter((term) => term.length > 1).map((term) => `"${term}"*`).join(" OR ");
1511
+ if (!searchTerms) {
1512
+ return [];
1513
+ }
1514
+ try {
1515
+ const rows = sqliteAll(
1516
+ this.db,
1517
+ `SELECT e.*, fts.rank
1518
+ FROM events_fts fts
1519
+ JOIN events e ON e.id = fts.event_id
1520
+ WHERE events_fts MATCH ?
1521
+ ORDER BY fts.rank
1522
+ LIMIT ?`,
1523
+ [searchTerms, limit]
1524
+ );
1525
+ return rows.map((row) => ({
1526
+ event: this.rowToEvent(row),
1527
+ rank: row.rank
1528
+ }));
1529
+ } catch (error) {
1530
+ const likePattern = `%${query}%`;
1531
+ const rows = sqliteAll(
1532
+ this.db,
1533
+ `SELECT *, 0 as rank FROM events
1534
+ WHERE content LIKE ?
1535
+ ORDER BY timestamp DESC
1536
+ LIMIT ?`,
1537
+ [likePattern, limit]
1538
+ );
1539
+ return rows.map((row) => ({
1540
+ event: this.rowToEvent(row),
1541
+ rank: 0
1542
+ }));
1543
+ }
1544
+ }
1545
+ /**
1546
+ * Rebuild FTS index from existing events
1547
+ * Call this once after upgrading to FTS5
1548
+ */
1549
+ async rebuildFtsIndex() {
1550
+ await this.initialize();
1551
+ const countRow = sqliteGet(this.db, "SELECT COUNT(*) as count FROM events", []);
1552
+ const totalEvents = countRow?.count ?? 0;
1553
+ sqliteExec(this.db, `
1554
+ DELETE FROM events_fts;
1555
+ INSERT INTO events_fts(rowid, content, event_id)
1556
+ SELECT rowid, content, id FROM events;
1557
+ `);
1558
+ return totalEvents;
1559
+ }
1482
1560
  /**
1483
1561
  * Get database instance for direct access
1484
1562
  */
@@ -4537,9 +4615,11 @@ var MemoryService = class {
4537
4615
  sharedStoreConfig = null;
4538
4616
  projectHash = null;
4539
4617
  readOnly;
4618
+ lightweightMode;
4540
4619
  constructor(config) {
4541
4620
  const storagePath = this.expandPath(config.storagePath);
4542
4621
  this.readOnly = config.readOnly ?? false;
4622
+ this.lightweightMode = config.lightweightMode ?? false;
4543
4623
  if (!this.readOnly && !fs.existsSync(storagePath)) {
4544
4624
  fs.mkdirSync(storagePath, { recursive: true });
4545
4625
  }
@@ -4586,6 +4666,10 @@ var MemoryService = class {
4586
4666
  if (this.initialized)
4587
4667
  return;
4588
4668
  await this.sqliteStore.initialize();
4669
+ if (this.lightweightMode) {
4670
+ this.initialized = true;
4671
+ return;
4672
+ }
4589
4673
  if (this.analyticsStore) {
4590
4674
  try {
4591
4675
  await this.analyticsStore.initialize();
@@ -4755,9 +4839,6 @@ var MemoryService = class {
4755
4839
  */
4756
4840
  async retrieveMemories(query, options) {
4757
4841
  await this.initialize();
4758
- if (this.vectorWorker) {
4759
- await this.vectorWorker.processAll();
4760
- }
4761
4842
  if (options?.includeShared && this.sharedStore) {
4762
4843
  return this.retriever.retrieveUnified(query, {
4763
4844
  ...options,
@@ -4767,6 +4848,29 @@ var MemoryService = class {
4767
4848
  }
4768
4849
  return this.retriever.retrieve(query, options);
4769
4850
  }
4851
+ /**
4852
+ * Fast keyword search using SQLite FTS5
4853
+ * Much faster than vector search - no embedding model needed
4854
+ */
4855
+ async keywordSearch(query, options) {
4856
+ await this.initialize();
4857
+ const results = await this.sqliteStore.keywordSearch(query, options?.topK ?? 10);
4858
+ const maxRank = Math.min(...results.map((r) => r.rank), -1e-3);
4859
+ const minRank = Math.max(...results.map((r) => r.rank), -1e3);
4860
+ const rankRange = maxRank - minRank || 1;
4861
+ return results.map((r) => ({
4862
+ event: r.event,
4863
+ score: 1 - (r.rank - minRank) / rankRange
4864
+ // Normalize to 0-1
4865
+ })).filter((r) => !options?.minScore || r.score >= options.minScore);
4866
+ }
4867
+ /**
4868
+ * Rebuild FTS index (call after database upgrade)
4869
+ */
4870
+ async rebuildFtsIndex() {
4871
+ await this.initialize();
4872
+ return this.sqliteStore.rebuildFtsIndex();
4873
+ }
4770
4874
  /**
4771
4875
  * Get session history
4772
4876
  */