mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-26 01:12:21 +00:00
Some checks are pending
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / schema-migration (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Security / security (push) Waiting to run
* Add support for environment variable in interactions api * Add sdk support for gemini create agent * Add agents endpoint support via proxy * Add outputs of each api * Add routing for model and agents param * Remove redundant condition in get_provider_agents_api_config LlmProviders.GEMINI.value is literally the string "gemini", so the second clause of the or was checking the exact same thing as the first. Co-authored-by: Sameer Kankute <Sameerlite@users.noreply.github.com> * fix: forward query-param credentials to list/get/delete/versions Gemini agent endpoints The list_gemini_agents, get_gemini_agent, delete_gemini_agent, and list_gemini_agent_versions endpoints previously constructed a hardcoded data dict with no mechanism to pass provider credentials. Unlike create_gemini_agent (POST, reads litellm_params_template from body), these GET/DELETE endpoints gave no way for multi-tenant callers to supply a per-request api_key or other LiteLLM params. Fix: - Add _merge_query_params_into_data() helper that reads query parameters from the request and merges them into the data dict without overwriting already-set keys (e.g. path params like 'name'). - Support a JSON-encoded litellm_params_template query parameter (matching the POST body pattern) as well as flat key=value pairs (e.g. api_key=AIza...). - Apply the helper in all four affected endpoints. - Add 13 unit tests covering the helper and each endpoint. Co-authored-by: Sameer Kankute <Sameerlite@users.noreply.github.com> * fix: pass model=None for managed agent proxy endpoints to prevent agent name polluting data["model"] Endpoints acreate_agent, aget_agent, adelete_agent, and alist_agent_versions were passing model=<agent_name> to base_process_llm_request. This caused common_processing_pre_call_logic to write the agent name into self.data["model"], which then triggered spurious model-alias mapping, rate-limiting lookups, and logging tied to a non-existent model deployment. The agent name is already carried in data["name"] and is passed correctly to the SDK functions (litellm.interactions.agents.*). There is no reason to also set model=<agent_name>; the correct value is model=None for all five managed-agent management routes. Adds tests/test_litellm/proxy/google_endpoints/test_managed_agents_model_param.py to verify all five managed-agent endpoints pass model=None. Co-authored-by: Sameer Kankute <Sameerlite@users.noreply.github.com> * fix: address greptile P1/P2 review comments P1 (router.py): Restore fallback/retry support for acreate_interaction and create_interaction. Both were silently moved to _init_interactions_api_endpoints (direct call, no fallbacks). Moved them back to _ageneric_api_call_with_fallbacks so users with configured fallback models keep retry behaviour. P1 security (agents_endpoints.py): Remove flat query-param credential path (e.g. ?api_key=AIza...) from _merge_query_params_into_data. Credentials in URL query strings appear verbatim in server access logs, CDN edge logs, and browser history. Only the JSON-encoded litellm_params_template query param (matching the POST body pattern) is retained. P2 (interactions/http_handler.py): Extract _BaseHTTPHandler with shared _handle_error, _sync_client, and _async_client helpers. InteractionsHTTPHandler now extends _BaseHTTPHandler. The _async_client reads the provider from litellm_params instead of hardcoding GEMINI. P2 (interactions/agents/http_handler.py): AgentsHTTPHandler now extends InteractionsHTTPHandler (which inherits _BaseHTTPHandler) so all shared HTTP infrastructure is reused rather than duplicated. Removes the hardcoded LlmProviders.GEMINI from the async client path. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: address CI failures from greptile review fixes - black: format interactions/agents/main.py and utils.py - tests: update test_gemini_agents_endpoints.py to match new _merge_query_params_into_data behaviour (flat credential params are rejected; only JSON-encoded litellm_params_template is accepted) - ci: add test_gemini_agents_endpoints.py to endpoints-and-responses shard in test-unit-proxy-db.yml so assert-shard-coverage passes - tests: add _initialize_managed_agents_endpoints and _init_managed_agents_api_endpoints test coverage so router_code_coverage passes; also fix TestRouterCreateInteractionRouting to reflect that acreate_interaction now correctly routes through _ageneric_api_call_with_fallbacks (restoring fallback support) Co-authored-by: Cursor <cursoragent@cursor.com> * fix: remove InteractionsHTTPHandler._handle_error override to fix type errors AgentsHTTPHandler extends InteractionsHTTPHandler and calls self._handle_error(provider_config=agents_api_config) where agents_api_config is BaseAgentsAPIConfig. Python MRO resolved _handle_error to InteractionsHTTPHandler._handle_error which expected BaseInteractionsAPIConfig, causing 10 mypy arg-type errors in interactions/agents/http_handler.py. Removing the redundant override lets both classes inherit _BaseHTTPHandler._handle_error (provider_config: Any) which is structurally correct for both config types. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: agent-only interactions and managed agents provider routing Resolve None custom_llm_provider in agents HTTP client lookup and set custom_llm_provider on GenericLiteLLMParams for all agent CRUD paths. Stop mapping agent names to proxy model routing; route interactions through _init_interactions_api_endpoints with fallbacks only when model is set. Consolidate duplicate router elif branches for interaction APIs. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix greptile review * test(agents): add unit tests for managed agents SDK and HTTP handler Adds coverage for the new `litellm.interactions.agents` surface area: - main.py: sync/async entry points (create/list/get/delete/list_versions), provider config lookup, logging-obj helper, async error wrapping - http_handler.py: every CRUD method (sync + async paths), `_is_async` dispatch branches, and provider error mapping through GeminiAgentsConfig - utils.py: get_provider_agents_api_config for supported / unsupported providers Brings patch coverage on these files from <25% to ~100% so codecov/patch is satisfied. Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com> * docs(gemini-agents): fix misleading credential-passing examples in GET/DELETE docstrings (#28293) The four GET/DELETE endpoint docstrings (list_gemini_agents, get_gemini_agent, delete_gemini_agent, list_gemini_agent_versions) documented passing per-request credentials as flat query parameters (e.g. ?api_key=AIza...). However, _merge_query_params_into_data only reads the JSON-encoded litellm_params_template query parameter and intentionally ignores flat params (URL query strings appear verbatim in access logs, browser history, and Referer headers). Callers following the documented curl examples would have their credentials silently dropped and hit auth failures against Gemini. Update the examples to use the supported JSON-encoded litellm_params_template query parameter, matching _merge_query_params_into_data's own docstring. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com> * refactor(agents): rename provider-agnostic agent response types Move GeminiAgent{ListResponse,DeleteResult,VersionsResponse} to provider-neutral names (AgentListResponse, AgentDeleteResult, AgentVersionsResponse) so the BaseAgentsAPIConfig interface no longer references Gemini-specific type names. * fix(gemini-agents): close veria-flagged credential-escalation gaps Two high-severity findings from the veria-ai PR review are addressed: 1. **api_base override could leak the shared Gemini key** GeminiAgentsConfig.validate_environment falls back to GOOGLE_API_KEY / GEMINI_API_KEY when no api_key is supplied. Combined with caller-controlled api_base on the proxy CRUD endpoints, an authenticated user could redirect the outbound request to an attacker-controlled host and capture the operator's shared Gemini key from the x-goog-api-key header. The config now refuses env-fallback whenever api_base is explicitly overridden. 2. **Managed-agent CRUD exposed to ordinary LLM keys** The new /v1beta/agents routes live in google_routes (i.e. llm_api_routes), so any non-admin LLM key can reach them. Unlike /v1beta/models/...: generateContent these endpoints are NOT model-routed and have no model_list-supplied credentials, so env-fallback would let any LLM key list / create / delete agents inside the operator's Gemini project. Each endpoint now calls _enforce_caller_supplied_provider_key, which requires non-admin callers to supply their own Gemini api_key via litellm_params_template. Proxy admins keep the env-fallback convenience. Tests cover non-admin rejection, admin allow-through, the api_base override guard, and SDK env-fallback when api_base is not overridden. Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com> * test(router): restore strict assert_called_once_with on interactions default-provider test --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Sameer Kankute <Sameerlite@users.noreply.github.com> Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
725 lines
24 KiB
Python
725 lines
24 KiB
Python
"""
|
|
HTTP Handler for Interactions API requests.
|
|
|
|
This module handles the HTTP communication for the Google Interactions API.
|
|
"""
|
|
|
|
from typing import (
|
|
Any,
|
|
AsyncIterator,
|
|
Coroutine,
|
|
Dict,
|
|
Iterator,
|
|
Optional,
|
|
Union,
|
|
)
|
|
|
|
import httpx
|
|
|
|
import litellm
|
|
from litellm.constants import request_timeout
|
|
from litellm.interactions.streaming_iterator import (
|
|
InteractionsAPIStreamingIterator,
|
|
SyncInteractionsAPIStreamingIterator,
|
|
)
|
|
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
|
from litellm.llms.base_llm.interactions.transformation import BaseInteractionsAPIConfig
|
|
from litellm.llms.custom_httpx.http_handler import (
|
|
AsyncHTTPHandler,
|
|
HTTPHandler,
|
|
_get_httpx_client,
|
|
get_async_httpx_client,
|
|
)
|
|
from litellm.types.interactions import (
|
|
CancelInteractionResult,
|
|
DeleteInteractionResult,
|
|
InteractionInput,
|
|
InteractionsAPIOptionalRequestParams,
|
|
InteractionsAPIResponse,
|
|
InteractionsAPIStreamingResponse,
|
|
)
|
|
from litellm.types.router import GenericLiteLLMParams
|
|
|
|
|
|
class _BaseHTTPHandler:
|
|
"""
|
|
Shared HTTP infrastructure for LiteLLM handler classes.
|
|
|
|
Provides common client resolution and error-mapping helpers so that
|
|
handler subclasses (InteractionsHTTPHandler, AgentsHTTPHandler, …) do
|
|
not duplicate this boilerplate.
|
|
"""
|
|
|
|
def _handle_error(self, e: Exception, provider_config: Any) -> Exception:
|
|
if isinstance(e, httpx.HTTPStatusError):
|
|
return provider_config.get_error_class(
|
|
error_message=e.response.text,
|
|
status_code=e.response.status_code,
|
|
headers=dict(e.response.headers),
|
|
)
|
|
return e
|
|
|
|
def _sync_client(
|
|
self,
|
|
litellm_params: GenericLiteLLMParams,
|
|
client: Optional[HTTPHandler],
|
|
) -> HTTPHandler:
|
|
return client or _get_httpx_client(
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)}
|
|
)
|
|
|
|
def _async_client(
|
|
self,
|
|
litellm_params: GenericLiteLLMParams,
|
|
client: Optional[AsyncHTTPHandler],
|
|
) -> AsyncHTTPHandler:
|
|
# GenericLiteLLMParams.get uses getattr; an unset field is None, not the default.
|
|
custom_llm_provider = litellm_params.get("custom_llm_provider") or "gemini"
|
|
return client or get_async_httpx_client(
|
|
llm_provider=litellm.LlmProviders(custom_llm_provider),
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)},
|
|
)
|
|
|
|
|
|
class InteractionsHTTPHandler(_BaseHTTPHandler):
|
|
"""
|
|
HTTP handler for Interactions API requests.
|
|
"""
|
|
|
|
# _handle_error is inherited from _BaseHTTPHandler (accepts Any provider_config).
|
|
# AgentsHTTPHandler also extends this class and passes BaseAgentsAPIConfig, which
|
|
# is structurally compatible but a different type — keeping the override here with
|
|
# BaseInteractionsAPIConfig would cause type errors in the subclass.
|
|
|
|
# =========================================================
|
|
# CREATE INTERACTION
|
|
# =========================================================
|
|
|
|
def create_interaction(
|
|
self,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
optional_params: InteractionsAPIOptionalRequestParams,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
model: Optional[str] = None,
|
|
agent: Optional[str] = None,
|
|
input: Optional[InteractionInput] = None,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
extra_body: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[HTTPHandler] = None,
|
|
_is_async: bool = False,
|
|
stream: Optional[bool] = None,
|
|
) -> Union[
|
|
InteractionsAPIResponse,
|
|
Iterator[InteractionsAPIStreamingResponse],
|
|
Coroutine[
|
|
Any,
|
|
Any,
|
|
Union[
|
|
InteractionsAPIResponse, AsyncIterator[InteractionsAPIStreamingResponse]
|
|
],
|
|
],
|
|
]:
|
|
"""
|
|
Create a new interaction (synchronous or async based on _is_async flag).
|
|
|
|
Per Google's OpenAPI spec, the endpoint is POST /{api_version}/interactions
|
|
"""
|
|
if _is_async:
|
|
return self.async_create_interaction(
|
|
model=model,
|
|
agent=agent,
|
|
input=input,
|
|
interactions_api_config=interactions_api_config,
|
|
optional_params=optional_params,
|
|
custom_llm_provider=custom_llm_provider,
|
|
litellm_params=litellm_params,
|
|
logging_obj=logging_obj,
|
|
extra_headers=extra_headers,
|
|
extra_body=extra_body,
|
|
timeout=timeout,
|
|
stream=stream,
|
|
)
|
|
|
|
if client is None:
|
|
sync_httpx_client = _get_httpx_client(
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)}
|
|
)
|
|
else:
|
|
sync_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model=model or "",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
api_base = interactions_api_config.get_complete_url(
|
|
api_base=litellm_params.api_base or "",
|
|
model=model,
|
|
agent=agent,
|
|
litellm_params=dict(litellm_params),
|
|
stream=stream,
|
|
)
|
|
|
|
data = interactions_api_config.transform_request(
|
|
model=model,
|
|
agent=agent,
|
|
input=input,
|
|
optional_params=optional_params,
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
if extra_body:
|
|
data.update(extra_body)
|
|
|
|
# Logging
|
|
logging_obj.pre_call(
|
|
input=input,
|
|
api_key="",
|
|
additional_args={
|
|
"complete_input_dict": data,
|
|
"api_base": api_base,
|
|
"headers": headers,
|
|
},
|
|
)
|
|
|
|
try:
|
|
if stream:
|
|
response = sync_httpx_client.post(
|
|
url=api_base,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
stream=True,
|
|
)
|
|
return self._create_sync_streaming_iterator(
|
|
response=response,
|
|
model=model,
|
|
logging_obj=logging_obj,
|
|
interactions_api_config=interactions_api_config,
|
|
)
|
|
else:
|
|
response = sync_httpx_client.post(
|
|
url=api_base,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_response(
|
|
model=model,
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
async def async_create_interaction(
|
|
self,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
optional_params: InteractionsAPIOptionalRequestParams,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
model: Optional[str] = None,
|
|
agent: Optional[str] = None,
|
|
input: Optional[InteractionInput] = None,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
extra_body: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[AsyncHTTPHandler] = None,
|
|
stream: Optional[bool] = None,
|
|
) -> Union[
|
|
InteractionsAPIResponse, AsyncIterator[InteractionsAPIStreamingResponse]
|
|
]:
|
|
"""
|
|
Create a new interaction (async version).
|
|
"""
|
|
if client is None:
|
|
async_httpx_client = get_async_httpx_client(
|
|
llm_provider=litellm.LlmProviders(custom_llm_provider),
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)},
|
|
)
|
|
else:
|
|
async_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model=model or "",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
api_base = interactions_api_config.get_complete_url(
|
|
api_base=litellm_params.api_base or "",
|
|
model=model,
|
|
agent=agent,
|
|
litellm_params=dict(litellm_params),
|
|
stream=stream,
|
|
)
|
|
|
|
data = interactions_api_config.transform_request(
|
|
model=model,
|
|
agent=agent,
|
|
input=input,
|
|
optional_params=optional_params,
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
if extra_body:
|
|
data.update(extra_body)
|
|
|
|
# Logging
|
|
logging_obj.pre_call(
|
|
input=input,
|
|
api_key="",
|
|
additional_args={
|
|
"complete_input_dict": data,
|
|
"api_base": api_base,
|
|
"headers": headers,
|
|
},
|
|
)
|
|
|
|
try:
|
|
if stream:
|
|
response = await async_httpx_client.post(
|
|
url=api_base,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
stream=True,
|
|
)
|
|
return self._create_async_streaming_iterator(
|
|
response=response,
|
|
model=model,
|
|
logging_obj=logging_obj,
|
|
interactions_api_config=interactions_api_config,
|
|
)
|
|
else:
|
|
response = await async_httpx_client.post(
|
|
url=api_base,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_response(
|
|
model=model,
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
def _create_sync_streaming_iterator(
|
|
self,
|
|
response: httpx.Response,
|
|
model: Optional[str],
|
|
logging_obj: LiteLLMLoggingObj,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
) -> SyncInteractionsAPIStreamingIterator:
|
|
"""Create a synchronous streaming iterator.
|
|
|
|
Google AI's streaming format uses SSE (Server-Sent Events).
|
|
Returns a proper streaming iterator that yields chunks as they arrive.
|
|
"""
|
|
return SyncInteractionsAPIStreamingIterator(
|
|
response=response,
|
|
model=model,
|
|
interactions_api_config=interactions_api_config,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
def _create_async_streaming_iterator(
|
|
self,
|
|
response: httpx.Response,
|
|
model: Optional[str],
|
|
logging_obj: LiteLLMLoggingObj,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
) -> InteractionsAPIStreamingIterator:
|
|
"""Create an asynchronous streaming iterator.
|
|
|
|
Google AI's streaming format uses SSE (Server-Sent Events).
|
|
Returns a proper streaming iterator that yields chunks as they arrive.
|
|
"""
|
|
return InteractionsAPIStreamingIterator(
|
|
response=response,
|
|
model=model,
|
|
interactions_api_config=interactions_api_config,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
# =========================================================
|
|
# GET INTERACTION
|
|
# =========================================================
|
|
|
|
def get_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[HTTPHandler] = None,
|
|
_is_async: bool = False,
|
|
) -> Union[InteractionsAPIResponse, Coroutine[Any, Any, InteractionsAPIResponse]]:
|
|
"""Get an interaction by ID."""
|
|
if _is_async:
|
|
return self.async_get_interaction(
|
|
interaction_id=interaction_id,
|
|
interactions_api_config=interactions_api_config,
|
|
custom_llm_provider=custom_llm_provider,
|
|
litellm_params=litellm_params,
|
|
logging_obj=logging_obj,
|
|
extra_headers=extra_headers,
|
|
timeout=timeout,
|
|
)
|
|
|
|
if client is None:
|
|
sync_httpx_client = _get_httpx_client(
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)}
|
|
)
|
|
else:
|
|
sync_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, params = interactions_api_config.transform_get_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = sync_httpx_client.get(
|
|
url=url,
|
|
headers=headers,
|
|
params=params,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_get_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
async def async_get_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[AsyncHTTPHandler] = None,
|
|
) -> InteractionsAPIResponse:
|
|
"""Get an interaction by ID (async version)."""
|
|
if client is None:
|
|
async_httpx_client = get_async_httpx_client(
|
|
llm_provider=litellm.LlmProviders(custom_llm_provider),
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)},
|
|
)
|
|
else:
|
|
async_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, params = interactions_api_config.transform_get_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = await async_httpx_client.get(
|
|
url=url,
|
|
headers=headers,
|
|
params=params,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_get_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
# =========================================================
|
|
# DELETE INTERACTION
|
|
# =========================================================
|
|
|
|
def delete_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[HTTPHandler] = None,
|
|
_is_async: bool = False,
|
|
) -> Union[DeleteInteractionResult, Coroutine[Any, Any, DeleteInteractionResult]]:
|
|
"""Delete an interaction by ID."""
|
|
if _is_async:
|
|
return self.async_delete_interaction(
|
|
interaction_id=interaction_id,
|
|
interactions_api_config=interactions_api_config,
|
|
custom_llm_provider=custom_llm_provider,
|
|
litellm_params=litellm_params,
|
|
logging_obj=logging_obj,
|
|
extra_headers=extra_headers,
|
|
timeout=timeout,
|
|
)
|
|
|
|
if client is None:
|
|
sync_httpx_client = _get_httpx_client(
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)}
|
|
)
|
|
else:
|
|
sync_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, data = interactions_api_config.transform_delete_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = sync_httpx_client.delete(
|
|
url=url,
|
|
headers=headers,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_delete_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
interaction_id=interaction_id,
|
|
)
|
|
|
|
async def async_delete_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[AsyncHTTPHandler] = None,
|
|
) -> DeleteInteractionResult:
|
|
"""Delete an interaction by ID (async version)."""
|
|
if client is None:
|
|
async_httpx_client = get_async_httpx_client(
|
|
llm_provider=litellm.LlmProviders(custom_llm_provider),
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)},
|
|
)
|
|
else:
|
|
async_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, data = interactions_api_config.transform_delete_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = await async_httpx_client.delete(
|
|
url=url,
|
|
headers=headers,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_delete_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
interaction_id=interaction_id,
|
|
)
|
|
|
|
# =========================================================
|
|
# CANCEL INTERACTION
|
|
# =========================================================
|
|
|
|
def cancel_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[HTTPHandler] = None,
|
|
_is_async: bool = False,
|
|
) -> Union[CancelInteractionResult, Coroutine[Any, Any, CancelInteractionResult]]:
|
|
"""Cancel an interaction by ID."""
|
|
if _is_async:
|
|
return self.async_cancel_interaction(
|
|
interaction_id=interaction_id,
|
|
interactions_api_config=interactions_api_config,
|
|
custom_llm_provider=custom_llm_provider,
|
|
litellm_params=litellm_params,
|
|
logging_obj=logging_obj,
|
|
extra_headers=extra_headers,
|
|
timeout=timeout,
|
|
)
|
|
|
|
if client is None:
|
|
sync_httpx_client = _get_httpx_client(
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)}
|
|
)
|
|
else:
|
|
sync_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, data = interactions_api_config.transform_cancel_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = sync_httpx_client.post(
|
|
url=url,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_cancel_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
async def async_cancel_interaction(
|
|
self,
|
|
interaction_id: str,
|
|
interactions_api_config: BaseInteractionsAPIConfig,
|
|
custom_llm_provider: str,
|
|
litellm_params: GenericLiteLLMParams,
|
|
logging_obj: LiteLLMLoggingObj,
|
|
extra_headers: Optional[Dict[str, Any]] = None,
|
|
timeout: Optional[Union[float, httpx.Timeout]] = None,
|
|
client: Optional[AsyncHTTPHandler] = None,
|
|
) -> CancelInteractionResult:
|
|
"""Cancel an interaction by ID (async version)."""
|
|
if client is None:
|
|
async_httpx_client = get_async_httpx_client(
|
|
llm_provider=litellm.LlmProviders(custom_llm_provider),
|
|
params={"ssl_verify": litellm_params.get("ssl_verify", None)},
|
|
)
|
|
else:
|
|
async_httpx_client = client
|
|
|
|
headers = interactions_api_config.validate_environment(
|
|
headers=extra_headers or {},
|
|
model="",
|
|
litellm_params=litellm_params,
|
|
)
|
|
|
|
url, data = interactions_api_config.transform_cancel_interaction_request(
|
|
interaction_id=interaction_id,
|
|
api_base=litellm_params.api_base or "",
|
|
litellm_params=litellm_params,
|
|
headers=headers,
|
|
)
|
|
|
|
logging_obj.pre_call(
|
|
input=interaction_id,
|
|
api_key="",
|
|
additional_args={"api_base": url, "headers": headers},
|
|
)
|
|
|
|
try:
|
|
response = await async_httpx_client.post(
|
|
url=url,
|
|
headers=headers,
|
|
json=data,
|
|
timeout=timeout or request_timeout,
|
|
)
|
|
except Exception as e:
|
|
raise self._handle_error(e=e, provider_config=interactions_api_config)
|
|
|
|
return interactions_api_config.transform_cancel_interaction_response(
|
|
raw_response=response,
|
|
logging_obj=logging_obj,
|
|
)
|
|
|
|
|
|
# Initialize the HTTP handler singleton
|
|
interactions_http_handler = InteractionsHTTPHandler()
|