From d4619c499a6052913c8fa548192966dd76c3fec9 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 09:53:43 +0000 Subject: [PATCH] refactor(types): replace Any with proven types in 6 files (#44491) * refactor(types): replace Any with proven types in 14 files Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(types): keep base parsing in sso userinfo, copilot auth and hf config lookups Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(types): keep base parsing at unproven provider seams Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(types): keep base delete in jwt orphan cleanup Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/__init__.py | 15 ++++++++------- litellm/harness/handlers/deepagents_handler.py | 8 ++++---- litellm/llms/openai/responses/transformation.py | 7 ++++--- .../_experimental/mcp_server/rest_endpoints.py | 5 ++--- litellm/proxy/auth/user_api_key_auth.py | 6 +++--- litellm/router.py | 2 +- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/litellm/__init__.py b/litellm/__init__.py index 03d8fccb27e..487d5da1663 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -1542,20 +1542,20 @@ from .passthrough import allm_passthrough_route, llm_passthrough_route from .google_genai import agenerate_content ### GLOBAL CONFIG ### -global_bitbucket_config: Optional[Dict[str, Any]] = None +global_bitbucket_config: Optional[Mapping[str, object]] = None -def set_global_bitbucket_config(config: Dict[str, Any]) -> None: +def set_global_bitbucket_config(config: Mapping[str, object]) -> None: """Set global BitBucket configuration for prompt management.""" global global_bitbucket_config global_bitbucket_config = config ### GLOBAL CONFIG ### -global_gitlab_config: Optional[Dict[str, Any]] = None +global_gitlab_config: Optional[Mapping[str, object]] = None -def set_global_gitlab_config(config: Dict[str, Any]) -> None: +def set_global_gitlab_config(config: Mapping[str, object]) -> None: """Set global BitBucket configuration for prompt management.""" global global_gitlab_config global_gitlab_config = config @@ -2210,12 +2210,13 @@ if TYPE_CHECKING: DefaultTeamSSOParams, LiteLLM_UpperboundKeyGenerateParams, ) + from litellm.utils import ModelResponseListIterator as _ModelResponseListIterator # Cost calculator functions cost_per_token: Callable[..., Tuple[float, float]] completion_cost: Callable[..., float] - response_cost_calculator: Any - modify_integration: Any + response_cost_calculator: Callable[..., float] + modify_integration: Callable[..., None] # Utils functions - type stubs for truly lazy loaded functions only # (functions NOT imported via "from .main import *") @@ -2249,7 +2250,7 @@ if TYPE_CHECKING: remove_index_from_tool_calls: Callable[..., None] # Response types - truly lazy loaded only (not in main.py or elsewhere) - ModelResponseListIterator: Type[Any] + ModelResponseListIterator: Type[_ModelResponseListIterator] # HTTP handler singletons (created lazily via __getattr__ at runtime) module_level_aclient: AsyncHTTPHandler diff --git a/litellm/harness/handlers/deepagents_handler.py b/litellm/harness/handlers/deepagents_handler.py index 3bdc158a0d1..9ffaf52ee59 100644 --- a/litellm/harness/handlers/deepagents_handler.py +++ b/litellm/harness/handlers/deepagents_handler.py @@ -63,7 +63,7 @@ class DeepAgentsDeps: chat_litellm: Any checkpointer_cls: Any command_cls: Any - subagent_defaults: Mapping[str, Any] + subagent_defaults: Mapping[str, object] convert_to_openai_messages: Any backend: ModuleType @@ -174,7 +174,7 @@ class DeepAgentsHandler(BaseHarnessHandler): yield event if not state.interrupts: break - resume: dict[str, Any] = {} # mutable-ok: Command(resume=) payload, filled per answered approval + resume: dict[str, object] = {} # mutable-ok: Command(resume=) payload, filled per answered approval for interrupt in state.interrupts: decisions: list[dict[str, Any]] = [] # mutable-ok: HITL decisions collected across awaited approvals for request in approval_requests(getattr(interrupt, "value", None)): @@ -236,13 +236,13 @@ class DeepAgentsHandler(BaseHarnessHandler): return run_config @staticmethod - def _middleware(deps: DeepAgentsDeps, blocked: frozenset[str]) -> list[Any]: # mutable-ok: deepagents API + def _middleware(deps: DeepAgentsDeps, blocked: frozenset[str]) -> list[object]: # mutable-ok: deepagents API filters = (deps.backend.ToolFilterMiddleware(blocked),) if blocked else () return list(filters) # mutable-ok: deepagents create_deep_agent(middleware=) takes a list def _subagents( self, ctx: SessionContext, deps: DeepAgentsDeps, blocked: frozenset[str] - ) -> list[Any]: # mutable-ok: deepagents create_deep_agent(subagents=) takes a list + ) -> list[object]: # mutable-ok: deepagents create_deep_agent(subagents=) takes a list """User subagents, plus a general-purpose one that honours disable_tools when set.""" options = ctx.options if isinstance(ctx.options, DeepAgentsOptions) else None user_subagents = tuple(options.subagents) if options is not None else () diff --git a/litellm/llms/openai/responses/transformation.py b/litellm/llms/openai/responses/transformation.py index e4928868699..434df9fae6a 100644 --- a/litellm/llms/openai/responses/transformation.py +++ b/litellm/llms/openai/responses/transformation.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Final, Protocol, cast, get_type_hints import httpx from openai.types.responses import ResponseReasoningItem -from pydantic import BaseModel, TypeAdapter, ValidationError +from pydantic import BaseModel, ConfigDict, TypeAdapter, ValidationError from typing_extensions import ReadOnly, TypedDict import litellm @@ -37,6 +37,7 @@ from ..common_utils import OpenAIError from ..workload_identity import get_workload_identity_bearer_token, resolve_openai_workload_identity_config OPENAI_RESPONSES_API_MIN_MAX_OUTPUT_TOKENS: Final = 16 +_RAW_RESPONSE_JSON: Final = TypeAdapter(dict[str, object], config=ConfigDict(strict=True)) if TYPE_CHECKING: from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj @@ -577,7 +578,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): original_response=raw_response.text, additional_args={"complete_input_dict": {}}, ) - raw_response_json: Final = raw_response.json() + raw_response_json: Final = _RAW_RESPONSE_JSON.validate_python(raw_response.json()) raw_response_json["created_at"] = _safe_convert_created_field(raw_response_json["created_at"]) except Exception: raise OpenAIError(message=raw_response.text, status_code=raw_response.status_code) @@ -977,7 +978,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): original_response=raw_response.text, additional_args={"complete_input_dict": {}}, ) - raw_response_json: Final = raw_response.json() + raw_response_json: Final = _RAW_RESPONSE_JSON.validate_python(raw_response.json()) raw_response_json["created_at"] = _safe_convert_created_field(raw_response_json["created_at"]) except Exception: raise OpenAIError(message=raw_response.text, status_code=raw_response.status_code) diff --git a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py index 534eda07292..305b8a27c92 100644 --- a/litellm/proxy/_experimental/mcp_server/rest_endpoints.py +++ b/litellm/proxy/_experimental/mcp_server/rest_endpoints.py @@ -569,9 +569,8 @@ if MCP_AVAILABLE: "alias": server.alias, } return [ - ListMCPToolsRestAPIResponseObject( - **tool.model_dump(by_alias=True, exclude={"mcp_info"}), - mcp_info=enriched_mcp_info, + ListMCPToolsRestAPIResponseObject.model_validate( + {**tool.model_dump(by_alias=True, exclude={"mcp_info"}), "mcp_info": enriched_mcp_info} ) for tool in tools ] diff --git a/litellm/proxy/auth/user_api_key_auth.py b/litellm/proxy/auth/user_api_key_auth.py index 65aa337c057..87bba4ecedd 100644 --- a/litellm/proxy/auth/user_api_key_auth.py +++ b/litellm/proxy/auth/user_api_key_auth.py @@ -147,7 +147,7 @@ from litellm.proxy.utils import ( ProxyLogging, normalize_route_for_root_path, ) -from litellm.repositories.table_repositories import TeamMembershipRepository +from litellm.repositories.table_repositories import JWTKeyMappingRepository, TeamMembershipRepository from litellm.repositories.verification_token_repository import VerificationTokenRepository from litellm.router_utils.common_utils import resolve_model_group_alias from litellm.secret_managers.main import get_secret_bool @@ -1038,7 +1038,7 @@ async def _auto_register_jwt_mapping( try: async with db_span("auto_register_jwt_mapping", "LiteLLM_JWTKeyMapping"): - await prisma_client.db.litellm_jwtkeymapping.create( + await JWTKeyMappingRepository(prisma_client).table.create( data={ "jwt_issuer": jwt_issuer or "", "jwt_claim_name": virtual_key_claim_field, @@ -2387,7 +2387,7 @@ async def validate_resolved_virtual_key( # noqa: C901 # Preserve ordering of e include={"litellm_budget_table": True}, ) if _db_member is not None: - team_member_info = LiteLLM_TeamMembership(**_db_member.model_dump()) + team_member_info = LiteLLM_TeamMembership.model_validate(_db_member.model_dump()) await user_api_key_cache.async_set_cache( key=_cache_key, value=team_member_info, diff --git a/litellm/router.py b/litellm/router.py index c57302c5645..513a5dc7c25 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -4339,7 +4339,7 @@ class Router: ) ) responses: Final = await asyncio.gather(*_tasks) - final_responses: Final[list[list[Any]]] = [[] for _ in range(len(messages))] + final_responses: Final[list[list[object]]] = [[] for _ in range(len(messages))] for response in responses: if isinstance(response, tuple): final_responses[response[1]].append(response[0])