From be9c09e8d225e9f2dd27f5ac40ed364359a582d3 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Wed, 4 Mar 2026 18:26:16 +0530 Subject: [PATCH] Add supports_native_websocket to handle providers who don't handle websocket --- litellm/llms/base_llm/responses/transformation.py | 12 ++++++++++++ litellm/llms/chatgpt/responses/transformation.py | 10 +++++++--- litellm/llms/databricks/responses/transformation.py | 4 ++++ .../llms/github_copilot/responses/transformation.py | 6 +++++- litellm/llms/hosted_vllm/responses/transformation.py | 4 ++++ .../llms/litellm_proxy/responses/transformation.py | 4 ++++ litellm/llms/manus/responses/transformation.py | 4 ++++ litellm/llms/openai/responses/transformation.py | 4 ++++ litellm/llms/openrouter/responses/transformation.py | 4 ++++ litellm/llms/perplexity/responses/transformation.py | 4 ++++ litellm/llms/volcengine/responses/transformation.py | 9 +++++++-- litellm/llms/xai/responses/transformation.py | 4 ++++ 12 files changed, 63 insertions(+), 6 deletions(-) diff --git a/litellm/llms/base_llm/responses/transformation.py b/litellm/llms/base_llm/responses/transformation.py index 7a4da985528..4cc3583ed89 100644 --- a/litellm/llms/base_llm/responses/transformation.py +++ b/litellm/llms/base_llm/responses/transformation.py @@ -218,6 +218,18 @@ class BaseResponsesAPIConfig(ABC): """Returns True if litellm should fake a stream for the given model and stream value""" return False + def supports_native_websocket(self) -> bool: + """ + Returns True if the provider has a native WebSocket endpoint for Responses API. + + Providers with native websocket support can connect directly to wss:// endpoints. + Providers without native support will use the ManagedResponsesWebSocketHandler + which makes HTTP streaming calls and forwards events over the websocket. + + Default: False (use managed websocket handler) + """ + return False + ######################################################### ########## CANCEL RESPONSE API TRANSFORMATION ########## ######################################################### diff --git a/litellm/llms/chatgpt/responses/transformation.py b/litellm/llms/chatgpt/responses/transformation.py index bcb6edd39f9..66acd933416 100644 --- a/litellm/llms/chatgpt/responses/transformation.py +++ b/litellm/llms/chatgpt/responses/transformation.py @@ -1,14 +1,14 @@ import json from typing import Any, Optional -from litellm.exceptions import AuthenticationError from litellm.constants import STREAM_SSE_DONE_STRING +from litellm.exceptions import AuthenticationError from litellm.litellm_core_utils.core_helpers import process_response_headers -from litellm.llms.openai.common_utils import OpenAIError -from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import ( _safe_convert_created_field, ) +from litellm.llms.openai.common_utils import OpenAIError +from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.types.llms.openai import ( ResponsesAPIResponse, ResponsesAPIStreamEvents, @@ -200,3 +200,7 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): api_base = api_base or self.authenticator.get_api_base() or CHATGPT_API_BASE api_base = api_base.rstrip("/") return f"{api_base}/responses" + + def supports_native_websocket(self) -> bool: + """ChatGPT does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/databricks/responses/transformation.py b/litellm/llms/databricks/responses/transformation.py index 0d9f433bfd2..090fef5ac82 100644 --- a/litellm/llms/databricks/responses/transformation.py +++ b/litellm/llms/databricks/responses/transformation.py @@ -98,3 +98,7 @@ class DatabricksResponsesAPIConfig(DatabricksBase, OpenAIResponsesAPIConfig): litellm_params=litellm_params, headers=headers, ) + + def supports_native_websocket(self) -> bool: + """Databricks does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/github_copilot/responses/transformation.py b/litellm/llms/github_copilot/responses/transformation.py index e19fabc17c7..73240d46512 100644 --- a/litellm/llms/github_copilot/responses/transformation.py +++ b/litellm/llms/github_copilot/responses/transformation.py @@ -22,8 +22,8 @@ from litellm.types.utils import LlmProviders from ..authenticator import Authenticator from ..common_utils import ( - GetAPIKeyError, GITHUB_COPILOT_API_BASE, + GetAPIKeyError, get_copilot_default_headers, ) @@ -329,3 +329,7 @@ class GithubCopilotResponsesAPIConfig(OpenAIResponsesAPIConfig): ) return False + + def supports_native_websocket(self) -> bool: + """GitHub Copilot does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/hosted_vllm/responses/transformation.py b/litellm/llms/hosted_vllm/responses/transformation.py index 4dfead0d980..4d44eeda9f9 100644 --- a/litellm/llms/hosted_vllm/responses/transformation.py +++ b/litellm/llms/hosted_vllm/responses/transformation.py @@ -69,3 +69,7 @@ class HostedVLLMResponsesAPIConfig(OpenAIResponsesAPIConfig): return f"{api_base}/responses" return f"{api_base}/v1/responses" + + def supports_native_websocket(self) -> bool: + """Hosted vLLM does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/litellm_proxy/responses/transformation.py b/litellm/llms/litellm_proxy/responses/transformation.py index 0b81d8be7d8..a122b768751 100644 --- a/litellm/llms/litellm_proxy/responses/transformation.py +++ b/litellm/llms/litellm_proxy/responses/transformation.py @@ -46,3 +46,7 @@ class LiteLLMProxyResponsesAPIConfig(OpenAIResponsesAPIConfig): api_base = api_base.rstrip("/") return f"{api_base}/responses" + + def supports_native_websocket(self) -> bool: + """LiteLLM Proxy does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/manus/responses/transformation.py b/litellm/llms/manus/responses/transformation.py index fbbed19f8d4..bf1a6fab503 100644 --- a/litellm/llms/manus/responses/transformation.py +++ b/litellm/llms/manus/responses/transformation.py @@ -247,6 +247,10 @@ class ManusResponsesAPIConfig(OpenAIResponsesAPIConfig): response._hidden_params["headers"] = raw_response_headers return response + def supports_native_websocket(self) -> bool: + """Manus does not support native WebSocket for Responses API""" + return False + def transform_get_response_api_request( self, response_id: str, diff --git a/litellm/llms/openai/responses/transformation.py b/litellm/llms/openai/responses/transformation.py index 3e089682097..2988e0970a3 100644 --- a/litellm/llms/openai/responses/transformation.py +++ b/litellm/llms/openai/responses/transformation.py @@ -344,6 +344,10 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): ) return False + def supports_native_websocket(self) -> bool: + """OpenAI supports native WebSocket for Responses API""" + return True + ######################################################### ########## DELETE RESPONSE API TRANSFORMATION ############## ######################################################### diff --git a/litellm/llms/openrouter/responses/transformation.py b/litellm/llms/openrouter/responses/transformation.py index ddce6fd3844..864e1549274 100644 --- a/litellm/llms/openrouter/responses/transformation.py +++ b/litellm/llms/openrouter/responses/transformation.py @@ -75,3 +75,7 @@ class OpenRouterResponsesAPIConfig(OpenAIResponsesAPIConfig): api_base = api_base.rstrip("/") return f"{api_base}/responses" + + def supports_native_websocket(self) -> bool: + """OpenRouter does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/perplexity/responses/transformation.py b/litellm/llms/perplexity/responses/transformation.py index 6d2ed51600c..b6feb4ae498 100644 --- a/litellm/llms/perplexity/responses/transformation.py +++ b/litellm/llms/perplexity/responses/transformation.py @@ -490,3 +490,7 @@ class PerplexityResponsesConfig(OpenAIResponsesAPIConfig): verbose_logger.debug("Failed to transform Perplexity cost object: %s", e) return chunk + + def supports_native_websocket(self) -> bool: + """Perplexity does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/volcengine/responses/transformation.py b/litellm/llms/volcengine/responses/transformation.py index 872c8dcf118..f9ed93f680c 100644 --- a/litellm/llms/volcengine/responses/transformation.py +++ b/litellm/llms/volcengine/responses/transformation.py @@ -16,16 +16,17 @@ from pydantic import fields as pyd_fields import litellm from litellm._logging import verbose_logger -from litellm.types.llms.openai import ResponseInputParam, ResponsesAPIStreamingResponse -from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.litellm_core_utils.core_helpers import process_response_headers from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import ( _safe_convert_created_field, ) +from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig from litellm.secret_managers.main import get_secret_str from litellm.types.llms.openai import ( + ResponseInputParam, ResponsesAPIOptionalRequestParams, ResponsesAPIResponse, + ResponsesAPIStreamingResponse, ) from litellm.types.responses.main import DeleteResponseResult from litellm.types.router import GenericLiteLLMParams @@ -555,3 +556,7 @@ class VolcEngineResponsesAPIConfig(OpenAIResponsesAPIConfig): # Fall back to the first candidate return candidates[0] + + def supports_native_websocket(self) -> bool: + """VolcEngine does not support native WebSocket for Responses API""" + return False diff --git a/litellm/llms/xai/responses/transformation.py b/litellm/llms/xai/responses/transformation.py index 95873aab846..3c69b7d08b7 100644 --- a/litellm/llms/xai/responses/transformation.py +++ b/litellm/llms/xai/responses/transformation.py @@ -252,3 +252,7 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): return f"{api_base}/responses" + def supports_native_websocket(self) -> bool: + """XAI does not support native WebSocket for Responses API""" + return False +