fix: Merge branch 'main' into litellm_fix_messages_token_counter

This commit is contained in:
Ishaan Jaffer 2026-01-20 17:25:48 -08:00
commit 8f475a3f08
6 changed files with 104 additions and 2 deletions

View file

@ -397,6 +397,7 @@ router_settings:
| AUDIO_SPEECH_CHUNK_SIZE | Chunk size for audio speech processing. Default is 1024
| ANTHROPIC_API_KEY | API key for Anthropic service
| ANTHROPIC_API_BASE | Base URL for Anthropic API. Default is https://api.anthropic.com
| ANTHROPIC_TOKEN_COUNTING_BETA_VERSION | Beta version header for Anthropic token counting API. Default is `token-counting-2024-11-01`
| AWS_ACCESS_KEY_ID | Access Key ID for AWS services
| AWS_BATCH_ROLE_ARN | ARN of the AWS IAM role for batch operations
| AWS_DEFAULT_REGION | Default AWS region for service interactions when AWS_REGION is not set
@ -412,6 +413,8 @@ router_settings:
| AWS_WEB_IDENTITY_TOKEN | Web identity token for AWS
| AWS_WEB_IDENTITY_TOKEN_FILE | Path to file containing web identity token for AWS
| AZURE_API_VERSION | Version of the Azure API being used
| AZURE_AI_API_BASE | Base URL for Azure AI services (e.g., Azure AI Anthropic)
| AZURE_AI_API_KEY | API key for Azure AI services (e.g., Azure AI Anthropic)
| AZURE_AUTHORITY_HOST | Azure authority host URL
| AZURE_CERTIFICATE_PASSWORD | Password for Azure OpenAI certificate
| AZURE_CLIENT_ID | Client ID for Azure services

View file

@ -14,6 +14,8 @@ from litellm.llms.base_llm.base_utils import BaseLLMModelInfo, BaseTokenCounter
from litellm.llms.base_llm.chat.transformation import BaseLLMException
from litellm.types.llms.anthropic import (
ANTHROPIC_HOSTED_TOOLS,
ANTHROPIC_OAUTH_BETA_HEADER,
ANTHROPIC_OAUTH_TOKEN_PREFIX,
AllAnthropicToolsValues,
AnthropicMcpServerTool,
)
@ -371,6 +373,8 @@ class AnthropicModelInfo(BaseLLMModelInfo):
api_key: Optional[str] = None,
api_base: Optional[str] = None,
) -> Dict:
# Check for Anthropic OAuth token in headers
headers, api_key = optionally_handle_anthropic_oauth(headers=headers, api_key=api_key)
if api_key is None:
raise litellm.AuthenticationError(
message="Missing Anthropic API Key - A call is being made to anthropic but no key is set either in the environment variables or via params. Please set `ANTHROPIC_API_KEY` in your environment vars",

View file

@ -17,7 +17,11 @@ from litellm.types.llms.anthropic_messages.anthropic_response import (
from litellm.types.llms.anthropic_tool_search import get_tool_search_beta_header
from litellm.types.router import GenericLiteLLMParams
from ...common_utils import AnthropicError, AnthropicModelInfo
from ...common_utils import (
AnthropicError,
AnthropicModelInfo,
optionally_handle_anthropic_oauth,
)
DEFAULT_ANTHROPIC_API_BASE = "https://api.anthropic.com"
DEFAULT_ANTHROPIC_API_VERSION = "2023-06-01"
@ -68,8 +72,11 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
) -> Tuple[dict, Optional[str]]:
import os
# Check for Anthropic OAuth token in Authorization header
headers, api_key = optionally_handle_anthropic_oauth(headers=headers, api_key=api_key)
if api_key is None:
api_key = os.getenv("ANTHROPIC_API_KEY")
if "x-api-key" not in headers and api_key:
headers["x-api-key"] = api_key
if "anthropic-version" not in headers:

View file

@ -642,4 +642,8 @@ ANTHROPIC_TOOL_SEARCH_BETA_HEADER = "advanced-tool-use-2025-11-20"
# Effort beta header constant
ANTHROPIC_EFFORT_BETA_HEADER = "effort-2025-11-24"
# OAuth constants
ANTHROPIC_OAUTH_TOKEN_PREFIX = "sk-ant-oat"
ANTHROPIC_OAUTH_BETA_HEADER = "oauth-2025-04-20"

View file

@ -0,0 +1,84 @@
"""
Tests for Anthropic OAuth token handling for Claude Code Max integration.
"""
import os
import sys
# Add litellm to path
sys.path.insert(0, os.path.abspath("../../../../.."))
# Fake OAuth token for testing (not a real secret)
FAKE_OAUTH_TOKEN = "sk-ant-oat01-fake-token-for-testing-123456789abcdef"
def test_oauth_detection_in_common_utils():
"""Test 1: OAuth token detection in common_utils"""
from litellm.llms.anthropic.common_utils import optionally_handle_anthropic_oauth
headers = {"authorization": f"Bearer {FAKE_OAUTH_TOKEN}"}
updated_headers, extracted_api_key = optionally_handle_anthropic_oauth(headers, None)
assert extracted_api_key == FAKE_OAUTH_TOKEN
assert updated_headers["anthropic-beta"] == "oauth-2025-04-20"
assert updated_headers["anthropic-dangerous-direct-browser-access"] == "true"
def test_oauth_integration_in_validate_environment():
"""Test 2: OAuth integration in AnthropicConfig validate_environment"""
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
config = AnthropicModelInfo()
headers = {"authorization": f"Bearer {FAKE_OAUTH_TOKEN}"}
updated_headers = config.validate_environment(
headers=headers,
model="claude-3-haiku-20240307",
messages=[{"role": "user", "content": "Hello"}],
optional_params={},
litellm_params={},
api_key=None,
api_base=None,
)
assert updated_headers["x-api-key"] == FAKE_OAUTH_TOKEN
assert updated_headers["anthropic-dangerous-direct-browser-access"] == "true"
def test_oauth_detection_in_messages_transformation():
"""Test 3: OAuth detection in messages transformation"""
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
config = AnthropicMessagesConfig()
headers = {"authorization": f"Bearer {FAKE_OAUTH_TOKEN}"}
updated_headers, _ = config.validate_anthropic_messages_environment(
headers=headers,
model="claude-3-haiku-20240307",
messages=[{"role": "user", "content": "Hello"}],
optional_params={},
litellm_params={},
api_key=None,
api_base=None,
)
assert updated_headers["x-api-key"] == FAKE_OAUTH_TOKEN
assert "oauth-2025-04-20" in updated_headers["anthropic-beta"]
assert updated_headers["anthropic-dangerous-direct-browser-access"] == "true"
def test_regular_api_keys_still_work():
"""Test 4: Regular API keys still work (regression test)"""
from litellm.llms.anthropic.common_utils import optionally_handle_anthropic_oauth
regular_key = "sk-ant-api03-regular-key-123"
headers = {"authorization": f"Bearer {regular_key}"}
updated_headers, extracted_api_key = optionally_handle_anthropic_oauth(headers, regular_key)
# Regular key should be unchanged
assert extracted_api_key == regular_key
# OAuth headers should NOT be added
assert "anthropic-dangerous-direct-browser-access" not in updated_headers

View file

@ -6,5 +6,5 @@ class TestVertexAIGenerateContent(BaseGoogleGenAITest):
@property
def model_config(self):
return {
"model": "vertex_ai/gemini-2.5-flash-lite",
"model": "vertex_ai/gemini-3-flash-preview",
}