fix(clipboard): dashboard Ctrl+C direct copy; TUI honest feedback; HERMES_TUI_FORCE_OSC52

- Dashboard copy: direct Clipboard API on Ctrl+C/Cmd+C (user gesture);
  send Escape to TUI to clear selection; Ctrl+Shift+C kept as fallback.
- TUI /copy: copySelection() async; only reports success if OSC52 emitted.
- Add HERMES_TUI_FORCE_OSC52 env var to override native-tool detection.
- Fixes "copied N chars" false-positive when clipboard backend absent.

Changes:
  web/src/pages/ChatPage.tsx — direct navigator.clipboard.writeText
  ui-tui/packages/hermes-ink/src/ink/ink.tsx — async copySelection
  ui-tui/packages/hermes-ink/src/ink/termio/osc.ts — HERMES_TUI_FORCE_OSC52
  ui-tui/src/app/slash/commands/core.ts — async /copy with honest feedback
This commit is contained in:
Harry Riddle 2026-04-26 18:37:21 +07:00 committed by Teknium
parent a562420383
commit 0f3a6f0fb3
4 changed files with 42 additions and 13 deletions

View file

@ -290,7 +290,9 @@ export default function ChatPage() {
term.attachCustomKeyEventHandler((ev) => {
if (ev.type !== "keydown") return true;
const copyModifier = isMac ? ev.metaKey : ev.ctrlKey && ev.shiftKey;
// 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;
const pasteModifier = isMac ? ev.metaKey : ev.ctrlKey && ev.shiftKey;
if (copyModifier && ev.key.toLowerCase() === "c") {
@ -299,9 +301,12 @@ export default function ChatPage() {
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");
ev.preventDefault();
return false;
}
// No selection → let Ctrl+C pass through as interrupt
}
if (pasteModifier && ev.key.toLowerCase() === "v") {