Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,25 @@
logger = logging.getLogger("kagent_adk." + __name__)


def serialize_metadata_value(value: Any) -> str:
"""Safely serializes metadata values to string format.
def serialize_metadata_value(value: Any) -> str | dict[str, Any]:
"""Safely serializes a metadata value for A2A message/event metadata.

Pydantic values (anything with ``model_dump``) are returned as their
JSON-compatible serialized ``dict`` so structured metadata such as
``usage_metadata`` stays machine-readable for consumers (for example the UI
reads the token counts as object fields). Everything else is returned as its
string representation.

Args:
value: The value to serialize.

Returns:
String representation of the value.
The value's JSON-compatible ``model_dump`` dict for Pydantic values,
otherwise its string representation.
"""
if hasattr(value, "model_dump"):
Comment thread
anxkhn marked this conversation as resolved.
Comment thread
anxkhn marked this conversation as resolved.
try:
return value.model_dump(exclude_none=True, by_alias=True)
return value.model_dump(mode="json", exclude_none=True, by_alias=True)
except Exception as e:
logger.warning("Failed to serialize metadata value: %s", e)
return str(value)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from enum import Enum
from unittest.mock import Mock

import pytest
from a2a.types import TaskState, TaskStatusUpdateEvent
from google.genai import types as genai_types
from kagent.core.a2a import get_kagent_metadata_key
from pydantic import BaseModel, Field

Comment thread
anxkhn marked this conversation as resolved.
from kagent.adk.converters.event_converter import convert_event_to_a2a_events
from kagent.adk.converters.event_converter import convert_event_to_a2a_events, serialize_metadata_value


def _create_mock_invocation_context():
Expand Down Expand Up @@ -135,3 +137,30 @@ def test_message_carries_task_and_context_ids(self):
assert message is not None
assert message.task_id == "task-xyz"
assert message.context_id == "ctx-xyz"


class TestSerializeMetadataValue:
"""Test cases for serialize_metadata_value."""

def test_pydantic_value_serializes_to_dump_dict(self):
"""A Pydantic value serializes to its JSON-compatible model_dump dict so
structured metadata (e.g. usage_metadata token counts) stays
machine-readable for consumers such as the UI."""

class _Status(Enum):
READY = "ready"

class _Model(BaseModel):
a: int
b: str | None = None
status: _Status
alias_value: str = Field(alias="aliasValue")

value = _Model(a=1, status=_Status.READY, aliasValue="x")

result = serialize_metadata_value(value)

assert result == {"a": 1, "status": "ready", "aliasValue": "x"}

def test_plain_value_serializes_to_str(self):
assert serialize_metadata_value(42) == "42"
Loading