fix(chatgpt): strip unknown Codex item fields before building ResponsesAPIResponse

The ChatGPT/Codex backend includes provider-specific fields in
`response.output_item.done` SSE events that are not part of the
OpenAI Responses API schema:

- `phase` on the output item itself (e.g. `"phase": "final_answer"`)
- `logprobs` inside content parts

When `_build_completed_response_from_chunk` passes these items verbatim
to `ResponsesAPIResponse(**response_payload)`, Pydantic validation fails
silently (falls through to `model_construct`) and the `output` list ends
up empty.  This causes LiteLLM to raise:

  APIConnectionError: ChatgptException - Unknown items in responses API response: []

Fix: filter out unknown fields from each item and its content parts
before constructing the response object, so Pydantic validation
succeeds and the assistant reply is returned correctly.

Reproduces with models: chatgpt/gpt-5.5, chatgpt/gpt-5.6-sol,
chatgpt/gpt-5.6-terra, chatgpt/gpt-5.6-luna.
This commit is contained in:
willcai1984 2026-07-29 15:34:49 +08:00
parent b79fc9f1b0
commit 6d767c88d5

View file

@ -208,7 +208,22 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
return None
response_payload = dict(response_payload)
if not response_payload.get("output") and streamed_output_items:
response_payload["output"] = [item for _, item in sorted(streamed_output_items.items())]
# The Codex backend includes provider-specific fields (e.g. `phase`,
# `logprobs`) in output items that are not part of the Responses API
# schema. Passing them verbatim to ResponsesAPIResponse causes
# Pydantic validation to fail, which leaves `output` empty and
# raises "Unknown items in responses API response: []". Strip the
# extra fields before building the response object.
_EXTRA_FIELDS = {"phase", "logprobs"}
clean_items = []
for _, item in sorted(streamed_output_items.items()):
ci = {k: v for k, v in item.items() if k not in _EXTRA_FIELDS}
ci["content"] = [
{k2: v2 for k2, v2 in c.items() if k2 not in _EXTRA_FIELDS}
for c in ci.get("content", [])
]
clean_items.append(ci)
response_payload["output"] = clean_items
if "created_at" in response_payload:
response_payload["created_at"] = _safe_convert_created_field(response_payload["created_at"])
try: