Skip to content

Commit e3ef136

Browse files
rudi193-cmdvincentkoc
authored andcommitted
fix(memory): keep FTS keyword search model agnostic
Make lexical FTS/LIKE search ignore embedding model identity so exact keyword recall survives provider/model changes. Vector search remains model-scoped, and refreshed or stale FTS rows are cleaned by path/source with live-chunk filtering to prevent old orphan rows from surfacing. Fixes #48300
1 parent 7499a02 commit e3ef136

6 files changed

Lines changed: 275 additions & 103 deletions

File tree

extensions/memory-core/src/memory/manager-fts-state.test.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe("memory FTS state", () => {
1111
db = null;
1212
});
1313

14-
it("only removes rows for the active model when a provider is active", () => {
14+
it("removes rows for all models when a provider is active", () => {
1515
db = new DatabaseSync(":memory:");
1616
db.exec("CREATE TABLE chunks_fts (path TEXT, source TEXT, model TEXT)");
1717
db.prepare("INSERT INTO chunks_fts (path, source, model) VALUES (?, ?, ?)").run(
@@ -24,6 +24,16 @@ describe("memory FTS state", () => {
2424
"memory",
2525
"other-model",
2626
);
27+
db.prepare("INSERT INTO chunks_fts (path, source, model) VALUES (?, ?, ?)").run(
28+
"memory/2026-01-13.md",
29+
"memory",
30+
"other-model",
31+
);
32+
db.prepare("INSERT INTO chunks_fts (path, source, model) VALUES (?, ?, ?)").run(
33+
"memory/2026-01-12.md",
34+
"sessions",
35+
"other-model",
36+
);
2737

2838
deleteMemoryFtsRows({
2939
db,
@@ -32,10 +42,15 @@ describe("memory FTS state", () => {
3242
currentModel: "mock-embed",
3343
});
3444

35-
const rows = db.prepare("SELECT model FROM chunks_fts ORDER BY model").all() as Array<{
45+
const rows = db.prepare("SELECT path, source, model FROM chunks_fts ORDER BY path, source").all() as Array<{
46+
path: string;
47+
source: string;
3648
model: string;
3749
}>;
38-
expect(rows).toEqual([{ model: "other-model" }]);
50+
expect(rows).toEqual([
51+
{ path: "memory/2026-01-12.md", source: "sessions", model: "other-model" },
52+
{ path: "memory/2026-01-13.md", source: "memory", model: "other-model" },
53+
]);
3954
});
4055

4156
it("removes all rows for the path in FTS-only mode", () => {

extensions/memory-core/src/memory/manager-fts-state.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,8 @@ export function deleteMemoryFtsRows(params: {
1010
currentModel?: string;
1111
}): void {
1212
const tableName = params.tableName ?? "chunks_fts";
13-
if (params.currentModel) {
14-
params.db
15-
.prepare(`DELETE FROM ${tableName} WHERE path = ? AND source = ? AND model = ?`)
16-
.run(params.path, params.source, params.currentModel);
17-
return;
18-
}
13+
// Lexical search is model-agnostic, so refreshed/deleted files must not
14+
// leave old-model FTS rows behind for the same path/source.
1915
params.db
2016
.prepare(`DELETE FROM ${tableName} WHERE path = ? AND source = ?`)
2117
.run(params.path, params.source);

0 commit comments

Comments
 (0)