Skip to content

Commit 1864526

Browse files
Merge branch '1.0-dev' into guglielmoc/refactor_server_call_context
2 parents 700ecf6 + 5d22186 commit 1864526

7 files changed

Lines changed: 88 additions & 25 deletions

File tree

.github/workflows/coverage-comment.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@ jobs:
1818
github.event.workflow_run.conclusion == 'success'
1919
steps:
2020
- name: Download Coverage Artifacts
21-
uses: actions/download-artifact@v4
21+
uses: actions/download-artifact@v8
2222
with:
2323
run-id: ${{ github.event.workflow_run.id }}
2424
github-token: ${{ secrets.A2A_BOT_PAT }}
2525
name: coverage-data
2626

2727
- name: Upload Coverage Report
2828
id: upload-report
29-
uses: actions/upload-artifact@v4
29+
uses: actions/upload-artifact@v7
3030
with:
3131
name: coverage-report
3232
path: coverage/
3333
retention-days: 14
3434

3535
- name: Post Comment
36-
uses: actions/github-script@v6
36+
uses: actions/github-script@v8
3737
env:
3838
ARTIFACT_URL: ${{ steps.upload-report.outputs.artifact-url }}
3939
with:

.github/workflows/spelling.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
name: Check Spelling
33
on:
4-
pull_request_target:
5-
branches: ["**"]
4+
pull_request:
5+
branches: ['**']
66
types: [opened, reopened, synchronize]
77
issue_comment:
88
types: [created]
@@ -11,7 +11,6 @@ jobs:
1111
name: Check Spelling
1212
permissions:
1313
contents: read
14-
pull-requests: read
1514
actions: read
1615
security-events: write
1716
outputs:
@@ -28,7 +27,7 @@ jobs:
2827
steps:
2928
- name: check-spelling
3029
id: spelling
31-
uses: check-spelling/check-spelling@main
30+
uses: check-spelling/check-spelling@a35147f799f30f8739c33f92222c847214e82e67 # https://github.com/check-spelling/check-spelling/issues/103#issuecomment-4181666219
3231
with:
3332
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
3433
checkout: true
@@ -75,6 +74,6 @@ jobs:
7574
cspell:sql/src/tsql.txt
7675
cspell:terraform/dict/terraform.txt
7776
cspell:typescript/dict/typescript.txt
78-
check_extra_dictionaries: ""
77+
check_extra_dictionaries: ''
7978
only_check_changed_files: true
80-
longest_word: "10"
79+
longest_word: '10'

.github/workflows/unit-tests.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
# Coverage comparison for PRs (only on Python 3.14 to avoid duplicate work)
6060
- name: Checkout Base Branch
6161
if: github.event_name == 'pull_request' && matrix.python-version == '3.14'
62-
uses: actions/checkout@v4
62+
uses: actions/checkout@v6
6363
with:
6464
ref: ${{ github.event.pull_request.base.ref || 'main' }}
6565
clean: true
@@ -75,7 +75,7 @@ jobs:
7575
7676
- name: Checkout PR Branch (Restore)
7777
if: github.event_name == 'pull_request' && matrix.python-version == '3.14'
78-
uses: actions/checkout@v4
78+
uses: actions/checkout@v6
7979
with:
8080
clean: true
8181

@@ -93,7 +93,7 @@ jobs:
9393
echo ${{ github.event.pull_request.base.ref || 'main' }} > ./BASE_BRANCH
9494
9595
- name: Upload Coverage Artifacts
96-
uses: actions/upload-artifact@v4
96+
uses: actions/upload-artifact@v7
9797
if: github.event_name == 'pull_request' && matrix.python-version == '3.14'
9898
with:
9999
name: coverage-data
@@ -111,7 +111,7 @@ jobs:
111111
run: uv run pytest --cov=a2a --cov-report term --cov-fail-under=88
112112

113113
- name: Upload Artifact (base)
114-
uses: actions/upload-artifact@v4
114+
uses: actions/upload-artifact@v7
115115
if: github.event_name != 'pull_request' && matrix.python-version == '3.14'
116116
with:
117117
name: coverage-report

src/a2a/compat/v0_3/jsonrpc_adapter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class JSONRPC03Adapter:
6262
'tasks/pushNotificationConfig/list': types_v03.ListTaskPushNotificationConfigRequest,
6363
'tasks/pushNotificationConfig/delete': types_v03.DeleteTaskPushNotificationConfigRequest,
6464
'tasks/resubscribe': types_v03.TaskResubscriptionRequest,
65-
'agent/authenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest,
65+
'agent/getAuthenticatedExtendedCard': types_v03.GetAuthenticatedExtendedCardRequest,
6666
}
6767

6868
def __init__( # noqa: PLR0913
@@ -224,7 +224,7 @@ async def _process_non_streaming_request(
224224
id=request_id, result=None
225225
)
226226
)
227-
elif method == 'agent/authenticatedExtendedCard':
227+
elif method == 'agent/getAuthenticatedExtendedCard':
228228
res_card = await self.get_authenticated_extended_card(
229229
request_obj, context
230230
)
@@ -247,7 +247,7 @@ async def get_authenticated_extended_card(
247247
request: types_v03.GetAuthenticatedExtendedCardRequest,
248248
context: ServerCallContext,
249249
) -> types_v03.AgentCard:
250-
"""Handles the 'agent/authenticatedExtendedCard' JSON-RPC method."""
250+
"""Handles the 'agent/getAuthenticatedExtendedCard' JSON-RPC method."""
251251
if not self.agent_card.capabilities.extended_agent_card:
252252
raise ExtendedAgentCardNotConfiguredError(
253253
message='Authenticated card not supported'

src/a2a/compat/v0_3/jsonrpc_transport.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ async def get_extended_agent_card(
376376
return card
377377

378378
rpc_request = JSONRPC20Request(
379-
method='agent/authenticatedExtendedCard',
379+
method='agent/getAuthenticatedExtendedCard',
380380
params={},
381381
_id=str(uuid4()),
382382
)

tests/compat/v0_3/test_jsonrpc_app_compat.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111
from a2a.server.request_handlers.request_handler import RequestHandler
1212
from a2a.types.a2a_pb2 import (
1313
AgentCard,
14+
AgentCapabilities,
15+
AgentInterface,
1416
Message as Message10,
1517
Part as Part10,
1618
Role as Role10,
1719
Task as Task10,
1820
TaskStatus as TaskStatus10,
1921
TaskState as TaskState10,
2022
)
23+
2124
from a2a.compat.v0_3 import a2a_v0_3_pb2
2225

2326

@@ -44,15 +47,21 @@ def mock_handler():
4447

4548
@pytest.fixture
4649
def test_app(mock_handler):
47-
mock_agent_card = MagicMock(spec=AgentCard)
48-
mock_agent_card.url = 'http://mockurl.com'
49-
# Set up capabilities.streaming to avoid validation issues
50-
mock_agent_card.capabilities = MagicMock()
51-
mock_agent_card.capabilities.streaming = False
52-
mock_agent_card.capabilities.push_notifications = True
53-
mock_agent_card.capabilities.extended_agent_card = True
50+
agent_card = AgentCard(
51+
name='TestAgent',
52+
description='Test Description',
53+
version='1.0.0',
54+
capabilities=AgentCapabilities(
55+
streaming=False, push_notifications=True, extended_agent_card=True
56+
),
57+
)
58+
interface = agent_card.supported_interfaces.add()
59+
interface.url = 'http://mockurl.com'
60+
interface.protocol_binding = 'jsonrpc'
61+
interface.protocol_version = '0.3'
62+
5463
jsonrpc_routes = create_jsonrpc_routes(
55-
agent_card=mock_agent_card,
64+
agent_card=agent_card,
5665
request_handler=mock_handler,
5766
enable_v0_3_compat=True,
5867
rpc_url='/',
@@ -111,3 +120,25 @@ def test_get_task_v03_compat(
111120
assert 'result' in data
112121
assert data['result']['id'] == 'test_task_id'
113122
assert data['result']['status']['state'] == 'completed'
123+
124+
125+
def test_get_extended_agent_card_v03_compat(
126+
client: TestClient,
127+
) -> None:
128+
"""Test that the v0.3 method name 'agent/getAuthenticatedExtendedCard' is correctly routed."""
129+
request_payload = {
130+
'jsonrpc': '2.0',
131+
'id': '3',
132+
'method': 'agent/getAuthenticatedExtendedCard',
133+
'params': {},
134+
}
135+
136+
response = client.post('/', json=request_payload)
137+
assert response.status_code == 200
138+
data = response.json()
139+
140+
assert data['jsonrpc'] == '2.0'
141+
assert data['id'] == '3'
142+
assert 'result' in data
143+
# The result should be a v0.3 AgentCard
144+
assert 'supportsAuthenticatedExtendedCard' in data['result']

tests/compat/v0_3/test_jsonrpc_transport.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,39 @@ async def test_compat_jsonrpc_transport_get_extended_agent_card_not_supported(
348348
assert response == transport.agent_card
349349

350350

351+
@pytest.mark.asyncio
352+
async def test_compat_jsonrpc_transport_get_extended_agent_card_method_name(
353+
transport,
354+
):
355+
"""Verify the correct v0.3 method name 'agent/getAuthenticatedExtendedCard' is used."""
356+
captured_request: dict | None = None
357+
358+
async def mock_send_request(data, *args, **kwargs):
359+
nonlocal captured_request
360+
captured_request = data
361+
return {
362+
'result': {
363+
'name': 'ExtendedAgent',
364+
'url': 'http://agent',
365+
'version': '1.0.0',
366+
'description': 'Description',
367+
'skills': [],
368+
'defaultInputModes': [],
369+
'defaultOutputModes': [],
370+
'capabilities': {},
371+
'supportsAuthenticatedExtendedCard': True,
372+
}
373+
}
374+
375+
transport._send_request = mock_send_request
376+
377+
req = GetExtendedAgentCardRequest()
378+
await transport.get_extended_agent_card(req)
379+
380+
assert captured_request is not None
381+
assert captured_request['method'] == 'agent/getAuthenticatedExtendedCard'
382+
383+
351384
@pytest.mark.asyncio
352385
async def test_compat_jsonrpc_transport_close(transport, mock_httpx_client):
353386
await transport.close()

0 commit comments

Comments
 (0)