Module: Rubino::Interaction::ClipboardImage
- Defined in:
- lib/rubino/interaction/clipboard_image.rb
Overview
Grabs an image from the system clipboard and writes it to a temp PNG so it can be attached to a turn’s image_paths (the native vision slot). Mirrors Claude Code’s Cmd+V image paste from the terminal.
Platform tools, best-effort and in priority order:
- macOS : `pngpaste` (brew install pngpaste)
- Wayland: `wl-paste` (wl-clipboard)
- X11 : `xclip`
Returns the temp file path on success, or nil when no tool is available or the clipboard holds no image. #unavailable_reason explains a nil so the CLI can show an actionable hint instead of a silent no-op.
Class Method Summary collapse
-
.capture(dest) ⇒ Object
Runs the first available tool.
-
.commands(dest) ⇒ Object
Ordered [tool, argv-builder] candidates.
-
.save_to_tempfile ⇒ Object
Saves the clipboard image to a temp PNG and returns its path, or nil.
-
.unavailable_reason ⇒ Object
Human-readable reason a paste produced nothing, for the CLI hint.
- .which(tool) ⇒ Object
Class Method Details
.capture(dest) ⇒ Object
Runs the first available tool. macOS pngpaste writes the file directly; the Linux tools write PNG bytes to stdout which we redirect to dest.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rubino/interaction/clipboard_image.rb', line 47 def capture(dest) commands(dest).each do |tool, args| next unless which(tool) if tool == "pngpaste" _out, = Open3.capture2e(tool, *args) else out, status = Open3.capture2(tool, *args) File.binwrite(dest, out) if status.success? && !out.empty? end return true if File.file?(dest) && File.size(dest).positive? end false rescue StandardError false end |
.commands(dest) ⇒ Object
Ordered [tool, argv-builder] candidates. The builder takes the dest path and returns the argv that writes a PNG of the clipboard image to it.
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/rubino/interaction/clipboard_image.rb', line 25 def commands(dest) case RbConfig::CONFIG["host_os"] when /darwin/ [["pngpaste", [dest]]] when /linux/ [ ["wl-paste", ["-t", "image/png", "--no-newline"]], # writes to stdout ["xclip", ["-selection", "clipboard", "-t", "image/png", "-o"]] ] else [] end end |
.save_to_tempfile ⇒ Object
Saves the clipboard image to a temp PNG and returns its path, or nil.
40 41 42 43 |
# File 'lib/rubino/interaction/clipboard_image.rb', line 40 def save_to_tempfile dest = File.join(Dir.tmpdir, "rubino_clip_#{Process.pid}_#{rand(1_000_000)}.png") capture(dest) ? dest : nil end |
.unavailable_reason ⇒ Object
Human-readable reason a paste produced nothing, for the CLI hint.
65 66 67 68 69 70 71 72 73 74 |
# File 'lib/rubino/interaction/clipboard_image.rb', line 65 def unavailable_reason case RbConfig::CONFIG["host_os"] when /darwin/ "no image on the clipboard, or `pngpaste` isn't installed (brew install pngpaste)." when /linux/ "no image on the clipboard, or neither `wl-paste` nor `xclip` is installed." else "clipboard image paste isn't supported on this platform." end end |
.which(tool) ⇒ Object
76 77 78 79 80 81 |
# File 'lib/rubino/interaction/clipboard_image.rb', line 76 def which(tool) ENV["PATH"].to_s.split(File::PATH_SEPARATOR).any? do |dir| path = File.join(dir, tool) File.executable?(path) && !File.directory?(path) end end |