From 898119c21bfbb345495f5f847646339ecdfbd59a Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Mon, 2 Feb 2026 22:26:51 +0100 Subject: [PATCH 1/4] refactor: Update to Protocol V1 and fix all tests Signed-off-by: Luca Muscariello --- .github/actions/spelling/allow.txt | 68 ++--- .github/workflows/linter.yaml | 4 +- .github/workflows/unit-tests.yml | 6 +- buf.gen.yaml | 2 +- pyproject.toml | 7 +- pyrightconfig.json | 13 + scripts/gen_proto.sh | 2 +- src/a2a/client/auth/interceptor.py | 4 +- src/a2a/client/base_client.py | 4 +- src/a2a/client/client.py | 4 +- src/a2a/client/client_factory.py | 1 - src/a2a/client/transports/base.py | 4 +- src/a2a/client/transports/grpc.py | 6 +- src/a2a/client/transports/jsonrpc.py | 8 +- src/a2a/client/transports/rest.py | 22 +- .../server/agent_execution/agent_executor.py | 2 +- src/a2a/server/apps/jsonrpc/fastapi_app.py | 7 +- src/a2a/server/apps/jsonrpc/jsonrpc_app.py | 15 +- src/a2a/server/events/event_consumer.py | 24 +- src/a2a/server/jsonrpc_models.py | 24 +- src/a2a/server/models.py | 6 +- .../default_request_handler.py | 46 +-- .../server/request_handlers/grpc_handler.py | 8 +- .../request_handlers/jsonrpc_handler.py | 6 +- .../request_handlers/request_handler.py | 4 +- .../request_handlers/response_helpers.py | 2 +- .../server/request_handlers/rest_handler.py | 13 +- src/a2a/server/tasks/database_task_store.py | 6 +- src/a2a/server/tasks/task_updater.py | 27 +- src/a2a/types/__init__.py | 20 +- src/a2a/types/a2a_pb2.py | 284 ++++++++++-------- src/a2a/types/a2a_pb2.pyi | 200 ++++++------ src/a2a/types/a2a_pb2_grpc.py | 24 +- src/a2a/utils/artifact.py | 8 +- src/a2a/utils/constants.py | 4 + src/a2a/utils/error_handlers.py | 13 +- src/a2a/utils/errors.py | 51 +++- src/a2a/utils/parts.py | 17 +- src/a2a/utils/telemetry.py | 4 +- tests/client/test_auth_middleware.py | 10 +- tests/client/test_client_factory.py | 1 - tests/client/test_client_task_manager.py | 2 - tests/client/transports/test_grpc_client.py | 88 +++--- .../client/transports/test_jsonrpc_client.py | 16 +- .../test_default_push_notification_support.py | 16 +- tests/extensions/test_common.py | 15 +- .../test_client_server_integration.py | 52 ++-- .../server/apps/jsonrpc/test_serialization.py | 2 +- tests/server/events/test_event_consumer.py | 11 +- tests/server/events/test_event_queue.py | 1 - .../test_default_request_handler.py | 153 ++++------ .../request_handlers/test_grpc_handler.py | 8 +- .../request_handlers/test_jsonrpc_handler.py | 102 +++---- tests/server/tasks/test_result_aggregator.py | 2 +- tests/server/tasks/test_task_manager.py | 5 - tests/server/tasks/test_task_updater.py | 50 +-- tests/server/test_integration.py | 51 ++-- tests/test_types.py | 106 +++---- tests/utils/test_artifact.py | 5 +- tests/utils/test_message.py | 5 +- tests/utils/test_parts.py | 46 +-- 61 files changed, 879 insertions(+), 838 deletions(-) create mode 100644 pyrightconfig.json diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index f82b16507..b7e78fb2e 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -1,13 +1,22 @@ +a2a A2A A2AFastAPI AAgent -ACMRTUXB ACard AClient +ACMRTUXB +aconnect +adk AError AException AFast +agentic AGrpc +aio +aiomysql +alg +amannn +aproject ARequest ARun AServer @@ -15,39 +24,6 @@ AServers AService AStarlette AUser -DSNs -ES256 -EUR -FastAPI -GBP -GVsb -HS256 -HS384 -INR -JOSE -JPY -JSONRPC -JSONRPCt -JWS -Llm -OpenAPI -POSTGRES -Protobuf -RS256 -RUF -SECP256R1 -SLF -Starlette -Tful -a2a -aconnect -adk -agentic -aio -aiomysql -alg -amannn -aproject autouse backticks base64url @@ -60,30 +36,45 @@ coro datamodel deepwiki drivername +DSNs dunders +ES256 euo +EUR excinfo +FastAPI fernet fetchrow fetchval +GBP genai getkwargs gle +GVsb hazmat +HS256 +HS384 ietf importlib initdb inmemory +INR isready jku +JOSE +JPY +JSONRPC +JSONRPCt jwk jwks jws +JWS kid kwarg langgraph lifecycles linting +Llm lstrips middleware mikeas @@ -91,15 +82,18 @@ mockurl notif oauthoidc oidc +OpenAPI openapiv openapiv2 opensource otherurl pb2 postgres +POSTGRES postgresql proto protobuf +Protobuf protoc pydantic pyi @@ -109,13 +103,19 @@ pyversions redef respx resub +RS256 +RUF +SECP256R1 +SLF socio sse starlette +Starlette swagger tagwords taskupdate testuuid +Tful tiangolo typ typeerror diff --git a/.github/workflows/linter.yaml b/.github/workflows/linter.yaml index 97bba6b6d..b0ddd9e08 100644 --- a/.github/workflows/linter.yaml +++ b/.github/workflows/linter.yaml @@ -2,7 +2,7 @@ name: Lint Code Base on: pull_request: - branches: [main] + branches: [main, 1.0-a2a_proto_refactor] permissions: contents: read jobs: @@ -22,6 +22,8 @@ jobs: - name: Add uv to PATH run: | echo "$HOME/.cargo/bin" >> $GITHUB_PATH + - name: Install Buf + uses: bufbuild/buf-setup-action@v1 - name: Install dependencies run: uv sync --dev diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index eb5b3d1f8..def446b9e 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -2,7 +2,7 @@ name: Run Unit Tests on: pull_request: - branches: [main] + branches: [main, 1.0-a2a_proto_refactor] permissions: contents: read jobs: @@ -36,7 +36,7 @@ jobs: strategy: matrix: - python-version: ['3.10', '3.13'] + python-version: ["3.10", "3.13"] steps: - name: Checkout code uses: actions/checkout@v6 @@ -52,6 +52,8 @@ jobs: - name: Add uv to PATH run: | echo "$HOME/.cargo/bin" >> $GITHUB_PATH + - name: Install Buf + uses: bufbuild/buf-setup-action@v1 - name: Install dependencies run: uv sync --dev --extra all - name: Run tests and check coverage diff --git a/buf.gen.yaml b/buf.gen.yaml index 0dd9a4d78..85106a5ee 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -3,7 +3,7 @@ version: v2 inputs: - git_repo: https://github.com/a2aproject/A2A.git ref: main - subdir: specification/grpc + subdir: specification managed: enabled: true # Python Generation diff --git a/pyproject.toml b/pyproject.toml index 7bfb59b34..5a0c9f6b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,6 +148,7 @@ follow_imports = "skip" [tool.pyright] include = ["src"] +ignore = ["src/a2a/types"] exclude = [ "**/__pycache__", "**/dist", @@ -155,11 +156,9 @@ exclude = [ "**/node_modules", "**/venv", "**/.venv", - "src/a2a/types/a2a_pb2.py", - "src/a2a/types/a2a_pb2_grpc.py", ] -reportMissingImports = "none" -reportMissingModuleSource = "none" +venvPath = "." +venv = ".venv" [tool.coverage.run] branch = true diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 000000000..89667a3c2 --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,13 @@ +{ + "venvPath": ".", + "venv": ".venv", + "include": [ + "src" + ], + "exclude": [ + "**/__pycache__", + "src/a2a/types" + ], + "reportMissingImports": false, + "reportMissingModuleSource": false +} diff --git a/scripts/gen_proto.sh b/scripts/gen_proto.sh index 1a1f84ea3..90cb8378f 100755 --- a/scripts/gen_proto.sh +++ b/scripts/gen_proto.sh @@ -18,4 +18,4 @@ fi # Fix imports in generated grpc file echo "Fixing imports in src/a2a/types/a2a_pb2_grpc.py" -sed -i '' 's/import a2a_pb2 as a2a__pb2/from . import a2a_pb2 as a2a__pb2/g' src/a2a/types/a2a_pb2_grpc.py +sed 's/import a2a_pb2 as a2a__pb2/from . import a2a_pb2 as a2a__pb2/g' src/a2a/types/a2a_pb2_grpc.py > src/a2a/types/a2a_pb2_grpc.py.tmp && mv src/a2a/types/a2a_pb2_grpc.py.tmp src/a2a/types/a2a_pb2_grpc.py diff --git a/src/a2a/client/auth/interceptor.py b/src/a2a/client/auth/interceptor.py index 07911caf6..a19c7a8ed 100644 --- a/src/a2a/client/auth/interceptor.py +++ b/src/a2a/client/auth/interceptor.py @@ -31,12 +31,12 @@ async def intercept( # We check for truthiness to see if they are non-empty. if ( agent_card is None - or not agent_card.security + or not agent_card.security_requirements or not agent_card.security_schemes ): return request_payload, http_kwargs - for requirement in agent_card.security: + for requirement in agent_card.security_requirements: for scheme_name in requirement.schemes: credential = await self._credential_service.get_credentials( scheme_name, context diff --git a/src/a2a/client/base_client.py b/src/a2a/client/base_client.py index 073db509e..cedf6741f 100644 --- a/src/a2a/client/base_client.py +++ b/src/a2a/client/base_client.py @@ -14,12 +14,12 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, Message, SendMessageConfiguration, SendMessageRequest, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -180,7 +180,7 @@ async def cancel_task( async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, diff --git a/src/a2a/client/client.py b/src/a2a/client/client.py index 0022ff771..2d672fc5d 100644 --- a/src/a2a/client/client.py +++ b/src/a2a/client/client.py @@ -12,11 +12,11 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, Message, PushNotificationConfig, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -147,7 +147,7 @@ async def cancel_task( @abstractmethod async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, diff --git a/src/a2a/client/client_factory.py b/src/a2a/client/client_factory.py index 0d741e673..d56910fcd 100644 --- a/src/a2a/client/client_factory.py +++ b/src/a2a/client/client_factory.py @@ -282,5 +282,4 @@ def minimal_agent_card( skills=[], version='', name='', - protocol_versions=['v1'], ) diff --git a/src/a2a/client/transports/base.py b/src/a2a/client/transports/base.py index 712ec5fd6..e7ba63e3c 100644 --- a/src/a2a/client/transports/base.py +++ b/src/a2a/client/transports/base.py @@ -5,11 +5,11 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -65,7 +65,7 @@ async def cancel_task( @abstractmethod async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, diff --git a/src/a2a/client/transports/grpc.py b/src/a2a/client/transports/grpc.py index 87fe7a9a0..f0eb6c41e 100644 --- a/src/a2a/client/transports/grpc.py +++ b/src/a2a/client/transports/grpc.py @@ -22,11 +22,11 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -158,13 +158,13 @@ async def cancel_task( async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, ) -> TaskPushNotificationConfig: """Sets or updates the push notification configuration for a specific task.""" - return await self.stub.SetTaskPushNotificationConfig( + return await self.stub.CreateTaskPushNotificationConfig( request, metadata=self._get_grpc_metadata(extensions), ) diff --git a/src/a2a/client/transports/jsonrpc.py b/src/a2a/client/transports/jsonrpc.py index 9feac93f3..5a1c76d82 100644 --- a/src/a2a/client/transports/jsonrpc.py +++ b/src/a2a/client/transports/jsonrpc.py @@ -24,12 +24,12 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetExtendedAgentCardRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -278,14 +278,14 @@ async def cancel_task( async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, ) -> TaskPushNotificationConfig: """Sets or updates the push notification configuration for a specific task.""" rpc_request = JSONRPC20Request( - method='SetTaskPushNotificationConfig', + method='CreateTaskPushNotificationConfig', params=json_format.MessageToDict(request), _id=str(uuid4()), ) @@ -294,7 +294,7 @@ async def set_task_callback( extensions if extensions is not None else self.extensions, ) payload, modified_kwargs = await self._apply_interceptors( - 'SetTaskPushNotificationConfig', + 'CreateTaskPushNotificationConfig', cast('dict[str, Any]', rpc_request.data), modified_kwargs, context, diff --git a/src/a2a/client/transports/rest.py b/src/a2a/client/transports/rest.py index d32fb1b72..26fd3f1be 100644 --- a/src/a2a/client/transports/rest.py +++ b/src/a2a/client/transports/rest.py @@ -17,11 +17,11 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, StreamResponse, SubscribeToTaskRequest, Task, @@ -229,10 +229,11 @@ async def get_task( context, ) - del params['name'] # name is part of the URL path, not query params + if 'id' in params: + del params['id'] # id is part of the URL path, not query params response_data = await self._send_get_request( - f'/v1/{request.name}', + f'/v1/{request.id}', params, modified_kwargs, ) @@ -258,14 +259,14 @@ async def cancel_task( context, ) response_data = await self._send_post_request( - f'/v1/{request.name}:cancel', payload, modified_kwargs + f'/v1/{request.id}:cancel', payload, modified_kwargs ) response: Task = ParseDict(response_data, Task()) return response async def set_task_callback( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None, extensions: list[str] | None = None, @@ -280,7 +281,7 @@ async def set_task_callback( payload, modified_kwargs, context ) response_data = await self._send_post_request( - f'/v1/{request.parent}/pushNotificationConfigs', + f'/v1/{request.task_id}/pushNotificationConfigs', payload, modified_kwargs, ) @@ -307,9 +308,12 @@ async def get_task_callback( modified_kwargs, context, ) - del params['name'] # name is part of the URL path, not query params + if 'id' in params: + del params['id'] + if 'task_id' in params: + del params['task_id'] response_data = await self._send_get_request( - f'/v1/{request.name}', + f'/v1/{request.task_id}/pushNotificationConfigs/{request.id}', params, modified_kwargs, ) @@ -335,7 +339,7 @@ async def subscribe( async with aconnect_sse( self.httpx_client, 'GET', - f'{self.url}/v1/{request.name}:subscribe', + f'{self.url}/v1/{request.id}:subscribe', **modified_kwargs, ) as event_source: try: diff --git a/src/a2a/server/agent_execution/agent_executor.py b/src/a2a/server/agent_execution/agent_executor.py index 74d7af6c1..e03232b35 100644 --- a/src/a2a/server/agent_execution/agent_executor.py +++ b/src/a2a/server/agent_execution/agent_executor.py @@ -36,7 +36,7 @@ async def cancel( The agent should attempt to stop the task identified by the task_id in the context and publish a `TaskStatusUpdateEvent` with state - `TaskState.TASK_STATE_CANCELLED` to the `event_queue`. + `TaskState.TASK_STATE_CANCELED` to the `event_queue`. Args: context: The request context containing the task ID to cancel. diff --git a/src/a2a/server/apps/jsonrpc/fastapi_app.py b/src/a2a/server/apps/jsonrpc/fastapi_app.py index 6c0610262..be6776d64 100644 --- a/src/a2a/server/apps/jsonrpc/fastapi_app.py +++ b/src/a2a/server/apps/jsonrpc/fastapi_app.py @@ -51,15 +51,16 @@ def openapi(self) -> dict[str, Any]: # Try to use the a2a.json schema generated from the proto file # if available, instead of generating one from the python types. try: - from a2a import types + from a2a import types # noqa: PLC0415 schema_file = importlib.resources.files(types).joinpath('a2a.json') if schema_file.is_file(): self.openapi_schema = json.loads( schema_file.read_text(encoding='utf-8') ) - return self.openapi_schema - except Exception: # pylint: disable=broad-except + if self.openapi_schema: + return self.openapi_schema + except Exception: # noqa: BLE001 logger.warning( "Could not load 'a2a.json' from 'a2a.types'. Falling back to auto-generation." ) diff --git a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py index e215b7a5c..ca9827be1 100644 --- a/src/a2a/server/apps/jsonrpc/jsonrpc_app.py +++ b/src/a2a/server/apps/jsonrpc/jsonrpc_app.py @@ -24,6 +24,7 @@ InvalidParamsError, InvalidRequestError, JSONParseError, + JSONRPCError, MethodNotFoundError, ) from a2a.server.request_handlers.jsonrpc_handler import JSONRPCHandler @@ -33,13 +34,13 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, GetExtendedAgentCardRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, ListTaskPushNotificationConfigRequest, SendMessageRequest, - SetTaskPushNotificationConfigRequest, SubscribeToTaskRequest, ) from a2a.utils.constants import ( @@ -49,6 +50,7 @@ PREV_AGENT_CARD_WELL_KNOWN_PATH, ) from a2a.utils.errors import ( + A2AException, MethodNotImplementedError, UnsupportedOperationError, ) @@ -164,7 +166,7 @@ class JSONRPCApplication(ABC): 'SendStreamingMessage': SendMessageRequest, # Same proto type as SendMessage 'GetTask': GetTaskRequest, 'CancelTask': CancelTaskRequest, - 'SetTaskPushNotificationConfig': SetTaskPushNotificationConfigRequest, + 'CreateTaskPushNotificationConfig': CreateTaskPushNotificationConfigRequest, 'GetTaskPushNotificationConfig': GetTaskPushNotificationConfigRequest, 'ListTaskPushNotificationConfig': ListTaskPushNotificationConfigRequest, 'DeleteTaskPushNotificationConfig': DeleteTaskPushNotificationConfigRequest, @@ -225,7 +227,9 @@ def __init__( # noqa: PLR0913 self._max_content_length = max_content_length def _generate_error_response( - self, request_id: str | int | None, error: Exception + self, + request_id: str | int | None, + error: Exception | JSONRPCError | A2AException, ) -> JSONResponse: """Creates a Starlette JSONResponse for a JSON-RPC error. @@ -238,6 +242,9 @@ def _generate_error_response( Returns: A `JSONResponse` object formatted as a JSON-RPC error response. """ + if not isinstance(error, A2AException | JSONRPCError): + error = InternalError(message=str(error)) + response_data = build_error_response(request_id, error) error_info = response_data.get('error', {}) code = error_info.get('code') @@ -457,7 +464,7 @@ async def _process_non_streaming_request( handler_result = await self.handler.on_get_task( request_obj, context ) - case SetTaskPushNotificationConfigRequest(): + case CreateTaskPushNotificationConfigRequest(): handler_result = ( await self.handler.set_push_notification_config( request_obj, diff --git a/src/a2a/server/events/event_consumer.py b/src/a2a/server/events/event_consumer.py index f8927521b..09d2cee2d 100644 --- a/src/a2a/server/events/event_consumer.py +++ b/src/a2a/server/events/event_consumer.py @@ -101,20 +101,16 @@ async def consume_all(self) -> AsyncGenerator[Event]: 'Marked task as done in event queue in consume_all' ) - is_final_event = ( - (isinstance(event, TaskStatusUpdateEvent) and event.final) - or isinstance(event, Message) - or ( - isinstance(event, Task) - and event.status.state - in ( - TaskState.TASK_STATE_COMPLETED, - TaskState.TASK_STATE_CANCELLED, - TaskState.TASK_STATE_FAILED, - TaskState.TASK_STATE_REJECTED, - TaskState.TASK_STATE_UNSPECIFIED, - TaskState.TASK_STATE_INPUT_REQUIRED, - ) + is_final_event = isinstance(event, Message) or ( + isinstance(event, Task | TaskStatusUpdateEvent) + and event.status.state + in ( + TaskState.TASK_STATE_COMPLETED, + TaskState.TASK_STATE_CANCELED, + TaskState.TASK_STATE_FAILED, + TaskState.TASK_STATE_REJECTED, + TaskState.TASK_STATE_UNSPECIFIED, + TaskState.TASK_STATE_INPUT_REQUIRED, ) ) diff --git a/src/a2a/server/jsonrpc_models.py b/src/a2a/server/jsonrpc_models.py index 43d083745..f5a056282 100644 --- a/src/a2a/server/jsonrpc_models.py +++ b/src/a2a/server/jsonrpc_models.py @@ -4,6 +4,8 @@ class JSONRPCBaseModel(BaseModel): + """Base model for JSON-RPC objects.""" + model_config = { 'extra': 'allow', 'populate_by_name': True, @@ -12,31 +14,43 @@ class JSONRPCBaseModel(BaseModel): class JSONRPCError(JSONRPCBaseModel): + """Base model for JSON-RPC error objects.""" + code: int message: str data: Any | None = None class JSONParseError(JSONRPCError): - code: Literal[-32700] = -32700 + """Error raised when invalid JSON was received by the server.""" + + code: Literal[-32700] = -32700 # pyright: ignore [reportIncompatibleVariableOverride] message: str = 'Parse error' class InvalidRequestError(JSONRPCError): - code: Literal[-32600] = -32600 + """Error raised when the JSON sent is not a valid Request object.""" + + code: Literal[-32600] = -32600 # pyright: ignore [reportIncompatibleVariableOverride] message: str = 'Invalid Request' class MethodNotFoundError(JSONRPCError): - code: Literal[-32601] = -32601 + """Error raised when the method does not exist / is not available.""" + + code: Literal[-32601] = -32601 # pyright: ignore [reportIncompatibleVariableOverride] message: str = 'Method not found' class InvalidParamsError(JSONRPCError): - code: Literal[-32602] = -32602 + """Error raised when invalid method parameter(s).""" + + code: Literal[-32602] = -32602 # pyright: ignore [reportIncompatibleVariableOverride] message: str = 'Invalid params' class InternalError(JSONRPCError): - code: Literal[-32603] = -32603 + """Error raised when internal JSON-RPC error.""" + + code: Literal[-32603] = -32603 # pyright: ignore [reportIncompatibleVariableOverride] message: str = 'Internal error' diff --git a/src/a2a/server/models.py b/src/a2a/server/models.py index ba6d39b02..41e9ac1d5 100644 --- a/src/a2a/server/models.py +++ b/src/a2a/server/models.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any, Generic, TypeVar +from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast if TYPE_CHECKING: @@ -65,7 +65,7 @@ def process_bind_param( if isinstance(value, ProtoMessage): return MessageToDict(value, preserving_proto_field_name=False) if isinstance(value, BaseModel): - return value.model_dump(mode='json') + return cast('BaseModel', value).model_dump(mode='json') return value # type: ignore[return-value] def process_result_value( @@ -112,7 +112,7 @@ def process_bind_param( MessageToDict(item, preserving_proto_field_name=False) ) elif isinstance(item, BaseModel): - result.append(item.model_dump(mode='json')) + result.append(cast('BaseModel', item).model_dump(mode='json')) else: result.append(item) # type: ignore[arg-type] return result diff --git a/src/a2a/server/request_handlers/default_request_handler.py b/src/a2a/server/request_handlers/default_request_handler.py index fe4d9c09b..7ea96c1ab 100644 --- a/src/a2a/server/request_handlers/default_request_handler.py +++ b/src/a2a/server/request_handlers/default_request_handler.py @@ -29,6 +29,7 @@ ) from a2a.types.a2a_pb2 import ( CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, @@ -37,8 +38,6 @@ Message, PushNotificationConfig, SendMessageRequest, - SetTaskPushNotificationConfigRequest, - StreamResponse, SubscribeToTaskRequest, Task, TaskPushNotificationConfig, @@ -57,10 +56,11 @@ def _extract_task_id(resource_name: str) -> str: - """Extract task ID from a resource name like 'tasks/{task_id}' or 'tasks/{task_id}/...'.""" + """Extract task ID from a resource name like 'tasks/{task_id}' or just returns '{task_id}'.""" match = re.match(r'^tasks/([^/]+)', resource_name) if match: return match.group(1) + return resource_name # Fall back to the raw value if no match (for backwards compatibility) return resource_name @@ -79,7 +79,7 @@ def _extract_config_id(resource_name: str) -> str | None: TERMINAL_TASK_STATES = { TaskState.TASK_STATE_COMPLETED, - TaskState.TASK_STATE_CANCELLED, + TaskState.TASK_STATE_CANCELED, TaskState.TASK_STATE_FAILED, TaskState.TASK_STATE_REJECTED, } @@ -141,7 +141,7 @@ async def on_get_task( context: ServerCallContext | None = None, ) -> Task | None: """Default handler for 'tasks/get'.""" - task_id = _extract_task_id(params.name) + task_id = _extract_task_id(params.id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -158,7 +158,7 @@ async def on_cancel_task( Attempts to cancel the task managed by the `AgentExecutor`. """ - task_id = _extract_task_id(params.name) + task_id = _extract_task_id(params.id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -206,7 +206,7 @@ async def on_cancel_task( ) ) - if result.status.state != TaskState.TASK_STATE_CANCELLED: + if result.status.state != TaskState.TASK_STATE_CANCELED: raise ServerError( error=TaskNotCancelableError( message=f'Task cannot be canceled - current state: {result.status.state}' @@ -476,7 +476,7 @@ async def _cleanup_producer( async def on_set_task_push_notification_config( self, - params: SetTaskPushNotificationConfigRequest, + params: CreateTaskPushNotificationConfigRequest, context: ServerCallContext | None = None, ) -> TaskPushNotificationConfig: """Default handler for 'tasks/pushNotificationConfig/set'. @@ -486,20 +486,20 @@ async def on_set_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.parent) + task_id = _extract_task_id(params.task_id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) await self._push_config_store.set_info( task_id, - params.config.push_notification_config, + params.config, ) - # Build the response config with the proper name return TaskPushNotificationConfig( - name=f'{params.parent}/pushNotificationConfigs/{params.config_id}', - push_notification_config=params.config.push_notification_config, + task_id=task_id, + id=params.config_id, + push_notification_config=params.config, ) async def on_get_task_push_notification_config( @@ -514,8 +514,8 @@ async def on_get_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.name) - config_id = _extract_config_id(params.name) + task_id = _extract_task_id(params.task_id) + config_id = params.id task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -527,7 +527,8 @@ async def on_get_task_push_notification_config( for config in push_notification_configs: if config.id == config_id: return TaskPushNotificationConfig( - name=params.name, + task_id=task_id, + id=config.id, push_notification_config=config, ) @@ -539,13 +540,13 @@ async def on_subscribe_to_task( self, params: SubscribeToTaskRequest, context: ServerCallContext | None = None, - ) -> AsyncGenerator[StreamResponse]: + ) -> AsyncGenerator[Event, None]: """Default handler for 'SubscribeToTask'. Allows a client to re-attach to a running streaming task's event stream. Requires the task and its queue to still be active. """ - task_id = _extract_task_id(params.name) + task_id = _extract_task_id(params.id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -587,7 +588,7 @@ async def on_list_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.parent) + task_id = _extract_task_id(params.task_id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -599,7 +600,8 @@ async def on_list_task_push_notification_config( return ListTaskPushNotificationConfigResponse( configs=[ TaskPushNotificationConfig( - name=f'tasks/{task_id}/pushNotificationConfigs/{config.id}', + task_id=task_id, + id=config.id, push_notification_config=config, ) for config in push_notification_config_list @@ -618,8 +620,8 @@ async def on_delete_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.name) - config_id = _extract_config_id(params.name) + task_id = _extract_task_id(params.task_id) + config_id = params.id task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) diff --git a/src/a2a/server/request_handlers/grpc_handler.py b/src/a2a/server/request_handlers/grpc_handler.py index 38d6609d4..50d415a1e 100644 --- a/src/a2a/server/request_handlers/grpc_handler.py +++ b/src/a2a/server/request_handlers/grpc_handler.py @@ -262,17 +262,17 @@ async def GetTaskPushNotificationConfig( lambda self: self.agent_card.capabilities.push_notifications, 'Push notifications are not supported by the agent', ) - async def SetTaskPushNotificationConfig( + async def CreateTaskPushNotificationConfig( self, - request: a2a_pb2.SetTaskPushNotificationConfigRequest, + request: a2a_pb2.CreateTaskPushNotificationConfigRequest, context: grpc.aio.ServicerContext, ) -> a2a_pb2.TaskPushNotificationConfig: - """Handles the 'SetTaskPushNotificationConfig' gRPC method. + """Handles the 'CreateTaskPushNotificationConfig' gRPC method. Requires the agent to support push notifications. Args: - request: The incoming `SetTaskPushNotificationConfigRequest` object. + request: The incoming `CreateTaskPushNotificationConfigRequest` object. context: Context provided by the server. Returns: diff --git a/src/a2a/server/request_handlers/jsonrpc_handler.py b/src/a2a/server/request_handlers/jsonrpc_handler.py index 2a4800e64..f8711247a 100644 --- a/src/a2a/server/request_handlers/jsonrpc_handler.py +++ b/src/a2a/server/request_handlers/jsonrpc_handler.py @@ -19,6 +19,7 @@ from a2a.types.a2a_pb2 import ( AgentCard, CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, GetExtendedAgentCardRequest, GetTaskPushNotificationConfigRequest, @@ -27,7 +28,6 @@ Message, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, SubscribeToTaskRequest, Task, ) @@ -320,7 +320,7 @@ async def get_push_notification_config( ) async def set_push_notification_config( self, - request: SetTaskPushNotificationConfigRequest, + request: CreateTaskPushNotificationConfigRequest, context: ServerCallContext | None = None, ) -> dict[str, Any]: """Handles the 'tasks/pushNotificationConfig/set' JSON-RPC method. @@ -328,7 +328,7 @@ async def set_push_notification_config( Requires the agent to support push notifications. Args: - request: The incoming `SetTaskPushNotificationConfigRequest` object. + request: The incoming `CreateTaskPushNotificationConfigRequest` object. context: Context provided by the server. Returns: diff --git a/src/a2a/server/request_handlers/request_handler.py b/src/a2a/server/request_handlers/request_handler.py index 2cabf85cc..a889ecd55 100644 --- a/src/a2a/server/request_handlers/request_handler.py +++ b/src/a2a/server/request_handlers/request_handler.py @@ -5,6 +5,7 @@ from a2a.server.events.event_queue import Event from a2a.types.a2a_pb2 import ( CancelTaskRequest, + CreateTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, @@ -12,7 +13,6 @@ ListTaskPushNotificationConfigResponse, Message, SendMessageRequest, - SetTaskPushNotificationConfigRequest, SubscribeToTaskRequest, Task, TaskPushNotificationConfig, @@ -109,7 +109,7 @@ async def on_message_send_stream( @abstractmethod async def on_set_task_push_notification_config( self, - params: SetTaskPushNotificationConfigRequest, + params: CreateTaskPushNotificationConfigRequest, context: ServerCallContext | None = None, ) -> TaskPushNotificationConfig: """Handles the 'tasks/pushNotificationConfig/set' method. diff --git a/src/a2a/server/request_handlers/response_helpers.py b/src/a2a/server/request_handlers/response_helpers.py index c68814f18..53ed4ac45 100644 --- a/src/a2a/server/request_handlers/response_helpers.py +++ b/src/a2a/server/request_handlers/response_helpers.py @@ -143,7 +143,7 @@ def prepare_response_object( result = MessageToDict(response, preserving_proto_field_name=False) return JSONRPC20Response(result=result, _id=request_id).data - if isinstance(response, _A2A_ERROR_TYPES): + if isinstance(response, A2AException | JSONRPCError): return build_error_response(request_id, response) # If response is not an expected success type and not an error, diff --git a/src/a2a/server/request_handlers/rest_handler.py b/src/a2a/server/request_handlers/rest_handler.py index acca1019a..31d2668f2 100644 --- a/src/a2a/server/request_handlers/rest_handler.py +++ b/src/a2a/server/request_handlers/rest_handler.py @@ -132,7 +132,7 @@ async def on_cancel_task( """ task_id = request.path_params['id'] task = await self.request_handler.on_cancel_task( - CancelTaskRequest(name=f'tasks/{task_id}'), context + CancelTaskRequest(id=task_id), context ) if task: return MessageToDict(task) @@ -160,7 +160,7 @@ async def on_subscribe_to_task( """ task_id = request.path_params['id'] async for event in self.request_handler.on_subscribe_to_task( - SubscribeToTaskRequest(name=task_id), context + SubscribeToTaskRequest(id=task_id), context ): yield MessageToJson(proto_utils.to_stream_response(event)) @@ -181,7 +181,8 @@ async def get_push_notification( task_id = request.path_params['id'] push_id = request.path_params['push_id'] params = GetTaskPushNotificationConfigRequest( - name=f'tasks/{task_id}/pushNotificationConfigs/{push_id}' + task_id=f'tasks/{task_id}', + id=push_id, ) config = ( await self.request_handler.on_get_task_push_notification_config( @@ -217,10 +218,10 @@ async def set_push_notification( """ task_id = request.path_params['id'] body = await request.body() - params = a2a_pb2.SetTaskPushNotificationConfigRequest() + params = a2a_pb2.CreateTaskPushNotificationConfigRequest() Parse(body, params) # Set the parent to the task resource name format - params.parent = f'tasks/{task_id}' + params.task_id = f'tasks/{task_id}' config = ( await self.request_handler.on_set_task_push_notification_config( params, context @@ -245,7 +246,7 @@ async def on_get_task( task_id = request.path_params['id'] history_length_str = request.query_params.get('historyLength') history_length = int(history_length_str) if history_length_str else None - params = GetTaskRequest(name=task_id, history_length=history_length) + params = GetTaskRequest(id=task_id, history_length=history_length) task = await self.request_handler.on_get_task(params, context) if task: return MessageToDict(task) diff --git a/src/a2a/server/tasks/database_task_store.py b/src/a2a/server/tasks/database_task_store.py index 5761e973f..9a0d42d45 100644 --- a/src/a2a/server/tasks/database_task_store.py +++ b/src/a2a/server/tasks/database_task_store.py @@ -1,5 +1,7 @@ import logging +from typing import Any, cast + try: from sqlalchemy import Table, delete, select @@ -126,7 +128,9 @@ def _from_orm(self, task_model: TaskModel) -> Task: if task_model.history: task.history.extend(task_model.history) if task_model.task_metadata: - task.metadata.update(task_model.task_metadata) + task.metadata.update( + cast('dict[str, Any]', task_model.task_metadata) + ) return task async def save( diff --git a/src/a2a/server/tasks/task_updater.py b/src/a2a/server/tasks/task_updater.py index 78037f95f..8298920da 100644 --- a/src/a2a/server/tasks/task_updater.py +++ b/src/a2a/server/tasks/task_updater.py @@ -53,7 +53,7 @@ def __init__( self._terminal_state_reached = False self._terminal_states = { TaskState.TASK_STATE_COMPLETED, - TaskState.TASK_STATE_CANCELLED, + TaskState.TASK_STATE_CANCELED, TaskState.TASK_STATE_FAILED, TaskState.TASK_STATE_REJECTED, } @@ -68,7 +68,6 @@ async def update_status( self, state: TaskState, message: Message | None = None, - final: bool = False, timestamp: str | None = None, metadata: dict[str, Any] | None = None, ) -> None: @@ -77,7 +76,6 @@ async def update_status( Args: state: The new state of the task. message: An optional message associated with the status update. - final: If True, indicates this is the final status update for the task. timestamp: Optional ISO 8601 datetime string. Defaults to current time. metadata: Optional metadata for extensions. """ @@ -88,7 +86,6 @@ async def update_status( ) if state in self._terminal_states: self._terminal_state_reached = True - final = True # Create proto timestamp from datetime ts = Timestamp() @@ -108,7 +105,6 @@ async def update_status( TaskStatusUpdateEvent( task_id=self.task_id, context_id=self.context_id, - final=final, metadata=metadata, status=status, ) @@ -163,19 +159,20 @@ async def complete(self, message: Message | None = None) -> None: await self.update_status( TaskState.TASK_STATE_COMPLETED, message=message, - final=True, ) async def failed(self, message: Message | None = None) -> None: """Marks the task as failed and publishes a final status update.""" await self.update_status( - TaskState.TASK_STATE_FAILED, message=message, final=True + TaskState.TASK_STATE_FAILED, + message=message, ) async def reject(self, message: Message | None = None) -> None: """Marks the task as rejected and publishes a final status update.""" await self.update_status( - TaskState.TASK_STATE_REJECTED, message=message, final=True + TaskState.TASK_STATE_REJECTED, + message=message, ) async def submit(self, message: Message | None = None) -> None: @@ -195,25 +192,21 @@ async def start_work(self, message: Message | None = None) -> None: async def cancel(self, message: Message | None = None) -> None: """Marks the task as cancelled and publishes a finalstatus update.""" await self.update_status( - TaskState.TASK_STATE_CANCELLED, message=message, final=True + TaskState.TASK_STATE_CANCELED, + message=message, ) - async def requires_input( - self, message: Message | None = None, final: bool = False - ) -> None: + async def requires_input(self, message: Message | None = None) -> None: """Marks the task as input required and publishes a status update.""" await self.update_status( TaskState.TASK_STATE_INPUT_REQUIRED, message=message, - final=final, ) - async def requires_auth( - self, message: Message | None = None, final: bool = False - ) -> None: + async def requires_auth(self, message: Message | None = None) -> None: """Marks the task as auth required and publishes a status update.""" await self.update_status( - TaskState.TASK_STATE_AUTH_REQUIRED, message=message, final=final + TaskState.TASK_STATE_AUTH_REQUIRED, message=message ) def new_agent_message( diff --git a/src/a2a/types/__init__.py b/src/a2a/types/__init__.py index 025d8ed34..23bfd615d 100644 --- a/src/a2a/types/__init__.py +++ b/src/a2a/types/__init__.py @@ -15,13 +15,14 @@ AuthorizationCodeOAuthFlow, CancelTaskRequest, ClientCredentialsOAuthFlow, - DataPart, + CreateTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, - FilePart, + DeviceCodeOAuthFlow, GetExtendedAgentCardRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, HTTPAuthSecurityScheme, + ImplicitOAuthFlow, ListTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigResponse, ListTasksRequest, @@ -32,14 +33,14 @@ OAuthFlows, OpenIdConnectSecurityScheme, Part, + PasswordOAuthFlow, PushNotificationConfig, Role, - Security, + SecurityRequirement, SecurityScheme, SendMessageConfiguration, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, StreamResponse, StringList, SubscribeToTaskRequest, @@ -73,7 +74,7 @@ SendMessageRequest | GetTaskRequest | CancelTaskRequest - | SetTaskPushNotificationConfigRequest + | CreateTaskPushNotificationConfigRequest | GetTaskPushNotificationConfigRequest | SubscribeToTaskRequest | GetExtendedAgentCardRequest @@ -100,13 +101,14 @@ 'CancelTaskRequest', 'ClientCredentialsOAuthFlow', 'ContentTypeNotSupportedError', - 'DataPart', + 'CreateTaskPushNotificationConfigRequest', 'DeleteTaskPushNotificationConfigRequest', - 'FilePart', + 'DeviceCodeOAuthFlow', 'GetExtendedAgentCardRequest', 'GetTaskPushNotificationConfigRequest', 'GetTaskRequest', 'HTTPAuthSecurityScheme', + 'ImplicitOAuthFlow', 'InternalError', 'InvalidAgentResponseError', 'InvalidParamsError', @@ -122,15 +124,15 @@ 'OAuthFlows', 'OpenIdConnectSecurityScheme', 'Part', + 'PasswordOAuthFlow', 'PushNotificationConfig', 'PushNotificationNotSupportedError', 'Role', - 'Security', + 'SecurityRequirement', 'SecurityScheme', 'SendMessageConfiguration', 'SendMessageRequest', 'SendMessageResponse', - 'SetTaskPushNotificationConfigRequest', 'StreamResponse', 'StringList', 'SubscribeToTaskRequest', diff --git a/src/a2a/types/a2a_pb2.py b/src/a2a/types/a2a_pb2.py index 5223acef6..b9d813888 100644 --- a/src/a2a/types/a2a_pb2.py +++ b/src/a2a/types/a2a_pb2.py @@ -30,7 +30,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ta2a.proto\x12\x06\x61\x32\x61.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x83\x02\n\x18SendMessageConfiguration\x12\x32\n\x15\x61\x63\x63\x65pted_output_modes\x18\x01 \x03(\tR\x13\x61\x63\x63\x65ptedOutputModes\x12X\n\x18push_notification_config\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.PushNotificationConfigR\x16pushNotificationConfig\x12*\n\x0ehistory_length\x18\x03 \x01(\x05H\x00R\rhistoryLength\x88\x01\x01\x12\x1a\n\x08\x62locking\x18\x04 \x01(\x08R\x08\x62lockingB\x11\n\x0f_history_length\"\x80\x02\n\x04Task\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12/\n\x06status\x18\x03 \x01(\x0b\x32\x12.a2a.v1.TaskStatusB\x03\xe0\x41\x02R\x06status\x12.\n\tartifacts\x18\x04 \x03(\x0b\x32\x10.a2a.v1.ArtifactR\tartifacts\x12)\n\x07history\x18\x05 \x03(\x0b\x32\x0f.a2a.v1.MessageR\x07history\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\x9f\x01\n\nTaskStatus\x12,\n\x05state\x18\x01 \x01(\x0e\x32\x11.a2a.v1.TaskStateB\x03\xe0\x41\x02R\x05state\x12)\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageR\x07message\x12\x38\n\ttimestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimestamp\"\xa9\x01\n\x04Part\x12\x14\n\x04text\x18\x01 \x01(\tH\x00R\x04text\x12&\n\x04\x66ile\x18\x02 \x01(\x0b\x32\x10.a2a.v1.FilePartH\x00R\x04\x66ile\x12&\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32\x10.a2a.v1.DataPartH\x00R\x04\x64\x61ta\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadataB\x06\n\x04part\"\x95\x01\n\x08\x46ilePart\x12$\n\rfile_with_uri\x18\x01 \x01(\tH\x00R\x0b\x66ileWithUri\x12(\n\x0f\x66ile_with_bytes\x18\x02 \x01(\x0cH\x00R\rfileWithBytes\x12\x1d\n\nmedia_type\x18\x03 \x01(\tR\tmediaType\x12\x12\n\x04name\x18\x04 \x01(\tR\x04nameB\x06\n\x04\x66ile\"<\n\x08\x44\x61taPart\x12\x30\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32\x17.google.protobuf.StructB\x03\xe0\x41\x02R\x04\x64\x61ta\"\xb8\x02\n\x07Message\x12\"\n\nmessage_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\tmessageId\x12\x1d\n\ncontext_id\x18\x02 \x01(\tR\tcontextId\x12\x17\n\x07task_id\x18\x03 \x01(\tR\x06taskId\x12%\n\x04role\x18\x04 \x01(\x0e\x32\x0c.a2a.v1.RoleB\x03\xe0\x41\x02R\x04role\x12\'\n\x05parts\x18\x05 \x03(\x0b\x32\x0c.a2a.v1.PartB\x03\xe0\x41\x02R\x05parts\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\x12\x1e\n\nextensions\x18\x07 \x03(\tR\nextensions\x12,\n\x12reference_task_ids\x18\x08 \x03(\tR\x10referenceTaskIds\"\xe4\x01\n\x08\x41rtifact\x12$\n\x0b\x61rtifact_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\nartifactId\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\'\n\x05parts\x18\x05 \x03(\x0b\x32\x0c.a2a.v1.PartB\x03\xe0\x41\x02R\x05parts\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\x12\x1e\n\nextensions\x18\x07 \x03(\tR\nextensions\"\xda\x01\n\x15TaskStatusUpdateEvent\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12/\n\x06status\x18\x03 \x01(\x0b\x32\x12.a2a.v1.TaskStatusB\x03\xe0\x41\x02R\x06status\x12\x19\n\x05\x66inal\x18\x04 \x01(\x08\x42\x03\xe0\x41\x02R\x05\x66inal\x12\x33\n\x08metadata\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\xfa\x01\n\x17TaskArtifactUpdateEvent\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12\x31\n\x08\x61rtifact\x18\x03 \x01(\x0b\x32\x10.a2a.v1.ArtifactB\x03\xe0\x41\x02R\x08\x61rtifact\x12\x16\n\x06\x61ppend\x18\x04 \x01(\x08R\x06\x61ppend\x12\x1d\n\nlast_chunk\x18\x05 \x01(\x08R\tlastChunk\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\x99\x01\n\x16PushNotificationConfig\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n\x03url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x03url\x12\x14\n\x05token\x18\x03 \x01(\tR\x05token\x12\x42\n\x0e\x61uthentication\x18\x04 \x01(\x0b\x32\x1a.a2a.v1.AuthenticationInfoR\x0e\x61uthentication\"U\n\x12\x41uthenticationInfo\x12\x1d\n\x07schemes\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x07schemes\x12 \n\x0b\x63redentials\x18\x02 \x01(\tR\x0b\x63redentials\"o\n\x0e\x41gentInterface\x12\x15\n\x03url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x03url\x12.\n\x10protocol_binding\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0fprotocolBinding\x12\x16\n\x06tenant\x18\x03 \x01(\tR\x06tenant\"\xa0\x07\n\tAgentCard\x12\x30\n\x11protocol_versions\x18\x10 \x03(\tB\x03\xe0\x41\x02R\x10protocolVersions\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12N\n\x14supported_interfaces\x18\x13 \x03(\x0b\x32\x16.a2a.v1.AgentInterfaceB\x03\xe0\x41\x02R\x13supportedInterfaces\x12\x31\n\x08provider\x18\x04 \x01(\x0b\x32\x15.a2a.v1.AgentProviderR\x08provider\x12\x1d\n\x07version\x18\x05 \x01(\tB\x03\xe0\x41\x02R\x07version\x12\x30\n\x11\x64ocumentation_url\x18\x06 \x01(\tH\x00R\x10\x64ocumentationUrl\x88\x01\x01\x12\x42\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x19.a2a.v1.AgentCapabilitiesB\x03\xe0\x41\x02R\x0c\x63\x61pabilities\x12Q\n\x10security_schemes\x18\x08 \x03(\x0b\x32&.a2a.v1.AgentCard.SecuritySchemesEntryR\x0fsecuritySchemes\x12,\n\x08security\x18\t \x03(\x0b\x32\x10.a2a.v1.SecurityR\x08security\x12\x33\n\x13\x64\x65\x66\x61ult_input_modes\x18\n \x03(\tB\x03\xe0\x41\x02R\x11\x64\x65\x66\x61ultInputModes\x12\x35\n\x14\x64\x65\x66\x61ult_output_modes\x18\x0b \x03(\tB\x03\xe0\x41\x02R\x12\x64\x65\x66\x61ultOutputModes\x12/\n\x06skills\x18\x0c \x03(\x0b\x32\x12.a2a.v1.AgentSkillB\x03\xe0\x41\x02R\x06skills\x12:\n\nsignatures\x18\x11 \x03(\x0b\x32\x1a.a2a.v1.AgentCardSignatureR\nsignatures\x12\x1e\n\x08icon_url\x18\x12 \x01(\tH\x01R\x07iconUrl\x88\x01\x01\x1aZ\n\x14SecuritySchemesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x16.a2a.v1.SecuritySchemeR\x05value:\x02\x38\x01\x42\x14\n\x12_documentation_urlB\x0b\n\t_icon_urlJ\x04\x08\x03\x10\x04J\x04\x08\x0e\x10\x0fJ\x04\x08\x0f\x10\x10\"O\n\rAgentProvider\x12\x15\n\x03url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x03url\x12\'\n\x0corganization\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0corganization\"\xf0\x02\n\x11\x41gentCapabilities\x12!\n\tstreaming\x18\x01 \x01(\x08H\x00R\tstreaming\x88\x01\x01\x12\x32\n\x12push_notifications\x18\x02 \x01(\x08H\x01R\x11pushNotifications\x88\x01\x01\x12\x36\n\nextensions\x18\x03 \x03(\x0b\x32\x16.a2a.v1.AgentExtensionR\nextensions\x12=\n\x18state_transition_history\x18\x04 \x01(\x08H\x02R\x16stateTransitionHistory\x88\x01\x01\x12\x33\n\x13\x65xtended_agent_card\x18\x05 \x01(\x08H\x03R\x11\x65xtendedAgentCard\x88\x01\x01\x42\x0c\n\n_streamingB\x15\n\x13_push_notificationsB\x1b\n\x19_state_transition_historyB\x16\n\x14_extended_agent_card\"\x91\x01\n\x0e\x41gentExtension\x12\x10\n\x03uri\x18\x01 \x01(\tR\x03uri\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12\x1a\n\x08required\x18\x03 \x01(\x08R\x08required\x12/\n\x06params\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x06params\"\x88\x02\n\nAgentSkill\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12\x17\n\x04tags\x18\x04 \x03(\tB\x03\xe0\x41\x02R\x04tags\x12\x1a\n\x08\x65xamples\x18\x05 \x03(\tR\x08\x65xamples\x12\x1f\n\x0binput_modes\x18\x06 \x03(\tR\ninputModes\x12!\n\x0coutput_modes\x18\x07 \x03(\tR\x0boutputModes\x12,\n\x08security\x18\x08 \x03(\x0b\x32\x10.a2a.v1.SecurityR\x08security\"\x8b\x01\n\x12\x41gentCardSignature\x12!\n\tprotected\x18\x01 \x01(\tB\x03\xe0\x41\x02R\tprotected\x12!\n\tsignature\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tsignature\x12/\n\x06header\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06header\"\x94\x01\n\x1aTaskPushNotificationConfig\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12]\n\x18push_notification_config\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.PushNotificationConfigB\x03\xe0\x41\x02R\x16pushNotificationConfig\" \n\nStringList\x12\x12\n\x04list\x18\x01 \x03(\tR\x04list\"\x93\x01\n\x08Security\x12\x37\n\x07schemes\x18\x01 \x03(\x0b\x32\x1d.a2a.v1.Security.SchemesEntryR\x07schemes\x1aN\n\x0cSchemesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x12.a2a.v1.StringListR\x05value:\x02\x38\x01\"\xe6\x03\n\x0eSecurityScheme\x12U\n\x17\x61pi_key_security_scheme\x18\x01 \x01(\x0b\x32\x1c.a2a.v1.APIKeySecuritySchemeH\x00R\x14\x61piKeySecurityScheme\x12[\n\x19http_auth_security_scheme\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.HTTPAuthSecuritySchemeH\x00R\x16httpAuthSecurityScheme\x12T\n\x16oauth2_security_scheme\x18\x03 \x01(\x0b\x32\x1c.a2a.v1.OAuth2SecuritySchemeH\x00R\x14oauth2SecurityScheme\x12k\n\x1fopen_id_connect_security_scheme\x18\x04 \x01(\x0b\x32#.a2a.v1.OpenIdConnectSecuritySchemeH\x00R\x1bopenIdConnectSecurityScheme\x12S\n\x14mtls_security_scheme\x18\x05 \x01(\x0b\x32\x1f.a2a.v1.MutualTlsSecuritySchemeH\x00R\x12mtlsSecuritySchemeB\x08\n\x06scheme\"r\n\x14\x41PIKeySecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x1f\n\x08location\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08location\x12\x17\n\x04name\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x04name\"|\n\x16HTTPAuthSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x1b\n\x06scheme\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x06scheme\x12#\n\rbearer_format\x18\x03 \x01(\tR\x0c\x62\x65\x61rerFormat\"\x97\x01\n\x14OAuth2SecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12-\n\x05\x66lows\x18\x02 \x01(\x0b\x32\x12.a2a.v1.OAuthFlowsB\x03\xe0\x41\x02R\x05\x66lows\x12.\n\x13oauth2_metadata_url\x18\x03 \x01(\tR\x11oauth2MetadataUrl\"s\n\x1bOpenIdConnectSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x32\n\x13open_id_connect_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x10openIdConnectUrl\";\n\x17MutualTlsSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\"\x8a\x02\n\nOAuthFlows\x12S\n\x12\x61uthorization_code\x18\x01 \x01(\x0b\x32\".a2a.v1.AuthorizationCodeOAuthFlowH\x00R\x11\x61uthorizationCode\x12S\n\x12\x63lient_credentials\x18\x02 \x01(\x0b\x32\".a2a.v1.ClientCredentialsOAuthFlowH\x00R\x11\x63lientCredentials\x12>\n\x0b\x64\x65vice_code\x18\x05 \x01(\x0b\x32\x1b.a2a.v1.DeviceCodeOAuthFlowH\x00R\ndeviceCodeB\x06\n\x04\x66lowJ\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"\xbe\x02\n\x1a\x41uthorizationCodeOAuthFlow\x12\x30\n\x11\x61uthorization_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x10\x61uthorizationUrl\x12 \n\ttoken_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x03 \x01(\tR\nrefreshUrl\x12K\n\x06scopes\x18\x04 \x03(\x0b\x32..a2a.v1.AuthorizationCodeOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x12#\n\rpkce_required\x18\x05 \x01(\x08R\x0cpkceRequired\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xe7\x01\n\x1a\x43lientCredentialsOAuthFlow\x12 \n\ttoken_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x02 \x01(\tR\nrefreshUrl\x12K\n\x06scopes\x18\x03 \x03(\x0b\x32..a2a.v1.ClientCredentialsOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x98\x02\n\x13\x44\x65viceCodeOAuthFlow\x12=\n\x18\x64\x65vice_authorization_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x16\x64\x65viceAuthorizationUrl\x12 \n\ttoken_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x03 \x01(\tR\nrefreshUrl\x12\x44\n\x06scopes\x18\x04 \x03(\x0b\x32\'.a2a.v1.DeviceCodeOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xd9\x01\n\x12SendMessageRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12.\n\x07message\x18\x01 \x01(\x0b\x32\x0f.a2a.v1.MessageB\x03\xe0\x41\x02R\x07message\x12\x46\n\rconfiguration\x18\x02 \x01(\x0b\x32 .a2a.v1.SendMessageConfigurationR\rconfiguration\x12\x33\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\x80\x01\n\x0eGetTaskRequest\x12\x16\n\x06tenant\x18\x03 \x01(\tR\x06tenant\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12*\n\x0ehistory_length\x18\x02 \x01(\x05H\x00R\rhistoryLength\x88\x01\x01\x42\x11\n\x0f_history_length\"\x9c\x03\n\x10ListTasksRequest\x12\x16\n\x06tenant\x18\t \x01(\tR\x06tenant\x12\x1d\n\ncontext_id\x18\x01 \x01(\tR\tcontextId\x12)\n\x06status\x18\x02 \x01(\x0e\x32\x11.a2a.v1.TaskStateR\x06status\x12 \n\tpage_size\x18\x03 \x01(\x05H\x00R\x08pageSize\x88\x01\x01\x12\x1d\n\npage_token\x18\x04 \x01(\tR\tpageToken\x12*\n\x0ehistory_length\x18\x05 \x01(\x05H\x01R\rhistoryLength\x88\x01\x01\x12P\n\x16status_timestamp_after\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x14statusTimestampAfter\x12\x30\n\x11include_artifacts\x18\x07 \x01(\x08H\x02R\x10includeArtifacts\x88\x01\x01\x42\x0c\n\n_page_sizeB\x11\n\x0f_history_lengthB\x14\n\x12_include_artifacts\"\xaf\x01\n\x11ListTasksResponse\x12\'\n\x05tasks\x18\x01 \x03(\x0b\x32\x0c.a2a.v1.TaskB\x03\xe0\x41\x02R\x05tasks\x12+\n\x0fnext_page_token\x18\x02 \x01(\tB\x03\xe0\x41\x02R\rnextPageToken\x12 \n\tpage_size\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x08pageSize\x12\"\n\ntotal_size\x18\x04 \x01(\x05\x42\x03\xe0\x41\x02R\ttotalSize\"?\n\x11\x43\x61ncelTaskRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"R\n$GetTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"U\n\'DeleteTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"\xbe\x01\n$SetTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12\x1b\n\x06parent\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06parent\x12 \n\tconfig_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08\x63onfigId\x12?\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\".a2a.v1.TaskPushNotificationConfigB\x03\xe0\x41\x02R\x06\x63onfig\"D\n\x16SubscribeToTaskRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\"\x93\x01\n%ListTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12\x16\n\x06parent\x18\x01 \x01(\tR\x06parent\x12\x1b\n\tpage_size\x18\x02 \x01(\x05R\x08pageSize\x12\x1d\n\npage_token\x18\x03 \x01(\tR\tpageToken\"5\n\x1bGetExtendedAgentCardRequest\x12\x16\n\x06tenant\x18\x01 \x01(\tR\x06tenant\"q\n\x13SendMessageResponse\x12\"\n\x04task\x18\x01 \x01(\x0b\x32\x0c.a2a.v1.TaskH\x00R\x04task\x12+\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageH\x00R\x07messageB\t\n\x07payload\"\xfe\x01\n\x0eStreamResponse\x12\"\n\x04task\x18\x01 \x01(\x0b\x32\x0c.a2a.v1.TaskH\x00R\x04task\x12+\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageH\x00R\x07message\x12\x44\n\rstatus_update\x18\x03 \x01(\x0b\x32\x1d.a2a.v1.TaskStatusUpdateEventH\x00R\x0cstatusUpdate\x12J\n\x0f\x61rtifact_update\x18\x04 \x01(\x0b\x32\x1f.a2a.v1.TaskArtifactUpdateEventH\x00R\x0e\x61rtifactUpdateB\t\n\x07payload\"\x8e\x01\n&ListTaskPushNotificationConfigResponse\x12<\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\".a2a.v1.TaskPushNotificationConfigR\x07\x63onfigs\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken*\xfa\x01\n\tTaskState\x12\x1a\n\x16TASK_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14TASK_STATE_SUBMITTED\x10\x01\x12\x16\n\x12TASK_STATE_WORKING\x10\x02\x12\x18\n\x14TASK_STATE_COMPLETED\x10\x03\x12\x15\n\x11TASK_STATE_FAILED\x10\x04\x12\x18\n\x14TASK_STATE_CANCELLED\x10\x05\x12\x1d\n\x19TASK_STATE_INPUT_REQUIRED\x10\x06\x12\x17\n\x13TASK_STATE_REJECTED\x10\x07\x12\x1c\n\x18TASK_STATE_AUTH_REQUIRED\x10\x08*;\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\r\n\tROLE_USER\x10\x01\x12\x0e\n\nROLE_AGENT\x10\x02\x32\xbe\x0e\n\nA2AService\x12}\n\x0bSendMessage\x12\x1a.a2a.v1.SendMessageRequest\x1a\x1b.a2a.v1.SendMessageResponse\"5\x82\xd3\xe4\x93\x02/\"\r/message:send:\x01*Z\x1b\"\x16/{tenant}/message:send:\x01*\x12\x87\x01\n\x14SendStreamingMessage\x12\x1a.a2a.v1.SendMessageRequest\x1a\x16.a2a.v1.StreamResponse\"9\x82\xd3\xe4\x93\x02\x33\"\x0f/message:stream:\x01*Z\x1d\"\x18/{tenant}/message:stream:\x01*0\x01\x12k\n\x07GetTask\x12\x16.a2a.v1.GetTaskRequest\x1a\x0c.a2a.v1.Task\":\xda\x41\x04name\x82\xd3\xe4\x93\x02-\x12\x0f/{name=tasks/*}Z\x1a\x12\x18/{tenant}/{name=tasks/*}\x12\x63\n\tListTasks\x12\x18.a2a.v1.ListTasksRequest\x1a\x19.a2a.v1.ListTasksResponse\"!\x82\xd3\xe4\x93\x02\x1b\x12\x06/tasksZ\x11\x12\x0f/{tenant}/tasks\x12~\n\nCancelTask\x12\x19.a2a.v1.CancelTaskRequest\x1a\x0c.a2a.v1.Task\"G\x82\xd3\xe4\x93\x02\x41\"\x16/{name=tasks/*}:cancel:\x01*Z$\"\x1f/{tenant}/{name=tasks/*}:cancel:\x01*\x12\x94\x01\n\x0fSubscribeToTask\x12\x1e.a2a.v1.SubscribeToTaskRequest\x1a\x16.a2a.v1.StreamResponse\"G\x82\xd3\xe4\x93\x02\x41\x12\x19/{name=tasks/*}:subscribeZ$\x12\"/{tenant}/{name=tasks/*}:subscribe0\x01\x12\xfb\x01\n\x1dSetTaskPushNotificationConfig\x12,.a2a.v1.SetTaskPushNotificationConfigRequest\x1a\".a2a.v1.TaskPushNotificationConfig\"\x87\x01\xda\x41\rparent,config\x82\xd3\xe4\x93\x02q\")/{parent=tasks/*/pushNotificationConfigs}:\x06\x63onfigZ<\"2/{tenant}/{parent=tasks/*/pushNotificationConfigs}:\x06\x63onfig\x12\xe1\x01\n\x1dGetTaskPushNotificationConfig\x12,.a2a.v1.GetTaskPushNotificationConfigRequest\x1a\".a2a.v1.TaskPushNotificationConfig\"n\xda\x41\x04name\x82\xd3\xe4\x93\x02\x61\x12)/{name=tasks/*/pushNotificationConfigs/*}Z4\x12\x32/{tenant}/{name=tasks/*/pushNotificationConfigs/*}\x12\xf1\x01\n\x1eListTaskPushNotificationConfig\x12-.a2a.v1.ListTaskPushNotificationConfigRequest\x1a..a2a.v1.ListTaskPushNotificationConfigResponse\"p\xda\x41\x06parent\x82\xd3\xe4\x93\x02\x61\x12)/{parent=tasks/*}/pushNotificationConfigsZ4\x12\x32/{tenant}/{parent=tasks/*}/pushNotificationConfigs\x12\x89\x01\n\x14GetExtendedAgentCard\x12#.a2a.v1.GetExtendedAgentCardRequest\x1a\x11.a2a.v1.AgentCard\"9\x82\xd3\xe4\x93\x02\x33\x12\x12/extendedAgentCardZ\x1d\x12\x1b/{tenant}/extendedAgentCard\x12\xdb\x01\n DeleteTaskPushNotificationConfig\x12/.a2a.v1.DeleteTaskPushNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"n\xda\x41\x04name\x82\xd3\xe4\x93\x02\x61*)/{name=tasks/*/pushNotificationConfigs/*}Z4*2/{tenant}/{name=tasks/*/pushNotificationConfigs/*}Bi\n\ncom.a2a.v1B\x08\x41\x32\x61ProtoP\x01Z\x18google.golang.org/a2a/v1\xa2\x02\x03\x41XX\xaa\x02\x06\x41\x32\x61.V1\xca\x02\x06\x41\x32\x61\\V1\xe2\x02\x12\x41\x32\x61\\V1\\GPBMetadata\xea\x02\x07\x41\x32\x61::V1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ta2a.proto\x12\x06\x61\x32\x61.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x83\x02\n\x18SendMessageConfiguration\x12\x32\n\x15\x61\x63\x63\x65pted_output_modes\x18\x01 \x03(\tR\x13\x61\x63\x63\x65ptedOutputModes\x12X\n\x18push_notification_config\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.PushNotificationConfigR\x16pushNotificationConfig\x12*\n\x0ehistory_length\x18\x03 \x01(\x05H\x00R\rhistoryLength\x88\x01\x01\x12\x1a\n\x08\x62locking\x18\x04 \x01(\x08R\x08\x62lockingB\x11\n\x0f_history_length\"\x80\x02\n\x04Task\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12/\n\x06status\x18\x03 \x01(\x0b\x32\x12.a2a.v1.TaskStatusB\x03\xe0\x41\x02R\x06status\x12.\n\tartifacts\x18\x04 \x03(\x0b\x32\x10.a2a.v1.ArtifactR\tartifacts\x12)\n\x07history\x18\x05 \x03(\x0b\x32\x0f.a2a.v1.MessageR\x07history\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\x9f\x01\n\nTaskStatus\x12,\n\x05state\x18\x01 \x01(\x0e\x32\x11.a2a.v1.TaskStateB\x03\xe0\x41\x02R\x05state\x12)\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageR\x07message\x12\x38\n\ttimestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimestamp\"\xed\x01\n\x04Part\x12\x14\n\x04text\x18\x01 \x01(\tH\x00R\x04text\x12\x12\n\x03raw\x18\x02 \x01(\x0cH\x00R\x03raw\x12\x12\n\x03url\x18\x03 \x01(\tH\x00R\x03url\x12,\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32\x16.google.protobuf.ValueH\x00R\x04\x64\x61ta\x12\x33\n\x08metadata\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\x12\x1a\n\x08\x66ilename\x18\x06 \x01(\tR\x08\x66ilename\x12\x1d\n\nmedia_type\x18\x07 \x01(\tR\tmediaTypeB\t\n\x07\x63ontent\"\xb8\x02\n\x07Message\x12\"\n\nmessage_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\tmessageId\x12\x1d\n\ncontext_id\x18\x02 \x01(\tR\tcontextId\x12\x17\n\x07task_id\x18\x03 \x01(\tR\x06taskId\x12%\n\x04role\x18\x04 \x01(\x0e\x32\x0c.a2a.v1.RoleB\x03\xe0\x41\x02R\x04role\x12\'\n\x05parts\x18\x05 \x03(\x0b\x32\x0c.a2a.v1.PartB\x03\xe0\x41\x02R\x05parts\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\x12\x1e\n\nextensions\x18\x07 \x03(\tR\nextensions\x12,\n\x12reference_task_ids\x18\x08 \x03(\tR\x10referenceTaskIds\"\xe4\x01\n\x08\x41rtifact\x12$\n\x0b\x61rtifact_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\nartifactId\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x04 \x01(\tR\x0b\x64\x65scription\x12\'\n\x05parts\x18\x05 \x03(\x0b\x32\x0c.a2a.v1.PartB\x03\xe0\x41\x02R\x05parts\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\x12\x1e\n\nextensions\x18\x07 \x03(\tR\nextensions\"\xc5\x01\n\x15TaskStatusUpdateEvent\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12/\n\x06status\x18\x03 \x01(\x0b\x32\x12.a2a.v1.TaskStatusB\x03\xe0\x41\x02R\x06status\x12\x33\n\x08metadata\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadataJ\x04\x08\x04\x10\x05\"\xfa\x01\n\x17TaskArtifactUpdateEvent\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\"\n\ncontext_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcontextId\x12\x31\n\x08\x61rtifact\x18\x03 \x01(\x0b\x32\x10.a2a.v1.ArtifactB\x03\xe0\x41\x02R\x08\x61rtifact\x12\x16\n\x06\x61ppend\x18\x04 \x01(\x08R\x06\x61ppend\x12\x1d\n\nlast_chunk\x18\x05 \x01(\x08R\tlastChunk\x12\x33\n\x08metadata\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"\x99\x01\n\x16PushNotificationConfig\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x15\n\x03url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x03url\x12\x14\n\x05token\x18\x03 \x01(\tR\x05token\x12\x42\n\x0e\x61uthentication\x18\x04 \x01(\x0b\x32\x1a.a2a.v1.AuthenticationInfoR\x0e\x61uthentication\"S\n\x12\x41uthenticationInfo\x12\x1b\n\x06scheme\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06scheme\x12 \n\x0b\x63redentials\x18\x02 \x01(\tR\x0b\x63redentials\"\x9f\x01\n\x0e\x41gentInterface\x12\x15\n\x03url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x03url\x12.\n\x10protocol_binding\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0fprotocolBinding\x12\x16\n\x06tenant\x18\x03 \x01(\tR\x06tenant\x12.\n\x10protocol_version\x18\x04 \x01(\tB\x03\xe0\x41\x02R\x0fprotocolVersion\"\x9e\x07\n\tAgentCard\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12N\n\x14supported_interfaces\x18\x13 \x03(\x0b\x32\x16.a2a.v1.AgentInterfaceB\x03\xe0\x41\x02R\x13supportedInterfaces\x12\x31\n\x08provider\x18\x04 \x01(\x0b\x32\x15.a2a.v1.AgentProviderR\x08provider\x12\x1d\n\x07version\x18\x05 \x01(\tB\x03\xe0\x41\x02R\x07version\x12\x30\n\x11\x64ocumentation_url\x18\x06 \x01(\tH\x00R\x10\x64ocumentationUrl\x88\x01\x01\x12\x42\n\x0c\x63\x61pabilities\x18\x07 \x01(\x0b\x32\x19.a2a.v1.AgentCapabilitiesB\x03\xe0\x41\x02R\x0c\x63\x61pabilities\x12Q\n\x10security_schemes\x18\x08 \x03(\x0b\x32&.a2a.v1.AgentCard.SecuritySchemesEntryR\x0fsecuritySchemes\x12P\n\x15security_requirements\x18\r \x03(\x0b\x32\x1b.a2a.v1.SecurityRequirementR\x14securityRequirements\x12\x33\n\x13\x64\x65\x66\x61ult_input_modes\x18\n \x03(\tB\x03\xe0\x41\x02R\x11\x64\x65\x66\x61ultInputModes\x12\x35\n\x14\x64\x65\x66\x61ult_output_modes\x18\x0b \x03(\tB\x03\xe0\x41\x02R\x12\x64\x65\x66\x61ultOutputModes\x12/\n\x06skills\x18\x0c \x03(\x0b\x32\x12.a2a.v1.AgentSkillB\x03\xe0\x41\x02R\x06skills\x12:\n\nsignatures\x18\x11 \x03(\x0b\x32\x1a.a2a.v1.AgentCardSignatureR\nsignatures\x12\x1e\n\x08icon_url\x18\x12 \x01(\tH\x01R\x07iconUrl\x88\x01\x01\x1aZ\n\x14SecuritySchemesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x16.a2a.v1.SecuritySchemeR\x05value:\x02\x38\x01\x42\x14\n\x12_documentation_urlB\x0b\n\t_icon_urlJ\x04\x08\x03\x10\x04J\x04\x08\t\x10\nJ\x04\x08\x0e\x10\x0fJ\x04\x08\x0f\x10\x10J\x04\x08\x10\x10\x11\"O\n\rAgentProvider\x12\x15\n\x03url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x03url\x12\'\n\x0corganization\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0corganization\"\x9a\x02\n\x11\x41gentCapabilities\x12!\n\tstreaming\x18\x01 \x01(\x08H\x00R\tstreaming\x88\x01\x01\x12\x32\n\x12push_notifications\x18\x02 \x01(\x08H\x01R\x11pushNotifications\x88\x01\x01\x12\x36\n\nextensions\x18\x03 \x03(\x0b\x32\x16.a2a.v1.AgentExtensionR\nextensions\x12\x33\n\x13\x65xtended_agent_card\x18\x05 \x01(\x08H\x02R\x11\x65xtendedAgentCard\x88\x01\x01\x42\x0c\n\n_streamingB\x15\n\x13_push_notificationsB\x16\n\x14_extended_agent_cardJ\x04\x08\x04\x10\x05\"\x91\x01\n\x0e\x41gentExtension\x12\x10\n\x03uri\x18\x01 \x01(\tR\x03uri\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12\x1a\n\x08required\x18\x03 \x01(\x08R\x08required\x12/\n\x06params\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x06params\"\xac\x02\n\nAgentSkill\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12\x17\n\x04tags\x18\x04 \x03(\tB\x03\xe0\x41\x02R\x04tags\x12\x1a\n\x08\x65xamples\x18\x05 \x03(\tR\x08\x65xamples\x12\x1f\n\x0binput_modes\x18\x06 \x03(\tR\ninputModes\x12!\n\x0coutput_modes\x18\x07 \x03(\tR\x0boutputModes\x12P\n\x15security_requirements\x18\x08 \x03(\x0b\x32\x1b.a2a.v1.SecurityRequirementR\x14securityRequirements\"\x8b\x01\n\x12\x41gentCardSignature\x12!\n\tprotected\x18\x01 \x01(\tB\x03\xe0\x41\x02R\tprotected\x12!\n\tsignature\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tsignature\x12/\n\x06header\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x06header\"\xc6\x01\n\x1aTaskPushNotificationConfig\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12\x1c\n\x07task_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12]\n\x18push_notification_config\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.PushNotificationConfigB\x03\xe0\x41\x02R\x16pushNotificationConfig\" \n\nStringList\x12\x12\n\x04list\x18\x01 \x03(\tR\x04list\"\xa9\x01\n\x13SecurityRequirement\x12\x42\n\x07schemes\x18\x01 \x03(\x0b\x32(.a2a.v1.SecurityRequirement.SchemesEntryR\x07schemes\x1aN\n\x0cSchemesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x12.a2a.v1.StringListR\x05value:\x02\x38\x01\"\xe6\x03\n\x0eSecurityScheme\x12U\n\x17\x61pi_key_security_scheme\x18\x01 \x01(\x0b\x32\x1c.a2a.v1.APIKeySecuritySchemeH\x00R\x14\x61piKeySecurityScheme\x12[\n\x19http_auth_security_scheme\x18\x02 \x01(\x0b\x32\x1e.a2a.v1.HTTPAuthSecuritySchemeH\x00R\x16httpAuthSecurityScheme\x12T\n\x16oauth2_security_scheme\x18\x03 \x01(\x0b\x32\x1c.a2a.v1.OAuth2SecuritySchemeH\x00R\x14oauth2SecurityScheme\x12k\n\x1fopen_id_connect_security_scheme\x18\x04 \x01(\x0b\x32#.a2a.v1.OpenIdConnectSecuritySchemeH\x00R\x1bopenIdConnectSecurityScheme\x12S\n\x14mtls_security_scheme\x18\x05 \x01(\x0b\x32\x1f.a2a.v1.MutualTlsSecuritySchemeH\x00R\x12mtlsSecuritySchemeB\x08\n\x06scheme\"r\n\x14\x41PIKeySecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x1f\n\x08location\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08location\x12\x17\n\x04name\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x04name\"|\n\x16HTTPAuthSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x1b\n\x06scheme\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x06scheme\x12#\n\rbearer_format\x18\x03 \x01(\tR\x0c\x62\x65\x61rerFormat\"\x97\x01\n\x14OAuth2SecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12-\n\x05\x66lows\x18\x02 \x01(\x0b\x32\x12.a2a.v1.OAuthFlowsB\x03\xe0\x41\x02R\x05\x66lows\x12.\n\x13oauth2_metadata_url\x18\x03 \x01(\tR\x11oauth2MetadataUrl\"s\n\x1bOpenIdConnectSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\x12\x32\n\x13open_id_connect_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x10openIdConnectUrl\";\n\x17MutualTlsSecurityScheme\x12 \n\x0b\x64\x65scription\x18\x01 \x01(\tR\x0b\x64\x65scription\"\xf8\x02\n\nOAuthFlows\x12S\n\x12\x61uthorization_code\x18\x01 \x01(\x0b\x32\".a2a.v1.AuthorizationCodeOAuthFlowH\x00R\x11\x61uthorizationCode\x12S\n\x12\x63lient_credentials\x18\x02 \x01(\x0b\x32\".a2a.v1.ClientCredentialsOAuthFlowH\x00R\x11\x63lientCredentials\x12;\n\x08implicit\x18\x03 \x01(\x0b\x32\x19.a2a.v1.ImplicitOAuthFlowB\x02\x18\x01H\x00R\x08implicit\x12;\n\x08password\x18\x04 \x01(\x0b\x32\x19.a2a.v1.PasswordOAuthFlowB\x02\x18\x01H\x00R\x08password\x12>\n\x0b\x64\x65vice_code\x18\x05 \x01(\x0b\x32\x1b.a2a.v1.DeviceCodeOAuthFlowH\x00R\ndeviceCodeB\x06\n\x04\x66low\"\xbe\x02\n\x1a\x41uthorizationCodeOAuthFlow\x12\x30\n\x11\x61uthorization_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x10\x61uthorizationUrl\x12 \n\ttoken_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x03 \x01(\tR\nrefreshUrl\x12K\n\x06scopes\x18\x04 \x03(\x0b\x32..a2a.v1.AuthorizationCodeOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x12#\n\rpkce_required\x18\x05 \x01(\x08R\x0cpkceRequired\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xe7\x01\n\x1a\x43lientCredentialsOAuthFlow\x12 \n\ttoken_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x02 \x01(\tR\nrefreshUrl\x12K\n\x06scopes\x18\x03 \x03(\x0b\x32..a2a.v1.ClientCredentialsOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xdb\x01\n\x11ImplicitOAuthFlow\x12+\n\x11\x61uthorization_url\x18\x01 \x01(\tR\x10\x61uthorizationUrl\x12\x1f\n\x0brefresh_url\x18\x02 \x01(\tR\nrefreshUrl\x12=\n\x06scopes\x18\x03 \x03(\x0b\x32%.a2a.v1.ImplicitOAuthFlow.ScopesEntryR\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xcb\x01\n\x11PasswordOAuthFlow\x12\x1b\n\ttoken_url\x18\x01 \x01(\tR\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x02 \x01(\tR\nrefreshUrl\x12=\n\x06scopes\x18\x03 \x03(\x0b\x32%.a2a.v1.PasswordOAuthFlow.ScopesEntryR\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\x98\x02\n\x13\x44\x65viceCodeOAuthFlow\x12=\n\x18\x64\x65vice_authorization_url\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x16\x64\x65viceAuthorizationUrl\x12 \n\ttoken_url\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08tokenUrl\x12\x1f\n\x0brefresh_url\x18\x03 \x01(\tR\nrefreshUrl\x12\x44\n\x06scopes\x18\x04 \x03(\x0b\x32\'.a2a.v1.DeviceCodeOAuthFlow.ScopesEntryB\x03\xe0\x41\x02R\x06scopes\x1a\x39\n\x0bScopesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xd9\x01\n\x12SendMessageRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12.\n\x07message\x18\x01 \x01(\x0b\x32\x0f.a2a.v1.MessageB\x03\xe0\x41\x02R\x07message\x12\x46\n\rconfiguration\x18\x02 \x01(\x0b\x32 .a2a.v1.SendMessageConfigurationR\rconfiguration\x12\x33\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"|\n\x0eGetTaskRequest\x12\x16\n\x06tenant\x18\x03 \x01(\tR\x06tenant\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\x12*\n\x0ehistory_length\x18\x02 \x01(\x05H\x00R\rhistoryLength\x88\x01\x01\x42\x11\n\x0f_history_length\"\x9c\x03\n\x10ListTasksRequest\x12\x16\n\x06tenant\x18\t \x01(\tR\x06tenant\x12\x1d\n\ncontext_id\x18\x01 \x01(\tR\tcontextId\x12)\n\x06status\x18\x02 \x01(\x0e\x32\x11.a2a.v1.TaskStateR\x06status\x12 \n\tpage_size\x18\x03 \x01(\x05H\x00R\x08pageSize\x88\x01\x01\x12\x1d\n\npage_token\x18\x04 \x01(\tR\tpageToken\x12*\n\x0ehistory_length\x18\x05 \x01(\x05H\x01R\rhistoryLength\x88\x01\x01\x12P\n\x16status_timestamp_after\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x14statusTimestampAfter\x12\x30\n\x11include_artifacts\x18\x07 \x01(\x08H\x02R\x10includeArtifacts\x88\x01\x01\x42\x0c\n\n_page_sizeB\x11\n\x0f_history_lengthB\x14\n\x12_include_artifacts\"\xaf\x01\n\x11ListTasksResponse\x12\'\n\x05tasks\x18\x01 \x03(\x0b\x32\x0c.a2a.v1.TaskB\x03\xe0\x41\x02R\x05tasks\x12+\n\x0fnext_page_token\x18\x02 \x01(\tB\x03\xe0\x41\x02R\rnextPageToken\x12 \n\tpage_size\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x08pageSize\x12\"\n\ntotal_size\x18\x04 \x01(\x05\x42\x03\xe0\x41\x02R\ttotalSize\"@\n\x11\x43\x61ncelTaskRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\"q\n$GetTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x1c\n\x07task_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\"t\n\'DeleteTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x1c\n\x07task_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\"\xc4\x01\n\'CreateTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12 \n\tconfig_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x08\x63onfigId\x12;\n\x06\x63onfig\x18\x05 \x01(\x0b\x32\x1e.a2a.v1.PushNotificationConfigB\x03\xe0\x41\x02R\x06\x63onfigJ\x04\x08\x03\x10\x04\"E\n\x16SubscribeToTaskRequest\x12\x16\n\x06tenant\x18\x02 \x01(\tR\x06tenant\x12\x13\n\x02id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x02id\"\x99\x01\n%ListTaskPushNotificationConfigRequest\x12\x16\n\x06tenant\x18\x04 \x01(\tR\x06tenant\x12\x1c\n\x07task_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06taskId\x12\x1b\n\tpage_size\x18\x02 \x01(\x05R\x08pageSize\x12\x1d\n\npage_token\x18\x03 \x01(\tR\tpageToken\"5\n\x1bGetExtendedAgentCardRequest\x12\x16\n\x06tenant\x18\x01 \x01(\tR\x06tenant\"q\n\x13SendMessageResponse\x12\"\n\x04task\x18\x01 \x01(\x0b\x32\x0c.a2a.v1.TaskH\x00R\x04task\x12+\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageH\x00R\x07messageB\t\n\x07payload\"\xfe\x01\n\x0eStreamResponse\x12\"\n\x04task\x18\x01 \x01(\x0b\x32\x0c.a2a.v1.TaskH\x00R\x04task\x12+\n\x07message\x18\x02 \x01(\x0b\x32\x0f.a2a.v1.MessageH\x00R\x07message\x12\x44\n\rstatus_update\x18\x03 \x01(\x0b\x32\x1d.a2a.v1.TaskStatusUpdateEventH\x00R\x0cstatusUpdate\x12J\n\x0f\x61rtifact_update\x18\x04 \x01(\x0b\x32\x1f.a2a.v1.TaskArtifactUpdateEventH\x00R\x0e\x61rtifactUpdateB\t\n\x07payload\"\x8e\x01\n&ListTaskPushNotificationConfigResponse\x12<\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\".a2a.v1.TaskPushNotificationConfigR\x07\x63onfigs\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken*\xf9\x01\n\tTaskState\x12\x1a\n\x16TASK_STATE_UNSPECIFIED\x10\x00\x12\x18\n\x14TASK_STATE_SUBMITTED\x10\x01\x12\x16\n\x12TASK_STATE_WORKING\x10\x02\x12\x18\n\x14TASK_STATE_COMPLETED\x10\x03\x12\x15\n\x11TASK_STATE_FAILED\x10\x04\x12\x17\n\x13TASK_STATE_CANCELED\x10\x05\x12\x1d\n\x19TASK_STATE_INPUT_REQUIRED\x10\x06\x12\x17\n\x13TASK_STATE_REJECTED\x10\x07\x12\x1c\n\x18TASK_STATE_AUTH_REQUIRED\x10\x08*;\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\r\n\tROLE_USER\x10\x01\x12\x0e\n\nROLE_AGENT\x10\x02\x32\xea\x0e\n\nA2AService\x12}\n\x0bSendMessage\x12\x1a.a2a.v1.SendMessageRequest\x1a\x1b.a2a.v1.SendMessageResponse\"5\x82\xd3\xe4\x93\x02/\"\r/message:send:\x01*Z\x1b\"\x16/{tenant}/message:send:\x01*\x12\x87\x01\n\x14SendStreamingMessage\x12\x1a.a2a.v1.SendMessageRequest\x1a\x16.a2a.v1.StreamResponse\"9\x82\xd3\xe4\x93\x02\x33\"\x0f/message:stream:\x01*Z\x1d\"\x18/{tenant}/message:stream:\x01*0\x01\x12\x65\n\x07GetTask\x12\x16.a2a.v1.GetTaskRequest\x1a\x0c.a2a.v1.Task\"4\xda\x41\x02id\x82\xd3\xe4\x93\x02)\x12\r/tasks/{id=*}Z\x18\x12\x16/{tenant}/tasks/{id=*}\x12\x63\n\tListTasks\x12\x18.a2a.v1.ListTasksRequest\x1a\x19.a2a.v1.ListTasksResponse\"!\x82\xd3\xe4\x93\x02\x1b\x12\x06/tasksZ\x11\x12\x0f/{tenant}/tasks\x12z\n\nCancelTask\x12\x19.a2a.v1.CancelTaskRequest\x1a\x0c.a2a.v1.Task\"C\x82\xd3\xe4\x93\x02=\"\x14/tasks/{id=*}:cancel:\x01*Z\"\"\x1d/{tenant}/tasks/{id=*}:cancel:\x01*\x12\x90\x01\n\x0fSubscribeToTask\x12\x1e.a2a.v1.SubscribeToTaskRequest\x1a\x16.a2a.v1.StreamResponse\"C\x82\xd3\xe4\x93\x02=\x12\x17/tasks/{id=*}:subscribeZ\"\x12 /{tenant}/tasks/{id=*}:subscribe0\x01\x12\x84\x02\n CreateTaskPushNotificationConfig\x12/.a2a.v1.CreateTaskPushNotificationConfigRequest\x1a\".a2a.v1.TaskPushNotificationConfig\"\x8a\x01\xda\x41\x0etask_id,config\x82\xd3\xe4\x93\x02s\"*/tasks/{task_id=*}/pushNotificationConfigs:\x06\x63onfigZ=\"3/{tenant}/tasks/{task_id=*}/pushNotificationConfigs:\x06\x63onfig\x12\xf8\x01\n\x1dGetTaskPushNotificationConfig\x12,.a2a.v1.GetTaskPushNotificationConfigRequest\x1a\".a2a.v1.TaskPushNotificationConfig\"\x84\x01\xda\x41\ntask_id,id\x82\xd3\xe4\x93\x02q\x12\x31/tasks/{task_id=*}/pushNotificationConfigs/{id=*}Z<\x12:/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}\x12\xf4\x01\n\x1eListTaskPushNotificationConfig\x12-.a2a.v1.ListTaskPushNotificationConfigRequest\x1a..a2a.v1.ListTaskPushNotificationConfigResponse\"s\xda\x41\x07task_id\x82\xd3\xe4\x93\x02\x63\x12*/tasks/{task_id=*}/pushNotificationConfigsZ5\x12\x33/{tenant}/tasks/{task_id=*}/pushNotificationConfigs\x12\x89\x01\n\x14GetExtendedAgentCard\x12#.a2a.v1.GetExtendedAgentCardRequest\x1a\x11.a2a.v1.AgentCard\"9\x82\xd3\xe4\x93\x02\x33\x12\x12/extendedAgentCardZ\x1d\x12\x1b/{tenant}/extendedAgentCard\x12\xf2\x01\n DeleteTaskPushNotificationConfig\x12/.a2a.v1.DeleteTaskPushNotificationConfigRequest\x1a\x16.google.protobuf.Empty\"\x84\x01\xda\x41\ntask_id,id\x82\xd3\xe4\x93\x02q*1/tasks/{task_id=*}/pushNotificationConfigs/{id=*}Z<*:/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}Bi\n\ncom.a2a.v1B\x08\x41\x32\x61ProtoP\x01Z\x18google.golang.org/a2a/v1\xa2\x02\x03\x41XX\xaa\x02\x06\x41\x32\x61.V1\xca\x02\x06\x41\x32\x61\\V1\xe2\x02\x12\x41\x32\x61\\V1\\GPBMetadata\xea\x02\x07\x41\x32\x61::V1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -46,8 +46,6 @@ _globals['_TASK'].fields_by_name['status']._serialized_options = b'\340A\002' _globals['_TASKSTATUS'].fields_by_name['state']._loaded_options = None _globals['_TASKSTATUS'].fields_by_name['state']._serialized_options = b'\340A\002' - _globals['_DATAPART'].fields_by_name['data']._loaded_options = None - _globals['_DATAPART'].fields_by_name['data']._serialized_options = b'\340A\002' _globals['_MESSAGE'].fields_by_name['message_id']._loaded_options = None _globals['_MESSAGE'].fields_by_name['message_id']._serialized_options = b'\340A\002' _globals['_MESSAGE'].fields_by_name['role']._loaded_options = None @@ -64,8 +62,6 @@ _globals['_TASKSTATUSUPDATEEVENT'].fields_by_name['context_id']._serialized_options = b'\340A\002' _globals['_TASKSTATUSUPDATEEVENT'].fields_by_name['status']._loaded_options = None _globals['_TASKSTATUSUPDATEEVENT'].fields_by_name['status']._serialized_options = b'\340A\002' - _globals['_TASKSTATUSUPDATEEVENT'].fields_by_name['final']._loaded_options = None - _globals['_TASKSTATUSUPDATEEVENT'].fields_by_name['final']._serialized_options = b'\340A\002' _globals['_TASKARTIFACTUPDATEEVENT'].fields_by_name['task_id']._loaded_options = None _globals['_TASKARTIFACTUPDATEEVENT'].fields_by_name['task_id']._serialized_options = b'\340A\002' _globals['_TASKARTIFACTUPDATEEVENT'].fields_by_name['context_id']._loaded_options = None @@ -74,16 +70,16 @@ _globals['_TASKARTIFACTUPDATEEVENT'].fields_by_name['artifact']._serialized_options = b'\340A\002' _globals['_PUSHNOTIFICATIONCONFIG'].fields_by_name['url']._loaded_options = None _globals['_PUSHNOTIFICATIONCONFIG'].fields_by_name['url']._serialized_options = b'\340A\002' - _globals['_AUTHENTICATIONINFO'].fields_by_name['schemes']._loaded_options = None - _globals['_AUTHENTICATIONINFO'].fields_by_name['schemes']._serialized_options = b'\340A\002' + _globals['_AUTHENTICATIONINFO'].fields_by_name['scheme']._loaded_options = None + _globals['_AUTHENTICATIONINFO'].fields_by_name['scheme']._serialized_options = b'\340A\002' _globals['_AGENTINTERFACE'].fields_by_name['url']._loaded_options = None _globals['_AGENTINTERFACE'].fields_by_name['url']._serialized_options = b'\340A\002' _globals['_AGENTINTERFACE'].fields_by_name['protocol_binding']._loaded_options = None _globals['_AGENTINTERFACE'].fields_by_name['protocol_binding']._serialized_options = b'\340A\002' + _globals['_AGENTINTERFACE'].fields_by_name['protocol_version']._loaded_options = None + _globals['_AGENTINTERFACE'].fields_by_name['protocol_version']._serialized_options = b'\340A\002' _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._loaded_options = None _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._serialized_options = b'8\001' - _globals['_AGENTCARD'].fields_by_name['protocol_versions']._loaded_options = None - _globals['_AGENTCARD'].fields_by_name['protocol_versions']._serialized_options = b'\340A\002' _globals['_AGENTCARD'].fields_by_name['name']._loaded_options = None _globals['_AGENTCARD'].fields_by_name['name']._serialized_options = b'\340A\002' _globals['_AGENTCARD'].fields_by_name['description']._loaded_options = None @@ -116,12 +112,14 @@ _globals['_AGENTCARDSIGNATURE'].fields_by_name['protected']._serialized_options = b'\340A\002' _globals['_AGENTCARDSIGNATURE'].fields_by_name['signature']._loaded_options = None _globals['_AGENTCARDSIGNATURE'].fields_by_name['signature']._serialized_options = b'\340A\002' - _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['name']._loaded_options = None - _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['name']._serialized_options = b'\340A\002' + _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['id']._loaded_options = None + _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['id']._serialized_options = b'\340A\002' + _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['task_id']._loaded_options = None + _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['task_id']._serialized_options = b'\340A\002' _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['push_notification_config']._loaded_options = None _globals['_TASKPUSHNOTIFICATIONCONFIG'].fields_by_name['push_notification_config']._serialized_options = b'\340A\002' - _globals['_SECURITY_SCHEMESENTRY']._loaded_options = None - _globals['_SECURITY_SCHEMESENTRY']._serialized_options = b'8\001' + _globals['_SECURITYREQUIREMENT_SCHEMESENTRY']._loaded_options = None + _globals['_SECURITYREQUIREMENT_SCHEMESENTRY']._serialized_options = b'8\001' _globals['_APIKEYSECURITYSCHEME'].fields_by_name['location']._loaded_options = None _globals['_APIKEYSECURITYSCHEME'].fields_by_name['location']._serialized_options = b'\340A\002' _globals['_APIKEYSECURITYSCHEME'].fields_by_name['name']._loaded_options = None @@ -132,6 +130,10 @@ _globals['_OAUTH2SECURITYSCHEME'].fields_by_name['flows']._serialized_options = b'\340A\002' _globals['_OPENIDCONNECTSECURITYSCHEME'].fields_by_name['open_id_connect_url']._loaded_options = None _globals['_OPENIDCONNECTSECURITYSCHEME'].fields_by_name['open_id_connect_url']._serialized_options = b'\340A\002' + _globals['_OAUTHFLOWS'].fields_by_name['implicit']._loaded_options = None + _globals['_OAUTHFLOWS'].fields_by_name['implicit']._serialized_options = b'\030\001' + _globals['_OAUTHFLOWS'].fields_by_name['password']._loaded_options = None + _globals['_OAUTHFLOWS'].fields_by_name['password']._serialized_options = b'\030\001' _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._loaded_options = None _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._serialized_options = b'8\001' _globals['_AUTHORIZATIONCODEOAUTHFLOW'].fields_by_name['authorization_url']._loaded_options = None @@ -146,6 +148,10 @@ _globals['_CLIENTCREDENTIALSOAUTHFLOW'].fields_by_name['token_url']._serialized_options = b'\340A\002' _globals['_CLIENTCREDENTIALSOAUTHFLOW'].fields_by_name['scopes']._loaded_options = None _globals['_CLIENTCREDENTIALSOAUTHFLOW'].fields_by_name['scopes']._serialized_options = b'\340A\002' + _globals['_IMPLICITOAUTHFLOW_SCOPESENTRY']._loaded_options = None + _globals['_IMPLICITOAUTHFLOW_SCOPESENTRY']._serialized_options = b'8\001' + _globals['_PASSWORDOAUTHFLOW_SCOPESENTRY']._loaded_options = None + _globals['_PASSWORDOAUTHFLOW_SCOPESENTRY']._serialized_options = b'8\001' _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._loaded_options = None _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._serialized_options = b'8\001' _globals['_DEVICECODEOAUTHFLOW'].fields_by_name['device_authorization_url']._loaded_options = None @@ -156,8 +162,8 @@ _globals['_DEVICECODEOAUTHFLOW'].fields_by_name['scopes']._serialized_options = b'\340A\002' _globals['_SENDMESSAGEREQUEST'].fields_by_name['message']._loaded_options = None _globals['_SENDMESSAGEREQUEST'].fields_by_name['message']._serialized_options = b'\340A\002' - _globals['_GETTASKREQUEST'].fields_by_name['name']._loaded_options = None - _globals['_GETTASKREQUEST'].fields_by_name['name']._serialized_options = b'\340A\002' + _globals['_GETTASKREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_GETTASKREQUEST'].fields_by_name['id']._serialized_options = b'\340A\002' _globals['_LISTTASKSRESPONSE'].fields_by_name['tasks']._loaded_options = None _globals['_LISTTASKSRESPONSE'].fields_by_name['tasks']._serialized_options = b'\340A\002' _globals['_LISTTASKSRESPONSE'].fields_by_name['next_page_token']._loaded_options = None @@ -166,38 +172,52 @@ _globals['_LISTTASKSRESPONSE'].fields_by_name['page_size']._serialized_options = b'\340A\002' _globals['_LISTTASKSRESPONSE'].fields_by_name['total_size']._loaded_options = None _globals['_LISTTASKSRESPONSE'].fields_by_name['total_size']._serialized_options = b'\340A\002' - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['parent']._loaded_options = None - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['parent']._serialized_options = b'\340A\002' - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config_id']._loaded_options = None - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config_id']._serialized_options = b'\340A\002' - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config']._loaded_options = None - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config']._serialized_options = b'\340A\002' + _globals['_CANCELTASKREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_CANCELTASKREQUEST'].fields_by_name['id']._serialized_options = b'\340A\002' + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._loaded_options = None + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._serialized_options = b'\340A\002' + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['id']._serialized_options = b'\340A\002' + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._loaded_options = None + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._serialized_options = b'\340A\002' + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['id']._serialized_options = b'\340A\002' + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._loaded_options = None + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._serialized_options = b'\340A\002' + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config_id']._loaded_options = None + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config_id']._serialized_options = b'\340A\002' + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config']._loaded_options = None + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['config']._serialized_options = b'\340A\002' + _globals['_SUBSCRIBETOTASKREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_SUBSCRIBETOTASKREQUEST'].fields_by_name['id']._serialized_options = b'\340A\002' + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._loaded_options = None + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST'].fields_by_name['task_id']._serialized_options = b'\340A\002' _globals['_A2ASERVICE'].methods_by_name['SendMessage']._loaded_options = None _globals['_A2ASERVICE'].methods_by_name['SendMessage']._serialized_options = b'\202\323\344\223\002/\"\r/message:send:\001*Z\033\"\026/{tenant}/message:send:\001*' _globals['_A2ASERVICE'].methods_by_name['SendStreamingMessage']._loaded_options = None _globals['_A2ASERVICE'].methods_by_name['SendStreamingMessage']._serialized_options = b'\202\323\344\223\0023\"\017/message:stream:\001*Z\035\"\030/{tenant}/message:stream:\001*' _globals['_A2ASERVICE'].methods_by_name['GetTask']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['GetTask']._serialized_options = b'\332A\004name\202\323\344\223\002-\022\017/{name=tasks/*}Z\032\022\030/{tenant}/{name=tasks/*}' + _globals['_A2ASERVICE'].methods_by_name['GetTask']._serialized_options = b'\332A\002id\202\323\344\223\002)\022\r/tasks/{id=*}Z\030\022\026/{tenant}/tasks/{id=*}' _globals['_A2ASERVICE'].methods_by_name['ListTasks']._loaded_options = None _globals['_A2ASERVICE'].methods_by_name['ListTasks']._serialized_options = b'\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tenant}/tasks' _globals['_A2ASERVICE'].methods_by_name['CancelTask']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['CancelTask']._serialized_options = b'\202\323\344\223\002A\"\026/{name=tasks/*}:cancel:\001*Z$\"\037/{tenant}/{name=tasks/*}:cancel:\001*' + _globals['_A2ASERVICE'].methods_by_name['CancelTask']._serialized_options = b'\202\323\344\223\002=\"\024/tasks/{id=*}:cancel:\001*Z\"\"\035/{tenant}/tasks/{id=*}:cancel:\001*' _globals['_A2ASERVICE'].methods_by_name['SubscribeToTask']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['SubscribeToTask']._serialized_options = b'\202\323\344\223\002A\022\031/{name=tasks/*}:subscribeZ$\022\"/{tenant}/{name=tasks/*}:subscribe' - _globals['_A2ASERVICE'].methods_by_name['SetTaskPushNotificationConfig']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['SetTaskPushNotificationConfig']._serialized_options = b'\332A\rparent,config\202\323\344\223\002q\")/{parent=tasks/*/pushNotificationConfigs}:\006configZ<\"2/{tenant}/{parent=tasks/*/pushNotificationConfigs}:\006config' + _globals['_A2ASERVICE'].methods_by_name['SubscribeToTask']._serialized_options = b'\202\323\344\223\002=\022\027/tasks/{id=*}:subscribeZ\"\022 /{tenant}/tasks/{id=*}:subscribe' + _globals['_A2ASERVICE'].methods_by_name['CreateTaskPushNotificationConfig']._loaded_options = None + _globals['_A2ASERVICE'].methods_by_name['CreateTaskPushNotificationConfig']._serialized_options = b'\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{task_id=*}/pushNotificationConfigs:\006configZ=\"3/{tenant}/tasks/{task_id=*}/pushNotificationConfigs:\006config' _globals['_A2ASERVICE'].methods_by_name['GetTaskPushNotificationConfig']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['GetTaskPushNotificationConfig']._serialized_options = b'\332A\004name\202\323\344\223\002a\022)/{name=tasks/*/pushNotificationConfigs/*}Z4\0222/{tenant}/{name=tasks/*/pushNotificationConfigs/*}' + _globals['_A2ASERVICE'].methods_by_name['GetTaskPushNotificationConfig']._serialized_options = b'\332A\ntask_id,id\202\323\344\223\002q\0221/tasks/{task_id=*}/pushNotificationConfigs/{id=*}Z<\022:/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}' _globals['_A2ASERVICE'].methods_by_name['ListTaskPushNotificationConfig']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['ListTaskPushNotificationConfig']._serialized_options = b'\332A\006parent\202\323\344\223\002a\022)/{parent=tasks/*}/pushNotificationConfigsZ4\0222/{tenant}/{parent=tasks/*}/pushNotificationConfigs' + _globals['_A2ASERVICE'].methods_by_name['ListTaskPushNotificationConfig']._serialized_options = b'\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=*}/pushNotificationConfigsZ5\0223/{tenant}/tasks/{task_id=*}/pushNotificationConfigs' _globals['_A2ASERVICE'].methods_by_name['GetExtendedAgentCard']._loaded_options = None _globals['_A2ASERVICE'].methods_by_name['GetExtendedAgentCard']._serialized_options = b'\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{tenant}/extendedAgentCard' _globals['_A2ASERVICE'].methods_by_name['DeleteTaskPushNotificationConfig']._loaded_options = None - _globals['_A2ASERVICE'].methods_by_name['DeleteTaskPushNotificationConfig']._serialized_options = b'\332A\004name\202\323\344\223\002a*)/{name=tasks/*/pushNotificationConfigs/*}Z4*2/{tenant}/{name=tasks/*/pushNotificationConfigs/*}' - _globals['_TASKSTATE']._serialized_start=9257 - _globals['_TASKSTATE']._serialized_end=9507 - _globals['_ROLE']._serialized_start=9509 - _globals['_ROLE']._serialized_end=9568 + _globals['_A2ASERVICE'].methods_by_name['DeleteTaskPushNotificationConfig']._serialized_options = b'\332A\ntask_id,id\202\323\344\223\002q*1/tasks/{task_id=*}/pushNotificationConfigs/{id=*}Z<*:/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}' + _globals['_TASKSTATE']._serialized_start=9766 + _globals['_TASKSTATE']._serialized_end=10015 + _globals['_ROLE']._serialized_start=10017 + _globals['_ROLE']._serialized_end=10076 _globals['_SENDMESSAGECONFIGURATION']._serialized_start=202 _globals['_SENDMESSAGECONFIGURATION']._serialized_end=461 _globals['_TASK']._serialized_start=464 @@ -205,101 +225,105 @@ _globals['_TASKSTATUS']._serialized_start=723 _globals['_TASKSTATUS']._serialized_end=882 _globals['_PART']._serialized_start=885 - _globals['_PART']._serialized_end=1054 - _globals['_FILEPART']._serialized_start=1057 - _globals['_FILEPART']._serialized_end=1206 - _globals['_DATAPART']._serialized_start=1208 - _globals['_DATAPART']._serialized_end=1268 - _globals['_MESSAGE']._serialized_start=1271 - _globals['_MESSAGE']._serialized_end=1583 - _globals['_ARTIFACT']._serialized_start=1586 - _globals['_ARTIFACT']._serialized_end=1814 - _globals['_TASKSTATUSUPDATEEVENT']._serialized_start=1817 - _globals['_TASKSTATUSUPDATEEVENT']._serialized_end=2035 - _globals['_TASKARTIFACTUPDATEEVENT']._serialized_start=2038 - _globals['_TASKARTIFACTUPDATEEVENT']._serialized_end=2288 - _globals['_PUSHNOTIFICATIONCONFIG']._serialized_start=2291 - _globals['_PUSHNOTIFICATIONCONFIG']._serialized_end=2444 - _globals['_AUTHENTICATIONINFO']._serialized_start=2446 - _globals['_AUTHENTICATIONINFO']._serialized_end=2531 - _globals['_AGENTINTERFACE']._serialized_start=2533 - _globals['_AGENTINTERFACE']._serialized_end=2644 - _globals['_AGENTCARD']._serialized_start=2647 - _globals['_AGENTCARD']._serialized_end=3575 - _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._serialized_start=3432 - _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._serialized_end=3522 - _globals['_AGENTPROVIDER']._serialized_start=3577 - _globals['_AGENTPROVIDER']._serialized_end=3656 - _globals['_AGENTCAPABILITIES']._serialized_start=3659 - _globals['_AGENTCAPABILITIES']._serialized_end=4027 - _globals['_AGENTEXTENSION']._serialized_start=4030 - _globals['_AGENTEXTENSION']._serialized_end=4175 - _globals['_AGENTSKILL']._serialized_start=4178 - _globals['_AGENTSKILL']._serialized_end=4442 - _globals['_AGENTCARDSIGNATURE']._serialized_start=4445 - _globals['_AGENTCARDSIGNATURE']._serialized_end=4584 - _globals['_TASKPUSHNOTIFICATIONCONFIG']._serialized_start=4587 - _globals['_TASKPUSHNOTIFICATIONCONFIG']._serialized_end=4735 - _globals['_STRINGLIST']._serialized_start=4737 - _globals['_STRINGLIST']._serialized_end=4769 - _globals['_SECURITY']._serialized_start=4772 - _globals['_SECURITY']._serialized_end=4919 - _globals['_SECURITY_SCHEMESENTRY']._serialized_start=4841 - _globals['_SECURITY_SCHEMESENTRY']._serialized_end=4919 - _globals['_SECURITYSCHEME']._serialized_start=4922 - _globals['_SECURITYSCHEME']._serialized_end=5408 - _globals['_APIKEYSECURITYSCHEME']._serialized_start=5410 - _globals['_APIKEYSECURITYSCHEME']._serialized_end=5524 - _globals['_HTTPAUTHSECURITYSCHEME']._serialized_start=5526 - _globals['_HTTPAUTHSECURITYSCHEME']._serialized_end=5650 - _globals['_OAUTH2SECURITYSCHEME']._serialized_start=5653 - _globals['_OAUTH2SECURITYSCHEME']._serialized_end=5804 - _globals['_OPENIDCONNECTSECURITYSCHEME']._serialized_start=5806 - _globals['_OPENIDCONNECTSECURITYSCHEME']._serialized_end=5921 - _globals['_MUTUALTLSSECURITYSCHEME']._serialized_start=5923 - _globals['_MUTUALTLSSECURITYSCHEME']._serialized_end=5982 - _globals['_OAUTHFLOWS']._serialized_start=5985 - _globals['_OAUTHFLOWS']._serialized_end=6251 - _globals['_AUTHORIZATIONCODEOAUTHFLOW']._serialized_start=6254 - _globals['_AUTHORIZATIONCODEOAUTHFLOW']._serialized_end=6572 - _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._serialized_start=6515 - _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._serialized_end=6572 - _globals['_CLIENTCREDENTIALSOAUTHFLOW']._serialized_start=6575 - _globals['_CLIENTCREDENTIALSOAUTHFLOW']._serialized_end=6806 - _globals['_CLIENTCREDENTIALSOAUTHFLOW_SCOPESENTRY']._serialized_start=6515 - _globals['_CLIENTCREDENTIALSOAUTHFLOW_SCOPESENTRY']._serialized_end=6572 - _globals['_DEVICECODEOAUTHFLOW']._serialized_start=6809 - _globals['_DEVICECODEOAUTHFLOW']._serialized_end=7089 - _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._serialized_start=6515 - _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._serialized_end=6572 - _globals['_SENDMESSAGEREQUEST']._serialized_start=7092 - _globals['_SENDMESSAGEREQUEST']._serialized_end=7309 - _globals['_GETTASKREQUEST']._serialized_start=7312 - _globals['_GETTASKREQUEST']._serialized_end=7440 - _globals['_LISTTASKSREQUEST']._serialized_start=7443 - _globals['_LISTTASKSREQUEST']._serialized_end=7855 - _globals['_LISTTASKSRESPONSE']._serialized_start=7858 - _globals['_LISTTASKSRESPONSE']._serialized_end=8033 - _globals['_CANCELTASKREQUEST']._serialized_start=8035 - _globals['_CANCELTASKREQUEST']._serialized_end=8098 - _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8100 - _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8182 - _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8184 - _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8269 - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8272 - _globals['_SETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8462 - _globals['_SUBSCRIBETOTASKREQUEST']._serialized_start=8464 - _globals['_SUBSCRIBETOTASKREQUEST']._serialized_end=8532 - _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8535 - _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8682 - _globals['_GETEXTENDEDAGENTCARDREQUEST']._serialized_start=8684 - _globals['_GETEXTENDEDAGENTCARDREQUEST']._serialized_end=8737 - _globals['_SENDMESSAGERESPONSE']._serialized_start=8739 - _globals['_SENDMESSAGERESPONSE']._serialized_end=8852 - _globals['_STREAMRESPONSE']._serialized_start=8855 - _globals['_STREAMRESPONSE']._serialized_end=9109 - _globals['_LISTTASKPUSHNOTIFICATIONCONFIGRESPONSE']._serialized_start=9112 - _globals['_LISTTASKPUSHNOTIFICATIONCONFIGRESPONSE']._serialized_end=9254 - _globals['_A2ASERVICE']._serialized_start=9571 - _globals['_A2ASERVICE']._serialized_end=11425 + _globals['_PART']._serialized_end=1122 + _globals['_MESSAGE']._serialized_start=1125 + _globals['_MESSAGE']._serialized_end=1437 + _globals['_ARTIFACT']._serialized_start=1440 + _globals['_ARTIFACT']._serialized_end=1668 + _globals['_TASKSTATUSUPDATEEVENT']._serialized_start=1671 + _globals['_TASKSTATUSUPDATEEVENT']._serialized_end=1868 + _globals['_TASKARTIFACTUPDATEEVENT']._serialized_start=1871 + _globals['_TASKARTIFACTUPDATEEVENT']._serialized_end=2121 + _globals['_PUSHNOTIFICATIONCONFIG']._serialized_start=2124 + _globals['_PUSHNOTIFICATIONCONFIG']._serialized_end=2277 + _globals['_AUTHENTICATIONINFO']._serialized_start=2279 + _globals['_AUTHENTICATIONINFO']._serialized_end=2362 + _globals['_AGENTINTERFACE']._serialized_start=2365 + _globals['_AGENTINTERFACE']._serialized_end=2524 + _globals['_AGENTCARD']._serialized_start=2527 + _globals['_AGENTCARD']._serialized_end=3453 + _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._serialized_start=3298 + _globals['_AGENTCARD_SECURITYSCHEMESENTRY']._serialized_end=3388 + _globals['_AGENTPROVIDER']._serialized_start=3455 + _globals['_AGENTPROVIDER']._serialized_end=3534 + _globals['_AGENTCAPABILITIES']._serialized_start=3537 + _globals['_AGENTCAPABILITIES']._serialized_end=3819 + _globals['_AGENTEXTENSION']._serialized_start=3822 + _globals['_AGENTEXTENSION']._serialized_end=3967 + _globals['_AGENTSKILL']._serialized_start=3970 + _globals['_AGENTSKILL']._serialized_end=4270 + _globals['_AGENTCARDSIGNATURE']._serialized_start=4273 + _globals['_AGENTCARDSIGNATURE']._serialized_end=4412 + _globals['_TASKPUSHNOTIFICATIONCONFIG']._serialized_start=4415 + _globals['_TASKPUSHNOTIFICATIONCONFIG']._serialized_end=4613 + _globals['_STRINGLIST']._serialized_start=4615 + _globals['_STRINGLIST']._serialized_end=4647 + _globals['_SECURITYREQUIREMENT']._serialized_start=4650 + _globals['_SECURITYREQUIREMENT']._serialized_end=4819 + _globals['_SECURITYREQUIREMENT_SCHEMESENTRY']._serialized_start=4741 + _globals['_SECURITYREQUIREMENT_SCHEMESENTRY']._serialized_end=4819 + _globals['_SECURITYSCHEME']._serialized_start=4822 + _globals['_SECURITYSCHEME']._serialized_end=5308 + _globals['_APIKEYSECURITYSCHEME']._serialized_start=5310 + _globals['_APIKEYSECURITYSCHEME']._serialized_end=5424 + _globals['_HTTPAUTHSECURITYSCHEME']._serialized_start=5426 + _globals['_HTTPAUTHSECURITYSCHEME']._serialized_end=5550 + _globals['_OAUTH2SECURITYSCHEME']._serialized_start=5553 + _globals['_OAUTH2SECURITYSCHEME']._serialized_end=5704 + _globals['_OPENIDCONNECTSECURITYSCHEME']._serialized_start=5706 + _globals['_OPENIDCONNECTSECURITYSCHEME']._serialized_end=5821 + _globals['_MUTUALTLSSECURITYSCHEME']._serialized_start=5823 + _globals['_MUTUALTLSSECURITYSCHEME']._serialized_end=5882 + _globals['_OAUTHFLOWS']._serialized_start=5885 + _globals['_OAUTHFLOWS']._serialized_end=6261 + _globals['_AUTHORIZATIONCODEOAUTHFLOW']._serialized_start=6264 + _globals['_AUTHORIZATIONCODEOAUTHFLOW']._serialized_end=6582 + _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._serialized_start=6525 + _globals['_AUTHORIZATIONCODEOAUTHFLOW_SCOPESENTRY']._serialized_end=6582 + _globals['_CLIENTCREDENTIALSOAUTHFLOW']._serialized_start=6585 + _globals['_CLIENTCREDENTIALSOAUTHFLOW']._serialized_end=6816 + _globals['_CLIENTCREDENTIALSOAUTHFLOW_SCOPESENTRY']._serialized_start=6525 + _globals['_CLIENTCREDENTIALSOAUTHFLOW_SCOPESENTRY']._serialized_end=6582 + _globals['_IMPLICITOAUTHFLOW']._serialized_start=6819 + _globals['_IMPLICITOAUTHFLOW']._serialized_end=7038 + _globals['_IMPLICITOAUTHFLOW_SCOPESENTRY']._serialized_start=6525 + _globals['_IMPLICITOAUTHFLOW_SCOPESENTRY']._serialized_end=6582 + _globals['_PASSWORDOAUTHFLOW']._serialized_start=7041 + _globals['_PASSWORDOAUTHFLOW']._serialized_end=7244 + _globals['_PASSWORDOAUTHFLOW_SCOPESENTRY']._serialized_start=6525 + _globals['_PASSWORDOAUTHFLOW_SCOPESENTRY']._serialized_end=6582 + _globals['_DEVICECODEOAUTHFLOW']._serialized_start=7247 + _globals['_DEVICECODEOAUTHFLOW']._serialized_end=7527 + _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._serialized_start=6525 + _globals['_DEVICECODEOAUTHFLOW_SCOPESENTRY']._serialized_end=6582 + _globals['_SENDMESSAGEREQUEST']._serialized_start=7530 + _globals['_SENDMESSAGEREQUEST']._serialized_end=7747 + _globals['_GETTASKREQUEST']._serialized_start=7749 + _globals['_GETTASKREQUEST']._serialized_end=7873 + _globals['_LISTTASKSREQUEST']._serialized_start=7876 + _globals['_LISTTASKSREQUEST']._serialized_end=8288 + _globals['_LISTTASKSRESPONSE']._serialized_start=8291 + _globals['_LISTTASKSRESPONSE']._serialized_end=8466 + _globals['_CANCELTASKREQUEST']._serialized_start=8468 + _globals['_CANCELTASKREQUEST']._serialized_end=8532 + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8534 + _globals['_GETTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8647 + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8649 + _globals['_DELETETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8765 + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=8768 + _globals['_CREATETASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=8964 + _globals['_SUBSCRIBETOTASKREQUEST']._serialized_start=8966 + _globals['_SUBSCRIBETOTASKREQUEST']._serialized_end=9035 + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_start=9038 + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGREQUEST']._serialized_end=9191 + _globals['_GETEXTENDEDAGENTCARDREQUEST']._serialized_start=9193 + _globals['_GETEXTENDEDAGENTCARDREQUEST']._serialized_end=9246 + _globals['_SENDMESSAGERESPONSE']._serialized_start=9248 + _globals['_SENDMESSAGERESPONSE']._serialized_end=9361 + _globals['_STREAMRESPONSE']._serialized_start=9364 + _globals['_STREAMRESPONSE']._serialized_end=9618 + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGRESPONSE']._serialized_start=9621 + _globals['_LISTTASKPUSHNOTIFICATIONCONFIGRESPONSE']._serialized_end=9763 + _globals['_A2ASERVICE']._serialized_start=10079 + _globals['_A2ASERVICE']._serialized_end=11977 # @@protoc_insertion_point(module_scope) diff --git a/src/a2a/types/a2a_pb2.pyi b/src/a2a/types/a2a_pb2.pyi index 2e12fd482..8a205b052 100644 --- a/src/a2a/types/a2a_pb2.pyi +++ b/src/a2a/types/a2a_pb2.pyi @@ -22,7 +22,7 @@ class TaskState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): TASK_STATE_WORKING: _ClassVar[TaskState] TASK_STATE_COMPLETED: _ClassVar[TaskState] TASK_STATE_FAILED: _ClassVar[TaskState] - TASK_STATE_CANCELLED: _ClassVar[TaskState] + TASK_STATE_CANCELED: _ClassVar[TaskState] TASK_STATE_INPUT_REQUIRED: _ClassVar[TaskState] TASK_STATE_REJECTED: _ClassVar[TaskState] TASK_STATE_AUTH_REQUIRED: _ClassVar[TaskState] @@ -37,7 +37,7 @@ TASK_STATE_SUBMITTED: TaskState TASK_STATE_WORKING: TaskState TASK_STATE_COMPLETED: TaskState TASK_STATE_FAILED: TaskState -TASK_STATE_CANCELLED: TaskState +TASK_STATE_CANCELED: TaskState TASK_STATE_INPUT_REQUIRED: TaskState TASK_STATE_REJECTED: TaskState TASK_STATE_AUTH_REQUIRED: TaskState @@ -84,34 +84,22 @@ class TaskStatus(_message.Message): def __init__(self, state: _Optional[_Union[TaskState, str]] = ..., message: _Optional[_Union[Message, _Mapping]] = ..., timestamp: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... class Part(_message.Message): - __slots__ = ("text", "file", "data", "metadata") + __slots__ = ("text", "raw", "url", "data", "metadata", "filename", "media_type") TEXT_FIELD_NUMBER: _ClassVar[int] - FILE_FIELD_NUMBER: _ClassVar[int] + RAW_FIELD_NUMBER: _ClassVar[int] + URL_FIELD_NUMBER: _ClassVar[int] DATA_FIELD_NUMBER: _ClassVar[int] METADATA_FIELD_NUMBER: _ClassVar[int] + FILENAME_FIELD_NUMBER: _ClassVar[int] + MEDIA_TYPE_FIELD_NUMBER: _ClassVar[int] text: str - file: FilePart - data: DataPart + raw: bytes + url: str + data: _struct_pb2.Value metadata: _struct_pb2.Struct - def __init__(self, text: _Optional[str] = ..., file: _Optional[_Union[FilePart, _Mapping]] = ..., data: _Optional[_Union[DataPart, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... - -class FilePart(_message.Message): - __slots__ = ("file_with_uri", "file_with_bytes", "media_type", "name") - FILE_WITH_URI_FIELD_NUMBER: _ClassVar[int] - FILE_WITH_BYTES_FIELD_NUMBER: _ClassVar[int] - MEDIA_TYPE_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] - file_with_uri: str - file_with_bytes: bytes + filename: str media_type: str - name: str - def __init__(self, file_with_uri: _Optional[str] = ..., file_with_bytes: _Optional[bytes] = ..., media_type: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ... - -class DataPart(_message.Message): - __slots__ = ("data",) - DATA_FIELD_NUMBER: _ClassVar[int] - data: _struct_pb2.Struct - def __init__(self, data: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + def __init__(self, text: _Optional[str] = ..., raw: _Optional[bytes] = ..., url: _Optional[str] = ..., data: _Optional[_Union[_struct_pb2.Value, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., filename: _Optional[str] = ..., media_type: _Optional[str] = ...) -> None: ... class Message(_message.Message): __slots__ = ("message_id", "context_id", "task_id", "role", "parts", "metadata", "extensions", "reference_task_ids") @@ -150,18 +138,16 @@ class Artifact(_message.Message): def __init__(self, artifact_id: _Optional[str] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., parts: _Optional[_Iterable[_Union[Part, _Mapping]]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., extensions: _Optional[_Iterable[str]] = ...) -> None: ... class TaskStatusUpdateEvent(_message.Message): - __slots__ = ("task_id", "context_id", "status", "final", "metadata") + __slots__ = ("task_id", "context_id", "status", "metadata") TASK_ID_FIELD_NUMBER: _ClassVar[int] CONTEXT_ID_FIELD_NUMBER: _ClassVar[int] STATUS_FIELD_NUMBER: _ClassVar[int] - FINAL_FIELD_NUMBER: _ClassVar[int] METADATA_FIELD_NUMBER: _ClassVar[int] task_id: str context_id: str status: TaskStatus - final: bool metadata: _struct_pb2.Struct - def __init__(self, task_id: _Optional[str] = ..., context_id: _Optional[str] = ..., status: _Optional[_Union[TaskStatus, _Mapping]] = ..., final: _Optional[bool] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + def __init__(self, task_id: _Optional[str] = ..., context_id: _Optional[str] = ..., status: _Optional[_Union[TaskStatus, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class TaskArtifactUpdateEvent(_message.Message): __slots__ = ("task_id", "context_id", "artifact", "append", "last_chunk", "metadata") @@ -192,25 +178,27 @@ class PushNotificationConfig(_message.Message): def __init__(self, id: _Optional[str] = ..., url: _Optional[str] = ..., token: _Optional[str] = ..., authentication: _Optional[_Union[AuthenticationInfo, _Mapping]] = ...) -> None: ... class AuthenticationInfo(_message.Message): - __slots__ = ("schemes", "credentials") - SCHEMES_FIELD_NUMBER: _ClassVar[int] + __slots__ = ("scheme", "credentials") + SCHEME_FIELD_NUMBER: _ClassVar[int] CREDENTIALS_FIELD_NUMBER: _ClassVar[int] - schemes: _containers.RepeatedScalarFieldContainer[str] + scheme: str credentials: str - def __init__(self, schemes: _Optional[_Iterable[str]] = ..., credentials: _Optional[str] = ...) -> None: ... + def __init__(self, scheme: _Optional[str] = ..., credentials: _Optional[str] = ...) -> None: ... class AgentInterface(_message.Message): - __slots__ = ("url", "protocol_binding", "tenant") + __slots__ = ("url", "protocol_binding", "tenant", "protocol_version") URL_FIELD_NUMBER: _ClassVar[int] PROTOCOL_BINDING_FIELD_NUMBER: _ClassVar[int] TENANT_FIELD_NUMBER: _ClassVar[int] + PROTOCOL_VERSION_FIELD_NUMBER: _ClassVar[int] url: str protocol_binding: str tenant: str - def __init__(self, url: _Optional[str] = ..., protocol_binding: _Optional[str] = ..., tenant: _Optional[str] = ...) -> None: ... + protocol_version: str + def __init__(self, url: _Optional[str] = ..., protocol_binding: _Optional[str] = ..., tenant: _Optional[str] = ..., protocol_version: _Optional[str] = ...) -> None: ... class AgentCard(_message.Message): - __slots__ = ("protocol_versions", "name", "description", "supported_interfaces", "provider", "version", "documentation_url", "capabilities", "security_schemes", "security", "default_input_modes", "default_output_modes", "skills", "signatures", "icon_url") + __slots__ = ("name", "description", "supported_interfaces", "provider", "version", "documentation_url", "capabilities", "security_schemes", "security_requirements", "default_input_modes", "default_output_modes", "skills", "signatures", "icon_url") class SecuritySchemesEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] @@ -218,7 +206,6 @@ class AgentCard(_message.Message): key: str value: SecurityScheme def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SecurityScheme, _Mapping]] = ...) -> None: ... - PROTOCOL_VERSIONS_FIELD_NUMBER: _ClassVar[int] NAME_FIELD_NUMBER: _ClassVar[int] DESCRIPTION_FIELD_NUMBER: _ClassVar[int] SUPPORTED_INTERFACES_FIELD_NUMBER: _ClassVar[int] @@ -227,13 +214,12 @@ class AgentCard(_message.Message): DOCUMENTATION_URL_FIELD_NUMBER: _ClassVar[int] CAPABILITIES_FIELD_NUMBER: _ClassVar[int] SECURITY_SCHEMES_FIELD_NUMBER: _ClassVar[int] - SECURITY_FIELD_NUMBER: _ClassVar[int] + SECURITY_REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] DEFAULT_INPUT_MODES_FIELD_NUMBER: _ClassVar[int] DEFAULT_OUTPUT_MODES_FIELD_NUMBER: _ClassVar[int] SKILLS_FIELD_NUMBER: _ClassVar[int] SIGNATURES_FIELD_NUMBER: _ClassVar[int] ICON_URL_FIELD_NUMBER: _ClassVar[int] - protocol_versions: _containers.RepeatedScalarFieldContainer[str] name: str description: str supported_interfaces: _containers.RepeatedCompositeFieldContainer[AgentInterface] @@ -242,13 +228,13 @@ class AgentCard(_message.Message): documentation_url: str capabilities: AgentCapabilities security_schemes: _containers.MessageMap[str, SecurityScheme] - security: _containers.RepeatedCompositeFieldContainer[Security] + security_requirements: _containers.RepeatedCompositeFieldContainer[SecurityRequirement] default_input_modes: _containers.RepeatedScalarFieldContainer[str] default_output_modes: _containers.RepeatedScalarFieldContainer[str] skills: _containers.RepeatedCompositeFieldContainer[AgentSkill] signatures: _containers.RepeatedCompositeFieldContainer[AgentCardSignature] icon_url: str - def __init__(self, protocol_versions: _Optional[_Iterable[str]] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., supported_interfaces: _Optional[_Iterable[_Union[AgentInterface, _Mapping]]] = ..., provider: _Optional[_Union[AgentProvider, _Mapping]] = ..., version: _Optional[str] = ..., documentation_url: _Optional[str] = ..., capabilities: _Optional[_Union[AgentCapabilities, _Mapping]] = ..., security_schemes: _Optional[_Mapping[str, SecurityScheme]] = ..., security: _Optional[_Iterable[_Union[Security, _Mapping]]] = ..., default_input_modes: _Optional[_Iterable[str]] = ..., default_output_modes: _Optional[_Iterable[str]] = ..., skills: _Optional[_Iterable[_Union[AgentSkill, _Mapping]]] = ..., signatures: _Optional[_Iterable[_Union[AgentCardSignature, _Mapping]]] = ..., icon_url: _Optional[str] = ...) -> None: ... + def __init__(self, name: _Optional[str] = ..., description: _Optional[str] = ..., supported_interfaces: _Optional[_Iterable[_Union[AgentInterface, _Mapping]]] = ..., provider: _Optional[_Union[AgentProvider, _Mapping]] = ..., version: _Optional[str] = ..., documentation_url: _Optional[str] = ..., capabilities: _Optional[_Union[AgentCapabilities, _Mapping]] = ..., security_schemes: _Optional[_Mapping[str, SecurityScheme]] = ..., security_requirements: _Optional[_Iterable[_Union[SecurityRequirement, _Mapping]]] = ..., default_input_modes: _Optional[_Iterable[str]] = ..., default_output_modes: _Optional[_Iterable[str]] = ..., skills: _Optional[_Iterable[_Union[AgentSkill, _Mapping]]] = ..., signatures: _Optional[_Iterable[_Union[AgentCardSignature, _Mapping]]] = ..., icon_url: _Optional[str] = ...) -> None: ... class AgentProvider(_message.Message): __slots__ = ("url", "organization") @@ -259,18 +245,16 @@ class AgentProvider(_message.Message): def __init__(self, url: _Optional[str] = ..., organization: _Optional[str] = ...) -> None: ... class AgentCapabilities(_message.Message): - __slots__ = ("streaming", "push_notifications", "extensions", "state_transition_history", "extended_agent_card") + __slots__ = ("streaming", "push_notifications", "extensions", "extended_agent_card") STREAMING_FIELD_NUMBER: _ClassVar[int] PUSH_NOTIFICATIONS_FIELD_NUMBER: _ClassVar[int] EXTENSIONS_FIELD_NUMBER: _ClassVar[int] - STATE_TRANSITION_HISTORY_FIELD_NUMBER: _ClassVar[int] EXTENDED_AGENT_CARD_FIELD_NUMBER: _ClassVar[int] streaming: bool push_notifications: bool extensions: _containers.RepeatedCompositeFieldContainer[AgentExtension] - state_transition_history: bool extended_agent_card: bool - def __init__(self, streaming: _Optional[bool] = ..., push_notifications: _Optional[bool] = ..., extensions: _Optional[_Iterable[_Union[AgentExtension, _Mapping]]] = ..., state_transition_history: _Optional[bool] = ..., extended_agent_card: _Optional[bool] = ...) -> None: ... + def __init__(self, streaming: _Optional[bool] = ..., push_notifications: _Optional[bool] = ..., extensions: _Optional[_Iterable[_Union[AgentExtension, _Mapping]]] = ..., extended_agent_card: _Optional[bool] = ...) -> None: ... class AgentExtension(_message.Message): __slots__ = ("uri", "description", "required", "params") @@ -285,7 +269,7 @@ class AgentExtension(_message.Message): def __init__(self, uri: _Optional[str] = ..., description: _Optional[str] = ..., required: _Optional[bool] = ..., params: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class AgentSkill(_message.Message): - __slots__ = ("id", "name", "description", "tags", "examples", "input_modes", "output_modes", "security") + __slots__ = ("id", "name", "description", "tags", "examples", "input_modes", "output_modes", "security_requirements") ID_FIELD_NUMBER: _ClassVar[int] NAME_FIELD_NUMBER: _ClassVar[int] DESCRIPTION_FIELD_NUMBER: _ClassVar[int] @@ -293,7 +277,7 @@ class AgentSkill(_message.Message): EXAMPLES_FIELD_NUMBER: _ClassVar[int] INPUT_MODES_FIELD_NUMBER: _ClassVar[int] OUTPUT_MODES_FIELD_NUMBER: _ClassVar[int] - SECURITY_FIELD_NUMBER: _ClassVar[int] + SECURITY_REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] id: str name: str description: str @@ -301,8 +285,8 @@ class AgentSkill(_message.Message): examples: _containers.RepeatedScalarFieldContainer[str] input_modes: _containers.RepeatedScalarFieldContainer[str] output_modes: _containers.RepeatedScalarFieldContainer[str] - security: _containers.RepeatedCompositeFieldContainer[Security] - def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., tags: _Optional[_Iterable[str]] = ..., examples: _Optional[_Iterable[str]] = ..., input_modes: _Optional[_Iterable[str]] = ..., output_modes: _Optional[_Iterable[str]] = ..., security: _Optional[_Iterable[_Union[Security, _Mapping]]] = ...) -> None: ... + security_requirements: _containers.RepeatedCompositeFieldContainer[SecurityRequirement] + def __init__(self, id: _Optional[str] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., tags: _Optional[_Iterable[str]] = ..., examples: _Optional[_Iterable[str]] = ..., input_modes: _Optional[_Iterable[str]] = ..., output_modes: _Optional[_Iterable[str]] = ..., security_requirements: _Optional[_Iterable[_Union[SecurityRequirement, _Mapping]]] = ...) -> None: ... class AgentCardSignature(_message.Message): __slots__ = ("protected", "signature", "header") @@ -315,12 +299,16 @@ class AgentCardSignature(_message.Message): def __init__(self, protected: _Optional[str] = ..., signature: _Optional[str] = ..., header: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class TaskPushNotificationConfig(_message.Message): - __slots__ = ("name", "push_notification_config") - NAME_FIELD_NUMBER: _ClassVar[int] + __slots__ = ("tenant", "id", "task_id", "push_notification_config") + TENANT_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] + TASK_ID_FIELD_NUMBER: _ClassVar[int] PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER: _ClassVar[int] - name: str + tenant: str + id: str + task_id: str push_notification_config: PushNotificationConfig - def __init__(self, name: _Optional[str] = ..., push_notification_config: _Optional[_Union[PushNotificationConfig, _Mapping]] = ...) -> None: ... + def __init__(self, tenant: _Optional[str] = ..., id: _Optional[str] = ..., task_id: _Optional[str] = ..., push_notification_config: _Optional[_Union[PushNotificationConfig, _Mapping]] = ...) -> None: ... class StringList(_message.Message): __slots__ = ("list",) @@ -328,7 +316,7 @@ class StringList(_message.Message): list: _containers.RepeatedScalarFieldContainer[str] def __init__(self, list: _Optional[_Iterable[str]] = ...) -> None: ... -class Security(_message.Message): +class SecurityRequirement(_message.Message): __slots__ = ("schemes",) class SchemesEntry(_message.Message): __slots__ = ("key", "value") @@ -400,14 +388,18 @@ class MutualTlsSecurityScheme(_message.Message): def __init__(self, description: _Optional[str] = ...) -> None: ... class OAuthFlows(_message.Message): - __slots__ = ("authorization_code", "client_credentials", "device_code") + __slots__ = ("authorization_code", "client_credentials", "implicit", "password", "device_code") AUTHORIZATION_CODE_FIELD_NUMBER: _ClassVar[int] CLIENT_CREDENTIALS_FIELD_NUMBER: _ClassVar[int] + IMPLICIT_FIELD_NUMBER: _ClassVar[int] + PASSWORD_FIELD_NUMBER: _ClassVar[int] DEVICE_CODE_FIELD_NUMBER: _ClassVar[int] authorization_code: AuthorizationCodeOAuthFlow client_credentials: ClientCredentialsOAuthFlow + implicit: ImplicitOAuthFlow + password: PasswordOAuthFlow device_code: DeviceCodeOAuthFlow - def __init__(self, authorization_code: _Optional[_Union[AuthorizationCodeOAuthFlow, _Mapping]] = ..., client_credentials: _Optional[_Union[ClientCredentialsOAuthFlow, _Mapping]] = ..., device_code: _Optional[_Union[DeviceCodeOAuthFlow, _Mapping]] = ...) -> None: ... + def __init__(self, authorization_code: _Optional[_Union[AuthorizationCodeOAuthFlow, _Mapping]] = ..., client_credentials: _Optional[_Union[ClientCredentialsOAuthFlow, _Mapping]] = ..., implicit: _Optional[_Union[ImplicitOAuthFlow, _Mapping]] = ..., password: _Optional[_Union[PasswordOAuthFlow, _Mapping]] = ..., device_code: _Optional[_Union[DeviceCodeOAuthFlow, _Mapping]] = ...) -> None: ... class AuthorizationCodeOAuthFlow(_message.Message): __slots__ = ("authorization_url", "token_url", "refresh_url", "scopes", "pkce_required") @@ -447,6 +439,40 @@ class ClientCredentialsOAuthFlow(_message.Message): scopes: _containers.ScalarMap[str, str] def __init__(self, token_url: _Optional[str] = ..., refresh_url: _Optional[str] = ..., scopes: _Optional[_Mapping[str, str]] = ...) -> None: ... +class ImplicitOAuthFlow(_message.Message): + __slots__ = ("authorization_url", "refresh_url", "scopes") + class ScopesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + AUTHORIZATION_URL_FIELD_NUMBER: _ClassVar[int] + REFRESH_URL_FIELD_NUMBER: _ClassVar[int] + SCOPES_FIELD_NUMBER: _ClassVar[int] + authorization_url: str + refresh_url: str + scopes: _containers.ScalarMap[str, str] + def __init__(self, authorization_url: _Optional[str] = ..., refresh_url: _Optional[str] = ..., scopes: _Optional[_Mapping[str, str]] = ...) -> None: ... + +class PasswordOAuthFlow(_message.Message): + __slots__ = ("token_url", "refresh_url", "scopes") + class ScopesEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: str + def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + TOKEN_URL_FIELD_NUMBER: _ClassVar[int] + REFRESH_URL_FIELD_NUMBER: _ClassVar[int] + SCOPES_FIELD_NUMBER: _ClassVar[int] + token_url: str + refresh_url: str + scopes: _containers.ScalarMap[str, str] + def __init__(self, token_url: _Optional[str] = ..., refresh_url: _Optional[str] = ..., scopes: _Optional[_Mapping[str, str]] = ...) -> None: ... + class DeviceCodeOAuthFlow(_message.Message): __slots__ = ("device_authorization_url", "token_url", "refresh_url", "scopes") class ScopesEntry(_message.Message): @@ -479,14 +505,14 @@ class SendMessageRequest(_message.Message): def __init__(self, tenant: _Optional[str] = ..., message: _Optional[_Union[Message, _Mapping]] = ..., configuration: _Optional[_Union[SendMessageConfiguration, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... class GetTaskRequest(_message.Message): - __slots__ = ("tenant", "name", "history_length") + __slots__ = ("tenant", "id", "history_length") TENANT_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] HISTORY_LENGTH_FIELD_NUMBER: _ClassVar[int] tenant: str - name: str + id: str history_length: int - def __init__(self, tenant: _Optional[str] = ..., name: _Optional[str] = ..., history_length: _Optional[int] = ...) -> None: ... + def __init__(self, tenant: _Optional[str] = ..., id: _Optional[str] = ..., history_length: _Optional[int] = ...) -> None: ... class ListTasksRequest(_message.Message): __slots__ = ("tenant", "context_id", "status", "page_size", "page_token", "history_length", "status_timestamp_after", "include_artifacts") @@ -521,60 +547,64 @@ class ListTasksResponse(_message.Message): def __init__(self, tasks: _Optional[_Iterable[_Union[Task, _Mapping]]] = ..., next_page_token: _Optional[str] = ..., page_size: _Optional[int] = ..., total_size: _Optional[int] = ...) -> None: ... class CancelTaskRequest(_message.Message): - __slots__ = ("tenant", "name") + __slots__ = ("tenant", "id") TENANT_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] tenant: str - name: str - def __init__(self, tenant: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ... + id: str + def __init__(self, tenant: _Optional[str] = ..., id: _Optional[str] = ...) -> None: ... class GetTaskPushNotificationConfigRequest(_message.Message): - __slots__ = ("tenant", "name") + __slots__ = ("tenant", "task_id", "id") TENANT_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] + TASK_ID_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] tenant: str - name: str - def __init__(self, tenant: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ... + task_id: str + id: str + def __init__(self, tenant: _Optional[str] = ..., task_id: _Optional[str] = ..., id: _Optional[str] = ...) -> None: ... class DeleteTaskPushNotificationConfigRequest(_message.Message): - __slots__ = ("tenant", "name") + __slots__ = ("tenant", "task_id", "id") TENANT_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] + TASK_ID_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] tenant: str - name: str - def __init__(self, tenant: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ... + task_id: str + id: str + def __init__(self, tenant: _Optional[str] = ..., task_id: _Optional[str] = ..., id: _Optional[str] = ...) -> None: ... -class SetTaskPushNotificationConfigRequest(_message.Message): - __slots__ = ("tenant", "parent", "config_id", "config") +class CreateTaskPushNotificationConfigRequest(_message.Message): + __slots__ = ("tenant", "task_id", "config_id", "config") TENANT_FIELD_NUMBER: _ClassVar[int] - PARENT_FIELD_NUMBER: _ClassVar[int] + TASK_ID_FIELD_NUMBER: _ClassVar[int] CONFIG_ID_FIELD_NUMBER: _ClassVar[int] CONFIG_FIELD_NUMBER: _ClassVar[int] tenant: str - parent: str + task_id: str config_id: str - config: TaskPushNotificationConfig - def __init__(self, tenant: _Optional[str] = ..., parent: _Optional[str] = ..., config_id: _Optional[str] = ..., config: _Optional[_Union[TaskPushNotificationConfig, _Mapping]] = ...) -> None: ... + config: PushNotificationConfig + def __init__(self, tenant: _Optional[str] = ..., task_id: _Optional[str] = ..., config_id: _Optional[str] = ..., config: _Optional[_Union[PushNotificationConfig, _Mapping]] = ...) -> None: ... class SubscribeToTaskRequest(_message.Message): - __slots__ = ("tenant", "name") + __slots__ = ("tenant", "id") TENANT_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_NUMBER: _ClassVar[int] + ID_FIELD_NUMBER: _ClassVar[int] tenant: str - name: str - def __init__(self, tenant: _Optional[str] = ..., name: _Optional[str] = ...) -> None: ... + id: str + def __init__(self, tenant: _Optional[str] = ..., id: _Optional[str] = ...) -> None: ... class ListTaskPushNotificationConfigRequest(_message.Message): - __slots__ = ("tenant", "parent", "page_size", "page_token") + __slots__ = ("tenant", "task_id", "page_size", "page_token") TENANT_FIELD_NUMBER: _ClassVar[int] - PARENT_FIELD_NUMBER: _ClassVar[int] + TASK_ID_FIELD_NUMBER: _ClassVar[int] PAGE_SIZE_FIELD_NUMBER: _ClassVar[int] PAGE_TOKEN_FIELD_NUMBER: _ClassVar[int] tenant: str - parent: str + task_id: str page_size: int page_token: str - def __init__(self, tenant: _Optional[str] = ..., parent: _Optional[str] = ..., page_size: _Optional[int] = ..., page_token: _Optional[str] = ...) -> None: ... + def __init__(self, tenant: _Optional[str] = ..., task_id: _Optional[str] = ..., page_size: _Optional[int] = ..., page_token: _Optional[str] = ...) -> None: ... class GetExtendedAgentCardRequest(_message.Message): __slots__ = ("tenant",) diff --git a/src/a2a/types/a2a_pb2_grpc.py b/src/a2a/types/a2a_pb2_grpc.py index f929e2ce1..9c625d011 100644 --- a/src/a2a/types/a2a_pb2_grpc.py +++ b/src/a2a/types/a2a_pb2_grpc.py @@ -46,9 +46,9 @@ def __init__(self, channel): request_serializer=a2a__pb2.SubscribeToTaskRequest.SerializeToString, response_deserializer=a2a__pb2.StreamResponse.FromString, _registered_method=True) - self.SetTaskPushNotificationConfig = channel.unary_unary( - '/a2a.v1.A2AService/SetTaskPushNotificationConfig', - request_serializer=a2a__pb2.SetTaskPushNotificationConfigRequest.SerializeToString, + self.CreateTaskPushNotificationConfig = channel.unary_unary( + '/a2a.v1.A2AService/CreateTaskPushNotificationConfig', + request_serializer=a2a__pb2.CreateTaskPushNotificationConfigRequest.SerializeToString, response_deserializer=a2a__pb2.TaskPushNotificationConfig.FromString, _registered_method=True) self.GetTaskPushNotificationConfig = channel.unary_unary( @@ -114,14 +114,14 @@ def CancelTask(self, request, context): def SubscribeToTask(self, request, context): """SubscribeToTask allows subscribing to task updates for tasks not in terminal state. - Returns UnsupportedOperationError if task is in terminal state (completed, failed, cancelled, rejected). + Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected). """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def SetTaskPushNotificationConfig(self, request, context): - """Set a push notification config for a task. + def CreateTaskPushNotificationConfig(self, request, context): + """Create a push notification config for a task. """ context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_details('Method not implemented!') @@ -188,9 +188,9 @@ def add_A2AServiceServicer_to_server(servicer, server): request_deserializer=a2a__pb2.SubscribeToTaskRequest.FromString, response_serializer=a2a__pb2.StreamResponse.SerializeToString, ), - 'SetTaskPushNotificationConfig': grpc.unary_unary_rpc_method_handler( - servicer.SetTaskPushNotificationConfig, - request_deserializer=a2a__pb2.SetTaskPushNotificationConfigRequest.FromString, + 'CreateTaskPushNotificationConfig': grpc.unary_unary_rpc_method_handler( + servicer.CreateTaskPushNotificationConfig, + request_deserializer=a2a__pb2.CreateTaskPushNotificationConfigRequest.FromString, response_serializer=a2a__pb2.TaskPushNotificationConfig.SerializeToString, ), 'GetTaskPushNotificationConfig': grpc.unary_unary_rpc_method_handler( @@ -388,7 +388,7 @@ def SubscribeToTask(request, _registered_method=True) @staticmethod - def SetTaskPushNotificationConfig(request, + def CreateTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, @@ -401,8 +401,8 @@ def SetTaskPushNotificationConfig(request, return grpc.experimental.unary_unary( request, target, - '/a2a.v1.A2AService/SetTaskPushNotificationConfig', - a2a__pb2.SetTaskPushNotificationConfigRequest.SerializeToString, + '/a2a.v1.A2AService/CreateTaskPushNotificationConfig', + a2a__pb2.CreateTaskPushNotificationConfigRequest.SerializeToString, a2a__pb2.TaskPushNotificationConfig.FromString, options, channel_credentials, diff --git a/src/a2a/utils/artifact.py b/src/a2a/utils/artifact.py index 6576c41ae..ac14087dc 100644 --- a/src/a2a/utils/artifact.py +++ b/src/a2a/utils/artifact.py @@ -4,9 +4,9 @@ from typing import Any -from google.protobuf.struct_pb2 import Struct +from google.protobuf.struct_pb2 import Struct, Value -from a2a.types.a2a_pb2 import Artifact, DataPart, Part +from a2a.types.a2a_pb2 import Artifact, Part from a2a.utils.parts import get_text_parts @@ -60,7 +60,7 @@ def new_data_artifact( data: dict[str, Any], description: str | None = None, ) -> Artifact: - """Creates a new Artifact object containing only a single DataPart. + """Creates a new Artifact object containing only a single data Part. Args: name: The human-readable name of the artifact. @@ -73,7 +73,7 @@ def new_data_artifact( struct_data = Struct() struct_data.update(data) return new_artifact( - [Part(data=DataPart(data=struct_data))], + [Part(data=Value(struct_value=struct_data))], name, description, ) diff --git a/src/a2a/utils/constants.py b/src/a2a/utils/constants.py index 615fce17b..f455f8f42 100644 --- a/src/a2a/utils/constants.py +++ b/src/a2a/utils/constants.py @@ -19,3 +19,7 @@ class TransportProtocol: jsonrpc = TRANSPORT_JSONRPC http_json = TRANSPORT_HTTP_JSON grpc = TRANSPORT_GRPC + + +DEFAULT_MAX_CONTENT_LENGTH = 10 * 1024 * 1024 # 10MB +JSONRPC_PARSE_ERROR_CODE = -32700 diff --git a/src/a2a/utils/error_handlers.py b/src/a2a/utils/error_handlers.py index 5802f5cee..2b3ffe692 100644 --- a/src/a2a/utils/error_handlers.py +++ b/src/a2a/utils/error_handlers.py @@ -2,7 +2,7 @@ import logging from collections.abc import Awaitable, Callable, Coroutine -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, cast if TYPE_CHECKING: @@ -88,7 +88,9 @@ async def wrapper(*args: Any, **kwargs: Any) -> Response: error = e.error or InternalError( message='Internal error due to unknown reason' ) - http_code = A2AErrorToHttpStatus.get(type(error), 500) + http_code = A2AErrorToHttpStatus.get( + cast('_A2AErrorType', type(error)), 500 + ) log_level = ( logging.ERROR @@ -99,13 +101,14 @@ async def wrapper(*args: Any, **kwargs: Any) -> Response: log_level, "Request error: Code=%s, Message='%s'%s", getattr(error, 'code', 'N/A'), - error.message, + getattr(error, 'message', str(error)), ', Data=' + str(getattr(error, 'data', '')) if getattr(error, 'data', None) else '', ) return JSONResponse( - content={'message': error.message}, status_code=http_code + content={'message': getattr(error, 'message', str(error))}, + status_code=http_code, ) except Exception: logger.exception('Unknown error occurred') @@ -139,7 +142,7 @@ async def wrapper(*args: Any, **kwargs: Any) -> Any: log_level, "Request error: Code=%s, Message='%s'%s", getattr(error, 'code', 'N/A'), - error.message, + getattr(error, 'message', str(error)), ', Data=' + str(getattr(error, 'data', '')) if getattr(error, 'data', None) else '', diff --git a/src/a2a/utils/errors.py b/src/a2a/utils/errors.py index 3703c2dbe..ef26ab117 100644 --- a/src/a2a/utils/errors.py +++ b/src/a2a/utils/errors.py @@ -5,7 +5,7 @@ """ -class A2AException(Exception): +class A2AError(Exception): """Base exception for A2A errors.""" message: str = 'A2A Error' @@ -16,54 +16,81 @@ def __init__(self, message: str | None = None): super().__init__(self.message) -class TaskNotFoundError(A2AException): +class TaskNotFoundError(A2AError): + """Exception raised when a task is not found.""" + message = 'Task not found' -class TaskNotCancelableError(A2AException): +class TaskNotCancelableError(A2AError): + """Exception raised when a task cannot be canceled.""" + message = 'Task cannot be canceled' -class PushNotificationNotSupportedError(A2AException): +class PushNotificationNotSupportedError(A2AError): + """Exception raised when push notifications are not supported.""" + message = 'Push Notification is not supported' -class UnsupportedOperationError(A2AException): +class UnsupportedOperationError(A2AError): + """Exception raised when an operation is not supported.""" + message = 'This operation is not supported' -class ContentTypeNotSupportedError(A2AException): +class ContentTypeNotSupportedError(A2AError): + """Exception raised when the content type is incompatible.""" + message = 'Incompatible content types' -class InternalError(A2AException): +class InternalError(A2AError): + """Exception raised for internal server errors.""" + message = 'Internal error' -class InvalidAgentResponseError(A2AException): +class InvalidAgentResponseError(A2AError): + """Exception raised when the agent response is invalid.""" + message = 'Invalid agent response' -class AuthenticatedExtendedCardNotConfiguredError(A2AException): +class AuthenticatedExtendedCardNotConfiguredError(A2AError): + """Exception raised when the authenticated extended card is not configured.""" + message = 'Authenticated Extended Card is not configured' -class InvalidParamsError(A2AException): +class InvalidParamsError(A2AError): + """Exception raised when parameters are invalid.""" + message = 'Invalid params' -class InvalidRequestError(A2AException): +class InvalidRequestError(A2AError): + """Exception raised when the request is invalid.""" + message = 'Invalid Request' -class MethodNotFoundError(A2AException): +class MethodNotFoundError(A2AError): + """Exception raised when a method is not found.""" + message = 'Method not found' +# For backward compatibility +A2AException = A2AError + + # For backward compatibility if needed, or just aliases for clean refactor # We remove the Pydantic models here. __all__ = [ + 'A2AError', 'A2AException', 'A2AServerError', 'AuthenticatedExtendedCardNotConfiguredError', diff --git a/src/a2a/utils/parts.py b/src/a2a/utils/parts.py index 1b3c7a7e5..1d0aaff46 100644 --- a/src/a2a/utils/parts.py +++ b/src/a2a/utils/parts.py @@ -6,7 +6,6 @@ from google.protobuf.json_format import MessageToDict from a2a.types.a2a_pb2 import ( - FilePart, Part, ) @@ -24,26 +23,24 @@ def get_text_parts(parts: Sequence[Part]) -> list[str]: def get_data_parts(parts: Sequence[Part]) -> list[dict[str, Any]]: - """Extracts dictionary data from all DataPart objects in a list of Parts. + """Extracts dictionary data from all data Parts in a list of Parts. Args: parts: A sequence of `Part` objects. Returns: - A list of dictionaries containing the data from any `DataPart` objects found. + A list of dictionaries containing the data from any data Parts found. """ - return [ - MessageToDict(part.data.data) for part in parts if part.HasField('data') - ] + return [MessageToDict(part.data) for part in parts if part.HasField('data')] -def get_file_parts(parts: Sequence[Part]) -> list[FilePart]: - """Extracts file data from all FilePart objects in a list of Parts. +def get_file_parts(parts: Sequence[Part]) -> list[Part]: + """Extracts file parts from a list of Parts. Args: parts: A sequence of `Part` objects. Returns: - A list of `FilePart` objects containing the file data from any `FilePart` objects found. + A list of `Part` objects containing file data (raw or url). """ - return [part.file for part in parts if part.HasField('file')] + return [part for part in parts if part.raw or part.url] diff --git a/src/a2a/utils/telemetry.py b/src/a2a/utils/telemetry.py index c73d2ac92..22d1e8730 100644 --- a/src/a2a/utils/telemetry.py +++ b/src/a2a/utils/telemetry.py @@ -61,6 +61,8 @@ def internal_method(self): from collections.abc import Callable from typing import TYPE_CHECKING, Any +from typing_extensions import Self + if TYPE_CHECKING: from opentelemetry.trace import SpanKind as SpanKindType @@ -86,7 +88,7 @@ class _NoOp: def __call__(self, *args: Any, **kwargs: Any) -> Any: return self - def __enter__(self) -> '_NoOp': + def __enter__(self) -> Self: return self def __exit__(self, *args: object, **kwargs: Any) -> None: diff --git a/tests/client/test_auth_middleware.py b/tests/client/test_auth_middleware.py index dca1bd1ee..ad3714f49 100644 --- a/tests/client/test_auth_middleware.py +++ b/tests/client/test_auth_middleware.py @@ -30,7 +30,7 @@ OAuthFlows, OpenIdConnectSecurityScheme, Role, - Security, + SecurityRequirement, SecurityScheme, SendMessageResponse, StringList, @@ -320,7 +320,9 @@ async def test_auth_interceptor_variants( default_output_modes=[], skills=[], capabilities=AgentCapabilities(), - security=[Security(schemes={test_case.scheme_name: StringList()})], + security_requirements=[ + SecurityRequirement(schemes={test_case.scheme_name: StringList()}) + ], security_schemes={ test_case.scheme_name: wrap_security_scheme( test_case.security_scheme @@ -370,7 +372,9 @@ async def test_auth_interceptor_skips_when_scheme_not_in_security_schemes( default_output_modes=[], skills=[], capabilities=AgentCapabilities(), - security=[Security(schemes={scheme_name: StringList()})], + security_requirements=[ + SecurityRequirement(schemes={scheme_name: StringList()}) + ], security_schemes={}, ) diff --git a/tests/client/test_client_factory.py b/tests/client/test_client_factory.py index 16b457b07..fd4fe1bc2 100644 --- a/tests/client/test_client_factory.py +++ b/tests/client/test_client_factory.py @@ -32,7 +32,6 @@ def base_agent_card() -> AgentCard: skills=[], default_input_modes=[], default_output_modes=[], - protocol_versions=['v1'], ) diff --git a/tests/client/test_client_task_manager.py b/tests/client/test_client_task_manager.py index 1abf8b0fd..4d7cbcaaa 100644 --- a/tests/client/test_client_task_manager.py +++ b/tests/client/test_client_task_manager.py @@ -100,7 +100,6 @@ async def test_process_with_status_update( status=TaskStatus( state=TaskState.TASK_STATE_COMPLETED, message=sample_message ), - final=True, ) status_event = StreamResponse(status_update=status_update) updated_task = await task_manager.process(status_event) @@ -145,7 +144,6 @@ async def test_process_creates_task_if_not_exists_on_status_update( task_id='new_task', context_id='new_context', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=False, ) status_event = StreamResponse(status_update=status_update) updated_task = await task_manager.process(status_event) diff --git a/tests/client/transports/test_grpc_client.py b/tests/client/transports/test_grpc_client.py index d6c978a39..f868b351d 100644 --- a/tests/client/transports/test_grpc_client.py +++ b/tests/client/transports/test_grpc_client.py @@ -19,7 +19,7 @@ PushNotificationConfig, Role, SendMessageRequest, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, Task, TaskArtifactUpdateEvent, TaskPushNotificationConfig, @@ -39,7 +39,7 @@ def mock_grpc_stub() -> AsyncMock: stub.SendStreamingMessage = MagicMock() stub.GetTask = AsyncMock() stub.CancelTask = AsyncMock() - stub.SetTaskPushNotificationConfig = AsyncMock() + stub.CreateTaskPushNotificationConfig = AsyncMock() stub.GetTaskPushNotificationConfig = AsyncMock() return stub @@ -133,7 +133,6 @@ def sample_task_status_update_event() -> TaskStatusUpdateEvent: task_id='task-1', context_id='ctx-1', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=False, metadata={}, ) @@ -156,9 +155,7 @@ def sample_task_artifact_update_event( @pytest.fixture def sample_authentication_info() -> AuthenticationInfo: """Provides a sample AuthenticationInfo object.""" - return AuthenticationInfo( - schemes=['apikey', 'oauth2'], credentials='secret-token' - ) + return AuthenticationInfo(scheme='apikey', credentials='secret-token') @pytest.fixture @@ -180,7 +177,8 @@ def sample_task_push_notification_config( ) -> TaskPushNotificationConfig: """Provides a sample TaskPushNotificationConfig object.""" return TaskPushNotificationConfig( - name='tasks/task-1', + task_id='tasks/task-1', + id=sample_push_notification_config.id, push_notification_config=sample_push_notification_config, ) @@ -308,13 +306,13 @@ async def test_get_task( ) -> None: """Test retrieving a task.""" mock_grpc_stub.GetTask.return_value = sample_task - params = GetTaskRequest(name=f'tasks/{sample_task.id}') + params = GetTaskRequest(id=f'tasks/{sample_task.id}') response = await grpc_transport.get_task(params) mock_grpc_stub.GetTask.assert_awaited_once_with( a2a_pb2.GetTaskRequest( - name=f'tasks/{sample_task.id}', history_length=None + id=f'tasks/{sample_task.id}', history_length=None ), metadata=[ ( @@ -334,14 +332,14 @@ async def test_get_task_with_history( mock_grpc_stub.GetTask.return_value = sample_task history_len = 10 params = GetTaskRequest( - name=f'tasks/{sample_task.id}', history_length=history_len + id=f'tasks/{sample_task.id}', history_length=history_len ) await grpc_transport.get_task(params) mock_grpc_stub.GetTask.assert_awaited_once_with( a2a_pb2.GetTaskRequest( - name=f'tasks/{sample_task.id}', history_length=history_len + id=f'tasks/{sample_task.id}', history_length=history_len ), metadata=[ ( @@ -360,20 +358,20 @@ async def test_cancel_task( cancelled_task = Task( id=sample_task.id, context_id=sample_task.context_id, - status=TaskStatus(state=TaskState.TASK_STATE_CANCELLED), + status=TaskStatus(state=TaskState.TASK_STATE_CANCELED), ) mock_grpc_stub.CancelTask.return_value = cancelled_task extensions = [ 'https://example.com/test-ext/v3', ] - request = a2a_pb2.CancelTaskRequest(name=f'tasks/{sample_task.id}') + request = a2a_pb2.CancelTaskRequest(id=f'tasks/{sample_task.id}') response = await grpc_transport.cancel_task(request, extensions=extensions) mock_grpc_stub.CancelTask.assert_awaited_once_with( - a2a_pb2.CancelTaskRequest(name=f'tasks/{sample_task.id}'), + a2a_pb2.CancelTaskRequest(id=f'tasks/{sample_task.id}'), metadata=[(HTTP_EXTENSION_HEADER, 'https://example.com/test-ext/v3')], ) - assert response.status.state == TaskState.TASK_STATE_CANCELLED + assert response.status.state == TaskState.TASK_STATE_CANCELED @pytest.mark.asyncio @@ -383,19 +381,19 @@ async def test_set_task_callback_with_valid_task( sample_task_push_notification_config: TaskPushNotificationConfig, ) -> None: """Test setting a task push notification config with a valid task id.""" - mock_grpc_stub.SetTaskPushNotificationConfig.return_value = ( + mock_grpc_stub.CreateTaskPushNotificationConfig.return_value = ( sample_task_push_notification_config ) # Create the request object expected by the transport - request = SetTaskPushNotificationConfigRequest( - parent='tasks/task-1', + request = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task-1', config_id=sample_task_push_notification_config.push_notification_config.id, - config=sample_task_push_notification_config, + config=sample_task_push_notification_config.push_notification_config, ) response = await grpc_transport.set_task_callback(request) - mock_grpc_stub.SetTaskPushNotificationConfig.assert_awaited_once_with( + mock_grpc_stub.CreateTaskPushNotificationConfig.assert_awaited_once_with( request, metadata=[ ( @@ -404,7 +402,7 @@ async def test_set_task_callback_with_valid_task( ) ], ) - assert response.name == sample_task_push_notification_config.name + assert response.task_id == sample_task_push_notification_config.task_id @pytest.mark.asyncio @@ -415,27 +413,24 @@ async def test_set_task_callback_with_invalid_task( ) -> None: """Test setting a task push notification config with an invalid task name format.""" # Return a config with an invalid name format - mock_grpc_stub.SetTaskPushNotificationConfig.return_value = a2a_pb2.TaskPushNotificationConfig( - name='invalid-path-to-tasks/task-1/pushNotificationConfigs/config-1', - push_notification_config=sample_push_notification_config, + mock_grpc_stub.CreateTaskPushNotificationConfig.return_value = ( + a2a_pb2.TaskPushNotificationConfig( + task_id='invalid-path-to-tasks/task-1', + id='config-1', + push_notification_config=sample_push_notification_config, + ) ) - request = SetTaskPushNotificationConfigRequest( - parent='tasks/task-1', + request = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task-1', config_id='config-1', - config=TaskPushNotificationConfig( - name='tasks/task-1/pushNotificationConfigs/config-1', - push_notification_config=sample_push_notification_config, - ), + config=sample_push_notification_config, ) # Note: The transport doesn't validate the response name format # It just returns the response from the stub response = await grpc_transport.set_task_callback(request) - assert ( - response.name - == 'invalid-path-to-tasks/task-1/pushNotificationConfigs/config-1' - ) + assert response.task_id == 'invalid-path-to-tasks/task-1' @pytest.mark.asyncio @@ -452,13 +447,15 @@ async def test_get_task_callback_with_valid_task( response = await grpc_transport.get_task_callback( GetTaskPushNotificationConfigRequest( - name=f'tasks/task-1/pushNotificationConfigs/{config_id}' + task_id='tasks/task-1', + id=config_id, ) ) mock_grpc_stub.GetTaskPushNotificationConfig.assert_awaited_once_with( a2a_pb2.GetTaskPushNotificationConfigRequest( - name=f'tasks/task-1/pushNotificationConfigs/{config_id}', + task_id='tasks/task-1', + id=config_id, ), metadata=[ ( @@ -467,7 +464,7 @@ async def test_get_task_callback_with_valid_task( ) ], ) - assert response.name == sample_task_push_notification_config.name + assert response.task_id == sample_task_push_notification_config.task_id @pytest.mark.asyncio @@ -477,21 +474,22 @@ async def test_get_task_callback_with_invalid_task( sample_push_notification_config: PushNotificationConfig, ) -> None: """Test retrieving a task push notification config with an invalid task name.""" - mock_grpc_stub.GetTaskPushNotificationConfig.return_value = a2a_pb2.TaskPushNotificationConfig( - name='invalid-path-to-tasks/task-1/pushNotificationConfigs/config-1', - push_notification_config=sample_push_notification_config, + mock_grpc_stub.GetTaskPushNotificationConfig.return_value = ( + a2a_pb2.TaskPushNotificationConfig( + task_id='invalid-path-to-tasks/task-1', + id='config-1', + push_notification_config=sample_push_notification_config, + ) ) response = await grpc_transport.get_task_callback( GetTaskPushNotificationConfigRequest( - name='tasks/task-1/pushNotificationConfigs/config-1' + task_id='tasks/task-1', + id='config-1', ) ) # The transport doesn't validate the response name format - assert ( - response.name - == 'invalid-path-to-tasks/task-1/pushNotificationConfigs/config-1' - ) + assert response.task_id == 'invalid-path-to-tasks/task-1' @pytest.mark.parametrize( diff --git a/tests/client/transports/test_jsonrpc_client.py b/tests/client/transports/test_jsonrpc_client.py index 86be1d77d..b4fddb3be 100644 --- a/tests/client/transports/test_jsonrpc_client.py +++ b/tests/client/transports/test_jsonrpc_client.py @@ -29,7 +29,7 @@ SendMessageConfiguration, SendMessageRequest, SendMessageResponse, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, Task, TaskPushNotificationConfig, TaskState, @@ -276,7 +276,7 @@ async def test_get_task_success(self, transport, mock_httpx_client): mock_httpx_client.post.return_value = mock_response # Proto uses 'name' field for task identifier in request - request = GetTaskRequest(name=f'tasks/{task_id}') + request = GetTaskRequest(id=f'tasks/{task_id}') response = await transport.get_task(request) assert isinstance(response, Task) @@ -303,7 +303,7 @@ async def test_get_task_with_history(self, transport, mock_httpx_client): mock_response.raise_for_status = MagicMock() mock_httpx_client.post.return_value = mock_response - request = GetTaskRequest(name=f'tasks/{task_id}', history_length=10) + request = GetTaskRequest(id=f'tasks/{task_id}', history_length=10) response = await transport.get_task(request) assert isinstance(response, Task) @@ -332,11 +332,11 @@ async def test_cancel_task_success(self, transport, mock_httpx_client): mock_response.raise_for_status = MagicMock() mock_httpx_client.post.return_value = mock_response - request = CancelTaskRequest(name=f'tasks/{task_id}') + request = CancelTaskRequest(id=f'tasks/{task_id}') response = await transport.cancel_task(request) assert isinstance(response, Task) - assert response.status.state == TaskState.TASK_STATE_CANCELLED + assert response.status.state == TaskState.TASK_STATE_CANCELED call_args = mock_httpx_client.post.call_args payload = call_args[1]['json'] assert payload['method'] == 'CancelTask' @@ -356,14 +356,16 @@ async def test_get_task_callback_success( 'jsonrpc': '2.0', 'id': '1', 'result': { - 'name': f'tasks/{task_id}/pushNotificationConfig', + 'task_id': f'tasks/{task_id}', + 'id': 'config-1', }, } mock_response.raise_for_status = MagicMock() mock_httpx_client.post.return_value = mock_response request = GetTaskPushNotificationConfigRequest( - name=f'tasks/{task_id}/pushNotificationConfig' + task_id=f'tasks/{task_id}', + id='config-1', ) response = await transport.get_task_callback(request) diff --git a/tests/e2e/push_notifications/test_default_push_notification_support.py b/tests/e2e/push_notifications/test_default_push_notification_support.py index d6e99057a..ce525edd2 100644 --- a/tests/e2e/push_notifications/test_default_push_notification_support.py +++ b/tests/e2e/push_notifications/test_default_push_notification_support.py @@ -25,7 +25,7 @@ Part, PushNotificationConfig, Role, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, Task, TaskPushNotificationConfig, TaskState, @@ -190,15 +190,13 @@ async def test_notification_triggering_after_config_change_e2e( # Set the push notification config. token = uuid.uuid4().hex await a2a_client.set_task_callback( - SetTaskPushNotificationConfigRequest( - parent=f'tasks/{task.id}', + CreateTaskPushNotificationConfigRequest( + task_id=f'tasks/{task.id}', config_id='after-config-change', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - id='after-config-change', - url=f'{notifications_server}/notifications', - token=token, - ), + config=PushNotificationConfig( + id='after-config-change', + url=f'{notifications_server}/notifications', + token=token, ), ) ) diff --git a/tests/extensions/test_common.py b/tests/extensions/test_common.py index 73f252cac..cfb142376 100644 --- a/tests/extensions/test_common.py +++ b/tests/extensions/test_common.py @@ -5,7 +5,12 @@ get_requested_extensions, update_extension_header, ) -from a2a.types.a2a_pb2 import AgentCapabilities, AgentInterface, AgentCard, AgentExtension +from a2a.types.a2a_pb2 import ( + AgentCapabilities, + AgentInterface, + AgentCard, + AgentExtension, +) def test_get_requested_extensions(): @@ -34,7 +39,9 @@ def test_find_extension_by_uri(): name='Test Agent', description='Test Agent Description', version='1.0', - supported_interfaces=[AgentInterface(url='http://test.com', protocol_binding='HTTP+JSON')], + supported_interfaces=[ + AgentInterface(url='http://test.com', protocol_binding='HTTP+JSON') + ], skills=[], default_input_modes=['text/plain'], default_output_modes=['text/plain'], @@ -51,7 +58,9 @@ def test_find_extension_by_uri_no_extensions(): name='Test Agent', description='Test Agent Description', version='1.0', - supported_interfaces=[AgentInterface(url='http://test.com', protocol_binding='HTTP+JSON')], + supported_interfaces=[ + AgentInterface(url='http://test.com', protocol_binding='HTTP+JSON') + ], skills=[], default_input_modes=['text/plain'], default_output_modes=['text/plain'], diff --git a/tests/integration/test_client_server_integration.py b/tests/integration/test_client_server_integration.py index 9f20673af..ae5008f72 100644 --- a/tests/integration/test_client_server_integration.py +++ b/tests/integration/test_client_server_integration.py @@ -40,7 +40,7 @@ PushNotificationConfig, Role, SendMessageRequest, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, SubscribeToTaskRequest, Task, TaskPushNotificationConfig, @@ -73,11 +73,12 @@ CANCEL_TASK_RESPONSE = Task( id='task-cancel-789', context_id='ctx-cancel-101', - status=TaskStatus(state=TaskState.TASK_STATE_CANCELLED), + status=TaskStatus(state=TaskState.TASK_STATE_CANCELED), ) CALLBACK_CONFIG = TaskPushNotificationConfig( - name='tasks/task-callback-123/pushNotificationConfigs/pnc-abc', + task_id='tasks/task-callback-123', + id='pnc-abc', push_notification_config=PushNotificationConfig( id='pnc-abc', url='http://callback.example.com', token='' ), @@ -87,7 +88,6 @@ task_id='task-resub-456', context_id='ctx-resub-789', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=False, ) @@ -414,7 +414,7 @@ async def test_http_transport_get_task( handler = transport_setup.handler # Use GetTaskRequest with name (AIP resource format) - params = GetTaskRequest(name=f'tasks/{GET_TASK_RESPONSE.id}') + params = GetTaskRequest(id=f'tasks/{GET_TASK_RESPONSE.id}') result = await transport.get_task(request=params) assert result.id == GET_TASK_RESPONSE.id @@ -438,7 +438,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use GetTaskRequest with name (AIP resource format) - params = GetTaskRequest(name=f'tasks/{GET_TASK_RESPONSE.id}') + params = GetTaskRequest(id=f'tasks/{GET_TASK_RESPONSE.id}') result = await transport.get_task(request=params) assert result.id == GET_TASK_RESPONSE.id @@ -465,7 +465,7 @@ async def test_http_transport_cancel_task( handler = transport_setup.handler # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(name=f'tasks/{CANCEL_TASK_RESPONSE.id}') + params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -489,7 +489,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(name=f'tasks/{CANCEL_TASK_RESPONSE.id}') + params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -515,16 +515,16 @@ async def test_http_transport_set_task_callback( transport = transport_setup.transport handler = transport_setup.handler - # Create SetTaskPushNotificationConfigRequest with required fields - params = SetTaskPushNotificationConfigRequest( - parent='tasks/task-callback-123', + # Create CreateTaskPushNotificationConfigRequest with required fields + params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task-callback-123', config_id='pnc-abc', - config=CALLBACK_CONFIG, + config=CALLBACK_CONFIG.push_notification_config, ) result = await transport.set_task_callback(request=params) # TaskPushNotificationConfig has 'name' and 'push_notification_config' - assert result.name == CALLBACK_CONFIG.name + assert result.id == CALLBACK_CONFIG.id assert ( result.push_notification_config.id == CALLBACK_CONFIG.push_notification_config.id @@ -552,16 +552,16 @@ def channel_factory(address: str) -> Channel: channel = channel_factory(server_address) transport = GrpcTransport(channel=channel, agent_card=agent_card) - # Create SetTaskPushNotificationConfigRequest with required fields - params = SetTaskPushNotificationConfigRequest( - parent='tasks/task-callback-123', + # Create CreateTaskPushNotificationConfigRequest with required fields + params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task-callback-123', config_id='pnc-abc', - config=CALLBACK_CONFIG, + config=CALLBACK_CONFIG.push_notification_config, ) result = await transport.set_task_callback(request=params) # TaskPushNotificationConfig has 'name' and 'push_notification_config' - assert result.name == CALLBACK_CONFIG.name + assert result.id == CALLBACK_CONFIG.id assert ( result.push_notification_config.id == CALLBACK_CONFIG.push_notification_config.id @@ -593,11 +593,13 @@ async def test_http_transport_get_task_callback( handler = transport_setup.handler # Use GetTaskPushNotificationConfigRequest with name field (resource name) - params = GetTaskPushNotificationConfigRequest(name=CALLBACK_CONFIG.name) + params = GetTaskPushNotificationConfigRequest( + task_id=CALLBACK_CONFIG.task_id, id=CALLBACK_CONFIG.id + ) result = await transport.get_task_callback(request=params) # TaskPushNotificationConfig has 'name' and 'push_notification_config' - assert result.name == CALLBACK_CONFIG.name + assert result.task_id == CALLBACK_CONFIG.task_id assert ( result.push_notification_config.id == CALLBACK_CONFIG.push_notification_config.id @@ -626,11 +628,13 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use GetTaskPushNotificationConfigRequest with name field (resource name) - params = GetTaskPushNotificationConfigRequest(name=CALLBACK_CONFIG.name) + params = GetTaskPushNotificationConfigRequest( + task_id=CALLBACK_CONFIG.task_id, id=CALLBACK_CONFIG.id + ) result = await transport.get_task_callback(request=params) # TaskPushNotificationConfig has 'name' and 'push_notification_config' - assert result.name == CALLBACK_CONFIG.name + assert result.task_id == CALLBACK_CONFIG.task_id assert ( result.push_notification_config.id == CALLBACK_CONFIG.push_notification_config.id @@ -662,7 +666,7 @@ async def test_http_transport_resubscribe( handler = transport_setup.handler # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(name=f'tasks/{RESUBSCRIBE_EVENT.task_id}') + params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') stream = transport.subscribe(request=params) first_event = await anext(stream) @@ -688,7 +692,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(name=f'tasks/{RESUBSCRIBE_EVENT.task_id}') + params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') stream = transport.subscribe(request=params) first_event = await anext(stream) diff --git a/tests/server/apps/jsonrpc/test_serialization.py b/tests/server/apps/jsonrpc/test_serialization.py index 0157f8da9..d2d694fb7 100644 --- a/tests/server/apps/jsonrpc/test_serialization.py +++ b/tests/server/apps/jsonrpc/test_serialization.py @@ -19,7 +19,7 @@ Message, Part, Role, - Security, + SecurityRequirement, SecurityScheme, ) diff --git a/tests/server/events/test_event_consumer.py b/tests/server/events/test_event_consumer.py index 6c90d8e9d..d8216b5a1 100644 --- a/tests/server/events/test_event_consumer.py +++ b/tests/server/events/test_event_consumer.py @@ -141,7 +141,6 @@ async def test_consume_all_multiple_events( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=True, ), ] cursor = 0 @@ -152,7 +151,8 @@ async def mock_dequeue() -> Any: event = events[cursor] cursor += 1 return event - return None + mock_event_queue.is_closed.return_value = True + raise asyncio.QueueEmpty() mock_event_queue.dequeue_event = mock_dequeue consumed_events: list[Any] = [] @@ -182,7 +182,6 @@ async def test_consume_until_message( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=True, ), ] cursor = 0 @@ -193,7 +192,8 @@ async def mock_dequeue() -> Any: event = events[cursor] cursor += 1 return event - return None + mock_event_queue.is_closed.return_value = True + raise asyncio.QueueEmpty() mock_event_queue.dequeue_event = mock_dequeue consumed_events: list[Any] = [] @@ -225,7 +225,8 @@ async def mock_dequeue() -> Any: event = events[cursor] cursor += 1 return event - return None + mock_event_queue.is_closed.return_value = True + raise asyncio.QueueEmpty() mock_event_queue.dequeue_event = mock_dequeue consumed_events: list[Any] = [] diff --git a/tests/server/events/test_event_queue.py b/tests/server/events/test_event_queue.py index 6fb6cc7be..47e12e1e4 100644 --- a/tests/server/events/test_event_queue.py +++ b/tests/server/events/test_event_queue.py @@ -112,7 +112,6 @@ async def test_dequeue_event_wait(event_queue: EventQueue) -> None: task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=True, ) await event_queue.enqueue_event(event) dequeued_event = await event_queue.dequeue_event() diff --git a/tests/server/request_handlers/test_default_request_handler.py b/tests/server/request_handlers/test_default_request_handler.py index 01be85116..d39ada2ba 100644 --- a/tests/server/request_handlers/test_default_request_handler.py +++ b/tests/server/request_handlers/test_default_request_handler.py @@ -47,7 +47,7 @@ Role, SendMessageConfiguration, SendMessageRequest, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, Task, TaskPushNotificationConfig, TaskState, @@ -138,7 +138,7 @@ async def test_on_get_task_not_found(): agent_executor=MockAgentExecutor(), task_store=mock_task_store ) - params = GetTaskRequest(name='tasks/non_existent_task') + params = GetTaskRequest(id='tasks/non_existent_task') from a2a.utils.errors import ServerError # Local import for ServerError @@ -159,7 +159,7 @@ async def test_on_cancel_task_task_not_found(): request_handler = DefaultRequestHandler( agent_executor=MockAgentExecutor(), task_store=mock_task_store ) - params = CancelTaskRequest(name='tasks/task_not_found_for_cancel') + params = CancelTaskRequest(id='tasks/task_not_found_for_cancel') from a2a.utils.errors import ServerError # Local import @@ -194,7 +194,7 @@ async def test_on_cancel_task_queue_tap_returns_none(): mock_result_aggregator_instance.consume_all.return_value = ( create_sample_task( task_id='tap_none_task', - status_state=TaskState.TASK_STATE_CANCELLED, # Expected final state + status_state=TaskState.TASK_STATE_CANCELED, # Expected final state ) ) @@ -209,7 +209,7 @@ async def test_on_cancel_task_queue_tap_returns_none(): 'a2a.server.request_handlers.default_request_handler.ResultAggregator', return_value=mock_result_aggregator_instance, ): - params = CancelTaskRequest(name='tasks/tap_none_task') + params = CancelTaskRequest(id='tasks/tap_none_task') result_task = await request_handler.on_cancel_task(params, context) mock_task_store.get.assert_awaited_once_with('tap_none_task', context) @@ -225,7 +225,7 @@ async def test_on_cancel_task_queue_tap_returns_none(): mock_result_aggregator_instance.consume_all.assert_awaited_once() assert result_task is not None - assert result_task.status.state == TaskState.TASK_STATE_CANCELLED + assert result_task.status.state == TaskState.TASK_STATE_CANCELED @pytest.mark.asyncio @@ -246,7 +246,7 @@ async def test_on_cancel_task_cancels_running_agent(): mock_result_aggregator_instance = AsyncMock(spec=ResultAggregator) mock_result_aggregator_instance.consume_all.return_value = ( create_sample_task( - task_id=task_id, status_state=TaskState.TASK_STATE_CANCELLED + task_id=task_id, status_state=TaskState.TASK_STATE_CANCELED ) ) @@ -265,7 +265,7 @@ async def test_on_cancel_task_cancels_running_agent(): 'a2a.server.request_handlers.default_request_handler.ResultAggregator', return_value=mock_result_aggregator_instance, ): - params = CancelTaskRequest(name=f'tasks/{task_id}') + params = CancelTaskRequest(id=f'tasks/{task_id}') await request_handler.on_cancel_task(params, context) mock_producer_task.cancel.assert_called_once() @@ -313,7 +313,7 @@ async def test_on_cancel_task_completes_during_cancellation(): 'a2a.server.request_handlers.default_request_handler.ResultAggregator', return_value=mock_result_aggregator_instance, ): - params = CancelTaskRequest(name=f'tasks/{task_id}') + params = CancelTaskRequest(id=f'tasks/{task_id}') with pytest.raises(ServerError) as exc_info: await request_handler.on_cancel_task( params, create_server_call_context() @@ -356,7 +356,7 @@ async def test_on_cancel_task_invalid_result_type(): 'a2a.server.request_handlers.default_request_handler.ResultAggregator', return_value=mock_result_aggregator_instance, ): - params = CancelTaskRequest(name=f'tasks/{task_id}') + params = CancelTaskRequest(id=f'tasks/{task_id}') with pytest.raises(ServerError) as exc_info: await request_handler.on_cancel_task( params, create_server_call_context() @@ -932,7 +932,7 @@ async def test_on_get_task_limit_history(): assert isinstance(result, Task) get_task_result = await request_handler.on_get_task( - GetTaskRequest(name=f'tasks/{result.id}', history_length=1), + GetTaskRequest(id=f'tasks/{result.id}', history_length=1), create_server_call_context(), ) assert get_task_result is not None @@ -1391,7 +1391,7 @@ async def exec_side_effect(_request, queue: EventQueue): # Resubscribe and start consuming future events resub_gen = request_handler.on_subscribe_to_task( - SubscribeToTaskRequest(name=f'tasks/{task_id}'), + SubscribeToTaskRequest(id=f'tasks/{task_id}'), create_server_call_context(), ) @@ -1859,14 +1859,10 @@ async def test_set_task_push_notification_config_no_notifier(): task_store=AsyncMock(spec=TaskStore), push_config_store=None, # Explicitly None ) - params = SetTaskPushNotificationConfigRequest( - parent='tasks/task1', + params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task1', config_id='config1', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='http://example.com' - ), - ), + config=PushNotificationConfig(url='http://example.com'), ) from a2a.utils.errors import ServerError # Local import @@ -1891,14 +1887,10 @@ async def test_set_task_push_notification_config_task_not_found(): push_config_store=mock_push_store, push_sender=mock_push_sender, ) - params = SetTaskPushNotificationConfigRequest( - parent='tasks/non_existent_task', + params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/non_existent_task', config_id='config1', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='http://example.com' - ), - ), + config=PushNotificationConfig(url='http://example.com'), ) from a2a.utils.errors import ServerError # Local import @@ -1922,7 +1914,8 @@ async def test_get_task_push_notification_config_no_store(): push_config_store=None, # Explicitly None ) params = GetTaskPushNotificationConfigRequest( - name='tasks/task1/push_notification_config' + task_id='tasks/task1', + id='push_notification_config', ) from a2a.utils.errors import ServerError # Local import @@ -1946,7 +1939,7 @@ async def test_get_task_push_notification_config_task_not_found(): push_config_store=mock_push_store, ) params = GetTaskPushNotificationConfigRequest( - name='tasks/non_existent_task/push_notification_config' + task_id='tasks/non_existent_task', id='push_notification_config' ) from a2a.utils.errors import ServerError # Local import @@ -1978,7 +1971,7 @@ async def test_get_task_push_notification_config_info_not_found(): push_config_store=mock_push_store, ) params = GetTaskPushNotificationConfigRequest( - name='tasks/non_existent_task/push_notification_config' + task_id='tasks/non_existent_task', id='push_notification_config' ) from a2a.utils.errors import ServerError # Local import @@ -2009,13 +2002,11 @@ async def test_get_task_push_notification_config_info_with_config(): push_config_store=push_store, ) - set_config_params = SetTaskPushNotificationConfigRequest( - parent='tasks/task_1', + set_config_params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task_1', config_id='config_id', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - id='config_id', url='http://1.example.com' - ), + config=PushNotificationConfig( + id='config_id', url='http://1.example.com' ), ) context = create_server_call_context() @@ -2024,7 +2015,7 @@ async def test_get_task_push_notification_config_info_with_config(): ) params = GetTaskPushNotificationConfigRequest( - name='tasks/task_1/pushNotificationConfigs/config_id' + task_id='tasks/task_1', id='config_id' ) result: TaskPushNotificationConfig = ( @@ -2034,11 +2025,8 @@ async def test_get_task_push_notification_config_info_with_config(): ) assert result is not None - assert 'task_1' in result.name - assert ( - result.push_notification_config.url - == set_config_params.config.push_notification_config.url - ) + assert result.task_id == 'task_1' + assert result.push_notification_config.url == set_config_params.config.url assert result.push_notification_config.id == 'config_id' @@ -2056,21 +2044,17 @@ async def test_get_task_push_notification_config_info_with_config_no_id(): push_config_store=push_store, ) - set_config_params = SetTaskPushNotificationConfigRequest( - parent='tasks/task_1', + set_config_params = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task_1', config_id='default', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='http://1.example.com' - ), - ), + config=PushNotificationConfig(url='http://1.example.com'), ) await request_handler.on_set_task_push_notification_config( set_config_params, create_server_call_context() ) params = GetTaskPushNotificationConfigRequest( - name='tasks/task_1/pushNotificationConfigs/task_1' + task_id='tasks/task_1', id='task_1' ) result: TaskPushNotificationConfig = ( @@ -2080,11 +2064,8 @@ async def test_get_task_push_notification_config_info_with_config_no_id(): ) assert result is not None - assert 'task_1' in result.name - assert ( - result.push_notification_config.url - == set_config_params.config.push_notification_config.url - ) + assert result.task_id == 'task_1' + assert result.push_notification_config.url == set_config_params.config.url assert result.push_notification_config.id == 'task_1' @@ -2097,7 +2078,7 @@ async def test_on_subscribe_to_task_task_not_found(): request_handler = DefaultRequestHandler( agent_executor=MockAgentExecutor(), task_store=mock_task_store ) - params = SubscribeToTaskRequest(name='tasks/resub_task_not_found') + params = SubscribeToTaskRequest(id='tasks/resub_task_not_found') from a2a.utils.errors import ServerError # Local import @@ -2128,7 +2109,7 @@ async def test_on_subscribe_to_task_queue_not_found(): task_store=mock_task_store, queue_manager=mock_queue_manager, ) - params = SubscribeToTaskRequest(name='tasks/resub_queue_not_found') + params = SubscribeToTaskRequest(id='tasks/resub_queue_not_found') from a2a.utils.errors import ServerError # Local import @@ -2191,7 +2172,7 @@ async def test_list_task_push_notification_config_no_store(): task_store=AsyncMock(spec=TaskStore), push_config_store=None, # Explicitly None ) - params = ListTaskPushNotificationConfigRequest(parent='tasks/task1') + params = ListTaskPushNotificationConfigRequest(task_id='tasks/task1') from a2a.utils.errors import ServerError # Local import with pytest.raises(ServerError) as exc_info: @@ -2214,7 +2195,7 @@ async def test_list_task_push_notification_config_task_not_found(): push_config_store=mock_push_store, ) params = ListTaskPushNotificationConfigRequest( - parent='tasks/non_existent_task' + task_id='tasks/non_existent_task' ) from a2a.utils.errors import ServerError # Local import @@ -2245,7 +2226,7 @@ async def test_list_no_task_push_notification_config_info(): push_config_store=push_store, ) params = ListTaskPushNotificationConfigRequest( - parent='tasks/non_existent_task' + task_id='tasks/non_existent_task' ) result = await request_handler.on_list_task_push_notification_config( @@ -2278,16 +2259,16 @@ async def test_list_task_push_notification_config_info_with_config(): task_store=mock_task_store, push_config_store=push_store, ) - params = ListTaskPushNotificationConfigRequest(parent='tasks/task_1') + params = ListTaskPushNotificationConfigRequest(task_id='tasks/task_1') result = await request_handler.on_list_task_push_notification_config( params, create_server_call_context() ) assert len(result.configs) == 2 - assert 'task_1' in result.configs[0].name + assert result.configs[0].task_id == 'task_1' assert result.configs[0].push_notification_config == push_config1 - assert 'task_1' in result.configs[1].name + assert result.configs[1].task_id == 'task_1' assert result.configs[1].push_notification_config == push_config2 @@ -2306,43 +2287,35 @@ async def test_list_task_push_notification_config_info_with_config_and_no_id(): ) # multiple calls without config id should replace the existing - set_config_params1 = SetTaskPushNotificationConfigRequest( - parent='tasks/task_1', + set_config_params1 = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task_1', config_id='default', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='http://1.example.com' - ), - ), + config=PushNotificationConfig(url='http://1.example.com'), ) await request_handler.on_set_task_push_notification_config( set_config_params1, create_server_call_context() ) - set_config_params2 = SetTaskPushNotificationConfigRequest( - parent='tasks/task_1', + set_config_params2 = CreateTaskPushNotificationConfigRequest( + task_id='tasks/task_1', config_id='default', - config=TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='http://2.example.com' - ), - ), + config=PushNotificationConfig(url='http://2.example.com'), ) await request_handler.on_set_task_push_notification_config( set_config_params2, create_server_call_context() ) - params = ListTaskPushNotificationConfigRequest(parent='tasks/task_1') + params = ListTaskPushNotificationConfigRequest(task_id='tasks/task_1') result = await request_handler.on_list_task_push_notification_config( params, create_server_call_context() ) assert len(result.configs) == 1 - assert 'task_1' in result.configs[0].name + assert result.configs[0].task_id == 'task_1' assert ( result.configs[0].push_notification_config.url - == set_config_params2.config.push_notification_config.url + == set_config_params2.config.url ) assert result.configs[0].push_notification_config.id == 'task_1' @@ -2356,7 +2329,7 @@ async def test_delete_task_push_notification_config_no_store(): push_config_store=None, # Explicitly None ) params = DeleteTaskPushNotificationConfigRequest( - name='tasks/task1/pushNotificationConfigs/config1' + task_id='tasks/task1', id='config1' ) from a2a.utils.errors import ServerError # Local import @@ -2380,7 +2353,7 @@ async def test_delete_task_push_notification_config_task_not_found(): push_config_store=mock_push_store, ) params = DeleteTaskPushNotificationConfigRequest( - name='tasks/non_existent_task/pushNotificationConfigs/config1' + task_id='tasks/non_existent_task', id='config1' ) from a2a.utils.errors import ServerError # Local import @@ -2415,7 +2388,7 @@ async def test_delete_no_task_push_notification_config_info(): push_config_store=push_store, ) params = DeleteTaskPushNotificationConfigRequest( - name='tasks/task1/pushNotificationConfigs/config_non_existant' + task_id='tasks/task1', id='config_non_existant' ) result = await request_handler.on_delete_task_push_notification_config( @@ -2424,7 +2397,7 @@ async def test_delete_no_task_push_notification_config_info(): assert result is None params = DeleteTaskPushNotificationConfigRequest( - name='tasks/task2/pushNotificationConfigs/config_non_existant' + task_id='tasks/task2', id='config_non_existant' ) result = await request_handler.on_delete_task_push_notification_config( @@ -2459,7 +2432,7 @@ async def test_delete_task_push_notification_config_info_with_config(): push_config_store=push_store, ) params = DeleteTaskPushNotificationConfigRequest( - name='tasks/task_1/pushNotificationConfigs/config_1' + task_id='tasks/task_1', id='config_1' ) result1 = await request_handler.on_delete_task_push_notification_config( @@ -2469,12 +2442,12 @@ async def test_delete_task_push_notification_config_info_with_config(): assert result1 is None result2 = await request_handler.on_list_task_push_notification_config( - ListTaskPushNotificationConfigRequest(parent='tasks/task_1'), + ListTaskPushNotificationConfigRequest(task_id='tasks/task_1'), create_server_call_context(), ) assert len(result2.configs) == 1 - assert 'task_1' in result2.configs[0].name + assert result2.configs[0].task_id == 'task_1' assert result2.configs[0].push_notification_config == push_config2 @@ -2499,7 +2472,7 @@ async def test_delete_task_push_notification_config_info_with_config_and_no_id() push_config_store=push_store, ) params = DeleteTaskPushNotificationConfigRequest( - name='tasks/task_1/pushNotificationConfigs/task_1' + task_id='tasks/task_1', id='task_1' ) result = await request_handler.on_delete_task_push_notification_config( @@ -2509,7 +2482,7 @@ async def test_delete_task_push_notification_config_info_with_config_and_no_id() assert result is None result2 = await request_handler.on_list_task_push_notification_config( - ListTaskPushNotificationConfigRequest(parent='tasks/task_1'), + ListTaskPushNotificationConfigRequest(task_id='tasks/task_1'), create_server_call_context(), ) @@ -2518,7 +2491,7 @@ async def test_delete_task_push_notification_config_info_with_config_and_no_id() TERMINAL_TASK_STATES = { TaskState.TASK_STATE_COMPLETED, - TaskState.TASK_STATE_CANCELLED, + TaskState.TASK_STATE_CANCELED, TaskState.TASK_STATE_FAILED, TaskState.TASK_STATE_REJECTED, } @@ -2635,7 +2608,7 @@ async def test_on_subscribe_to_task_in_terminal_state(terminal_state): task_store=mock_task_store, queue_manager=AsyncMock(spec=QueueManager), ) - params = SubscribeToTaskRequest(name=f'tasks/{task_id}') + params = SubscribeToTaskRequest(id=f'tasks/{task_id}') from a2a.utils.errors import ServerError diff --git a/tests/server/request_handlers/test_grpc_handler.py b/tests/server/request_handlers/test_grpc_handler.py index a3055195d..b36e250c8 100644 --- a/tests/server/request_handlers/test_grpc_handler.py +++ b/tests/server/request_handlers/test_grpc_handler.py @@ -111,7 +111,7 @@ async def test_get_task_success( mock_grpc_context: AsyncMock, ) -> None: """Test successful GetTask call.""" - request_proto = a2a_pb2.GetTaskRequest(name='tasks/task-1') + request_proto = a2a_pb2.GetTaskRequest(id='tasks/task-1') response_model = types.Task( id='task-1', context_id='ctx-1', @@ -133,7 +133,7 @@ async def test_get_task_not_found( mock_grpc_context: AsyncMock, ) -> None: """Test GetTask call when task is not found.""" - request_proto = a2a_pb2.GetTaskRequest(name='tasks/task-1') + request_proto = a2a_pb2.GetTaskRequest(id='tasks/task-1') mock_request_handler.on_get_task.return_value = None await grpc_handler.GetTask(request_proto, mock_grpc_context) @@ -150,7 +150,7 @@ async def test_cancel_task_server_error( mock_grpc_context: AsyncMock, ) -> None: """Test CancelTask call when handler raises ServerError.""" - request_proto = a2a_pb2.CancelTaskRequest(name='tasks/task-1') + request_proto = a2a_pb2.CancelTaskRequest(id='tasks/task-1') error = ServerError(error=types.TaskNotCancelableError()) mock_request_handler.on_cancel_task.side_effect = error @@ -313,7 +313,7 @@ async def test_abort_context_error_mapping( # noqa: PLR0913 error_message_part: str, ) -> None: mock_request_handler.on_get_task.side_effect = server_error - request_proto = a2a_pb2.GetTaskRequest(name='tasks/any') + request_proto = a2a_pb2.GetTaskRequest(id='tasks/any') await grpc_handler.GetTask(request_proto, mock_grpc_context) mock_grpc_context.abort.assert_awaited_once() diff --git a/tests/server/request_handlers/test_jsonrpc_handler.py b/tests/server/request_handlers/test_jsonrpc_handler.py index e39d16613..41ac3d5dc 100644 --- a/tests/server/request_handlers/test_jsonrpc_handler.py +++ b/tests/server/request_handlers/test_jsonrpc_handler.py @@ -47,7 +47,7 @@ Role, SendMessageConfiguration, SendMessageRequest, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, SubscribeToTaskRequest, Task, TaskArtifactUpdateEvent, @@ -142,7 +142,7 @@ async def test_on_get_task_success(self) -> None: task_id = 'test_task_id' mock_task = create_task(task_id=task_id) mock_task_store.get.return_value = mock_task - request = GetTaskRequest(name=f'tasks/{task_id}') + request = GetTaskRequest(id=f'tasks/{task_id}') response = await handler.on_get_task(request, call_context) # Response is now a dict with 'result' key for success self.assertIsInstance(response, dict) @@ -158,7 +158,7 @@ async def test_on_get_task_not_found(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) mock_task_store.get.return_value = None - request = GetTaskRequest(name='tasks/nonexistent_id') + request = GetTaskRequest(id='tasks/nonexistent_id') call_context = ServerCallContext( state={'foo': 'bar', 'request_id': '1'} ) @@ -183,14 +183,14 @@ async def test_on_cancel_task_success(self) -> None: ) async def streaming_coro(): - mock_task.status.state = TaskState.TASK_STATE_CANCELLED + mock_task.status.state = TaskState.TASK_STATE_CANCELED yield mock_task with patch( 'a2a.server.request_handlers.default_request_handler.EventConsumer.consume_all', return_value=streaming_coro(), ): - request = CancelTaskRequest(name=f'tasks/{task_id}') + request = CancelTaskRequest(id=f'tasks/{task_id}') response = await handler.on_cancel_task(request, call_context) assert mock_agent_executor.cancel.call_count == 1 self.assertIsInstance(response, dict) @@ -198,7 +198,7 @@ async def streaming_coro(): # Result is converted to dict for JSON serialization assert response['result']['id'] == task_id # type: ignore assert ( - response['result']['status']['state'] == 'TASK_STATE_CANCELLED' + response['result']['status']['state'] == 'TASK_STATE_CANCELED' ) # type: ignore mock_agent_executor.cancel.assert_called_once() @@ -225,7 +225,7 @@ async def streaming_coro(): 'a2a.server.request_handlers.default_request_handler.EventConsumer.consume_all', return_value=streaming_coro(), ): - request = CancelTaskRequest(name=f'tasks/{task_id}') + request = CancelTaskRequest(id=f'tasks/{task_id}') response = await handler.on_cancel_task(request, call_context) assert mock_agent_executor.cancel.call_count == 1 self.assertIsInstance(response, dict) @@ -241,7 +241,7 @@ async def test_on_cancel_task_not_found(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) mock_task_store.get.return_value = None - request = CancelTaskRequest(name='tasks/nonexistent_id') + request = CancelTaskRequest(id='tasks/nonexistent_id') call_context = ServerCallContext(state={'request_id': '1'}) response = await handler.on_cancel_task(request, call_context) self.assertIsInstance(response, dict) @@ -383,7 +383,6 @@ async def test_on_message_stream_new_message_success( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_COMPLETED), - final=True, ), ] @@ -443,7 +442,6 @@ async def test_on_message_stream_new_message_existing_task_success( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=True, ), ] @@ -498,13 +496,10 @@ async def test_set_push_notification_success(self) -> None: mock_task = create_task() mock_task_store.get.return_value = mock_task push_config = PushNotificationConfig(url='http://example.com') - task_config = TaskPushNotificationConfig( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', - push_notification_config=push_config, - ) - request = SetTaskPushNotificationConfigRequest( - parent=f'tasks/{mock_task.id}', - config=task_config, + request = CreateTaskPushNotificationConfigRequest( + task_id=mock_task.id, + config_id='default', + config=push_config, ) response = await handler.set_push_notification_config(request) self.assertIsInstance(response, dict) @@ -531,20 +526,17 @@ async def test_get_push_notification_success(self) -> None: push_config = PushNotificationConfig( id='default', url='http://example.com' ) - task_config = TaskPushNotificationConfig( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', - push_notification_config=push_config, - ) # Set up the config first - request = SetTaskPushNotificationConfigRequest( - parent=f'tasks/{mock_task.id}', + request = CreateTaskPushNotificationConfigRequest( + task_id=mock_task.id, config_id='default', - config=task_config, + config=push_config, ) await handler.set_push_notification_config(request) get_request = GetTaskPushNotificationConfigRequest( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', + task_id=mock_task.id, + id='default', ) get_response = await handler.get_push_notification_config(get_request) self.assertIsInstance(get_response, dict) @@ -593,7 +585,6 @@ async def test_on_message_stream_new_message_send_push_notification_success( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_COMPLETED), - final=True, ), ] @@ -645,7 +636,6 @@ async def test_on_resubscribe_existing_task_success( task_id='task_123', context_id='session-xyz', status=TaskStatus(state=TaskState.TASK_STATE_COMPLETED), - final=True, ), ] @@ -659,7 +649,7 @@ async def streaming_coro(): ): mock_task_store.get.return_value = mock_task mock_queue_manager.tap.return_value = EventQueue() - request = SubscribeToTaskRequest(name=f'tasks/{mock_task.id}') + request = SubscribeToTaskRequest(id=f'tasks/{mock_task.id}') response = handler.on_subscribe_to_task(request) assert isinstance(response, AsyncGenerator) collected_events: list[Any] = [] @@ -676,7 +666,7 @@ async def test_on_subscribe_no_existing_task_error(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) mock_task_store.get.return_value = None - request = SubscribeToTaskRequest(name='tasks/nonexistent_id') + request = SubscribeToTaskRequest(id='tasks/nonexistent_id') response = handler.on_subscribe_to_task(request) assert isinstance(response, AsyncGenerator) collected_events: list[Any] = [] @@ -732,13 +722,10 @@ async def test_push_notifications_not_supported_error(self) -> None: # Act & Assert push_config = PushNotificationConfig(url='http://example.com') - task_config = TaskPushNotificationConfig( - name='tasks/task_123/pushNotificationConfigs/default', - push_notification_config=push_config, - ) - request = SetTaskPushNotificationConfigRequest( - parent='tasks/task_123', - config=task_config, + request = CreateTaskPushNotificationConfigRequest( + task_id='task_123', + config_id='default', + config=push_config, ) # Should raise ServerError about push notifications not supported @@ -769,7 +756,8 @@ async def test_on_get_push_notification_no_push_config_store(self) -> None: # Act get_request = GetTaskPushNotificationConfigRequest( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', + task_id=mock_task.id, + id='default', ) response = await handler.get_push_notification_config(get_request) @@ -797,13 +785,10 @@ async def test_on_set_push_notification_no_push_config_store(self) -> None: # Act push_config = PushNotificationConfig(url='http://example.com') - task_config = TaskPushNotificationConfig( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', - push_notification_config=push_config, - ) - request = SetTaskPushNotificationConfigRequest( - parent=f'tasks/{mock_task.id}', - config=task_config, + request = CreateTaskPushNotificationConfigRequest( + task_id=mock_task.id, + config_id='default', + config=push_config, ) response = await handler.set_push_notification_config(request) @@ -1016,7 +1001,8 @@ async def test_on_get_push_notification(self) -> None: # Create request handler without a push notifier request_handler = AsyncMock(spec=DefaultRequestHandler) task_push_config = TaskPushNotificationConfig( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/config1', + task_id=mock_task.id, + id='config1', push_notification_config=PushNotificationConfig( id='config1', url='http://example.com' ), @@ -1030,7 +1016,8 @@ async def test_on_get_push_notification(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) get_request = GetTaskPushNotificationConfigRequest( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/config1', + task_id=mock_task.id, + id='config1', ) response = await handler.get_push_notification_config(get_request) # Assert @@ -1038,8 +1025,12 @@ async def test_on_get_push_notification(self) -> None: self.assertTrue(is_success_response(response)) # Result is converted to dict for JSON serialization self.assertEqual( - response['result']['name'], - f'tasks/{mock_task.id}/pushNotificationConfigs/config1', + response['result']['id'], + 'config1', + ) + self.assertEqual( + response['result']['taskId'], + mock_task.id, ) async def test_on_list_push_notification(self) -> None: @@ -1052,7 +1043,8 @@ async def test_on_list_push_notification(self) -> None: # Create request handler without a push notifier request_handler = AsyncMock(spec=DefaultRequestHandler) task_push_config = TaskPushNotificationConfig( - name=f'tasks/{mock_task.id}/pushNotificationConfigs/default', + task_id=mock_task.id, + id='default', push_notification_config=PushNotificationConfig( url='http://example.com' ), @@ -1066,7 +1058,7 @@ async def test_on_list_push_notification(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) list_request = ListTaskPushNotificationConfigRequest( - parent=f'tasks/{mock_task.id}', + task_id=mock_task.id, ) response = await handler.list_push_notification_config(list_request) # Assert @@ -1094,7 +1086,7 @@ async def test_on_list_push_notification_error(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) list_request = ListTaskPushNotificationConfigRequest( - parent=f'tasks/{mock_task.id}', + task_id=mock_task.id, ) response = await handler.list_push_notification_config(list_request) # Assert @@ -1116,7 +1108,8 @@ async def test_on_delete_push_notification(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) delete_request = DeleteTaskPushNotificationConfigRequest( - name='tasks/task1/pushNotificationConfigs/config1', + task_id='tasks/task1', + id='config1', ) response = await handler.delete_push_notification_config(delete_request) # Assert @@ -1139,7 +1132,8 @@ async def test_on_delete_push_notification_error(self) -> None: ) handler = JSONRPCHandler(self.mock_agent_card, request_handler) delete_request = DeleteTaskPushNotificationConfigRequest( - name='tasks/task1/pushNotificationConfigs/config1', + task_id='tasks/task1', + id='config1', ) response = await handler.delete_push_notification_config(delete_request) # Assert @@ -1160,7 +1154,6 @@ async def test_get_authenticated_extended_card_success(self) -> None: url='http://agent.example.com/api', ) ], - protocol_versions=['v1'], version='1.1', capabilities=AgentCapabilities(), default_input_modes=['text/plain'], @@ -1232,7 +1225,6 @@ async def test_get_authenticated_extended_card_with_modifier(self) -> None: url='http://agent.example.com/api', ) ], - protocol_versions=['v1'], version='1.0', capabilities=AgentCapabilities(), default_input_modes=['text/plain'], diff --git a/tests/server/tasks/test_result_aggregator.py b/tests/server/tasks/test_result_aggregator.py index 8973ea2dd..2452e8be3 100644 --- a/tests/server/tasks/test_result_aggregator.py +++ b/tests/server/tasks/test_result_aggregator.py @@ -56,7 +56,7 @@ def create_sample_status_update( task_id=task_id, context_id=context_id, status=TaskStatus(state=status_state), - final=False, # Typically false unless it's the very last update + # Typically false unless it's the very last update ) diff --git a/tests/server/tasks/test_task_manager.py b/tests/server/tasks/test_task_manager.py index fd556a369..c3fc9a572 100644 --- a/tests/server/tasks/test_task_manager.py +++ b/tests/server/tasks/test_task_manager.py @@ -118,7 +118,6 @@ async def test_save_task_event_status_update( task_id=MINIMAL_TASK_ID, context_id=MINIMAL_CONTEXT_ID, status=new_status, - final=False, ) await task_manager.save_task_event(event) # Verify save was called and the task has updated status @@ -168,7 +167,6 @@ async def test_save_task_event_metadata_update( context_id=MINIMAL_CONTEXT_ID, metadata=new_metadata, status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=False, ) await task_manager.save_task_event(event) @@ -187,7 +185,6 @@ async def test_ensure_task_existing( task_id=MINIMAL_TASK_ID, context_id=MINIMAL_CONTEXT_ID, status=TaskStatus(state=TaskState.TASK_STATE_WORKING), - final=False, ) retrieved_task = await task_manager.ensure_task(event) assert retrieved_task == expected_task @@ -210,7 +207,6 @@ async def test_ensure_task_nonexistent( task_id='new-task', context_id='some-context', status=TaskStatus(state=TaskState.TASK_STATE_SUBMITTED), - final=False, ) new_task = await task_manager_without_id.ensure_task(event) assert new_task.id == 'new-task' @@ -313,7 +309,6 @@ async def test_save_task_event_no_task_existing( task_id='event-task-id', context_id='some-context', status=TaskStatus(state=TaskState.TASK_STATE_COMPLETED), - final=True, ) await task_manager_without_id.save_task_event(event) # Check if a new task was created and saved diff --git a/tests/server/tasks/test_task_updater.py b/tests/server/tasks/test_task_updater.py index 525a96253..49d9dee43 100644 --- a/tests/server/tasks/test_task_updater.py +++ b/tests/server/tasks/test_task_updater.py @@ -78,7 +78,6 @@ async def test_update_status_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.task_id == 'test-task-id' assert event.context_id == 'test-context-id' - assert event.final is False assert event.status.state == TaskState.TASK_STATE_WORKING assert not event.status.HasField('message') @@ -98,7 +97,6 @@ async def test_update_status_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.task_id == 'test-task-id' assert event.context_id == 'test-context-id' - assert event.final is False assert event.status.state == TaskState.TASK_STATE_WORKING assert event.status.message == sample_message @@ -107,14 +105,13 @@ async def test_update_status_with_message( async def test_update_status_final( task_updater: TaskUpdater, event_queue: AsyncMock ) -> None: - """Test updating status with final=True.""" - await task_updater.update_status(TaskState.TASK_STATE_COMPLETED, final=True) + """Test updating status with .""" + await task_updater.update_status(TaskState.TASK_STATE_COMPLETED) event_queue.enqueue_event.assert_called_once() event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) - assert event.final is True assert event.status.state == TaskState.TASK_STATE_COMPLETED @@ -226,7 +223,6 @@ async def test_complete_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_COMPLETED - assert event.final is True assert not event.status.HasField('message') @@ -242,7 +238,6 @@ async def test_complete_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_COMPLETED - assert event.final is True assert event.status.message == sample_message @@ -258,7 +253,6 @@ async def test_submit_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_SUBMITTED - assert event.final is False assert not event.status.HasField('message') @@ -274,7 +268,6 @@ async def test_submit_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_SUBMITTED - assert event.final is False assert event.status.message == sample_message @@ -290,7 +283,6 @@ async def test_start_work_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_WORKING - assert event.final is False assert not event.status.HasField('message') @@ -306,7 +298,6 @@ async def test_start_work_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_WORKING - assert event.final is False assert event.status.message == sample_message @@ -331,7 +322,7 @@ def test_new_agent_message( def test_new_agent_message_with_metadata( task_updater: TaskUpdater, sample_parts: list[Part] ) -> None: - """Test creating a new agent message with metadata and final=True.""" + """Test creating a new agent message with metadata and .""" metadata = {'key': 'value'} with patch( @@ -380,7 +371,6 @@ async def test_failed_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_FAILED - assert event.final is True assert not event.status.HasField('message') @@ -396,7 +386,6 @@ async def test_failed_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_FAILED - assert event.final is True assert event.status.message == sample_message @@ -412,7 +401,6 @@ async def test_reject_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_REJECTED - assert event.final is True assert not event.status.HasField('message') @@ -428,7 +416,6 @@ async def test_reject_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_REJECTED - assert event.final is True assert event.status.message == sample_message @@ -444,7 +431,6 @@ async def test_requires_input_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_INPUT_REQUIRED - assert event.final is False assert not event.status.HasField('message') @@ -460,7 +446,6 @@ async def test_requires_input_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_INPUT_REQUIRED - assert event.final is False assert event.status.message == sample_message @@ -468,15 +453,14 @@ async def test_requires_input_with_message( async def test_requires_input_final_true( task_updater: TaskUpdater, event_queue: AsyncMock ) -> None: - """Test marking a task as input required with final=True.""" - await task_updater.requires_input(final=True) + """Test marking a task as input required with .""" + await task_updater.requires_input() event_queue.enqueue_event.assert_called_once() event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_INPUT_REQUIRED - assert event.final is True assert not event.status.HasField('message') @@ -484,15 +468,14 @@ async def test_requires_input_final_true( async def test_requires_input_with_message_and_final( task_updater: TaskUpdater, event_queue: AsyncMock, sample_message: Message ) -> None: - """Test marking a task as input required with message and final=True.""" - await task_updater.requires_input(message=sample_message, final=True) + """Test marking a task as input required with message and .""" + await task_updater.requires_input(message=sample_message) event_queue.enqueue_event.assert_called_once() event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_INPUT_REQUIRED - assert event.final is True assert event.status.message == sample_message @@ -508,7 +491,6 @@ async def test_requires_auth_without_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_AUTH_REQUIRED - assert event.final is False assert not event.status.HasField('message') @@ -524,7 +506,6 @@ async def test_requires_auth_with_message( assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_AUTH_REQUIRED - assert event.final is False assert event.status.message == sample_message @@ -532,15 +513,14 @@ async def test_requires_auth_with_message( async def test_requires_auth_final_true( task_updater: TaskUpdater, event_queue: AsyncMock ) -> None: - """Test marking a task as auth required with final=True.""" - await task_updater.requires_auth(final=True) + """Test marking a task as auth required with .""" + await task_updater.requires_auth() event_queue.enqueue_event.assert_called_once() event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_AUTH_REQUIRED - assert event.final is True assert not event.status.HasField('message') @@ -548,15 +528,14 @@ async def test_requires_auth_final_true( async def test_requires_auth_with_message_and_final( task_updater: TaskUpdater, event_queue: AsyncMock, sample_message: Message ) -> None: - """Test marking a task as auth required with message and final=True.""" - await task_updater.requires_auth(message=sample_message, final=True) + """Test marking a task as auth required with message and .""" + await task_updater.requires_auth(message=sample_message) event_queue.enqueue_event.assert_called_once() event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) assert event.status.state == TaskState.TASK_STATE_AUTH_REQUIRED - assert event.final is True assert event.status.message == sample_message @@ -571,8 +550,7 @@ async def test_cancel_without_message( event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) - assert event.status.state == TaskState.TASK_STATE_CANCELLED - assert event.final is True + assert event.status.state == TaskState.TASK_STATE_CANCELED assert not event.status.HasField('message') @@ -587,8 +565,7 @@ async def test_cancel_with_message( event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) - assert event.status.state == TaskState.TASK_STATE_CANCELLED - assert event.final is True + assert event.status.state == TaskState.TASK_STATE_CANCELED assert event.status.message == sample_message @@ -652,7 +629,6 @@ async def test_reject_concurrently_with_complete( event = event_queue.enqueue_event.call_args[0][0] assert isinstance(event, TaskStatusUpdateEvent) - assert event.final is True assert event.status.state in [ TaskState.TASK_STATE_REJECTED, TaskState.TASK_STATE_COMPLETED, diff --git a/tests/server/test_integration.py b/tests/server/test_integration.py index 3274c5d27..c633aac50 100644 --- a/tests/server/test_integration.py +++ b/tests/server/test_integration.py @@ -39,7 +39,6 @@ AgentInterface, AgentSkill, Artifact, - DataPart, Message, Part, PushNotificationConfig, @@ -68,9 +67,7 @@ tags=['cooking'], ) -AGENT_CAPS = AgentCapabilities( - push_notifications=True, state_transition_history=False, streaming=True -) +AGENT_CAPS = AgentCapabilities(push_notifications=True, streaming=True) MINIMAL_AGENT_CARD_DATA = AgentCard( capabilities=AGENT_CAPS, @@ -108,14 +105,14 @@ ], version='1.0', ) -from google.protobuf.struct_pb2 import Struct +from google.protobuf.struct_pb2 import Struct, Value TEXT_PART_DATA = Part(text='Hello') -# For proto, Part.data takes a DataPart, and DataPart.data takes a Struct +# For proto, Part.data takes a Value(struct_value=Struct) _struct = Struct() _struct.update({'key': 'value'}) -DATA_PART = Part(data=DataPart(data=_struct)) +DATA_PART = Part(data=Value(struct_value=_struct)) MINIMAL_MESSAGE_USER = Message( role=Role.ROLE_USER, @@ -315,7 +312,7 @@ def test_starlette_rpc_endpoint_custom_url( 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTask', - 'params': {'name': 'task1'}, + 'params': {'id': 'task1'}, }, ) assert response.status_code == 200 @@ -338,7 +335,7 @@ def test_fastapi_rpc_endpoint_custom_url( 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTask', - 'params': {'name': 'task1'}, + 'params': {'id': 'task1'}, }, ) assert response.status_code == 200 @@ -472,7 +469,7 @@ def test_cancel_task(client: TestClient, handler: mock.AsyncMock): """Test cancelling a task.""" # Setup mock response task_status = MINIMAL_TASK_STATUS - task_status.state = TaskState.TASK_STATE_CANCELLED # 'cancelled' # + task_status.state = TaskState.TASK_STATE_CANCELED # 'cancelled' # task = Task(id='task1', context_id='ctx1', status=task_status) handler.on_cancel_task.return_value = task @@ -483,7 +480,7 @@ def test_cancel_task(client: TestClient, handler: mock.AsyncMock): 'jsonrpc': '2.0', 'id': '123', 'method': 'CancelTask', - 'params': {'name': 'tasks/task1'}, + 'params': {'id': 'tasks/task1'}, }, ) @@ -491,7 +488,7 @@ def test_cancel_task(client: TestClient, handler: mock.AsyncMock): assert response.status_code == 200 data = response.json() assert data['result']['id'] == 'task1' - assert data['result']['status']['state'] == 'TASK_STATE_CANCELLED' + assert data['result']['status']['state'] == 'TASK_STATE_CANCELED' # Verify handler was called handler.on_cancel_task.assert_awaited_once() @@ -511,7 +508,7 @@ def test_get_task(client: TestClient, handler: mock.AsyncMock): 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTask', - 'params': {'name': 'tasks/task1'}, + 'params': {'id': 'tasks/task1'}, }, ) @@ -530,7 +527,8 @@ def test_set_push_notification_config( """Test setting push notification configuration.""" # Setup mock response task_push_config = TaskPushNotificationConfig( - name='tasks/t2/pushNotificationConfig', + task_id='t2', + id='pushNotificationConfig', push_notification_config=PushNotificationConfig( url='https://example.com', token='secret-token' ), @@ -543,14 +541,13 @@ def test_set_push_notification_config( json={ 'jsonrpc': '2.0', 'id': '123', - 'method': 'SetTaskPushNotificationConfig', + 'method': 'CreateTaskPushNotificationConfig', 'params': { - 'parent': 'tasks/t2', + 'task_id': 'tasks/t2', + 'config_id': 'pushNotificationConfig', 'config': { - 'pushNotificationConfig': { - 'url': 'https://example.com', - 'token': 'secret-token', - }, + 'url': 'https://example.com', + 'token': 'secret-token', }, }, }, @@ -571,7 +568,8 @@ def test_get_push_notification_config( """Test getting push notification configuration.""" # Setup mock response task_push_config = TaskPushNotificationConfig( - name='tasks/task1/pushNotificationConfig', + task_id='task1', + id='pushNotificationConfig', push_notification_config=PushNotificationConfig( url='https://example.com', token='secret-token' ), @@ -586,7 +584,10 @@ def test_get_push_notification_config( 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTaskPushNotificationConfig', - 'params': {'name': 'tasks/task1/pushNotificationConfig'}, + 'params': { + 'task_id': 'tasks/task1', + 'id': 'pushNotificationConfig', + }, }, ) @@ -774,7 +775,7 @@ async def stream_generator(): 'jsonrpc': '2.0', 'id': '123', # This ID is used in the success_event above 'method': 'SubscribeToTask', - 'params': {'name': 'tasks/task1'}, + 'params': {'id': 'tasks/task1'}, }, ) as response: # Verify response is a stream @@ -946,7 +947,7 @@ def test_method_not_implemented(client: TestClient, handler: mock.AsyncMock): 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTask', - 'params': {'name': 'tasks/task1'}, + 'params': {'id': 'tasks/task1'}, }, ) assert response.status_code == 200 @@ -1006,7 +1007,7 @@ def test_unhandled_exception(client: TestClient, handler: mock.AsyncMock): 'jsonrpc': '2.0', 'id': '123', 'method': 'GetTask', - 'params': {'name': 'tasks/task1'}, + 'params': {'id': 'tasks/task1'}, }, ) assert response.status_code == 200 diff --git a/tests/test_types.py b/tests/test_types.py index 8adec3bd6..fe495021b 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -8,6 +8,7 @@ import pytest from google.protobuf.json_format import MessageToDict, ParseDict +from google.protobuf.struct_pb2 import Struct, Value from a2a.types.a2a_pb2 import ( AgentCapabilities, @@ -18,8 +19,7 @@ APIKeySecurityScheme, Artifact, CancelTaskRequest, - DataPart, - FilePart, + CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, Message, @@ -28,7 +28,7 @@ Role, SecurityScheme, SendMessageRequest, - SetTaskPushNotificationConfigRequest, + CreateTaskPushNotificationConfigRequest, SubscribeToTaskRequest, Task, TaskPushNotificationConfig, @@ -78,17 +78,14 @@ def test_agent_capabilities(): # Empty capabilities caps = AgentCapabilities() assert caps.streaming is False # Proto default - assert caps.state_transition_history is False assert caps.push_notifications is False # Full capabilities caps_full = AgentCapabilities( push_notifications=True, - state_transition_history=False, streaming=True, ) assert caps_full.push_notifications is True - assert caps_full.state_transition_history is False assert caps_full.streaming is True @@ -155,44 +152,35 @@ def test_text_part(): part = Part(text='Hello') assert part.text == 'Hello' # Check oneof - assert part.WhichOneof('part') == 'text' + assert part.WhichOneof('content') == 'text' -def test_file_part_with_uri(): - """Test FilePart with file_with_uri.""" - file_part = FilePart( - file_with_uri='file:///path/to/file.txt', +def test_part_with_url(): + """Test Part with url.""" + part = Part( + url='file:///path/to/file.txt', media_type='text/plain', ) - assert file_part.file_with_uri == 'file:///path/to/file.txt' - assert file_part.media_type == 'text/plain' + assert part.url == 'file:///path/to/file.txt' + assert part.media_type == 'text/plain' - # Part with file - part = Part(file=file_part) - assert part.HasField('file') - assert part.WhichOneof('part') == 'file' - -def test_file_part_with_bytes(): - """Test FilePart with file_with_bytes.""" - file_part = FilePart( - file_with_bytes=b'hello', - name='hello.txt', +def test_part_with_raw(): + """Test Part with raw bytes.""" + part = Part( + raw=b'hello', + filename='hello.txt', ) - assert file_part.file_with_bytes == b'hello' - assert file_part.name == 'hello.txt' - + assert part.raw == b'hello' + assert part.filename == 'hello.txt' -def test_data_part(): - """Test DataPart proto construction.""" - data_part = DataPart() - data_part.data.update({'key': 'value'}) - assert dict(data_part.data) == {'key': 'value'} - # Part with data - part = Part(data=data_part) +def test_part_with_data(): + """Test Part with data.""" + s = Struct() + s.update({'key': 'value'}) + part = Part(data=Value(struct_value=s)) assert part.HasField('data') - assert part.WhichOneof('part') == 'data' # --- Test Message and Task --- @@ -292,9 +280,10 @@ def test_task_with_artifacts(): # Add artifact artifact = Artifact(artifact_id='artifact-123', name='result') - data_part = DataPart() - data_part.data.update({'result': 42}) - artifact.parts.append(Part(data=data_part)) + s = Struct() + s.update({'result': 42}) + v = Value(struct_value=s) + artifact.parts.append(Part(data=v)) task.artifacts.append(artifact) assert len(task.artifacts) == 1 @@ -317,45 +306,42 @@ def test_send_message_request(): def test_get_task_request(): """Test GetTaskRequest proto construction.""" - request = GetTaskRequest(name='task-123') - assert request.name == 'task-123' + request = GetTaskRequest(id='task-123') + assert request.id == 'task-123' def test_cancel_task_request(): """Test CancelTaskRequest proto construction.""" - request = CancelTaskRequest(name='task-123') - assert request.name == 'task-123' + request = CancelTaskRequest(id='task-123') + assert request.id == 'task-123' def test_subscribe_to_task_request(): """Test SubscribeToTaskRequest proto construction.""" - request = SubscribeToTaskRequest(name='task-123') - assert request.name == 'task-123' + request = SubscribeToTaskRequest(id='task-123') + assert request.id == 'task-123' def test_set_task_push_notification_config_request(): - """Test SetTaskPushNotificationConfigRequest proto construction.""" - config = TaskPushNotificationConfig( - push_notification_config=PushNotificationConfig( - url='https://example.com/webhook', - ), + """Test CreateTaskPushNotificationConfigRequest proto construction.""" + config = PushNotificationConfig( + url='https://example.com/webhook', ) - request = SetTaskPushNotificationConfigRequest( - parent='tasks/task-123', + request = CreateTaskPushNotificationConfigRequest( + task_id='task-123', config_id='config-1', config=config, ) - assert request.parent == 'tasks/task-123' - assert ( - request.config.push_notification_config.url - == 'https://example.com/webhook' - ) + assert request.task_id == 'task-123' + assert request.config.url == 'https://example.com/webhook' def test_get_task_push_notification_config_request(): """Test GetTaskPushNotificationConfigRequest proto construction.""" - request = GetTaskPushNotificationConfigRequest(name='task-123') - assert request.name == 'task-123' + request = GetTaskPushNotificationConfigRequest( + task_id='task-123', id='config-1' + ) + assert request.task_id == 'task-123' # --- Test Enum Values --- @@ -375,7 +361,7 @@ def test_task_state_enum(): assert TaskState.TASK_STATE_WORKING == 2 assert TaskState.TASK_STATE_COMPLETED == 3 assert TaskState.TASK_STATE_FAILED == 4 - assert TaskState.TASK_STATE_CANCELLED == 5 + assert TaskState.TASK_STATE_CANCELED == 5 assert TaskState.TASK_STATE_INPUT_REQUIRED == 6 assert TaskState.TASK_STATE_REJECTED == 7 assert TaskState.TASK_STATE_AUTH_REQUIRED == 8 @@ -495,11 +481,11 @@ def test_has_field_oneof(): """Test HasField for oneof fields.""" part = Part(text='Hello') assert part.HasField('text') - assert not part.HasField('file') + assert not part.HasField('url') assert not part.HasField('data') # WhichOneof for checking which oneof is set - assert part.WhichOneof('part') == 'text' + assert part.WhichOneof('content') == 'text' # --- Test Repeated Fields --- diff --git a/tests/utils/test_artifact.py b/tests/utils/test_artifact.py index 465deebce..cbe8e9c91 100644 --- a/tests/utils/test_artifact.py +++ b/tests/utils/test_artifact.py @@ -7,7 +7,6 @@ from a2a.types.a2a_pb2 import ( Artifact, - DataPart, Part, ) from a2a.utils.artifact import ( @@ -79,9 +78,7 @@ def test_new_data_artifact_part_contains_provided_data(self): # Compare via MessageToDict for proto Struct from google.protobuf.json_format import MessageToDict - self.assertEqual( - MessageToDict(artifact.parts[0].data.data), sample_data - ) + self.assertEqual(MessageToDict(artifact.parts[0].data), sample_data) def test_new_data_artifact_assigns_name_description(self): sample_data = {'info': 'some details'} diff --git a/tests/utils/test_message.py b/tests/utils/test_message.py index ac9316306..c90d422aa 100644 --- a/tests/utils/test_message.py +++ b/tests/utils/test_message.py @@ -2,10 +2,9 @@ from unittest.mock import patch -from google.protobuf.struct_pb2 import Struct +from google.protobuf.struct_pb2 import Struct, Value from a2a.types.a2a_pb2 import ( - DataPart, Message, Part, Role, @@ -122,7 +121,7 @@ def test_new_agent_parts_message(self): data.update({'product_id': 123, 'quantity': 2}) parts = [ Part(text='Here is some text.'), - Part(data=DataPart(data=data)), + Part(data=Value(struct_value=data)), ] context_id = 'ctx-multi-part' task_id = 'task-multi-part' diff --git a/tests/utils/test_parts.py b/tests/utils/test_parts.py index 6e2cffc2d..a7a24e225 100644 --- a/tests/utils/test_parts.py +++ b/tests/utils/test_parts.py @@ -1,8 +1,5 @@ -from google.protobuf.struct_pb2 import Struct - +from google.protobuf.struct_pb2 import Struct, Value from a2a.types.a2a_pb2 import ( - DataPart, - FilePart, Part, ) from a2a.utils.parts import ( @@ -53,7 +50,7 @@ def test_get_data_parts_single_data_part(self): # Setup data = Struct() data.update({'key': 'value'}) - parts = [Part(data=DataPart(data=data))] + parts = [Part(data=Value(struct_value=data))] # Exercise result = get_data_parts(parts) @@ -68,8 +65,8 @@ def test_get_data_parts_multiple_data_parts(self): data2 = Struct() data2.update({'key2': 'value2'}) parts = [ - Part(data=DataPart(data=data1)), - Part(data=DataPart(data=data2)), + Part(data=Value(struct_value=data1)), + Part(data=Value(struct_value=data2)), ] # Exercise @@ -86,8 +83,8 @@ def test_get_data_parts_mixed_parts(self): data2.update({'key2': 'value2'}) parts = [ Part(text='some text'), - Part(data=DataPart(data=data1)), - Part(data=DataPart(data=data2)), + Part(data=Value(struct_value=data1)), + Part(data=Value(struct_value=data2)), ] # Exercise @@ -122,31 +119,21 @@ def test_get_data_parts_empty_list(self): class TestGetFileParts: def test_get_file_parts_single_file_part(self): # Setup - file_part = FilePart( - file_with_uri='file://path/to/file', media_type='text/plain' - ) - parts = [Part(file=file_part)] + parts = [Part(url='file://path/to/file', media_type='text/plain')] # Exercise result = get_file_parts(parts) # Verify assert len(result) == 1 - assert result[0].file_with_uri == 'file://path/to/file' + assert result[0].url == 'file://path/to/file' assert result[0].media_type == 'text/plain' def test_get_file_parts_multiple_file_parts(self): # Setup - file_part1 = FilePart( - file_with_uri='file://path/to/file1', media_type='text/plain' - ) - file_part2 = FilePart( - file_with_bytes=b'file content', - media_type='application/octet-stream', - ) parts = [ - Part(file=file_part1), - Part(file=file_part2), + Part(url='file://path/to/file1', media_type='text/plain'), + Part(raw=b'file content', media_type='application/octet-stream'), ] # Exercise @@ -154,17 +141,14 @@ def test_get_file_parts_multiple_file_parts(self): # Verify assert len(result) == 2 - assert result[0].file_with_uri == 'file://path/to/file1' - assert result[1].file_with_bytes == b'file content' + assert result[0].url == 'file://path/to/file1' + assert result[1].raw == b'file content' def test_get_file_parts_mixed_parts(self): # Setup - file_part = FilePart( - file_with_uri='file://path/to/file', media_type='text/plain' - ) parts = [ Part(text='some text'), - Part(file=file_part), + Part(url='file://path/to/file', media_type='text/plain'), ] # Exercise @@ -172,7 +156,7 @@ def test_get_file_parts_mixed_parts(self): # Verify assert len(result) == 1 - assert result[0].file_with_uri == 'file://path/to/file' + assert result[0].url == 'file://path/to/file' def test_get_file_parts_no_file_parts(self): # Setup @@ -180,7 +164,7 @@ def test_get_file_parts_no_file_parts(self): data.update({'key': 'value'}) parts = [ Part(text='some text'), - Part(data=DataPart(data=data)), + Part(data=Value(struct_value=data)), ] # Exercise From 6d04127e5fe45184f329eea37cbcf1623fbad0ea Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Wed, 4 Feb 2026 13:31:22 +0100 Subject: [PATCH 2/4] fix(review): Address feedback from PR #665 Signed-off-by: Luca Muscariello --- pyproject.toml | 2 +- src/a2a/client/transports/rest.py | 10 ++++---- src/a2a/server/models.py | 2 +- .../default_request_handler.py | 12 +++++----- .../server/request_handlers/grpc_handler.py | 8 +++---- .../request_handlers/jsonrpc_handler.py | 6 ++--- .../request_handlers/request_handler.py | 4 ++-- .../server/request_handlers/rest_handler.py | 6 ++--- src/a2a/utils/parts.py | 2 +- tests/client/transports/test_grpc_client.py | 2 +- .../test_client_server_integration.py | 24 ++++++++++--------- 11 files changed, 38 insertions(+), 40 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5a0c9f6b4..c38a4266a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,6 @@ follow_imports = "skip" [tool.pyright] include = ["src"] -ignore = ["src/a2a/types"] exclude = [ "**/__pycache__", "**/dist", @@ -156,6 +155,7 @@ exclude = [ "**/node_modules", "**/venv", "**/.venv", + "src/a2a/types", ] venvPath = "." venv = ".venv" diff --git a/src/a2a/client/transports/rest.py b/src/a2a/client/transports/rest.py index 26fd3f1be..fc15f6396 100644 --- a/src/a2a/client/transports/rest.py +++ b/src/a2a/client/transports/rest.py @@ -233,7 +233,7 @@ async def get_task( del params['id'] # id is part of the URL path, not query params response_data = await self._send_get_request( - f'/v1/{request.id}', + f'/v1/tasks/{request.id}', params, modified_kwargs, ) @@ -259,7 +259,7 @@ async def cancel_task( context, ) response_data = await self._send_post_request( - f'/v1/{request.id}:cancel', payload, modified_kwargs + f'/v1/tasks/{request.id}:cancel', payload, modified_kwargs ) response: Task = ParseDict(response_data, Task()) return response @@ -281,7 +281,7 @@ async def set_task_callback( payload, modified_kwargs, context ) response_data = await self._send_post_request( - f'/v1/{request.task_id}/pushNotificationConfigs', + f'/v1/tasks/{request.task_id}/pushNotificationConfigs', payload, modified_kwargs, ) @@ -313,7 +313,7 @@ async def get_task_callback( if 'task_id' in params: del params['task_id'] response_data = await self._send_get_request( - f'/v1/{request.task_id}/pushNotificationConfigs/{request.id}', + f'/v1/tasks/{request.task_id}/pushNotificationConfigs/{request.id}', params, modified_kwargs, ) @@ -339,7 +339,7 @@ async def subscribe( async with aconnect_sse( self.httpx_client, 'GET', - f'{self.url}/v1/{request.id}:subscribe', + f'{self.url}/v1/tasks/{request.id}:subscribe', **modified_kwargs, ) as event_source: try: diff --git a/src/a2a/server/models.py b/src/a2a/server/models.py index 41e9ac1d5..34162fcf4 100644 --- a/src/a2a/server/models.py +++ b/src/a2a/server/models.py @@ -65,7 +65,7 @@ def process_bind_param( if isinstance(value, ProtoMessage): return MessageToDict(value, preserving_proto_field_name=False) if isinstance(value, BaseModel): - return cast('BaseModel', value).model_dump(mode='json') + return value.model_dump(mode='json') return value # type: ignore[return-value] def process_result_value( diff --git a/src/a2a/server/request_handlers/default_request_handler.py b/src/a2a/server/request_handlers/default_request_handler.py index 7ea96c1ab..86a21720f 100644 --- a/src/a2a/server/request_handlers/default_request_handler.py +++ b/src/a2a/server/request_handlers/default_request_handler.py @@ -474,19 +474,19 @@ async def _cleanup_producer( async with self._running_agents_lock: self._running_agents.pop(task_id, None) - async def on_set_task_push_notification_config( + async def on_create_task_push_notification_config( self, params: CreateTaskPushNotificationConfigRequest, context: ServerCallContext | None = None, ) -> TaskPushNotificationConfig: - """Default handler for 'tasks/pushNotificationConfig/set'. + """Default handler for 'tasks/pushNotificationConfig/create'. Requires a `PushNotifier` to be configured. """ if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.task_id) + task_id = params.task_id task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -514,7 +514,7 @@ async def on_get_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.task_id) + task_id = params.task_id config_id = params.id task: Task | None = await self.task_store.get(task_id, context) if not task: @@ -546,7 +546,7 @@ async def on_subscribe_to_task( Allows a client to re-attach to a running streaming task's event stream. Requires the task and its queue to still be active. """ - task_id = _extract_task_id(params.id) + task_id = params.id task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -588,7 +588,7 @@ async def on_list_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = _extract_task_id(params.task_id) + task_id = params.task_id task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) diff --git a/src/a2a/server/request_handlers/grpc_handler.py b/src/a2a/server/request_handlers/grpc_handler.py index 50d415a1e..14b8516c7 100644 --- a/src/a2a/server/request_handlers/grpc_handler.py +++ b/src/a2a/server/request_handlers/grpc_handler.py @@ -284,11 +284,9 @@ async def CreateTaskPushNotificationConfig( """ try: server_context = self.context_builder.build(context) - return ( - await self.request_handler.on_set_task_push_notification_config( - request, - server_context, - ) + return await self.request_handler.on_create_task_push_notification_config( + request, + server_context, ) except ServerError as e: await self.abort_context(e, context) diff --git a/src/a2a/server/request_handlers/jsonrpc_handler.py b/src/a2a/server/request_handlers/jsonrpc_handler.py index f8711247a..442a145ec 100644 --- a/src/a2a/server/request_handlers/jsonrpc_handler.py +++ b/src/a2a/server/request_handlers/jsonrpc_handler.py @@ -341,10 +341,8 @@ async def set_push_notification_config( request_id = self._get_request_id(context) try: # Pass the full request to the handler - result_config = ( - await self.request_handler.on_set_task_push_notification_config( - request, context - ) + result_config = await self.request_handler.on_create_task_push_notification_config( + request, context ) result = MessageToDict( result_config, preserving_proto_field_name=False diff --git a/src/a2a/server/request_handlers/request_handler.py b/src/a2a/server/request_handlers/request_handler.py index a889ecd55..d41e83af0 100644 --- a/src/a2a/server/request_handlers/request_handler.py +++ b/src/a2a/server/request_handlers/request_handler.py @@ -107,12 +107,12 @@ async def on_message_send_stream( yield @abstractmethod - async def on_set_task_push_notification_config( + async def on_create_task_push_notification_config( self, params: CreateTaskPushNotificationConfigRequest, context: ServerCallContext | None = None, ) -> TaskPushNotificationConfig: - """Handles the 'tasks/pushNotificationConfig/set' method. + """Handles the 'tasks/pushNotificationConfig/create' method. Sets or updates the push notification configuration for a task. diff --git a/src/a2a/server/request_handlers/rest_handler.py b/src/a2a/server/request_handlers/rest_handler.py index 31d2668f2..748be42ef 100644 --- a/src/a2a/server/request_handlers/rest_handler.py +++ b/src/a2a/server/request_handlers/rest_handler.py @@ -181,7 +181,7 @@ async def get_push_notification( task_id = request.path_params['id'] push_id = request.path_params['push_id'] params = GetTaskPushNotificationConfigRequest( - task_id=f'tasks/{task_id}', + task_id=task_id, id=push_id, ) config = ( @@ -221,9 +221,9 @@ async def set_push_notification( params = a2a_pb2.CreateTaskPushNotificationConfigRequest() Parse(body, params) # Set the parent to the task resource name format - params.task_id = f'tasks/{task_id}' + params.task_id = task_id config = ( - await self.request_handler.on_set_task_push_notification_config( + await self.request_handler.on_create_task_push_notification_config( params, context ) ) diff --git a/src/a2a/utils/parts.py b/src/a2a/utils/parts.py index 1d0aaff46..4043f0927 100644 --- a/src/a2a/utils/parts.py +++ b/src/a2a/utils/parts.py @@ -22,7 +22,7 @@ def get_text_parts(parts: Sequence[Part]) -> list[str]: return [part.text for part in parts if part.HasField('text')] -def get_data_parts(parts: Sequence[Part]) -> list[dict[str, Any]]: +def get_data_parts(parts: Sequence[Part]) -> list[Any]: """Extracts dictionary data from all data Parts in a list of Parts. Args: diff --git a/tests/client/transports/test_grpc_client.py b/tests/client/transports/test_grpc_client.py index f868b351d..8645b5a9d 100644 --- a/tests/client/transports/test_grpc_client.py +++ b/tests/client/transports/test_grpc_client.py @@ -177,7 +177,7 @@ def sample_task_push_notification_config( ) -> TaskPushNotificationConfig: """Provides a sample TaskPushNotificationConfig object.""" return TaskPushNotificationConfig( - task_id='tasks/task-1', + task_id='task-1', id=sample_push_notification_config.id, push_notification_config=sample_push_notification_config, ) diff --git a/tests/integration/test_client_server_integration.py b/tests/integration/test_client_server_integration.py index ae5008f72..dc528cb6c 100644 --- a/tests/integration/test_client_server_integration.py +++ b/tests/integration/test_client_server_integration.py @@ -77,7 +77,7 @@ ) CALLBACK_CONFIG = TaskPushNotificationConfig( - task_id='tasks/task-callback-123', + task_id='task-callback-123', id='pnc-abc', push_notification_config=PushNotificationConfig( id='pnc-abc', url='http://callback.example.com', token='' @@ -120,7 +120,9 @@ async def stream_side_effect(*args, **kwargs): # Configure other methods handler.on_get_task.return_value = GET_TASK_RESPONSE handler.on_cancel_task.return_value = CANCEL_TASK_RESPONSE - handler.on_set_task_push_notification_config.return_value = CALLBACK_CONFIG + handler.on_create_task_push_notification_config.return_value = ( + CALLBACK_CONFIG + ) handler.on_get_task_push_notification_config.return_value = CALLBACK_CONFIG async def resubscribe_side_effect(*args, **kwargs): @@ -414,7 +416,7 @@ async def test_http_transport_get_task( handler = transport_setup.handler # Use GetTaskRequest with name (AIP resource format) - params = GetTaskRequest(id=f'tasks/{GET_TASK_RESPONSE.id}') + params = GetTaskRequest(id=GET_TASK_RESPONSE.id) result = await transport.get_task(request=params) assert result.id == GET_TASK_RESPONSE.id @@ -465,7 +467,7 @@ async def test_http_transport_cancel_task( handler = transport_setup.handler # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') + params = CancelTaskRequest(id=CANCEL_TASK_RESPONSE.id) result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -489,7 +491,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') + params = CancelTaskRequest(id=CANCEL_TASK_RESPONSE.id) result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -517,7 +519,7 @@ async def test_http_transport_set_task_callback( # Create CreateTaskPushNotificationConfigRequest with required fields params = CreateTaskPushNotificationConfigRequest( - task_id='tasks/task-callback-123', + task_id='task-callback-123', config_id='pnc-abc', config=CALLBACK_CONFIG.push_notification_config, ) @@ -533,7 +535,7 @@ async def test_http_transport_set_task_callback( result.push_notification_config.url == CALLBACK_CONFIG.push_notification_config.url ) - handler.on_set_task_push_notification_config.assert_awaited_once() + handler.on_create_task_push_notification_config.assert_awaited_once() if hasattr(transport, 'close'): await transport.close() @@ -554,7 +556,7 @@ def channel_factory(address: str) -> Channel: # Create CreateTaskPushNotificationConfigRequest with required fields params = CreateTaskPushNotificationConfigRequest( - task_id='tasks/task-callback-123', + task_id='task-callback-123', config_id='pnc-abc', config=CALLBACK_CONFIG.push_notification_config, ) @@ -570,7 +572,7 @@ def channel_factory(address: str) -> Channel: result.push_notification_config.url == CALLBACK_CONFIG.push_notification_config.url ) - handler.on_set_task_push_notification_config.assert_awaited_once() + handler.on_create_task_push_notification_config.assert_awaited_once() await transport.close() @@ -666,7 +668,7 @@ async def test_http_transport_resubscribe( handler = transport_setup.handler # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') + params = SubscribeToTaskRequest(id=RESUBSCRIBE_EVENT.task_id) stream = transport.subscribe(request=params) first_event = await anext(stream) @@ -692,7 +694,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') + params = SubscribeToTaskRequest(id=RESUBSCRIBE_EVENT.task_id) stream = transport.subscribe(request=params) first_event = await anext(stream) From 38d266ad51eef76db68d97340ffea457ef719c00 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Wed, 4 Feb 2026 15:35:02 +0100 Subject: [PATCH 3/4] fix(tests): resolve failing tests after review feedback Signed-off-by: Luca Muscariello --- src/a2a/client/transports/rest.py | 8 ++++---- .../request_handlers/default_request_handler.py | 8 ++++---- .../test_client_server_integration.py | 8 ++++---- .../test_default_request_handler.py | 16 ++++++++-------- tests/server/test_integration.py | 6 ++++-- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/a2a/client/transports/rest.py b/src/a2a/client/transports/rest.py index fc15f6396..7ab13e648 100644 --- a/src/a2a/client/transports/rest.py +++ b/src/a2a/client/transports/rest.py @@ -259,7 +259,7 @@ async def cancel_task( context, ) response_data = await self._send_post_request( - f'/v1/tasks/{request.id}:cancel', payload, modified_kwargs + f'/v1/{request.id}:cancel', payload, modified_kwargs ) response: Task = ParseDict(response_data, Task()) return response @@ -281,7 +281,7 @@ async def set_task_callback( payload, modified_kwargs, context ) response_data = await self._send_post_request( - f'/v1/tasks/{request.task_id}/pushNotificationConfigs', + f'/v1/{request.task_id}/pushNotificationConfigs', payload, modified_kwargs, ) @@ -313,7 +313,7 @@ async def get_task_callback( if 'task_id' in params: del params['task_id'] response_data = await self._send_get_request( - f'/v1/tasks/{request.task_id}/pushNotificationConfigs/{request.id}', + f'/v1/{request.task_id}/pushNotificationConfigs/{request.id}', params, modified_kwargs, ) @@ -339,7 +339,7 @@ async def subscribe( async with aconnect_sse( self.httpx_client, 'GET', - f'{self.url}/v1/tasks/{request.id}:subscribe', + f'{self.url}/v1/{request.id}:subscribe', **modified_kwargs, ) as event_source: try: diff --git a/src/a2a/server/request_handlers/default_request_handler.py b/src/a2a/server/request_handlers/default_request_handler.py index 86a21720f..f323b41ea 100644 --- a/src/a2a/server/request_handlers/default_request_handler.py +++ b/src/a2a/server/request_handlers/default_request_handler.py @@ -486,7 +486,7 @@ async def on_create_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = params.task_id + task_id = _extract_task_id(params.task_id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -514,7 +514,7 @@ async def on_get_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = params.task_id + task_id = _extract_task_id(params.task_id) config_id = params.id task: Task | None = await self.task_store.get(task_id, context) if not task: @@ -546,7 +546,7 @@ async def on_subscribe_to_task( Allows a client to re-attach to a running streaming task's event stream. Requires the task and its queue to still be active. """ - task_id = params.id + task_id = _extract_task_id(params.id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) @@ -588,7 +588,7 @@ async def on_list_task_push_notification_config( if not self._push_config_store: raise ServerError(error=UnsupportedOperationError()) - task_id = params.task_id + task_id = _extract_task_id(params.task_id) task: Task | None = await self.task_store.get(task_id, context) if not task: raise ServerError(error=TaskNotFoundError()) diff --git a/tests/integration/test_client_server_integration.py b/tests/integration/test_client_server_integration.py index dc528cb6c..e08ab4a8d 100644 --- a/tests/integration/test_client_server_integration.py +++ b/tests/integration/test_client_server_integration.py @@ -467,7 +467,7 @@ async def test_http_transport_cancel_task( handler = transport_setup.handler # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(id=CANCEL_TASK_RESPONSE.id) + params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -519,7 +519,7 @@ async def test_http_transport_set_task_callback( # Create CreateTaskPushNotificationConfigRequest with required fields params = CreateTaskPushNotificationConfigRequest( - task_id='task-callback-123', + task_id='tasks/task-callback-123', config_id='pnc-abc', config=CALLBACK_CONFIG.push_notification_config, ) @@ -596,7 +596,7 @@ async def test_http_transport_get_task_callback( # Use GetTaskPushNotificationConfigRequest with name field (resource name) params = GetTaskPushNotificationConfigRequest( - task_id=CALLBACK_CONFIG.task_id, id=CALLBACK_CONFIG.id + task_id=f'tasks/{CALLBACK_CONFIG.task_id}', id=CALLBACK_CONFIG.id ) result = await transport.get_task_callback(request=params) @@ -668,7 +668,7 @@ async def test_http_transport_resubscribe( handler = transport_setup.handler # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(id=RESUBSCRIBE_EVENT.task_id) + params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') stream = transport.subscribe(request=params) first_event = await anext(stream) diff --git a/tests/server/request_handlers/test_default_request_handler.py b/tests/server/request_handlers/test_default_request_handler.py index d39ada2ba..6247ef194 100644 --- a/tests/server/request_handlers/test_default_request_handler.py +++ b/tests/server/request_handlers/test_default_request_handler.py @@ -1853,7 +1853,7 @@ async def noop_coro_for_task(): @pytest.mark.asyncio async def test_set_task_push_notification_config_no_notifier(): - """Test on_set_task_push_notification_config when _push_config_store is None.""" + """Test on_create_task_push_notification_config when _push_config_store is None.""" request_handler = DefaultRequestHandler( agent_executor=MockAgentExecutor(), task_store=AsyncMock(spec=TaskStore), @@ -1867,7 +1867,7 @@ async def test_set_task_push_notification_config_no_notifier(): from a2a.utils.errors import ServerError # Local import with pytest.raises(ServerError) as exc_info: - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( params, create_server_call_context() ) assert isinstance(exc_info.value.error, UnsupportedOperationError) @@ -1875,7 +1875,7 @@ async def test_set_task_push_notification_config_no_notifier(): @pytest.mark.asyncio async def test_set_task_push_notification_config_task_not_found(): - """Test on_set_task_push_notification_config when task is not found.""" + """Test on_create_task_push_notification_config when task is not found.""" mock_task_store = AsyncMock(spec=TaskStore) mock_task_store.get.return_value = None # Task not found mock_push_store = AsyncMock(spec=PushNotificationConfigStore) @@ -1896,7 +1896,7 @@ async def test_set_task_push_notification_config_task_not_found(): context = create_server_call_context() with pytest.raises(ServerError) as exc_info: - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( params, context ) @@ -2010,7 +2010,7 @@ async def test_get_task_push_notification_config_info_with_config(): ), ) context = create_server_call_context() - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( set_config_params, context ) @@ -2049,7 +2049,7 @@ async def test_get_task_push_notification_config_info_with_config_no_id(): config_id='default', config=PushNotificationConfig(url='http://1.example.com'), ) - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( set_config_params, create_server_call_context() ) @@ -2292,7 +2292,7 @@ async def test_list_task_push_notification_config_info_with_config_and_no_id(): config_id='default', config=PushNotificationConfig(url='http://1.example.com'), ) - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( set_config_params1, create_server_call_context() ) @@ -2301,7 +2301,7 @@ async def test_list_task_push_notification_config_info_with_config_and_no_id(): config_id='default', config=PushNotificationConfig(url='http://2.example.com'), ) - await request_handler.on_set_task_push_notification_config( + await request_handler.on_create_task_push_notification_config( set_config_params2, create_server_call_context() ) diff --git a/tests/server/test_integration.py b/tests/server/test_integration.py index c633aac50..dcd580b44 100644 --- a/tests/server/test_integration.py +++ b/tests/server/test_integration.py @@ -533,7 +533,9 @@ def test_set_push_notification_config( url='https://example.com', token='secret-token' ), ) - handler.on_set_task_push_notification_config.return_value = task_push_config + handler.on_create_task_push_notification_config.return_value = ( + task_push_config + ) # Send request response = client.post( @@ -559,7 +561,7 @@ def test_set_push_notification_config( assert data['result']['pushNotificationConfig']['token'] == 'secret-token' # Verify handler was called - handler.on_set_task_push_notification_config.assert_awaited_once() + handler.on_create_task_push_notification_config.assert_awaited_once() def test_get_push_notification_config( From c181de748c4d8ffc5fad1ebc84e7b6e32c3710ee Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Wed, 4 Feb 2026 21:49:18 +0100 Subject: [PATCH 4/4] fix(client): update rest transport URL construction and integration tests Signed-off-by: Luca Muscariello --- src/a2a/client/transports/rest.py | 2 +- tests/integration/test_client_server_integration.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/a2a/client/transports/rest.py b/src/a2a/client/transports/rest.py index 7ab13e648..b36f9ec4f 100644 --- a/src/a2a/client/transports/rest.py +++ b/src/a2a/client/transports/rest.py @@ -339,7 +339,7 @@ async def subscribe( async with aconnect_sse( self.httpx_client, 'GET', - f'{self.url}/v1/{request.id}:subscribe', + f'{self.url}/v1/tasks/{request.id}:subscribe', **modified_kwargs, ) as event_source: try: diff --git a/tests/integration/test_client_server_integration.py b/tests/integration/test_client_server_integration.py index e08ab4a8d..6a0aeae75 100644 --- a/tests/integration/test_client_server_integration.py +++ b/tests/integration/test_client_server_integration.py @@ -491,7 +491,7 @@ def channel_factory(address: str) -> Channel: transport = GrpcTransport(channel=channel, agent_card=agent_card) # Use CancelTaskRequest with name (AIP resource format) - params = CancelTaskRequest(id=CANCEL_TASK_RESPONSE.id) + params = CancelTaskRequest(id=f'tasks/{CANCEL_TASK_RESPONSE.id}') result = await transport.cancel_task(request=params) assert result.id == CANCEL_TASK_RESPONSE.id @@ -556,7 +556,7 @@ def channel_factory(address: str) -> Channel: # Create CreateTaskPushNotificationConfigRequest with required fields params = CreateTaskPushNotificationConfigRequest( - task_id='task-callback-123', + task_id='tasks/task-callback-123', config_id='pnc-abc', config=CALLBACK_CONFIG.push_notification_config, ) @@ -631,7 +631,7 @@ def channel_factory(address: str) -> Channel: # Use GetTaskPushNotificationConfigRequest with name field (resource name) params = GetTaskPushNotificationConfigRequest( - task_id=CALLBACK_CONFIG.task_id, id=CALLBACK_CONFIG.id + task_id=f'tasks/{CALLBACK_CONFIG.task_id}', id=CALLBACK_CONFIG.id ) result = await transport.get_task_callback(request=params) @@ -668,7 +668,7 @@ async def test_http_transport_resubscribe( handler = transport_setup.handler # Use SubscribeToTaskRequest with name (AIP resource format) - params = SubscribeToTaskRequest(id=f'tasks/{RESUBSCRIBE_EVENT.task_id}') + params = SubscribeToTaskRequest(id=RESUBSCRIBE_EVENT.task_id) stream = transport.subscribe(request=params) first_event = await anext(stream)