Skip to content

Commit ec18c02

Browse files
authored
Merge branch 'main' into feat/durable_task
2 parents 5beb041 + f696ac9 commit ec18c02

File tree

32 files changed

+1770
-341
lines changed

32 files changed

+1770
-341
lines changed

python/packages/a2a/agent_framework_a2a/_agent.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ def __init__(
114114
"""Initialize the A2AAgent.
115115
116116
Keyword Args:
117-
name: The name of the agent.
117+
name: The name of the agent. Defaults to agent_card.name if agent_card is provided.
118118
id: The unique identifier for the agent, will be created automatically if not provided.
119-
description: A brief description of the agent's purpose.
119+
description: A brief description of the agent's purpose. Defaults to agent_card.description
120+
if agent_card is provided.
120121
agent_card: The agent card for the agent.
121122
url: The URL for the A2A server.
122123
client: The A2A client for the agent.
@@ -127,6 +128,13 @@ def __init__(
127128
10.0s write, 5.0s pool - optimized for A2A operations).
128129
kwargs: any additional properties, passed to BaseAgent.
129130
"""
131+
# Default name/description from agent_card when not explicitly provided
132+
if agent_card is not None:
133+
if name is None:
134+
name = agent_card.name
135+
if description is None:
136+
description = agent_card.description
137+
130138
super().__init__(id=id, name=name, description=description, **kwargs)
131139
self._http_client: httpx.AsyncClient | None = http_client
132140
self._timeout_config = self._create_timeout_config(timeout)

python/packages/a2a/tests/test_a2a_agent.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,54 @@ def test_a2a_agent_initialization_with_client(mock_a2a_client: MockA2AClient) ->
145145
assert agent.client == mock_a2a_client
146146

147147

148+
def test_a2a_agent_defaults_name_description_from_agent_card(mock_a2a_client: MockA2AClient) -> None:
149+
"""Test A2AAgent defaults name and description from agent_card when not explicitly provided."""
150+
mock_card = MagicMock(spec=AgentCard)
151+
mock_card.name = "Card Agent Name"
152+
mock_card.description = "Card agent description"
153+
154+
agent = A2AAgent(agent_card=mock_card, client=mock_a2a_client, http_client=None)
155+
156+
assert agent.name == "Card Agent Name"
157+
assert agent.description == "Card agent description"
158+
159+
160+
def test_a2a_agent_explicit_name_description_overrides_agent_card(mock_a2a_client: MockA2AClient) -> None:
161+
"""Test that explicit name/description take precedence over agent_card values."""
162+
mock_card = MagicMock(spec=AgentCard)
163+
mock_card.name = "Card Agent Name"
164+
mock_card.description = "Card agent description"
165+
166+
agent = A2AAgent(
167+
name="Explicit Name",
168+
description="Explicit description",
169+
agent_card=mock_card,
170+
client=mock_a2a_client,
171+
http_client=None,
172+
)
173+
174+
assert agent.name == "Explicit Name"
175+
assert agent.description == "Explicit description"
176+
177+
178+
def test_a2a_agent_empty_string_name_description_not_overridden(mock_a2a_client: MockA2AClient) -> None:
179+
"""Test that explicitly provided empty strings are not overridden by agent_card values."""
180+
mock_card = MagicMock(spec=AgentCard)
181+
mock_card.name = "Card Agent Name"
182+
mock_card.description = "Card agent description"
183+
184+
agent = A2AAgent(
185+
name="",
186+
description="",
187+
agent_card=mock_card,
188+
client=mock_a2a_client,
189+
http_client=None,
190+
)
191+
192+
assert agent.name == ""
193+
assert agent.description == ""
194+
195+
148196
def test_a2a_agent_initialization_without_client_raises_error() -> None:
149197
"""Test A2AAgent initialization without client or URL raises ValueError."""
150198
with raises(ValueError, match="Either agent_card or url must be provided"):
@@ -561,6 +609,8 @@ def test_transport_negotiation_both_fail() -> None:
561609
# Create a mock agent card
562610
mock_agent_card = MagicMock(spec=AgentCard)
563611
mock_agent_card.url = "http://test-agent.example.com"
612+
mock_agent_card.name = "Test Agent"
613+
mock_agent_card.description = "A test agent"
564614

565615
# Mock the factory to simulate both primary and fallback failures
566616
mock_factory = MagicMock()

python/packages/ag-ui/tests/ag_ui/test_event_converters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def test_tool_call_result_event(self) -> None:
185185
assert update.role == "tool"
186186
assert len(update.contents) == 1
187187
assert update.contents[0].call_id == "call_123"
188-
assert update.contents[0].result == {"temperature": 22, "condition": "sunny"}
188+
assert update.contents[0].result == '{"temperature": 22, "condition": "sunny"}'
189189

190190
def test_run_finished_event(self) -> None:
191191
"""Test conversion of RUN_FINISHED event."""

python/packages/anthropic/agent_framework_anthropic/_chat_client.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,46 @@ def _prepare_message_for_anthropic(self, message: Message) -> dict[str, Any]:
716716
"input": content.parse_arguments(),
717717
})
718718
case "function_result":
719-
a_content.append({
720-
"type": "tool_result",
721-
"tool_use_id": content.call_id,
722-
"content": content.result if content.result is not None else "",
723-
"is_error": content.exception is not None,
724-
})
719+
if content.items:
720+
tool_content: list[dict[str, Any]] = []
721+
for item in content.items:
722+
if item.type == "text":
723+
tool_content.append({"type": "text", "text": item.text or ""})
724+
elif item.type == "data" and item.has_top_level_media_type("image"):
725+
tool_content.append({
726+
"type": "image",
727+
"source": {
728+
"data": _get_data_bytes_as_str(item), # type: ignore[attr-defined]
729+
"media_type": item.media_type,
730+
"type": "base64",
731+
},
732+
})
733+
elif item.type == "uri" and item.has_top_level_media_type("image"):
734+
tool_content.append({
735+
"type": "image",
736+
"source": {"type": "url", "url": item.uri},
737+
})
738+
else:
739+
logger.debug(
740+
"Ignoring unsupported rich content media type in tool result: %s",
741+
item.media_type,
742+
)
743+
tool_result_content = (
744+
tool_content if tool_content else (content.result if content.result is not None else "")
745+
)
746+
a_content.append({
747+
"type": "tool_result",
748+
"tool_use_id": content.call_id,
749+
"content": tool_result_content,
750+
"is_error": content.exception is not None,
751+
})
752+
else:
753+
a_content.append({
754+
"type": "tool_result",
755+
"tool_use_id": content.call_id,
756+
"content": content.result if content.result is not None else "",
757+
"is_error": content.exception is not None,
758+
})
725759
case "mcp_server_tool_call":
726760
mcp_call: dict[str, Any] = {
727761
"type": "mcp_tool_use",

0 commit comments

Comments
 (0)