litellm/litellm/rust_bridge/catalog.py
devin-ai-integration[bot] 5e38a08741
feat(cache): select Rust caching through explicit cache objects (#43601)
* refactor(cache): organize v2 cache as a package

* docs: clarify experimental v2 guidance

* fix(cache): verify cache-hit accounting and preserve logging metadata

* refactor(cache): separate execution facts from host accounting

* refactor(rust): build messages routes with named dependencies

* wip

* fix(cache): preserve facade policy and preflight fallback

* refactor(cache): defer shared Python logging changes

* test(gateway-inference): allow dead code in shared test helpers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(cache): key prepared requests and honor facade controls

* feat(cache): use Python caches from Rust Messages inference

* refactor(cache): separate native and Python cache adapters

* refactor(cache): enforce shared composition and adapter boundaries

* fix(cache): let Python key delegated Rust Messages entries

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-29 00:01:44 +00:00

112 lines
4.1 KiB
Python

"""Ordered rollout policy for routes, loggers, and secret managers.
The first matching rule wins; unmatched contexts stay on Python. Native
admission separately decides whether the selected implementation can execute.
"""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import Final, TypeAlias
from litellm.rust_bridge.configuration import Decision, Rollout
from litellm.rust_bridge.configuration import decision as _decision
from litellm.types.secret_managers.main import KeyManagementSystem
class Route(str, Enum):
CHAT_COMPLETIONS = "chat_completions"
EMBEDDINGS = "embeddings"
MESSAGES = "messages"
RESPONSES = "responses"
TRANSCRIPTION = "transcription"
OCR = "ocr"
TOKEN_COUNTER = "token_counter"
TOKENIZER = "tokenizer"
@dataclass(frozen=True, slots=True)
class RouteContext:
route: Route
provider: str | None = None
model: str | None = None
@dataclass(frozen=True, slots=True)
class RouteRule:
route: Route
rollout: Rollout
providers: frozenset[str] | None = None
models: frozenset[str] | None = None
def matches(self, context: Context) -> bool:
return (
isinstance(context, RouteContext)
and context.route is self.route
and (self.providers is None or context.provider in self.providers)
and (self.models is None or context.model in self.models)
)
@dataclass(frozen=True, slots=True)
class SecretManagerContext:
system: str
@dataclass(frozen=True, slots=True)
class SecretManagerRule:
rollout: Rollout
systems: frozenset[str] | None = None
def matches(self, context: Context) -> bool:
return isinstance(context, SecretManagerContext) and (self.systems is None or context.system in self.systems)
@dataclass(frozen=True, slots=True)
class LoggerContext:
pass
@dataclass(frozen=True, slots=True)
class LoggerRule:
rollout: Rollout
def matches(self, context: Context) -> bool:
return isinstance(context, LoggerContext)
Context: TypeAlias = RouteContext | SecretManagerContext | LoggerContext
Rule: TypeAlias = RouteRule | SecretManagerRule | LoggerRule
Rules: TypeAlias = tuple[Rule, ...]
RULES: Final[Rules] = (
LoggerRule(Rollout.RUST_OPT_IN),
RouteRule(Route.CHAT_COMPLETIONS, Rollout.PYTHON_ONLY),
RouteRule(Route.EMBEDDINGS, Rollout.PYTHON_ONLY),
RouteRule(Route.OCR, Rollout.RUST_REQUIRED),
RouteRule(Route.MESSAGES, Rollout.RUST_OPT_IN, providers=frozenset({"anthropic"})),
RouteRule(Route.MESSAGES, Rollout.PYTHON_ONLY),
RouteRule(Route.RESPONSES, Rollout.PYTHON_ONLY),
RouteRule(Route.TOKEN_COUNTER, Rollout.PYTHON_ONLY),
RouteRule(Route.TOKENIZER, Rollout.PYTHON_ONLY),
RouteRule(Route.TRANSCRIPTION, Rollout.RUST_REQUIRED, providers=frozenset({"bedrock"})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.GOOGLE_KMS.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.AZURE_KEY_VAULT.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.AWS_SECRET_MANAGER.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.GOOGLE_SECRET_MANAGER.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.HASHICORP_VAULT.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.CYBERARK.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.LOCAL.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.AWS_KMS.value})),
SecretManagerRule(Rollout.PYTHON_ONLY, systems=frozenset({KeyManagementSystem.CUSTOM.value})),
)
def rollout(context: Context, rules: Rules | None = None) -> Rollout:
selected_rules: Final = RULES if rules is None else rules
return next((rule.rollout for rule in selected_rules if rule.matches(context)), Rollout.PYTHON_ONLY)
def decision(context: Context, rules: Rules | None = None) -> Decision:
return _decision(rollout(context, rules))