fix: Support escaped curly braces in instruction templates

Close #3527

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 868199186
This commit is contained in:
George Weale
2026-02-10 10:04:15 -08:00
committed by Copybara-Service
parent ec660ed4f0
commit 7c7d25a4a6
2 changed files with 51 additions and 1 deletions
+25 -1
View File
@@ -79,7 +79,16 @@ async def inject_session_state(
return ''.join(result)
async def _replace_match(match) -> str:
var_name = match.group().lstrip('{').rstrip('}').strip()
matched_text = match.group()
if matched_text.startswith('{{') and matched_text.endswith('}}'):
# Preserve escaped non-placeholder literals (e.g. JSON snippets),
# but keep escaped placeholders as literal placeholders.
escaped_value = matched_text[2:-2]
if _is_escaped_placeholder(escaped_value):
return matched_text[1:-1]
return matched_text
var_name = matched_text.lstrip('{').rstrip('}').strip()
optional = False
if var_name.endswith('?'):
optional = True
@@ -124,6 +133,21 @@ async def inject_session_state(
return await _async_sub(r'{+[^{}]*}+', _replace_match, template)
def _is_escaped_placeholder(value: str) -> bool:
"""Checks if escaped braces contain a supported placeholder pattern."""
var_name = value.strip()
if not var_name:
return False
if var_name.endswith('?'):
var_name = var_name.removesuffix('?')
if var_name.startswith('artifact.'):
return True
return _is_valid_state_name(var_name)
def _is_valid_state_name(var_name):
"""Checks if the variable name is a valid state name.
@@ -146,6 +146,32 @@ async def test_inject_session_state_with_invalid_state_name_returns_original():
assert populated_instruction == "Hello {invalid-key}!"
@pytest.mark.asyncio
async def test_inject_session_state_with_escaped_braces_returns_literal():
instruction_template = "Code sample: {{user_name}}. Value: {user_name}."
invocation_context = await _create_test_readonly_context(
state={"user_name": "Foo"}
)
populated_instruction = await instructions_utils.inject_session_state(
instruction_template, invocation_context
)
assert populated_instruction == "Code sample: {user_name}. Value: Foo."
@pytest.mark.asyncio
async def test_inject_session_state_with_escaped_non_placeholder_keeps_double_braces():
instruction_template = "Literal template: {{'key2': 'value2'}}."
invocation_context = await _create_test_readonly_context(
state={"user_name": "Foo"}
)
populated_instruction = await instructions_utils.inject_session_state(
instruction_template, invocation_context
)
assert populated_instruction == "Literal template: {{'key2': 'value2'}}."
@pytest.mark.asyncio
async def test_inject_session_state_with_invalid_prefix_state_name_returns_original():
instruction_template = "Hello {invalid:key}!"