|
8 | 8 |
|
9 | 9 | from google.protobuf.json_format import MessageToDict, Parse, ParseDict |
10 | 10 | from httpx_sse import SSEError, aconnect_sse |
| 11 | +from pydantic import BaseModel |
11 | 12 |
|
12 | 13 | from a2a.client.card_resolver import A2ACardResolver |
13 | 14 | from a2a.client.errors import A2AClientHTTPError, A2AClientJSONError |
|
18 | 19 | from a2a.types import ( |
19 | 20 | AgentCard, |
20 | 21 | GetTaskPushNotificationConfigParams, |
| 22 | + ListTasksParams, |
| 23 | + ListTasksResult, |
21 | 24 | Message, |
22 | 25 | MessageSendParams, |
23 | 26 | Task, |
|
28 | 31 | TaskStatusUpdateEvent, |
29 | 32 | ) |
30 | 33 | from a2a.utils import proto_utils |
| 34 | +from a2a.utils.constants import DEFAULT_LIST_TASKS_PAGE_SIZE |
31 | 35 | from a2a.utils.telemetry import SpanKind, trace_class |
32 | 36 |
|
33 | 37 |
|
@@ -244,6 +248,28 @@ async def get_task( |
244 | 248 | ParseDict(response_data, task) |
245 | 249 | return proto_utils.FromProto.task(task) |
246 | 250 |
|
| 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 | + |
247 | 273 | async def cancel_task( |
248 | 274 | self, |
249 | 275 | request: TaskIdParams, |
@@ -415,3 +441,21 @@ async def get_card( |
415 | 441 | async def close(self) -> None: |
416 | 442 | """Closes the httpx client.""" |
417 | 443 | 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