feat(ui): add video clipboard paste support#1325
feat(ui): add video clipboard paste support#1325yumesha wants to merge 1 commit intoMoonshotAI:mainfrom
Conversation
- Add ClipboardVideo class and grab_video_from_clipboard() in clipboard.py - Add video support to AttachmentCache with store_video_reference() - Add _try_paste_video() method in prompt.py for Ctrl-V handling - Add _extract_video_paths() and _build_content_parts() in print/__init__.py - Export VIDEO_EXTENSIONS constant from file utils - Update documentation for video clipboard paste - Add tests for video attachment handling
| for start_candidate in range(0, ext_end): | ||
| # Must start at word boundary or with @ or / | ||
| if start_candidate > 0 and text[start_candidate - 1] not in " \t\n": | ||
| continue | ||
|
|
||
| path_str = text[start_candidate:ext_end] | ||
|
|
||
| # Remove @ prefix for validation | ||
| check_path_str = path_str[1:] if path_str.startswith("@") else path_str | ||
| path = Path(check_path_str) | ||
|
|
||
| # Check if this is a valid video file | ||
| if path.suffix.lower() in VIDEO_EXTENSIONS and path.is_file(): | ||
| # Found a valid file - update best match (preferring longer paths) | ||
| best_match = (start_candidate, path) |
There was a problem hiding this comment.
🟡 _extract_video_paths selects shortest valid path instead of longest
The loop in _extract_video_paths iterates start_candidate from 0 (longest candidate) to ext_end (shortest candidate), overwriting best_match on every valid hit. Because the last assignment wins, the function returns the shortest valid path, contradicting the stated intent to prefer longer paths.
Root Cause
The loop at src/kimi_cli/ui/print/__init__.py:50-64 iterates forward:
for start_candidate in range(0, ext_end):
...
if path.suffix.lower() in VIDEO_EXTENSIONS and path.is_file():
best_match = (start_candidate, path) # overwrites previous longer matchEach valid match overwrites the previous one. Since start_candidate increases, later matches correspond to shorter path strings. The final best_match is the shortest valid path, not the longest.
For example, given the command "Check /data/my clips/intro.mp4" where both /data/my clips/intro.mp4 (path with space) and clips/intro.mp4 (relative) exist as files, the algorithm would first find the longer path (correct), then overwrite it with the shorter clips/intro.mp4 (incorrect).
Impact: When multiple substrings ending at the same video extension resolve to existing files, the wrong (shorter) path is selected and the original text is incorrectly sliced, losing part of the user's command text or referencing the wrong file.
| for start_candidate in range(0, ext_end): | |
| # Must start at word boundary or with @ or / | |
| if start_candidate > 0 and text[start_candidate - 1] not in " \t\n": | |
| continue | |
| path_str = text[start_candidate:ext_end] | |
| # Remove @ prefix for validation | |
| check_path_str = path_str[1:] if path_str.startswith("@") else path_str | |
| path = Path(check_path_str) | |
| # Check if this is a valid video file | |
| if path.suffix.lower() in VIDEO_EXTENSIONS and path.is_file(): | |
| # Found a valid file - update best match (preferring longer paths) | |
| best_match = (start_candidate, path) | |
| for start_candidate in range(0, ext_end): | |
| # Must start at word boundary or with @ or / | |
| if start_candidate > 0 and text[start_candidate - 1] not in " \t\n": | |
| continue | |
| path_str = text[start_candidate:ext_end] | |
| # Remove @ prefix for validation | |
| check_path_str = path_str[1:] if path_str.startswith("@") else path_str | |
| path = Path(check_path_str) | |
| # Check if this is a valid video file | |
| if path.suffix.lower() in VIDEO_EXTENSIONS and path.is_file(): | |
| # Found a valid file - take the first (longest) match and stop | |
| best_match = (start_candidate, path) | |
| break |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de2bfcfd9b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| # Find all video extension occurrences (not using \b to avoid issues with [ or other chars) | ||
| # Match extensions followed by space, punctuation, or end of string | ||
| for match in re.finditer(rf"\.({video_exts})(?=\s|$|[.,;!?])", text, re.IGNORECASE): |
There was a problem hiding this comment.
Detect quoted video paths in print-mode parsing
_extract_video_paths only matches video extensions when the next character is whitespace, end-of-string, or [.,;!?], so quoted paths like "/tmp/my clip.mp4" or '/tmp/my clip.mp4' are never detected. This is a common way to include paths with spaces in --print -c input, and in that case the command is sent as plain text without <video ...> tags, so automatic video attachment handling is skipped.
Useful? React with 👍 / 👎.
Summary
Add video clipboard paste support (Ctrl-V) in shell mode and automatic video file detection in print mode.
Changes
Testing
kimiand press Ctrl-V