style(responses): drop inline comments from #34754 fix

This commit is contained in:
Devin AI 2026-07-28 15:55:32 +00:00
parent eaa0abbf07
commit 79e559d296
2 changed files with 13 additions and 32 deletions

View file

@ -1,17 +1,12 @@
"""
Best-effort construction of Responses API objects from raw provider payloads.
Providers deviate from the OpenAI Responses spec often enough that strict
pydantic validation fails (missing ``output``, a ``usage`` block with unexpected
fields, ...). Callers used to fall back to ``model_construct``, which skips
validation *and* nested model coercion, so ``response.usage`` stayed a plain
dict and ``response.output`` could be missing entirely. Everything downstream
reads those attributes as declared (``ResponsesAPIResponse.usage`` is a
``ResponseAPIUsage``, ``.output`` is a list), so the fallback produced objects
that violate their own type and blew up with ``AttributeError`` mid-stream.
These helpers keep the declared shape intact even when validation fails, so the
fallback stays a degraded-data path instead of a crash path.
When a provider payload fails strict validation, callers fall back to
``model_construct``, which skips nested model coercion and leaves ``usage`` as a
plain dict and ``output`` missing. Downstream code reads those attributes as
declared, so such objects raise ``AttributeError`` mid-stream. These helpers keep
the declared shape intact so the fallback stays a degraded-data path rather than
a crash path
"""
from collections.abc import Callable, Mapping
@ -26,11 +21,7 @@ _FIELD_MAPPING_ADAPTER = TypeAdapter(dict[str, object])
def construct_responses_api_response(payload: Mapping[str, object]) -> ResponsesAPIResponse:
"""Build a ``ResponsesAPIResponse``, validating when possible.
On validation failure, fields required by the model are defaulted and
``usage`` is coerced, so attribute access on the result behaves as declared.
"""
"""Validate a raw response payload, coercing ``output`` and ``usage`` when validation fails"""
try:
return ResponsesAPIResponse.model_validate(dict(payload))
except ValidationError:
@ -54,12 +45,7 @@ def construct_responses_api_stream_event(
event_model: type[BaseLiteLLMOpenAIResponseObject],
payload: Mapping[str, object],
) -> BaseLiteLLMOpenAIResponseObject:
"""Build a Responses API streaming event without validation.
Terminal events (``response.completed`` / ``.failed`` / ``.incomplete``)
declare a ``ResponsesAPIResponse``; ``model_construct`` alone would leave it
as the raw dict, so construct that nested object explicitly.
"""
"""Build a streaming event without validation, keeping its nested ``response`` typed"""
construct: Callable[..., BaseLiteLLMOpenAIResponseObject] = event_model.model_construct
response_payload = _as_field_mapping(payload.get("response"))
if response_payload is None:
@ -68,7 +54,6 @@ def construct_responses_api_stream_event(
def _construct_usage(usage: object) -> ResponseAPIUsage | None:
"""Coerce a raw ``usage`` payload into ``ResponseAPIUsage``, or drop it."""
if usage is None or isinstance(usage, ResponseAPIUsage):
return usage
usage_fields = _as_field_mapping(usage)
@ -92,7 +77,6 @@ def _construct_usage(usage: object) -> ResponseAPIUsage | None:
def _as_field_mapping(value: object) -> Mapping[str, object] | None:
"""Validate an untyped payload into a string-keyed field mapping."""
try:
return _FIELD_MAPPING_ADAPTER.validate_python(value)
except ValidationError:

View file

@ -1,11 +1,10 @@
"""
Regression tests for GitHub issue #34754.
Providers whose Responses API payloads fail strict validation used to be built
with bare ``model_construct``, leaving ``event.response`` as a raw dict and
``response.usage`` unparsed. Consumers read those as declared, so streaming
requests died with ``AttributeError: 'dict' object has no attribute 'usage'``
(HTTP 500 mid-stream) or silently dropped the SpendLogs entry.
Providers whose Responses API payloads fail strict validation used to be built with bare
``model_construct``, leaving ``event.response`` as a raw dict and ``response.usage`` unparsed. Consumers
read those as declared, so streaming requests died with ``AttributeError: 'dict' object has no attribute
'usage'`` (HTTP 500 mid-stream) or silently dropped the SpendLogs entry
"""
import datetime
@ -22,8 +21,6 @@ from litellm.types.llms.openai import (
ResponsesAPIResponse,
)
# `response.completed` payload that fails validation: `output` is required by
# ResponsesAPIResponse but plenty of providers omit it.
DICT_FORMAT_COMPLETED_CHUNK = {
"type": "response.completed",
"response": {
@ -87,7 +84,7 @@ def test_valid_payload_is_validated_not_constructed():
)
assert isinstance(response.usage, ResponseAPIUsage)
assert response.model_fields_set # validated instance, not a bare model_construct
assert response.model_fields_set
def test_streaming_event_response_is_not_a_dict():