|
20 | 20 | from google.adk.agents.invocation_context import InvocationContext |
21 | 21 | from google.adk.code_executors.agent_engine_sandbox_code_executor import AgentEngineSandboxCodeExecutor |
22 | 22 | from google.adk.code_executors.code_execution_utils import CodeExecutionInput |
| 23 | +from google.adk.code_executors.code_execution_utils import File as InputFile |
23 | 24 | from google.adk.sessions.session import Session |
24 | 25 | import pytest |
25 | 26 |
|
@@ -125,6 +126,63 @@ def test_execute_code_success( |
125 | 126 | input_data={"code": 'print("hello world")'}, |
126 | 127 | ) |
127 | 128 |
|
| 129 | + @patch("vertexai.Client") |
| 130 | + def test_execute_code_input_files_content_key( |
| 131 | + self, |
| 132 | + mock_vertexai_client, |
| 133 | + mock_invocation_context, |
| 134 | + ): |
| 135 | + """Tests that input_files are sent with 'content' (singular), not 'contents'. |
| 136 | +
|
| 137 | + Regression test for https://github.com/google/adk-python/issues/5500. |
| 138 | + The Vertex AI Sandbox API reads file.get("content", b""), so using the |
| 139 | + key "contents" silently creates empty files. |
| 140 | + """ |
| 141 | + mock_api_client = MagicMock() |
| 142 | + mock_vertexai_client.return_value = mock_api_client |
| 143 | + mock_response = MagicMock() |
| 144 | + mock_json_output = MagicMock() |
| 145 | + mock_json_output.mime_type = "application/json" |
| 146 | + mock_json_output.data = json.dumps( |
| 147 | + {"msg_out": "ok", "msg_err": ""} |
| 148 | + ).encode("utf-8") |
| 149 | + mock_json_output.metadata = None |
| 150 | + mock_response.outputs = [mock_json_output] |
| 151 | + mock_api_client.agent_engines.sandboxes.execute_code.return_value = ( |
| 152 | + mock_response |
| 153 | + ) |
| 154 | + |
| 155 | + executor = AgentEngineSandboxCodeExecutor( |
| 156 | + sandbox_resource_name="projects/123/locations/us-central1/reasoningEngines/456/sandboxEnvironments/789" |
| 157 | + ) |
| 158 | + code_input = CodeExecutionInput( |
| 159 | + code='print("hello world")', |
| 160 | + input_files=[ |
| 161 | + InputFile( |
| 162 | + name="test.txt", |
| 163 | + content=b"hello world", |
| 164 | + mime_type="text/plain", |
| 165 | + ) |
| 166 | + ], |
| 167 | + ) |
| 168 | + executor.execute_code(mock_invocation_context, code_input) |
| 169 | + |
| 170 | + # Verify the API was called with 'content' key, NOT 'contents' |
| 171 | + expected_input_data = { |
| 172 | + "code": 'print("hello world")', |
| 173 | + "files": [ |
| 174 | + { |
| 175 | + "name": "test.txt", |
| 176 | + "content": b"hello world", |
| 177 | + "mimeType": "text/plain", |
| 178 | + } |
| 179 | + ], |
| 180 | + } |
| 181 | + mock_api_client.agent_engines.sandboxes.execute_code.assert_called_once_with( |
| 182 | + name="projects/123/locations/us-central1/reasoningEngines/456/sandboxEnvironments/789", |
| 183 | + input_data=expected_input_data, |
| 184 | + ) |
| 185 | + |
128 | 186 | @patch("vertexai.Client") |
129 | 187 | def test_execute_code_recreates_sandbox_when_get_returns_none( |
130 | 188 | self, |
|
0 commit comments