mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-30 01:41:43 +00:00
fix(clipboard): report native/tmux success, keep Ctrl+Shift+C on dashboard
Follow-up on #16020 salvage. Three corrections: 1. Truth signal for /copy Before: success was 'OSC 52 sequence was emitted to stdout'. That's false on local Linux inside tmux (emitSequence=false), so /copy kept printing 'clipboard copy failed' to users whose xclip/wl-copy had already succeeded fire-and-forget. Fix: setClipboard() now returns { sequence, success } where success = native-fired OR tmux-buffer-loaded OR osc52-emitted. copyNative() returns a boolean telling setClipboard whether a native attempt was made. /copy only shows 'failed' when literally no path was taken. 2. Dashboard keybinding Before: Ctrl+C for copy on non-Mac (Ctrl+Shift+C for paste). That swallows SIGINT when a stale selection is present and breaks the xterm/gnome-terminal/konsole/Windows-Terminal convention where Ctrl+C in a terminal emulator is always SIGINT. The real bug was that clipboard writes lost user-gesture through OSC-52 round-trips, which the direct writeText already fixes. Fix: revert copyModifier to Ctrl+Shift+C on non-Mac. Direct writeText in the keydown handler preserves user gesture. term.write Escape replaced with term.clearSelection() (works without relying on TUI input mode). 3. Error toast text Before: 'see HERMES_TUI_DEBUG_CLIPBOARD' — tells users how to debug but not how to fix. Fix: point users at HERMES_TUI_FORCE_OSC52=1 first (the actual escape hatch), mention the debug var second.
This commit is contained in:
parent
2511207cb0
commit
e8441c4c0f
9 changed files with 120 additions and 50 deletions
|
|
@ -290,23 +290,31 @@ export default function ChatPage() {
|
|||
term.attachCustomKeyEventHandler((ev) => {
|
||||
if (ev.type !== "keydown") return true;
|
||||
|
||||
// Copy: Cmd+C on macOS, Ctrl+C on other platforms (when selection exists)
|
||||
// Paste: Cmd+Shift+V on macOS, Ctrl+Shift+V on others
|
||||
const copyModifier = isMac ? ev.metaKey : ev.ctrlKey;
|
||||
// Copy: Cmd+C on macOS, Ctrl+Shift+C on other platforms. Bare Ctrl+C
|
||||
// is reserved for SIGINT to the TUI child — matches xterm / gnome-terminal /
|
||||
// konsole / Windows Terminal. Ctrl+Shift+C only copies if a selection exists;
|
||||
// without a selection it passes through to the TUI so agents can still
|
||||
// react to the keypress.
|
||||
// Paste: Cmd+Shift+V on macOS, Ctrl+Shift+V on others.
|
||||
const copyModifier = isMac ? ev.metaKey : ev.ctrlKey && ev.shiftKey;
|
||||
const pasteModifier = isMac ? ev.metaKey : ev.ctrlKey && ev.shiftKey;
|
||||
|
||||
if (copyModifier && ev.key.toLowerCase() === "c") {
|
||||
const sel = term.getSelection();
|
||||
if (sel) {
|
||||
// Direct writeText inside the keydown handler preserves the user
|
||||
// gesture — async round-trips through OSC 52 can lose activation
|
||||
// and fail with "Document is not focused".
|
||||
navigator.clipboard.writeText(sel).catch((err) => {
|
||||
console.warn("[dashboard clipboard] direct copy failed:", err.message);
|
||||
});
|
||||
// Send Escape to the TUI to clear its selection overlay
|
||||
term.write("\x1b");
|
||||
// Clear xterm.js's highlight after copy (matches gnome-terminal).
|
||||
term.clearSelection();
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
// No selection → let Ctrl+C pass through as interrupt
|
||||
// No selection → fall through so the TUI receives Ctrl+Shift+C
|
||||
// (or the bare ev if the user used a different modifier).
|
||||
}
|
||||
|
||||
if (pasteModifier && ev.key.toLowerCase() === "v") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue