fix(azure_ai): let the caller's output_config from extra_body win over the legacy thinking upgrade

This commit is contained in:
mateo-berri 2026-09-02 16:23:52 -07:00
parent 277cb3a938
commit 683fc34044
2 changed files with 31 additions and 6 deletions

View file

@ -17,13 +17,14 @@ def _promote_extra_body_to_optional_params(optional_params: dict) -> None:
``output_config`` get auto-routed into ``extra_body`` by
``add_provider_specific_params_to_optional_params``. For the AzureAnthropic
route those keys must reach the request body and be validated, so promote
them. ``setdefault`` keeps explicit top-level values authoritative.
them. The caller's values overwrite mapped top-level duplicates, matching
the native ``anthropic`` provider, where the same passthrough lands on
top-level ``optional_params`` after mapping.
"""
extra_body: Final = optional_params.get("extra_body")
if not isinstance(extra_body, dict) or not extra_body:
return
for k, v in extra_body.items():
optional_params.setdefault(k, v)
optional_params.update(extra_body)
optional_params.pop("extra_body", None)

View file

@ -362,8 +362,8 @@ class TestAzureAnthropicConfig:
)
assert "xhigh" in str(exc_info.value)
def test_extra_body_promotion_does_not_clobber_top_level(self):
"""Top-level ``optional_params`` wins over duplicates in ``extra_body``."""
def test_extra_body_promotion_overrides_mapped_top_level(self):
"""The caller's ``extra_body`` wins over a mapped top-level duplicate, like the native ``anthropic`` passthrough."""
config = AzureAnthropicConfig()
messages = [{"role": "user", "content": "Hello"}]
@ -383,7 +383,31 @@ class TestAzureAnthropicConfig:
headers=headers,
)
assert result["output_config"] == {"effort": "low"}
assert result["output_config"] == {"effort": "high"}
def test_legacy_thinking_upgrade_keeps_caller_effort_from_extra_body(self, local_model_cost_map):
config = AzureAnthropicConfig()
mapped = config.map_openai_params(
non_default_params={"thinking": {"type": "enabled", "budget_tokens": 1024}, "max_tokens": 100},
optional_params={},
model="claude-opus-4-8",
drop_params=False,
)
assert mapped["thinking"] == {"type": "adaptive"}
assert mapped["output_config"] == {"effort": "low"}
result = config.transform_request(
model="claude-opus-4-8",
messages=[{"role": "user", "content": "Hello"}],
optional_params={**mapped, "extra_body": {"output_config": {"effort": "high"}}},
litellm_params={"api_key": "test-key"},
headers={"api-key": "test-key", "anthropic-version": "2023-06-01"},
)
assert result["thinking"] == {"type": "adaptive"}
assert result["output_config"] == {"effort": "high"}
assert "extra_body" not in result
def test_context_management_mixed_edits_beta_headers(self):
"""Test that context_management with both compact and other edits adds both beta headers"""