diff --git a/src/a2a/server/request_handlers/default_request_handler.py b/src/a2a/server/request_handlers/default_request_handler.py index f8d56c24c..387fc864d 100644 --- a/src/a2a/server/request_handlers/default_request_handler.py +++ b/src/a2a/server/request_handlers/default_request_handler.py @@ -137,25 +137,15 @@ async def on_list_tasks( ) -> ListTasksResponse: """Default handler for 'tasks/list'.""" page = await self.task_store.list(params, context) - processed_tasks = [] for task in page.tasks: - processed_task = task - if not params.include_artifacts: - new_task = Task() - new_task.CopyFrom(processed_task) - new_task.ClearField('artifacts') - processed_task = new_task - - if params.history_length > 0: - processed_task = apply_history_length( - processed_task, params.history_length - ) - processed_tasks.append(processed_task) - return ListTasksResponse( - next_page_token=page.next_page_token or '', - tasks=processed_tasks, - ) + task.ClearField('artifacts') + + updated_task = apply_history_length(task, params.history_length) + if updated_task is not task: + task.CopyFrom(updated_task) + + return page async def on_cancel_task( self, diff --git a/src/a2a/server/tasks/database_task_store.py b/src/a2a/server/tasks/database_task_store.py index b41e797aa..0acb9c2d4 100644 --- a/src/a2a/server/tasks/database_task_store.py +++ b/src/a2a/server/tasks/database_task_store.py @@ -261,7 +261,8 @@ async def list( return a2a_pb2.ListTasksResponse( tasks=tasks[:page_size], total_size=total_count, - next_page_token=next_page_token or '', + next_page_token=next_page_token, + page_size=page_size, ) async def delete( diff --git a/src/a2a/server/tasks/inmemory_task_store.py b/src/a2a/server/tasks/inmemory_task_store.py index c5fe1b8dc..241d9899e 100644 --- a/src/a2a/server/tasks/inmemory_task_store.py +++ b/src/a2a/server/tasks/inmemory_task_store.py @@ -106,7 +106,8 @@ async def list( break if not valid_token: raise ValueError(f'Invalid page token: {params.page_token}') - end_idx = start_idx + (params.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE) + page_size = params.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE + end_idx = start_idx + page_size next_page_token = ( encode_page_token(tasks[end_idx].id) if end_idx < total_size @@ -115,9 +116,10 @@ async def list( tasks = tasks[start_idx:end_idx] return a2a_pb2.ListTasksResponse( - next_page_token=next_page_token or '', + next_page_token=next_page_token, tasks=tasks, total_size=total_size, + page_size=page_size, ) async def delete( diff --git a/tests/integration/test_client_server_integration.py b/tests/integration/test_client_server_integration.py index 011359fc3..3299af1d6 100644 --- a/tests/integration/test_client_server_integration.py +++ b/tests/integration/test_client_server_integration.py @@ -96,6 +96,8 @@ LIST_TASKS_RESPONSE = ListTasksResponse( tasks=[TASK_FROM_BLOCKING, GET_TASK_RESPONSE], next_page_token='page-2', + total_size=12, + page_size=10, ) @@ -480,6 +482,8 @@ async def test_http_transport_list_tasks( assert len(result.tasks) == 2 assert result.next_page_token == 'page-2' + assert result.total_size == 12 + assert result.page_size == 10 handler.on_list_tasks.assert_awaited_once() if hasattr(transport, 'close'): diff --git a/tests/integration/test_end_to_end.py b/tests/integration/test_end_to_end.py index b8b7e91f6..9d6aa65df 100644 --- a/tests/integration/test_end_to_end.py +++ b/tests/integration/test_end_to_end.py @@ -304,6 +304,8 @@ async def test_end_to_end_list_tasks(transport_setups): list_response = await transport.list_tasks(request=list_request) assert 0 < len(list_response.tasks) <= page_size + assert list_response.total_size == total_items + assert list_response.page_size == page_size for task in list_response.tasks: unique_task_ids.add(task.id) diff --git a/tests/server/tasks/test_database_task_store.py b/tests/server/tasks/test_database_task_store.py index e8667338b..aa9132172 100644 --- a/tests/server/tasks/test_database_task_store.py +++ b/tests/server/tasks/test_database_task_store.py @@ -30,6 +30,7 @@ TaskState, TaskStatus, ) +from a2a.utils.constants import DEFAULT_LIST_TASKS_PAGE_SIZE # DSNs for different databases @@ -305,6 +306,7 @@ async def test_list_tasks( assert retrieved_ids == expected_ids assert page.total_size == total_count assert page.next_page_token == (next_page_token or '') + assert page.page_size == (params.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE) # Cleanup for task in tasks_to_create: diff --git a/tests/server/tasks/test_inmemory_task_store.py b/tests/server/tasks/test_inmemory_task_store.py index e6534d868..d6ebc5919 100644 --- a/tests/server/tasks/test_inmemory_task_store.py +++ b/tests/server/tasks/test_inmemory_task_store.py @@ -3,6 +3,7 @@ from a2a.server.tasks import InMemoryTaskStore from a2a.types.a2a_pb2 import Task, TaskState, TaskStatus, ListTasksRequest +from a2a.utils.constants import DEFAULT_LIST_TASKS_PAGE_SIZE def create_minimal_task( @@ -167,6 +168,7 @@ async def test_list_tasks( assert retrieved_ids == expected_ids assert page.total_size == total_count assert page.next_page_token == (next_page_token or '') + assert page.page_size == (params.page_size or DEFAULT_LIST_TASKS_PAGE_SIZE) # Cleanup for task in tasks_to_create: