Skip to content

fix(config): endpoint-derived API keys outrank provider defaults in selectRuntimeApiKey#682

Merged
simongonzalezdc merged 1 commit into
mainfrom
fix/custom-endpoint-key-precedence
Jun 10, 2026
Merged

fix(config): endpoint-derived API keys outrank provider defaults in selectRuntimeApiKey#682
simongonzalezdc merged 1 commit into
mainfrom
fix/custom-endpoint-key-precedence

Conversation

@simongonzalezdc

Copy link
Copy Markdown
Member

Bug

selectRuntimeApiKey() in src/config/ProviderRuntime.ts built its non-generic candidate list as [...providerKeys, ...endpointKeys]. For provider 'custom', apiKeyEnvNamesForProvider returns ['OPENAI_API_KEY'], which therefore outranked the endpoint-derived keys.

Consequence: a custom endpoint pointed at api.anthropic.com (endpoint keys ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN) or generativelanguage.googleapis.com (GOOGLE_API_KEY/GEMINI_API_KEY) with OPENAI_API_KEY also set in the environment sent the OpenAI key to the wrong API → auth failure.

Concrete repro path: getHarnessProviderConfig() (src/harness/MultiProviderConfig.ts) with LIMINAL_HARNESS_BASE_URL=https://api.anthropic.com/v1 calls selectRuntimeApiKey with provider='custom' and genericFirst false.

Fix

One-line precedence reorder: endpoint-derived keys now come before provider-default keys. Rationale: the endpoint is what the request actually hits, so its keys must win.

First-class providers are unaffected — for every menu provider (minimax, glm, kimi, moonshot, openai, openrouter, ollama, lmstudio), apiKeyEnvNamesForEndpoint resolves to the same key set as apiKeyEnvNamesForProvider (verified per-host through detectProviderAdapter/detectProviderLabel), so the reorder only changes behavior when provider and endpoint genuinely diverge — which is exactly the bug case. configuredApiKey/currentApiKey still rank first; genericFirst block ordering is unchanged.

Tests (TDD)

New regression test (red → green): anthropic and google endpoints with both the OpenAI key and the endpoint key set assert the exact endpoint key is selected; a plain OpenAI-compatible custom endpoint asserts OPENAI_API_KEY still applies.

pnpm exec vitest run test/unit/config/ProviderRuntime.test.ts test/unit/harness/MultiProviderConfig.test.ts test/unit/tui/ProviderCommand.test.ts test/unit/llm/ProviderFactory.test.ts
Test Files  4 passed (4)
     Tests  109 passed (109)

pnpm exec eslint src/config/ProviderRuntime.ts clean.

Relation to #681

#681 (open) documents the menu-vs-adapter layering and pins URL→adapter routing; this PR fixes the real key-precedence edge found during that investigation. Edits are placed away from #681's hunks (different function / different test position), so the two merge independently in either order.

🤖 Generated with Claude Code

selectRuntimeApiKey ordered provider-default keys before endpoint-derived
keys, so a 'custom' provider pointed at api.anthropic.com or
generativelanguage.googleapis.com with OPENAI_API_KEY also set sent the
OpenAI key to the wrong API (auth failure). Repro: getHarnessProviderConfig
with LIMINAL_HARNESS_BASE_URL=https://api.anthropic.com/v1.

The endpoint is what the request hits, so its keys win; first-class
providers are unaffected because their provider and endpoint key sets
coincide. Regression test covers anthropic/google endpoints with both
keys set, plus the unchanged OpenAI-compatible custom path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@simongonzalezdc simongonzalezdc merged commit 9987adb into main Jun 10, 2026
8 checks passed
@simongonzalezdc simongonzalezdc deleted the fix/custom-endpoint-key-precedence branch June 10, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant