3535from google .adk .a2a .converters .utils import ADK_METADATA_KEY_PREFIX
3636from google .adk .agents .invocation_context import InvocationContext
3737from google .adk .events .event import Event
38+ from google .genai import types as genai_types
3839import pytest
3940
4041
@@ -109,7 +110,7 @@ def test_serialize_metadata_value_with_model_dump(self):
109110
110111 assert result == {"key" : "value" }
111112 mock_value .model_dump .assert_called_once_with (
112- exclude_none = True , by_alias = True
113+ mode = "json" , exclude_none = True , by_alias = True
113114 )
114115
115116 def test_serialize_metadata_value_with_model_dump_exception (self ):
@@ -131,6 +132,51 @@ def test_serialize_metadata_value_without_model_dump(self):
131132 result = _serialize_metadata_value (value )
132133 assert result == "simple_string"
133134
135+ def _serialized_metadata_with_bytes (self ):
136+ value = genai_types .FunctionResponse (
137+ name = "computer_use" ,
138+ response = {"inline_data" : {"data" : b"\x89 PNG_BYTES" }},
139+ )
140+ result = _serialize_metadata_value (value )
141+
142+ # No raw bytes anywhere in the serialized structure.
143+ def _assert_no_bytes (obj ):
144+ if isinstance (obj , bytes ):
145+ raise AssertionError ("raw bytes leaked into serialized metadata" )
146+ if isinstance (obj , dict ):
147+ for v in obj .values ():
148+ _assert_no_bytes (v )
149+ elif isinstance (obj , (list , tuple )):
150+ for v in obj :
151+ _assert_no_bytes (v )
152+
153+ _assert_no_bytes (result )
154+ return result
155+
156+ @pytest .mark .skipif (
157+ _compat .IS_A2A_V1 , reason = "0.3-only proto_utils.dict_to_struct"
158+ )
159+ def test_serialize_metadata_value_with_bytes_to_struct_v03 (self ):
160+ """0.3: serialized metadata builds a proto Struct without raising."""
161+ from a2a .utils import proto_utils
162+
163+ result = self ._serialized_metadata_with_bytes ()
164+ struct = proto_utils .dict_to_struct ({"meta" : result })
165+ assert struct is not None
166+
167+ @pytest .mark .skipif (
168+ not _compat .IS_A2A_V1 , reason = "1.x-only ParseDict into proto Struct"
169+ )
170+ def test_serialize_metadata_value_with_bytes_to_struct_v1x (self ):
171+ """1.x: serialized metadata ParseDicts into a proto Struct."""
172+ from google .protobuf import struct_pb2
173+ from google .protobuf .json_format import ParseDict
174+
175+ result = self ._serialized_metadata_with_bytes ()
176+ struct = struct_pb2 .Struct ()
177+ ParseDict ({"meta" : result }, struct )
178+ assert struct is not None
179+
134180 def test_get_context_metadata_success (self ):
135181 """Test successful context metadata creation."""
136182 result = _get_context_metadata (
@@ -601,7 +647,6 @@ def test_create_status_update_event_with_input_required_state(self):
601647 def test_convert_event_to_a2a_message_with_multiple_parts_returned (self ):
602648 """Test event to message conversion when part_converter returns multiple parts."""
603649 from google .adk .a2a .converters .event_converter import convert_event_to_a2a_message
604- from google .genai import types as genai_types
605650
606651 # Arrange
607652 mock_genai_part = genai_types .Part (text = "source part" )
@@ -815,7 +860,6 @@ def test_convert_a2a_task_to_event_message_conversion_error(self):
815860 def test_convert_a2a_message_to_event_success (self ):
816861 """Test successful conversion of A2A message to event."""
817862 from google .adk .a2a .converters .event_converter import convert_a2a_message_to_event
818- from google .genai import types as genai_types
819863
820864 # Use a real A2A part (production reads its metadata); the part_converter
821865 # callback is still mocked to return a canned genai Part.
@@ -844,7 +888,6 @@ def test_convert_a2a_message_to_event_success(self):
844888 def test_convert_a2a_message_to_event_with_multiple_parts_returned (self ):
845889 """Test message to event conversion when part_converter returns multiple parts."""
846890 from google .adk .a2a .converters .event_converter import convert_a2a_message_to_event
847- from google .genai import types as genai_types
848891
849892 # Arrange
850893 mock_a2a_part = _compat .make_text_part ("part 1" )
@@ -945,7 +988,6 @@ def test_convert_a2a_message_to_event_part_conversion_fails(self):
945988 def test_convert_a2a_message_to_event_part_conversion_exception (self ):
946989 """Test handling when part conversion raises exception."""
947990 from google .adk .a2a .converters .event_converter import convert_a2a_message_to_event
948- from google .genai import types as genai_types
949991
950992 # Setup mock to raise exception. The A2A parts are real (production
951993 # reads their metadata); the converter callback drives the behavior.
0 commit comments