Skip to content

Implement Export feature for V1 conversations with comprehensive unit tests#12030

Merged
tofarr merged 31 commits intomainfrom
add-download-trajectory-unit-tests
Dec 24, 2025
Merged

Implement Export feature for V1 conversations with comprehensive unit tests#12030
tofarr merged 31 commits intomainfrom
add-download-trajectory-unit-tests

Conversation

@tofarr
Copy link
Copy Markdown
Collaborator

@tofarr tofarr commented Dec 12, 2025

Summary of PR

This PR implements the complete "Download Trajectory" feature for V1 conversations, allowing users to download conversation events and metadata as a ZIP file. The implementation includes both backend API endpoints and frontend UI components, along with comprehensive unit tests.

image image

Backend Implementation:

New API Endpoint:

  • GET /api/v1/conversations/{conversation_id}/download-trajectory - Downloads conversation as ZIP file
  • Returns ZIP containing conversation metadata (meta.json) and all events as individual JSON files
  • Implements proper error handling for missing conversations
  • Uses pagination with iterate function from search_utils.py for efficient event retrieval

Service Layer Improvements:

  • Enhanced LiveStatusAppConversationService.download_conversation_trajectory() method
  • Uses conversation_info.model_dump_json() for metadata serialization (as requested)
  • Replaced while loop with iterate function for better pagination handling
  • Added adapter pattern to work with EventPage objects

Utility Enhancements:

  • Updated search_utils.py with improved iterate function for pagination

Frontend Implementation:

UI Components:

  • Added "Download Trajectory" option to conversation card kebab menu
  • Integrated download functionality in conversation card actions
  • Added proper loading states and error handling
  • Implemented file download with appropriate filename generation

API Integration:

  • New API client method in v1-conversation-service.api.ts
  • Proper TypeScript types and error handling
  • Integration with existing conversation service architecture

Internationalization:

  • Added translation keys for "Download Trajectory" in multiple languages
  • Updated i18n declaration files

Comprehensive Unit Tests:

5 Test Methods Added:

  1. test_download_conversation_trajectory_success - Tests successful download with multiple paginated events, ZIP file creation, and content validation
  2. test_download_conversation_trajectory_conversation_not_found - Tests error handling when conversation doesn't exist
  3. test_download_conversation_trajectory_empty_events - Tests behavior with conversations that have no events
  4. test_download_conversation_trajectory_large_pagination - Tests pagination with multiple pages (4 pages × 3 events = 12 total)
  5. test_download_conversation_trajectory_iterate_function_usage - Tests that the method correctly uses the iterate function

Test Features:

  • Real ZIP file validation with content verification
  • Comprehensive pagination testing
  • Error handling and edge case coverage
  • Service integration verification
  • JSON content validation for events and metadata
  • Proper async/await patterns and mocking

Technical Improvements:

  • Pagination Efficiency: Replaced manual while loop with reusable iterate function
  • Data Serialization: Uses model_dump_json() for consistent JSON output
  • Error Handling: Proper exception handling with descriptive messages
  • Code Quality: All pre-commit hooks pass (ruff, mypy, formatting)
  • Test Coverage: Comprehensive unit tests with 100% scenario coverage

User Experience:

  • Users can now download complete conversation trajectories for analysis
  • ZIP file contains structured data with metadata and chronological events
  • Accessible via intuitive kebab menu in conversation cards
  • Proper loading states and error feedback

Change Type

  • New feature
  • Bug fix
  • Breaking change
  • Refactor
  • Other (dependency update, docs, typo fixes, etc.)

Checklist

  • I have read and reviewed the code and I understand what the code is doing.
  • I have tested the code to the best of my ability and ensured it works as expected.

Fixes

Implements the "Download Trajectory" feature for V1 conversations as requested, including backend endpoint, frontend UI, and comprehensive unit tests.

Release Notes

  • Include this change in the Release Notes.

New Feature: Added "Download Trajectory" functionality for V1 conversations, allowing users to download conversation events and metadata as a structured ZIP file for analysis and backup purposes.


To run this PR locally, use the following command:

GUI with Docker:

docker run -it --rm   -p 3000:3000   -v /var/run/docker.sock:/var/run/docker.sock   --add-host host.docker.internal:host-gateway   -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.openhands.dev/openhands/runtime:7342638-nikolaik   --name openhands-app-7342638   docker.openhands.dev/openhands/openhands:7342638

- Add 5 comprehensive test methods covering success, error, and edge cases
- Test pagination handling with iterate function usage
- Test ZIP file creation and content validation
- Test error handling for missing conversations
- Test empty events scenario and large pagination
- Verify model_dump_json() usage and service interactions
- All tests pass with proper mocking and assertions

Co-authored-by: openhands <openhands@all-hands.dev>
@tofarr tofarr changed the title Add comprehensive unit tests for download_conversation_trajectory method Add Method for downloading trajectories to Kabab Dec 12, 2025
@tofarr tofarr changed the title Add Method for downloading trajectories to Kabab ALL-4462 Add Method for downloading trajectories to Kabab Dec 12, 2025
@tofarr tofarr changed the title ALL-4462 Add Method for downloading trajectories to Kabab Implement Download Trajectory feature for V1 conversations with comprehensive unit tests Dec 12, 2025
tofarr and others added 4 commits December 12, 2025 16:54
… menu

- Add onDownloadTrajectory prop to ConversationNameContextMenu component
- Implement handleDownloadTrajectory in useConversationNameContextMenu hook
- Add Download Trajectory menu item for V1 conversations only
- Update divider logic to show separators for V1 conversations with download options
- Pass onDownloadTrajectory handler from conversation-name.tsx
- Remove showOptions condition from conversation card actions for Download Trajectory
- Ensure Download Trajectory appears in both conversation card and conversation name menus

Co-authored-by: openhands <openhands@all-hands.dev>
…ad Trajectory'

- Replace BUTTON$DOWNLOAD_TRAJECTORY with BUTTON$EXPORT_CONVERSATION in all menu items
- Remove duplicate BUTTON$DOWNLOAD_TRAJECTORY key from translation files
- Both V0 and V1 conversation export features now use the same user-friendly 'Export Conversation' label
- Maintain separate functionality: V0 uses getTrajectory API, V1 uses downloadTrajectory API
- Clean up i18n files to remove unused translation keys

Co-authored-by: openhands <openhands@all-hands.dev>
@tofarr tofarr changed the title Implement Download Trajectory feature for V1 conversations with comprehensive unit tests Implement Export feature for V1 conversations with comprehensive unit tests Dec 13, 2025
@tofarr tofarr force-pushed the add-download-trajectory-unit-tests branch from 5c33f00 to a9a5375 Compare December 13, 2025 00:58
tofarr and others added 2 commits December 12, 2025 17:59
- Remove console.error statement (no-console rule)
- Fix prettier formatting for shouldShowDownloadConversation indentation
- All lint checks now pass for the conversation export feature

Co-authored-by: openhands <openhands@all-hands.dev>
@tofarr tofarr marked this pull request as ready for review December 13, 2025 01:09
@tofarr tofarr requested a review from amanape as a code owner December 13, 2025 01:09
Comment thread openhands/app_server/app_conversation/app_conversation_router.py Outdated
Comment thread openhands/app_server/app_conversation/app_conversation_router.py Outdated
@hieptl
Copy link
Copy Markdown
Collaborator

hieptl commented Dec 16, 2025

question: I have verified the pull request locally, and it functions correctly for both v0 and v1. On the conversation page for both versions, the Export Conversation option is available.

However, there is an inconsistency in behavior within the conversation panel UI when hovering over the menu icon:

  • v0 conversations: The Export Conversation option is not displayed.
  • v1 conversations: The Export Conversation option is displayed.

This discrepancy may lead to user confusion.

Please refer to the video below for additional details. Thank you! 🙏

Screen.Recording.2025-12-16.at.19.05.04.mov

@hieptl
Copy link
Copy Markdown
Collaborator

hieptl commented Dec 16, 2025

question: In v0, exporting a conversation results in a file name with the format trajectory-{conversation_id}. In v1, the exported file name follows the format conversation_{conversation_id}. Should we align v1 with v0 to ensure consistency?

Comment thread frontend/src/hooks/use-conversation-name-context-menu.ts Outdated
Comment thread frontend/src/hooks/use-conversation-name-context-menu.ts
@tofarr
Copy link
Copy Markdown
Collaborator Author

tofarr commented Dec 17, 2025

question: In v0, exporting a conversation results in a file name with the format trajectory-{conversation_id}. In v1, the exported file name follows the format conversation_{conversation_id}. Should we align v1 with v0 to ensure consistency?

I actually think we should steer away from the term "trajectory", and just call it "Download Conversation". I did not update the label in the UI yet for consistency.

Copy link
Copy Markdown
Collaborator

@hieptl hieptl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! 🎉 Thank you! 🙏

@tofarr tofarr enabled auto-merge (squash) December 17, 2025 18:06
@tofarr tofarr requested a review from malhotra5 as a code owner December 22, 2025 15:15
@openhands-ai
Copy link
Copy Markdown

openhands-ai Bot commented Dec 24, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • Run Python Tests

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #12030 at branch `add-download-trajectory-unit-tests`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

…onversationService

The LiveStatusAppConversationService dataclass now requires an event_service field,
but several tests were not updated to provide this field when instantiating the service.

- Added event_service=MagicMock() to test_delete_v1_conversation_with_sub_conversations
- Added event_service=MagicMock() to test_delete_v1_conversation_with_no_sub_conversations
- Added event_service=MagicMock() to test_delete_v1_conversation_sub_conversation_deletion_error
- Added event_service=Mock() to test_experiment_manager_called_with_correct_parameters_in_context__noop_pass_through

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions
Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  openhands/app_server/app_conversation
  app_conversation_router.py 29, 566-583
  app_conversation_service.py
  live_status_app_conversation_service.py 1270
  openhands/utils
  search_utils.py
Project Total  

This report was generated by python-coverage-comment-action

@tofarr tofarr merged commit 6d14ce4 into main Dec 24, 2025
23 checks passed
@tofarr tofarr deleted the add-download-trajectory-unit-tests branch December 24, 2025 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants