/ tests / unit / common / utils / embeds / test_automatic_template_resolution.py
test_automatic_template_resolution.py
  1  """
  2  Test that template resolution happens automatically when resolving late embeds.
  3  """
  4  
  5  import pytest
  6  from solace_agent_mesh.common.utils.embeds import (
  7      LATE_EMBED_TYPES,
  8      evaluate_embed,
  9      resolve_embeds_recursively_in_string,
 10  )
 11  from solace_agent_mesh.common.utils.embeds.types import ResolutionMode
 12  from tests.integration.conftest import TestInMemoryArtifactService
 13  
 14  
 15  @pytest.mark.asyncio
 16  async def test_template_resolution_automatic_with_late_embeds():
 17      """
 18      Test that templates are automatically resolved when resolving late embeds
 19      without needing a separate call to resolve_template_blocks_in_string.
 20      """
 21      artifact_service = TestInMemoryArtifactService()
 22  
 23      # Create a CSV data artifact
 24      csv_content = """name,age,department
 25  Alice,30,Engineering
 26  Bob,25,Sales"""
 27  
 28      await artifact_service.save_artifact(
 29          app_name="test_app",
 30          user_id="test_user",
 31          session_id="test_session",
 32          filename="employees.csv",
 33          artifact=type('Part', (), {'inline_data': type('InlineData', (), {
 34              'data': csv_content.encode('utf-8'),
 35              'mime_type': 'text/csv'
 36          })})()
 37      )
 38  
 39      # Create an artifact with a template block
 40      artifact_content = """# Employee Report
 41  
 42  Here are all our employees:
 43  
 44  «««template: data="employees.csv"
 45  | {% for h in headers %}{{ h }} | {% endfor %}
 46  |{% for h in headers %}---|{% endfor %}
 47  {% for row in data_rows %}| {% for cell in row %}{{ cell }} | {% endfor %}
 48  {% endfor %}
 49  »»»
 50  
 51  End of report."""
 52  
 53      await artifact_service.save_artifact(
 54          app_name="test_app",
 55          user_id="test_user",
 56          session_id="test_session",
 57          filename="report.md",
 58          artifact=type('Part', (), {'inline_data': type('InlineData', (), {
 59              'data': artifact_content.encode('utf-8'),
 60              'mime_type': 'text/markdown'
 61          })})()
 62      )
 63  
 64      # Now embed the artifact using artifact_content (a late embed)
 65      text_with_embed = "Here's the report: «artifact_content:report.md»"
 66  
 67      context = {
 68          "artifact_service": artifact_service,
 69          "session_context": {
 70              "app_name": "test_app",
 71              "user_id": "test_user",
 72              "session_id": "test_session",
 73          }
 74      }
 75  
 76      config = {
 77          "gateway_max_artifact_resolve_size_bytes": -1,
 78          "gateway_recursive_embed_depth": 12,
 79      }
 80  
 81      # Resolve late embeds - templates should be resolved automatically
 82      result = await resolve_embeds_recursively_in_string(
 83          text=text_with_embed,
 84          context=context,
 85          resolver_func=evaluate_embed,
 86          types_to_resolve=LATE_EMBED_TYPES,
 87          resolution_mode=ResolutionMode.RECURSIVE_ARTIFACT_CONTENT,
 88          log_identifier="[Test]",
 89          config=config,
 90          max_depth=12,
 91          max_total_size=-1,
 92      )
 93  
 94      # Verify the template was resolved (should contain the CSV data as a table)
 95      assert "Alice" in result
 96      assert "Bob" in result
 97      assert "Engineering" in result
 98      assert "Sales" in result
 99      assert "| name | age | department |" in result
100  
101      # The template block delimiters should be gone
102      assert "«««template:" not in result
103      assert "»»»" not in result
104  
105      print("\n=== Result ===")
106      print(result)
107      print("=== End Result ===")
108  
109  
110  @pytest.mark.asyncio
111  async def test_no_template_resolution_with_early_embeds_only():
112      """
113      Test that templates are NOT resolved when only early embeds are being resolved
114      (since templates are considered late embeds).
115      """
116      from solace_agent_mesh.common.utils.embeds import EARLY_EMBED_TYPES, resolve_embeds_recursively_in_string
117  
118      artifact_service = TestInMemoryArtifactService()
119  
120      # Create a text artifact with a template block
121      artifact_content = """Report generated at «datetime:iso»
122  
123  «««template: data="data.csv"
124  Some template content
125  »»»"""
126  
127      # Resolve only early embeds (datetime)
128      # Templates should NOT be resolved since they're late embeds
129      context = {
130          "artifact_service": artifact_service,
131          "session_context": {
132              "app_name": "test_app",
133              "user_id": "test_user",
134              "session_id": "test_session",
135          }
136      }
137  
138      result = await resolve_embeds_recursively_in_string(
139          text=artifact_content,
140          context=context,
141          resolver_func=evaluate_embed,
142          types_to_resolve=EARLY_EMBED_TYPES,
143          resolution_mode=ResolutionMode.A2A_MESSAGE_TO_USER,
144          log_identifier="[Test]",
145          config={},
146          max_depth=12,
147          max_total_size=-1,
148      )
149  
150      # datetime should be resolved
151      assert "«datetime:iso»" not in result
152  
153      # But template block should still be present (not resolved)
154      assert "«««template:" in result
155      assert "»»»" in result
156  
157      print("\n=== Result (Early Embeds Only) ===")
158      print(result)
159      print("=== End Result ===")