feat(ai-providers): Bearer auth for Anthropic-compatible gateways (MiniMax intl)#228
Merged
Merged
Conversation
The Workspace AI Provider modal only ever sent the key via x-api-key
(ANTHROPIC_API_KEY). anthropic-compatible gateways that authenticate via
Authorization: Bearer — notably MiniMax's international endpoint
(api.minimax.io) — reject that with a 401 ("carry the key in X-Api-Key
field"), even though the China endpoint (api.minimaxi.com) tolerates
x-api-key. The Test button faithfully mirrored the broken real-session
auth, so it failed too.
Add a Claude-only "Auth header" dropdown: x-api-key (default, unchanged
for first-party Anthropic) vs Authorization: Bearer. The probe, the
.claude/settings.local.json writer/reader, and the form state all carry
the mode. Writer emits exactly one of ANTHROPIC_API_KEY /
ANTHROPIC_AUTH_TOKEN — never both, since dual auth headers can be
rejected as ambiguous and Claude Code warns when both are set.
Profiles can optionally pin authMode so a future MiniMax-international
profile applies Bearer on "Apply" (field is read-through only for now;
the OpenAlice profile schema doesn't yet emit it).
https://claude.ai/code/session_01XPhP1PsJR9A3PVz1BjQUw1
Light Apply hookup for the Bearer auth mode added in the prior commit: - Profile schema (config.ts baseProfileFields) gains optional `authMode` so a stored profile can pin x-api-key vs bearer. Additive only — the in-process GenerateRouter runtime does NOT yet honor it (deferred). - /agent-profiles surfaces authMode so the workspace modal's "Apply from OpenAlice profile" pre-fills the right header mode. - MiniMax preset: add authMode to its schema, defaulting to `bearer`. MiniMax documents Authorization: Bearer (ANTHROPIC_AUTH_TOKEN) for all endpoints and the international site (api.minimax.io) rejects x-api-key, so bearer is the vendor-correct default that works on both .com and .io (the .io endpoint option already existed in the catalog). https://claude.ai/code/session_01XPhP1PsJR9A3PVz1BjQUw1
…(ANG-72) Closes the half-wired authMode field: the legacy chat path now sends the right Anthropic auth header (x-api-key vs Authorization: Bearer) per profile, not just the workspace path. Fixes MiniMax-international (api.minimax.io, which rejects x-api-key) 401s on Telegram / MCP Ask / heartbeat / chat, and makes the AI-Provider Test button mirror the real session instead of passing-while-chat-fails. Single source of truth: resolveAnthropicAuthMode(profile) in credential-inference.ts. Explicit profile.authMode wins; otherwise infers `bearer` ONLY for api.minimax.io (the one endpoint confirmed to reject x-api-key) so pre-existing MiniMax-intl profiles work without recreation. Other gateways (GLM/Kimi/DeepSeek) stay at the x-api-key default — over- promoting would silently break a working setup. Three auth-header construction sites now consume it: - agent-sdk (chat): query.ts emits exactly one of ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY, never both (extracted as pure buildAuthEnv + spec — the "never dual-set" invariant is the security-sensitive bit). Mirrors the workspace .claude/settings.local.json writer from the prior commit. - vercel-ai-sdk (chat): model-factory anthropic case passes authToken vs apiKey to createAnthropic. - sdk-adapters (Test button): resolveTestAdapter threads the resolved mode onto the vercel-anthropic / agent-sdk declarations. Only bearer is injected, so the common first-party path stays byte-identical. ResolvedProfile gains authMode (carries through resolveProfile's spread). Tests: +18 (buildAuthEnv invariants, resolveAnthropicAuthMode decision table, adapter threading + invoker authToken translation). Full suite 1811 passing; tsc --noEmit clean. Boundary touch: auth (AI-provider credentials only — no broker/trading/UTA). https://claude.ai/code/session_01XPhP1PsJR9A3PVz1BjQUw1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
x-api-key. Gateways that authenticate withAuthorization: Bearer— notably MiniMax's international endpointapi.minimax.io— reject that with a 401, while the China endpoint (minimaxi.com) tolerates it. This adds per-profile Bearer support end-to-end..claude/settings.local.jsonwriter/reader carry the mode, emitting exactly one ofANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN.authMode;/agent-profilessurfaces it so "Apply from profile" pre-fills the right mode; MiniMax preset defaults to Bearer (correct for both.comand.io).authMode. Single source of truthresolveAnthropicAuthMode(profile)— explicit choice wins; otherwise infersbeareronly forapi.minimax.ioso pre-existing MiniMax-intl profiles work without recreation. Three header-construction sites consume it: agent-sdk env (buildAuthEnv, never dual-sets the two key vars), vercel-ai-sdk anthropic client (authTokenvsapiKey), and the AI-Provider Test button (so test mirrors the real session instead of passing-while-chat-401s).Test plan
tsc --noEmitcleanpnpm testpasses (1811 passing; +18 new:buildAuthEnvinvariants,resolveAnthropicAuthModedecision table, adapter threading + invoker authToken translation)api.minimax.io) with a real key and confirm chat + Test button both succeed (key is region-locked; deferred to whoever has one)Boundary touch
Touches auth — AI-provider credential handling only (which header carries the model API key). No broker / trading / UTA / migration surface.
🤖 Generated with Claude Code
Generated by Claude Code