This commit is contained in:
himalmangla 2026-10-29 00:57:50 +05:30 • committed by GitHub
commit 2263df016d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 80 additions and 18 deletions

View file

@ -1129,7 +1129,7 @@ class LiteLLMCompletionStreamingIterator(ResponsesAPIStreamingIterator):
"id": self._cached_reasoning_item_id,
"type": "reasoning",
"status": "in_progress",
"summary": None,
"summary": [],
}
),
)

View file

@ -3436,24 +3436,29 @@ class LiteLLMCompletionResponsesConfig:
encrypted_content = LiteLLMCompletionResponsesConfig._encode_thinking_blocks(message)
if reasoning_content or encrypted_content:
# Only check the first choice for reasoning content
# summary and encrypted_content are reasoning-only extras the shared model does not declare
return [
GenericResponseOutputItem(
type="reasoning",
id=mint_reasoning_item_id(),
status=LiteLLMCompletionResponsesConfig._map_chat_completion_finish_reason_to_responses_status(
choice.finish_reason
),
role="assistant",
content=[
OutputText(
type="output_text",
text=text,
annotations=[],
)
for text in (reasoning_content,)
if text
],
encrypted_content=encrypted_content,
GenericResponseOutputItem.model_validate(
{
"type": "reasoning",
"id": mint_reasoning_item_id(),
"status": LiteLLMCompletionResponsesConfig._map_chat_completion_finish_reason_to_responses_status(
choice.finish_reason
),
"role": "assistant",
"content": [
OutputText(
type="output_text",
text=text,
annotations=[],
)
for text in (reasoning_content,)
if text
],
# Required by the Responses schema. The reasoning text rides in content, so it stays empty
"summary": [],
"encrypted_content": encrypted_content,
}
)
]
return []

View file

@ -503,6 +503,39 @@ class TestLiteLLMCompletionResponsesConfig:
assert reasoning_items[0].content[0].text == "counting the primes"
assert "sig" in reasoning_items[0].encrypted_content
@pytest.mark.parametrize(
"message",
[
pytest.param(
Message(content="No, 1001 = 7 x 11 x 13", role="assistant", reasoning_content="Trying small primes"),
id="gemini-thought-text",
),
pytest.param(
Message(
content="No",
role="assistant",
reasoning_content="",
thinking_blocks=[{"type": "thinking", "thinking": "", "signature": "sig"}],
),
id="signature-only-thinking",
),
],
)
def test_reasoning_item_always_carries_a_summary_list(self, message: Message):
"""`summary` is required on a Responses reasoning item, and clients that read it
(e.g. OpenAI Agents SDK tracing) fail on the missing field"""
response: Final = LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response(
request_input="Is 1001 prime?",
responses_api_request={},
chat_completion_response=ModelResponse(
model="gemini-3.8-flash", choices=[Choices(index=0, finish_reason="stop", message=message)]
),
)
reasoning_items: Final = [item for item in response.output if item.type == "reasoning"]
assert len(reasoning_items) == 1
assert reasoning_items[0].summary == []
def test_transform_chat_completion_response_status_with_stop(self):
"""
Test that transforming a chat completion response with 'stop' finish_reason

View file

@ -1173,6 +1173,30 @@ async def test_signature_only_thinking_streams_a_replayable_reasoning_item(sync_
assert json.loads(reasoning_items[0].encrypted_content)[0]["signature"] == "sig_only"
@pytest.mark.parametrize(
"stream_chunks",
[_reasoning_then_text_chunks, _signed_thinking_and_text_in_one_chunk],
ids=["gemini-thought-text", "signature-only-thinking"],
)
@pytest.mark.parametrize("sync_mode", [True, False])
@pytest.mark.asyncio
async def test_streamed_reasoning_item_carries_a_summary_list_from_added_to_completed(
stream_chunks: StreamChunks, sync_mode: bool
):
events: Final = await _collect_events(_build_iterator(stream_chunks()), sync_mode)
added: Final = next(
event.item
for event in events
if getattr(event, "type", None) == ResponsesAPIStreamEvents.OUTPUT_ITEM_ADDED and event.item.type == "reasoning"
)
completed: Final = next(
event for event in events if getattr(event, "type", None) == ResponsesAPIStreamEvents.RESPONSE_COMPLETED
)
assert added.summary == []
assert [item.summary for item in completed.response.output if item.type == "reasoning"] == [[]]
@REASONING_THEN_TEXT_STREAMS
@pytest.mark.parametrize("sync_mode", [True, False])
@pytest.mark.asyncio