|
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 |
|
@@ -239,6 +243,28 @@ async def get_task( |
239 | 243 | ParseDict(response_data, task) |
240 | 244 | return proto_utils.FromProto.task(task) |
241 | 245 |
|
| 246 | + async def list_tasks( |
| 247 | + self, |
| 248 | + request: ListTasksParams, |
| 249 | + *, |
| 250 | + context: ClientCallContext | None = None, |
| 251 | + ) -> ListTasksResult: |
| 252 | + """Retrieves tasks for an agent.""" |
| 253 | + _, modified_kwargs = await self._apply_interceptors( |
| 254 | + request.model_dump(mode='json', exclude_none=True), |
| 255 | + self._get_http_args(context), |
| 256 | + context, |
| 257 | + ) |
| 258 | + response_data = await self._send_get_request( |
| 259 | + '/v1/tasks', |
| 260 | + _model_to_query_params(request), |
| 261 | + modified_kwargs, |
| 262 | + ) |
| 263 | + response = a2a_pb2.ListTasksResponse() |
| 264 | + ParseDict(response_data, response) |
| 265 | + page_size = request.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE |
| 266 | + return proto_utils.FromProto.list_tasks_result(response, page_size) |
| 267 | + |
242 | 268 | async def cancel_task( |
243 | 269 | self, |
244 | 270 | request: TaskIdParams, |
@@ -404,3 +430,21 @@ async def get_card( |
404 | 430 | async def close(self) -> None: |
405 | 431 | """Closes the httpx client.""" |
406 | 432 | await self.httpx_client.aclose() |
| 433 | + |
| 434 | + |
| 435 | +def _model_to_query_params(instance: BaseModel) -> dict[str, str]: |
| 436 | + data = instance.model_dump(mode='json', exclude_none=True) |
| 437 | + return _json_to_query_params(data) |
| 438 | + |
| 439 | + |
| 440 | +def _json_to_query_params(data: dict[str, Any]) -> dict[str, str]: |
| 441 | + query_dict = {} |
| 442 | + for key, value in data.items(): |
| 443 | + if isinstance(value, list): |
| 444 | + query_dict[key] = ','.join(map(str, value)) |
| 445 | + elif isinstance(value, bool): |
| 446 | + query_dict[key] = str(value).lower() |
| 447 | + else: |
| 448 | + query_dict[key] = str(value) |
| 449 | + |
| 450 | + return query_dict |
0 commit comments