From 9968f7074fcad28542b6653ca37ee4c5738f3aa9 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Sun, 22 Mar 2026 22:05:37 +0000 Subject: [PATCH] fix: auto-enable embeddings when VOYAGE_API_KEY is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Flip search.embeddings.enabled default from false to true - isAvailable() now returns true when VOYAGE_API_KEY is set, unless explicitly disabled via enabled: false in .lore.json - Remove redundant config().search.embeddings.enabled check from startup backfill — isAvailable() already handles it - Users just need to set VOYAGE_API_KEY, no config change needed --- src/config.ts | 13 ++++++++----- src/embedding.ts | 7 +++++-- src/index.ts | 2 +- test/config.test.ts | 10 +++++----- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index 28bba33..fae80df 100644 --- a/src/config.ts +++ b/src/config.ts @@ -66,18 +66,21 @@ export const LoreConfig = z.object({ * When enabled, the configured model generates 2–3 alternative query phrasings * before search, improving recall for ambiguous queries. */ queryExpansion: z.boolean().default(false), - /** Vector embedding search via Voyage AI. Requires VOYAGE_API_KEY env var. */ + /** Vector embedding search via Voyage AI. + * Automatically enabled when VOYAGE_API_KEY env var is set. + * Set enabled: false to explicitly disable even with the key present. */ embeddings: z .object({ - /** Enable vector embedding search. Requires VOYAGE_API_KEY env var. Default: false. */ - enabled: z.boolean().default(false), + /** Enable/disable vector embedding search. Default: true. + * Set to false to explicitly disable even when VOYAGE_API_KEY is set. */ + enabled: z.boolean().default(true), /** Voyage AI model ID. Default: voyage-code-3. */ model: z.string().default("voyage-code-3"), /** Embedding dimensions. Default: 1024. */ dimensions: z.number().min(256).max(2048).default(1024), }) .default({ - enabled: false, + enabled: true, model: "voyage-code-3", dimensions: 1024, }), @@ -86,7 +89,7 @@ export const LoreConfig = z.object({ ftsWeights: { title: 6.0, content: 2.0, category: 3.0 }, recallLimit: 10, queryExpansion: false, - embeddings: { enabled: false, model: "voyage-code-3", dimensions: 1024 }, + embeddings: { enabled: true, model: "voyage-code-3", dimensions: 1024 }, }), crossProject: z.boolean().default(false), agentsFile: z diff --git a/src/embedding.ts b/src/embedding.ts index cdf0f03..a7de592 100644 --- a/src/embedding.ts +++ b/src/embedding.ts @@ -21,9 +21,12 @@ function getApiKey(): string | undefined { return process.env.VOYAGE_API_KEY; } -/** Returns true if embedding is configured and the API key is present. */ +/** Returns true if embedding is available. + * Active when VOYAGE_API_KEY is set, unless explicitly disabled via + * `search.embeddings.enabled: false` in .lore.json. */ export function isAvailable(): boolean { - return config().search.embeddings.enabled && !!getApiKey(); + if (config().search.embeddings.enabled === false) return false; + return !!getApiKey(); } // --------------------------------------------------------------------------- diff --git a/src/index.ts b/src/index.ts index c9b1598..4c6d610 100644 --- a/src/index.ts +++ b/src/index.ts @@ -682,7 +682,7 @@ End with "I'm ready to continue." so the agent knows to pick up where it left of // Background: backfill embeddings for entries that don't have one yet. // Fires once when embeddings are first enabled — subsequent entries // get embedded on create/update via ltm.ts hooks. - if (config().search.embeddings.enabled && embedding.isAvailable()) { + if (embedding.isAvailable()) { embedding.backfillEmbeddings().catch((err) => { log.info("embedding backfill failed:", err); }); diff --git a/test/config.test.ts b/test/config.test.ts index 6a82eb5..62d152b 100644 --- a/test/config.test.ts +++ b/test/config.test.ts @@ -84,7 +84,7 @@ describe("LoreConfig — search schema", () => { expect(cfg.search.ftsWeights.category).toBe(3.0); expect(cfg.search.recallLimit).toBe(10); expect(cfg.search.queryExpansion).toBe(false); - expect(cfg.search.embeddings.enabled).toBe(false); + expect(cfg.search.embeddings.enabled).toBe(true); expect(cfg.search.embeddings.model).toBe("voyage-code-3"); expect(cfg.search.embeddings.dimensions).toBe(1024); }); @@ -125,14 +125,14 @@ describe("LoreConfig — search schema", () => { expect(cfg.search.ftsWeights.title).toBe(6.0); expect(cfg.search.recallLimit).toBe(20); expect(cfg.search.queryExpansion).toBe(false); - expect(cfg.search.embeddings.enabled).toBe(false); + expect(cfg.search.embeddings.enabled).toBe(true); }); - test("search.embeddings can be enabled", () => { + test("search.embeddings can be disabled", () => { const cfg = LoreConfig.parse({ - search: { embeddings: { enabled: true } }, + search: { embeddings: { enabled: false } }, }); - expect(cfg.search.embeddings.enabled).toBe(true); + expect(cfg.search.embeddings.enabled).toBe(false); expect(cfg.search.embeddings.model).toBe("voyage-code-3"); expect(cfg.search.embeddings.dimensions).toBe(1024); });