mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(tui): approval flow + input ergonomics + selection perf
- tui_gateway: route approvals through gateway callback (HERMES_GATEWAY_SESSION/ HERMES_EXEC_ASK) so dangerous commands emit approval.request instead of silently falling through the CLI input() path and auto-denying - approval UX: dedicated PromptZone between transcript and composer, safer defaults (sel=0, numeric quick-picks, no Esc=deny), activity trail line, outcome footer under the cost row - text input: Ctrl+A select-all, real forward Delete, Ctrl+W always consumed (fixes Ctrl+Backspace at cursor 0 inserting literal w) - hermes-ink selection: swap synchronous onRender() for throttled scheduleRender() on drag, and only notify React subscribers on presence change — no more per-cell paint/subscribe spam - useConfigSync: silence config.get polling failures instead of surfacing 'error: timeout: config.get' in the transcript
This commit is contained in:
parent
0219da9626
commit
5b386ced71
15 changed files with 319 additions and 129 deletions
|
|
@ -11,6 +11,7 @@ import type {
|
|||
import type { InputHandlerContext, InputHandlerResult } from './interfaces.js'
|
||||
import { $isBlocked, $overlayState, patchOverlayState } from './overlayStore.js'
|
||||
import { turnController } from './turnController.js'
|
||||
import { patchTurnState } from './turnStore.js'
|
||||
import { getUiState, patchUiState } from './uiStore.js'
|
||||
|
||||
const isCtrl = (key: { ctrl: boolean }, ch: string, target: string) => key.ctrl && ch.toLowerCase() === target
|
||||
|
|
@ -24,11 +25,17 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||
const pagerPageSize = Math.max(5, (terminal.stdout?.rows ?? 24) - 6)
|
||||
|
||||
const copySelection = () => {
|
||||
if (terminal.selection.copySelection()) {
|
||||
actions.sys('copied selection')
|
||||
const text = terminal.selection.copySelection()
|
||||
|
||||
if (text) {
|
||||
actions.sys(`copied ${text.length} chars`)
|
||||
}
|
||||
}
|
||||
|
||||
const clearSelection = () => {
|
||||
terminal.selection.clearSelection()
|
||||
}
|
||||
|
||||
const cancelOverlayFromCtrlC = () => {
|
||||
if (overlay.clarify) {
|
||||
return actions.answerClarify('')
|
||||
|
|
@ -37,7 +44,7 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||
if (overlay.approval) {
|
||||
return gateway
|
||||
.rpc<ApprovalRespondResponse>('approval.respond', { choice: 'deny', session_id: getUiState().sid })
|
||||
.then(r => r && (patchOverlayState({ approval: null }), actions.sys('denied')))
|
||||
.then(r => r && (patchOverlayState({ approval: null }), patchTurnState({ outcome: 'denied' })))
|
||||
}
|
||||
|
||||
if (overlay.sudo) {
|
||||
|
|
@ -215,6 +222,10 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||
return copySelection()
|
||||
}
|
||||
|
||||
if (key.escape && terminal.hasSelection) {
|
||||
return clearSelection()
|
||||
}
|
||||
|
||||
if (key.upArrow && !cState.inputBuf.length) {
|
||||
cycleQueue(1) || cycleHistory(-1)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue