mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-05 16:24:59 +00:00
fix(responses-api): simplify reasoning item handling for gpt-5-codex (#15815)
Simplifies the _handle_reasoning_item method to only filter out None values without attempting to construct ResponseReasoningItem objects. This approach: - Avoids mutation of encrypted_content in reasoning items - Fixes compatibility with gpt-5-codex and Codex CLI - Removes dependency on ResponseReasoningItem import - Simplifies the code by removing complex fallback logic The previous approach was trying to construct ResponseReasoningItem objects with required fields (id, summary), which caused issues with encrypted payloads. The new approach simply filters None values while preserving all other data intact. Issue: https://github.com/BerriAI/litellm/issues/13484 Reported-by: rajpathak (OpenAI) Tested-by: rajpathak (OpenAI Codex CLI)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Union, cast, get_type_hints
|
||||
|
||||
import httpx
|
||||
from openai.types.responses import ResponseReasoningItem
|
||||
from pydantic import BaseModel
|
||||
|
||||
import litellm
|
||||
@@ -94,14 +93,12 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
|
||||
if isinstance(item, BaseModel):
|
||||
validated_input.append(item.model_dump(exclude_none=True))
|
||||
elif isinstance(item, dict):
|
||||
# Handle reasoning items specifically to filter out status=None
|
||||
# Handle reasoning items specifically to filter out None values without mutating contents
|
||||
verbose_logger.debug(f"Handling reasoning item: {item}")
|
||||
if item.get("type") == "reasoning":
|
||||
# Type assertion since we know it's a dict at this point
|
||||
dict_item = cast(Dict[str, Any], item)
|
||||
filtered_item = self._handle_reasoning_item(dict_item)
|
||||
else:
|
||||
# For other dict items, just pass through
|
||||
filtered_item = cast(Dict[str, Any], item)
|
||||
validated_input.append(filtered_item)
|
||||
else:
|
||||
@@ -112,43 +109,15 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
|
||||
|
||||
def _handle_reasoning_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Handle reasoning items specifically to filter out status=None using OpenAI's model.
|
||||
Handle reasoning items specifically to filter out None values.
|
||||
Issue: https://github.com/BerriAI/litellm/issues/13484
|
||||
OpenAI API does not accept ReasoningItem(status=None), so we need to:
|
||||
1. Check if the item is a reasoning type
|
||||
2. Create a ResponseReasoningItem object with the item data
|
||||
3. Convert it back to dict with exclude_none=True to filter None values
|
||||
OpenAI API does not accept ReasoningItem(status=None), so we need to
|
||||
make sure optional fields with None are stripped while leaving the
|
||||
encrypted payload untouched.
|
||||
"""
|
||||
if item.get("type") == "reasoning":
|
||||
try:
|
||||
# Ensure required fields are present for ResponseReasoningItem
|
||||
item_data = dict(item)
|
||||
if "summary" not in item_data:
|
||||
item_data["summary"] = (
|
||||
item_data.get("reasoning_content", "")[:100] + "..."
|
||||
if len(item_data.get("reasoning_content", "")) > 100
|
||||
else item_data.get("reasoning_content", "")
|
||||
)
|
||||
|
||||
# Create ResponseReasoningItem object from the item data
|
||||
reasoning_item = ResponseReasoningItem(**item_data)
|
||||
|
||||
# Convert back to dict with exclude_none=True to exclude None fields
|
||||
dict_reasoning_item = reasoning_item.model_dump(exclude_none=True)
|
||||
|
||||
return dict_reasoning_item
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
f"Failed to create ResponseReasoningItem, falling back to manual filtering: {e}"
|
||||
)
|
||||
# Fallback: manually filter out known None fields
|
||||
filtered_item = {
|
||||
k: v
|
||||
for k, v in item.items()
|
||||
if v is not None
|
||||
or k not in {"status", "content", "encrypted_content"}
|
||||
}
|
||||
return filtered_item
|
||||
filtered_item = {k: v for k, v in item.items() if v is not None}
|
||||
return filtered_item
|
||||
return item
|
||||
|
||||
def transform_response_api_response(
|
||||
|
||||
Reference in New Issue
Block a user