From 4c26e4845b82779b00fad2aab24bc53ca9c79478 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Wed, 6 May 2026 18:04:56 -0700 Subject: [PATCH] fix(types): doctor 8b uses portable executeRaw + Voyage fetch-shim cast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #665's doctor 8b dim-probe used `engine.sql\`...\`` directly (Postgres template literal) which doesn't typecheck against the BrainEngine interface (only PostgresEngine has the .sql getter; PGLite does not). Refactored to use `readContentChunksEmbeddingDim` from src/core/embedding-dim-check.ts — same helper init's A4 hard-error path uses, runs portably on both engines. #680's Voyage fetch-shim passes a custom fetch handler to `createOpenAICompatible` for the encoding_format + prompt_tokens normalization. The SDK accepts the field at runtime but the typed parameter on the pinned version doesn't expose it. Cast to the parameter type so the shim ships without a type error. Both fixes are mechanical cleanup of cherry-picked PRs that didn't typecheck against current master's stricter shape. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/commands/doctor.ts | 16 +++++++--------- src/core/ai/gateway.ts | 5 ++++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/commands/doctor.ts b/src/commands/doctor.ts index 38d09bce4..06a4bf68e 100644 --- a/src/commands/doctor.ts +++ b/src/commands/doctor.ts @@ -607,17 +607,15 @@ export async function runDoctor(engine: BrainEngine | null, args: string[], dbSo issues.push(`Dimension mismatch: provider returned ${actualDims} but config expects ${configuredDims}`); } - // Check DB column dimensions match + // Check DB column dimensions match (engine-portable; works on both + // Postgres and PGLite via the shared dim-check helper added in v0.28.5). try { - const dbDimRow = await engine.sql` - SELECT vector_dims(embedding) as dims - FROM content_chunks - WHERE embedding IS NOT NULL - LIMIT 1`; - if (dbDimRow.length > 0 && dbDimRow[0].dims !== actualDims) { - issues.push(`DB dimension mismatch: stored vectors are ${dbDimRow[0].dims}-dim but provider returns ${actualDims}-dim. Migration needed.`); + const { readContentChunksEmbeddingDim } = await import('../core/embedding-dim-check.ts'); + const colDim = await readContentChunksEmbeddingDim(engine); + if (colDim.exists && colDim.dims !== null && colDim.dims !== actualDims) { + issues.push(`DB dimension mismatch: column is vector(${colDim.dims}) but provider returns ${actualDims}-dim. See docs/embedding-migrations.md for the manual ALTER recipe.`); } - } catch { /* no chunks with embeddings yet, that's fine */ } + } catch { /* column or table missing — fresh brain, fine */ } if (issues.length > 0) { checks.push({ diff --git a/src/core/ai/gateway.ts b/src/core/ai/gateway.ts index f4c55613d..66380e2e8 100644 --- a/src/core/ai/gateway.ts +++ b/src/core/ai/gateway.ts @@ -229,12 +229,15 @@ function instantiateEmbedding(recipe: Recipe, modelId: string, cfg: AIGatewayCon } } : undefined; + // SDK accepts a `fetch` override at runtime but the typed settings don't + // expose it on this version pin; cast so v0.28.5's #680 fetch-shim + // (Voyage encoding_format + usage normalization) typechecks. const client = createOpenAICompatible({ name: recipe.id, baseURL: baseUrl, apiKey: apiKey ?? 'unauthenticated', ...(voyageFetch ? { fetch: voyageFetch } : {}), - }); + } as Parameters[0]); return client.textEmbeddingModel(modelId); } default: