diff --git a/litellm/types/llms/anthropic.py b/litellm/types/llms/anthropic.py index c7bb5d73d93..1d903e9907a 100644 --- a/litellm/types/llms/anthropic.py +++ b/litellm/types/llms/anthropic.py @@ -1,4 +1,4 @@ -from collections.abc import Iterable +from collections.abc import Iterable, Mapping, Sequence from enum import Enum from typing import Any, Final, Literal, TypeAlias @@ -387,7 +387,7 @@ class AnthropicMessagesRequestOptionalParams(TypedDict, total=False): output_config: AnthropicOutputConfig | None # Configuration for Claude's output behavior cache_control: dict[str, Any] | None # Automatic prompt caching reasoning_effort: str | None - safeguards: ReadOnly[list[dict[str, object]] | None] + safeguards: ReadOnly[Sequence[Mapping[str, object]] | None] class AnthropicMessagesRequest(AnthropicMessagesRequestOptionalParams, total=False): @@ -500,7 +500,7 @@ ContentBlockStart = ContentBlockStartToolUse | ContentBlockStartText class MessageDelta(TypedDict, total=False): stop_reason: str | None - safeguard_results: ReadOnly[list[dict[str, object]]] + safeguard_results: ReadOnly[Sequence[Mapping[str, object]]] class UsageDelta(TypedDict, total=False): @@ -566,7 +566,7 @@ class MessageChunk(TypedDict, total=False): stop_reason: str | None stop_sequence: str | None usage: UsageDelta - safeguard_results: ReadOnly[list[dict[str, object]]] + safeguard_results: ReadOnly[Sequence[Mapping[str, object]]] class MessageStartBlock(TypedDict): diff --git a/litellm/types/llms/anthropic_messages/anthropic_response.py b/litellm/types/llms/anthropic_messages/anthropic_response.py index 4fadd7d3c1d..cffca68d4f8 100644 --- a/litellm/types/llms/anthropic_messages/anthropic_response.py +++ b/litellm/types/llms/anthropic_messages/anthropic_response.py @@ -1,3 +1,4 @@ +from collections.abc import Mapping, Sequence from typing import Any, Literal, TypeAlias from typing_extensions import NotRequired, ReadOnly, TypedDict @@ -89,4 +90,4 @@ class AnthropicMessagesResponse(TypedDict, total=False): type: Literal["message"] | None usage: AnthropicUsage | None context_management: NotRequired[ContextManagementResponse] - safeguard_results: NotRequired[ReadOnly[list[dict[str, object]]]] + safeguard_results: NotRequired[ReadOnly[Sequence[Mapping[str, object]]]] diff --git a/litellm/types/llms/bedrock.py b/litellm/types/llms/bedrock.py index fb96b1598d8..55c0ca93d34 100644 --- a/litellm/types/llms/bedrock.py +++ b/litellm/types/llms/bedrock.py @@ -1,8 +1,9 @@ import json +from collections.abc import Mapping, Sequence from enum import Enum from typing import TYPE_CHECKING, Any, Final, Literal -from typing_extensions import Required, TypedDict, override +from typing_extensions import ReadOnly, Required, TypedDict, override from .openai import ChatCompletionToolCallChunk @@ -1090,7 +1091,7 @@ class BedrockInvokeAnthropicMessagesRequest(TypedDict, total=False): thinking: dict metadata: dict output_config: dict - safeguards: list + safeguards: ReadOnly[Sequence[Mapping[str, object]]] # `context_management` is allowed for Bedrock InvokeModel only when it # carries `compact_20260112` edits paired with the `compact-2026-01-12` diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py index e2b0b153502..1b429674591 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py @@ -1475,7 +1475,9 @@ async def test_anthropic_messages_forwards_safeguards_and_dangerous_tool_use_bet safeguards, safeguard_results = _claude_code_auto_mode_request() captured: dict[str, object] = {} - with patch.object(VertexBase, "_ensure_access_token", return_value=("test-token", "test-project")): + with patch.object( # test-quality-ok: the GCP token exchange runs before the faked HTTP boundary + VertexBase, "_ensure_access_token", return_value=("test-token", "test-project") + ): response = await handler.anthropic_messages( max_tokens=16, messages=[{"role": "user", "content": "hi"}],