diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py index 4fb072a2c0f..ea77fd07b34 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/handler.py @@ -40,6 +40,18 @@ if TYPE_CHECKING: ANTHROPIC_ONLY_REQUEST_KEYS: frozenset[str] = frozenset({"output_config"}) +def _messages_have_compaction_block(messages: List[Dict]) -> bool: + """Return True when any message carries a ``compaction`` content block.""" + for msg in messages: + content = msg.get("content") + if not isinstance(content, list): + continue + for block in content: + if isinstance(block, dict) and block.get("type") == "compaction": + return True + return False + + async def _prepare_context_managed_request( *, model: str, @@ -677,17 +689,26 @@ class LiteLLMMessagesToCompletionTransformationHandler: # unaffected because it ``await``s within the original event loop. litellm_router = kwargs.pop("litellm_router", None) - polyfill_result = run_async_function( - _prepare_context_managed_request, - model=model, - messages=messages, - tools=tools, - system=system, - context_management_spec=context_management, - metadata=metadata, - drop_params=drop_params, - llm_router=litellm_router, - ) + # Skip the async bridge entirely when there is nothing for either the + # polyfill or the client-history slice-only fallback to do. The vast + # majority of sync ``litellm.messages.create()`` requests carry no + # ``context_management`` spec and no client-sent ``compaction`` block, + # and bridging through a worker-thread event loop just to discover + # there is no work is pure overhead. + if context_management is None and not _messages_have_compaction_block(messages): + polyfill_result: Optional[PolyfillResult] = None + else: + polyfill_result = run_async_function( + _prepare_context_managed_request, + model=model, + messages=messages, + tools=tools, + system=system, + context_management_spec=context_management, + metadata=metadata, + drop_params=drop_params, + llm_router=litellm_router, + ) effective_messages = ( polyfill_result.messages if polyfill_result is not None else messages diff --git a/litellm/llms/bedrock/chat/converse_transformation.py b/litellm/llms/bedrock/chat/converse_transformation.py index 31d2d74cba4..0bd2abaf4b3 100644 --- a/litellm/llms/bedrock/chat/converse_transformation.py +++ b/litellm/llms/bedrock/chat/converse_transformation.py @@ -1477,6 +1477,8 @@ class AmazonConverseConfig(BaseConfig): anthropic_beta_list: list, ) -> None: """Keep only compact_20260112 edits for Bedrock; add beta header or drop field.""" + from litellm.types.llms.anthropic import ANTHROPIC_BETA_HEADER_VALUES + cm = additional_request_params.get("context_management") if not isinstance(cm, dict): additional_request_params.pop("context_management", None) @@ -1492,8 +1494,9 @@ class AmazonConverseConfig(BaseConfig): if isinstance(e, dict) and e.get("type") == "compact_20260112" ] if compact_edits: - if "compact-2026-01-12" not in anthropic_beta_list: - anthropic_beta_list.append("compact-2026-01-12") + compact_beta = ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value + if compact_beta not in anthropic_beta_list: + anthropic_beta_list.append(compact_beta) additional_request_params["context_management"] = { **cm, "edits": compact_edits, diff --git a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py index 69b61298d33..cd2fd39904d 100644 --- a/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py +++ b/litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py @@ -38,7 +38,10 @@ from litellm.llms.bedrock.common_utils import ( normalize_tool_input_schema_types_for_bedrock_invoke, remove_custom_field_from_tools, ) -from litellm.types.llms.anthropic import ANTHROPIC_TOOL_SEARCH_BETA_HEADER +from litellm.types.llms.anthropic import ( + ANTHROPIC_BETA_HEADER_VALUES, + ANTHROPIC_TOOL_SEARCH_BETA_HEADER, +) from litellm.types.llms.bedrock import BedrockInvokeAnthropicMessagesRequest from litellm.types.llms.openai import AllMessageValues from litellm.types.router import GenericLiteLLMParams @@ -442,7 +445,7 @@ class AmazonAnthropicClaudeMessagesConfig( if isinstance(e, dict) and e.get("type") == "compact_20260112" ] if compact_edits: - beta_set.add("compact-2026-01-12") + beta_set.add(ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value) anthropic_messages_request["context_management"] = { **cm, "edits": compact_edits, diff --git a/litellm/types/llms/anthropic.py b/litellm/types/llms/anthropic.py index 2fb881cb003..a1e1a41a60e 100644 --- a/litellm/types/llms/anthropic.py +++ b/litellm/types/llms/anthropic.py @@ -537,14 +537,14 @@ class ContextManagementResponse(TypedDict, total=False): class CompactionBlock(TypedDict, total=False): """Synthesized ``compaction`` content block (compact_20260112).""" - type: Literal["compaction"] + type: Required[Literal["compaction"]] content: Optional[str] class UsageIteration(TypedDict, total=False): """One sampling iteration's token usage (compact_20260112).""" - type: Literal["compaction", "message"] + type: Required[Literal["compaction", "message"]] input_tokens: int output_tokens: int