Skip to content

Commit 9ecbaed

Browse files
boyangsvlcopybara-github
authored andcommitted
fix: Fix regression in instructions_utils placeholder matching
Co-authored-by: Bo Yang <ybo@google.com> PiperOrigin-RevId: 934602575
1 parent 20ba01c commit 9ecbaed

2 files changed

Lines changed: 20 additions & 9 deletions

File tree

src/google/adk/utils/instructions_utils.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,24 +181,29 @@ async def _replace_match(match) -> str:
181181

182182
if leading_count == trailing_count:
183183
n = leading_count
184+
is_valid = _is_valid_path(full_path) or full_path.startswith('artifact.')
184185
if n % 2 == 0:
185186
# Even: Escaped, no evaluation
186-
half_n = n // 2
187-
return '{' * half_n + full_path + '}' * half_n
187+
if is_valid:
188+
half_n = n // 2
189+
return '{' * half_n + full_path + '}' * half_n
190+
else:
191+
return raw_match
188192
else:
189193
# Odd: Evaluate and wrap
190-
if not _is_valid_path(full_path) and not full_path.startswith('artifact.'):
194+
if not is_valid:
191195
return raw_match
192196
evaluated_value = await _evaluate_path(full_path)
193197
wrap_braces = (n - 1) // 2
194198
return '{' * wrap_braces + evaluated_value + '}' * wrap_braces
195199
else:
196200
# Asymmetric: fallback to old behavior (treat as N=1 if valid path)
197-
if not _is_valid_path(full_path) and not full_path.startswith('artifact.'):
201+
if not _is_valid_path(full_path) and not full_path.startswith(
202+
'artifact.'
203+
):
198204
return raw_match
199205
return await _evaluate_path(full_path)
200206

201-
202207
return await _async_sub(r'{+[^{}]*}+', _replace_match, template)
203208

204209

tests/unittests/utils/test_instructions_utils.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,14 +516,19 @@ async def test_inject_session_state_with_invalid_nested_path_returns_original():
516516

517517
@pytest.mark.asyncio
518518
async def test_inject_session_state_escaped_braces():
519-
instruction_template = "This is a literal {{placeholder}} and this is {value}."
519+
instruction_template = (
520+
"This is a literal {{placeholder}} and this is {value}."
521+
)
520522
invocation_context = await _create_test_readonly_context(
521523
state={"value": "real_value"}
522524
)
523525
populated_instruction = await instructions_utils.inject_session_state(
524526
instruction_template, invocation_context
525527
)
526-
assert populated_instruction == "This is a literal {placeholder} and this is real_value."
528+
assert (
529+
populated_instruction
530+
== "This is a literal {placeholder} and this is real_value."
531+
)
527532

528533

529534
@pytest.mark.asyncio
@@ -556,7 +561,9 @@ async def test_inject_session_state_quadruple_braces():
556561
populated_instruction = await instructions_utils.inject_session_state(
557562
instruction_template, invocation_context
558563
)
559-
assert populated_instruction == "This is literal double braces: {{placeholder}}."
564+
assert (
565+
populated_instruction == "This is literal double braces: {{placeholder}}."
566+
)
560567

561568

562569
@pytest.mark.asyncio
@@ -581,4 +588,3 @@ async def test_inject_session_state_asymmetric_braces_right():
581588
instruction_template, invocation_context
582589
)
583590
assert populated_instruction == "Asymmetric right: real_value."
584-

0 commit comments

Comments
 (0)