fix(web): reliable terminal copy with fallback, feedback, and shift-drag hint#2120
Open
Bdandc wants to merge 1 commit into
Open
fix(web): reliable terminal copy with fallback, feedback, and shift-drag hint#2120Bdandc wants to merge 1 commit into
Bdandc wants to merge 1 commit into
Conversation
…rag hint
Copy from the dashboard terminal silently no-oped on non-secure origins
(LAN IP instead of localhost) because every copy path ended in
navigator.clipboard.writeText(...).catch(() => {}), and agent TUIs that
enable mouse reporting made drag-selection appear broken with no
explanation.
- Add writeClipboardText() helper: navigator.clipboard.writeText →
document.execCommand('copy') via a temporary sr-only textarea →
surfaced failure. Used by both terminal copy paths (OSC 52 handler
and Cmd+C / Ctrl+Shift+C).
- registerClipboardHandlers now reports every copy outcome via an
onCopyResult callback; DirectTerminal flashes a transient
'Copied' / 'Copy failed' pill over the terminal (design tokens,
Tailwind only).
- Detect active mouse reporting via terminal.modes.mouseTrackingMode
after parsed writes and show a subtle '⇧+drag to select' hint in
TerminalControls (chrome bar and chromeless overlay) while active.
- Tests: execCommand fallback matrix (clipboard present/absent/
rejected, execCommand ok/false/throw/missing), onCopyResult
reporting, toast show/dismiss/reset, hint visibility.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Copy/paste from the dashboard terminal (xterm.js + tmux) was unreliable, with zero feedback when it failed:
navigator.clipboard.writeText(...).catch(() => {}).navigator.clipboardisundefinedon non-secure origins (dashboard opened via LAN IP instead of localhost) and can be permission-denied, so copies silently no-oped.Changes
writeClipboardText()layered helper (terminal-clipboard.ts):navigator.clipboard.writeText→document.execCommand('copy')via a temporarysr-onlytextarea (works on non-secure origins, restores focus afterwards) → resolvesfalseso the failure is surfaced instead of swallowed. Used by both terminal copy paths: the OSC 52 handler and the Cmd+C / Ctrl+Shift+C key handler (these are the only terminal copy paths — verified by sweep).registerClipboardHandlersreports every copy outcome via a new optionalonCopyResultcallback.DirectTerminalflashes a small transient Copied / Copy failed pill (role="status") over the terminal for 2s. Design tokens + Tailwind classes only — no inline styles, no new libraries (C-01, C-02, C-07).useXtermTerminaldetects active mouse reporting viaterminal.modes.mouseTrackingMode(checked in the parsed-write callback, setState only on transitions). While active,TerminalControlsshows a subtle ⇧+drag to select hint with an explanatory tooltip, in both the chrome bar and the chromeless floating controls. It disappears when the TUI releases the mouse.The optional copy-on-select toggle was deliberately left out — reliable selection-end detection on top of
onSelectionChangeisn't low-risk, and the core fix doesn't depend on it. Happy to follow up if wanted.Invariants preserved
onCopyResultRef) so a changing identity can't tear down/recreate the terminal or WebSocket.Tests
terminal-clipboard.test.tsextended (15 new tests):writeClipboardTextmatrix — clipboard present / absent / rejected, execCommand ok / false / throws / missing, textarea cleanup — andonCopyResultreporting for OSC 52 success, decode failure, fallback success/failure, and Cmd+C.DirectTerminal.copy-feedback.test.tsx: toast show/auto-dismiss/timer-reset, hint visible while mouse reporting active (chrome + chromeless), hidden otherwise.Verification
pnpm --filter @aoagents/ao-web typecheck✅pnpm --filter @aoagents/ao-web test✅ (92 files, 1050 passed, 5 skipped)pnpm lint✅ (0 errors; remaining warnings pre-existing)🤖 Generated with Claude Code