Skip to content

Commit ba74f4c

Browse files
committed
Merge branch '1.0-dev' into ishymko/merge-main-1.0-dev
# Conflicts: # CHANGELOG.md # tests/client/transports/test_rest_client.py # tests/utils/test_proto_utils.py
2 parents ffe31e2 + 5a2ca75 commit ba74f4c

37 files changed

Lines changed: 1648 additions & 49 deletions

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: Run Unit Tests
33
on:
44
pull_request:
5-
branches: [main]
5+
branches: [main, 1.0-dev]
66
permissions:
77
contents: read
88
jobs:

CHANGELOG.md

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

4141
* return updated `agent_card` in `JsonRpcTransport.get_card()` ([#552](https://github.com/a2aproject/a2a-python/issues/552)) ([0ce239e](https://github.com/a2aproject/a2a-python/commit/0ce239e98f67ccbf154f2edcdbcee43f3b080ead))
4242

43+
4344
## [0.3.17](https://github.com/a2aproject/a2a-python/compare/v0.3.16...v0.3.17) (2025-11-24)
4445

4546

@@ -86,6 +87,20 @@
8687
## [0.3.11](https://github.com/a2aproject/a2a-python/compare/v0.3.10...v0.3.11) (2025-11-07)
8788

8889

90+
### Bug Fixes
91+
92+
* add metadata to send message request ([12b4a1d](https://github.com/a2aproject/a2a-python/commit/12b4a1d565a53794f5b55c8bd1728221c906ed41))
93+
94+
## [0.3.12](https://github.com/a2aproject/a2a-python/compare/v0.3.11...v0.3.12) (2025-11-12)
95+
96+
97+
### Bug Fixes
98+
99+
* **grpc:** Add `extensions` to `Artifact` converters. ([#523](https://github.com/a2aproject/a2a-python/issues/523)) ([c03129b](https://github.com/a2aproject/a2a-python/commit/c03129b99a663ae1f1ae72f20e4ead7807ede941))
100+
101+
## [0.3.11](https://github.com/a2aproject/a2a-python/compare/v0.3.10...v0.3.11) (2025-11-07)
102+
103+
89104
### Bug Fixes
90105

91106
* add metadata to send message request ([12b4a1d](https://github.com/a2aproject/a2a-python/commit/12b4a1d565a53794f5b55c8bd1728221c906ed41))

src/a2a/client/base_client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from a2a.types import (
1616
AgentCard,
1717
GetTaskPushNotificationConfigParams,
18+
ListTasksParams,
19+
ListTasksResult,
1820
Message,
1921
MessageSendConfiguration,
2022
MessageSendParams,
@@ -157,6 +159,15 @@ async def get_task(
157159
request, context=context, extensions=extensions
158160
)
159161

162+
async def list_tasks(
163+
self,
164+
request: ListTasksParams,
165+
*,
166+
context: ClientCallContext | None = None,
167+
) -> ListTasksResult:
168+
"""Retrieves tasks for an agent."""
169+
return await self._transport.list_tasks(request, context=context)
170+
160171
async def cancel_task(
161172
self,
162173
request: TaskIdParams,

src/a2a/client/client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from a2a.types import (
1313
AgentCard,
1414
GetTaskPushNotificationConfigParams,
15+
ListTasksParams,
16+
ListTasksResult,
1517
Message,
1618
PushNotificationConfig,
1719
Task,
@@ -137,6 +139,15 @@ async def get_task(
137139
) -> Task:
138140
"""Retrieves the current state and history of a specific task."""
139141

142+
@abstractmethod
143+
async def list_tasks(
144+
self,
145+
request: ListTasksParams,
146+
*,
147+
context: ClientCallContext | None = None,
148+
) -> ListTasksResult:
149+
"""Retrieves tasks for an agent."""
150+
140151
@abstractmethod
141152
async def cancel_task(
142153
self,

src/a2a/client/transports/base.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from a2a.types import (
66
AgentCard,
77
GetTaskPushNotificationConfigParams,
8+
ListTasksParams,
9+
ListTasksResult,
810
Message,
911
MessageSendParams,
1012
Task,
@@ -53,6 +55,15 @@ async def get_task(
5355
) -> Task:
5456
"""Retrieves the current state and history of a specific task."""
5557

58+
@abstractmethod
59+
async def list_tasks(
60+
self,
61+
request: ListTasksParams,
62+
*,
63+
context: ClientCallContext | None = None,
64+
) -> ListTasksResult:
65+
"""Retrieves tasks for an agent."""
66+
5667
@abstractmethod
5768
async def cancel_task(
5869
self,

src/a2a/client/transports/grpc.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from collections.abc import AsyncGenerator, Callable
44

5+
from a2a.utils.constants import DEFAULT_LIST_TASKS_PAGE_SIZE
6+
57

68
try:
79
import grpc
@@ -22,6 +24,8 @@
2224
from a2a.types import (
2325
AgentCard,
2426
GetTaskPushNotificationConfigParams,
27+
ListTasksParams,
28+
ListTasksResult,
2529
Message,
2630
MessageSendParams,
2731
Task,
@@ -168,6 +172,19 @@ async def get_task(
168172
)
169173
return proto_utils.FromProto.task(task)
170174

175+
async def list_tasks(
176+
self,
177+
request: ListTasksParams,
178+
*,
179+
context: ClientCallContext | None = None,
180+
) -> ListTasksResult:
181+
"""Retrieves tasks for an agent."""
182+
response = await self.stub.ListTasks(
183+
proto_utils.ToProto.list_tasks_request(request)
184+
)
185+
page_size = request.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE
186+
return proto_utils.FromProto.list_tasks_result(response, page_size)
187+
171188
async def cancel_task(
172189
self,
173190
request: TaskIdParams,

src/a2a/client/transports/jsonrpc.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
GetTaskRequest,
3232
GetTaskResponse,
3333
JSONRPCErrorResponse,
34+
ListTasksParams,
35+
ListTasksRequest,
36+
ListTasksResponse,
37+
ListTasksResult,
3438
Message,
3539
MessageSendParams,
3640
SendMessageRequest,
@@ -244,6 +248,26 @@ async def get_task(
244248
raise A2AClientJSONRPCError(response.root)
245249
return response.root.result
246250

251+
async def list_tasks(
252+
self,
253+
request: ListTasksParams,
254+
*,
255+
context: ClientCallContext | None = None,
256+
) -> ListTasksResult:
257+
"""Retrieves tasks for an agent."""
258+
rpc_request = ListTasksRequest(params=request, id=str(uuid4()))
259+
payload, modified_kwargs = await self._apply_interceptors(
260+
'tasks/list',
261+
rpc_request.model_dump(mode='json', exclude_none=True),
262+
self._get_http_args(context),
263+
context,
264+
)
265+
response_data = await self._send_request(payload, modified_kwargs)
266+
response = ListTasksResponse.model_validate(response_data)
267+
if isinstance(response.root, JSONRPCErrorResponse):
268+
raise A2AClientJSONRPCError(response.root)
269+
return response.root.result
270+
247271
async def cancel_task(
248272
self,
249273
request: TaskIdParams,

src/a2a/client/transports/rest.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from google.protobuf.json_format import MessageToDict, Parse, ParseDict
1010
from httpx_sse import SSEError, aconnect_sse
11+
from pydantic import BaseModel
1112

1213
from a2a.client.card_resolver import A2ACardResolver
1314
from a2a.client.errors import A2AClientHTTPError, A2AClientJSONError
@@ -18,6 +19,8 @@
1819
from a2a.types import (
1920
AgentCard,
2021
GetTaskPushNotificationConfigParams,
22+
ListTasksParams,
23+
ListTasksResult,
2124
Message,
2225
MessageSendParams,
2326
Task,
@@ -28,6 +31,7 @@
2831
TaskStatusUpdateEvent,
2932
)
3033
from a2a.utils import proto_utils
34+
from a2a.utils.constants import DEFAULT_LIST_TASKS_PAGE_SIZE
3135
from a2a.utils.telemetry import SpanKind, trace_class
3236

3337

@@ -244,6 +248,28 @@ async def get_task(
244248
ParseDict(response_data, task)
245249
return proto_utils.FromProto.task(task)
246250

251+
async def list_tasks(
252+
self,
253+
request: ListTasksParams,
254+
*,
255+
context: ClientCallContext | None = None,
256+
) -> ListTasksResult:
257+
"""Retrieves tasks for an agent."""
258+
_, modified_kwargs = await self._apply_interceptors(
259+
request.model_dump(mode='json', exclude_none=True),
260+
self._get_http_args(context),
261+
context,
262+
)
263+
response_data = await self._send_get_request(
264+
'/v1/tasks',
265+
_model_to_query_params(request),
266+
modified_kwargs,
267+
)
268+
response = a2a_pb2.ListTasksResponse()
269+
ParseDict(response_data, response)
270+
page_size = request.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE
271+
return proto_utils.FromProto.list_tasks_result(response, page_size)
272+
247273
async def cancel_task(
248274
self,
249275
request: TaskIdParams,
@@ -415,3 +441,21 @@ async def get_card(
415441
async def close(self) -> None:
416442
"""Closes the httpx client."""
417443
await self.httpx_client.aclose()
444+
445+
446+
def _model_to_query_params(instance: BaseModel) -> dict[str, str]:
447+
data = instance.model_dump(mode='json', exclude_none=True)
448+
return _json_to_query_params(data)
449+
450+
451+
def _json_to_query_params(data: dict[str, Any]) -> dict[str, str]:
452+
query_dict = {}
453+
for key, value in data.items():
454+
if isinstance(value, list):
455+
query_dict[key] = ','.join(map(str, value))
456+
elif isinstance(value, bool):
457+
query_dict[key] = str(value).lower()
458+
else:
459+
query_dict[key] = str(value)
460+
461+
return query_dict

0 commit comments

Comments
 (0)