mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
feat(tui): double ESC discards the draft, even mid-stream
Mirrors the CLI binding. Placed above the isBlocked early-return so it works while the agent streams — that is the whole gap, since Ctrl+C interrupts a running turn and only clears the composer when idle. Pushes the draft to history before clearing so Up recalls it.
This commit is contained in:
parent
59a7da9a89
commit
01022d737a
2 changed files with 31 additions and 1 deletions
|
|
@ -3,7 +3,7 @@ import { useStore } from '@nanostores/react'
|
|||
import { useEffect, useRef } from 'react'
|
||||
|
||||
import { DASHBOARD_TUI_MODE } from '../config/env.js'
|
||||
import { TYPING_IDLE_MS } from '../config/timing.js'
|
||||
import { DOUBLE_ESC_MS, TYPING_IDLE_MS } from '../config/timing.js'
|
||||
import { applyCompletion } from '../domain/slash.js'
|
||||
import type {
|
||||
ApprovalRespondResponse,
|
||||
|
|
@ -320,9 +320,33 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||
})
|
||||
}
|
||||
|
||||
// Double-Esc discards the draft, matching Claude Code / Gemini CLI. It
|
||||
// sits above the isBlocked early-return on purpose: Ctrl+C interrupts a
|
||||
// running turn rather than clearing, so while the agent streams there is
|
||||
// otherwise no way to throw away a half-typed prompt. The draft is pushed
|
||||
// to history first so Up recalls it.
|
||||
const lastEscRef = useRef(0)
|
||||
|
||||
useInput((ch, key) => {
|
||||
const live = getUiState()
|
||||
|
||||
if (key.escape) {
|
||||
const now = Date.now()
|
||||
const isDouble = now - lastEscRef.current <= DOUBLE_ESC_MS
|
||||
|
||||
lastEscRef.current = isDouble ? 0 : now
|
||||
|
||||
if (isDouble && (cState.input || cState.inputBuf.length)) {
|
||||
if (cState.input.trim()) {
|
||||
cActions.pushHistory(cState.input)
|
||||
}
|
||||
|
||||
cActions.clearIn()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (isBlocked) {
|
||||
// When approval/clarify/confirm overlays are active, their own useInput
|
||||
// handlers must receive keystrokes (arrow keys, numbers, Enter). Only
|
||||
|
|
|
|||
|
|
@ -12,3 +12,9 @@ export const REASONING_PULSE_MS = 700
|
|||
// responsive enough to track the drag, cheap enough to stay smooth, and the
|
||||
// trailing edge always lands the final width so the settled layout is exact.
|
||||
export const RESIZE_COALESCE_MS = 32
|
||||
|
||||
// Two Esc presses within this window discard the draft (Claude Code /
|
||||
// Gemini CLI parity). Long enough for a deliberate double-tap, short
|
||||
// enough that two unrelated Escs — dismissing a completion, then a
|
||||
// selection — don't silently clear the composer.
|
||||
export const DOUBLE_ESC_MS = 500
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue