* Build a full-text index over `session_facts` so memory can be SEARCHED, not just dumped * newest-first. Uses an FTS5 external-content table (no data duplication — it indexes the * existing rows) kept in sync by triggers, plus a one-time rebuild for rows that predate it. * All best-effort:
()
| 353 | } |
| 354 | const rows = this.db.prepare( |
| 355 | `SELECT DISTINCT fact FROM session_facts WHERE cwd = ? AND scope = 'project' ORDER BY id DESC LIMIT ?`, |
| 356 | ).all(cwd, limit) as { fact: string }[]; |
| 357 | return rows.map(r => r.fact); |
| 358 | } |
| 359 | |
| 360 | private ftsReady = false; |
| 361 | |
| 362 | /** |
| 363 | * Build a full-text index over `session_facts` so memory can be SEARCHED, not just dumped |
| 364 | * newest-first. Uses an FTS5 external-content table (no data duplication — it indexes the |
| 365 | * existing rows) kept in sync by triggers, plus a one-time rebuild for rows that predate it. |
| 366 | * All best-effort: if this SQLite build lacks FTS5, searchFacts falls back to a LIKE scan. |
| 367 | */ |
| 368 | private initFactsFts(): void { |
| 369 | try { |
| 370 | this.db.exec(` |
| 371 | CREATE VIRTUAL TABLE IF NOT EXISTS session_facts_fts USING fts5(fact, content='session_facts', content_rowid='id'); |
| 372 | CREATE TRIGGER IF NOT EXISTS session_facts_ai AFTER INSERT ON session_facts BEGIN |
| 373 | INSERT INTO session_facts_fts(rowid, fact) VALUES (new.id, new.fact); |
| 374 | END; |
| 375 | CREATE TRIGGER IF NOT EXISTS session_facts_ad AFTER DELETE ON session_facts BEGIN |
| 376 | INSERT INTO session_facts_fts(session_facts_fts, rowid, fact) VALUES('delete', old.id, old.fact); |
| 377 | END; |
| 378 | CREATE TRIGGER IF NOT EXISTS session_facts_au AFTER UPDATE ON session_facts BEGIN |
| 379 | INSERT INTO session_facts_fts(session_facts_fts, rowid, fact) VALUES('delete', old.id, old.fact); |
| 380 | INSERT INTO session_facts_fts(rowid, fact) VALUES (new.id, new.fact); |
| 381 | END; |
| 382 | `); |
| 383 | // Backfill rows that existed before the index/triggers (FTS empty but facts present). |
| 384 | const ftsN = (this.db.prepare(`SELECT count(*) AS n FROM session_facts_fts`).get() as { n: number }).n; |
no test coverage detected