fix(memory): rebuild migrated search indexes

This commit is contained in:
Vincent Koc 2026-06-18 10:49:18 +02:00
parent 28fb5b019a
commit 6e6bd5633f
4 changed files with 18 additions and 1 deletions

View file

@ -1716,7 +1716,7 @@ describe("memory index", () => {
expect(status.vector?.available).toBe(available);
});
it("drops the shipped legacy vector table after loading sqlite-vec", async () => {
it("drops the shipped legacy vector table and schedules a full reindex", async () => {
const cfg = createCfg({ vectorEnabled: true });
const manager = await getPersistentManager(cfg);
const db = Reflect.get(manager, "db") as DatabaseSync;
@ -1732,6 +1732,7 @@ describe("memory index", () => {
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'chunks_vec'")
.get(),
).toBeUndefined();
expect(Reflect.get(manager, "memoryFullRetryDirty")).toBe(true);
});
it("probes sqlite vector store availability without initializing embeddings", async () => {

View file

@ -650,7 +650,10 @@ export abstract class MemoryManagerSyncOps {
this.vector.extensionPath = loaded.extensionPath;
this.vector.available = true;
if (this.dropLegacyVectorTable()) {
// A broad dirty sync can skip unchanged files whose source hashes were
// migrated. Force the next sync to republish the derived vector rows.
this.dirty = true;
this.memoryFullRetryDirty = true;
}
return true;
} catch (err) {

View file

@ -69,6 +69,9 @@ describe("memory index schema", () => {
expect(db.prepare("SELECT id, text FROM memory_index_chunks").all()).toEqual([
{ id: "chunk-1", text: "remember this" },
]);
expect(db.prepare("SELECT id, text FROM memory_index_chunks_fts").all()).toEqual([
{ id: "chunk-1", text: "remember this" },
]);
expect(db.prepare("SELECT provider, hash FROM memory_embedding_cache").all()).toEqual([
{ provider: "openai", hash: "chunk-hash" },
]);

View file

@ -367,6 +367,16 @@ export function ensureMemoryIndexSchema(params: {
` end_line UNINDEXED\n` +
`${tokenizeClause});`,
);
// The shipped generic-table migration and a later FTS enablement both
// create an empty derived table beside already-canonical chunk rows.
params.db.exec(`
INSERT INTO ${MEMORY_INDEX_FTS_TABLE} (
text, id, path, source, model, start_line, end_line
)
SELECT text, id, path, source, model, start_line, end_line
FROM ${MEMORY_INDEX_CHUNKS_TABLE}
WHERE NOT EXISTS (SELECT 1 FROM ${MEMORY_INDEX_FTS_TABLE} LIMIT 1);
`);
ftsAvailable = true;
} catch (err) {
const message = formatErrorMessage(err);