Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/a2a/server/request_handlers/rest_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ async def list_tasks(
proto_utils.parse_params(request.query_params, params)

result = await self.request_handler.on_list_tasks(params, context)
return MessageToDict(result)
return MessageToDict(result, always_print_fields_with_no_presence=True)
Comment thread
guglielmo-san marked this conversation as resolved.

async def list_push_notifications(
self,
Expand Down
70 changes: 64 additions & 6 deletions tck/sut_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@

from datetime import datetime, timezone

import grpc.aio
import uvicorn

from starlette.applications import Starlette

import a2a.compat.v0_3.a2a_v0_3_pb2_grpc as a2a_v0_3_grpc
import a2a.types.a2a_pb2_grpc as a2a_grpc

from a2a.compat.v0_3.grpc_handler import CompatGrpcHandler
from a2a.server.agent_execution.agent_executor import AgentExecutor
from a2a.server.agent_execution.context import RequestContext
from a2a.server.apps import A2AStarletteApplication
from a2a.server.apps import (
A2ARESTFastAPIApplication,
A2AStarletteApplication,
)
from a2a.server.events.event_queue import EventQueue
from a2a.server.request_handlers.default_request_handler import (
DefaultRequestHandler,
)
from a2a.server.request_handlers.grpc_handler import GrpcHandler
from a2a.server.tasks.inmemory_task_store import InMemoryTaskStore
from a2a.server.tasks.task_store import TaskStore
from a2a.types import (
Expand All @@ -32,6 +43,7 @@


JSONRPC_URL = '/a2a/jsonrpc'
REST_URL = '/a2a/rest'

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('SUTAgent')
Expand Down Expand Up @@ -133,14 +145,26 @@ def serve(task_store: TaskStore) -> None:
"""Sets up the A2A service and starts the HTTP server."""
http_port = int(os.environ.get('HTTP_PORT', '41241'))

grpc_port = int(os.environ.get('GRPC_PORT', '50051'))
Comment thread
guglielmo-san marked this conversation as resolved.

agent_card = AgentCard(
name='SUT Agent',
description='An agent to be used as SUT against TCK tests.',
supported_interfaces=[
AgentInterface(
url=f'http://localhost:{http_port}{JSONRPC_URL}',
protocol_binding='JSONRPC',
protocol_version='0.3.0',
protocol_version='1.0.0',
),
AgentInterface(
url=f'http://localhost:{http_port}{REST_URL}',
protocol_binding='REST',
protocol_version='1.0.0',
),
AgentInterface(
url=f'http://localhost:{grpc_port}',
protocol_binding='GRPC',
protocol_version='1.0.0',
),
],
provider=AgentProvider(
Expand Down Expand Up @@ -172,15 +196,49 @@ def serve(task_store: TaskStore) -> None:
task_store=task_store,
)

server = A2AStarletteApplication(
main_app = Starlette()

# JSONRPC
jsonrpc_server = A2AStarletteApplication(
agent_card=agent_card,
http_handler=request_handler,
)
jsonrpc_server.add_routes_to_app(main_app, rpc_url=JSONRPC_URL)

app = server.build(rpc_url=JSONRPC_URL)
# REST
rest_server = A2ARESTFastAPIApplication(
agent_card=agent_card,
http_handler=request_handler,
)
rest_app = rest_server.build(rpc_url=REST_URL)
main_app.mount('', rest_app)

config = uvicorn.Config(
main_app, host='127.0.0.1', port=http_port, log_level='info'
)
uvicorn_server = uvicorn.Server(config)

# GRPC
grpc_server = grpc.aio.server()
grpc_server.add_insecure_port(f'[::]:{grpc_port}')
servicer = GrpcHandler(agent_card, request_handler)
compat_servicer = CompatGrpcHandler(agent_card, request_handler)
a2a_grpc.add_A2AServiceServicer_to_server(servicer, grpc_server)
a2a_v0_3_grpc.add_A2AServiceServicer_to_server(compat_servicer, grpc_server)

logger.info(
'Starting HTTP server on port %s and gRPC on port %s...',
http_port,
grpc_port,
)

logger.info('Starting HTTP server on port %s...', http_port)
uvicorn.run(app, host='127.0.0.1', port=http_port, log_level='info')
loop = asyncio.get_event_loop()
loop.run_until_complete(grpc_server.start())
loop.run_until_complete(
asyncio.gather(
uvicorn_server.serve(), grpc_server.wait_for_termination()
)
)


def main() -> None:
Expand Down
Loading