mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-26 06:01:49 +00:00
fix(tui): route update-behind banner through theme + auto-detect light terminals (#11300)
- branding.tsx: `color="yellow"` → `t.color.warn` so light-mode users get the burnt-orange warn instead of unreadable bright yellow on white bg. - theme.ts: replace HERMES_TUI_LIGHT regex with `detectLightMode(env)` that also sniffs `COLORFGBG` (XFCE Terminal, rxvt, Terminal.app, iTerm2). Bg slot 7 or 15 → LIGHT_THEME. Explicit HERMES_TUI_LIGHT (on *or* off) still wins. - tests: cover empty env, explicit on/off, COLORFGBG positions, and off-override.
This commit is contained in:
parent
b7e71fb727
commit
6a06973b0d
3 changed files with 51 additions and 8 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
import { DARK_THEME, DEFAULT_THEME, fromSkin, LIGHT_THEME } from '../theme.js'
|
import { DARK_THEME, DEFAULT_THEME, detectLightMode, fromSkin, LIGHT_THEME } from '../theme.js'
|
||||||
|
|
||||||
describe('DEFAULT_THEME', () => {
|
describe('DEFAULT_THEME', () => {
|
||||||
it('has brand defaults', () => {
|
it('has brand defaults', () => {
|
||||||
|
|
@ -30,11 +30,37 @@ describe('LIGHT_THEME', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('DEFAULT_THEME aliasing', () => {
|
describe('DEFAULT_THEME aliasing', () => {
|
||||||
it('defaults to DARK_THEME when HERMES_TUI_LIGHT is unset', () => {
|
it('defaults to DARK_THEME when nothing signals light', () => {
|
||||||
expect(DEFAULT_THEME).toBe(DARK_THEME)
|
expect(DEFAULT_THEME).toBe(DARK_THEME)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('detectLightMode', () => {
|
||||||
|
it('returns false on empty env', () => {
|
||||||
|
expect(detectLightMode({})).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('honors HERMES_TUI_LIGHT on/off', () => {
|
||||||
|
expect(detectLightMode({ HERMES_TUI_LIGHT: '1' })).toBe(true)
|
||||||
|
expect(detectLightMode({ HERMES_TUI_LIGHT: 'true' })).toBe(true)
|
||||||
|
expect(detectLightMode({ HERMES_TUI_LIGHT: 'on' })).toBe(true)
|
||||||
|
expect(detectLightMode({ HERMES_TUI_LIGHT: '0' })).toBe(false)
|
||||||
|
expect(detectLightMode({ HERMES_TUI_LIGHT: 'off' })).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sniffs COLORFGBG bg slots 7 and 15 as light (#11300)', () => {
|
||||||
|
expect(detectLightMode({ COLORFGBG: '0;15' })).toBe(true)
|
||||||
|
expect(detectLightMode({ COLORFGBG: '0;default;15' })).toBe(true)
|
||||||
|
expect(detectLightMode({ COLORFGBG: '0;7' })).toBe(true)
|
||||||
|
expect(detectLightMode({ COLORFGBG: '15;0' })).toBe(false)
|
||||||
|
expect(detectLightMode({ COLORFGBG: '7;default;0' })).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('lets HERMES_TUI_LIGHT=0 override a light COLORFGBG', () => {
|
||||||
|
expect(detectLightMode({ COLORFGBG: '0;15', HERMES_TUI_LIGHT: '0' })).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('fromSkin', () => {
|
describe('fromSkin', () => {
|
||||||
it('overrides banner colors', () => {
|
it('overrides banner colors', () => {
|
||||||
expect(fromSkin({ banner_title: '#FF0000' }, {}).color.gold).toBe('#FF0000')
|
expect(fromSkin({ banner_title: '#FF0000' }, {}).color.gold).toBe('#FF0000')
|
||||||
|
|
|
||||||
|
|
@ -161,16 +161,16 @@ export function SessionPanel({ info, sid, t }: SessionPanelProps) {
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{typeof info.update_behind === 'number' && info.update_behind > 0 && (
|
{typeof info.update_behind === 'number' && info.update_behind > 0 && (
|
||||||
<Text bold color="yellow">
|
<Text bold color={t.color.warn}>
|
||||||
! {info.update_behind} {info.update_behind === 1 ? 'commit' : 'commits'} behind
|
! {info.update_behind} {info.update_behind === 1 ? 'commit' : 'commits'} behind
|
||||||
<Text bold={false} color="yellow" dimColor>
|
<Text bold={false} color={t.color.warn} dimColor>
|
||||||
{' '}
|
{' '}
|
||||||
- run{' '}
|
- run{' '}
|
||||||
</Text>
|
</Text>
|
||||||
<Text bold color="yellow">
|
<Text bold color={t.color.warn}>
|
||||||
{info.update_command || 'hermes update'}
|
{info.update_command || 'hermes update'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text bold={false} color="yellow" dimColor>
|
<Text bold={false} color={t.color.warn} dimColor>
|
||||||
{' '}
|
{' '}
|
||||||
to update
|
to update
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
||||||
|
|
@ -171,9 +171,26 @@ export const LIGHT_THEME: Theme = {
|
||||||
bannerHero: ''
|
bannerHero: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const LIGHT_MODE = /^(?:1|true|yes|on)$/i.test((process.env.HERMES_TUI_LIGHT ?? '').trim())
|
// Pick light vs dark. Explicit `HERMES_TUI_LIGHT` wins; otherwise sniff
|
||||||
|
// `COLORFGBG` (set by XFCE Terminal, rxvt, Terminal.app, etc.) — last field is the
|
||||||
|
// background ANSI index; 7/15 are the "white" slots most light themes emit (#11300).
|
||||||
|
export function detectLightMode(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||||
|
const explicit = (env.HERMES_TUI_LIGHT ?? '').trim().toLowerCase()
|
||||||
|
|
||||||
export const DEFAULT_THEME: Theme = LIGHT_MODE ? LIGHT_THEME : DARK_THEME
|
if (/^(?:1|true|yes|on)$/.test(explicit)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^(?:0|false|no|off)$/.test(explicit)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const bg = Number((env.COLORFGBG ?? '').trim().split(';').at(-1))
|
||||||
|
|
||||||
|
return bg === 7 || bg === 15
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_THEME: Theme = detectLightMode() ? LIGHT_THEME : DARK_THEME
|
||||||
|
|
||||||
// ── Skin → Theme ─────────────────────────────────────────────────────
|
// ── Skin → Theme ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue