From ae6893bc6498d45785fad095821813d13e21cce3 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Wed, 9 Sep 2026 15:38:55 -0700 Subject: [PATCH] refactor(guardrails): narrow the Responses tool-call item mapping types --- .../openai/responses/guardrail_translation/handler.py | 4 ++-- .../responses/test_openai_responses_guardrail_handler.py | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/litellm/llms/openai/responses/guardrail_translation/handler.py b/litellm/llms/openai/responses/guardrail_translation/handler.py index e78e1f56915..fd0d7b66bee 100644 --- a/litellm/llms/openai/responses/guardrail_translation/handler.py +++ b/litellm/llms/openai/responses/guardrail_translation/handler.py @@ -193,11 +193,11 @@ def _is_tool_call_item(item: object) -> bool: return isinstance(item, Mapping) and item.get("type") in _TOOL_CALL_ITEM_TYPES -def _tool_call_output_item_mapping(item: object) -> Mapping[str, Any] | None: +def _tool_call_output_item_mapping(item: object) -> Mapping[str, object] | None: if stream_item_field(item, "type") not in _TOOL_CALL_ITEM_TYPES: return None if isinstance(item, Mapping): - return cast("Mapping[str, Any]", item) # cast-ok: output items are str-keyed JSON objects + return cast("Mapping[str, object]", item) # cast-ok: output items are str-keyed JSON objects return item.model_dump() if isinstance(item, BaseModel) else None diff --git a/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py b/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py index 628ada05267..cf4895f637f 100644 --- a/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py @@ -14,6 +14,7 @@ import pytest from fastapi import HTTPException +from pydantic import BaseModel from openai.types.responses import ( ResponseCustomToolCall, ResponseCustomToolCallInputDeltaEvent, @@ -28,6 +29,7 @@ from litellm.llms.openai.responses.guardrail_translation.handler import ( OpenAIResponsesHandler, ) from litellm.llms.openai.responses.guardrail_translation.tool_merge import merge_guardrailed_tools +from litellm.types.llms.openai import ChatCompletionToolCallChunk from litellm.responses.litellm_completion_transformation.transformation import ( LiteLLMCompletionResponsesConfig, ) @@ -68,7 +70,7 @@ class PersimmonMaskingGuardrail(CustomGuardrail): inputs: GenericGuardrailAPIInputs, request_data: dict, input_type: Literal["request", "response"], - logging_obj: Optional[Any] = None, + logging_obj: Optional[LiteLLMLoggingObj] = None, ) -> GenericGuardrailAPIInputs: tool_calls = [ { @@ -593,7 +595,7 @@ class TestOpenAIResponsesHandlerToolCallExtraction: texts_to_check: List[str] = [] images_to_check: List[str] = [] - tool_calls_to_check: List[Any] = [] + tool_calls_to_check: List[ChatCompletionToolCallChunk] = [] task_mappings: List[Tuple[int, int]] = [] # Extract tool calls @@ -1476,7 +1478,7 @@ class TestOpenAIResponsesHandlerStreamingOutputProcessing: ) handler = OpenAIResponsesHandler() - typed_events: List[Any] = [ + typed_events: List[BaseModel] = [ model.model_validate({**event, "sequence_number": sequence_number}) for sequence_number, (model, event) in enumerate( zip(