From bcedf79b0f3041a78574ec1b67303d24c848eb87 Mon Sep 17 00:00:00 2001 From: Will Koh Date: Wed, 29 Apr 2026 17:05:53 -0700 Subject: [PATCH] Address greptile commands and add support for input_file and input_image --- .../transformation.py | 24 ++++++----- .../test_litellm_completion_responses.py | 42 +++++++++++++++++++ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/litellm/responses/litellm_completion_transformation/transformation.py b/litellm/responses/litellm_completion_transformation/transformation.py index 551f0ee552a..32aef002a74 100644 --- a/litellm/responses/litellm_completion_transformation/transformation.py +++ b/litellm/responses/litellm_completion_transformation/transformation.py @@ -1278,19 +1278,23 @@ class LiteLLMCompletionResponsesConfig: content_list.append(item) elif isinstance(item, dict): if item.get("type") == "input_file": - content_list.append( - LiteLLMCompletionResponsesConfig._transform_input_file_item_to_file_item( + block = LiteLLMCompletionResponsesConfig._transform_input_file_item_to_file_item( + item + ) + cache_control = item.get("cache_control") + if cache_control is not None: + block["cache_control"] = cache_control # type: ignore[typeddict-unknown-key] + content_list.append(block) + elif item.get("type") == "input_image": + block = dict( + LiteLLMCompletionResponsesConfig._transform_input_image_item_to_image_item( item ) ) - elif item.get("type") == "input_image": - content_list.append( - dict( - LiteLLMCompletionResponsesConfig._transform_input_image_item_to_image_item( - item - ) - ) - ) + cache_control = item.get("cache_control") + if cache_control is not None: + block["cache_control"] = cache_control + content_list.append(block) else: # Skip text blocks with None text to avoid downstream errors text_value = item.get("text") diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py b/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py index 8fa57eb6bb4..93e45c7dd11 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py @@ -1011,6 +1011,48 @@ class TestContentTypeTransformation: assert result[1]["text"] == "uncached text" assert "cache_control" not in result[1] + def test_cache_control_propagated_to_input_file_block(self): + """ + Test that cache_control on an input_file item is propagated onto the + resulting file content block. + """ + cache_control = {"type": "ephemeral"} + content = [ + { + "type": "input_file", + "file_id": "file-abc123", + "cache_control": cache_control, + }, + {"type": "input_file", "file_id": "file-xyz789"}, + ] + result = LiteLLMCompletionResponsesConfig._transform_responses_api_content_to_chat_completion_content( + content + ) + assert len(result) == 2 + assert result[0]["cache_control"] == cache_control + assert "cache_control" not in result[1] + + def test_cache_control_propagated_to_input_image_block(self): + """ + Test that cache_control on an input_image item is propagated onto the + resulting image content block. + """ + cache_control = {"type": "ephemeral"} + content = [ + { + "type": "input_image", + "image_url": "https://example.com/img.png", + "cache_control": cache_control, + }, + {"type": "input_image", "image_url": "https://example.com/other.png"}, + ] + result = LiteLLMCompletionResponsesConfig._transform_responses_api_content_to_chat_completion_content( + content + ) + assert len(result) == 2 + assert result[0]["cache_control"] == cache_control + assert "cache_control" not in result[1] + def test_cache_control_propagated_to_message(self): """ Test that a cache_control field on a Responses API input item is