refactor(responses): move streaming header restore behind a typed model method

Keeps the logged copy's hidden params limited to headers so cost fields on the bridge path are untouched, and avoids private-attr writes from outside the model.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-08-24 20:09:03 +00:00
parent 237b0f1fac
commit 9572b60b80
2 changed files with 19 additions and 5 deletions

View file

@ -207,10 +207,11 @@ class BaseResponsesAPIStreamingIterator:
"api_base": _api_base,
"custom_llm_provider": custom_llm_provider,
}
self._hidden_params["additional_headers"] = process_response_headers(
self.response.headers or {}
) # GUARANTEE OPENAI HEADERS IN RESPONSE
self._hidden_params["headers"] = dict(self.response.headers or {}) # mutable-ok: raw headers for logging
_raw_headers: Final = dict(self.response.headers or {}) # mutable-ok: process_response_headers takes a dict
_processed_headers: Final = process_response_headers(_raw_headers)
self._hidden_params["additional_headers"] = _processed_headers # GUARANTEE OPENAI HEADERS IN RESPONSE
self._raw_headers: Final[Mapping[str, str]] = MappingProxyType(_raw_headers)
self._processed_headers: Final[Mapping[str, object]] = MappingProxyType(_processed_headers)
def _check_max_streaming_duration(self) -> None:
"""Raise litellm.Timeout if the stream has exceeded LITELLM_MAX_STREAMING_DURATION_SECONDS."""
@ -425,7 +426,10 @@ class BaseResponsesAPIStreamingIterator:
copied: Final = self._copy_for_logging(completed)
inner_response: Final = getattr(copied, "response", None)
if isinstance(inner_response, ResponsesAPIResponse):
inner_response._hidden_params = dict(self._hidden_params) # mutable-ok: model_dump drops private attrs
inner_response.store_provider_response_headers(
processed_headers=self._processed_headers,
raw_headers=self._raw_headers,
)
return copied
@staticmethod

View file

@ -1337,6 +1337,16 @@ class ResponsesAPIResponse(BaseLiteLLMOpenAIResponseObject):
# Define private attributes using PrivateAttr
_hidden_params: dict = PrivateAttr(default_factory=dict)
def store_provider_response_headers(
self, *, processed_headers: Mapping[str, object], raw_headers: Mapping[str, str]
) -> None:
"""Keep provider headers on a response rebuilt from `model_dump()`, which drops private attrs."""
self._hidden_params = { # mutable-ok: the private attr is typed as dict
**self._hidden_params,
"additional_headers": dict(processed_headers), # mutable-ok: logging callbacks expect a plain dict
"headers": dict(raw_headers), # mutable-ok: logging callbacks expect a plain dict
}
@field_validator("reasoning", mode="before")
@classmethod
def validate_reasoning_to_dict(cls, value: Any) -> dict[str, Any] | None: