From cb8b9c0e0bf7ace558d4c73ad7bf5984beff1d02 Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Mon, 19 Oct 2026 12:44:58 -0400 Subject: [PATCH 1/7] fix: prevent reasoning field from being copied into provider_specific_fields --- .../convert_dict_to_response.py | 2 +- .../test_convert_dict_to_response.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py index f3c60679c81..592755ac29e 100644 --- a/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py +++ b/litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py @@ -741,7 +741,7 @@ def convert_to_model_response_object( # Preserve provider_specific_fields if already present # in the response (e.g. from proxy passthrough) provider_specific_fields = dict(choice["message"].get("provider_specific_fields", None) or {}) - for f in choice["message"].keys() - _MESSAGE_FIELDS: + for f in choice["message"].keys() - _MESSAGE_FIELDS - {"reasoning"}: provider_specific_fields[f] = choice["message"][f] # Handle reasoning models that display `reasoning_content` within `content` diff --git a/tests/unit/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py b/tests/unit/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py index 0c601a6b2c8..51b47d8c014 100644 --- a/tests/unit/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py +++ b/tests/unit/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py @@ -2873,6 +2873,28 @@ class TestConvertToModelResponseObjectCompletion: assert message.reasoning_content == "2+2=4" assert "reasoning_content" not in (message.provider_specific_fields or {}) + def test_reasoning_not_mirrored_into_provider_specific_fields(self): + response_object = { + "id": "chatcmpl-6", + "model": "openrouter/deepseek/deepseek-r1", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": {"content": "The answer is 4.", "role": "assistant", "reasoning": "2+2=4"}, + } + ], + "usage": {"prompt_tokens": 5, "completion_tokens": 10, "total_tokens": 15}, + } + + result = convert_to_model_response_object( + response_object=response_object, + model_response_object=ModelResponse(), + ) + message = result.choices[0].message + assert message.reasoning_content == "2+2=4" + assert "reasoning" not in (message.provider_specific_fields or {}) + def test_response_none_raises(self): with pytest.raises(Exception, match="Invalid response object"): convert_to_model_response_object( From 953b93d1a87293bbf3663f2ca7f83726b56cfbe2 Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Mon, 19 Oct 2026 12:45:28 -0400 Subject: [PATCH 2/7] fix: ensure reasoning field in provider_specific_fields is redacted --- litellm/litellm_core_utils/redact_messages.py | 1 + tests/unit/litellm_core_utils/test_redact_messages.py | 1 + 2 files changed, 2 insertions(+) diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index c2cca5739cf..55741790954 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -147,6 +147,7 @@ def _redacted_provider_specific_fields(fields: Mapping[str, object]) -> Mapping[ return { **fields, **({"reasoning_content": REDACTED_BY_LITELLM} if fields.get("reasoning_content") is not None else {}), + **({"reasoning": REDACTED_BY_LITELLM} if fields.get("reasoning") is not None else {}), **{key: None for key in ("thinking_blocks", "reasoningContentBlocks", "citations") if key in fields}, } diff --git a/tests/unit/litellm_core_utils/test_redact_messages.py b/tests/unit/litellm_core_utils/test_redact_messages.py index d14f236f765..f279cf82cef 100644 --- a/tests/unit/litellm_core_utils/test_redact_messages.py +++ b/tests/unit/litellm_core_utils/test_redact_messages.py @@ -51,6 +51,7 @@ SIGNATURE: Final = "opaque-thought-signature" def _provider_fields() -> dict[str, object]: return { "reasoning_content": SECRET, + "reasoning": SECRET, "thinking_blocks": [{"type": "thinking", "thinking": SECRET}], "reasoningContentBlocks": [{"reasoningText": {"text": SECRET}}], "citations": [{"cited_text": SECRET}], From eac21e5beea2e5f66568023162d7b8ab8ac11c29 Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Mon, 19 Oct 2026 15:44:37 -0400 Subject: [PATCH 3/7] fix: redact reasoning_details in provider_specific_fields --- litellm/litellm_core_utils/redact_messages.py | 2 +- tests/unit/litellm_core_utils/test_redact_messages.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index 55741790954..18bacc88c6c 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -148,7 +148,7 @@ def _redacted_provider_specific_fields(fields: Mapping[str, object]) -> Mapping[ **fields, **({"reasoning_content": REDACTED_BY_LITELLM} if fields.get("reasoning_content") is not None else {}), **({"reasoning": REDACTED_BY_LITELLM} if fields.get("reasoning") is not None else {}), - **{key: None for key in ("thinking_blocks", "reasoningContentBlocks", "citations") if key in fields}, + **{key: None for key in ("thinking_blocks", "reasoningContentBlocks", "citations", "reasoning_details") if key in fields}, } diff --git a/tests/unit/litellm_core_utils/test_redact_messages.py b/tests/unit/litellm_core_utils/test_redact_messages.py index f279cf82cef..dc9148f6526 100644 --- a/tests/unit/litellm_core_utils/test_redact_messages.py +++ b/tests/unit/litellm_core_utils/test_redact_messages.py @@ -52,6 +52,7 @@ def _provider_fields() -> dict[str, object]: return { "reasoning_content": SECRET, "reasoning": SECRET, + "reasoning_details": [{"type": "reasoning.text", "text": SECRET, "index": 0, "format": "unknown"}], "thinking_blocks": [{"type": "thinking", "thinking": SECRET}], "reasoningContentBlocks": [{"reasoningText": {"text": SECRET}}], "citations": [{"cited_text": SECRET}], From a705bc96fbe0f79e7eee69665812bd6d775ad13c Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Tue, 20 Oct 2026 10:28:23 -0400 Subject: [PATCH 4/7] fix: format redact_messages.py --- litellm/litellm_core_utils/redact_messages.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index 18bacc88c6c..286f2aa8b77 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -148,7 +148,11 @@ def _redacted_provider_specific_fields(fields: Mapping[str, object]) -> Mapping[ **fields, **({"reasoning_content": REDACTED_BY_LITELLM} if fields.get("reasoning_content") is not None else {}), **({"reasoning": REDACTED_BY_LITELLM} if fields.get("reasoning") is not None else {}), - **{key: None for key in ("thinking_blocks", "reasoningContentBlocks", "citations", "reasoning_details") if key in fields}, + **{ + key: None + for key in ("thinking_blocks", "reasoningContentBlocks", "citations", "reasoning_details") + if key in fields + }, } From 8dac8abe2bdf00b6814204b474303eb745d9ad95 Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Tue, 20 Oct 2026 11:04:39 -0400 Subject: [PATCH 5/7] ci: retrigger From c868913614c24ed02ccdc3dc7d34e3b5a44236ed Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Tue, 20 Oct 2026 11:22:05 -0400 Subject: [PATCH 6/7] ci: retrigger From 769327965f44c7d8a0ce886f4e8cf1f96a35bef7 Mon Sep 17 00:00:00 2001 From: alchemicjon Date: Tue, 20 Oct 2026 11:38:44 -0400 Subject: [PATCH 7/7] ci: retrigger