Skip to content

Conversation

@Mostafa-Khairy0
Copy link
Contributor

This feature adds support for pasting images directly into the Wave AI input panel.

When a user copies an image (e.g., from their clipboard or a screenshot) and pastes it into the input area, the image is automatically:

  • Detected from the clipboard (image/* MIME type)
  • Converted into a File object with a unique timestamp-based filename
  • Validated for file type and size
  • Added to the AI model via model.addFile()

This update improves the user experience by removing the need to manually upload images enabling faster and smoother AI-assisted workflows.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 2, 2025

Walkthrough

This change refactors a frontend component to centralize file validation/upload via a new processFile(file) function, consolidates type and size checks, and adds paste-to-image support with handlePaste that converts clipboard images to File objects and processes them. handleFileChange now iterates over selected files, delegates to processFile, and clears the input afterward. handleUploadClick was shortened to a single invocation of the file input. Focus/blur logic was simplified and an inline focus method exposed on the input ref; handleFocus now calls model.requestWaveAIFocus() and handleBlur delegates to model.requestNodeFocus() when appropriate. Textarea receives an onPaste handler and textarea resizing is triggered in a useEffect on input and when the panel open state changes. No exported/public signatures were changed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Verify processFile enforces allowed types and sizes, and that model.setError messages are appropriate for UI display
  • Confirm handlePaste extracts image items from the clipboard consistently across browsers, infers extensions correctly, and constructs valid File objects
  • Check focus/blur simplifications for regressions around requestWaveAIFocus() and focus retention when relatedTarget remains inside the panel
  • Validate textarea resize useEffect dependencies and that resizeTextarea runs when input changes and when isPanelOpen toggles
  • Ensure clearing the file input in handleFileChange and the one-line handleUploadClick work for multiple-file selections across target browsers

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "[Feature]: Paste Image Support in Wave AI Panel" directly and clearly reflects the main objective of the changeset. The raw summary confirms that the primary change involves "Expanded clipboard support" with a new handlePaste function to capture and process image data from the clipboard. The title is concise, specific, and accurately represents the feature being introduced without vague terminology or noise. It aligns perfectly with the PR objectives which state the core purpose is to add support for pasting images directly into the Wave AI input panel.
Description Check ✅ Passed The pull request description is directly related to the changeset and provides meaningful information about the feature being implemented. It accurately describes the paste image functionality, including how images are detected from the clipboard, converted to File objects with timestamped filenames, validated for type and size, and added to the AI model. The description aligns with the raw summary which documents the "Expanded clipboard support" and new handlePaste function, and it clearly communicates the user experience benefit of removing the need for manual image uploads.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f75c7a and ab13a7e.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelinput.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/app/aipanel/aipanelinput.tsx

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7d76d3 and 60451d8.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelinput.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-14T06:30:54.763Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2430
File: frontend/app/aipanel/aimessage.tsx:137-144
Timestamp: 2025-10-14T06:30:54.763Z
Learning: In `frontend/app/aipanel/aimessage.tsx`, the `AIToolUseGroup` component splits file operation tool calls into separate batches (`fileOpsNeedApproval` and `fileOpsNoApproval`) based on their approval state before passing them to `AIToolUseBatch`. This ensures each batch has homogeneous approval states, making group-level approval handling valid.

Applied to files:

  • frontend/app/aipanel/aipanelinput.tsx
🧬 Code graph analysis (1)
frontend/app/aipanel/aipanelinput.tsx (2)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasFocusWithin (15-42)
frontend/app/aipanel/ai-utils.ts (3)
  • isAcceptableFile (11-199)
  • validateFileSize (308-339)
  • formatFileSizeError (372-375)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60451d8 and 67f27ee.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelinput.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-14T06:30:54.763Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2430
File: frontend/app/aipanel/aimessage.tsx:137-144
Timestamp: 2025-10-14T06:30:54.763Z
Learning: In `frontend/app/aipanel/aimessage.tsx`, the `AIToolUseGroup` component splits file operation tool calls into separate batches (`fileOpsNeedApproval` and `fileOpsNoApproval`) based on their approval state before passing them to `AIToolUseBatch`. This ensures each batch has homogeneous approval states, making group-level approval handling valid.

Applied to files:

  • frontend/app/aipanel/aipanelinput.tsx
🧬 Code graph analysis (1)
frontend/app/aipanel/aipanelinput.tsx (2)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasFocusWithin (15-42)
frontend/app/aipanel/ai-utils.ts (3)
  • isAcceptableFile (11-199)
  • validateFileSize (308-339)
  • formatFileSizeError (372-375)
🔇 Additional comments (6)
frontend/app/aipanel/aipanelinput.tsx (6)

41-41: LGTM!

Inlining the focus handler simplifies the code while maintaining the same functionality.


56-65: LGTM!

The focus and blur handlers are correctly refactored with proper early returns and dependencies.


67-70: LGTM!

The textarea resize behavior is correctly triggered on input changes and when the panel opens.


72-72: LGTM!

Simplifying the upload click handler to a one-liner improves code clarity.


92-99: LGTM!

The refactored handleFileChange correctly processes each file through the centralized processFile helper and clears the input afterwards. Sequential processing is acceptable for file uploads to maintain order and avoid overwhelming the system.


136-136: LGTM!

The onPaste handler is correctly wired to enable image paste functionality.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/app/aipanel/aipanelinput.tsx (1)

121-121: Consider adding randomness or UUID for guaranteed filename uniqueness.

While Date.now() combined with sequential await processing makes collisions extremely unlikely, adding a random component or using a UUID would eliminate even the theoretical possibility of duplicate filenames.

For example:

const filename = `pasted-image-${Date.now()}-${Math.random().toString(36).substr(2, 9)}.${ext}`;

or use a UUID library if available:

const filename = `pasted-image-${crypto.randomUUID()}.${ext}`;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67f27ee and 7f75c7a.

📒 Files selected for processing (1)
  • frontend/app/aipanel/aipanelinput.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-14T06:30:54.763Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2430
File: frontend/app/aipanel/aimessage.tsx:137-144
Timestamp: 2025-10-14T06:30:54.763Z
Learning: In `frontend/app/aipanel/aimessage.tsx`, the `AIToolUseGroup` component splits file operation tool calls into separate batches (`fileOpsNeedApproval` and `fileOpsNoApproval`) based on their approval state before passing them to `AIToolUseBatch`. This ensures each batch has homogeneous approval states, making group-level approval handling valid.

Applied to files:

  • frontend/app/aipanel/aipanelinput.tsx
🧬 Code graph analysis (1)
frontend/app/aipanel/aipanelinput.tsx (2)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasFocusWithin (15-42)
frontend/app/aipanel/ai-utils.ts (3)
  • isAcceptableFile (11-199)
  • validateFileSize (308-339)
  • formatFileSizeError (372-375)
🔇 Additional comments (2)
frontend/app/aipanel/aipanelinput.tsx (2)

74-95: LGTM! Robust file processing with proper validation and error handling.

The processFile function effectively centralizes file validation, size checking, and upload logic. The try-catch around model.addFile() ensures that upload failures are gracefully handled with clear user feedback. The memoization with [model] correctly prevents stale closures.


97-104: LGTM! File change handler properly integrated.

The sequential file processing ensures predictable behavior, and clearing the input value allows users to re-select the same file if needed.

@sawka
Copy link
Member

sawka commented Nov 3, 2025

ah this looks like a good change, but the formatting differences make it a little harder to make sure there are no regressions. will try to review and make sure.

@Mostafa-Khairy0
Copy link
Contributor Author

Appreciate the feedback! I can revert or isolate the formatting changes to make the review easier. Would you prefer I do that?

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.

2 participants