mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-14 04:02:26 +00:00
fix(tui): normalize legacy Terminal.app colors (#17695)
Keep light Terminal.app TUI colors readable by normalizing non-banner theme tokens into ANSI256-safe buckets while preserving truecolor terminals.
This commit is contained in:
parent
31f70d1f2a
commit
4cc6da84a1
9 changed files with 487 additions and 50 deletions
|
|
@ -1,18 +1,38 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { shouldUseAnsiDim } from './Text.js'
|
||||
import { dimColorFallback, 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('disables ANSI dim on Apple Terminal by default', () => {
|
||||
expect(shouldUseAnsiDim({ TERM_PROGRAM: 'Apple_Terminal' } 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: '1', TERM_PROGRAM: 'Apple_Terminal' } as NodeJS.ProcessEnv)).toBe(true)
|
||||
expect(shouldUseAnsiDim({ HERMES_TUI_DIM: '0' } as NodeJS.ProcessEnv)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('dimColorFallback', () => {
|
||||
it('renders Apple Terminal dim as muted gray by default', () => {
|
||||
expect(dimColorFallback({ TERM_PROGRAM: 'Apple_Terminal' } as NodeJS.ProcessEnv)).toBe('#6B7280')
|
||||
})
|
||||
|
||||
it('normalizes Apple Terminal names before matching', () => {
|
||||
expect(dimColorFallback({ TERM_PROGRAM: ' Apple_Terminal ' } as NodeJS.ProcessEnv)).toBe('#6B7280')
|
||||
})
|
||||
|
||||
it('does not apply when dim is explicitly configured', () => {
|
||||
expect(dimColorFallback({ HERMES_TUI_DIM: '1', TERM_PROGRAM: 'Apple_Terminal' } as NodeJS.ProcessEnv)).toBeUndefined()
|
||||
expect(dimColorFallback({ HERMES_TUI_DIM: '0', TERM_PROGRAM: 'Apple_Terminal' } as NodeJS.ProcessEnv)).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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
|
||||
const LEGACY_APPLE_DIM_COLOR: Color = '#6B7280'
|
||||
type BaseProps = {
|
||||
/**
|
||||
* Change text color. Accepts a raw color value (rgb, hex, ansi).
|
||||
|
|
@ -76,9 +77,23 @@ export function shouldUseAnsiDim(env: NodeJS.ProcessEnv = process.env): boolean
|
|||
return false
|
||||
}
|
||||
|
||||
if ((env.TERM_PROGRAM ?? '').trim() === 'Apple_Terminal') {
|
||||
return false
|
||||
}
|
||||
|
||||
return !env.VTE_VERSION
|
||||
}
|
||||
|
||||
export function dimColorFallback(env: NodeJS.ProcessEnv = process.env): Color | undefined {
|
||||
const override = (env.HERMES_TUI_DIM ?? '').trim()
|
||||
|
||||
if (ENV_ON_RE.test(override) || ENV_OFF_RE.test(override)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return (env.TERM_PROGRAM ?? '').trim() === 'Apple_Terminal' ? LEGACY_APPLE_DIM_COLOR : undefined
|
||||
}
|
||||
|
||||
const memoizedStylesForWrap: Record<NonNullable<Styles['textWrap']>, Styles> = {
|
||||
wrap: {
|
||||
flexGrow: 0,
|
||||
|
|
@ -161,6 +176,7 @@ export default function Text(t0: Props) {
|
|||
const inverse = t4 === undefined ? false : t4
|
||||
const wrap = t5 === undefined ? 'wrap' : t5
|
||||
const effectiveDim = dim && shouldUseAnsiDim()
|
||||
const effectiveColor = dim && !effectiveDim ? (color ?? dimColorFallback()) : color
|
||||
|
||||
if (children === undefined || children === null) {
|
||||
return null
|
||||
|
|
@ -168,11 +184,11 @@ export default function Text(t0: Props) {
|
|||
|
||||
let t6
|
||||
|
||||
if ($[0] !== color) {
|
||||
t6 = color && {
|
||||
color
|
||||
if ($[0] !== effectiveColor) {
|
||||
t6 = effectiveColor && {
|
||||
color: effectiveColor
|
||||
}
|
||||
$[0] = color
|
||||
$[0] = effectiveColor
|
||||
$[1] = t6
|
||||
} else {
|
||||
t6 = $[1]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue