diff --git a/litellm/llms/a2a/chat/guardrail_translation/handler.py b/litellm/llms/a2a/chat/guardrail_translation/handler.py index 921d33f16b6..5dc9679fe78 100644 --- a/litellm/llms/a2a/chat/guardrail_translation/handler.py +++ b/litellm/llms/a2a/chat/guardrail_translation/handler.py @@ -14,7 +14,7 @@ import json from collections.abc import Sequence from typing import TYPE_CHECKING, Any, Final, Optional -from pydantic import ConfigDict, TypeAdapter +from pydantic import ConfigDict, TypeAdapter, ValidationError from typing_extensions import ReadOnly, TypedDict from litellm._logging import verbose_proxy_logger @@ -337,7 +337,7 @@ class A2AGuardrailHandler(BaseTranslation): elif isinstance(item, str): try: obj = _JSON_OBJECT.validate_python(json.loads(item.strip())) - except (json.JSONDecodeError, TypeError): + except (json.JSONDecodeError, TypeError, ValidationError): continue else: continue diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py b/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py index 4cbd252f65c..70d83eeb840 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py @@ -5,6 +5,7 @@ from collections.abc import Mapping from typing import Literal, TypedDict from pydantic import Field +from typing_extensions import ReadOnly from .base import GuardrailConfigModel @@ -42,7 +43,7 @@ class PolicyApplicableTo(str, enum.Enum): class DynamoAIRequest(TypedDict, total=False): """Request structure for DynamoAI /moderation/analyze endpoint""" - messages: list[dict[str, object]] + messages: ReadOnly[list[dict[str, object]]] textType: DynamoTextType | None policyIds: list[str] modelId: str | None @@ -58,8 +59,8 @@ class PolicyInfo(TypedDict, total=False): description: str method: PolicyMethod action: Literal["BLOCK", "WARN", "REDACT", "SANITIZE", "NONE"] - methodParams: dict[str, object] - decisionParams: dict[str, object] + methodParams: ReadOnly[dict[str, object]] + decisionParams: ReadOnly[dict[str, object]] applicableTo: PolicyApplicableTo created_at: str creatorId: str @@ -76,7 +77,7 @@ class AppliedPolicyDto(TypedDict, total=False): """Applied policy details from DynamoAI response""" policy: PolicyInfo - outputs: dict[str, object] | None + outputs: ReadOnly[dict[str, object] | None] action: str | None diff --git a/tests/unit/llms/a2a/chat/guardrail_translation/test_a2a_guardrail_handler.py b/tests/unit/llms/a2a/chat/guardrail_translation/test_a2a_guardrail_handler.py index dd7e8fadcd8..01eff7f6bbf 100644 --- a/tests/unit/llms/a2a/chat/guardrail_translation/test_a2a_guardrail_handler.py +++ b/tests/unit/llms/a2a/chat/guardrail_translation/test_a2a_guardrail_handler.py @@ -33,3 +33,7 @@ class TestA2AGuardrailHandlerStreamingScanKey: def test_unparseable_items_are_ignored(self): key = A2AGuardrailHandler().get_streaming_scan_key([_text_event("hi"), "not json", b"bytes"]) assert key.texts == ("hi",) + + def test_json_items_that_are_not_objects_are_ignored(self): + key = A2AGuardrailHandler().get_streaming_scan_key([_text_event("hi"), "[1, 2]", "5"]) + assert key.texts == ("hi",)