Skip to content

feat: allow editing messages in AI chat #6117

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

Merged
merged 12 commits into from
Jul 4, 2025

Conversation

claude[bot]
Copy link
Contributor

@claude claude bot commented Jul 2, 2025

Summary

  • Add edit button to user messages in AI chat interface
  • Transform message display into text input when editing
  • Remove subsequent messages and resend with edited content when Enter is pressed

Changes Made

AIChatManager.svelte.ts

  • Added editMessage() method that:
    • Updates the message content at the specified index
    • Removes all messages after the edited message (both display and actual messages)
    • Sends a new request with the edited content

AIChatDisplay.svelte

  • Added state management for editing (editingMessageIndex, editingMessageContent)
  • Added edit functionality functions (startEditMessage(), cancelEditMessage(), saveEditMessage())
  • Added EditIcon import for the edit button
  • Modified message display logic to show textarea when editing
  • Added edit button that appears on hover for all user messages
  • Added keyboard shortcuts: Enter to save/send, Escape to cancel
  • Added cancel/send buttons during edit mode
  • Maintained the existing "restart generation" button for the last user message

Implementation Details

  • Edit button appears on hover for all user messages (not just the last one)
  • When editing, the message transforms into a textarea with autosize
  • The original message content is preserved if editing is cancelled
  • When saving, all subsequent messages are removed and a new AI request is sent
  • UI follows existing patterns and styling conventions

Test Plan

  • ✅ Frontend validation (npm run check) passes
  • Manual testing needed:
    • Edit button appears on hover for user messages
    • Clicking edit transforms message to textarea
    • Enter key saves and sends new request
    • Escape key cancels editing
    • Subsequent messages are properly removed
    • AI responds to the edited message

Closes #6116

Generated with Claude Code

Co-authored-by: Ruben Fiszel [email protected]


Important

This PR adds functionality to edit user messages in the AI chat interface, including UI updates and message handling logic.

  • Behavior:
    • Add edit button to user messages in AI chat interface.
    • Transform message display into text input when editing.
    • Remove subsequent messages and resend with edited content when Enter is pressed.
  • Components:
    • AIChatManager.svelte.ts: Add editMessage() method to update message content, remove subsequent messages, and send new request.
    • AIChatDisplay.svelte: Add state management for editing and edit functionality functions. Modify message display logic to show textarea when editing.
    • AIChatInput.svelte: Handle input focus, context selection, and request sending during editing.
  • Misc:
    • Add AIChatMessage.svelte to handle individual message rendering and editing logic.
    • Update ContextTextarea.svelte to support context selection and input handling during editing.
    • Modify shared.ts to include error property in UserDisplayMessage.

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

- Add editMessage() method to AIChatManager for editing user messages
- Add edit button UI that appears on hover for all user messages  
- Transform message display into textarea when editing
- Remove subsequent messages and resend on Enter
- Add keyboard shortcuts: Enter to save, Escape to cancel
- Maintain existing restart generation functionality

Co-authored-by: Ruben Fiszel <[email protected]>
Copy link

cloudflare-workers-and-pages bot commented Jul 2, 2025

Deploying windmill with  Cloudflare Pages  Cloudflare Pages

Latest commit: 117ed4f
Status: ✅  Deploy successful!
Preview URL: https://ef9bb07e.windmill.pages.dev
Branch Preview URL: https://claude-issue-6116-20250702-1.windmill.pages.dev

View logs

@centdix centdix force-pushed the claude/issue-6116-20250702_124357 branch from e76ed63 to 3706c34 Compare July 3, 2025 13:42
@centdix centdix force-pushed the claude/issue-6116-20250702_124357 branch from 3706c34 to 2b5685c Compare July 3, 2025 14:25
@windmill-labs windmill-labs deleted a comment from github-actions bot Jul 3, 2025
@windmill-labs windmill-labs deleted a comment from github-actions bot Jul 3, 2025
@centdix centdix force-pushed the claude/issue-6116-20250702_124357 branch from d56c8c5 to 7ca4169 Compare July 3, 2025 15:00
@centdix centdix marked this pull request as ready for review July 3, 2025 16:55
@rubenfiszel
Copy link
Contributor

/ai review this PR

centdix and others added 2 commits July 3, 2025 19:00
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed b1d98fe in 1 minute and 33 seconds. Click for details.
  • Reviewed 181 lines of code in 3 files
  • Skipped 0 files when reviewing.
  • Skipped posting 4 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte:53
  • Draft comment:
    Shared editing state (editingMessageIndex) is set up clearly. Verify that allowing only one message to be edited at a time fits the intended UX.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. frontend/src/lib/components/copilot/chat/AIChatInput.svelte:44
  • Draft comment:
    The clickOutside directive correctly cancels edit mode via onEditEnd. Consider extracting this utility to a shared helper if it’s reused elsewhere.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. frontend/src/lib/components/copilot/chat/AIChatMessage.svelte:28
  • Draft comment:
    Consider renaming the function 'editMessage' to 'startEditMessage' for consistency with the PR description and clarity of purpose.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. frontend/src/lib/components/copilot/chat/AIChatMessage.svelte:42
  • Draft comment:
    For improved accessibility, add aria-labels or appropriate roles on the clickable message container that triggers editing.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.

Workflow ID: wflow_1QgkHoQ7ob5xJYQI

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@windmill-labs windmill-labs deleted a comment from claude bot Jul 3, 2025
@centdix
Copy link
Collaborator

centdix commented Jul 3, 2025

/ai review this PR

@windmill-labs windmill-labs deleted a comment from ellipsis-dev bot Jul 3, 2025
Copy link
Contributor Author

claude bot commented Jul 3, 2025

Claude finished @centdix's task —— View job


Code Review Complete ✅

I've thoroughly analyzed the AI chat message editing implementation. Overall, this is a well-structured feature with good component separation and proper use of Svelte 5 patterns. Here's my detailed assessment:

Strengths

Component Architecture

  • Excellent refactoring: Breaking down AIChatDisplay into focused components (AIChatInput, AIChatMessage) greatly improves maintainability
  • Clean separation of concerns: Each component has a single responsibility
  • Proper state management: Good use of Svelte 5 runes with $state, $bindable, and $effect

Implementation Quality

  • Solid editing logic: The restartGeneration method in AIChatManager.svelte.ts:520-542 correctly removes subsequent messages and resends
  • Good state synchronization: The index field in UserDisplayMessage properly links display and actual messages
  • Appropriate UX patterns: Click-to-edit, keyboard shortcuts (Enter/Escape), and proper focus management

⚠️ Areas for Improvement

1. Race Condition Handling

Issue: No protection against editing while AI is generating responses.

// In AIChatMessage.svelte:28-33
function editMessage() {
    if (message.role !== 'user' || editingMessageIndex !== null || aiChatManager.loading) {
        return // ✅ Good - already checks loading state
    }
}

Status: ✅ Already handled correctly

2. User Experience Concerns

Issue: No visual indication of what content will be removed when editing

Suggestion: Add a subtle warning or preview showing affected messages

3. Accessibility Improvements

Issue: Missing accessibility features in AIChatMessage.svelte:42-45

<div
    role="button"
    tabindex="0"
    onclick={() => editMessage()}
    onkeydown={() => {}} // ❌ Empty handler
>

Recommendations:

  • Implement proper onkeydown handler for Enter/Space keys
  • Add aria-label for screen readers
  • Consider aria-describedby for editing instructions

4. Error Handling

Issue: Limited error recovery in edge cases

  • What if restartGeneration fails to find the correct message index?
  • No fallback if display/actual message arrays become desynchronized

Current code in AIChatManager.svelte.ts:531-535:

let actualMessageIndex = this.messages.findIndex((_, i) => i === userMessage.index)
if (actualMessageIndex === -1) {
    throw new Error('No actual user message found to restart from') // ❌ Throws, no graceful handling
}

5. Performance Considerations

Minor: Multiple $effect calls could be optimized, but current implementation is acceptable for typical chat volumes.

🔍 Specific Code Issues

AIChatInput.svelte

  • Line 88-91: Effect for auto-focus is good, but consider debouncing if editing state changes rapidly
  • Line 46: clickOutside directive is well-implemented

AIChatMessage.svelte

  • Line 44: The onclick for the entire message div might conflict with text selection. Consider adding the edit button only on hover instead.

ContextTextarea.svelte

  • Line 302-304: Good addition of Escape key handling for edit mode

📋 Security Assessment

No security concerns identified

  • Proper input sanitization maintained
  • No XSS vulnerabilities introduced
  • State management is secure

🎯 Final Recommendation

APPROVE with minor suggestions

This is a solid implementation that successfully adds message editing functionality while maintaining code quality. The component refactoring is particularly well done and makes the codebase more maintainable.

Priority Fixes (Optional):

  1. Add proper keyboard event handling in AIChatMessage.svelte
  2. Consider UX improvements for showing affected messages during editing
  3. Add error boundaries for edge cases in message synchronization

Test Coverage Recommendations:

  • Test editing first message in conversation
  • Test editing while AI response is in progress
  • Test rapid edit/cancel cycles
  • Test keyboard navigation and accessibility
  • Test edge case where message indices become misaligned

The implementation follows Svelte 5 best practices and provides a clean, intuitive editing experience for users.


Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 117ed4f in 2 minutes and 9 seconds. Click for details.
  • Reviewed 36 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. frontend/src/lib/components/copilot/chat/AIChatManager.svelte.ts:219
  • Draft comment:
    retryRequest now requires a messageIndex and throws an error if no valid user message is found. Consider handling this case more gracefully rather than throwing an error, and ensure that all call sites pass a valid index.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% The comment addresses a real change in the code - the function now takes an index parameter and throws an error in invalid cases. However, throwing an error here is likely intentional and appropriate since: 1. This represents a programming error (invalid index passed) 2. The error message is clear and descriptive 3. The calling code should validate indices before calling this method 4. Graceful handling would mask bugs in the calling code Perhaps throwing an error is too harsh and could cause UI issues if not caught properly. Maybe returning false or undefined would be more idiomatic for a UI component. No, throwing an error is appropriate here because: 1. It clearly indicates a programming bug that should be fixed 2. The error has a descriptive message to help debugging 3. Silent failures would make bugs harder to track down The comment should be deleted. Throwing an error is appropriate for this programming error case and handling it "more gracefully" would actually make the code worse by masking bugs.
2. frontend/src/lib/components/copilot/chat/AIChatMessage.svelte:45
  • Draft comment:
    The onkeydown handler is empty. For better accessibility, implement key handling (e.g. Enter/Space to edit) or remove the handler to avoid confusion.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. frontend/src/lib/components/copilot/chat/AIChatMessage.svelte:28
  • Draft comment:
    The editMessage function is triggered by clicking the entire message container. Consider adding a dedicated edit icon/button to reduce accidental edits and clarify the action to users.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_jYEjb5FeGCvKpITg

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@HugoCasa HugoCasa merged commit c498c48 into main Jul 4, 2025
9 of 10 checks passed
@HugoCasa HugoCasa deleted the claude/issue-6116-20250702_124357 branch July 4, 2025 11:11
@github-actions github-actions bot locked and limited conversation to collaborators Jul 4, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: allow editing a message in the ai chat
3 participants