diff --git a/src/memory/index.test.ts b/src/memory/index.test.ts index 1b5b939aea4..0154f8932f4 100644 --- a/src/memory/index.test.ts +++ b/src/memory/index.test.ts @@ -216,6 +216,7 @@ describe("memory index", () => { vectorEnabled?: boolean; cacheEnabled?: boolean; minScore?: number; + onSearch?: boolean; hybrid?: { enabled: boolean; vectorWeight?: number; textWeight?: number }; }): TestCfg { return { @@ -229,7 +230,7 @@ describe("memory index", () => { store: { path: params.storePath, vector: { enabled: params.vectorEnabled ?? false } }, // Perf: keep test indexes to a single chunk to reduce sqlite work. chunking: { tokens: 4000, overlap: 0 }, - sync: { watch: false, onSessionStart: false, onSearch: true }, + sync: { watch: false, onSessionStart: false, onSearch: params.onSearch ?? true }, query: { minScore: params.minScore ?? 0, hybrid: params.hybrid ?? { enabled: false }, @@ -970,6 +971,25 @@ describe("memory index", () => { await manager.close?.(); }); + it("does not initialize the provider when searching an empty index", async () => { + const cfg = createCfg({ + storePath: path.join(workspaceDir, `index-empty-${randomUUID()}.sqlite`), + provider: "gemini", + model: "gemini-embedding-2-preview", + outputDimensionality: 1536, + onSearch: false, + }); + + const result = await getMemorySearchManager({ cfg, agentId: "main" }); + const manager = requireManager(result); + + const results = await manager.search("hello"); + + expect(results).toEqual([]); + expect(providerCalls).toEqual([]); + await manager.close?.(); + }); + it("reindexes when Gemini outputDimensionality changes", async () => { const base = createCfg({ storePath: indexModelPath, diff --git a/src/memory/manager.ts b/src/memory/manager.ts index fe8622f6ae3..4c698e389b1 100644 --- a/src/memory/manager.ts +++ b/src/memory/manager.ts @@ -436,29 +436,23 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem } private hasIndexedContent(): boolean { - const chunks = - ( - this.db.prepare(`SELECT COUNT(*) as c FROM chunks`).get() as - | { - c: number; - } - | undefined - )?.c ?? 0; - if (chunks > 0) { + const chunkRow = this.db.prepare(`SELECT 1 as found FROM chunks LIMIT 1`).get() as + | { + found?: number; + } + | undefined; + if (chunkRow?.found === 1) { return true; } if (!this.fts.enabled || !this.fts.available) { return false; } - const ftsRows = - ( - this.db.prepare(`SELECT COUNT(*) as c FROM ${FTS_TABLE}`).get() as - | { - c: number; - } - | undefined - )?.c ?? 0; - return ftsRows > 0; + const ftsRow = this.db.prepare(`SELECT 1 as found FROM ${FTS_TABLE} LIMIT 1`).get() as + | { + found?: number; + } + | undefined; + return ftsRow?.found === 1; } private async searchVector(