From 1493619f84b7f4b64b06388fc93facbcfb48386a Mon Sep 17 00:00:00 2001 From: Jokasa7 <42598207+Jokasa7@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:09:28 +0800 Subject: [PATCH 1/2] Python: Preserve message status in chat history XML --- .../contents/chat_message_content.py | 2 +- python/tests/unit/contents/test_chat_history.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/python/semantic_kernel/contents/chat_message_content.py b/python/semantic_kernel/contents/chat_message_content.py index 13376106e8b1..5c06259eb378 100644 --- a/python/semantic_kernel/contents/chat_message_content.py +++ b/python/semantic_kernel/contents/chat_message_content.py @@ -243,7 +243,7 @@ def to_element(self) -> "Element": """ root = Element(self.tag) for field in self.model_fields_set: - if field not in ["role", "name", "encoding", "finish_reason", "ai_model_id"]: + if field not in ["role", "name", "encoding", "finish_reason", "status", "ai_model_id"]: continue value = getattr(self, field) if isinstance(value, Enum): diff --git a/python/tests/unit/contents/test_chat_history.py b/python/tests/unit/contents/test_chat_history.py index 3c1b92945296..db6c10da0b7b 100644 --- a/python/tests/unit/contents/test_chat_history.py +++ b/python/tests/unit/contents/test_chat_history.py @@ -12,6 +12,7 @@ from semantic_kernel.contents.image_content import ImageContent from semantic_kernel.contents.text_content import TextContent from semantic_kernel.contents.utils.author_role import AuthorRole +from semantic_kernel.contents.utils.status import Status from semantic_kernel.exceptions import ContentInitializationError from semantic_kernel.functions.kernel_arguments import KernelArguments from semantic_kernel.kernel import Kernel @@ -33,6 +34,18 @@ def mock_chat_completion_response() -> ChatCompletion: ) +@pytest.mark.parametrize("serializer", [str, ChatHistory.to_prompt], ids=["str", "to_prompt"]) +@pytest.mark.parametrize("status", list(Status)) +def test_xml_roundtrip_preserves_message_status(status: Status, serializer): + history = ChatHistory(messages=[ChatMessageContent(role=AuthorRole.ASSISTANT, content="Working", status=status)]) + + xml = serializer(history) + restored = ChatHistory.from_rendered_prompt(xml) + + assert f'status="{status.value}"' in xml + assert restored[0].status is status + + def test_init_with_system_message_only(): system_msg = "test message" chat_history = ChatHistory(system_message=system_msg) From 4ed9d6ee8a5e22d9acf87c83511a2c89e0f66d93 Mon Sep 17 00:00:00 2001 From: Jokasa7 <42598207+Jokasa7@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:26:24 +0800 Subject: [PATCH 2/2] Python: Skip cleared optional XML attributes --- .../semantic_kernel/contents/chat_message_content.py | 2 ++ python/tests/unit/contents/test_chat_history.py | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/python/semantic_kernel/contents/chat_message_content.py b/python/semantic_kernel/contents/chat_message_content.py index 5c06259eb378..226514e26090 100644 --- a/python/semantic_kernel/contents/chat_message_content.py +++ b/python/semantic_kernel/contents/chat_message_content.py @@ -246,6 +246,8 @@ def to_element(self) -> "Element": if field not in ["role", "name", "encoding", "finish_reason", "status", "ai_model_id"]: continue value = getattr(self, field) + if value is None: + continue if isinstance(value, Enum): value = value.value root.set(field, value) diff --git a/python/tests/unit/contents/test_chat_history.py b/python/tests/unit/contents/test_chat_history.py index db6c10da0b7b..0623062442a6 100644 --- a/python/tests/unit/contents/test_chat_history.py +++ b/python/tests/unit/contents/test_chat_history.py @@ -46,6 +46,18 @@ def test_xml_roundtrip_preserves_message_status(status: Status, serializer): assert restored[0].status is status +@pytest.mark.parametrize("serializer", [str, ChatHistory.to_prompt], ids=["str", "to_prompt"]) +def test_xml_serialization_omits_cleared_message_status(serializer): + message = ChatMessageContent(role=AuthorRole.ASSISTANT, content="Working", status=Status.IN_PROGRESS) + message.status = None + + xml = serializer(ChatHistory(messages=[message])) + restored = ChatHistory.from_rendered_prompt(xml) + + assert "status=" not in xml + assert restored[0].status is None + + def test_init_with_system_message_only(): system_msg = "test message" chat_history = ChatHistory(system_message=system_msg)