diff --git a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts index 7c795d1f0e..5107f41d97 100644 --- a/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts +++ b/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts @@ -731,7 +731,8 @@ function parseKeypress(s: string = ''): ParsedKey { key.raw = undefined key.name = 'return' } else if (s === '\n') { - key.name = 'enter' + key.raw = undefined + key.name = 'return' } else if (s === '\t') { key.name = 'tab' } else if (s === '\b' || s === '\x1b\b') { diff --git a/ui-tui/src/app.tsx b/ui-tui/src/app.tsx index ca65830053..703f33ec29 100644 --- a/ui-tui/src/app.tsx +++ b/ui-tui/src/app.tsx @@ -406,6 +406,7 @@ function TranscriptScrollbar({ scrollRef, t }: { scrollRef: RefObject { + const row = completions[compIdx] + + if (!row?.text) { + return false + } + + const text = value.startsWith('/') && row.text.startsWith('/') && compReplace > 0 ? row.text.slice(1) : row.text + const next = value.slice(0, compReplace) + text + + if (next === value) { + return false + } + + setInput(next) + + return true + }, + [compIdx, compReplace, completions, input] + ) + const pulseReasoningStreaming = useCallback(() => { if (reasoningStreamingTimerRef.current) { clearTimeout(reasoningStreamingTimerRef.current) @@ -1480,12 +1503,7 @@ export function App({ gw }: { gw: GatewayClient }) { } if (key.tab && completions.length) { - const row = completions[compIdx] - - if (row?.text) { - const text = input.startsWith('/') && row.text.startsWith('/') && compReplace > 0 ? row.text.slice(1) : row.text - setInput(input.slice(0, compReplace) + text) - } + applyCompletion() return } @@ -3122,6 +3140,17 @@ export function App({ gw }: { gw: GatewayClient }) { [dequeue, dispatchSubmission, inputBuf, sid] ) + const submitOrComplete = useCallback( + (value: string) => { + if (value.startsWith('/') && completions.length && applyCompletion(value)) { + return + } + + submit(value) + }, + [applyCompletion, completions.length, submit] + ) + // ── Derived ────────────────────────────────────────────────────── const statusColor = @@ -3389,7 +3418,7 @@ export function App({ gw }: { gw: GatewayClient }) { columns={Math.max(20, cols - 3)} onChange={setInput} onPaste={handleTextPaste} - onSubmit={submit} + onSubmit={submitOrComplete} placeholder={empty ? PLACEHOLDER : busy ? 'Ctrl+C to interrupt…' : ''} value={input} />