From 6f192f901941b1c42d21e64f6d757350939c8e32 Mon Sep 17 00:00:00 2001 From: Yufei-Z <39251819+Yufei-Z@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:00:16 +0800 Subject: [PATCH] Python: preserve metadata in raw-data content mappings --- .../packages/core/agent_framework/_types.py | 8 ++++- python/packages/core/tests/core/test_types.py | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/python/packages/core/agent_framework/_types.py b/python/packages/core/agent_framework/_types.py index d2ed7de92c1..1cb1322edd9 100644 --- a/python/packages/core/agent_framework/_types.py +++ b/python/packages/core/agent_framework/_types.py @@ -1533,7 +1533,13 @@ def from_dict(cls: type[ContentT], data: Mapping[str, Any]) -> ContentT: # Special handling for DataContent with data and media_type if content_type == "data" and "data" in remaining and "media_type" in remaining: # Use from_data() to properly create the DataContent with URI - return cls.from_data(remaining["data"], remaining["media_type"]) + return cls.from_data( + remaining["data"], + remaining["media_type"], + annotations=annotations, + additional_properties=additional_properties, + raw_representation=raw_representation, + ) # Handle nested Content objects (e.g., function_call in function_approval_request) if (function_call := remaining.get("function_call")) and isinstance(function_call, dict): diff --git a/python/packages/core/tests/core/test_types.py b/python/packages/core/tests/core/test_types.py index df2f55efb63..438ec74a36f 100644 --- a/python/packages/core/tests/core/test_types.py +++ b/python/packages/core/tests/core/test_types.py @@ -245,6 +245,38 @@ def test_data_content_uri(): assert isinstance(content, Content) +@mark.parametrize( + "parse_content", + [ + pytest.param(Content.from_dict, id="content"), + pytest.param(lambda data: Message("user", [data]).contents[0], id="message"), + ], +) +def test_data_content_from_dict_preserves_metadata(parse_content: Callable[[dict[str, Any]], Content]) -> None: + """Raw data mappings retain the same metadata as Content.from_data.""" + annotations: list[Annotation] = [{"type": "citation", "title": "Source document", "file_id": "file-123"}] + additional_properties = {"filename": "document.txt"} + raw_representation = object() + content_data = { + "type": "data", + "data": b"test data", + "media_type": "text/plain", + "annotations": annotations, + "additional_properties": additional_properties, + "raw_representation": raw_representation, + } + original_data = content_data.copy() + + content = parse_content(content_data) + + assert content.uri == "data:text/plain;base64,dGVzdCBkYXRh" + assert content.media_type == "text/plain" + assert content.annotations == annotations + assert content.additional_properties == additional_properties + assert content.raw_representation is raw_representation + assert content_data == original_data + + def test_data_content_invalid(): """Test the DataContent class to ensure it raises an error for invalid initialization.""" with pytest.raises(ContentError):