diff --git a/litellm/completion_extras/litellm_responses_transformation/transformation.py b/litellm/completion_extras/litellm_responses_transformation/transformation.py index 55a8e665bb..5b206317b2 100644 --- a/litellm/completion_extras/litellm_responses_transformation/transformation.py +++ b/litellm/completion_extras/litellm_responses_transformation/transformation.py @@ -691,19 +691,19 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge): if isinstance(reasoning_effort, dict): return Reasoning(**reasoning_effort) # type: ignore[typeddict-item] - # If string is passed, map without summary (default) + # If string is passed, map with summary="detailed" if reasoning_effort == "none": - return Reasoning(effort="none") # type: ignore + return Reasoning(effort="none", summary="detailed") # type: ignore elif reasoning_effort == "high": - return Reasoning(effort="high") + return Reasoning(effort="high", summary="detailed") elif reasoning_effort == "xhigh": - return Reasoning(effort="xhigh") # type: ignore[typeddict-item] + return Reasoning(effort="xhigh", summary="detailed") # type: ignore[typeddict-item] elif reasoning_effort == "medium": - return Reasoning(effort="medium") + return Reasoning(effort="medium", summary="detailed") elif reasoning_effort == "low": - return Reasoning(effort="low") + return Reasoning(effort="low", summary="detailed") elif reasoning_effort == "minimal": - return Reasoning(effort="minimal") + return Reasoning(effort="minimal", summary="detailed") return None def _transform_response_format_to_text_format( diff --git a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py index 4320c932f4..6490352c39 100644 --- a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py +++ b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py @@ -1007,3 +1007,43 @@ def test_multiple_tool_calls_in_single_choice(): assert tool_calls[2]["function"]["name"] == "get_horoscope" print("✓ Multiple tool calls are correctly grouped in a single choice") + + +def test_map_reasoning_effort_adds_summary_detailed(): + """ + Test that _map_reasoning_effort adds summary="detailed" when user provides reasoning_effort as a string. + + This ensures that when users pass reasoning_effort in the completions API for OpenAI responses/models, + the transformation automatically includes summary="detailed" in the reasoning parameter. + """ + from litellm.completion_extras.litellm_responses_transformation.transformation import ( + LiteLLMResponsesTransformationHandler, + ) + + handler = LiteLLMResponsesTransformationHandler() + + # Test all string effort levels + effort_levels = ["none", "low", "medium", "high", "xhigh", "minimal"] + + for effort in effort_levels: + result = handler._map_reasoning_effort(effort) + + assert result is not None, f"Result should not be None for effort={effort}" + assert result["effort"] == effort, f"Effort should be {effort}" + assert result["summary"] == "detailed", f"Summary should be 'detailed' for effort={effort}" + + print(f"✓ reasoning_effort='{effort}' correctly maps to effort='{effort}', summary='detailed'") + + # Test that dict input is passed through as-is (no modification) + dict_input = {"effort": "high", "summary": "custom_summary"} + result_dict = handler._map_reasoning_effort(dict_input) + assert result_dict["effort"] == "high" + assert result_dict["summary"] == "custom_summary" + print("✓ Dict input is passed through without modification") + + # Test that None/unknown values return None + result_unknown = handler._map_reasoning_effort("unknown_value") + assert result_unknown is None + print("✓ Unknown reasoning_effort values return None") + + print("✓ All reasoning_effort string values correctly map to summary='detailed'")