fix(anthropic): scope MiniMax beta-strip to MiniMax only

Cherry-pick of @sharziki's #27022 routed Azure Foundry through
_requires_bearer_auth, which also triggered the MiniMax-specific
beta-strip in _common_betas_for_base_url — dropping the 1M-context
beta from Azure even though Azure needs it for 1M context.

Split the strip predicate: introduce _is_minimax_anthropic_endpoint
so the fine-grained-tool-streaming and context-1m strips only fire
for MiniMax hosts, leaving Azure's bearer-auth header swap intact
without losing 1M context.

Also add a regression test that asserts Azure gets Bearer auth,
the api-version query param, and the context-1m-2025-08-07 beta.
This commit is contained in:
teknium 2026-05-18 09:23:50 -07:00 committed by Teknium
parent 73407b1e30
commit f0c6d59148
2 changed files with 40 additions and 2 deletions

View file

@ -493,6 +493,21 @@ def _base_url_needs_context_1m_beta(base_url: str | None) -> bool:
return "azure.com" in normalized
def _is_minimax_anthropic_endpoint(base_url: str | None) -> bool:
"""Return True for MiniMax's Anthropic-compatible endpoints.
MiniMax rejects the fine-grained-tool-streaming and context-1m betas;
those need to be stripped even though MiniMax also uses Bearer auth.
"""
normalized = _normalize_base_url_text(base_url)
if not normalized:
return False
normalized = normalized.rstrip("/").lower()
return normalized.startswith(
("https://api.minimax.io/anthropic", "https://api.minimaxi.com/anthropic")
)
def _common_betas_for_base_url(
base_url: str | None,
*,
@ -502,7 +517,9 @@ def _common_betas_for_base_url(
MiniMax's Anthropic-compatible endpoints (Bearer-auth) reject requests
that include Anthropic's ``fine-grained-tool-streaming`` beta — every
tool-use message triggers a connection error.
tool-use message triggers a connection error. They also reject the
1M-context beta. Azure AI Foundry's Anthropic endpoint also uses
Bearer auth but keeps both betas (it needs the 1M beta for 1M context).
The ``context-1m-2025-08-07`` beta is not sent to native Anthropic by
default because some subscriptions reject it. Add it only for endpoint
@ -515,7 +532,7 @@ def _common_betas_for_base_url(
betas = list(_COMMON_BETAS)
if _base_url_needs_context_1m_beta(base_url) and not drop_context_1m_beta:
betas.append(_CONTEXT_1M_BETA)
if _requires_bearer_auth(base_url):
if _is_minimax_anthropic_endpoint(base_url):
_stripped = {_TOOL_STREAMING_BETA, _CONTEXT_1M_BETA}
return [b for b in betas if b not in _stripped]
if drop_context_1m_beta:

View file

@ -155,6 +155,27 @@ class TestBuildAnthropicClient:
"anthropic-beta": "interleaved-thinking-2025-05-14"
}
def test_azure_foundry_anthropic_endpoint_uses_bearer_auth(self):
"""Azure AI Foundry's /anthropic endpoint requires Authorization: Bearer.
Regression test for #26970: without this, builds set api_key (x-api-key)
and the endpoint returns HTTP 401. Also verifies that Azure retains the
1M-context beta even though it now matches `_requires_bearer_auth`.
"""
with patch("agent.anthropic_adapter._anthropic_sdk") as mock_sdk:
build_anthropic_client(
"azure-foundry-secret-123",
base_url="https://my-resource.openai.azure.com/anthropic",
)
kwargs = mock_sdk.Anthropic.call_args[1]
assert kwargs["auth_token"] == "azure-foundry-secret-123"
assert "api_key" not in kwargs
# Azure endpoints still get the api-version query param plumbing.
assert kwargs.get("default_query") == {"api-version": "2025-04-15"}
# Azure keeps the 1M-context beta (it's not MiniMax).
betas = kwargs["default_headers"]["anthropic-beta"]
assert "context-1m-2025-08-07" in betas
class TestReadClaudeCodeCredentials:
@pytest.fixture(autouse=True)