-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Fix: Correct message part ordering in A2A history #3262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).
View this failed invocation of the CLA check for more information.
For the most up to date status, view the checks section at the bottom of the pull request.
Response from ADK Triaging Agent
Hello @eranco74, thank you for creating this PR!
Before we can proceed with the review, could you please address the following points from our contribution guidelines:
- Sign our Contributor License Agreement (CLA): It appears the CLA check has failed. Please visit https://cla.developers.google.com/ to sign the agreement.
- Testing Plan: Could you please provide a testing plan for your changes? This should include details on unit tests and/or manual end-to-end tests as described in our testing requirements.
This information is necessary to ensure the quality and maintainability of the project. Thanks!
8e8f7ef to
626425c
Compare
Unit tests:
python3.13 -m pytest tests/unittests/agents/test_remote_a2a_agent.py -v
==================================================================================================================== test session starts =====================================================================================================================
platform linux -- Python 3.13.1, pytest-8.4.1, pluggy-1.5.0 -- /usr/bin/python3.13
cachedir: .pytest_cache
rootdir: /home/eran/go/src/github/eranco74/adk-python
configfile: pyproject.toml
plugins: langsmith-0.3.45, mock-3.14.1, asyncio-1.1.0, anyio-4.11.0
asyncio: mode=Mode.AUTO, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 67 items
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_agent_card_object PASSED [ 1%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_url_string PASSED [ 2%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_file_path PASSED [ 4%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_shared_httpx_client PASSED [ 5%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_factory PASSED [ 7%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_none_agent_card PASSED [ 8%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_empty_string_agent_card PASSED [ 10%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_invalid_type_agent_card PASSED [ 11%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentInit::test_init_with_custom_timeout PASSED [ 13%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_httpx_client_creates_new_client PASSED [ 14%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_httpx_client_reuses_existing_client PASSED [ 16%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_factory_reuses_existing_client PASSED [ 17%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_httpx_client_updates_factory_with_new_client PASSED [ 19%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_httpx_client_reregisters_transports_with_new_client PASSED [ 20%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_resolve_agent_card_from_url_success PASSED [ 22%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_resolve_agent_card_from_url_invalid_url PASSED [ 23%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_resolve_agent_card_from_file_success PASSED [ 25%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_resolve_agent_card_from_file_not_found PASSED [ 26%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_resolve_agent_card_from_file_invalid_json PASSED [ 28%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_validate_agent_card_success PASSED [ 29%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_validate_agent_card_no_url PASSED [ 31%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_validate_agent_card_invalid_url PASSED [ 32%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_resolved_with_direct_agent_card PASSED [ 34%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_resolved_with_direct_agent_card_with_factory PASSED [ 35%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_resolved_with_url_source PASSED [ 37%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentResolution::test_ensure_resolved_already_resolved PASSED [ 38%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_create_a2a_request_for_user_function_response_no_function_call PASSED [ 40%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_create_a2a_request_for_user_function_response_success PASSED [ 41%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_construct_message_parts_from_session_success PASSED [ 43%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_construct_message_parts_from_session_empty_events PASSED [ 44%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_success_with_message PASSED [ 46%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_task_completed_and_no_update PASSED [ 47%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_task_submitted_and_no_update PASSED [ 49%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_task_status_update_with_message PASSED [ 50%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_task_status_working_update_with_message PASSED [ 52%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_task_status_update_no_message PASSED [ 53%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_artifact_update PASSED [ 55%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandling::test_handle_a2a_response_with_partial_artifact_update PASSED [ 56%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_create_a2a_request_for_user_function_response_no_function_call PASSED [ 58%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_create_a2a_request_for_user_function_response_success PASSED [ 59%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_construct_message_parts_from_session_success PASSED [ 61%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_construct_message_parts_from_session_empty_events PASSED [ 62%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_success_with_message PASSED [ 64%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_task_completed_and_no_update PASSED [ 65%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_task_submitted_and_no_update PASSED [ 67%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_task_status_update_with_message PASSED [ 68%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_task_status_working_update_with_message PASSED [ 70%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_task_status_update_no_message PASSED [ 71%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_artifact_update PASSED [ 73%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentMessageHandlingFromFactory::test_handle_a2a_response_with_partial_artifact_update PASSED [ 74%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecution::test_run_async_impl_initialization_failure PASSED [ 76%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecution::test_run_async_impl_no_message_parts PASSED [ 77%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecution::test_run_async_impl_successful_request PASSED [ 79%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecution::test_run_async_impl_a2a_client_error PASSED [ 80%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecution::test_run_live_impl_not_implemented PASSED [ 82%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecutionFromFactory::test_run_async_impl_initialization_failure PASSED [ 83%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecutionFromFactory::test_run_async_impl_no_message_parts PASSED [ 85%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecutionFromFactory::test_run_async_impl_successful_request PASSED [ 86%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecutionFromFactory::test_run_async_impl_a2a_client_error PASSED [ 88%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentExecutionFromFactory::test_run_live_impl_not_implemented PASSED [ 89%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentCleanup::test_cleanup_owns_httpx_client PASSED [ 91%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentCleanup::test_cleanup_owns_httpx_client_factory PASSED [ 92%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentCleanup::test_cleanup_does_not_own_httpx_client PASSED [ 94%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentCleanup::test_cleanup_does_not_own_httpx_client_factory PASSED [ 95%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentCleanup::test_cleanup_client_close_error PASSED [ 97%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentIntegration::test_full_workflow_with_direct_agent_card PASSED [ 98%]
tests/unittests/agents/test_remote_a2a_agent.py::TestRemoteA2aAgentIntegration::test_full_workflow_with_direct_agent_card_and_factory PASSED [100%]
...
============================================================================================================== 67 passed, 77 warnings in 4.81s ===============================================================================================================
Response from ADK Triaging Agent
Hello @eranco74, thank you for the update and for providing the unit test results!
Before we can proceed with a full review, could you please address the remaining items from our contribution guidelines?
- Sign our Contributor License Agreement (CLA): The CLA check is still failing. You can sign the agreement at https://cla.developers.google.com/.
- Associate a GitHub Issue: For bug fixes, we require an associated GitHub issue. If one doesn't exist, please create one and link it in the PR description.
- Manual End-to-End (E2E) Tests: Could you please provide logs or screenshots from a manual E2E test to demonstrate that the fix works as expected? This is very helpful for reviewers to understand the impact of the change.
You can find more details in our CONTRIBUTING.md. Thanks for your contribution!
626425c to
0578d43
Compare
The overall logic processes events in reverse chronological order and then reverses the entire list of collected parts at the end to restore the correct sequence of messages. However, the parts *within* a single message were being appended in their original forward order. This resulted in their sequence being incorrectly inverted by the final list reversal. This change fixes the issue by iterating over an event's parts in reverse. This pre-reversal ensures that after the final list-wide reversal, the internal order of parts within each message is correctly maintained. Signed-off-by: Eran Cohen <eranco@redhat.com>
0578d43 to
a7f01bc
Compare
Relates to #3260
@speedstorm1 - Can I be assigned to this?
Uh oh!
There was an error while loading. Please reload this page.
Link to Issue or Description of Change
The previous logic iterated through session events in reverse and then reversed the resulting list of parts. This caused incorrect ordering for multi-part messages generated by
_present_other_agent_message.Specifically, introductory text like "For context:" was appearing after the content it was meant to introduce.
This change simplifies the implementation by removing both reversals. It now processes events in chronological order, ensuring all message parts are appended in the correct sequence.
Please ensure you have read the contribution guide before creating a pull request.
Problem:
Incorrect ordering for multi-part messages generated by
_present_other_agent_message.Solution:
processes events in chronological order, ensuring all message parts are appended in the correct sequence.
Testing Plan
Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes.
Unit Tests:
Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix.
Checklist
Additional context