mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix missing methods on the Content class in durable tasks (#4738)
* Fix Content serialization in DurableAgentStateUnknownContent (#4719) DurableAgentStateUnknownContent.from_unknown_content() stored raw Content objects without converting them to dicts, causing json.dumps to fail in Azure Durable Functions' entity state serialization. This affected content types not explicitly handled (e.g., mcp_server_tool_call/result). The fix converts Content objects to dicts via to_dict() when storing in DurableAgentStateUnknownContent, and restores them via Content.from_dict() in to_ai_content(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add to_json and from_json methods to Content class (#4719) Add to_json() and from_json() methods to the Content class to match the serialization interface provided by SerializationMixin on other model classes. Also fix pre-existing pyright type errors in durabletask's DurableAgentStateUnknownContent.to_ai_content(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: add type guard, remove to_json, add fallback, and tests - Remove Content.to_json() per reviewer request (comment 3) - Add type guard in Content.from_json() for non-dict JSON (comments 1, 4) - Wrap json.JSONDecodeError as ValueError for consistent exception contract - Add try/except fallback in to_ai_content() for invalid Content dicts (comment 5) - Add test_content_to_dict_exclude_none and test_content_to_dict_exclude_fields (comment 2) - Add test_unknown_content_to_ai_content_fallback_on_invalid_type_dict (comment 5) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply pre-commit auto-fixes * Address review feedback for #4719: review comment fixes * Remove Content.from_json, move logic to consuming code (#4719) Remove the from_json convenience method from Content class per review feedback. This is the same trivial json.loads + from_dict wrapper as to_json which was already removed. Consumers should call json.loads and Content.from_dict directly. Update tests to use Content.from_dict(json.loads(...)) pattern and remove from_json-specific error handling tests (those errors are already covered by json.loads and Content.from_dict). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
192a283c9a
commit
705ed47a0b
@@ -1,6 +1,7 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import base64
|
||||
import json
|
||||
from collections.abc import AsyncIterable, Sequence
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
@@ -1710,6 +1711,47 @@ def test_content_roundtrip_preserves_compaction_annotation_dict() -> None:
|
||||
assert annotation[GROUP_TOKEN_COUNT_KEY] is None
|
||||
|
||||
|
||||
def test_content_from_dict_via_json() -> None:
|
||||
"""Test Content.from_dict with data parsed from a JSON string."""
|
||||
data = json.loads(json.dumps({"type": "text", "text": "Hello world"}))
|
||||
content = Content.from_dict(data)
|
||||
assert content.type == "text"
|
||||
assert content.text == "Hello world"
|
||||
|
||||
|
||||
def test_content_from_dict_roundtrip_via_json() -> None:
|
||||
"""Test Content.from_dict roundtrip via to_dict and json.dumps."""
|
||||
original = Content.from_function_call(call_id="call1", name="my_func", arguments={"key": "value"})
|
||||
data = json.loads(json.dumps(original.to_dict()))
|
||||
restored = Content.from_dict(data)
|
||||
assert restored.type == "function_call"
|
||||
assert restored.call_id == "call1"
|
||||
assert restored.name == "my_func"
|
||||
assert restored.arguments == {"key": "value"}
|
||||
|
||||
|
||||
def test_content_to_dict_exclude_none() -> None:
|
||||
"""Test Content.to_dict excludes None fields by default."""
|
||||
content = Content.from_text("Hello")
|
||||
d = content.to_dict()
|
||||
parsed = json.loads(json.dumps(d))
|
||||
assert "uri" not in parsed
|
||||
|
||||
d_with_none = content.to_dict(exclude_none=False)
|
||||
parsed_with_none = json.loads(json.dumps(d_with_none))
|
||||
assert "uri" in parsed_with_none
|
||||
assert parsed_with_none["uri"] is None
|
||||
|
||||
|
||||
def test_content_to_dict_exclude_fields() -> None:
|
||||
"""Test Content.to_dict with explicit field exclusion."""
|
||||
content = Content.from_text("Hello")
|
||||
d = content.to_dict(exclude={"text"})
|
||||
parsed = json.loads(json.dumps(d))
|
||||
assert "text" not in parsed
|
||||
assert parsed["type"] == "text"
|
||||
|
||||
|
||||
def test_chat_response_roundtrip_preserves_compaction_annotation_dict() -> None:
|
||||
response = ChatResponse(
|
||||
messages=[
|
||||
|
||||
Reference in New Issue
Block a user