| 482 | } |
| 483 | |
| 484 | private migrateContentHash(): void { |
| 485 | const cols = this.db.prepare("PRAGMA table_info(chunks)").all() as Array<{ name: string }>; |
| 486 | if (!cols.some((c) => c.name === "content_hash")) { |
| 487 | this.db.exec("ALTER TABLE chunks ADD COLUMN content_hash TEXT"); |
| 488 | this.db.exec("CREATE INDEX IF NOT EXISTS idx_chunks_dedup ON chunks(session_key, role, content_hash)"); |
| 489 | |
| 490 | // Backfill existing rows |
| 491 | const rows = this.db.prepare("SELECT id, content FROM chunks WHERE content_hash IS NULL").all() as Array<{ id: string; content: string }>; |
| 492 | const updateStmt = this.db.prepare("UPDATE chunks SET content_hash = ? WHERE id = ?"); |
| 493 | for (const r of rows) { |
| 494 | updateStmt.run(contentHash(r.content), r.id); |
| 495 | } |
| 496 | if (rows.length > 0) { |
| 497 | this.log.info(`Migrated: backfilled content_hash for ${rows.length} chunks`); |
| 498 | } |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | private migrateSkillTables(): void { |
| 503 | this.db.exec(` |