From f58d34cf5ebc05d017ea9a2002a393f09f26274f Mon Sep 17 00:00:00 2001 From: ethernet Date: Thu, 17 Sep 2026 14:36:43 -0400 Subject: [PATCH] fix(install-e2e): pin the mock provider's endpoint in config.yaml The desktop smoke configured a provider as `model.provider: custom` plus OPENAI_BASE_URL/OPENAI_API_KEY in .env, with deliberately no provider entry in config.yaml. Every `installer-script+desktop` leg then died at its OLD checkpoint: the v2026.8.31 app boots behind the onboarding overlay ("No usable credentials found for custom. setup.status reports configured credentials, but runtime resolution still failed"), so the smoke's trial click on the composer never landed (225 retries against the covering div). That vintage resolves a bare `custom` only from config.yaml `custom_providers:` (name + base_url + key_env, with a bare-"custom" fallback to the first valid entry); the env pair stays for the trees that resolve the endpoint from the environment. Write both, replacing the entry this writer owns rather than stacking duplicates. --- tests-js/scripts/desktop-smoke.test.ts | 4 ++++ tests-js/scripts/mock-provider-config.ts | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tests-js/scripts/desktop-smoke.test.ts b/tests-js/scripts/desktop-smoke.test.ts index 0569bb3931..837de3e1a1 100644 --- a/tests-js/scripts/desktop-smoke.test.ts +++ b/tests-js/scripts/desktop-smoke.test.ts @@ -54,6 +54,10 @@ test('provider reconfiguration preserves feed, plugins, history and explicit fix updates: feed, plugins: { witness: true }, model: { provider: 'custom', temperature: 0.7, context_length: 12000 }, providers: {}, + // Exactly one entry, repointed at the second URL: a bare `custom` resolves + // from this list on every vintage, and reconfiguring must not stack + // duplicates. + custom_providers: [{ name: 'Mock', base_url: 'http://127.0.0.1:9001/v1', key_env: 'OPENAI_API_KEY' }], auxiliary: { title_generation: { enabled: false } }, approvals: { mode: 'smart' }, display: { interim_assistant_messages: true }, }) expect(fs.readFileSync(path.join(home, '.env'), 'utf8')).toBe('OTHER_TEST_VALUE=kept\nMOCK_API_KEY=e2e-mock-key\n') diff --git a/tests-js/scripts/mock-provider-config.ts b/tests-js/scripts/mock-provider-config.ts index 785366a473..45dcd24fba 100644 --- a/tests-js/scripts/mock-provider-config.ts +++ b/tests-js/scripts/mock-provider-config.ts @@ -9,11 +9,16 @@ const section = z.object({}).passthrough() const configSchema = z.object({ model: section.optional(), providers: section.optional(), + custom_providers: z.array(section).optional(), auxiliary: z.object({ title_generation: section.optional() }).passthrough().optional(), approvals: section.optional(), display: section.optional(), }).passthrough() +//: Entry name this writer owns in ``custom_providers``; reconfiguring replaces +//: it rather than stacking duplicates. +const MOCK_PROVIDER_NAME = 'Mock' + export function validateMockUrl(value: string): string { const url = new URL(value) if (url.protocol !== 'http:' || url.hostname !== '127.0.0.1' || !url.port @@ -40,12 +45,19 @@ export function writeMockProviderConfig( const merged = { ...config, model: { ...config.model, default: 'mock-model', provider: 'custom', context_length: modelContextLength ?? 64000 }, - // No named provider block: "an external OpenAI-compatible endpoint" is - // expressed by provider 'custom' + OPENAI_BASE_URL/OPENAI_API_KEY (written - // by writeEnvFile). A provider named 'mock' only resolved on trees that - // had registered such a profile, so older refs died with "Unknown - // provider 'mock'". + // Two shapes, one endpoint. `providers:` stays untouched (a provider named + // 'mock' only resolved on trees that had registered such a profile, so + // older refs died with "Unknown provider 'mock'"). A bare `custom` resolves + // from `custom_providers:` on every vintage -- v2026.8.31's desktop + // readiness check reports "No usable credentials found for custom ... + // runtime resolution still failed" without an entry here -- while the .env + // OPENAI_BASE_URL/OPENAI_API_KEY pair (writeEnvFile) is how trees that + // resolve the endpoint from the environment reach the same URL. providers: { ...config.providers }, + custom_providers: [ + ...(config.custom_providers ?? []).filter(entry => entry?.name !== MOCK_PROVIDER_NAME), + { name: MOCK_PROVIDER_NAME, base_url: `${url}/v1`, key_env: 'OPENAI_API_KEY' }, + ], auxiliary: { ...config.auxiliary, title_generation: { ...config.auxiliary?.title_generation, enabled: false } }, approvals: { ...config.approvals, mode: 'off' }, ...extra,