From 8c2e910d8a81b1012cfd60e53447149b909ddd7b Mon Sep 17 00:00:00 2001 From: mateo Date: Tue, 15 Sep 2026 15:01:22 +0000 Subject: [PATCH] fix(proxy): unblock CI - drop banned casts, gate missing request method, fix ui lint Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/proxy/auth/login_utils.py | 13 +++++-------- litellm/proxy/auth/master_key_policy.py | 8 +++----- litellm/proxy/auth/user_api_key_auth.py | 2 +- .../management_endpoints/password_endpoints.py | 2 +- tests/proxy_behavior/management/conftest.py | 2 +- ui/litellm-dashboard/eslint-suppressions.json | 4 ++-- .../src/components/model_info_view.tsx | 10 +++------- 7 files changed, 16 insertions(+), 25 deletions(-) diff --git a/litellm/proxy/auth/login_utils.py b/litellm/proxy/auth/login_utils.py index 4da178b6ae7..0dd8689417f 100644 --- a/litellm/proxy/auth/login_utils.py +++ b/litellm/proxy/auth/login_utils.py @@ -10,7 +10,7 @@ import secrets from collections.abc import Mapping from datetime import datetime, timedelta, timezone from types import MappingProxyType -from typing import TYPE_CHECKING, Final, Literal, cast +from typing import TYPE_CHECKING, Final, Literal import jwt from fastapi import HTTPException @@ -263,11 +263,8 @@ async def authenticate_user( ) = None if prisma_client is not None: - _user_row = cast( - LiteLLM_UserTable | None, - await UserRepository(prisma_client).table.find_first( - where={"user_email": {"equals": username, "mode": "insensitive"}} - ), + _user_row = await UserRepository(prisma_client).table.find_first( + where={"user_email": {"equals": username, "mode": "insensitive"}} ) """ @@ -414,7 +411,7 @@ async def authenticate_user( user_id=user_id, key=key, user_email=user_email, - user_role=cast(str, user_role), + user_role=user_role.value if user_role is not None else LitellmUserRoles.INTERNAL_USER_VIEW_ONLY.value, login_method="username_password", password_reset_required=password_reset_required, ) @@ -458,7 +455,7 @@ def encode_ui_session_jwt(returned_ui_token_object: ReturnedUITokenObject, maste master key rotates, and the session-cookie readers that require a bounded lifetime (the MCP interactive sign-in) reject it. """ - claims: Final = {**cast(dict, returned_ui_token_object), "exp": _ui_session_exp_timestamp()} + claims: Final = {**returned_ui_token_object, "exp": _ui_session_exp_timestamp()} return jwt.encode(claims, master_key, algorithm="HS256") diff --git a/litellm/proxy/auth/master_key_policy.py b/litellm/proxy/auth/master_key_policy.py index 20b66f15f67..9ca4c81a2ee 100644 --- a/litellm/proxy/auth/master_key_policy.py +++ b/litellm/proxy/auth/master_key_policy.py @@ -1,5 +1,5 @@ from collections.abc import Mapping, Sequence -from typing import Final, Literal, cast +from typing import Final, Literal from pydantic import TypeAdapter from typing_extensions import TypedDict, assert_never @@ -109,11 +109,9 @@ def stored_credentials_present() -> bool: if not isinstance(llm_router, Router): return False - model_list: Final = cast( - "list[object]", - llm_router.model_list or [], # pyright: ignore[reportUnknownMemberType] # Router.model_list is declared bare `list`; elements are validated by the TypeAdapter below + deployments: Final = _DEPLOYMENT_MARKERS.validate_python( + llm_router.model_list or [] # pyright: ignore[reportUnknownMemberType] # Router.model_list is declared bare `list`; elements are validated by the TypeAdapter ) - deployments: Final = _DEPLOYMENT_MARKERS.validate_python(model_list) return any((d.get("model_info") or {}).get("db_model") is True for d in deployments) diff --git a/litellm/proxy/auth/user_api_key_auth.py b/litellm/proxy/auth/user_api_key_auth.py index 71e2bc2f5e0..12bdb9e1e60 100644 --- a/litellm/proxy/auth/user_api_key_auth.py +++ b/litellm/proxy/auth/user_api_key_auth.py @@ -1366,7 +1366,7 @@ async def _user_api_key_auth_builder( _lockout_reason is not None and master_key_lockout_action( route=route, - method=request.method, + method=request.scope.get("method") or "", reason=_lockout_reason, stored_credentials_present=stored_credentials_present(), ) diff --git a/litellm/proxy/management_endpoints/password_endpoints.py b/litellm/proxy/management_endpoints/password_endpoints.py index bd3c9722d4d..7f1aec922a2 100644 --- a/litellm/proxy/management_endpoints/password_endpoints.py +++ b/litellm/proxy/management_endpoints/password_endpoints.py @@ -58,7 +58,7 @@ def _user_table( ) async def change_password( data: ChangePasswordRequest, - user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), # noqa: B008 # FastAPI dependency injection ) -> ChangePasswordResponse: """ Change the calling user's own password. diff --git a/tests/proxy_behavior/management/conftest.py b/tests/proxy_behavior/management/conftest.py index 4c5b2ee9949..96a89042e9d 100644 --- a/tests/proxy_behavior/management/conftest.py +++ b/tests/proxy_behavior/management/conftest.py @@ -13,7 +13,7 @@ from prisma import Json from litellm.proxy.utils import hash_token -MASTER_KEY = "sk-1234" +MASTER_KEY = "sk-litellm-behavior-master-key" SCRATCH_PREFIX = "scratch-" diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json index 773854d29e6..101c0451b2e 100644 --- a/ui/litellm-dashboard/eslint-suppressions.json +++ b/ui/litellm-dashboard/eslint-suppressions.json @@ -1071,7 +1071,7 @@ "count": 1 }, "prefer-const": { - "count": 2 + "count": 1 } }, "src/app/(dashboard)/search-tools/_components/SearchTools.tsx": { @@ -1785,7 +1785,7 @@ "count": 1 }, "prefer-const": { - "count": 5 + "count": 4 }, "react-hooks/set-state-in-effect": { "count": 1 diff --git a/ui/litellm-dashboard/src/components/model_info_view.tsx b/ui/litellm-dashboard/src/components/model_info_view.tsx index f896be52a91..1d05012678f 100644 --- a/ui/litellm-dashboard/src/components/model_info_view.tsx +++ b/ui/litellm-dashboard/src/components/model_info_view.tsx @@ -298,13 +298,9 @@ export default function ModelInfoView({ custom_llm_provider: localModelData.litellm_params?.custom_llm_provider, }, }; - toast.info("Storing credential.."); - try { - await credentialCreateCall(accessToken, credentialItem); - toast.success("Credential stored successfully"); - } catch (error) { - toast.fromError(error); - } + await credentialCreateCall(accessToken, credentialItem) + .then(() => toast.success("Credential stored successfully")) + .catch((error) => toast.fromError(error)); }; const handleModelUpdate = async (