From e87ae809a66852550a6639048952e0421eaebadb Mon Sep 17 00:00:00 2001 From: Maximilian Rink Date: Sat, 10 Oct 2026 18:56:23 +0200 Subject: [PATCH] fix(cache): keep typed cache helper within strict gates --- litellm/caching/caching_handler.py | 20 ++++++++++++++----- .../vertex_ai_context_caching.py | 6 +++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/litellm/caching/caching_handler.py b/litellm/caching/caching_handler.py index b1667921b22..2f3484ae12b 100644 --- a/litellm/caching/caching_handler.py +++ b/litellm/caching/caching_handler.py @@ -19,7 +19,14 @@ import datetime import inspect import time from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Mapping -from typing import TYPE_CHECKING, Any, Final, Optional, TypeVar, cast +from typing import ( + TYPE_CHECKING, + Any, + Final, + Optional, + TypeVar, + cast, # noqa: TID251 # typed boundary for dynamic cache request kwargs +) from pydantic import ConfigDict, SkipValidation, TypeAdapter, ValidationError @@ -106,6 +113,11 @@ def _drop_logging_obj_from_kwargs(request_kwargs: dict[str, object]) -> dict[str return {k: v for k, v in request_kwargs.items() if k != "litellm_logging_obj"} +def _set_cache_key_if_available(request_kwargs: dict[str, object], cache_key: str | None) -> None: + if cache_key is not None: + request_kwargs["cache_key"] = cache_key + + def _is_response_cache_excluded(model: str | None, kwargs: Mapping[str, object]) -> bool: from litellm.llms.github_copilot.per_user_auth import is_github_copilot_per_user_request @@ -465,8 +477,7 @@ class LLMCachingHandler: new_kwargs.pop("metadata", None) if new_kwargs.get("stream") is True and "cache_key" not in new_kwargs: derived_cache_key = litellm.cache.get_cache_key(**cast(dict[str, object], new_kwargs)) - if derived_cache_key is not None: - new_kwargs["cache_key"] = derived_cache_key + _set_cache_key_if_available(new_kwargs, derived_cache_key) self.request_kwargs = _drop_logging_obj_from_kwargs(new_kwargs) print_verbose("Checking Sync Cache") logging_obj.reset_caching_details() @@ -888,8 +899,7 @@ class LLMCachingHandler: return None if new_kwargs.get("stream") is True and "cache_key" not in new_kwargs: derived_cache_key = litellm.cache.get_cache_key(**new_kwargs) - if derived_cache_key is not None: - new_kwargs["cache_key"] = derived_cache_key + _set_cache_key_if_available(new_kwargs, derived_cache_key) cached_result: object | None = None if call_type == CallTypes.aembedding.value: new_kwargs["input"] = self.handle_kwargs_input_list_or_str(new_kwargs) diff --git a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py index 26ca1be77a2..f39194b72a0 100644 --- a/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py +++ b/litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py @@ -1,5 +1,9 @@ from collections.abc import Sequence -from typing import Final, Literal, cast +from typing import ( + Final, + Literal, + cast, # noqa: TID251 # preserve the runtime-compatible auth header union +) import httpx from pydantic import ConfigDict, RootModel, with_config