From 0272f8ff41b0470c722e3365d37e9d4de16f9437 Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Sun, 7 Jun 2026 11:11:24 +0800 Subject: [PATCH] fix: skip code extraction regex without delimiters --- .../code_executors/code_execution_utils.py | 2 + .../test_code_execution_utils.py | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/unittests/code_executors/test_code_execution_utils.py diff --git a/src/google/adk/code_executors/code_execution_utils.py b/src/google/adk/code_executors/code_execution_utils.py index 7cccce48be..17b86a2949 100644 --- a/src/google/adk/code_executors/code_execution_utils.py +++ b/src/google/adk/code_executors/code_execution_utils.py @@ -144,6 +144,8 @@ def extract_code_and_truncate_content( first_text_part = copy.deepcopy(text_parts[0]) response_text = '\n'.join([p.text for p in text_parts]) + if not any(d[0] in response_text for d in code_block_delimiters): + return # Find the first code block. leading_delimiter_pattern = '|'.join(d[0] for d in code_block_delimiters) diff --git a/tests/unittests/code_executors/test_code_execution_utils.py b/tests/unittests/code_executors/test_code_execution_utils.py new file mode 100644 index 0000000000..e541855108 --- /dev/null +++ b/tests/unittests/code_executors/test_code_execution_utils.py @@ -0,0 +1,54 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest.mock import patch + +from google.adk.code_executors import code_execution_utils as utils_module +from google.adk.code_executors.code_execution_utils import CodeExecutionUtils +from google.genai import types + + +CODE_BLOCK_DELIMITERS = [('```python\n', '\n```')] + + +def test_extract_code_skips_regex_when_opening_delimiter_is_missing(): + content = types.Content(parts=[types.Part(text='x' * 100_000)]) + + with patch.object( + utils_module.re, + 'compile', + side_effect=AssertionError('the full regex should be skipped'), + ): + code = CodeExecutionUtils.extract_code_and_truncate_content( + content, CODE_BLOCK_DELIMITERS + ) + + assert code is None + assert content.parts[0].text == 'x' * 100_000 + + +def test_extract_code_from_text_part_still_truncates_after_first_block(): + content = types.Content( + parts=[ + types.Part(text='before ```python\nprint("ok")\n``` after'), + ] + ) + + code = CodeExecutionUtils.extract_code_and_truncate_content( + content, CODE_BLOCK_DELIMITERS + ) + + assert code == 'print("ok")' + assert content.parts[0].text == 'before ' + assert content.parts[1].executable_code.code == 'print("ok")'