|
24 | 24 | from google.adk.code_executors.built_in_code_executor import BuiltInCodeExecutor |
25 | 25 | from google.adk.code_executors.code_execution_utils import CodeExecutionResult |
26 | 26 | from google.adk.flows.llm_flows._code_execution import _extract_code_from_error_message |
| 27 | +from google.adk.flows.llm_flows._code_execution import _maybe_recover_from_api_rejection |
27 | 28 | from google.adk.flows.llm_flows._code_execution import response_processor |
28 | 29 | from google.adk.models.llm_response import LlmResponse |
29 | 30 | from google.genai import types |
@@ -174,3 +175,55 @@ async def test_logs_executed_code(mock_logger): |
174 | 175 | mock_logger.debug.assert_called_once_with( |
175 | 176 | 'Executed code:\n```\n%s\n```', 'print("hello")' |
176 | 177 | ) |
| 178 | + |
| 179 | + |
| 180 | +# --------------------------------------------------------------------------- |
| 181 | +# _maybe_recover_from_api_rejection |
| 182 | +# --------------------------------------------------------------------------- |
| 183 | + |
| 184 | + |
| 185 | +def _make_rejected_response(error_code: str, code_snippet: str) -> LlmResponse: |
| 186 | + return LlmResponse( |
| 187 | + content=None, |
| 188 | + error_code=error_code, |
| 189 | + error_message=f'Unexpected tool call: {code_snippet}', |
| 190 | + ) |
| 191 | + |
| 192 | + |
| 193 | +def test_maybe_recover_unexpected_tool_call(): |
| 194 | + llm_response = _make_rejected_response('UNEXPECTED_TOOL_CALL', 'print(42)') |
| 195 | + recovered = _maybe_recover_from_api_rejection(llm_response) |
| 196 | + |
| 197 | + assert recovered is True |
| 198 | + assert llm_response.content is not None |
| 199 | + assert len(llm_response.content.parts) == 1 |
| 200 | + assert llm_response.content.parts[0].executable_code.code == 'print(42)' |
| 201 | + assert llm_response.error_code is None |
| 202 | + assert llm_response.error_message is None |
| 203 | + assert llm_response.finish_reason is None |
| 204 | + |
| 205 | + |
| 206 | +def test_maybe_recover_malformed_function_call(): |
| 207 | + llm_response = _make_rejected_response('MALFORMED_FUNCTION_CALL', 'x=1') |
| 208 | + assert _maybe_recover_from_api_rejection(llm_response) is True |
| 209 | + assert llm_response.content is not None |
| 210 | + |
| 211 | + |
| 212 | +def test_maybe_recover_unrecognised_error_code(): |
| 213 | + llm_response = _make_rejected_response('SAFETY', 'print(42)') |
| 214 | + assert _maybe_recover_from_api_rejection(llm_response) is False |
| 215 | + assert llm_response.content is None |
| 216 | + |
| 217 | + |
| 218 | +def test_maybe_recover_no_error_code(): |
| 219 | + llm_response = LlmResponse(content=None, error_code=None, error_message=None) |
| 220 | + assert _maybe_recover_from_api_rejection(llm_response) is False |
| 221 | + |
| 222 | + |
| 223 | +def test_maybe_recover_unparseable_message(): |
| 224 | + llm_response = LlmResponse( |
| 225 | + content=None, |
| 226 | + error_code='UNEXPECTED_TOOL_CALL', |
| 227 | + error_message='some completely different message', |
| 228 | + ) |
| 229 | + assert _maybe_recover_from_api_rejection(llm_response) is False |
0 commit comments