mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-08 03:01:47 +00:00
fix(tui): suspend Ink properly when opening $EDITOR via Ctrl+G
The Ctrl+G handler was toggling the alt-screen by hand (`\x1b[?1049l` ... `\x1b[?1049h`) without releasing stdin or kitty keyboard mode, so the launched editor would lose keystrokes (Ink kept swallowing them) and editors that don't speak CSI-u (e.g. nano) would print "Unknown sequence" for every Ctrl-key. Switch to `withInkSuspended` from @hermes/ink, the same helper `/setup` already uses. It pauses Ink, removes stdin listeners, drops raw mode, disables kitty/modifyOtherKeys + mouse + focus reporting, runs the editor, then restores everything with a full repaint.
This commit is contained in:
parent
489bed6f96
commit
3944b22506
2 changed files with 8 additions and 6 deletions
|
|
@ -121,7 +121,7 @@ export interface ComposerActions {
|
||||||
dequeue: () => string | undefined
|
dequeue: () => string | undefined
|
||||||
enqueue: (text: string) => void
|
enqueue: (text: string) => void
|
||||||
handleTextPaste: (event: PasteEvent) => MaybePromise<ComposerPasteResult | null>
|
handleTextPaste: (event: PasteEvent) => MaybePromise<ComposerPasteResult | null>
|
||||||
openEditor: () => void
|
openEditor: () => Promise<void>
|
||||||
pushHistory: (text: string) => void
|
pushHistory: (text: string) => void
|
||||||
replaceQueue: (index: number, text: string) => void
|
replaceQueue: (index: number, text: string) => void
|
||||||
setCompIdx: StateSetter<number>
|
setCompIdx: StateSetter<number>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||||
import { tmpdir } from 'node:os'
|
import { tmpdir } from 'node:os'
|
||||||
import { join } from 'node:path'
|
import { join } from 'node:path'
|
||||||
|
|
||||||
import { useStdin } from '@hermes/ink'
|
import { useStdin, withInkSuspended } from '@hermes/ink'
|
||||||
import { useStore } from '@nanostores/react'
|
import { useStore } from '@nanostores/react'
|
||||||
import { useCallback, useMemo, useState } from 'react'
|
import { useCallback, useMemo, useState } from 'react'
|
||||||
|
|
||||||
|
|
@ -253,14 +253,16 @@ export function useComposerState({
|
||||||
[handleResolvedPaste, onClipboardPaste, querier]
|
[handleResolvedPaste, onClipboardPaste, querier]
|
||||||
)
|
)
|
||||||
|
|
||||||
const openEditor = useCallback(() => {
|
const openEditor = useCallback(async () => {
|
||||||
const editor = process.env.EDITOR || process.env.VISUAL || 'vi'
|
const editor = process.env.EDITOR || process.env.VISUAL || 'vi'
|
||||||
const file = join(mkdtempSync(join(tmpdir(), 'hermes-')), 'prompt.md')
|
const file = join(mkdtempSync(join(tmpdir(), 'hermes-')), 'prompt.md')
|
||||||
|
let code: null | number = null
|
||||||
|
|
||||||
writeFileSync(file, [...inputBuf, input].join('\n'))
|
writeFileSync(file, [...inputBuf, input].join('\n'))
|
||||||
process.stdout.write('\x1b[?1049l')
|
|
||||||
const { status: code } = spawnSync(editor, [file], { stdio: 'inherit' })
|
await withInkSuspended(async () => {
|
||||||
process.stdout.write('\x1b[?1049h\x1b[2J\x1b[H')
|
code = spawnSync(editor, [file], { stdio: 'inherit' }).status
|
||||||
|
})
|
||||||
|
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
const text = readFileSync(file, 'utf8').trimEnd()
|
const text = readFileSync(file, 'utf8').trimEnd()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue