This commit is contained in:
Charlie Freeman 2026-10-28 20:50:36 +08:00 • committed by GitHub
commit 9d24b3df8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 0 deletions

View file

@ -1006,6 +1006,7 @@ class CustomStreamWrapper:
and model_response.choices[0].delta.role is not None
)
or (getattr(model_response.choices[0].delta, "reasoning_items", None) is not None)
or bool(getattr(model_response.choices[0].delta, "reasoning_details", None))
):
return True
else:

View file

@ -10093,6 +10093,8 @@ def _fast_serialize_simple_model_response_stream(
"thinking_blocks",
"provider_specific_fields",
"refusal",
"reasoning_items",
"reasoning_details",
)
if any(getattr(delta, field, None) is not None for field in unsupported_delta_fields):
return None

View file

@ -0,0 +1,75 @@
from unittest.mock import MagicMock
from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper
from litellm.types.utils import ModelResponseStream
def test_is_chunk_non_empty_with_reasoning_details():
"""
Unit test that chunks carrying only delta.reasoning_details (e.g., OpenRouter
Anthropic signatures or encrypted reasoning blobs) are treated as non-empty.
Regression test for https://github.com/BerriAI/litellm/issues/48401
"""
wrapper = CustomStreamWrapper(
completion_stream=iter([]),
model="anthropic/claude-sonnet-4.5",
custom_llm_provider="openrouter",
logging_obj=MagicMock(),
)
chunk_with_signature = {
"id": "gen-sig-1",
"object": "chat.completion.chunk",
"created": 1741037890,
"model": "anthropic/claude-sonnet-4.5",
"choices": [
{
"index": 0,
"delta": {
"content": None,
"reasoning_details": [
{
"type": "reasoning.text",
"signature": "sig-abc",
"index": 0,
"format": "anthropic-claude-v1",
}
],
},
"finish_reason": None,
}
],
}
assert (
wrapper.is_chunk_non_empty(
completion_obj={},
model_response=ModelResponseStream(**chunk_with_signature),
response_obj={},
)
is True
)
chunk_with_empty_reasoning_details = {
"id": "gen-sig-2",
"object": "chat.completion.chunk",
"created": 1741037890,
"model": "anthropic/claude-sonnet-4.5",
"choices": [
{
"index": 0,
"delta": {
"content": None,
"reasoning_details": [],
},
"finish_reason": None,
}
],
}
assert (
wrapper.is_chunk_non_empty(
completion_obj={},
model_response=ModelResponseStream(**chunk_with_empty_reasoning_details),
response_obj={},
)
is False
)