From 276b5695681ac4f545362df9cf4127b2e1f92788 Mon Sep 17 00:00:00 2001 From: Tom Ron Date: Fri, 2 Oct 2026 11:18:57 +0300 Subject: [PATCH] fix(responses): emit response.incomplete on replayed streams and default temperature to 0 Co-Authored-By: Claude Sonnet 5.5 --- .../transformation.py | 4 ++-- litellm/responses/streaming_iterator.py | 8 +++++++ .../test_incomplete_status_transformation.py | 21 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/litellm/responses/litellm_completion_transformation/transformation.py b/litellm/responses/litellm_completion_transformation/transformation.py index a922e95912d..2b050c56098 100644 --- a/litellm/responses/litellm_completion_transformation/transformation.py +++ b/litellm/responses/litellm_completion_transformation/transformation.py @@ -243,7 +243,7 @@ class LiteLLMCompletionResponsesConfig: "tools": tools, "top_p": responses_api_request.get("top_p"), "user": responses_api_request.get("user"), - "temperature": responses_api_request.get("temperature"), + "temperature": responses_api_request.get("temperature", 0), "parallel_tool_calls": responses_api_request.get("parallel_tool_calls"), "max_tokens": responses_api_request.get("max_output_tokens"), "stream": stream, @@ -1625,7 +1625,7 @@ class LiteLLMCompletionResponsesConfig: responses_api_request=responses_api_request, ), parallel_tool_calls=getattr(chat_completion_response, "parallel_tool_calls", False), - temperature=responses_api_request.get("temperature"), + temperature=responses_api_request.get("temperature", 0), tool_choice=getattr(chat_completion_response, "tool_choice", "auto"), tools=getattr(chat_completion_response, "tools", []), top_p=responses_api_request.get("top_p"), diff --git a/litellm/responses/streaming_iterator.py b/litellm/responses/streaming_iterator.py index dab666ff0d9..5844c34eaa2 100644 --- a/litellm/responses/streaming_iterator.py +++ b/litellm/responses/streaming_iterator.py @@ -1253,6 +1253,14 @@ def _build_synthetic_response_events( ) ) + if transformed.status == "incomplete": + events.append( + openai_types.ResponseIncompleteEvent( + type=openai_types.ResponsesAPIStreamEvents.RESPONSE_INCOMPLETE, + response=transformed, + ) + ) + return events events.append( openai_types.ResponseCompletedEvent( type=openai_types.ResponsesAPIStreamEvents.RESPONSE_COMPLETED, diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_incomplete_status_transformation.py b/tests/test_litellm/responses/litellm_completion_transformation/test_incomplete_status_transformation.py index 92785b52849..4ae7b8c75a5 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_incomplete_status_transformation.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_incomplete_status_transformation.py @@ -8,6 +8,7 @@ from litellm.responses.litellm_completion_transformation.streaming_iterator impo from litellm.responses.litellm_completion_transformation.transformation import ( LiteLLMCompletionResponsesConfig, ) +from litellm.responses.streaming_iterator import _build_synthetic_response_events from litellm.types.llms.openai import ResponsesAPIStreamEvents from litellm.types.utils import Choices, Message, ModelResponse, Usage @@ -70,3 +71,23 @@ def test_stream_terminal_event_follows_status(finish_reason, event_type): event = iterator._emit_response_completed_event(_chat_response(finish_reason)) assert event is not None assert event.type == event_type + + +@pytest.mark.parametrize( + "finish_reason, event_type", + [ + ("length", ResponsesAPIStreamEvents.RESPONSE_INCOMPLETE), + ("stop", ResponsesAPIStreamEvents.RESPONSE_COMPLETED), + ], +) +def test_replayed_stream_terminal_event_follows_status(finish_reason, event_type): + events = _build_synthetic_response_events( + transformed=_transform(finish_reason, {}), + logging_obj=None, + chunk_size=10, + ) + assert events[-1].type == event_type + + +def test_omitted_temperature_defaults_to_zero(): + assert _transform("stop", {}).temperature == 0