Skip to content

Commit 30466c4

Browse files
committed
wip
1 parent fdc2156 commit 30466c4

12 files changed

Lines changed: 85 additions & 76 deletions

File tree

src/a2a/compat/v0_3/grpc_handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from a2a.server.context import ServerCallContext
2424
from a2a.server.request_handlers.grpc_handler import (
2525
_ERROR_CODE_MAP,
26-
GrpcUserBuilder,
26+
GrpcContextBuilder,
2727
build_grpc_server_call_context,
2828
default_grpc_user_builder,
2929
)
@@ -45,7 +45,7 @@ def __init__(
4545
self,
4646
agent_card: AgentCard,
4747
request_handler: RequestHandler,
48-
user_builder: GrpcUserBuilder | None = None,
48+
context_builder: GrpcContextBuilder | None = None,
4949
card_modifier: Callable[[AgentCard], Awaitable[AgentCard] | AgentCard]
5050
| None = None,
5151
):
@@ -55,14 +55,14 @@ def __init__(
5555
agent_card: The AgentCard describing the agent's capabilities (v1.0).
5656
request_handler: The underlying `RequestHandler` instance to
5757
delegate requests to.
58-
user_builder: Optional custom user builder to extract user from the
58+
context_builder: Optional custom user builder to extract user from the
5959
gRPC context.
6060
card_modifier: An optional callback to dynamically modify the public
6161
agent card before it is served.
6262
"""
6363
self.agent_card = agent_card
6464
self.handler03 = RequestHandler03(request_handler=request_handler)
65-
self.user_builder = user_builder or default_grpc_user_builder
65+
self.user_builder =context_builder or default_grpc_user_builder
6666
self.card_modifier = card_modifier
6767

6868
async def _handle_unary(

src/a2a/compat/v0_3/jsonrpc_adapter.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@
3838
JSONRPCError as CoreJSONRPCError,
3939
)
4040
from a2a.server.routes.common import (
41-
UserBuilder,
42-
build_server_call_context,
43-
default_user_builder,
41+
ContextBuilder,
42+
DefaultContextBuilder,
4443
)
4544
from a2a.utils import constants
4645
from a2a.utils.errors import ExtendedAgentCardNotConfiguredError
@@ -71,7 +70,7 @@ def __init__( # noqa: PLR0913
7170
agent_card: 'AgentCard',
7271
http_handler: 'RequestHandler',
7372
extended_agent_card: 'AgentCard | None' = None,
74-
user_builder: 'UserBuilder | None' = None,
73+
context_builder: 'ContextBuilder | None' = None,
7574
card_modifier: 'Callable[[AgentCard], Awaitable[AgentCard] | AgentCard] | None' = None,
7675
extended_card_modifier: 'Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard] | AgentCard] | None' = None,
7776
):
@@ -82,7 +81,7 @@ def __init__( # noqa: PLR0913
8281
self.handler = RequestHandler03(
8382
request_handler=http_handler,
8483
)
85-
self._user_builder = user_builder or default_user_builder
84+
self._context_builder = context_builder or DefaultContextBuilder()
8685

8786
def supports_method(self, method: str) -> bool:
8887
"""Returns True if the v0.3 adapter supports the given method name."""
@@ -130,9 +129,7 @@ async def handle_request(
130129
CoreInvalidRequestError(data=str(e)),
131130
)
132131

133-
call_context = build_server_call_context(
134-
request, self._user_builder
135-
)
132+
call_context = self._context_builder.build(request)
136133
call_context.tenant = (
137134
getattr(specific_request.params, 'tenant', '')
138135
if hasattr(specific_request, 'params')

src/a2a/compat/v0_3/rest_adapter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from a2a.compat.v0_3.rest_handler import REST03Handler
3636
from a2a.server.context import ServerCallContext
3737
from a2a.server.routes.common import (
38-
UserBuilder,
38+
ContextBuilder,
3939
build_server_call_context,
4040
default_user_builder,
4141
)
@@ -64,7 +64,7 @@ def __init__( # noqa: PLR0913
6464
agent_card: 'AgentCard',
6565
http_handler: 'RequestHandler',
6666
extended_agent_card: 'AgentCard | None' = None,
67-
user_builder: 'UserBuilder | None' = None,
67+
context_builder: 'ContextBuilder | None' = None,
6868
card_modifier: 'Callable[[AgentCard], Awaitable[AgentCard] | AgentCard] | None' = None,
6969
extended_card_modifier: 'Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard] | AgentCard] | None' = None,
7070
):
@@ -75,7 +75,7 @@ def __init__( # noqa: PLR0913
7575
self.handler = REST03Handler(
7676
agent_card=agent_card, request_handler=http_handler
7777
)
78-
self._user_builder = user_builder or default_user_builder
78+
self._user_builder =context_builder or default_user_builder
7979

8080
@rest_error_handler
8181
async def _handle_request(

src/a2a/server/request_handlers/grpc_handler.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
logger = logging.getLogger(__name__)
4242

43-
GrpcUserBuilder = Callable[[grpc.aio.ServicerContext], User]
43+
GrpcContextBuilder = Callable[[grpc.aio.ServicerContext], User]
4444

4545

4646
def default_grpc_user_builder(context: grpc.aio.ServicerContext) -> User:
@@ -64,10 +64,10 @@ def _get_metadata_value(
6464

6565

6666
def build_grpc_server_call_context(
67-
context: grpc.aio.ServicerContext, user_builder: GrpcUserBuilder
67+
context: grpc.aio.ServicerContext,context_builder: GrpcContextBuilder
6868
) -> ServerCallContext:
6969
"""Builds a ServerCallContext from a gRPC ServicerContext."""
70-
user = user_builder(context)
70+
user =context_builder(context)
7171
state = {'grpc_context': context}
7272
return ServerCallContext(
7373
user=user,
@@ -105,7 +105,7 @@ def __init__(
105105
self,
106106
agent_card: AgentCard,
107107
request_handler: RequestHandler,
108-
user_builder: GrpcUserBuilder | None = None,
108+
context_builder: GrpcContextBuilder | None = None,
109109
card_modifier: Callable[[AgentCard], Awaitable[AgentCard] | AgentCard]
110110
| None = None,
111111
):
@@ -115,14 +115,14 @@ def __init__(
115115
agent_card: The AgentCard describing the agent's capabilities.
116116
request_handler: The underlying `RequestHandler` instance to
117117
delegate requests to.
118-
user_builder: Optional custom user builder to extract user from the
118+
context_builder: Optional custom user builder to extract user from the
119119
gRPC context.
120120
card_modifier: An optional callback to dynamically modify the public
121121
agent card before it is served.
122122
"""
123123
self.agent_card = agent_card
124124
self.request_handler = request_handler
125-
self.user_builder = user_builder or default_grpc_user_builder
125+
self.user_builder =context_builder or default_grpc_user_builder
126126
self.card_modifier = card_modifier
127127

128128
async def _handle_unary(

src/a2a/server/routes/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""A2A Routes."""
22

33
from a2a.server.routes.agent_card_routes import create_agent_card_routes
4-
from a2a.server.routes.common import UserBuilder
4+
from a2a.server.routes.common import ContextBuilder
55
from a2a.server.routes.jsonrpc_routes import create_jsonrpc_routes
66
from a2a.server.routes.rest_routes import create_rest_routes
77

88

99
__all__ = [
10-
'UserBuilder',
10+
'ContextBuilder',
1111
'create_agent_card_routes',
1212
'create_jsonrpc_routes',
1313
'create_rest_routes',

src/a2a/server/routes/common.py

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from abc import ABC, abstractmethod
12
from collections.abc import Callable
23
from typing import TYPE_CHECKING, Any
34

@@ -20,10 +21,6 @@
2021
)
2122
from a2a.server.context import ServerCallContext
2223

23-
24-
UserBuilder = Callable[[Request], User]
25-
26-
2724
class StarletteUser(User):
2825
"""Adapts a Starlette BaseUser to the A2A User interface."""
2926

@@ -41,36 +38,52 @@ def user_name(self) -> str:
4138
return self._user.display_name
4239

4340

44-
def default_user_builder(request: Request) -> User:
45-
"""Default strategy for creating an A2AUser from a Starlette Request."""
46-
if 'user' in request.scope:
47-
return StarletteUser(request.user)
48-
return UnauthenticatedUser()
41+
class ContextBuilder(ABC):
42+
"""A class for building ServerCallContexts using the Starlette Request."""
43+
44+
@abstractmethod
45+
def build(self, request: Request) -> ServerCallContext:
46+
"""Builds a ServerCallContext from a Starlette Request."""
47+
48+
@abstractmethod
49+
def build_user(self, request: Request) -> User:
50+
"""Builds a User from a Starlette Request."""
51+
52+
53+
class DefaultContextBuilder(ContextBuilder):
54+
"""A default implementation of ContextBuilder."""
4955

56+
def build(self, request: Request) -> ServerCallContext:
57+
"""Builds a ServerCallContext from a Starlette Request.
5058
51-
def build_server_call_context(
52-
request: Request, user_builder: UserBuilder
53-
) -> ServerCallContext:
54-
"""Builds a ServerCallContext from a Starlette Request.
59+
Args:
60+
request: The incoming Starlette Request object.
5561
56-
Args:
57-
request: The incoming Starlette Request object.
58-
user_builder: A callable that creates a User from the request.
62+
Returns:
63+
A ServerCallContext instance populated with user and state
64+
information from the request.
65+
"""
66+
state = {}
67+
if 'auth' in request.scope:
68+
state['auth'] = request.auth
69+
state['headers'] = dict(request.headers)
70+
return ServerCallContext(
71+
user=self.build_user(request),
72+
state=state,
73+
requested_extensions=get_requested_extensions(
74+
request.headers.getlist(HTTP_EXTENSION_HEADER)
75+
),
76+
)
5977

60-
Returns:
61-
A ServerCallContext instance populated with user and state.
62-
"""
63-
user = user_builder(request)
78+
def build_user(self, request: Request) -> User:
79+
"""Builds a User from a Starlette Request.
6480
65-
state = {}
66-
if 'auth' in request.scope:
67-
state['auth'] = request.auth
68-
state['headers'] = dict(request.headers)
81+
Args:
82+
request: The incoming Starlette Request object.
6983
70-
return ServerCallContext(
71-
user=user,
72-
state=state,
73-
requested_extensions=get_requested_extensions(
74-
request.headers.getlist(HTTP_EXTENSION_HEADER)
75-
),
76-
)
84+
Returns:
85+
A User instance populated with user information from the request.
86+
"""
87+
if 'user' in request.scope:
88+
return StarletteUser(request.user)
89+
return UnauthenticatedUser()

src/a2a/server/routes/jsonrpc_dispatcher.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@
2828
build_error_response,
2929
)
3030
from a2a.server.routes.common import (
31-
UserBuilder,
32-
build_server_call_context,
33-
default_user_builder,
31+
ContextBuilder,
32+
3433
)
3534
from a2a.types import A2ARequest
3635
from a2a.types.a2a_pb2 import (
@@ -145,7 +144,7 @@ def __init__( # noqa: PLR0913
145144
agent_card: AgentCard,
146145
request_handler: RequestHandler,
147146
extended_agent_card: AgentCard | None = None,
148-
user_builder: UserBuilder | None = None,
147+
context_builder: ContextBuilder | None = None,
149148
card_modifier: Callable[[AgentCard], Awaitable[AgentCard] | AgentCard]
150149
| None = None,
151150
extended_card_modifier: Callable[
@@ -162,7 +161,7 @@ def __init__( # noqa: PLR0913
162161
requests via http.
163162
extended_agent_card: An optional, distinct AgentCard to be served
164163
at the authenticated extended card endpoint.
165-
user_builder: Optional custom user builder to extract user from the
164+
context_builder: Optional custom user builder to extract user from the
166165
request.
167166
card_modifier: An optional callback to dynamically modify the public
168167
agent card before it is served.
@@ -183,7 +182,7 @@ def __init__( # noqa: PLR0913
183182
self.extended_agent_card = extended_agent_card
184183
self.card_modifier = card_modifier
185184
self.extended_card_modifier = extended_card_modifier
186-
self._user_builder = user_builder or default_user_builder
185+
self._context_builder = context_builder or DefaultContextBuilder()
187186
self.enable_v0_3_compat = enable_v0_3_compat
188187
self._v03_adapter: JSONRPC03Adapter | None = None
189188

@@ -192,7 +191,7 @@ def __init__( # noqa: PLR0913
192191
agent_card=agent_card,
193192
http_handler=request_handler,
194193
extended_agent_card=extended_agent_card,
195-
user_builder=self._user_builder,
194+
context_builder=self._context_builder,
196195
card_modifier=card_modifier,
197196
extended_card_modifier=extended_card_modifier,
198197
)

src/a2a/server/routes/jsonrpc_routes.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from a2a.server.context import ServerCallContext
2121
from a2a.server.request_handlers.request_handler import RequestHandler
22-
from a2a.server.routes.common import UserBuilder
22+
from a2a.server.routes.common import ContextBuilder
2323
from a2a.server.routes.jsonrpc_dispatcher import JsonRpcDispatcher
2424
from a2a.types.a2a_pb2 import AgentCard
2525

@@ -29,7 +29,7 @@ def create_jsonrpc_routes( # noqa: PLR0913
2929
request_handler: RequestHandler,
3030
rpc_url: str,
3131
extended_agent_card: AgentCard | None = None,
32-
user_builder: UserBuilder | None = None,
32+
context_builder: ContextBuilder | None = None,
3333
card_modifier: Callable[[AgentCard], Awaitable[AgentCard] | AgentCard]
3434
| None = None,
3535
extended_card_modifier: Callable[
@@ -51,7 +51,7 @@ def create_jsonrpc_routes( # noqa: PLR0913
5151
rpc_url: The URL prefix for the RPC endpoints.
5252
extended_agent_card: An optional, distinct AgentCard to be served
5353
at the authenticated extended card endpoint.
54-
user_builder: Optional custom user builder to extract user from the
54+
context_builder: Optional custom context builder to extract user from the
5555
request.
5656
card_modifier: An optional callback to dynamically modify the public
5757
agent card before it is served.
@@ -71,7 +71,7 @@ def create_jsonrpc_routes( # noqa: PLR0913
7171
agent_card=agent_card,
7272
request_handler=request_handler,
7373
extended_agent_card=extended_agent_card,
74-
user_builder=user_builder,
74+
context_builder=context_builder,
7575
card_modifier=card_modifier,
7676
extended_card_modifier=extended_card_modifier,
7777
enable_v0_3_compat=enable_v0_3_compat,

src/a2a/server/routes/rest_dispatcher.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from a2a.server.context import ServerCallContext
1010
from a2a.server.request_handlers.request_handler import RequestHandler
1111
from a2a.server.routes.common import (
12-
UserBuilder,
12+
ContextBuilder,
1313
build_server_call_context,
1414
default_user_builder,
1515
)
@@ -72,7 +72,7 @@ def __init__( # noqa: PLR0913
7272
agent_card: AgentCard,
7373
request_handler: RequestHandler,
7474
extended_agent_card: AgentCard | None = None,
75-
user_builder: UserBuilder | None = None,
75+
context_builder: ContextBuilder | None = None,
7676
card_modifier: Callable[[AgentCard], Awaitable[AgentCard] | AgentCard]
7777
| None = None,
7878
extended_card_modifier: Callable[
@@ -87,7 +87,7 @@ def __init__( # noqa: PLR0913
8787
request_handler: The underlying `RequestHandler` instance to delegate requests to.
8888
extended_agent_card: An optional, distinct AgentCard to be served
8989
at the authenticated extended card endpoint.
90-
user_builder: Optional custom user builder to extract user from the
90+
context_builder: Optional custom user builder to extract user from the
9191
request.
9292
card_modifier: An optional callback to dynamically modify the public
9393
agent card before it is served.
@@ -106,7 +106,7 @@ def __init__( # noqa: PLR0913
106106
self.extended_agent_card = extended_agent_card
107107
self.card_modifier = card_modifier
108108
self.extended_card_modifier = extended_card_modifier
109-
self._user_builder = user_builder or default_user_builder
109+
self._user_builder =context_builder or default_user_builder
110110
self.request_handler = request_handler
111111

112112
def _build_call_context(self, request: Request) -> ServerCallContext:

0 commit comments

Comments
 (0)