fix(tui): harden terminal dimming and multiplexer copy (#14906)

- disable ANSI dim on VTE terminals by default so dark-background reasoning and accents stay readable
- suppress local multiplexer OSC52 echo while preserving remote passthrough and add regression coverage
This commit is contained in:
brooklyn! 2026-04-24 00:46:28 -05:00 committed by GitHub
parent 51f4c9827f
commit acdcb167fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 85 additions and 6 deletions

View file

@ -0,0 +1,18 @@
import { describe, expect, it } from 'vitest'
import { shouldUseAnsiDim } from './Text.js'
describe('shouldUseAnsiDim', () => {
it('disables ANSI dim on VTE terminals by default', () => {
expect(shouldUseAnsiDim({ VTE_VERSION: '7603' } as NodeJS.ProcessEnv)).toBe(false)
})
it('keeps ANSI dim enabled elsewhere by default', () => {
expect(shouldUseAnsiDim({ TERM: 'xterm-256color' } as NodeJS.ProcessEnv)).toBe(true)
})
it('honors explicit env override', () => {
expect(shouldUseAnsiDim({ HERMES_TUI_DIM: '1', VTE_VERSION: '7603' } as NodeJS.ProcessEnv)).toBe(true)
expect(shouldUseAnsiDim({ HERMES_TUI_DIM: '0' } as NodeJS.ProcessEnv)).toBe(false)
})
})

View file

@ -3,6 +3,9 @@ import React from 'react'
import { c as _c } from 'react/compiler-runtime'
import type { Color, Styles } from '../styles.js'
const ENV_ON_RE = /^(?:1|true|yes|on)$/i
const ENV_OFF_RE = /^(?:0|false|no|off)$/i
type BaseProps = {
/**
* Change text color. Accepts a raw color value (rgb, hex, ansi).
@ -62,6 +65,20 @@ type WeightProps =
}
export type Props = BaseProps & WeightProps
export function shouldUseAnsiDim(env: NodeJS.ProcessEnv = process.env): boolean {
const override = (env.HERMES_TUI_DIM ?? '').trim()
if (ENV_ON_RE.test(override)) {
return true
}
if (ENV_OFF_RE.test(override)) {
return false
}
return !env.VTE_VERSION
}
const memoizedStylesForWrap: Record<NonNullable<Styles['textWrap']>, Styles> = {
wrap: {
flexGrow: 0,
@ -143,6 +160,7 @@ export default function Text(t0: Props) {
const strikethrough = t3 === undefined ? false : t3
const inverse = t4 === undefined ? false : t4
const wrap = t5 === undefined ? 'wrap' : t5
const effectiveDim = dim && shouldUseAnsiDim()
if (children === undefined || children === null) {
return null
@ -174,11 +192,11 @@ export default function Text(t0: Props) {
let t8
if ($[4] !== dim) {
t8 = dim && {
dim
if ($[4] !== effectiveDim) {
t8 = effectiveDim && {
dim: effectiveDim
}
$[4] = dim
$[4] = effectiveDim
$[5] = t8
} else {
t8 = $[5]