refactor(anthropic): rename experimental_pass_through to pass_through (#43329)

* refactor(anthropic): rename experimental_pass_through to pass_through

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

* test(anthropic): point compact patch targets at renamed pass_through path

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

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-09-26 13:00:50 -07:00 • committed by GitHub
parent 0300fc4ab2
commit 69ad004015
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
129 changed files with 417 additions and 417 deletions

View file

@ -336,7 +336,7 @@ Each translation is isolated in its own file, making it easy to test and modify
| `/v1/chat/completions` | Gemini | `llms/gemini/chat/transformation.py` |
| `/v1/chat/completions` | Vertex AI | `llms/vertex_ai/gemini/transformation.py` |
| `/v1/chat/completions` | OpenAI | `llms/openai/chat/gpt_transformation.py` |
| `/v1/messages` (passthrough) | Anthropic | `llms/anthropic/experimental_pass_through/messages/transformation.py` |
| `/v1/messages` (passthrough) | Anthropic | `llms/anthropic/pass_through/messages/transformation.py` |
| `/v1/messages` (passthrough) | Bedrock | `llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py` |
| `/v1/messages` (passthrough) | Vertex AI | `llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py` |
| Passthrough endpoints | All | `proxy/pass_through_endpoints/llm_provider_handlers/` |

View file

@ -1691,7 +1691,7 @@ if TYPE_CHECKING:
SagemakerNovaConfig as SagemakerNovaConfig,
)
from .llms.cohere.chat.transformation import CohereChatConfig as CohereChatConfig
from .llms.anthropic.experimental_pass_through.messages.transformation import (
from .llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig as AnthropicMessagesConfig,
)
from .llms.bedrock.messages.invoke_transformations.anthropic_claude3_transformation import (

View file

@ -742,7 +742,7 @@ _LLM_CONFIGS_IMPORT_MAP: Final = {
),
"CohereChatConfig": (".llms.cohere.chat.transformation", "CohereChatConfig"),
"AnthropicMessagesConfig": (
".llms.anthropic.experimental_pass_through.messages.transformation",
".llms.anthropic.pass_through.messages.transformation",
"AnthropicMessagesConfig",
),
"BedrockClaudePlatformMessagesConfig": (

View file

@ -52,7 +52,7 @@ from litellm.types.utils import (
if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.llms.anthropic.experimental_pass_through.messages.response_cache import (
from litellm.llms.anthropic.pass_through.messages.response_cache import (
AnthropicMessagesStreamCacheWriter,
)
from litellm.types.utils import PromptTokensDetailsWrapper
@ -127,7 +127,7 @@ def _should_defer_streaming_cache_hit_callbacks(*, cached_result: object) -> boo
spend and callback records. A plain (non-stream) replay logs here, since nothing
else will.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.response_cache import (
from litellm.llms.anthropic.pass_through.messages.response_cache import (
CachedAnthropicMessagesStreamIterator,
)
from litellm.responses.streaming_iterator import BaseResponsesAPIStreamingIterator
@ -930,7 +930,7 @@ class LLMCachingHandler:
elif (
call_type == CallTypes.anthropic_messages.value or call_type == CallTypes.aanthropic_messages.value
) and isinstance(cached_result, dict):
from litellm.llms.anthropic.experimental_pass_through.messages.response_cache import (
from litellm.llms.anthropic.pass_through.messages.response_cache import (
convert_cached_anthropic_messages_result,
)
@ -1150,7 +1150,7 @@ class LLMCachingHandler:
return result
if not isinstance(result, AsyncIterator):
return result
from litellm.llms.anthropic.experimental_pass_through.messages.response_cache import (
from litellm.llms.anthropic.pass_through.messages.response_cache import (
AnthropicMessagesStreamCacheWriter,
)

View file

@ -111,7 +111,7 @@ def _chat_request_from_anthropic_messages(
because the logged optional_params switch dialect per provider path (the bridge's
inner completion rewrites them to chat shape mid-flight); the adapter translates
them alongside the messages, and sampling params copy through untranslated."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)

View file

@ -70,7 +70,7 @@ Claude Code (Anthropic's official CLI) sends web search requests using Anthropic
Native tools are converted to LiteLLM standard format **before** sending to the provider:
1. **Conversion Point** (`litellm/llms/anthropic/experimental_pass_through/messages/handler.py`):
1. **Conversion Point** (`litellm/llms/anthropic/pass_through/messages/handler.py`):
- In `anthropic_messages()` function (lines 60-127)
- Runs BEFORE the API request is made
- Detects native web search tools using `is_web_search_tool()`

View file

@ -25,7 +25,7 @@ from typing_extensions import ReadOnly, TypedDict, assert_never
from litellm._logging import verbose_proxy_logger
from litellm.llms.anthropic.chat.transformation import AnthropicConfig
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
is_provider_native_tool_dict,
)
@ -365,7 +365,7 @@ class AnthropicMessagesHandler(BaseTranslation):
def _standalone_block_chunks(self, exc: "ModifyResponseException") -> list[bytes]:
import uuid
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.base_llm.guardrail_translation.utils import (

View file

@ -11,15 +11,15 @@ from typing_extensions import TypedDict
import litellm
from litellm._logging import verbose_logger
from litellm.litellm_core_utils.asyncify import run_async_function
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
AnthropicAdapter,
)
from litellm.llms.anthropic.experimental_pass_through.context_management import (
from litellm.llms.anthropic.pass_through.context_management import (
AnthropicContextManagementError,
PolyfillResult,
apply_context_management,
)
from litellm.llms.anthropic.experimental_pass_through.utils import (
from litellm.llms.anthropic.pass_through.utils import (
is_reasoning_auto_summary_enabled,
litellm_logging_obj_from_kwargs,
local_model_name,
@ -102,7 +102,7 @@ async def _prepare_context_managed_request(
user_api_key_auth: "UserAPIKeyAuth | None" = None,
) -> PolyfillResult | None:
"""Apply client compaction history, then optional context_management polyfill."""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
apply_client_compaction_block_history,
)
@ -179,7 +179,7 @@ def _polyfill_will_run(
if edits is None:
return False
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_EDIT_TYPE,
)
@ -205,7 +205,7 @@ def _spec_has_non_compact_edits(
if edits is None:
return False
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_EDIT_TYPE,
)
@ -240,7 +240,7 @@ def _normalize_spec_edits(
if _context_management_explicitly_dropped(additional_drop_params):
return None
from litellm.llms.anthropic.experimental_pass_through.context_management.dispatcher import (
from litellm.llms.anthropic.pass_through.context_management.dispatcher import (
_normalize_spec,
)
@ -437,7 +437,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
Handles both string ("max") and dict ({"effort": "max", "summary": ...})
formats. Uses model registry to check supports_xhigh/supports_minimal.
"""
from litellm.llms.anthropic.experimental_pass_through.utils import (
from litellm.llms.anthropic.pass_through.utils import (
normalize_reasoning_effort_value,
)

View file

@ -118,7 +118,7 @@ class _CombinedChunkSplitter:
@staticmethod
def _is_combined(chunk: "ModelResponseStream") -> bool:
"""True if ``chunk`` carries response content AND a finish_reason."""
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
openai_chat_refusal_text,
)
@ -1029,7 +1029,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
delta: Final = processed_chunk["delta"]
if delta.get("stop_reason") == "max_tokens":
return processed_chunk
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
refusal_stop_details,
)
@ -1083,7 +1083,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
@staticmethod
def _is_blank_delta(chunk: "ModelResponseStream") -> bool:
from litellm.llms.anthropic.common_utils import is_empty_unsigned_thinking_block
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
openai_chat_refusal_text,
)
@ -1120,7 +1120,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
- Different content types in the response
- Specific markers in the content
"""
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
openai_chat_refusal_text,
)

View file

@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias, TypeVar, cast
from pydantic import JsonValue, TypeAdapter
import litellm
from litellm.llms.anthropic.experimental_pass_through.utils import (
from litellm.llms.anthropic.pass_through.utils import (
is_reasoning_auto_summary_enabled,
prompt_cache_key_from_user_id,
)
@ -134,14 +134,14 @@ from litellm.llms.anthropic.common_utils import (
normalize_anthropic_tool_use_id,
strip_encrypted_reasoning_blocks_from_anthropic_messages,
)
from litellm.llms.anthropic.experimental_pass_through.context_management import (
from litellm.llms.anthropic.pass_through.context_management import (
PolyfillResult,
)
from litellm.llms.anthropic.experimental_pass_through.messages.mid_conversation_system import (
from litellm.llms.anthropic.pass_through.messages.mid_conversation_system import (
convert_mid_conversation_system_turns,
is_system_role_message,
)
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
openai_chat_refusal_text,
refusal_stop_details,
)

View file

@ -798,7 +798,7 @@ def _count_effective_tokens(
threshold check matches the downstream ``input_tokens`` metric.
"""
# Local import to avoid pulling the adapter at module load time.
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -955,7 +955,7 @@ def _build_summary_messages(
system prompt); the conversation history is translated to OpenAI shape;
the summarization prompt is appended as a final user turn.
"""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)

View file

@ -336,7 +336,7 @@ class AgenticAnthropicStreamingIterator:
await task
async def aclose(self) -> None:
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
aclose_if_supported,
)
@ -379,7 +379,7 @@ class AgenticAnthropicStreamingIterator:
if hasattr(result, "__aiter__"):
self._follow_up_iterator = result.__aiter__()
elif isinstance(result, dict):
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.types.llms.anthropic_messages.anthropic_response import (

View file

@ -215,7 +215,7 @@ async def _try_websearch_short_circuit(
if response is not None:
anthropic_response = cast(AnthropicMessagesResponse, response)
if stream:
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
@ -531,7 +531,7 @@ def anthropic_messages_handler(
# reference the provider cannot resolve. Popped from kwargs so it never reaches the provider.
skip_mcp_handler: Final = kwargs.pop("_skip_mcp_handler", False)
if not skip_mcp_handler and tools:
from litellm.llms.anthropic.experimental_pass_through.messages.mcp_handler import (
from litellm.llms.anthropic.pass_through.messages.mcp_handler import (
anthropic_messages_with_mcp,
)
from litellm.responses.mcp.litellm_proxy_mcp_handler import (

View file

@ -67,7 +67,7 @@ class AdvisorOrchestrationHandler(MessagesInterceptor):
custom_llm_provider: str | None,
**kwargs,
) -> AnthropicMessagesResponse | AsyncIterator:
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)

View file

@ -180,7 +180,7 @@ async def anthropic_messages_with_mcp(
)
if stream:
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)

View file

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Final
import litellm
from litellm._logging import verbose_logger
from litellm.caching.caching_handler import create_cache_write_task
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
AnthropicMessagesStreamingResponse,
BaseAnthropicMessagesStreamingIterator,
_is_message_stop_chunk,

View file

@ -16,7 +16,7 @@ from litellm.litellm_core_utils.core_helpers import process_response_headers
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.litellm_core_utils.logging_worker import GLOBAL_LOGGING_WORKER
from litellm.llms.anthropic.common_utils import ANTHROPIC_ERROR_STATUS_CODE_MAP
from litellm.llms.anthropic.experimental_pass_through.messages.utils import INCOMPLETE_STREAM_ERROR_MESSAGE
from litellm.llms.anthropic.pass_through.messages.utils import INCOMPLETE_STREAM_ERROR_MESSAGE
from litellm.proxy.pass_through_endpoints.success_handler import (
PassThroughEndpointLogging,
)

View file

@ -590,7 +590,7 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
litellm_logging_obj: LiteLLMLoggingObj,
) -> AsyncIterator:
"""Helper function to handle Anthropic streaming responses using the existing logging handlers"""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
BaseAnthropicMessagesStreamingIterator,
)

View file

@ -109,7 +109,7 @@ def _build_responses_kwargs(
if isinstance(reasoning, dict):
effort: Final[object] = reasoning.get("effort")
if isinstance(effort, str):
from litellm.llms.anthropic.experimental_pass_through.utils import (
from litellm.llms.anthropic.pass_through.utils import (
normalize_reasoning_effort_value,
)

View file

@ -15,7 +15,7 @@ from litellm.exceptions import MidStreamFallbackError
from litellm.litellm_core_utils.prompt_templates.common_utils import (
encrypted_reasoning_signature,
)
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
INCOMPLETE_STREAM_ERROR_MESSAGE,
refusal_stop_details,
responses_output_refusal_text,

View file

@ -20,11 +20,11 @@ from litellm.litellm_core_utils.prompt_templates.common_utils import (
from litellm.litellm_core_utils.reasoning_effort_utils import (
reasoning_effort_from_thinking_budget,
)
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
refusal_stop_details,
responses_output_refusal_text,
)
from litellm.llms.anthropic.experimental_pass_through.utils import (
from litellm.llms.anthropic.pass_through.utils import (
is_reasoning_auto_summary_enabled,
prompt_cache_key_from_user_id,
)
@ -69,7 +69,7 @@ class LiteLLMAnthropicToResponsesAPIAdapter:
if raw_usage is None:
return AnthropicUsage(input_tokens=0, output_tokens=0)
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
from litellm.responses.utils import ResponseAPILoggingUtils

View file

@ -16,7 +16,7 @@ import litellm
from litellm.llms.anthropic.common_utils import AnthropicModelInfo, is_anthropic_oauth_key
from litellm.llms.anthropic.count_tokens.handler import AnthropicCountTokensHandler
from litellm.llms.anthropic.count_tokens.transformation import COUNT_TOKEN_OPTION_NAMES
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
DEFAULT_ANTHROPIC_API_VERSION,
AnthropicMessagesConfig,
)

View file

@ -4,7 +4,7 @@ Azure Anthropic messages transformation config - extends AnthropicMessagesConfig
from typing import Any, Final
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.azure.common_utils import BaseAzureLLM

View file

@ -1831,7 +1831,7 @@ class AmazonConverseConfig(BaseConfig):
anthropic_beta_list: list,
) -> None:
"""Keep only compact_20260112 edits for Bedrock; add beta header or drop field."""
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_EDIT_TYPE,
)
from litellm.types.llms.anthropic import ANTHROPIC_BETA_HEADER_VALUES

View file

@ -1,7 +1,7 @@
from typing import Any, Final
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
DEFAULT_ANTHROPIC_API_VERSION,
AnthropicMessagesConfig,
)

View file

@ -18,7 +18,7 @@ from litellm.llms.anthropic.chat.transformation import (
AnthropicConfig,
)
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.base_llm.anthropic_messages.transformation import (
@ -798,7 +798,7 @@ class AmazonAnthropicClaudeMessagesConfig(
merge them from ``message_start`` so logging/cost sees a consistent usage
object (fixes negative input costs: LIT-2411).
"""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
BaseAnthropicMessagesStreamingIterator,
)

View file

@ -14,7 +14,7 @@ from typing import TYPE_CHECKING, Any, Final
import httpx
from pydantic import TypeAdapter
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
DEFAULT_ANTHROPIC_API_VERSION,
AnthropicMessagesConfig,
)

View file

@ -204,7 +204,7 @@ if TYPE_CHECKING:
from litellm.integrations.custom_logger import CustomLogger
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.litellm_core_utils.tokenizer import Encoding as Tokenizer
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.base_llm.passthrough.transformation import BasePassthroughConfig
@ -2124,7 +2124,7 @@ class BaseLLMHTTPHandler:
initial_response: AsyncIterator | AnthropicMessagesResponse
if stream:
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
AnthropicMessagesStreamingResponse,
anthropic_messages_stream_hidden_params,
)
@ -2148,7 +2148,7 @@ class BaseLLMHTTPHandler:
hidden_params=stream_hidden_params,
)
from litellm.llms.anthropic.experimental_pass_through.messages.agentic_streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.agentic_streaming_iterator import (
AgenticAnthropicStreamingIterator,
)
@ -5540,7 +5540,7 @@ class BaseLLMHTTPHandler:
from typing import cast
from litellm._logging import verbose_logger
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.types.llms.anthropic_messages.anthropic_response import (

View file

@ -5,7 +5,7 @@ DeepSeek Anthropic-compatible messages transformation config.
from typing import Any, Final
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.secret_managers.main import get_secret_str

View file

@ -1,7 +1,7 @@
from typing import Any, Final
from litellm.exceptions import AuthenticationError
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)

View file

@ -5,7 +5,7 @@ MiniMax Anthropic transformation config - extends AnthropicConfig for MiniMax's
from typing import Any, Final # noqa: TID251 # override below must mirror the legacy base signature
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.secret_managers.main import get_secret_str

View file

@ -2,7 +2,7 @@ from typing import Any, Final
import litellm
from litellm.llms.anthropic.common_utils import normalize_cache_control_in_anthropic_payload
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.openai_like.json_loader import SimpleProviderConfig

View file

@ -8,7 +8,7 @@ alongside its standard OpenAI-compatible chat completions endpoint.
from typing import Any
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.secret_managers.main import get_secret_str

View file

@ -1,7 +1,7 @@
from typing import Any, Final
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.types.llms.anthropic import (

View file

@ -5,7 +5,7 @@ from typing import Final, TypeAlias, cast # noqa: TID251 # native binding sele
from litellm.exceptions import BadRequestError
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
from litellm.llms.anthropic.experimental_pass_through.messages import handler as main
from litellm.llms.anthropic.pass_through.messages import handler as main
from litellm.rust_bridge.catalog import Delivery, Route, RouteContext
from litellm.rust_bridge.dispatch import PublicDispatch, call_hook
from litellm.rust_bridge.messages.entrypoints import (

View file

@ -14,7 +14,7 @@ from litellm.anthropic_interface.exceptions import (
AnthropicExceptionMapping,
)
from litellm.integrations.custom_guardrail import ModifyResponseException
from litellm.llms.anthropic.experimental_pass_through.context_management import (
from litellm.llms.anthropic.pass_through.context_management import (
AnthropicContextManagementError,
)
from litellm.llms.base_llm.guardrail_translation.utils import (

View file

@ -167,10 +167,10 @@ def is_sse_error_stream(all_chunks: Sequence[object]) -> bool:
def anthropic_sse_chunks_from_response(assembled: ModelResponse) -> tuple[bytes, ...]:
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)

View file

@ -535,7 +535,7 @@ def _v3_answer(request_data: Mapping[str, object], model: str | None) -> Mapping
return _v3_text_completion_as_chat(response)
if not isinstance(response, ModelResponse) or not _v3_anthropic_messages_route(request_data):
return _jsonable_dict(response)
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)

View file

@ -294,7 +294,7 @@ class PassThroughStreamingHandler:
- Vertex AI
- OpenAI
"""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
_is_message_stop_chunk, # pyright: ignore[reportPrivateUsage] # both native stream paths share terminal-event detection
_is_provider_error_chunk, # pyright: ignore[reportPrivateUsage] # provider errors must not become cache evidence
)

View file

@ -525,7 +525,7 @@ MAX_BUFFERED_PRE_CONTENT_ANTHROPIC_CHUNKS: Final = 200
def _anthropic_stream_should_drop_pre_content_ping(chunk: object, has_generated_content: bool) -> bool:
"""A `ping` keepalive seen before any real content is dropped outright - it recurs indefinitely on a
slow-starting connection and carries nothing worth buffering toward a possible fallback."""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import is_anthropic_ping_chunk
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import is_anthropic_ping_chunk
if has_generated_content:
return False
@ -536,7 +536,7 @@ def _anthropic_stream_forwards_ping_live(chunk: object, has_generated_content: b
"""A `ping` that no lifecycle frame precedes reaches the client live: a fallback's own message_start can still
follow it without overlapping lifecycles, and AgenticAnthropicStreamingIterator's hold-back keepalive is exactly
such a ping."""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import is_anthropic_ping_chunk
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import is_anthropic_ping_chunk
if has_generated_content or buffered_chunk_count:
return False
@ -550,7 +550,7 @@ def _is_retriable_anthropic_status(status_code: int) -> bool:
def _anthropic_stream_error_is_gateway_verdict(chunk: object) -> bool:
"""AgenticAnthropicStreamingIterator's own retrieval-failure frame is the gateway's verdict, not a provider
failure: another deployment would rerun the same failed hook, so it reaches the client instead of falling back."""
from litellm.llms.anthropic.experimental_pass_through.messages.agentic_streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.agentic_streaming_iterator import (
is_server_fulfilled_tool_leak_error,
)
@ -605,7 +605,7 @@ def _anthropic_stream_commits_now(chunk: object, has_generated_content: bool, bu
pre-content buffer cap was hit) rather than keep buffering lifecycle
frames toward a possible fallback.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
is_anthropic_content_delta_chunk,
)
@ -5354,7 +5354,7 @@ class Router:
response=response,
kwargs=kwargs,
):
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
safeguard_refusal_error,
)
@ -5464,12 +5464,12 @@ class Router:
anyway) or once the stream ends without ever producing content or
an error.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
aclose_if_supported,
parse_anthropic_error_event,
parse_anthropic_refusal_stop_details,
)
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
safeguard_refusal_error,
)
@ -5626,7 +5626,7 @@ class Router:
budget.
"""
from litellm.exceptions import MidStreamFallbackError
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
aclose_if_supported,
anthropic_messages_response_as_sse_events,
)
@ -8466,7 +8466,7 @@ class Router:
when a content-policy fallback is configured; a plain refusal without stop_details, or
any response with nothing configured, is returned to the client unchanged.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
get_safeguard_refusal_stop_details,
)
@ -12206,7 +12206,7 @@ class Router:
`tools` (Chat Completions, Responses and Anthropic Messages shapes) and the
Anthropic Messages top-level `system` block.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.utils import (
from litellm.llms.anthropic.pass_through.messages.utils import (
anthropic_system_to_openai_message,
)

View file

@ -326,7 +326,7 @@ def stream_success(
end: datetime.datetime,
first_chunk: datetime.datetime | None,
) -> None:
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
GLOBAL_PASS_THROUGH_SUCCESS_HANDLER_OBJ,
)
from litellm.proxy.pass_through_endpoints.streaming_handler import PassThroughStreamingHandler

View file

@ -9,7 +9,7 @@ from pydantic import TypeAdapter, ValidationError
import litellm
from litellm.litellm_core_utils.core_helpers import normalize_drop_params
from litellm.llms.anthropic.experimental_pass_through.utils import is_reasoning_auto_summary_enabled
from litellm.llms.anthropic.pass_through.utils import is_reasoning_auto_summary_enabled
from litellm.rust_bridge import failures
from litellm.rust_bridge.messages.entrypoints import LiteLLMMessagesRequest
from litellm.types.llms.anthropic_messages.anthropic_response import AnthropicMessagesResponse
@ -55,7 +55,7 @@ def response(value: Mapping[str, object]) -> AnthropicMessagesResponse:
def stream_hidden_params(headers: Sequence[tuple[str, str]]) -> Mapping[str, object]:
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
anthropic_messages_stream_hidden_params,
)

View file

@ -63,7 +63,7 @@ max-args = 5
# directly, each with a `# noqa: TID251 # <reason>`.
"litellm.responses.main.responses".msg = "Import litellm.responses.dispatch.responses so the call routes through dispatch."
"litellm.responses.main.aresponses".msg = "Import litellm.responses.dispatch.aresponses so the call routes through dispatch."
"litellm.llms.anthropic.experimental_pass_through.messages.handler.anthropic_messages".msg = "Import litellm.messages.anthropic_messages so the call routes through dispatch."
"litellm.llms.anthropic.experimental_pass_through.messages.handler.anthropic_messages_handler".msg = "Import litellm.messages.anthropic_messages_handler so the call routes through dispatch."
"litellm.llms.anthropic.pass_through.messages.handler.anthropic_messages".msg = "Import litellm.messages.anthropic_messages so the call routes through dispatch."
"litellm.llms.anthropic.pass_through.messages.handler.anthropic_messages_handler".msg = "Import litellm.messages.anthropic_messages_handler so the call routes through dispatch."
"litellm.main.completion".msg = "Import litellm.completion so the call routes through dispatch."
"litellm.main.acompletion".msg = "Import litellm.acompletion so the call routes through dispatch."

View file

@ -41,7 +41,7 @@
- {id: quota_management.budget.spend_counter.reseed_matches_db, module: quota_management, tier: P2, behavior: budget, variant: spend_counter, assertions: [reseed_matches_db], exercised_on: [chat_completions], source: "proxy/spend_tracking/budget_reservation.py", rationale: "Concurrent cold-counter reseeds keep the enforcement counter equal to DB spend (#26829)"}
- {id: quota_management.spend_tracking.chat_completions.logs_cost, module: quota_management, tier: P0, behavior: spend_tracking, variant: chat_completions, assertions: [logs_cost], exercised_on: [chat_completions], source: "proxy/spend_tracking/spend_tracking_utils.py", rationale: "A paid chat call writes a nonzero spend row"}
- {id: quota_management.spend_tracking.stream.logs_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: stream, assertions: [logs_cost], exercised_on: [chat_completions], source: "proxy/spend_tracking/spend_tracking_utils.py", rationale: "Streaming responses aggregate token counts into a spend row"}
- {id: quota_management.spend_tracking.messages_bridge.logs_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: messages_bridge, assertions: [logs_cost], exercised_on: [messages], source: "llms/anthropic/experimental_pass_through/responses_adapters/handler.py", rationale: "A streaming /v1/messages request served by an openai-provider model is bridged through the anthropic-messages -> Responses adapter and must aggregate the consumed SSE stream into one spend row with nonzero cost and token counts, attributed to custom_llm_provider openai under call_type anthropic_messages"}
- {id: quota_management.spend_tracking.messages_bridge.logs_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: messages_bridge, assertions: [logs_cost], exercised_on: [messages], source: "llms/anthropic/pass_through/responses_adapters/handler.py", rationale: "A streaming /v1/messages request served by an openai-provider model is bridged through the anthropic-messages -> Responses adapter and must aggregate the consumed SSE stream into one spend row with nonzero cost and token counts, attributed to custom_llm_provider openai under call_type anthropic_messages"}
- {id: quota_management.spend_tracking.embeddings.logs_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: embeddings, assertions: [logs_cost], exercised_on: [embeddings], source: "proxy/spend_tracking/spend_tracking_utils.py", rationale: "Embedding calls write nonzero spend rows"}
- {id: quota_management.spend_tracking.cache_hit.zero_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: cache_hit, assertions: [zero_cost], exercised_on: [chat_completions], source: "proxy/spend_tracking/spend_tracking_utils.py", rationale: "A response-cache hit logs at zero cost with the cache-hit marker"}
- {id: quota_management.spend_tracking.key_rollup.matches_sum_of_logs, module: quota_management, tier: P1, behavior: spend_tracking, variant: key_rollup, assertions: [matches_sum_of_logs], exercised_on: [chat_completions], source: "proxy/db/db_spend_update_writer.py", rationale: "A key's rolled-up spend equals the sum of its log rows"}
@ -59,7 +59,7 @@
- {id: quota_management.spend_tracking.cache_write.bills_cache_creation_rate, module: quota_management, tier: P1, behavior: spend_tracking, variant: cache_write, assertions: [bills_cache_creation_rate], exercised_on: [chat_completions], source: "litellm_core_utils/llm_cost_calc/utils.py", rationale: "OpenAI cache-write tokens land on the spend row as cache-creation tokens billed at the cache-creation rate, not silently at the input rate (#34046)"}
- {id: quota_management.spend_tracking.cost_breakdown.reports_component_costs, module: quota_management, tier: P1, behavior: spend_tracking, variant: cost_breakdown, assertions: [reports_component_costs], exercised_on: [chat_completions], source: "proxy/spend_tracking/spend_tracking_utils.py", rationale: "The spend row's metadata.cost_breakdown itemizes cache-read, cache-creation, output, and reasoning costs at the deployment's own rates and they sum to the row's spend (#31686)"}
- {id: quota_management.spend_tracking.stream_cache_read.bills_cache_read_rate, module: quota_management, tier: P1, behavior: spend_tracking, variant: stream_cache_read, assertions: [bills_cache_read_rate], exercised_on: [chat_completions], source: "litellm_core_utils/streaming_chunk_builder_utils.py", rationale: "A streamed call's reassembled usage keeps the cached-token detail so cache reads bill at the cache-read discount, not full input price (#34812)"}
- {id: quota_management.spend_tracking.messages_bridge.keeps_cache_tokens, module: quota_management, tier: P1, behavior: spend_tracking, variant: messages_bridge, assertions: [keeps_cache_tokens], exercised_on: [messages], source: "llms/anthropic/experimental_pass_through/responses_adapters/handler.py", rationale: "A /v1/messages request served by a Responses-only OpenAI model keeps its cache-read tokens and their discounted billing across the bridge (#34957)"}
- {id: quota_management.spend_tracking.messages_bridge.keeps_cache_tokens, module: quota_management, tier: P1, behavior: spend_tracking, variant: messages_bridge, assertions: [keeps_cache_tokens], exercised_on: [messages], source: "llms/anthropic/pass_through/responses_adapters/handler.py", rationale: "A /v1/messages request served by a Responses-only OpenAI model keeps its cache-read tokens and their discounted billing across the bridge (#34957)"}
- {id: quota_management.spend_tracking.service_tier.bills_tier_rates, module: quota_management, tier: P1, behavior: spend_tracking, variant: service_tier, assertions: [bills_tier_rates], exercised_on: [chat_completions], source: "cost_calculator.py", rationale: "A priority service_tier call bills input, output, and reasoning at the deployment's *_priority rates and records the tier on the row (#35923, #35925)"}
- {id: quota_management.spend_tracking.cost_headers.additive_components, module: quota_management, tier: P1, behavior: spend_tracking, variant: cost_headers, assertions: [additive_components], exercised_on: [chat_completions], source: "proxy/common_request_processing.py", rationale: "The x-litellm-response-cost-* component headers sum to the total, input covers only fresh tokens, and reasoning stays a subset of output (#36965)"}
- {id: quota_management.spend_tracking.passthrough_stream.injects_usage_cost, module: quota_management, tier: P1, behavior: spend_tracking, variant: passthrough_stream, assertions: [injects_usage_cost], exercised_on: [openai_passthrough], source: "proxy/pass_through_endpoints/streaming_handler.py", rationale: "With include_cost_in_streaming_usage on, the /openai passthrough's final streaming usage frame carries the proxy-computed cost (#36503). Uncovered: the flag is only settable in litellm_settings, and the shared e2e stack does not turn it on yet"}

View file

@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, MagicMock
import litellm
import pytest
from dotenv import load_dotenv
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)

View file

@ -9,7 +9,7 @@ from unittest.mock import AsyncMock, MagicMock
import litellm
import pytest
from dotenv import load_dotenv
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)

View file

@ -6,7 +6,7 @@ from unittest.mock import patch
import pytest
import litellm
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
CLEARED_TOOL_RESULT_PLACEHOLDER,
)
from litellm.types.utils import (

View file

@ -993,7 +993,7 @@ async def test_pre_request_hook_modifies_request_body():
# Patch the anthropic_messages_handler function (called after hooks)
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.handler.anthropic_messages_handler",
"litellm.llms.anthropic.pass_through.messages.handler.anthropic_messages_handler",
side_effect=mock_anthropic_messages_handler,
), patch( # test-quality-ok: the hook imports this process-global router at call time; no injection seam exists to register search_tools
"litellm.proxy.proxy_server.llm_router",

View file

@ -2650,7 +2650,7 @@ async def test_retrieved_content_protected_when_mcp_tool_name_is_truncated(guard
the OpenAI-translated view the guardrail scans, dropping the suffix. The call
id read from the request's own Anthropic tool_use (never truncated) still
pairs the retrieved row so it is held back."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
truncate_tool_name,
)

View file

@ -4089,7 +4089,7 @@ async def test_spend_log_request_id_is_the_message_id_a_bridged_streaming_caller
adapter mints itself, and it is the only request id that call ever shows the caller, so
GET /spend/logs?request_id=msg_... has to land on the row."""
from litellm.litellm_core_utils.litellm_logging import Logging
from litellm.llms.anthropic.experimental_pass_through.responses_adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.responses_adapters.streaming_iterator import (
AnthropicResponsesStreamWrapper,
)
from litellm.types.llms.openai import (

View file

@ -13,10 +13,10 @@ import litellm
from litellm.caching.dual_cache import DualCache
from litellm.types.caching import RedisPipelineIncrementOperation
from litellm.constants import STREAM_SSE_KEEPALIVE_PING_BYTES
from litellm.llms.anthropic.experimental_pass_through.messages.agentic_streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.agentic_streaming_iterator import (
AgenticAnthropicStreamingIterator,
)
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
AnthropicMessagesStreamingResponse,
)
from litellm.proxy._types import (

View file

@ -23,7 +23,7 @@ from litellm.exceptions import GuardrailRaisedException
from litellm.integrations.custom_guardrail import CustomGuardrail
from litellm.integrations.custom_logger import CustomLogger
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.streaming_iterator import (
BaseAnthropicMessagesStreamingIterator,
)
from litellm.proxy._types import UserAPIKeyAuth

View file

@ -25,7 +25,7 @@ from litellm.integrations.websearch_interception.handler import (
)
from litellm.integrations.websearch_interception.tools import get_litellm_web_search_tool
from litellm.litellm_core_utils.agentic_loop_settings import DEFAULT_MAX_AGENTIC_LOOPS
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.base_llm.search.transformation import SearchResponse, SearchResult

View file

@ -229,7 +229,7 @@ class TestShortCircuitEntryPoint:
@pytest.mark.asyncio
async def test_returns_none_when_no_callbacks(self):
"""No callbacks configured → returns None"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)
@ -246,7 +246,7 @@ class TestShortCircuitEntryPoint:
@pytest.mark.asyncio
async def test_returns_dict_when_not_streaming(self):
"""Non-streaming short-circuit → returns dict"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)
@ -271,10 +271,10 @@ class TestShortCircuitEntryPoint:
@pytest.mark.asyncio
async def test_returns_stream_iterator_when_streaming(self):
"""Streaming short-circuit → returns FakeAnthropicMessagesStreamIterator"""
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)
@ -313,7 +313,7 @@ class TestShortCircuitEntryPoint:
"""Non-WebSearchInterceptionLogger callbacks are ignored"""
from unittest.mock import MagicMock
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)
@ -336,10 +336,10 @@ class TestShortCircuitEntryPoint:
loop. The short-circuit must use the ORIGINAL stream value so streaming
callers get SSE events instead of a plain dict.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)
@ -369,7 +369,7 @@ class TestShortCircuitEntryPoint:
still fire the short-circuit when the caller propagates the derived
provider.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
_try_websearch_short_circuit,
)

View file

@ -13,7 +13,7 @@ import pytest
from litellm.integrations.custom_logger import CustomLogger
from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.types.integrations.custom_logger import AgenticLoopPlan

View file

@ -19,7 +19,7 @@ from litellm.constants import (
)
from litellm.litellm_core_utils.prompt_templates.common_utils import encrypted_reasoning_signature
from litellm.llms.anthropic.chat.transformation import AnthropicConfig
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.azure_ai.anthropic.transformation import AzureAnthropicConfig
@ -5783,7 +5783,7 @@ def test_translate_system_message_strips_billing_header_for_bedrock_invoke():
[
("litellm.llms.anthropic.chat.transformation", "AnthropicConfig", False),
(
"litellm.llms.anthropic.experimental_pass_through.messages.transformation",
"litellm.llms.anthropic.pass_through.messages.transformation",
"AnthropicMessagesConfig",
False,
),

View file

@ -68,7 +68,7 @@ def _make_advisor_tool_use_response(
def test_can_handle_edge_cases():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -96,7 +96,7 @@ async def test_anthropic_native_interceptor_skipped():
For provider=anthropic, can_handle() must return False.
The interceptor must never call handle().
"""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -114,7 +114,7 @@ async def test_anthropic_native_interceptor_skipped():
@pytest.mark.asyncio
async def test_loop_no_advisor_call():
"""Executor returns text on first try — no advisor call, loop exits immediately."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
_call_messages_handler,
)
@ -123,7 +123,7 @@ async def test_loop_no_advisor_call():
executor_response = _make_text_response(final_text)
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
new_callable=AsyncMock,
return_value=executor_response,
) as mock_call:
@ -156,7 +156,7 @@ async def test_loop_one_advisor_call():
Executor calls advisor once → advisor responds → executor produces final text.
Total calls: 3 (executor, advisor, executor-final).
"""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -184,7 +184,7 @@ async def test_loop_one_advisor_call():
return final_resp # executor: final answer
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -218,7 +218,7 @@ async def test_loop_one_advisor_call():
@pytest.mark.asyncio
async def test_loop_max_uses_raises():
"""Loop exceeding max_uses must raise AdvisorMaxIterationsError."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorMaxIterationsError,
AdvisorOrchestrationHandler,
)
@ -239,7 +239,7 @@ async def test_loop_max_uses_raises():
return advisor_tool_use_resp
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -262,17 +262,17 @@ async def test_loop_max_uses_raises():
@pytest.mark.asyncio
async def test_loop_streaming_wraps_response():
"""stream=True: final response must be wrapped in FakeAnthropicMessagesStreamIterator."""
from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
from litellm.llms.anthropic.pass_through.messages.fake_stream_iterator import (
FakeAnthropicMessagesStreamIterator,
)
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
executor_response = _make_text_response("Hello, world!")
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
new_callable=AsyncMock,
return_value=executor_response,
):
@ -308,7 +308,7 @@ async def test_prior_advisor_blocks_replaced_in_history():
History containing server_tool_use + advisor_tool_result blocks gets
collapsed to <advisor_feedback> text before forwarding to the executor.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -341,7 +341,7 @@ async def test_prior_advisor_blocks_replaced_in_history():
return _make_text_response("Here is the efficient version.")
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -383,7 +383,7 @@ async def test_advisor_tool_translated_for_executor():
"""
The executor must receive a regular tool definition (not advisor_20260301 type).
"""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -395,7 +395,7 @@ async def test_advisor_tool_translated_for_executor():
return _make_text_response("Done.")
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -425,7 +425,7 @@ async def test_advisor_tool_translated_for_executor():
@pytest.mark.asyncio
async def test_max_uses_zero_raises_on_first_advisor_call():
"""max_uses=0 must cause AdvisorMaxIterationsError on the first advisor call."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorMaxIterationsError,
AdvisorOrchestrationHandler,
)
@ -437,7 +437,7 @@ async def test_max_uses_zero_raises_on_first_advisor_call():
return advisor_tool_use_resp # executor always tries to call advisor
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -460,7 +460,7 @@ async def test_max_uses_zero_raises_on_first_advisor_call():
@pytest.mark.asyncio
async def test_missing_advisor_model_raises_value_error():
"""handle() must raise ValueError when the advisor tool has no model field."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -487,7 +487,7 @@ async def test_missing_advisor_model_raises_value_error():
async def test_max_uses_none_falls_back_to_default():
"""When max_uses is absent, the handler uses ADVISOR_MAX_USES from constants."""
import litellm.constants as _c
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorMaxIterationsError,
AdvisorOrchestrationHandler,
)
@ -501,7 +501,7 @@ async def test_max_uses_none_falls_back_to_default():
return advisor_tool_use_resp
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -535,7 +535,7 @@ ADVISOR_TOOL_WITH_CREDS = {
async def _run_advisor_and_capture_subcall_kwargs():
"""Run one advisor turn and return the kwargs of the advisor sub-call."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -560,11 +560,11 @@ async def _run_advisor_and_capture_subcall_kwargs():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor.validate_url",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor.validate_url",
),
):
h = AdvisorOrchestrationHandler()
@ -584,7 +584,7 @@ async def test_advisor_creds_dropped_when_proxy_opt_in_disabled():
"""On the proxy without opt-in, the caller's advisor api_base/api_key must
NOT reach the sub-call (would redirect it / leak the server key)."""
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=False,
):
captured = await _run_advisor_and_capture_subcall_kwargs()
@ -596,7 +596,7 @@ async def test_advisor_creds_dropped_when_proxy_opt_in_disabled():
async def test_advisor_creds_honored_when_proxy_opt_in_enabled():
"""With the admin opt-in, the documented clientside routing still works."""
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
):
captured = await _run_advisor_and_capture_subcall_kwargs()
@ -629,7 +629,7 @@ def test_allow_client_side_advisor_credentials_reads_proxy_flag():
"""The gate mirrors the proxy's allow_client_side_credentials opt-in."""
import sys
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_allow_client_side_advisor_credentials,
)
@ -653,7 +653,7 @@ def test_allow_client_side_advisor_credentials_defaults_true_outside_proxy():
import builtins
import sys
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_allow_client_side_advisor_credentials,
)
@ -677,7 +677,7 @@ def test_advisor_gate_propagates_non_import_errors():
returning True."""
import sys
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors import (
from litellm.llms.anthropic.pass_through.messages.interceptors import (
advisor,
)
@ -744,12 +744,12 @@ async def test_advisor_uses_tool_credentials_when_clientside_enabled():
def test_resolve_advisor_credentials_returns_none_when_gate_closed():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=False,
):
result = _resolve_advisor_credentials(ADVISOR_TOOL_WITH_CREDS)
@ -757,18 +757,18 @@ def test_resolve_advisor_credentials_returns_none_when_gate_closed():
def test_resolve_advisor_credentials_allows_api_key_without_api_base():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
tool = {**ADVISOR_TOOL, "api_key": "sk-other"}
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor.validate_url",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor.validate_url",
side_effect=AssertionError("validate_url must not run without an api_base"),
),
):
@ -777,13 +777,13 @@ def test_resolve_advisor_credentials_allows_api_key_without_api_base():
def test_resolve_advisor_credentials_rejects_api_base_without_api_key():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
tool = {**ADVISOR_TOOL, "api_base": "https://other.example"}
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
):
with pytest.raises(ValueError, match="api_base"):
@ -791,17 +791,17 @@ def test_resolve_advisor_credentials_rejects_api_base_without_api_key():
def test_resolve_advisor_credentials_validates_api_base_before_use():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor.validate_url"
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor.validate_url"
) as mock_validate,
):
result = _resolve_advisor_credentials(ADVISOR_TOOL_WITH_CREDS)
@ -811,17 +811,17 @@ def test_resolve_advisor_credentials_validates_api_base_before_use():
def test_resolve_advisor_credentials_propagates_ssrf_error():
from litellm.litellm_core_utils.url_utils import SSRFError
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor.validate_url",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor.validate_url",
side_effect=SSRFError("URL targets a blocked address"),
),
):
@ -832,18 +832,18 @@ def test_resolve_advisor_credentials_propagates_ssrf_error():
def test_resolve_advisor_credentials_skips_validation_when_url_validation_disabled():
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
),
patch.object(litellm, "user_url_validation", False),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor.validate_url",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor.validate_url",
side_effect=AssertionError("validate_url must not run when user_url_validation is disabled"),
),
):
@ -855,7 +855,7 @@ def test_resolve_advisor_credentials_blocks_real_cloud_metadata_address():
"""End-to-end (no mocked validate_url): a caller can't redirect the
advisor sub-call to the cloud-metadata address even with an api_key."""
from litellm.litellm_core_utils.url_utils import SSRFError
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
@ -865,7 +865,7 @@ def test_resolve_advisor_credentials_blocks_real_cloud_metadata_address():
"api_base": "https://169.254.169.254/latest/meta-data/",
}
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
):
with pytest.raises(SSRFError):
@ -873,13 +873,13 @@ def test_resolve_advisor_credentials_blocks_real_cloud_metadata_address():
def test_resolve_advisor_credentials_rejects_non_https_api_base():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
tool = {**ADVISOR_TOOL, "api_key": "sk-other", "api_base": "http://8.8.8.8"}
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
):
with pytest.raises(ValueError, match="https"):
@ -889,14 +889,14 @@ def test_resolve_advisor_credentials_rejects_non_https_api_base():
def test_resolve_advisor_credentials_rejects_api_base_when_ssl_verify_disabled():
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
tool = {**ADVISOR_TOOL, "api_key": "sk-other", "api_base": "https://8.8.8.8"}
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
),
patch.object(litellm, "ssl_verify", False),
@ -908,13 +908,13 @@ def test_resolve_advisor_credentials_rejects_api_base_when_ssl_verify_disabled()
def test_resolve_advisor_credentials_allows_real_public_ip_address():
"""End-to-end (no mocked validate_url): a globally-routable literal IP
api_base is honored when paired with an api_key."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
_resolve_advisor_credentials,
)
tool = {**ADVISOR_TOOL, "api_key": "sk-other", "api_base": "https://8.8.8.8"}
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._allow_client_side_advisor_credentials",
return_value=True,
):
result = _resolve_advisor_credentials(tool)
@ -933,7 +933,7 @@ async def test_advisor_sub_call_failure_is_tagged():
"""When the advisor sub-call raises, the exception that propagates out of
handle() must be tagged as an advisor orchestration failure."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
from litellm.router_utils.cooldown_handlers import is_advisor_orchestration_failure
@ -952,7 +952,7 @@ async def test_advisor_sub_call_failure_is_tagged():
)
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -975,7 +975,7 @@ async def test_advisor_max_iterations_failure_is_tagged():
"""When the orchestration loop exceeds max_uses (the executor keeps calling
the advisor), the AdvisorMaxIterationsError must be tagged so the healthy
executor deployment is not cooled down."""
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorMaxIterationsError,
AdvisorOrchestrationHandler,
)
@ -991,7 +991,7 @@ async def test_advisor_max_iterations_failure_is_tagged():
return _make_advisor_tool_use_response()
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -1013,7 +1013,7 @@ async def test_executor_failure_is_not_tagged():
"""A failure of the executor call (not advisor orchestration) must NOT be
tagged — the selected deployment genuinely failed and should cool down."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
from litellm.router_utils.cooldown_handlers import is_advisor_orchestration_failure
@ -1026,7 +1026,7 @@ async def test_executor_failure_is_not_tagged():
)
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()
@ -1082,7 +1082,7 @@ def _router_with_advisor_deployment(
@pytest.mark.asyncio
async def test_advisor_sub_call_routes_through_proxy_router():
import litellm.proxy.proxy_server as proxy_server
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -1105,7 +1105,7 @@ async def test_advisor_sub_call_routes_through_proxy_router():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
),
patch.object(proxy_server, "llm_router", router),
@ -1143,7 +1143,7 @@ async def test_advisor_sub_call_routes_through_proxy_router():
async def test_advisor_sub_call_routes_through_router_for_alias_and_wildcard(router_kwargs, advisor_model):
"""Alias and wildcard advisor models resolve through the router like exact model_list matches."""
import litellm.proxy.proxy_server as proxy_server
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -1166,7 +1166,7 @@ async def test_advisor_sub_call_routes_through_router_for_alias_and_wildcard(rou
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
),
patch.object(proxy_server, "llm_router", router),
@ -1192,7 +1192,7 @@ async def test_advisor_sub_call_routes_through_router_for_alias_and_wildcard(rou
async def test_advisor_sub_call_bypasses_router_for_unconfigured_model():
"""An advisor model the router doesn't know about keeps the SDK-level path."""
import litellm.proxy.proxy_server as proxy_server
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -1217,7 +1217,7 @@ async def test_advisor_sub_call_bypasses_router_for_unconfigured_model():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
),
patch.object(proxy_server, "llm_router", router),
@ -1241,7 +1241,7 @@ async def test_advisor_sub_call_client_override_bypasses_router():
"""A caller-supplied api_key/api_base override must not be re-routed."""
import litellm
import litellm.proxy.proxy_server as proxy_server
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -1272,7 +1272,7 @@ async def test_advisor_sub_call_client_override_bypasses_router():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
),
patch.object(proxy_server, "llm_router", router),
@ -1307,7 +1307,7 @@ async def test_advisor_sub_call_client_override_bypasses_router():
@pytest.mark.asyncio
async def test_advisor_context_excludes_in_sequence_system_rows():
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorOrchestrationHandler,
)
@ -1327,7 +1327,7 @@ async def test_advisor_context_excludes_in_sequence_system_rows():
return _make_text_response("Final answer.")
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_call,
):
h = AdvisorOrchestrationHandler()

View file

@ -16,14 +16,14 @@ from litellm.litellm_core_utils.prompt_templates.factory import (
THOUGHT_SIGNATURE_SEPARATOR,
_bedrock_converse_messages_pt,
)
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
OPENAI_MAX_TOOL_NAME_LENGTH,
AnthropicAdapter,
LiteLLMAnthropicMessagesAdapter,
create_tool_name_mapping,
truncate_tool_name,
)
from litellm.llms.anthropic.experimental_pass_through.messages.mid_conversation_system import (
from litellm.llms.anthropic.pass_through.messages.mid_conversation_system import (
CONVERTED_SYSTEM_NOTE,
)
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
@ -3944,7 +3944,7 @@ class TestAnthropicStreamWrapperToolArgs:
return [text_chunk, tool_chunk, finish_chunk]
def _make_stream_wrapper(self, chunks):
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
@ -4059,7 +4059,7 @@ def _make_simple_openai_response(
def test_translate_openai_response_to_anthropic_with_polyfill_compaction_block():
"""compaction_block from PolyfillResult must be prepended to content at index 0."""
from litellm.llms.anthropic.experimental_pass_through.context_management.result import (
from litellm.llms.anthropic.pass_through.context_management.result import (
PolyfillResult,
)
@ -4092,7 +4092,7 @@ def test_translate_openai_response_to_anthropic_with_polyfill_compaction_block()
def test_translate_openai_response_to_anthropic_with_polyfill_iterations_usage():
"""iterations_usage from PolyfillResult must produce usage['iterations'] with a message entry."""
from litellm.llms.anthropic.experimental_pass_through.context_management.result import (
from litellm.llms.anthropic.pass_through.context_management.result import (
PolyfillResult,
)
@ -4147,7 +4147,7 @@ def test_translate_openai_response_to_anthropic_no_polyfill_no_change():
def test_translate_openai_response_to_anthropic_with_polyfill_both_compaction_and_iterations():
"""Full summary path: compaction_block and iterations_usage both present simultaneously."""
from litellm.llms.anthropic.experimental_pass_through.context_management.result import (
from litellm.llms.anthropic.pass_through.context_management.result import (
PolyfillResult,
)

View file

@ -38,7 +38,7 @@ sys.path.insert(
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../../.."))
)
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
ANTHROPIC_ONLY_REQUEST_KEYS,
LiteLLMMessagesToCompletionTransformationHandler,
)

View file

@ -6,7 +6,7 @@ import pytest
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../../..")))
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)

View file

@ -10,7 +10,7 @@ from typing import Final
import pytest
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)

View file

@ -14,7 +14,7 @@ import json
from types import SimpleNamespace
from typing import AsyncIterator
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
_CombinedChunkSplitter,
)

View file

@ -6,7 +6,7 @@ from unittest.mock import MagicMock
import pytest
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
from litellm.types.utils import Delta, StreamingChoices, Usage

View file

@ -12,7 +12,7 @@ import asyncio
import json
from typing import Any, AsyncIterator, Dict, List, Optional
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
from litellm.types.utils import Delta, ModelResponseStream, StreamingChoices, Usage

View file

@ -27,7 +27,7 @@ from unittest.mock import MagicMock
import pytest
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
from litellm.types.utils import (

View file

@ -12,10 +12,10 @@ import pytest
import respx
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)

View file

@ -25,7 +25,7 @@ import pytest
sys.path.insert(0, os.path.abspath("../../../../.."))
from litellm.exceptions import MidStreamFallbackError
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
_mid_stream_error_sse_event,
)

View file

@ -12,7 +12,7 @@ bridge emitted ``stop_reason: "end_turn"`` and Anthropic tool-runners
import pytest
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
from litellm.llms.ollama.chat.transformation import (

View file

@ -16,7 +16,7 @@ from unittest.mock import MagicMock
import pytest
from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import (
from litellm.llms.anthropic.pass_through.adapters.streaming_iterator import (
AnthropicStreamWrapper,
)
from litellm.types.utils import (

View file

@ -4,10 +4,10 @@ Unit tests for the in-gateway `clear_tool_uses_20250919` polyfill editor.
from copy import deepcopy
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
CLEARED_TOOL_RESULT_PLACEHOLDER,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.clear_tool_uses import (
from litellm.llms.anthropic.pass_through.context_management.editors.clear_tool_uses import (
apply_clear_tool_uses_20250919,
)

View file

@ -21,11 +21,11 @@ import pytest
from fastapi import HTTPException
import litellm
from litellm.llms.anthropic.experimental_pass_through.context_management import (
from litellm.llms.anthropic.pass_through.context_management import (
AnthropicContextManagementError,
apply_context_management,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_augment_system_with_summary,
_extract_summary_text,
_select_last_user_question,
@ -34,7 +34,7 @@ from litellm.llms.anthropic.experimental_pass_through.context_management.editors
apply_client_compaction_block_history,
apply_compact_20260112,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.result import (
from litellm.llms.anthropic.pass_through.context_management.result import (
PolyfillResult,
)
from litellm.proxy.hooks.parallel_request_limiter_v3 import RateLimitUnverifiableError
@ -315,7 +315,7 @@ async def test_trigger_below_minimum_raises():
async def test_trigger_at_minimum_does_not_raise():
"""Exactly 50 000 is allowed — only strictly less than 50k is rejected."""
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_compact_20260112(
@ -340,7 +340,7 @@ async def test_trigger_at_minimum_does_not_raise():
async def test_opt_in_gating_no_summary_model_configured():
messages = _simple_messages()
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_compact_20260112(
@ -367,7 +367,7 @@ async def test_opt_in_gating_no_summary_model_keeps_post_compaction_tail():
messages = _messages_with_compaction("prior summary text")
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_compact_20260112(
@ -451,7 +451,7 @@ async def test_slice_only_path_with_existing_compaction_block():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=500), # well under threshold
@ -488,7 +488,7 @@ async def test_slice_only_no_compaction_block_under_threshold():
messages = _simple_messages()
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=500),
@ -521,12 +521,12 @@ async def test_full_summary_path():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000), # over 150k threshold
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
return_value=mock_response,
),
@ -575,7 +575,7 @@ async def test_full_summary_path_uses_router_when_available():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="my-summary-model",
),
patch("litellm.token_counter", return_value=200_000),
@ -611,12 +611,12 @@ async def test_litellm_metadata_propagated_to_summary_call():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
return_value=mock_response,
) as mock_call,
@ -648,12 +648,12 @@ async def test_summary_call_failed():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
side_effect=RuntimeError("network error"),
),
@ -684,12 +684,12 @@ async def test_summary_extraction_failed_no_tags():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
return_value=mock_response,
),
@ -716,7 +716,7 @@ async def test_pause_after_compaction_ignored_warning():
"""pause_after_compaction: true → warning recorded, request proceeds normally."""
messages = _simple_messages()
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_compact_20260112(
@ -739,7 +739,7 @@ async def test_pause_after_compaction_ignored_warning():
async def test_unsupported_trigger_type_falls_back_to_default():
messages = _simple_messages()
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_compact_20260112(
@ -777,12 +777,12 @@ async def test_custom_instructions_used_verbatim():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -822,12 +822,12 @@ async def test_default_instructions_appended_with_no_tool_suffix_when_no_tools()
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -858,12 +858,12 @@ async def test_default_instructions_with_tools_appends_no_tool_suffix():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -892,12 +892,12 @@ async def test_system_prompt_forwarded_to_summary_call_as_string():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -932,12 +932,12 @@ async def test_system_prompt_forwarded_to_summary_call_as_content_blocks():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -975,12 +975,12 @@ async def test_summary_call_carries_prior_compaction_summary_into_system():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -1012,12 +1012,12 @@ async def test_summary_call_omits_system_message_when_system_is_none():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -1053,12 +1053,12 @@ async def test_summary_call_does_not_emit_consecutive_user_turns():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
side_effect=_fake_call_summary_model,
),
):
@ -1085,10 +1085,10 @@ async def test_summary_call_sends_default_max_tokens():
(which require it) don't reject the request and silently fall back to
``summary_call_failed``.
"""
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_SUMMARY_MAX_TOKENS,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -1112,7 +1112,7 @@ async def test_summary_call_sends_default_max_tokens():
async def test_summary_call_honors_max_tokens_override():
"""Operators can override the default summary ``max_tokens`` via
``general_settings.context_management_summary_max_tokens``."""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_read_summary_max_tokens_setting,
)
@ -1129,7 +1129,7 @@ async def test_summary_call_honors_max_tokens_override():
):
assert _read_summary_max_tokens_setting() == 8192
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -1148,10 +1148,10 @@ def test_summary_max_tokens_setting_falls_back_for_invalid_values():
"""Invalid override values (non-int, non-positive, missing) fall back to
the compiled default so a typo in ``general_settings`` doesn't break the
summary call."""
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_SUMMARY_MAX_TOKENS,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_read_summary_max_tokens_setting,
)
@ -1168,10 +1168,10 @@ def test_summary_max_tokens_setting_falls_back_for_invalid_values():
async def test_summary_call_sends_default_timeout():
"""``timeout`` is set on the summary call so a slow or unresponsive summary
model cannot hang the parent ``/v1/messages`` request indefinitely."""
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_SUMMARY_TIMEOUT_SECONDS,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -1240,12 +1240,12 @@ async def test_summary_model_denied_when_key_not_in_allowlist():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
):
@ -1272,12 +1272,12 @@ async def test_summary_model_denied_when_team_not_in_allowlist():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
):
@ -1303,12 +1303,12 @@ async def test_summary_model_allowed_when_in_key_allowlist():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
):
@ -1336,12 +1336,12 @@ async def test_summary_model_allowed_when_no_user_api_key_auth():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
):
@ -1373,12 +1373,12 @@ async def test_summary_model_denied_when_user_scope_excludes_it():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch(
@ -1423,12 +1423,12 @@ async def test_summary_model_denied_when_project_scope_excludes_it():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch(
@ -1475,12 +1475,12 @@ async def test_summary_model_denied_when_team_member_scope_excludes_it():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch(
@ -1528,12 +1528,12 @@ async def test_summary_model_denied_when_team_membership_read_hits_a_db_outage()
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch(
@ -1582,12 +1582,12 @@ async def test_summary_model_denied_when_key_over_model_budget():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.model_max_budget_limiter", limiter),
@ -1635,12 +1635,12 @@ async def test_summary_model_denied_when_user_over_model_budget():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.model_max_budget_limiter", limiter),
@ -1702,12 +1702,12 @@ async def test_summary_model_denied_when_end_user_over_model_budget():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.model_max_budget_limiter", limiter),
@ -1743,12 +1743,12 @@ async def test_summary_model_allowed_when_within_model_budget():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.model_max_budget_limiter", limiter),
@ -1834,12 +1834,12 @@ async def test_summary_model_rate_limit_check_errors(limiter_error, summary_call
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.proxy_logging_obj", proxy_logging),
@ -1876,12 +1876,12 @@ async def test_summary_model_denied_when_over_rate_limit():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.proxy_logging_obj", proxy_logging),
@ -1912,12 +1912,12 @@ async def test_summary_model_allowed_when_within_rate_limit():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.proxy_logging_obj", proxy_logging),
@ -1960,12 +1960,12 @@ async def test_summary_model_allowed_while_the_caller_holds_the_keys_only_parall
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.proxy_logging_obj", _proxy_logging_like_the_live_proxy(limiter)),
@ -1996,12 +1996,12 @@ async def test_summary_model_rate_limit_skipped_for_legacy_limiter():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch("litellm.proxy.proxy_server.proxy_logging_obj", proxy_logging),
@ -2050,12 +2050,12 @@ async def test_summary_model_denied_when_team_over_model_budget():
with (
patch( # test-quality-ok: apply_compact_20260112 reads the summary model setting as a module global, no seam
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000), # test-quality-ok: forces the over-threshold branch
patch( # test-quality-ok: the summary call is the observable that must NOT happen when the team is over budget
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
patch( # test-quality-ok: the limiter is a proxy_server module global the editor imports, no injection seam
@ -2108,12 +2108,12 @@ async def test_scoped_budget_metadata_propagated_to_summary_call():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
return_value=mock_response,
) as mock_call,
@ -2136,7 +2136,7 @@ async def test_scoped_budget_metadata_propagated_to_summary_call():
async def test_summary_call_passes_end_user_id_as_top_level_user():
"""``_call_summary_model`` forwards the propagated end-user id as the top-level
``user`` kwarg that legacy limiter / prometheus end-user tracking reads."""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -2159,7 +2159,7 @@ async def test_summary_call_passes_end_user_id_as_top_level_user():
async def test_summary_call_omits_user_when_no_end_user_id():
"""No end-user id on the parent request means no ``user`` kwarg is sent."""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -2195,12 +2195,12 @@ async def test_model_budget_metadata_propagated_to_summary_call():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
new_callable=AsyncMock,
return_value=mock_response,
) as mock_call,
@ -2236,12 +2236,12 @@ async def test_summary_call_propagates_allowed_model_region():
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._call_summary_model",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._call_summary_model",
mock_call,
),
):
@ -2262,7 +2262,7 @@ async def test_summary_call_omits_allowed_model_region_when_unset():
"""Callers without a region restriction must not get an ``allowed_model_region=None``
kwarg, which would otherwise force the router to evaluate region filtering.
"""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -2285,7 +2285,7 @@ async def test_summary_call_omits_allowed_model_region_when_unset():
async def test_summary_call_forwards_allowed_model_region_when_set():
"""When the caller is region-restricted, the kwarg reaches the router."""
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_call_summary_model,
)
@ -2316,7 +2316,7 @@ async def test_dispatcher_routes_compact_edit():
"""compact_20260112 in the dispatcher resolves to opt-in gate when no model set."""
messages = _simple_messages()
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await apply_context_management(
@ -2358,7 +2358,7 @@ async def test_dispatcher_trigger_below_minimum_raises_through():
async def test_run_polyfill_skipped_when_context_management_in_additional_drop_params():
"""additional_drop_params=["context_management"] is the explicit opt-out."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
_run_polyfill_if_enabled,
)
@ -2379,13 +2379,13 @@ async def test_run_polyfill_runs_when_litellm_drop_params_true(monkeypatch):
"""drop_params must not disable the polyfill: context_management is a
LiteLLM-supported param (polyfilled where not native), and drop_params only
exists to strip genuinely unsupported params."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
_run_polyfill_if_enabled,
)
monkeypatch.setattr(litellm, "drop_params", True)
with patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value=None,
):
result = await _run_polyfill_if_enabled(
@ -2404,7 +2404,7 @@ async def test_run_polyfill_runs_when_litellm_drop_params_true(monkeypatch):
async def test_run_polyfill_skipped_when_spec_empty():
"""Empty context_management_spec must also return None (no polyfill work)."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
_run_polyfill_if_enabled,
)
@ -2473,7 +2473,7 @@ def _openai_chat_response():
async def _call_async_adapter_handler(**handler_kwargs: Any):
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -2532,7 +2532,7 @@ async def test_async_handler_additional_drop_params_strips_context_management():
def _call_sync_adapter_handler(**handler_kwargs: Any):
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -2584,7 +2584,7 @@ async def test_prepare_context_managed_request_forwards_proxy_litellm_metadata()
Anthropic-shape ``metadata`` arg (which only carries ``user_id``). Otherwise
the summary subcall lands on the router with no parent attribution, and
those tokens go unbilled to the caller's key/team."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
_prepare_context_managed_request,
)
@ -2597,7 +2597,7 @@ async def test_prepare_context_managed_request_forwards_proxy_litellm_metadata()
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact._read_summary_model_setting",
"litellm.llms.anthropic.pass_through.context_management.editors.compact._read_summary_model_setting",
return_value="claude-haiku-4-5",
),
patch("litellm.token_counter", return_value=200_000),
@ -2786,7 +2786,7 @@ def test_endpoint_runs_failure_hook_on_500_context_management_error():
def test_count_effective_tokens_counts_midturn_system_correction():
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_count_effective_tokens,
)
@ -2813,7 +2813,7 @@ def test_count_effective_tokens_counts_midturn_system_correction():
def test_build_summary_messages_keeps_midturn_system_correction_in_place():
from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import (
from litellm.llms.anthropic.pass_through.context_management.editors.compact import (
_build_summary_messages,
)
@ -2847,7 +2847,7 @@ async def test_threshold_check_counts_tokens_off_the_event_loop(monkeypatch):
warm_tokenizer,
)
from litellm.llms.anthropic.experimental_pass_through.context_management.constants import (
from litellm.llms.anthropic.pass_through.context_management.constants import (
COMPACT_SUMMARY_MODEL_SETTING_KEY,
)
from litellm.proxy.proxy_server import general_settings

View file

@ -2,7 +2,7 @@
Unit tests for the context_management polyfill dispatcher.
"""
from litellm.llms.anthropic.experimental_pass_through.context_management import (
from litellm.llms.anthropic.pass_through.context_management import (
apply_context_management,
)

View file

@ -72,7 +72,7 @@ async def test_full_dispatch_interceptor_fires_and_loop_completes():
The interceptor must fire, run the loop (1 advisor call), and return a
clean final response with no advisor tool_use blocks.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)
@ -88,7 +88,7 @@ async def test_full_dispatch_interceptor_fires_and_loop_completes():
return _text_resp("def is_prime(n): ...") # executor: final
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_handler,
):
result = await anthropic_messages(
@ -127,10 +127,10 @@ async def test_max_uses_enforced_through_full_handler():
AdvisorMaxIterationsError propagates out of anthropic_messages() when
the executor keeps calling the advisor past max_uses.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)
from litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor import (
from litellm.llms.anthropic.pass_through.messages.interceptors.advisor import (
AdvisorMaxIterationsError,
)
@ -143,7 +143,7 @@ async def test_max_uses_enforced_through_full_handler():
return _advisor_call_resp()
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_handler,
):
with pytest.raises(AdvisorMaxIterationsError):
@ -168,7 +168,7 @@ async def test_anthropic_provider_bypasses_interceptor():
With custom_llm_provider='anthropic', the interceptor must NOT fire.
The advisor_20260301 tool is forwarded as-is to the underlying handler.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)
@ -176,7 +176,7 @@ async def test_anthropic_provider_bypasses_interceptor():
# Patch the non-interceptor code path — anthropic_messages_handler
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.handler.anthropic_messages_handler",
"litellm.llms.anthropic.pass_through.messages.handler.anthropic_messages_handler",
return_value=direct_response,
) as mock_native:
result = await anthropic_messages(
@ -215,7 +215,7 @@ async def test_named_params_forwarded_into_advisor_executor_subcall():
them, e.g. Vertex AI rejecting ``clear_thinking_20251015`` context_management
edits with: ``strategy requires thinking to be enabled or adaptive``.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)
@ -246,7 +246,7 @@ async def test_named_params_forwarded_into_advisor_executor_subcall():
return _text_resp("Final answer.")
with patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_handler,
):
await anthropic_messages(
@ -298,7 +298,7 @@ async def test_pre_request_hook_override_does_not_collide_with_explicit_kwargs()
Regression for Greptile P2 on PR #27810.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages,
)
@ -339,11 +339,11 @@ async def test_pre_request_hook_override_does_not_collide_with_explicit_kwargs()
with (
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.handler._execute_pre_request_hooks",
"litellm.llms.anthropic.pass_through.messages.handler._execute_pre_request_hooks",
side_effect=fake_pre_request_hooks,
),
patch(
"litellm.llms.anthropic.experimental_pass_through.messages.interceptors.advisor._call_messages_handler",
"litellm.llms.anthropic.pass_through.messages.interceptors.advisor._call_messages_handler",
side_effect=mock_handler,
),
):

View file

@ -11,7 +11,7 @@ import pytest
from litellm.constants import STREAM_SSE_KEEPALIVE_PING_BYTES
from litellm.llms.anthropic.experimental_pass_through.messages.agentic_streaming_iterator import (
from litellm.llms.anthropic.pass_through.messages.agentic_streaming_iterator import (
SERVER_FULFILLED_TOOL_LEAK_ERROR_SSE_BYTES,
AgenticAnthropicStreamingIterator,
_handle_content_block_delta,

View file

@ -30,7 +30,7 @@ def test_anthropic_experimental_pass_through_messages_handler():
Test that api key is passed to litellm.responses for OpenAI models.
OpenAI and Azure models are routed directly to the Responses API.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -115,7 +115,7 @@ def test_anthropic_experimental_pass_through_messages_handler_dynamic_api_key_an
Test that api key, api base, and extra kwargs are forwarded to litellm.completion for Azure models.
Azure models are routed through chat/completions (not the Responses API).
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -142,7 +142,7 @@ async def test_anthropic_messages_sanitizes_empty_text_blocks_before_dispatch():
"""Regression test for #22930. The unified /v1/messages path must
strip empty text blocks before forwarding, otherwise Anthropic
returns 400 "text content blocks must be non-empty"."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
msgs = [
{
@ -180,7 +180,7 @@ async def test_anthropic_messages_sanitizes_empty_text_blocks_before_dispatch():
@pytest.mark.asyncio
async def test_anthropic_messages_sanitizes_tool_use_ids_before_dispatch():
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
msgs = [
{
@ -231,7 +231,7 @@ def test_anthropic_experimental_pass_through_messages_handler_custom_llm_provide
Provider resolution now happens exactly once, inside litellm.completion itself
(BerriAI/litellm#37716), so the handler passes the original unresolved model through.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -315,7 +315,7 @@ def test_openai_model_with_thinking_converts_to_reasoning():
OpenAI models are routed directly to the Responses API, so we verify that
litellm.responses() is called with `reasoning` properly set.
"""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -355,7 +355,7 @@ class TestThinkingParameterTransformation:
def test_claude_model_preserves_thinking_with_budget_tokens(self):
"""Test that Claude models get thinking parameter passed through with exact budget_tokens."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -370,7 +370,7 @@ class TestThinkingParameterTransformation:
def test_non_claude_model_converts_thinking_to_reasoning_effort(self):
"""Test that non-Claude models convert thinking to reasoning_effort."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -388,7 +388,7 @@ class TestThinkingParameterTransformation:
def test_translate_thinking_for_model_summary_when_enabled(self):
"""When reasoning_auto_summary is True, summary='detailed' is injected."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -406,7 +406,7 @@ class TestThinkingParameterTransformation:
def test_translate_thinking_for_model_preserves_user_summary(self):
"""User-provided summary is always preserved regardless of flag."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -423,7 +423,7 @@ class TestThinkingSummaryPreservation:
def test_thinking_summary_concise_preserved_for_openai(self):
"""User-provided summary='concise' should not be replaced with 'detailed'."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -439,7 +439,7 @@ class TestThinkingSummaryPreservation:
def test_thinking_summary_auto_preserved_for_openai(self):
"""User-provided summary='auto' should be preserved."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -456,7 +456,7 @@ class TestThinkingSummaryPreservation:
def test_summary_added_when_auto_summary_enabled(self):
"""When reasoning_auto_summary is True, summary='detailed' is added."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -481,7 +481,7 @@ class TestThinkingSummaryPreservation:
def test_no_summary_by_default_string_reasoning(self):
"""By default (reasoning_auto_summary=False), summary is not added for string reasoning_effort."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -504,7 +504,7 @@ class TestThinkingSummaryPreservation:
def test_no_summary_by_default_dict_reasoning(self):
"""By default (reasoning_auto_summary=False), summary is not injected into dict reasoning_effort."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -527,7 +527,7 @@ class TestThinkingSummaryPreservation:
def test_summary_added_when_env_var_set(self, monkeypatch):
"""When LITELLM_REASONING_AUTO_SUMMARY env var is true, summary is added."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -554,7 +554,7 @@ class TestThinkingSummaryPreservation:
def test_user_provided_summary_preserved_even_when_flag_off(self):
"""When user already set summary in dict reasoning_effort, it's preserved regardless of flag."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
@ -575,7 +575,7 @@ class TestThinkingSummaryPreservation:
def test_openai_model_with_thinking_summary_end_to_end(self):
"""End-to-end: anthropic_messages_handler should preserve thinking.summary for OpenAI models."""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -604,7 +604,7 @@ class TestThinkingSummaryPreservation:
def test_responses_adapter_preserves_summary(self):
"""translate_thinking_to_reasoning should include summary when user provides it."""
from litellm.llms.anthropic.experimental_pass_through.responses_adapters.transformation import (
from litellm.llms.anthropic.pass_through.responses_adapters.transformation import (
LiteLLMAnthropicToResponsesAPIAdapter,
)
@ -615,7 +615,7 @@ class TestThinkingSummaryPreservation:
def test_responses_adapter_no_summary_by_default(self):
"""translate_thinking_to_reasoning should not include summary by default (opt-in)."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.responses_adapters.transformation import (
from litellm.llms.anthropic.pass_through.responses_adapters.transformation import (
LiteLLMAnthropicToResponsesAPIAdapter,
)
@ -631,7 +631,7 @@ class TestThinkingSummaryPreservation:
def test_translate_thinking_for_model_preserves_summary(self):
"""translate_thinking_for_model should include summary in reasoning_effort dict when user provides it."""
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -645,7 +645,7 @@ class TestThinkingSummaryPreservation:
def test_translate_thinking_for_model_disabled_stays_plain_string_when_auto_summary_enabled(self):
"""Disabled thinking must stay a plain string even when reasoning_auto_summary is on."""
import litellm
from litellm.llms.anthropic.experimental_pass_through.adapters.transformation import (
from litellm.llms.anthropic.pass_through.adapters.transformation import (
LiteLLMAnthropicMessagesAdapter,
)
@ -684,7 +684,7 @@ def _empty_block_msgs():
def test_handler_strips_when_no_presanitized_flag():
"""Sync entry point (no async wrapper): handler must still sanitize."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
with patch.object(
handler,
@ -704,7 +704,7 @@ def test_handler_strips_when_no_presanitized_flag():
def test_handler_skips_strip_when_presanitized():
"""Async wrapper already sanitized -> handler must NOT rescan."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
with patch.object(
handler,
@ -725,7 +725,7 @@ def test_handler_skips_strip_when_presanitized():
def test_handler_flattens_replayed_unencrypted_web_search_results():
"""Synthesized search blocks replayed as history must reach the provider as text."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
captured = {}
@ -780,7 +780,7 @@ def test_handler_flattens_replayed_unencrypted_web_search_results():
def test_presanitized_flag_not_leaked_to_provider_params():
"""The private sentinel must be popped, never forwarded as a request param."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
captured = {}
@ -809,7 +809,7 @@ def test_presanitized_flag_not_leaked_to_provider_params():
@pytest.mark.asyncio
async def test_async_wrapper_sets_presanitized_and_sanitizes_once():
"""End-to-end: wrapper sanitizes (once) AND signals the handler to skip."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
captured = {}
@ -853,7 +853,7 @@ def _gate_stubs(monkeypatch):
provider config handed to the native passthrough path and ``translation_calls``
counts hits on the Anthropic->OpenAI translation handlers.
"""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
captured = {}
translation_calls = {"count": 0}
@ -883,7 +883,7 @@ def _gate_stubs(monkeypatch):
def test_gate_passthrough_when_supported_endpoints_opts_in(monkeypatch):
"""provider=openai + model_info.supported_endpoints containing /v1/messages
must route to the native passthrough config, NOT the translation handlers."""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
from litellm.llms.openai_like.messages.transformation import (
@ -909,7 +909,7 @@ def test_gate_passthrough_when_supported_endpoints_opts_in(monkeypatch):
def test_gate_translates_when_supported_endpoints_absent(monkeypatch):
"""Default behavior is unchanged: without the /v1/messages opt-in, an openai
deployment is translated (Responses API), never passed through natively."""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -931,7 +931,7 @@ def test_gate_translates_when_supported_endpoints_absent(monkeypatch):
def test_gate_passthrough_skipped_when_only_chat_completions_supported(monkeypatch):
"""A deployment that lists only /v1/chat/completions is still translated;
the opt-in is specifically the /v1/messages entry."""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -964,7 +964,7 @@ def test_gate_passthrough_forwards_cache_control_ttl_only_when_deployment_opts_i
):
"""The passthrough config strips cache_control.ttl unless the deployment sets
model_info.cache_control_ttl to exactly true."""
from litellm.llms.anthropic.experimental_pass_through.messages.handler import (
from litellm.llms.anthropic.pass_through.messages.handler import (
anthropic_messages_handler,
)
@ -1275,7 +1275,7 @@ class TestMessagesStreamingSuccessLogging:
@pytest.mark.asyncio
async def test_responses_bridge_streaming_emits_success_logging(self, capture_success_payloads):
"""The Responses bridge, which is the default for openai/ deployments."""
from litellm.llms.anthropic.experimental_pass_through.responses_adapters.handler import (
from litellm.llms.anthropic.pass_through.responses_adapters.handler import (
LiteLLMMessagesToResponsesAPIHandler,
)
@ -1316,14 +1316,14 @@ class TestMessagesStreamingSuccessLogging:
"""The chat-completions bridge, reached via
litellm.use_chat_completions_url_for_anthropic_messages. Its router lookup is
stubbed to what an SDK caller with no proxy running already resolves to."""
from litellm.llms.anthropic.experimental_pass_through.adapters.handler import (
from litellm.llms.anthropic.pass_through.adapters.handler import (
LiteLLMMessagesToCompletionTransformationHandler,
)
_bind_logging_worker_to_running_loop()
with patch(
"litellm.llms.anthropic.experimental_pass_through.adapters.handler._proxy_router_fallback",
"litellm.llms.anthropic.pass_through.adapters.handler._proxy_router_fallback",
return_value=None,
):
sse_stream = await LiteLLMMessagesToCompletionTransformationHandler.async_anthropic_messages_handler(
@ -1376,7 +1376,7 @@ async def test_anthropic_messages_maps_provider_exception_before_failure_logging
The 403 row pins the upstream status on the way through the mapper: Anthropic's
documented permission_error must reach the caller as a 403, never as the mapper's
APIConnectionError 500 fallthrough."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
capture = _FailureCapture()
monkeypatch.setattr(litellm, "callbacks", [capture])
@ -1418,7 +1418,7 @@ async def test_anthropic_messages_leaves_non_provider_failures_unmapped():
"""The mapping boundary is for provider failures only. A request rejected before
the provider call (here invalid metadata) must surface as the original exception,
not as the mapper's APIConnectionError, whose message embeds a server traceback."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
def upstream_must_not_be_called(request: httpx.Request) -> httpx.Response:
raise AssertionError("the provider must not be called for a request rejected locally")
@ -1464,7 +1464,7 @@ def _recording_client(seen_urls: list[str]) -> AsyncHTTPHandler:
@pytest.mark.asyncio
async def test_provider_messages_api_base_env_is_not_shadowed_by_the_chat_default(monkeypatch):
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
monkeypatch.delenv("DEEPSEEK_API_BASE", raising=False)
monkeypatch.setenv("DEEPSEEK_ANTHROPIC_API_BASE", "https://deepseek.internal.example/anthropic")
@ -1483,7 +1483,7 @@ async def test_provider_messages_api_base_env_is_not_shadowed_by_the_chat_defaul
@pytest.mark.asyncio
async def test_anthropic_messages_forwards_safeguards_and_unknown_beta_to_anthropic():
"""Shapes are what Claude Code 2.1.278 sends and api.anthropic.com returns, captured 2026-09-21."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
safeguards = [{"type": "dangerous_tool_use", "classifier_context": {"v": 1, "permission_mode": "auto"}}]
client_betas = "dangerous-tool-use-2026-09-03,interleaved-thinking-2025-05-14"
@ -1531,7 +1531,7 @@ async def test_anthropic_messages_forwards_safeguards_and_unknown_beta_to_anthro
@pytest.mark.asyncio
async def test_anthropic_messages_streaming_forwards_safeguards_and_keeps_safeguard_results():
"""Shapes are what Claude Code 2.1.278 sends and api.anthropic.com returns, captured 2026-09-21."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
safeguards = [{"type": "dangerous_tool_use", "classifier_context": {"v": 1, "permission_mode": "auto"}}]
tool_verdicts = {"toolu_01": {"type": "evaluated", "outcome": "not_flagged"}}
@ -1632,7 +1632,7 @@ async def test_anthropic_messages_forwards_safeguards_and_dangerous_tool_use_bet
local_beta_headers_config, client_headers
):
"""Bedrock Invoke takes betas in the body's `anthropic_beta` and 400s on `safeguards` without the beta, so the beta rides along with the field."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
safeguards, safeguard_results = _claude_code_auto_mode_request()
captured: dict[str, object] = {}
@ -1661,7 +1661,7 @@ async def test_anthropic_messages_forwards_safeguards_and_dangerous_tool_use_bet
local_beta_headers_config, client_headers
):
"""Vertex rawPredict takes the beta as the `anthropic-beta` header and 400s on `safeguards` without it, so the beta rides along with the field."""
from litellm.llms.anthropic.experimental_pass_through.messages import handler
from litellm.llms.anthropic.pass_through.messages import handler
from litellm.llms.vertex_ai.vertex_llm_base import VertexBase
safeguards, safeguard_results = _claude_code_auto_mode_request()

View file

@ -7,7 +7,7 @@ from litellm.constants import (
DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET,
)
from litellm.llms.anthropic.common_utils import AnthropicError
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.openai_like.json_loader import SimpleProviderConfig

View file

@ -1,7 +1,7 @@
from litellm.litellm_core_utils.prompt_templates.common_utils import (
encrypted_reasoning_signature,
)
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)

View file

@ -2,7 +2,7 @@ import pytest
from litellm import anthropic_beta_headers_manager
from litellm.anthropic_beta_headers_manager import update_headers_with_filtered_beta
from litellm.llms.anthropic.experimental_pass_through.messages.transformation import (
from litellm.llms.anthropic.pass_through.messages.transformation import (
AnthropicMessagesConfig,
)
from litellm.llms.openai_like.json_loader import SimpleProviderConfig

Some files were not shown because too many files have changed in this diff Show more