fix(anthropic): skip credential refresh for third-party endpoints

With provider 'anthropic' pointed at a third-party Anthropic-compatible
endpoint, _try_refresh_anthropic_client_credentials only skipped Azure and
otherwise re-resolved native Anthropic credentials (ANTHROPIC_API_KEY, the
stored OAuth token) and rebuilt the client with them, so the endpoint got
a credential it was never given. Skip the refresh for any endpoint
build_anthropic_client already classifies as third-party.

Ported from run_agent.py onto agent/client_lifecycle.py, where the method
lives now; the separate Azure test is dropped (Azure is one such endpoint).

Salvaged from #17829.
This commit is contained in:
leemove
2026-09-23 07:03:39 -07:00
committed by Teknium
parent 94c0e49307
commit 96ff42ff66
2 changed files with 26 additions and 1 deletions

View File

@@ -872,10 +872,13 @@ class ClientLifecycleMixin:
def _try_refresh_anthropic_client_credentials(self) -> bool:
# Only native Anthropic rotates OAuth tokens; other anthropic_messages providers (MiniMax, Alibaba, ...)
# and Azure use static keys — a refresh would pick up the ~/.claude OAuth token and break auth.
# Third-party Anthropic-compatible endpoints under provider 'anthropic' use static keys too;
# skip them with the same detection build_anthropic_client uses.
from agent.anthropic_endpoints import _is_third_party_anthropic_endpoint
if (
self.api_mode != "anthropic_messages" or not hasattr(self, "_anthropic_api_key")
or self.provider != "anthropic"
or base_url_host_matches(getattr(self, "_anthropic_base_url", "") or "", "azure.com")
or _is_third_party_anthropic_endpoint(getattr(self, "_anthropic_base_url", "") or "")
):
return False
try:

View File

@@ -75,6 +75,28 @@ class TestOAuthFlagOnRefresh:
# And the flag is untouched regardless.
assert agent._is_anthropic_oauth is False
def test_third_party_endpoint_skips_refresh(self, agent):
"""provider == 'anthropic' on a third-party endpoint must not refresh: the refresh
would swap in native Anthropic credentials the endpoint was never given."""
agent.api_mode = "anthropic_messages"
agent.provider = "anthropic"
agent._anthropic_api_key = "custom-api-key"
agent._anthropic_base_url = "https://llmbox.bytedance.net"
agent._anthropic_client = MagicMock()
agent._is_anthropic_oauth = False
with (
patch("agent.anthropic_credentials.resolve_anthropic_token",
return_value=_OAUTH_LIKE_TOKEN),
patch("agent.anthropic_adapter.build_anthropic_client",
return_value=MagicMock()),
):
result = agent._try_refresh_anthropic_client_credentials()
assert result is False
assert agent._anthropic_api_key == "custom-api-key"
assert agent._is_anthropic_oauth is False
class TestOAuthFlagOnCredentialSwap: