ACP input: @ git file mentions and clipboard image paste - #61
Conversation
Typing @ in the ACP input opens a git file picker; Return inserts an @path mention that is sent as an ACP ResourceLink (or Image block for image files). Ctrl+Shift+V pastes clipboard images as Image content blocks with base64 payload and MIME type, matching Zed/ACP prompt context. Co-authored-by: samwdp <samwdp@gmail.com>
|
Cursor Agent can help with this pull request. Just |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9c8d9c71a
ℹ️ 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".
| .map_err(|_| "acp manager lock was poisoned".to_owned())?; | ||
| manager.session_for_buffer(buffer_id) | ||
| }; | ||
| let workspace_root = active_workspace_root(runtime)?.or_else(|| git_root(runtime).ok()); |
There was a problem hiding this comment.
Resolve mentions against the same root used by the picker
When a workspace is a subdirectory of a Git repository, the picker lists --full-name paths relative to the repository root, but submission prefers the workspace root here. For example, selecting pkg/src/lib.rs from a workspace rooted at /repo/pkg produces a link to /repo/pkg/pkg/src/lib.rs, so every selected mention can reference the wrong or nonexistent file. Preserve and use the picker’s Git root, or use the same root-selection order in both paths.
Useful? React with 👍 / 👎.
| let replacement = format!("@{relative_path} "); | ||
| input.replace_char_range(mention.at_char, mention.end_char, &replacement); |
There was a problem hiding this comment.
Encode file mentions containing whitespace
When the selected Git filename contains a space, this inserts an unquoted token such as @docs/user guide.md . The mention parser stops at the first whitespace, so submission creates a resource link for only docs/user and leaves guide.md as ordinary text. Use an escaping or structured representation that preserves the complete picker path.
Useful? React with 👍 / 👎.
| fn paste_into_active_input_buffer(runtime: &mut EditorRuntime) -> Result<bool, String> { | ||
| match read_system_clipboard_paste() { | ||
| ClipboardPaste::Empty => Ok(false), | ||
| ClipboardPaste::Text(text) => paste_text_into_active_input_buffer(runtime, &text), | ||
| ClipboardPaste::Image(image) => paste_image_into_active_input_buffer(runtime, image), | ||
| } |
There was a problem hiding this comment.
Preserve text paste fallback outside ACP inputs
When a non-ACP input is active and the clipboard advertises image data alongside text, or its text is an existing image path, read_system_clipboard_paste returns Image and this branch delegates to an ACP-only handler that returns false. The shortcut is still consumed, so browser and other prompt inputs no longer paste the text they accepted before this change. Only prefer images for ACP buffers, or fall back to the clipboard text when image insertion is unsupported.
Useful? React with 👍 / 👎.
| let mime_type = match mime_type { | ||
| Some(mime) => mime, | ||
| None => { | ||
| image::load_from_memory(&bytes).ok()?; | ||
| "image/png".to_owned() | ||
| } |
There was a problem hiding this comment.
Convert decoded images before labeling them as PNG
When loading a TIFF file through an @ mention, MIME sniffing returns nothing but image::load_from_memory succeeds, after which the original TIFF bytes are retained while being labeled image/png. The resulting ACP image block therefore contains data that does not match its MIME type and clients decoding it as PNG will reject it. Either infer the actual format or re-encode the decoded image to PNG before returning this MIME type.
Useful? React with 👍 / 👎.
Summary
Extends the ACP prompt input with two context attachments, composed into real ACP
ContentBlocks on submit (not just extra text in the message).1.
@git file pickerTyping
@in the ACP input opens a picker of git files (git ls-files --cached --others --exclude-standard), matching the workspace file picker. Return replaces the@querytoken with@relative/path.On submit, each
@pathmention becomes:ContentBlock::ResourceLinkwith afile://URI (ACP baseline; every agent must support this)ContentBlock::Imagewhen the mentioned file is itself an image, with base64 data + MIME type + file URI (same as Zed when attaching an image file)Emails like
user@host.comdo not trigger the picker;@must start a token.2. Clipboard image paste
Ctrl+Shift+Vin the ACP input prefers image clipboard data over text, following Zed / ACP:image/png,image/jpeg,image/webp, …)text/uri-list/ a copied image file path (file-manager copy)in the input and store the payload on the bufferOn submit that token becomes:
{ "type": "image", "mimeType": "image/png", "data": "<base64>", "uri": "volt://agent/pasted-image?name=Image" }This matches the ACP image content block and Zed’s pasted-image mention (
uri+ base64 + MIME), so vision-capable agents receive the pixels in-context rather than a path string.Raw clipboard screenshots are labeled
Image; copies of named files keep the filename.Test plan
cargo test -p editor-sdl --libfor the new unit/integration tests:@opens the git file picker and Return inserts@src/main.rsplus stored base64