Skip to content

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Sep 8, 2025

Summary

This PR fixes critical issues with chat message edit and delete operations that were causing duplication and errors.

Problems Fixed

1. Message Editing Bug

  • Issue: When editing a chat message, the exported chat history contained duplicated entries. The edited message appeared twice instead of replacing the original.
  • Root Cause: When apiConversationHistoryIndex was -1 (message not found in API history), the code wasn't properly truncating the API conversation history.

2. Message Deletion Bug

  • Issue: Users encountered "Couldn't find timestamp" errors and messages weren't being deleted properly.
  • Root Cause: Similar to edit issue - incorrect handling when apiConversationHistoryIndex was -1, plus missing UI refresh after deletion.

Solution Implemented

Timestamp-Based Fallback Logic

Added fallback logic to both edit and delete operations when the exact API history index cannot be found:

  • When the API history index is -1, the code now searches for the first API message with timestamp >= target message timestamp
  • This ensures proper truncation of subsequent messages even when the exact message isn't in API history

UI State Refresh

Added explicit UI state refresh after message deletion to ensure the interface reflects the changes.

Changes Made

  • src/core/webview/webviewMessageHandler.ts: Added timestamp-based fallback and UI refresh
  • src/core/webview/ClineProvider.ts: Added timestamp-based fallback for checkpoint-driven edits
  • src/core/webview/tests/webviewMessageHandler.edit.spec.ts: Comprehensive edit test coverage
  • src/test/webviewMessageHandler.delete.spec.ts: Comprehensive delete test coverage

Testing

All tests passing:

  • ✅ Normal message deletion with valid indices
  • ✅ Timestamp-based fallback when API index is -1
  • ✅ Handling of messages not found in API history
  • ✅ Complete message history clearing
  • ✅ UI state updates after deletion
  • ✅ Message editing with and without API history

Impact

This fix ensures:

  • Chat message edits correctly replace the original message without duplication
  • Message deletion works reliably without errors
  • The UI properly reflects changes after deletion
  • Better error handling through the fallback mechanism

Important

Fixes chat message edit/delete duplication issues by implementing timestamp-based fallback logic and enhancing UI updates.

  • Behavior:
    • Fixes duplication in chat message edits by replacing original messages instead of duplicating them.
    • Resolves message deletion errors by ensuring proper handling when apiConversationHistoryIndex is -1.
    • Adds UI refresh after message deletion to reflect changes.
  • Implementation:
    • Adds timestamp-based fallback logic in webviewMessageHandler.ts and ClineProvider.ts for edit/delete operations.
    • Updates webviewMessageHandler.ts to handle cases where messages are not found in API history.
  • Testing:
    • Adds comprehensive test coverage for edit and delete operations in webviewMessageHandler.edit.spec.ts and webviewMessageHandler.delete.spec.ts.
  • Localization:
    • Updates error messages in multiple language files to improve clarity and consistency.

This description was created by Ellipsis for 890ed27. You can customize this summary. It will automatically update as commits are pushed.

- Implement timestamp-based fallback for API history truncation
- Fix message duplication when editing chat messages
- Fix 'Couldn't find timestamp' error when deleting messages
- Add UI state refresh after message deletion
- Add comprehensive test coverage for delete functionality
- Add detailed logging for debugging message operations

Fixes issues where edited messages appeared twice in exported history
and deletion operations failed with timestamp errors.
- Remove all console.log statements added for debugging
- Remove CHAT_MESSAGE_FIX_SUMMARY.md working document
- Keep core fix logic for timestamp-based fallback
- Keep UI update after deletion
- Keep comprehensive test coverage

All tests passing after cleanup
@daniel-lxs daniel-lxs moved this from Triage to PR [Needs Prelim Review] in Roo Code Roadmap Sep 8, 2025
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. bug Something isn't working labels Sep 8, 2025
// Edit this message and delete subsequent
await removeMessagesThisAndSubsequent(currentCline, messageIndex, apiConversationHistoryIndex)
// If apiConversationHistoryIndex is -1, use timestamp-based fallback
let effectiveApiIndex = apiConversationHistoryIndex
Copy link

Choose a reason for hiding this comment

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

The fallback logic in handleEditMessageConfirm (lines 347-357) duplicates similar logic in removeMessagesThisAndSubsequent; consider refactoring to avoid duplication.

Copy link

@roomote roomote bot left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution! I've reviewed the changes and found that this is a solid fix for the chat message edit/delete duplication issues. The timestamp-based fallback logic is a clever solution for handling missing API history entries. The code is well-tested and focused on the specific problem. I have some suggestions for improvement below.


if (apiConversationHistoryIndex !== -1) {
// If apiConversationHistoryIndex is -1, use timestamp-based fallback
let effectiveApiIndex = apiConversationHistoryIndex
Copy link

Choose a reason for hiding this comment

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

I notice the timestamp-based fallback logic is duplicated here and at lines 347-358 (edit operation) and in ClineProvider.ts:920-931. Could we extract this into a shared utility function to improve maintainability?

}
}

if (effectiveApiIndex !== -1) {
Copy link

Choose a reason for hiding this comment

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

When no API messages match the timestamp criteria (fallbackIndex remains -1), we don't call overwriteApiConversationHistory. Is this intentional? It might be worth adding a comment explaining why we skip the API history update in this case for future maintainers.

})

// Update the UI to reflect the deletion
await provider.postStateToWebview()
Copy link

Choose a reason for hiding this comment

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

Good addition of UI state refresh after deletion! Should we also add await provider.postStateToWebview() after successful edit operations (around line 383) for consistency?

if (message.messageTs) {
await handleDeleteMessageConfirm(message.messageTs, message.restoreCheckpoint)
if (!message.messageTs) {
await vscode.window.showErrorMessage("Cannot delete message: missing timestamp")
Copy link

Choose a reason for hiding this comment

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

Could we make this error message more descriptive? For example: 'Cannot delete message with timestamp ${message.messageTs}: timestamp is missing'

Copy link
Collaborator

Choose a reason for hiding this comment

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

And translate pls

expect(mockCurrentTask.overwriteClineMessages).toHaveBeenCalledWith([])

// API history should not be truncated when fallback finds no matching messages
// The effectiveApiIndex remains -1
Copy link

Choose a reason for hiding this comment

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

Excellent test coverage! Consider adding a test case for when the timestamp fallback logic fails to find any matching messages in the API history (when all API messages have timestamps < target timestamp). This would ensure the edge case is properly handled.

- Truncate from preceding user_feedback message
- Remove timestamp fallback logic
- Update tests to match new behavior
@daniel-lxs daniel-lxs moved this from PR [Needs Prelim Review] to PR [Needs Review] in Roo Code Roadmap Sep 9, 2025
The tests were expecting handleWebviewAskResponse to be called, but PR #7793
changed the implementation to use submitUserMessage instead to fix chat message
edit/delete duplication issues. This commit updates the tests to match the new
implementation.
console.log("[webviewMessageHandler] Message not found! Looking for ts:", messageTs)
}
if (!currentCline) {
await vscode.window.showErrorMessage("No active task to delete messages from")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Mind translating this?

}

if (typeof message.messageTs !== "number") {
await vscode.window.showErrorMessage("Cannot delete message: invalid timestamp")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here too

- Added translation keys for all error messages in message edit/delete operations
- Updated webviewMessageHandler.ts to use t() function for all error messages
- Added translations to all 17 supported languages for the new keys:
  - message.no_active_task_to_delete
  - message.invalid_timestamp_for_deletion
  - message.cannot_delete_missing_timestamp
  - message.cannot_delete_invalid_timestamp
  - message.message_not_found
  - message.error_deleting_message
  - message.error_editing_message

This addresses review feedback from mrubens about hardcoded English strings.
The test was expecting the actual translated message but since t() is mocked
to return the key, it should expect the translation key instead.
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Sep 9, 2025
@mrubens mrubens merged commit 88b5d66 into main Sep 9, 2025
9 checks passed
@mrubens mrubens deleted the fix/chat-message-edit-delete-duplication branch September 9, 2025 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer PR - Needs Review size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants