From dce01d84c5257ebc6a2490b4517f2b0cb2531d54 Mon Sep 17 00:00:00 2001 From: mateo Date: Fri, 16 Oct 2026 21:39:13 +0000 Subject: [PATCH] fix(responses): drop metadata from compact requests to OpenAI and Azure Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../llms/openai/responses/transformation.py | 10 ++++- .../test_openai_responses_transformation.py | 37 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/litellm/llms/openai/responses/transformation.py b/litellm/llms/openai/responses/transformation.py index 768d89b9a97..e7800115e68 100644 --- a/litellm/llms/openai/responses/transformation.py +++ b/litellm/llms/openai/responses/transformation.py @@ -63,6 +63,7 @@ _PROVIDERS_VALIDATING_TOOL_CALL_ITEM_IDS: Final = frozenset({LlmProviders.AZURE, _PROVIDERS_REPLAYING_ONLY_THEIR_OWN_REASONING: Final = _PROVIDERS_VALIDATING_TOOL_CALL_ITEM_IDS _ROLES_READING_PROMPT_CACHE_BREAKPOINTS: Final = frozenset({"system", "developer", "user"}) _PART_TYPES_READING_PROMPT_CACHE_BREAKPOINTS: Final = frozenset({"input_text", "input_image", "input_file"}) +_COMPACT_UNSUPPORTED_PARAMS: Final = frozenset({"metadata"}) _INPUT_ITEM: Final[TypeAdapter[Mapping[str, object]]] = TypeAdapter(Mapping[str, object]) _CONTENT_PARTS: Final[TypeAdapter[Sequence[Mapping[str, object]]]] = TypeAdapter(Sequence[Mapping[str, object]]) @@ -1163,7 +1164,14 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig): if sanitized_tools is not None: response_api_optional_request_params["tools"] = sanitized_tools data: Final = dict( - ResponsesAPIRequestParams(model=model, input=replay_safe_input, **response_api_optional_request_params) + ResponsesAPIRequestParams( + model=model, + input=replay_safe_input, + **cast( # cast-ok: the inherited base signature leaves caller parameters untyped + "ResponsesAPIOptionalRequestParams", + {key: value for key, value in request_params.items() if key not in _COMPACT_UNSUPPORTED_PARAMS}, + ), + ) ) return url, data diff --git a/tests/unit/llms/openai/responses/test_openai_responses_transformation.py b/tests/unit/llms/openai/responses/test_openai_responses_transformation.py index 0da28e7207e..342ca19ac69 100644 --- a/tests/unit/llms/openai/responses/test_openai_responses_transformation.py +++ b/tests/unit/llms/openai/responses/test_openai_responses_transformation.py @@ -1630,6 +1630,43 @@ class TestTransformListInputItemsRequest: assert data["model"] == "gpt-4o" assert data["input"] == "hello" + @pytest.mark.parametrize( + ("config", "api_base"), + [ + pytest.param( + OpenAIResponsesAPIConfig(), + "https://api.openai.com/v1/responses", + id="openai", + ), + pytest.param( + AzureOpenAIResponsesAPIConfig(), + "https://x.openai.azure.com/openai/v1/responses?api-version=preview", + id="azure", + ), + ], + ) + def test_compact_response_request_omits_metadata( + self, + config: OpenAIResponsesAPIConfig | AzureOpenAIResponsesAPIConfig, + api_base: str, + ) -> None: + _, data = config.transform_compact_response_api_request( + model="gpt-5-mini", + input="hi", + response_api_optional_request_params={ + "metadata": {"a": "b"}, + "instructions": "be brief", + "previous_response_id": "resp_1", + }, + api_base=api_base, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + + assert "metadata" not in data + assert data["instructions"] == "be brief" + assert data["previous_response_id"] == "resp_1" + def test_azure_transform_list_input_items_request_minimal(self): """Test Azure implementation with minimal parameters""" # Setup