Skip to content

feat(ai-providers): Bearer auth for Anthropic-compatible gateways (MiniMax intl)#228

Merged
luokerenx4 merged 3 commits into
masterfrom
claude/minimax-api-key-config-QHB3V
May 29, 2026
Merged

feat(ai-providers): Bearer auth for Anthropic-compatible gateways (MiniMax intl)#228
luokerenx4 merged 3 commits into
masterfrom
claude/minimax-api-key-config-QHB3V

Conversation

@luokerenx4
Copy link
Copy Markdown
Contributor

Summary

  • OpenAlice only ever sent the Anthropic key via x-api-key. Gateways that authenticate with Authorization: Bearer — notably MiniMax's international endpoint api.minimax.io — reject that with a 401, while the China endpoint (minimaxi.com) tolerates it. This adds per-profile Bearer support end-to-end.
  • Workspace path (commit 1): Claude AI-config modal gains an "Auth header" dropdown (x-api-key vs Bearer); probe + .claude/settings.local.json writer/reader carry the mode, emitting exactly one of ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN.
  • Profile + preset wiring (commit 2): profile schema gains optional authMode; /agent-profiles surfaces it so "Apply from profile" pre-fills the right mode; MiniMax preset defaults to Bearer (correct for both .com and .io).
  • Legacy chat-path runtime (commit 3, ANG-72): GenerateRouter now honors authMode. Single source of truth resolveAnthropicAuthMode(profile) — explicit choice wins; otherwise infers bearer only for api.minimax.io so 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 (authToken vs apiKey), and the AI-Provider Test button (so test mirrors the real session instead of passing-while-chat-401s).

Test plan

  • tsc --noEmit clean
  • pnpm test passes (1811 passing; +18 new: buildAuthEnv invariants, resolveAnthropicAuthMode decision table, adapter threading + invoker authToken translation)
  • Manual: configure a MiniMax-international profile (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

claude added 3 commits May 29, 2026 06:29
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
@luokerenx4 luokerenx4 merged commit 8012bcf into master May 29, 2026
1 check passed
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.

2 participants