Skip to content

feat(ui): add video clipboard paste support#1325

Open
yumesha wants to merge 1 commit intoMoonshotAI:mainfrom
yumesha:pr/video-clipboard-paste
Open

feat(ui): add video clipboard paste support#1325
yumesha wants to merge 1 commit intoMoonshotAI:mainfrom
yumesha:pr/video-clipboard-paste

Conversation

@yumesha
Copy link
Copy Markdown

@yumesha yumesha commented Mar 3, 2026

Summary

Add video clipboard paste support (Ctrl-V) in shell mode and automatic video file detection in print mode.

Changes

  • Support all major video formats: MP4, MKV, AVI, MOV, WMV, WebM, M4V, FLV, 3GP, 3G2
  • Shell mode: Paste video files from clipboard with Ctrl-V
  • Print mode: Automatic video file detection for non-interactive usage
  • Updated documentation for video input capabilities

Testing

  1. Copy a video file path to clipboard
  2. Run kimi and press Ctrl-V
  3. Verify video is attached to the conversation

Open with Devin

- 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
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment on lines +50 to +64
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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 _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 match

Each 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.

Suggested change
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
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 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):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

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.

1 participant