Skip to content

Commit c6730d3

Browse files
committed
make extended_card_modifier async
1 parent ffe31e2 commit c6730d3

4 files changed

Lines changed: 34 additions & 17 deletions

File tree

src/a2a/server/apps/rest/fastapi_app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22

3-
from collections.abc import Callable
3+
from collections.abc import Awaitable, Callable
44
from typing import TYPE_CHECKING, Any
55

66

@@ -51,7 +51,7 @@ def __init__( # noqa: PLR0913
5151
context_builder: CallContextBuilder | None = None,
5252
card_modifier: Callable[[AgentCard], AgentCard] | None = None,
5353
extended_card_modifier: Callable[
54-
[AgentCard, ServerCallContext], AgentCard
54+
[AgentCard, ServerCallContext], Awaitable[AgentCard]
5555
]
5656
| None = None,
5757
):
@@ -68,7 +68,7 @@ def __init__( # noqa: PLR0913
6868
ServerCallContext is passed.
6969
card_modifier: An optional callback to dynamically modify the public
7070
agent card before it is served.
71-
extended_card_modifier: An optional callback to dynamically modify
71+
extended_card_modifier: An optional async callback to dynamically modify
7272
the extended agent card before it is served. It receives the
7373
call context.
7474
"""

src/a2a/server/apps/rest/rest_adapter.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__( # noqa: PLR0913
6060
context_builder: CallContextBuilder | None = None,
6161
card_modifier: Callable[[AgentCard], AgentCard] | None = None,
6262
extended_card_modifier: Callable[
63-
[AgentCard, ServerCallContext], AgentCard
63+
[AgentCard, ServerCallContext], Awaitable[AgentCard]
6464
]
6565
| None = None,
6666
):
@@ -77,9 +77,9 @@ def __init__( # noqa: PLR0913
7777
ServerCallContext is passed.
7878
card_modifier: An optional callback to dynamically modify the public
7979
agent card before it is served.
80-
extended_card_modifier: An optional callback to dynamically modify
81-
the extended agent card before it is served. It receives the
82-
call context.
80+
extended_card_modifier: An optional async callback to dynamically
81+
modify the extended agent card before it is served. It receives
82+
the call context.
8383
"""
8484
if not _package_starlette_installed:
8585
raise ImportError(
@@ -182,7 +182,9 @@ async def handle_authenticated_agent_card(
182182

183183
if self.extended_card_modifier:
184184
context = self._context_builder.build(request)
185-
card_to_serve = self.extended_card_modifier(card_to_serve, context)
185+
card_to_serve = await self.extended_card_modifier(
186+
card_to_serve, context
187+
)
186188
elif self.card_modifier:
187189
card_to_serve = self.card_modifier(card_to_serve)
188190

src/a2a/utils/signing.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import json
2-
32
from collections.abc import Callable
43
from typing import Any, TypedDict
54

65
from a2a.utils.helpers import canonicalize_agent_card
76

8-
97
try:
108
import jwt
11-
129
from jwt.api_jwk import PyJWK
1310
from jwt.exceptions import PyJWTError
1411
from jwt.utils import base64url_decode, base64url_encode
@@ -66,7 +63,7 @@ def create_agent_card_signer(
6663
A callable that takes an AgentCard and returns the modified AgentCard with a signature.
6764
"""
6865

69-
def agent_card_signer(agent_card: AgentCard) -> AgentCard:
66+
async def agent_card_signer(agent_card: AgentCard) -> AgentCard:
7067
"""Signs agent card."""
7168
canonical_payload = canonicalize_agent_card(agent_card)
7269
payload_dict = json.loads(canonical_payload)

tests/server/apps/rest/test_rest_fastapi_app.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22

3+
from collections.abc import Awaitable, Callable
34
from typing import Any
45
from unittest.mock import MagicMock
56

@@ -13,6 +14,7 @@
1314
from a2a.server.apps.rest import fastapi_app, rest_adapter
1415
from a2a.server.apps.rest.fastapi_app import A2ARESTFastAPIApplication
1516
from a2a.server.apps.rest.rest_adapter import RESTAdapter
17+
from a2a.server.context import ServerCallContext
1618
from a2a.server.request_handlers.request_handler import RequestHandler
1719
from a2a.types import (
1820
AgentCard,
@@ -33,7 +35,7 @@
3335
async def agent_card() -> AgentCard:
3436
mock_agent_card = MagicMock(spec=AgentCard)
3537
mock_agent_card.url = 'http://mockurl.com'
36-
mock_agent_card.supports_authenticated_extended_card = False
38+
mock_agent_card.supports_authenticated_extended_card = True
3739

3840
# Mock the capabilities object with streaming disabled
3941
mock_capabilities = MagicMock()
@@ -58,6 +60,15 @@ async def streaming_agent_card() -> AgentCard:
5860
return mock_agent_card
5961

6062

63+
@pytest.fixture
64+
async def extended_card_modifier() -> Callable[
65+
[AgentCard, ServerCallContext], Awaitable[AgentCard]
66+
]:
67+
return MagicMock(
68+
spec=Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard]]
69+
)
70+
71+
6172
@pytest.fixture
6273
async def request_handler() -> RequestHandler:
6374
return MagicMock(spec=RequestHandler)
@@ -84,13 +95,20 @@ async def streaming_client(streaming_app: FastAPI) -> AsyncClient:
8495

8596
@pytest.fixture
8697
async def app(
87-
agent_card: AgentCard, request_handler: RequestHandler
98+
agent_card: AgentCard,
99+
request_handler: RequestHandler,
100+
extended_card_modifier: Callable[
101+
[AgentCard, ServerCallContext], Awaitable[AgentCard]
102+
],
88103
) -> FastAPI:
89104
"""Builds the FastAPI application for testing."""
90105

91-
return A2ARESTFastAPIApplication(agent_card, request_handler).build(
92-
agent_card_url='/well-known/agent.json', rpc_url=''
93-
)
106+
return A2ARESTFastAPIApplication(
107+
agent_card,
108+
request_handler,
109+
extended_agent_card=agent_card,
110+
extended_card_modifier=extended_card_modifier,
111+
).build(agent_card_url='/well-known/agent.json', rpc_url='')
94112

95113

96114
@pytest.fixture

0 commit comments

Comments
 (0)