-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feat: Add Conversation Merge Functionality Bounty #1505 #3487
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
base: main
Are you sure you want to change the base?
Conversation
* feat: Add conversation merging functionality
Frontend:
- Multi-select merge UI with selection mode and bottom action bar
- Conversation list updates for selection indicators and guarded taps
- Provider support for mergeSelectedConversations with API integration
- Analytics tracking for conversationsMerged event
Backend:
- MergeConversationsRequest model and POST /v1/conversations/merge endpoint
- DB helper merge_conversations with validation and LLM structuring
- Merges segments, photos, events, action items, and audio files
* fix: remove invalid config section from pubspec.yaml
* feat: enhance conversation merge with improved adjacency validation and UX
- Move selection state to ConversationProvider for better state management
- Implement true adjacency validation: contiguous list position + 1-hour time gap
- Add tap-to-deselect functionality for selected conversations
- Block long-press selection for locked/discarded conversations
- Disable swipe-to-delete during selection mode
- Add canMergeSelectedConversations() validation method
- Improve merge error messages with specific validation feedback
- Add Mixpanel analytics tracking for merge operations
- Keep selection mode active until explicit cancel (no auto-exit on empty)
- Proper state cleanup on merge success/failure
* feat: complete conversation merge UX with Stack-based merge bar and search guards
Complete implementation of conversation merge feature with all UX improvements:
Selection Mode:
- Long-press enters selection with locked/discarded guards
- Tap to toggle selection (fast deselect for already-selected items)
- Swipe-to-delete disabled during selection mode
- 50% opacity for locked/discarded conversations (visual feedback)
- Checkbox indicators show selection state
- Purple border highlights selected conversations
Merge Bar UX:
- Positioned above bottom navigation using Stack + Positioned (bottom: 90)
- Shows selection count and Cancel/Merge buttons
- Merge button enabled only when canMergeSelectedConversations() passes
- Inline spinner during merge (no blocking dialog)
- Success toast (green) on successful merge
- Error toast (red) with specific validation messages
Validation & Safety:
- True adjacency: contiguous list position + ≤1-hour time gaps
- Locked/discarded conversations blocked from selection and merge
- Search automatically clears selection to prevent stale state
- Selection cleared after successful merge
- No count cap on merge (unlimited adjacent conversations)
Analytics:
- Track merge initiated, successful, and failed events
- Include conversation count and IDs in tracking
Backend Integration:
- mergeConversations API call with sorted conversation IDs
- Error message extraction from backend responses
- Local state updates after successful merge
* fix: correct delete_vector calls to pass both uid and conversation_id
The delete_vector function signature is delete_vector(uid, conversation_id) and it deletes
the Pinecone vector using the prefixed ID format: f'{uid}-{conversation_id}'.
Updated the merge endpoint to correctly call delete_vector(uid, conv_id) matching the
function signature and ensuring vectors are properly deleted with the correct ID prefix.
* Update backend/database/conversations.py
* fix: Add visible Cancel button and fix syntax errors in conversation merge UI - Fixed syntax errors in conversation_list_item.dart that were preventing compilation - Added white text color to Cancel button in merge action bar to make it visible against dark background - Fixed widget nesting structure in Dismissible widget - Changed UniqueKey() to ValueKey(widget.conversation.id) for consistent widget identity The Cancel button was present in the code but invisible due to default TextButton styling. * Update backend/database/conversations.py Co-authored-by: Copilot <[email protected]> * fix: Update delete_vector to use prefixed vector IDs Fixes critical bug where delete_vector was trying to delete by bare conversation_id instead of the prefixed ID format 'uid-conversation_id' that vectors are actually stored with in Pinecone. This caused: - TypeError at runtime (function signature mismatch) - Pinecone deletions never matching any vectors - Orphaned vectors remaining after conversation deletion/merge Changes: - Updated delete_vector signature to accept both uid and conversation_id - Construct prefixed vector_id using f'{uid}-{conversation_id}' - Enhanced logging to show the actual vector_id being deleted Addresses Copilot review comments on lines 143 and 696 in conversations.py * Revert pubspec.yaml to upstream version Remove unrelated Swift Package Manager config change to keep PR focused only on conversation merge feature code. * Update backend/database/conversations.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update backend/database/conversations.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update backend/routers/conversations.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: Eulices Lopez <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces functionality to merge conversations, with changes across the mobile app and the backend. The frontend is updated to allow users to select and merge conversations, and the backend adds a new API endpoint for this purpose. My review identifies a potential performance bottleneck in the client-side validation logic that could impact UI responsiveness, and a critical data integrity issue on the backend where the non-atomic deletion of old conversations after a merge could lead to data duplication or orphaned data. I've provided a suggestion for the performance issue and a recommendation for a more robust architectural approach for the backend issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds conversation merge functionality (Bounty #1505) that allows users to combine multiple adjacent conversations into a single conversation with merged transcripts, photos, action items, and events. The feature includes both backend API support and frontend UI with a selection mode interface.
Key Changes:
- Backend merge endpoint validates chronological adjacency and time gaps (≤1 hour), combines conversation data, and uses LLM to generate new metadata
- Frontend selection mode UI with visual indicators, validation logic for mergeable conversations, and merge confirmation flow
- Updated vector database deletion to use proper composite IDs (
uid-conversation_id)
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| backend/routers/conversations.py | Adds POST endpoint /v1/conversations/merge with validation, LLM processing, and batch deletion of original conversations |
| backend/database/conversations.py | Implements merge_conversations() function with validation for locked/discarded/consecutive conversations and data merging logic |
| backend/database/vector_db.py | Updates delete_vector() to accept uid parameter and construct proper composite vector IDs |
| backend/models/conversation.py | Adds MergeConversationsRequest model for API request validation |
| app/lib/providers/conversation_provider.dart | Implements selection mode state management, merge validation with adjacency checks, and API integration |
| app/lib/pages/conversations/conversations_page.dart | Adds selection mode UI with floating action bar showing selected count and merge button |
| app/lib/pages/conversations/widgets/conversation_list_item.dart | Adds selection mode support with visual indicators, long-press activation, and swipe-to-delete disabling during selection |
| app/lib/pages/conversations/widgets/conversations_group_widget.dart | Passes selection mode props to individual conversation list items |
| app/lib/backend/http/api/conversations.dart | Implements mergeConversations() API client function with error handling |
| app/lib/utils/analytics/mixpanel.dart | Adds conversationsMerged() analytics tracking method |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
…dex lookup performance Backend (routers/conversations.py): - Replace hard-delete with soft-delete pattern for merged conversations - Mark original conversations as discarded=True with merged_into_id reference - Reuses existing discarded filtering to hide from user views - Add rollback mechanism: if soft-delete fails, delete merged conversation - Prevents data duplication and orphaned conversations Frontend (providers/conversation_provider.dart): - Optimize conversation index lookup from O(N*M) to O(N) complexity - Replace nested indexWhere loop with map-based lookup - Improves performance and prevents UI lag with large conversation lists Other: - Fix pubspec.yaml: Remove invalid 'config' section under 'flutter' Addresses critical and high-severity feedback from Gemini Code Assist on PR BasedHardware#3487 (Bounty BasedHardware#1505)
…dex lookup performance Backend (routers/conversations.py): - Replace hard-delete with soft-delete pattern for merged conversations - Mark original conversations as discarded=True with merged_into_id reference - Reuses existing discarded filtering to hide from user views - Add rollback mechanism: if soft-delete fails, delete merged conversation - Prevents data duplication and orphaned conversations Frontend (providers/conversation_provider.dart): - Optimize conversation index lookup from O(N*M) to O(N) complexity - Replace nested indexWhere loop with map-based lookup - Improves performance and prevents UI lag with large conversation lists Other: - Fix pubspec.yaml: Remove invalid 'config' section under 'flutter' Addresses critical and high-severity feedback from Gemini Code Assist on PR BasedHardware#3487 (Bounty BasedHardware#1505)
|
demo doesnt show merging and reprocessing and summary being generated successfully @eulicesl |
Implements conversation merging to combine chronologically consecutive conversations into a single unified conversation with LLM-generated summaries.
Features
Long-press selection: Activate multi-select mode with long-press gesture
Visual indicators: Purple borders, checkboxes, and 50% opacity for locked/discarded items
Smart validation: Only consecutive conversations within 1-hour gaps can be merged
Action bar: Bottom toolbar with selection count, Cancel, and Merge buttons
Protected items: Locked and discarded conversations cannot be selected
Auto-cleanup: Original conversations and vector embeddings deleted after merge
LLM re-structuring: Auto-generates title, overview, emoji, and category for merged conversation
Implementation
Frontend (6 files)
Selection mode state management with validation logic
Multi-select UI with checkboxes and purple selection borders
Bottom action bar with loading states and error handling
Analytics tracking for merge events
Backend (4 files)
POST /v1/conversations/merge endpoint with LLM integration
Core merge logic: combines segments, photos, action items, events
Chronological consecutiveness validation
Critical fix: delete_vector(uid, conversation_id) now properly constructs prefixed Pinecone IDs
Validation Rules
Minimum 2 conversations
Chronologically consecutive (no conversations between selections)
Within 1-hour time gaps
No locked or discarded conversations
Adjacent in conversation list
Screen.Recording.2025-11-18.at.6.12.09.AM.mov