fix(responses): stop managed Responses WS from leaking litellm_params into provider body

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-07-13 17:47:48 +00:00
parent 20e646c49a
commit 48fe111c12
2 changed files with 54 additions and 2 deletions

View file

@ -2097,8 +2097,7 @@ class ManagedResponsesWebSocketHandler:
if "litellm_metadata" not in call_kwargs:
call_kwargs["litellm_metadata"] = {}
call_kwargs["litellm_metadata"]["proxy_server_request"] = proxy_server_request
call_kwargs.setdefault("litellm_params", {})
call_kwargs["litellm_params"]["proxy_server_request"] = proxy_server_request
call_kwargs["proxy_server_request"] = proxy_server_request
async def _stream_and_forward(self, model: str, call_kwargs: Dict[str, Any]) -> Optional[Dict[str, Any]]:
"""

View file

@ -660,6 +660,59 @@ class TestChunkTransformation:
assert ManagedResponsesWebSocketHandler._input_to_messages({}) == []
class TestUpdateProxyRequest:
"""Regression tests for ManagedResponsesWebSocketHandler._update_proxy_request.
The managed WebSocket path calls ``litellm.aresponses(model=..., **call_kwargs)``.
``litellm_params`` is not a Responses API request field, so passing it as a
top-level kwarg leaks it into the provider request body and providers that
forbid extra inputs (e.g. Anthropic) reject the call with
``litellm_params: Extra inputs are not permitted``. The request-tracking data
must ride along as ``proxy_server_request`` instead, which litellm consumes
internally and never forwards to the provider.
"""
def test_does_not_inject_litellm_params_kwarg(self):
from litellm.responses.streaming_iterator import (
ManagedResponsesWebSocketHandler,
)
call_kwargs = {
"input": "hello",
"store": True,
"litellm_metadata": {
"proxy_server_request": {"headers": {}, "body": {}},
},
}
ManagedResponsesWebSocketHandler._update_proxy_request(
call_kwargs, "anthropic/claude-sonnet-4-5"
)
assert "litellm_params" not in call_kwargs
assert call_kwargs["proxy_server_request"]["body"]["model"] == (
"anthropic/claude-sonnet-4-5"
)
assert call_kwargs["proxy_server_request"]["body"]["input"] == "hello"
def test_proxy_server_request_matches_metadata(self):
from litellm.responses.streaming_iterator import (
ManagedResponsesWebSocketHandler,
)
call_kwargs = {
"input": "hi",
"litellm_metadata": {"proxy_server_request": {"body": {}}},
}
ManagedResponsesWebSocketHandler._update_proxy_request(call_kwargs, "gpt-4o")
assert (
call_kwargs["proxy_server_request"]
== call_kwargs["litellm_metadata"]["proxy_server_request"]
)
class TestWebSocketEventTypes:
"""Test that all WebSocket event types are properly handled with dict-based chunks"""