From c830ee204c11a2c5907093833804a69c7f52ed81 Mon Sep 17 00:00:00 2001 From: samtsai15 <6171228+samtsai15@users.noreply.github.com> Date: Thu, 27 Aug 2026 16:26:31 +0800 Subject: [PATCH] fix: type the forwarded kwargs so basedpyright can check the httpx call CI's basedpyright budget moved with the base and surfaced 12 new reportArgumentType errors, ten of them on one line. `request_kwargs` was typed `dict[str, object]` to keep an earlier gate happy, but `object` does not unpack into httpx's typed parameters: `stream()` names ten of them (content, data, files, params, headers, cookies, auth, follow_redirects, timeout, extensions) and every one was an error. `dict[str, Any]` is what the values actually are -- whatever `async_safe_get`'s caller passed through -- and it lets the call be checked instead of merely tolerated. The other two are the OUTPUT branch's `enumerate(filtered_messages)`. Making skip_scan conditional on `image_urls` removed pyright's narrowing there, since skip_scan used to be the only way that name could still be None. It cannot be None at runtime -- images exist on the request side only, so a response scan returns early exactly as before -- but the branch now says so with `or ()` rather than resting on that indirection. Co-Authored-By: Claude Opus 5 (1M context) --- litellm/litellm_core_utils/url_utils.py | 6 +++--- .../proxy/guardrails/guardrail_hooks/bedrock_guardrails.py | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/litellm/litellm_core_utils/url_utils.py b/litellm/litellm_core_utils/url_utils.py index ec3afe7276e..50cdc679f9b 100644 --- a/litellm/litellm_core_utils/url_utils.py +++ b/litellm/litellm_core_utils/url_utils.py @@ -443,7 +443,7 @@ async def _async_get_capped( client: object, url: str, max_bytes: int, - request_kwargs: dict[str, object], # mutable-ok: forwarded straight to httpx as **kwargs + request_kwargs: dict[str, Any], # mutable-ok: forwarded straight to httpx as **kwargs ) -> httpx.Response: """GET ``url``, aborting the transfer once the body exceeds ``max_bytes``. @@ -483,7 +483,7 @@ async def async_safe_get(client: Any, url: str, max_bytes: int | None = None, ** async def _issue( target_url: str, - request_kwargs: dict[str, object], # mutable-ok: forwarded straight to httpx as **kwargs + request_kwargs: dict[str, Any], # mutable-ok: forwarded straight to httpx as **kwargs ) -> httpx.Response: if max_bytes is None: return await client.get(target_url, **request_kwargs) @@ -496,7 +496,7 @@ async def async_safe_get(client: Any, url: str, max_bytes: int | None = None, ** caller_headers: Final = kwargs.pop("headers", {}) for _ in range(_MAX_REDIRECTS): validated_url, original_host = validate_url(url) - hop_kwargs: dict[str, object] = { # mutable-ok: a fresh per-hop kwargs dict, consumed by this call + hop_kwargs: dict[str, Any] = { # mutable-ok: a fresh per-hop kwargs dict, consumed by this call **kwargs, "headers": {**caller_headers, "Host": original_host}, # mutable-ok: httpx takes headers as a dict "follow_redirects": False, diff --git a/litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py b/litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py index b49040580f7..2e9971697cd 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py +++ b/litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py @@ -3465,7 +3465,11 @@ class BedrockGuardrail(CustomGuardrail, BaseAWSLLM): ), finish_reason="stop", ) - for _idx, _msg in enumerate(filtered_messages) + # `or ()`: skip_scan is now bypassed when an image is present, + # and images exist on the request side only, so a response scan + # still always has messages here. Spelled out rather than left + # leaning on that indirection. + for _idx, _msg in enumerate(filtered_messages or ()) ] ) bedrock_response = await self.make_bedrock_api_request(