feat: support pasting video files from clipboard via Ctrl-V#1369
Conversation
… crash when clipboard data is `None`
There was a problem hiding this comment.
Pull request overview
This PR extends the Ctrl-V clipboard paste handler to support video files in addition to images. grab_image_from_clipboard() is replaced with grab_media_from_clipboard(), which returns a typed ClipboardImage | ClipboardVideo | None. Video files are detected by extension, with video taking priority over images in multi-file clipboard payloads. On macOS, the native pasteboard API is tried first (avoiding misidentification via video thumbnails). The toolbar tip is updated from "paste image" to "paste media", and a crash when clipboard_data is None in the fallback paste path is fixed.
Changes:
clipboard.py: IntroducesClipboardImage/ClipboardVideodataclasses,_VIDEO_SUFFIXES, renames and restructures the clipboard-reading function, and extracts_classify_file_paths().prompt.py: Renames_try_paste_image→_try_paste_media, adds video path insertion logic (with shell-quoting), fixes theNoneclipboard_data crash, and updates the toolbar tip.- Tests: Adds
tests/test_clipboard.pyfor_classify_file_pathsclassification andtests/ui_and_conv/test_prompt_clipboard.pyfor the video-paste prompt behavior; updates the toolbar tip assertion.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/kimi_cli/utils/clipboard.py |
Core change: new typed result classes, video suffix set, updated grab_media_from_clipboard with macOS-priority path, and _classify_file_paths helper |
src/kimi_cli/ui/shell/prompt.py |
Renames handler to _try_paste_media, adds video path insertion with shell-quoting, fixes None clipboard crash, updates toolbar tip |
tests/test_clipboard.py |
New tests for _classify_file_paths covering all video suffixes, image files, priority ordering, and edge cases |
tests/ui_and_conv/test_prompt_clipboard.py |
New tests for _try_paste_media covering video path shell-quoting and agent-mode behavior |
tests/ui_and_conv/test_prompt_tips.py |
Updates toolbar tip assertion to match "paste media" |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if isinstance(media, ClipboardVideo): | ||
| logger.debug("Pasted video from clipboard: {path}", path=media.path) | ||
| video_text = str(media.path) | ||
| if self._mode == PromptMode.SHELL: | ||
| video_text = shlex.quote(video_text) | ||
| event.current_buffer.insert_text(video_text) | ||
| event.app.invalidate() | ||
| return True |
There was a problem hiding this comment.
When a video is detected from the clipboard in AGENT mode, the path is inserted into the buffer without checking whether video_in is in self._model_capabilities. By contrast, the image branch already checks image_in and shows a warning to the user when the model doesn't support image input (line 869–871). A user pasting a video with a model that lacks video_in capability will silently get a path inserted into their prompt with no feedback, which is inconsistent and likely to cause confusion.
The video branch should check "video_in" not in self._model_capabilities and print a similar warning (e.g., "Video input is not supported by the selected LLM model") before returning True, mirroring the image-capability guard.
| # Note: if a video file was copied, the native path above would have | ||
| # already caught it. Reaching here means no video file was found. |
There was a problem hiding this comment.
The inline comment "Note: if a video file was copied, the native path above would have already caught it. Reaching here means no video file was found." is inaccurate. The macOS native path lookup in step 1 returns None and falls through whenever any call to _classify_file_paths returns None — this includes the case where a non-video, non-image file (e.g. a .pdf or .dmg) was copied. In that scenario, the clipboard paths did exist but no video was in them; ImageGrab.grabclipboard() might then still return an image object (for example, the macOS-generated thumbnail of a copied document). The comment's reasoning is therefore only correct when there were no file paths at all in the native clipboard. Consider revising the comment to reflect this more precisely, for example: "If we reach here, the native path lookup did not identify a video or image file path (either no file paths were present, or none were media files)."
| # Note: if a video file was copied, the native path above would have | |
| # already caught it. Reaching here means no video file was found. | |
| # Note: if we reach here, the macOS native path lookup did not identify | |
| # a video or image file path (either no file paths were present, or none | |
| # were recognized as media files). |
… improve paste functionality
Extends Ctrl-V clipboard paste to handle video files in addition to images.
grab_media_from_clipboard()replacesgrab_image_from_clipboard(), returning a typedClipboardImage | ClipboardVideo | Noneclipboard_dataisNoneafter a non-media paste attemptChecklist
make gen-changelogto update the changelog.make gen-docsto update the user documentation.