diff --git a/src/a2a/compat/v0_3/jsonrpc_adapter.py b/src/a2a/compat/v0_3/jsonrpc_adapter.py index 073c7854b..d9d698411 100644 --- a/src/a2a/compat/v0_3/jsonrpc_adapter.py +++ b/src/a2a/compat/v0_3/jsonrpc_adapter.py @@ -59,7 +59,7 @@ class JSONRPC03Adapter: 'tasks/pushNotificationConfig/list': types_v03.ListTaskPushNotificationConfigRequest, 'tasks/pushNotificationConfig/delete': types_v03.DeleteTaskPushNotificationConfigRequest, 'tasks/resubscribe': types_v03.TaskResubscriptionRequest, - 'agent/authenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest, + 'agent/getAuthenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest, } def __init__( # noqa: PLR0913 @@ -225,7 +225,7 @@ async def _process_non_streaming_request( id=request_id, result=None ) ) - elif method == 'agent/authenticatedExtendedCard': + elif method == 'agent/getAuthenticatedExtendedCard': res_card = await self.get_authenticated_extended_card( request_obj, context ) @@ -248,7 +248,7 @@ async def get_authenticated_extended_card( request: types_v03.GetAuthenticatedExtendedCardRequest, context: ServerCallContext, ) -> types_v03.AgentCard: - """Handles the 'agent/authenticatedExtendedCard' JSON-RPC method.""" + """Handles the 'agent/getAuthenticatedExtendedCard' JSON-RPC method.""" if not self.agent_card.capabilities.extended_agent_card: raise ExtendedAgentCardNotConfiguredError( message='Authenticated card not supported' diff --git a/src/a2a/compat/v0_3/jsonrpc_transport.py b/src/a2a/compat/v0_3/jsonrpc_transport.py index 6153ccfc0..557a63a16 100644 --- a/src/a2a/compat/v0_3/jsonrpc_transport.py +++ b/src/a2a/compat/v0_3/jsonrpc_transport.py @@ -376,7 +376,7 @@ async def get_extended_agent_card( return card rpc_request = JSONRPC20Request( - method='agent/authenticatedExtendedCard', + method='agent/getAuthenticatedExtendedCard', params={}, _id=str(uuid4()), ) diff --git a/tests/compat/v0_3/test_jsonrpc_app_compat.py b/tests/compat/v0_3/test_jsonrpc_app_compat.py index 8120e322f..1417b5dac 100644 --- a/tests/compat/v0_3/test_jsonrpc_app_compat.py +++ b/tests/compat/v0_3/test_jsonrpc_app_compat.py @@ -11,6 +11,8 @@ from a2a.server.request_handlers.request_handler import RequestHandler from a2a.types.a2a_pb2 import ( AgentCard, + AgentCapabilities, + AgentInterface, Message as Message10, Part as Part10, Role as Role10, @@ -18,6 +20,7 @@ TaskStatus as TaskStatus10, TaskState as TaskState10, ) + from a2a.compat.v0_3 import a2a_v0_3_pb2 @@ -44,15 +47,21 @@ def mock_handler(): @pytest.fixture def test_app(mock_handler): - mock_agent_card = MagicMock(spec=AgentCard) - mock_agent_card.url = 'http://mockurl.com' - # Set up capabilities.streaming to avoid validation issues - mock_agent_card.capabilities = MagicMock() - mock_agent_card.capabilities.streaming = False - mock_agent_card.capabilities.push_notifications = True - mock_agent_card.capabilities.extended_agent_card = True + agent_card = AgentCard( + name='TestAgent', + description='Test Description', + version='1.0.0', + capabilities=AgentCapabilities( + streaming=False, push_notifications=True, extended_agent_card=True + ), + ) + interface = agent_card.supported_interfaces.add() + interface.url = 'http://mockurl.com' + interface.protocol_binding = 'jsonrpc' + interface.protocol_version = '0.3' + jsonrpc_routes = create_jsonrpc_routes( - agent_card=mock_agent_card, + agent_card=agent_card, request_handler=mock_handler, enable_v0_3_compat=True, rpc_url='/', @@ -111,3 +120,25 @@ def test_get_task_v03_compat( assert 'result' in data assert data['result']['id'] == 'test_task_id' assert data['result']['status']['state'] == 'completed' + + +def test_get_extended_agent_card_v03_compat( + client: TestClient, +) -> None: + """Test that the v0.3 method name 'agent/getAuthenticatedExtendedCard' is correctly routed.""" + request_payload = { + 'jsonrpc': '2.0', + 'id': '3', + 'method': 'agent/getAuthenticatedExtendedCard', + 'params': {}, + } + + response = client.post('/', json=request_payload) + assert response.status_code == 200 + data = response.json() + + assert data['jsonrpc'] == '2.0' + assert data['id'] == '3' + assert 'result' in data + # The result should be a v0.3 AgentCard + assert 'supportsAuthenticatedExtendedCard' in data['result'] diff --git a/tests/compat/v0_3/test_jsonrpc_transport.py b/tests/compat/v0_3/test_jsonrpc_transport.py index 250608014..50b33e162 100644 --- a/tests/compat/v0_3/test_jsonrpc_transport.py +++ b/tests/compat/v0_3/test_jsonrpc_transport.py @@ -348,6 +348,39 @@ async def test_compat_jsonrpc_transport_get_extended_agent_card_not_supported( assert response == transport.agent_card +@pytest.mark.asyncio +async def test_compat_jsonrpc_transport_get_extended_agent_card_method_name( + transport, +): + """Verify the correct v0.3 method name 'agent/getAuthenticatedExtendedCard' is used.""" + captured_request: dict | None = None + + async def mock_send_request(data, *args, **kwargs): + nonlocal captured_request + captured_request = data + return { + 'result': { + 'name': 'ExtendedAgent', + 'url': 'http://agent', + 'version': '1.0.0', + 'description': 'Description', + 'skills': [], + 'defaultInputModes': [], + 'defaultOutputModes': [], + 'capabilities': {}, + 'supportsAuthenticatedExtendedCard': True, + } + } + + transport._send_request = mock_send_request + + req = GetExtendedAgentCardRequest() + await transport.get_extended_agent_card(req) + + assert captured_request is not None + assert captured_request['method'] == 'agent/getAuthenticatedExtendedCard' + + @pytest.mark.asyncio async def test_compat_jsonrpc_transport_close(transport, mock_httpx_client): await transport.close()