mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
Every repository handed its `.table` back untyped, so a dozen modules had each grown a private `_PrismaTableActions` Protocol to paper over it. They had drifted: some declared `update` as returning the row, others the row or None, and none agreed on whether `find_many` was covariant Replace all of them with a single `TableActions[RowT_co]` in `litellm/repositories/prisma_protocols.py`, keyed to the prisma row each repository is bound to. Query inputs stay `Mapping[str, object]` so callers keep passing plain dicts, and `find_many` returns `Sequence` so the row type stays covariant Typing the nullable returns honestly surfaced paths that were already crashing. A team admin could never edit or delete a memory entry owned by their team: the write-auth check fed a raw prisma row to a helper that expects the domain model, so `members_with_roles` arrived as plain dicts and the request died as a 500 instead of applying the edit. Non-admin members hit the same 500 in place of the 403 they were owed, so refusal and breakage were indistinguishable. `/v2/model/info?user_models_only=true` dereferenced a missing user row rather than returning the 400 the route already had, three team routes dereferenced a team deleted between the read and the write, and the agent registry dereferenced a missing agent instead of naming it basedpyright drops 2,132 errors, 1,454 of them reportAny and 73 reportExplicitAny. The dashboard's generated types pick up `string[]` where they had `unknown[]` for a team's members, admins and models
134 lines
5.5 KiB
Python
134 lines
5.5 KiB
Python
"""
|
|
Handler for transforming responses api requests to litellm.completion requests
|
|
"""
|
|
|
|
from collections.abc import Coroutine, Mapping
|
|
from typing import Final
|
|
|
|
import litellm
|
|
from litellm.responses.litellm_completion_transformation.streaming_iterator import (
|
|
LiteLLMCompletionStreamingIterator,
|
|
)
|
|
from litellm.responses.litellm_completion_transformation.transformation import (
|
|
LiteLLMCompletionResponsesConfig,
|
|
)
|
|
from litellm.responses.streaming_iterator import BaseResponsesAPIStreamingIterator
|
|
from litellm.types.llms.openai import (
|
|
ResponseInputParam,
|
|
ResponsesAPIOptionalRequestParams,
|
|
ResponsesAPIResponse,
|
|
)
|
|
from litellm.types.utils import ModelResponse
|
|
|
|
|
|
class LiteLLMCompletionTransformationHandler:
|
|
def response_api_handler(
|
|
self,
|
|
model: str,
|
|
input: str | ResponseInputParam,
|
|
responses_api_request: ResponsesAPIOptionalRequestParams,
|
|
custom_llm_provider: str | None = None,
|
|
_is_async: bool = False,
|
|
stream: bool | None = None,
|
|
extra_headers: Mapping[str, object] | None = None,
|
|
**kwargs,
|
|
) -> (
|
|
ResponsesAPIResponse
|
|
| BaseResponsesAPIStreamingIterator
|
|
| Coroutine[object, object, ResponsesAPIResponse | BaseResponsesAPIStreamingIterator]
|
|
):
|
|
litellm_completion_request: Final[dict] = (
|
|
LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
|
|
model=model,
|
|
input=input,
|
|
responses_api_request=responses_api_request,
|
|
custom_llm_provider=custom_llm_provider,
|
|
stream=stream,
|
|
extra_headers=extra_headers,
|
|
**kwargs,
|
|
)
|
|
)
|
|
|
|
if _is_async:
|
|
return self.async_response_api_handler(
|
|
litellm_completion_request=litellm_completion_request,
|
|
request_input=input,
|
|
responses_api_request=responses_api_request,
|
|
**kwargs,
|
|
)
|
|
|
|
completion_args: Final = {}
|
|
completion_args.update(kwargs)
|
|
completion_args.update(litellm_completion_request)
|
|
completion_args["_skip_responses_api_bridge"] = True
|
|
|
|
litellm_completion_response: Final[ModelResponse | litellm.CustomStreamWrapper] = litellm.completion(
|
|
**completion_args,
|
|
)
|
|
|
|
if isinstance(litellm_completion_response, ModelResponse):
|
|
responses_api_response: Final[ResponsesAPIResponse] = (
|
|
LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response(
|
|
chat_completion_response=litellm_completion_response,
|
|
request_input=input,
|
|
responses_api_request=responses_api_request,
|
|
)
|
|
)
|
|
|
|
return responses_api_response
|
|
|
|
elif isinstance(litellm_completion_response, litellm.CustomStreamWrapper):
|
|
return LiteLLMCompletionStreamingIterator(
|
|
model=model,
|
|
litellm_custom_stream_wrapper=litellm_completion_response,
|
|
request_input=input,
|
|
responses_api_request=responses_api_request,
|
|
custom_llm_provider=custom_llm_provider,
|
|
litellm_metadata=kwargs.get("litellm_metadata", {}),
|
|
)
|
|
raise ValueError(f"Unexpected response type: {type(litellm_completion_response)}")
|
|
|
|
async def async_response_api_handler(
|
|
self,
|
|
litellm_completion_request: dict,
|
|
request_input: str | ResponseInputParam,
|
|
responses_api_request: ResponsesAPIOptionalRequestParams,
|
|
**kwargs,
|
|
) -> ResponsesAPIResponse | BaseResponsesAPIStreamingIterator:
|
|
previous_response_id: Final[str | None] = responses_api_request.get("previous_response_id")
|
|
if previous_response_id:
|
|
litellm_completion_request = await LiteLLMCompletionResponsesConfig.async_responses_api_session_handler(
|
|
previous_response_id=previous_response_id,
|
|
litellm_completion_request=litellm_completion_request,
|
|
)
|
|
|
|
acompletion_args: Final = {}
|
|
acompletion_args.update(kwargs)
|
|
acompletion_args.update(litellm_completion_request)
|
|
acompletion_args["_skip_responses_api_bridge"] = True
|
|
|
|
litellm_completion_response: Final[ModelResponse | litellm.CustomStreamWrapper] = await litellm.acompletion(
|
|
**acompletion_args,
|
|
)
|
|
|
|
if isinstance(litellm_completion_response, ModelResponse):
|
|
responses_api_response: Final[ResponsesAPIResponse] = (
|
|
LiteLLMCompletionResponsesConfig.transform_chat_completion_response_to_responses_api_response(
|
|
chat_completion_response=litellm_completion_response,
|
|
request_input=request_input,
|
|
responses_api_request=responses_api_request,
|
|
)
|
|
)
|
|
|
|
return responses_api_response
|
|
|
|
elif isinstance(litellm_completion_response, litellm.CustomStreamWrapper):
|
|
return LiteLLMCompletionStreamingIterator(
|
|
model=litellm_completion_request.get("model") or "",
|
|
litellm_custom_stream_wrapper=litellm_completion_response,
|
|
request_input=request_input,
|
|
responses_api_request=responses_api_request,
|
|
custom_llm_provider=litellm_completion_request.get("custom_llm_provider"),
|
|
litellm_metadata=kwargs.get("litellm_metadata", {}),
|
|
)
|
|
raise ValueError(f"Unexpected response type: {type(litellm_completion_response)}")
|