mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-07 02:51:50 +00:00
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:
parent
a562420383
commit
0f3a6f0fb3
4 changed files with 42 additions and 13 deletions
|
|
@ -1301,7 +1301,13 @@ export default class Ink {
|
|||
* highlight. Matches iTerm2's copy-on-select behavior where the selected
|
||||
* region stays visible after the automatic copy.
|
||||
*/
|
||||
copySelectionNoClear(): string {
|
||||
/**
|
||||
* Copy the current text selection to the system clipboard without clearing the
|
||||
* selection. Returns the copied text on success (empty if no selection or
|
||||
* clipboard operation failed). Success is determined by whether an OSC 52
|
||||
* sequence was emitted (native/tmux paths do not produce a sequence).
|
||||
*/
|
||||
async copySelectionNoClear(): Promise<string> {
|
||||
if (!hasSelection(this.selection)) {
|
||||
return ''
|
||||
}
|
||||
|
|
@ -1309,28 +1315,36 @@ export default class Ink {
|
|||
const text = getSelectedText(this.selection, this.frontFrame.screen)
|
||||
|
||||
if (text) {
|
||||
void setClipboard(text).then(raw => {
|
||||
try {
|
||||
const raw = await setClipboard(text)
|
||||
if (raw) {
|
||||
this.options.stdout.write(raw)
|
||||
} else if (process.env.HERMES_TUI_DEBUG_CLIPBOARD) {
|
||||
return text
|
||||
}
|
||||
if (process.env.HERMES_TUI_DEBUG_CLIPBOARD) {
|
||||
console.error('[clipboard] [osc52] no sequence emitted — native clipboard or tmux buffer path in use')
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
if (process.env.HERMES_TUI_DEBUG_CLIPBOARD) {
|
||||
console.error('[clipboard] [osc52] error:', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the current text selection to the system clipboard via OSC 52
|
||||
* and clear the selection. Returns the copied text (empty if no selection).
|
||||
* and clear the selection. Returns the copied text (empty if no selection
|
||||
* or clipboard operation failed).
|
||||
*/
|
||||
copySelection(): string {
|
||||
async copySelection(): Promise<string> {
|
||||
if (!hasSelection(this.selection)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const text = this.copySelectionNoClear()
|
||||
const text = await this.copySelectionNoClear()
|
||||
clearSelection(this.selection)
|
||||
this.notifySelectionChange()
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,11 @@ export function getClipboardPath(): ClipboardPath {
|
|||
}
|
||||
|
||||
export function shouldEmitClipboardSequence(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||
const override = (env.HERMES_TUI_CLIPBOARD_OSC52 ?? env.HERMES_TUI_COPY_OSC52 ?? '').trim()
|
||||
const override = (
|
||||
env.HERMES_TUI_FORCE_OSC52 ??
|
||||
env.HERMES_TUI_CLIPBOARD_OSC52 ??
|
||||
env.HERMES_TUI_COPY_OSC52 ?? ''
|
||||
).trim()
|
||||
|
||||
if (ENV_ON_RE.test(override)) {
|
||||
return true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue