-
Notifications
You must be signed in to change notification settings - Fork 516
Add drag-and-drop from preview directory to WaveAI panel #2502
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
Conversation
|
|
- Import useDrop from react-dnd - Add RpcApi and TabRpcClient imports for file reading - Implement handleFileItemDrop to convert DraggedFile to File object - Add useDrop hook to accept FILE_ITEM drops - Update isDragOver state for FILE_ITEM drags - Handle file reading via RPC API and base64 decoding - Validate file types and sizes before adding to AI panel Co-authored-by: sawka <[email protected]>
Simplify the drag over state logic to properly clear when neither FILE_ITEM nor native files are being dragged. Co-authored-by: sawka <[email protected]>
- Improve error handling with instanceof Error check - Simplify drag state logic by removing mock object usage - Add clearer comments for drag state handling Co-authored-by: sawka <[email protected]>
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the WalkthroughThis pull request adds React Drag-and-Drop (React DnD) support to an AI panel component for handling remote file uploads. The changes introduce a new file size validation utility in Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–75 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/app/aipanel/ai-utils.ts(2 hunks)frontend/app/aipanel/aipanel.tsx(7 hunks)frontend/app/aipanel/waveai-model.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
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.
📚 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/aipanel.tsxfrontend/app/aipanel/ai-utils.tsfrontend/app/aipanel/waveai-model.tsx
| const handleFileItemDrop = useCallback( | ||
| (draggedFile: DraggedFile) => model.addFileFromRemoteUri(draggedFile), | ||
| [model] | ||
| ); | ||
|
|
||
| const [{ isOver, canDrop }, drop] = useDrop( | ||
| () => ({ | ||
| accept: "FILE_ITEM", | ||
| drop: handleFileItemDrop, | ||
| collect: (monitor) => ({ | ||
| isOver: monitor.isOver(), | ||
| canDrop: monitor.canDrop(), | ||
| }), | ||
| }), | ||
| [handleFileItemDrop] | ||
| ); | ||
|
|
||
| // Update drag over state for FILE_ITEM drags |
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.
Bring DraggedFile into scope for the drop handler.
handleFileItemDrop and the useDrop spec type this argument as DraggedFile, but the type isn’t imported anywhere in this file. TypeScript will fail with “Cannot find name 'DraggedFile'” until you add the appropriate import from the preview drag-and-drop module.
🤖 Prompt for AI Agents
In frontend/app/aipanel/aipanel.tsx around lines 408 to 425, the drop handler
and useDrop callback reference the DraggedFile type but it’s not imported; add
an import for DraggedFile from the preview drag-and-drop module at the top of
the file (e.g. import { DraggedFile } from
'<your-preview-drag-and-drop-module>') so the type is in scope, then rebuild to
ensure TypeScript errors are resolved.
| async addFileFromRemoteUri(draggedFile: DraggedFile): Promise<void> { | ||
| if (draggedFile.isDir) { | ||
| this.setError("Cannot add directories to Wave AI. Please select a file."); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| const fileInfo = await RpcApi.FileInfoCommand(TabRpcClient, { info: { path: draggedFile.uri } }, null); | ||
| if (fileInfo.notfound) { | ||
| this.setError(`File not found: ${draggedFile.relName}`); | ||
| return; | ||
| } | ||
| if (fileInfo.isdir) { | ||
| this.setError("Cannot add directories to Wave AI. Please select a file."); | ||
| return; | ||
| } | ||
|
|
||
| const mimeType = fileInfo.mimetype || "application/octet-stream"; | ||
| const fileSize = fileInfo.size || 0; | ||
| const sizeError = validateFileSizeFromInfo(draggedFile.relName, fileSize, mimeType); | ||
| if (sizeError) { | ||
| this.setError(formatFileSizeError(sizeError)); | ||
| return; | ||
| } | ||
|
|
||
| const fileData = await RpcApi.FileReadCommand(TabRpcClient, { info: { path: draggedFile.uri } }, null); | ||
| if (!fileData.data64) { | ||
| this.setError(`Failed to read file: ${draggedFile.relName}`); | ||
| return; | ||
| } | ||
|
|
||
| const buffer = base64ToArrayBuffer(fileData.data64); | ||
| const file = new File([buffer], draggedFile.relName, { type: mimeType }); | ||
| if (!isAcceptableFile(file)) { | ||
| this.setError( | ||
| `File type not supported: ${draggedFile.relName}. Supported: images, PDFs, and text/code files.` | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| await this.addFile(file); | ||
| } catch (error) { | ||
| console.error("Error handling FILE_ITEM drop:", error); | ||
| const errorMsg = error instanceof Error ? error.message : String(error); | ||
| this.setError(`Failed to add file: ${errorMsg}`); | ||
| } |
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.
Import DraggedFile to avoid a TS build break.
DraggedFile is referenced here but never brought into scope, so TypeScript will raise “Cannot find name 'DraggedFile'” and block the build. Please import the DraggedFile type from the preview drag-and-drop module before using it in addFileFromRemoteUri.
🤖 Prompt for AI Agents
In frontend/app/aipanel/waveai-model.tsx around lines 163 to 208, the function
addFileFromRemoteUri references the DraggedFile type but it is not imported,
causing a TypeScript “Cannot find name 'DraggedFile'” build error; add an import
for DraggedFile from the preview drag-and-drop module (using a type-only import
if desired) at the top of the file so the type is in scope, and run the
TypeScript build to verify the error is resolved.
Enables dragging files from preview directory listings directly into the WaveAI panel for analysis.
Changes
Modified
frontend/app/aipanel/aipanel.tsx:useDrophook to acceptFILE_ITEMdrag type from preview directoryhandleFileItemDropto:RpcApi.FileReadCommandusing the remote URIFileobject with proper MIME typemodel.addFile()flowImplementation
No changes required to preview directory—it already exports
FILE_ITEMdrag items. Works independently from native file system drag-and-drop.Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.