route OpenAI responses WebSocket through managed HTTP path

This commit is contained in:
joereyna 2026-04-10 10:59:27 -07:00
parent 3ac4333be1
commit 7dd09daa98
No known key found for this signature in database
GPG key ID: 37E09E2BDB5920E5
2 changed files with 31 additions and 14 deletions

View file

@ -348,8 +348,15 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
return False
def supports_native_websocket(self) -> bool:
"""OpenAI supports native WebSocket for Responses API"""
return True
"""Use managed HTTP-streaming path for Responses API WebSocket mode.
OpenAI's wss://api.openai.com/v1/responses endpoint exists but does not
reliably stream events back in response to response.create messages in all
deployment contexts. The ManagedResponsesWebSocketHandler makes a normal
HTTP streaming call to /v1/responses and forwards the events over the
WebSocket, which is proven to work.
"""
return False
#########################################################
########## DELETE RESPONSE API TRANSFORMATION ##############

View file

@ -38,19 +38,19 @@ from litellm.llms.xai.responses.transformation import XAIResponsesAPIConfig
class TestResponsesAPIWebSocketSupport:
"""Test that all providers have websocket support configured correctly"""
def test_openai_supports_native_websocket(self):
"""OpenAI should support native websocket"""
def test_openai_uses_managed_websocket(self):
"""OpenAI uses managed WebSocket handler (HTTP streaming path)"""
config = OpenAIResponsesAPIConfig()
assert (
config.supports_native_websocket() is True
), "OpenAI should support native websocket"
config.supports_native_websocket() is False
), "OpenAI should use managed websocket handler"
def test_azure_supports_native_websocket(self):
"""Azure should support native websocket (inherits from OpenAI)"""
def test_azure_uses_managed_websocket(self):
"""Azure uses managed WebSocket handler (inherits from OpenAI)"""
config = AzureOpenAIResponsesAPIConfig()
assert (
config.supports_native_websocket() is True
), "Azure should support native websocket"
config.supports_native_websocket() is False
), "Azure should use managed websocket handler"
def test_xai_uses_managed_websocket(self):
"""XAI should use managed websocket handler"""
@ -1000,7 +1000,9 @@ class TestNativeWebSocketUrlConstruction:
mock_config = MagicMock(spec=OpenAIResponsesAPIConfig)
mock_config.supports_native_websocket.return_value = True
mock_config.get_complete_url.return_value = "https://api.openai.com/v1/responses"
mock_config.get_complete_url.return_value = (
"https://api.openai.com/v1/responses"
)
mock_config.validate_environment.return_value = {}
mock_logging = MagicMock()
@ -1024,8 +1026,11 @@ class TestNativeWebSocketUrlConstruction:
assert len(captured_urls) == 1
from urllib.parse import parse_qs, urlparse
qs = parse_qs(urlparse(captured_urls[0]).query)
assert qs.get("model") == ["gpt-4o-mini"], f"Expected model in URL, got: {captured_urls[0]}"
assert qs.get("model") == [
"gpt-4o-mini"
], f"Expected model in URL, got: {captured_urls[0]}"
@pytest.mark.asyncio
async def test_ws_url_preserves_existing_params_and_adds_model(self):
@ -1071,6 +1076,11 @@ class TestNativeWebSocketUrlConstruction:
assert len(captured_urls) == 1
from urllib.parse import parse_qs, urlparse
qs = parse_qs(urlparse(captured_urls[0]).query)
assert qs.get("model") == ["gpt-4o"], f"model missing from URL: {captured_urls[0]}"
assert qs.get("api-version") == ["2024-05-01"], f"existing param lost: {captured_urls[0]}"
assert qs.get("model") == [
"gpt-4o"
], f"model missing from URL: {captured_urls[0]}"
assert qs.get("api-version") == [
"2024-05-01"
], f"existing param lost: {captured_urls[0]}"