mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-06 07:51:53 +00:00
fix(tui): harden Terminal.app render behavior
Avoid Terminal.app paint corruption by disabling fast-echo in that terminal, sanitizing non-SGR control sequences before ANSI rendering, and defaulting Apple Terminal back to the safer 256-color path unless truecolor is explicitly requested.
This commit is contained in:
parent
3b39096904
commit
290bf93104
9 changed files with 214 additions and 10 deletions
|
|
@ -12,6 +12,7 @@ import {
|
|||
compactPreview,
|
||||
hasAnsi,
|
||||
isPasteBackedText,
|
||||
sanitizeAnsiForRender,
|
||||
stripAnsi
|
||||
} from '../lib/text.js'
|
||||
import type { Theme } from '../theme.js'
|
||||
|
|
@ -85,13 +86,14 @@ export const MessageLine = memo(function MessageLine({
|
|||
if (msg.role === 'tool') {
|
||||
const maxChars = Math.max(24, cols - 14)
|
||||
const stripped = hasAnsi(msg.text) ? stripAnsi(msg.text) : msg.text
|
||||
const safeAnsi = hasAnsi(msg.text) ? sanitizeAnsiForRender(msg.text) : msg.text
|
||||
const preview = compactPreview(stripped, maxChars) || '(empty tool result)'
|
||||
|
||||
return (
|
||||
<Box alignSelf="flex-start" borderColor={t.color.muted} borderStyle="round" marginLeft={3} paddingX={1}>
|
||||
{hasAnsi(msg.text) ? (
|
||||
<Text wrap="truncate-end">
|
||||
<Ansi>{msg.text}</Ansi>
|
||||
<Ansi>{safeAnsi}</Ansi>
|
||||
</Text>
|
||||
) : (
|
||||
<Text color={t.color.muted} wrap="truncate-end">
|
||||
|
|
@ -129,13 +131,13 @@ export const MessageLine = memo(function MessageLine({
|
|||
{msg.text.length.toLocaleString()} chars
|
||||
</Text>
|
||||
</Box>
|
||||
{systemOpen && <Ansi>{msg.text}</Ansi>}
|
||||
{systemOpen && <Ansi>{sanitizeAnsiForRender(msg.text)}</Ansi>}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
if (msg.role !== 'user' && hasAnsi(msg.text)) {
|
||||
return <Ansi>{msg.text}</Ansi>
|
||||
return <Ansi>{sanitizeAnsiForRender(msg.text)}</Ansi>
|
||||
}
|
||||
|
||||
if (msg.role === 'assistant') {
|
||||
|
|
|
|||
|
|
@ -283,6 +283,12 @@ export function canFastBackspaceShape(current: string, cursor: number, columns?:
|
|||
return ASCII_PRINTABLE_RE.test(removed)
|
||||
}
|
||||
|
||||
export function supportsFastEchoTerminal(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||
// Terminal.app still shows paint/cursor artifacts under the fast-echo
|
||||
// bypass path. Fall back to the normal Ink render path there.
|
||||
return (env.TERM_PROGRAM ?? '').trim() !== 'Apple_Terminal'
|
||||
}
|
||||
|
||||
function renderWithCursor(value: string, cursor: number) {
|
||||
const pos = Math.max(0, Math.min(cursor, value.length))
|
||||
|
||||
|
|
@ -559,7 +565,7 @@ export function TextInput({
|
|||
}, 16)
|
||||
}
|
||||
|
||||
const canFastEchoBase = () => focus && termFocus && !selected && !mask && !!stdout?.isTTY
|
||||
const canFastEchoBase = () => supportsFastEchoTerminal() && focus && termFocus && !selected && !mask && !!stdout?.isTTY
|
||||
|
||||
const canFastAppend = (current: string, cursor: number, text: string) =>
|
||||
canFastEchoBase() && canFastAppendShape(current, cursor, text, columns, lineWidthRef.current)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue