fix(bedrock/claude_platform): align messages beta headers with filtered body

validate_anthropic_messages_environment derived anthropic-beta from unfiltered optional_params, while transform_anthropic_messages_request strips context_management from the body. Requests advertised a beta the body did not use. Filter optional_params with the same helper before computing headers (silently, to avoid a duplicate warning since the transform path still logs once).
This commit is contained in:
Cursor Agent 2026-06-24 16:19:03 +00:00
parent 4320f5eb9e
commit 934ae7dd7f
No known key found for this signature in database
3 changed files with 75 additions and 2 deletions

View file

@ -34,6 +34,7 @@ CLAUDE_PLATFORM_ON_AWS_UNSUPPORTED_REQUEST_PARAMS = {
def filter_claude_platform_request_body(
params: dict,
unsupported_override: Optional[frozenset[str]] = None,
log_dropped: bool = True,
) -> dict:
"""Return a copy of ``params`` with fields the Claude Platform on AWS
endpoint rejects removed.
@ -58,7 +59,7 @@ def filter_claude_platform_request_body(
else CLAUDE_PLATFORM_ON_AWS_UNSUPPORTED_REQUEST_PARAMS
)
dropped_unsupported = [k for k in params if k in unsupported]
if dropped_unsupported:
if dropped_unsupported and log_dropped:
verbose_logger.warning(
"bedrock/claude_platform: dropping unsupported Messages API "
"param(s) %s from the request body - the Claude Platform on AWS "

View file

@ -52,9 +52,15 @@ class BedrockClaudePlatformMessagesConfig(
if resolved_api_key and "x-api-key" not in headers:
headers["x-api-key"] = resolved_api_key
unsupported_override = resolve_unsupported_override(litellm_params)
filtered_optional_params = filter_claude_platform_request_body(
optional_params,
unsupported_override=unsupported_override,
log_dropped=False,
)
headers = self._update_headers_with_anthropic_beta(
headers=headers,
optional_params=optional_params,
optional_params=filtered_optional_params,
)
return headers, api_base

View file

@ -507,6 +507,72 @@ def test_claude_platform_unsupported_override_ignores_invalid_type():
assert request_body["max_tokens"] == 10
def test_claude_platform_messages_does_not_advertise_beta_for_stripped_context_management():
"""
Regression: validate_anthropic_messages_environment used to compute
anthropic-beta from unfiltered optional_params, while
transform_anthropic_messages_request strips context_management from the
body. The resulting request claimed a beta the body did not use, which
can trip strict gateway validation. Headers must be derived from the
same filtered view as the body.
"""
import litellm
from litellm.types.utils import LlmProviders
config = litellm.ProviderConfigManager.get_provider_anthropic_messages_config(
model="claude_platform/claude-sonnet-4-6",
provider=LlmProviders.BEDROCK,
)
assert config is not None
headers, _ = config.validate_anthropic_messages_environment(
api_key="fake-platform-key",
headers={},
model="claude_platform/claude-sonnet-4-6",
messages=[{"role": "user", "content": "hello"}],
optional_params={
"max_tokens": 10,
"context_management": {"edits": [{"type": "clear_tool_uses_20250919"}]},
},
litellm_params={"workspace_id": "wrkspc_test"},
)
assert "context-management-2025-06-27" not in headers.get("anthropic-beta", "")
def test_claude_platform_messages_override_keeps_beta_for_context_management():
"""
When the operator opts back into context_management via
claude_platform_unsupported_params=[], the body keeps the field and the
header must still advertise the matching beta.
"""
import litellm
from litellm.types.utils import LlmProviders
config = litellm.ProviderConfigManager.get_provider_anthropic_messages_config(
model="claude_platform/claude-sonnet-4-6",
provider=LlmProviders.BEDROCK,
)
assert config is not None
headers, _ = config.validate_anthropic_messages_environment(
api_key="fake-platform-key",
headers={},
model="claude_platform/claude-sonnet-4-6",
messages=[{"role": "user", "content": "hello"}],
optional_params={
"max_tokens": 10,
"context_management": {"edits": [{"type": "clear_tool_uses_20250919"}]},
},
litellm_params={
"workspace_id": "wrkspc_test",
"claude_platform_unsupported_params": [],
},
)
assert "context-management-2025-06-27" in headers.get("anthropic-beta", "")
def test_claude_platform_messages_unsupported_override_allows_context_management():
"""
Messages-path: operators can pass claude_platform_unsupported_params=[]