Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}),
Expand All @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/embedding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

// ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
10 changes: 5 additions & 5 deletions test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down Expand Up @@ -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);
});
Expand Down
Loading