mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-31 04:07:52 +00:00
Takeover of #2430 (rebased onto master; the providers.ts hunk already landed there). Five command callsites still rebuilt partial gateway configs by hand, dropping file-plane API keys (config.json openai/anthropic/zeroentropy/openrouter keys), env-provided provider base URLs, and provider_chat_options: - src/commands/eval-takes-quality.ts: spread `{...cfg, ...process.env}` at top level, so the gateway's `env` field was never populated at all — availability/diagnose checks dereferenced undefined and threw. - src/commands/eval-cross-modal.ts: configureGatewayForCli hand-rolled both branches; now one buildGatewayConfig call. - src/commands/init.ts: all three configureGateway sites (merged- precedence helper + PGLite + Postgres init) now overlay the resolved model fields on loadConfig() and route through the adapter. - src/commands/migrations/in-process.ts: runMigrateOnlyCore same. Tests: new test/eval-takes-quality-gateway.test.ts (fails with a throw on the old code path); LLAMA_SERVER_RERANKER_BASE_URL added to the adapter passthrough sweep; cli-multimodal-integration now imports the real adapter instead of a hand-maintained mirror copy. KEY_FILES.md entries updated to current state. Co-authored-by: TheAngryPit <TheAngryPit@users.noreply.github.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
107 lines
4.1 KiB
TypeScript
107 lines
4.1 KiB
TypeScript
// v0.28.11 (PR #719, D5): cli connectEngine() DB→gateway plumbing.
|
|
//
|
|
// The unit tests for loadConfigWithEngine and embedMultimodal cover their
|
|
// own contracts but don't exercise the cli.ts glue that ties them together.
|
|
// Codex F3 flagged this as the actual bug site. This file drives the same
|
|
// merge + reconfigure sequence connectEngine() runs and asserts the gateway
|
|
// observed the DB-set value through buildGatewayConfig.
|
|
//
|
|
// PGLite-only: in-memory engine, no DATABASE_URL needed.
|
|
|
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from 'bun:test';
|
|
import { PGLiteEngine } from '../src/core/pglite-engine.ts';
|
|
import { loadConfigWithEngine, type GBrainConfig } from '../src/core/config.ts';
|
|
import { buildGatewayConfig } from '../src/core/ai/build-gateway-config.ts';
|
|
import {
|
|
configureGateway,
|
|
getEmbeddingModel,
|
|
getMultimodalModel,
|
|
resetGateway,
|
|
} from '../src/core/ai/gateway.ts';
|
|
|
|
let engine: PGLiteEngine;
|
|
|
|
beforeAll(async () => {
|
|
engine = new PGLiteEngine();
|
|
await engine.connect({});
|
|
await engine.initSchema();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await engine.disconnect();
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
resetGateway();
|
|
// Clear any prior config rows so tests are independent. setConfig with
|
|
// empty string is treated as undefined by loadConfigWithEngine (per
|
|
// dbStr semantics), so this is safe to call between tests.
|
|
await engine.setConfig('embedding_multimodal_model', '');
|
|
});
|
|
|
|
describe('cli connectEngine — embedding_multimodal_model DB→gateway plumbing', () => {
|
|
test('DB-set multimodal_model flows to gateway via merge + reconfigure', async () => {
|
|
await engine.setConfig('embedding_multimodal_model', 'voyage:voyage-multimodal-3');
|
|
|
|
const baseConfig: GBrainConfig = {
|
|
engine: 'pglite',
|
|
embedding_model: 'openai:text-embedding-3-large',
|
|
embedding_dimensions: 1536,
|
|
};
|
|
|
|
// First call mirrors cli.ts:715 (pre-engine-connect).
|
|
configureGateway(buildGatewayConfig(baseConfig));
|
|
expect(getMultimodalModel()).toBeUndefined();
|
|
|
|
// Second call mirrors cli.ts:776 (post-DB-merge).
|
|
const merged = await loadConfigWithEngine(engine, baseConfig);
|
|
expect(merged).not.toBeNull();
|
|
configureGateway(buildGatewayConfig(merged!));
|
|
|
|
// Primary embedding_model stays put (file/env wins); multimodal_model
|
|
// arrived via DB.
|
|
expect(getEmbeddingModel()).toBe('openai:text-embedding-3-large');
|
|
expect(getMultimodalModel()).toBe('voyage:voyage-multimodal-3');
|
|
});
|
|
|
|
test('file value wins over DB value (env > file > DB precedence at gateway level)', async () => {
|
|
await engine.setConfig('embedding_multimodal_model', 'voyage:voyage-3-large');
|
|
|
|
const baseConfig: GBrainConfig = {
|
|
engine: 'pglite',
|
|
embedding_model: 'openai:text-embedding-3-large',
|
|
embedding_dimensions: 1536,
|
|
embedding_multimodal_model: 'voyage:voyage-multimodal-3', // file plane
|
|
};
|
|
|
|
const merged = await loadConfigWithEngine(engine, baseConfig);
|
|
configureGateway(buildGatewayConfig(merged!));
|
|
|
|
expect(getMultimodalModel()).toBe('voyage:voyage-multimodal-3');
|
|
});
|
|
|
|
test('un-gated re-config: merged DB has no multimodal_model → gateway still gets re-configured', async () => {
|
|
// Codex F5 was about whether the un-gated re-config weakens an
|
|
// intentional contract. This test pins the actual behavior (D6 = B):
|
|
// re-config always fires when merge succeeds, even when no DB key
|
|
// changed. Schema-sizing fields stay stable because loadConfigWithEngine
|
|
// respects file/env first.
|
|
const baseConfig: GBrainConfig = {
|
|
engine: 'pglite',
|
|
embedding_model: 'openai:text-embedding-3-large',
|
|
embedding_dimensions: 1536,
|
|
};
|
|
|
|
configureGateway(buildGatewayConfig(baseConfig));
|
|
expect(getEmbeddingModel()).toBe('openai:text-embedding-3-large');
|
|
|
|
const merged = await loadConfigWithEngine(engine, baseConfig);
|
|
configureGateway(buildGatewayConfig(merged!));
|
|
|
|
// Primary model unchanged (DB had no override); the re-config is a
|
|
// semantic no-op for these fields.
|
|
expect(getEmbeddingModel()).toBe('openai:text-embedding-3-large');
|
|
expect(getMultimodalModel()).toBeUndefined();
|
|
});
|
|
});
|