fix(bedrock/agentcore): type forwarding params to clear the basedpyright gate

This commit is contained in:
Sindri 2026-10-28 11:06:30 +00:00
parent 1ff6a96be7
commit 9ae2549645
2 changed files with 15 additions and 8 deletions

View file

@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any, Final, Optional, Union
from urllib.parse import quote
import httpx
from pydantic import TypeAdapter
from litellm._logging import verbose_logger
from litellm._uuid import uuid
@ -50,6 +51,9 @@ else:
HTTPHandler = Any
AsyncHTTPHandler = Any
_PARAMS: Final = TypeAdapter(dict[str, object])
_TOOLS: Final = TypeAdapter(tuple[object, ...])
class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM):
def __init__(self, **kwargs):
@ -267,7 +271,10 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM):
# list verbatim under "content" so an attachment-aware agent can read the raw
# blocks (image_url, file, etc.). Default off keeps the payload byte-identical
# to the legacy {"prompt": "..."} shape for agents that only read the prompt.
if self._is_flag_enabled(optional_params, litellm_params, "forward_multimodal_content"):
typed_optional_params: Final = _PARAMS.validate_python(optional_params)
typed_litellm_params: Final = _PARAMS.validate_python(litellm_params)
if self._is_flag_enabled(typed_optional_params, typed_litellm_params, "forward_multimodal_content"):
last_content: Final = messages[-1].get("content")
if isinstance(last_content, list) and any(
isinstance(block, dict) and block.get("type") not in (None, "text") for block in last_content
@ -276,13 +283,13 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM):
# not deep, to avoid cloning large base64 media on the request path.
payload["content"] = list(last_content)
if self._is_flag_enabled(optional_params, litellm_params, "forward_tools"):
tools: Final = optional_params.get("tools")
if self._is_flag_enabled(typed_optional_params, typed_litellm_params, "forward_tools"):
tools: Final = typed_optional_params.get("tools")
if isinstance(tools, list) and tools:
# Immutable shallow copy: the payload can never alias the caller's list,
# the nested dicts stay shared to avoid a deep clone, and json.dumps
# serializes a tuple to the same JSON array a list would.
payload["tools"] = tuple(tools)
payload["tools"] = _TOOLS.validate_python(tools)
# Get or generate session ID - this goes in the header
runtime_session_id: Final = self._get_runtime_session_id(optional_params)

View file

@ -878,7 +878,7 @@ class TestAgentCoreForwardToolsEndToEnd:
"""
def test_tools_dropped_without_allowed_openai_params(self):
optional_params = litellm.utils.get_optional_params(
optional_params: Final[dict[str, object]] = litellm.utils.get_optional_params(
model=AGENTCORE_TEST_MODEL,
custom_llm_provider="bedrock",
tools=[WEB_SEARCH_TOOL],
@ -888,7 +888,7 @@ class TestAgentCoreForwardToolsEndToEnd:
assert "tools" not in optional_params
def test_allowed_openai_params_carries_tools_to_the_transform(self):
optional_params = litellm.utils.get_optional_params(
optional_params: Final[dict[str, object]] = litellm.utils.get_optional_params(
model=AGENTCORE_TEST_MODEL,
custom_llm_provider="bedrock",
tools=[WEB_SEARCH_TOOL],
@ -914,7 +914,7 @@ class TestAgentCoreForwardToolsEndToEnd:
forward_tools, so this is the path every real caller takes: both the flag and
the tools list arrive in optional_params and litellm_params stays empty.
"""
optional_params = litellm.utils.get_optional_params(
optional_params: Final[dict[str, object]] = litellm.utils.get_optional_params(
model=AGENTCORE_TEST_MODEL,
custom_llm_provider="bedrock",
tools=[WEB_SEARCH_TOOL],
@ -936,7 +936,7 @@ class TestAgentCoreForwardToolsEndToEnd:
def test_allowed_openai_params_alone_does_not_forward(self):
"""Both opt-ins are required; the escape hatch alone changes nothing."""
optional_params = litellm.utils.get_optional_params(
optional_params: Final[dict[str, object]] = litellm.utils.get_optional_params(
model=AGENTCORE_TEST_MODEL,
custom_llm_provider="bedrock",
tools=[WEB_SEARCH_TOOL],