mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-26 06:01:49 +00:00
feat(tui): add LIGHT_THEME preset for white/light terminal backgrounds
Splits the existing palette into DARK_THEME (current yellow-heavy default) and LIGHT_THEME (darker browns + proper contrast on white). DEFAULT_THEME aliases DARK_THEME, and flips to LIGHT_THEME when HERMES_TUI_LIGHT=1 is set at launch. Skin system (fromSkin) still layers on top of whichever preset is active, so users can keep customizing on top of either palette. Refs #11300.
This commit is contained in:
parent
3366714ba4
commit
20eab355e7
2 changed files with 80 additions and 11 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
import { DEFAULT_THEME, fromSkin } from '../theme.js'
|
import { DARK_THEME, DEFAULT_THEME, fromSkin, LIGHT_THEME } from '../theme.js'
|
||||||
|
|
||||||
describe('DEFAULT_THEME', () => {
|
describe('DEFAULT_THEME', () => {
|
||||||
it('has brand defaults', () => {
|
it('has brand defaults', () => {
|
||||||
|
|
@ -15,6 +15,26 @@ describe('DEFAULT_THEME', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('LIGHT_THEME', () => {
|
||||||
|
it('avoids bright-yellow accents unreadable on white backgrounds (#11300)', () => {
|
||||||
|
expect(LIGHT_THEME.color.gold).not.toBe('#FFD700')
|
||||||
|
expect(LIGHT_THEME.color.amber).not.toBe('#FFBF00')
|
||||||
|
expect(LIGHT_THEME.color.dim).not.toBe('#B8860B')
|
||||||
|
expect(LIGHT_THEME.color.statusWarn).not.toBe('#FFD700')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps the same shape as DARK_THEME', () => {
|
||||||
|
expect(Object.keys(LIGHT_THEME.color).sort()).toEqual(Object.keys(DARK_THEME.color).sort())
|
||||||
|
expect(LIGHT_THEME.brand).toEqual(DARK_THEME.brand)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('DEFAULT_THEME aliasing', () => {
|
||||||
|
it('defaults to DARK_THEME when HERMES_TUI_LIGHT is unset', () => {
|
||||||
|
expect(DEFAULT_THEME).toBe(DARK_THEME)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
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')
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,17 @@ function mix(a: string, b: string, t: number) {
|
||||||
|
|
||||||
// ── Defaults ─────────────────────────────────────────────────────────
|
// ── Defaults ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export const DEFAULT_THEME: Theme = {
|
const BRAND: ThemeBrand = {
|
||||||
|
name: 'Hermes Agent',
|
||||||
|
icon: '⚕',
|
||||||
|
prompt: '❯',
|
||||||
|
welcome: 'Type your message or /help for commands.',
|
||||||
|
goodbye: 'Goodbye! ⚕',
|
||||||
|
tool: '┊',
|
||||||
|
helpHeader: '(^_^)? Commands'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DARK_THEME: Theme = {
|
||||||
color: {
|
color: {
|
||||||
gold: '#FFD700',
|
gold: '#FFD700',
|
||||||
amber: '#FFBF00',
|
amber: '#FFBF00',
|
||||||
|
|
@ -112,20 +122,59 @@ export const DEFAULT_THEME: Theme = {
|
||||||
shellDollar: '#4dabf7'
|
shellDollar: '#4dabf7'
|
||||||
},
|
},
|
||||||
|
|
||||||
brand: {
|
brand: BRAND,
|
||||||
name: 'Hermes Agent',
|
|
||||||
icon: '⚕',
|
|
||||||
prompt: '❯',
|
|
||||||
welcome: 'Type your message or /help for commands.',
|
|
||||||
goodbye: 'Goodbye! ⚕',
|
|
||||||
tool: '┊',
|
|
||||||
helpHeader: '(^_^)? Commands'
|
|
||||||
},
|
|
||||||
|
|
||||||
bannerLogo: '',
|
bannerLogo: '',
|
||||||
bannerHero: ''
|
bannerHero: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Light-terminal palette: darker golds/ambers that stay legible on white
|
||||||
|
// backgrounds. Same shape as DARK_THEME so `fromSkin` still layers on top
|
||||||
|
// cleanly (#11300).
|
||||||
|
export const LIGHT_THEME: Theme = {
|
||||||
|
color: {
|
||||||
|
gold: '#8B6914',
|
||||||
|
amber: '#A0651C',
|
||||||
|
bronze: '#7A4F1F',
|
||||||
|
cornsilk: '#3D2F13',
|
||||||
|
dim: '#7A5A0F',
|
||||||
|
completionBg: '#F5F5F5',
|
||||||
|
completionCurrentBg: mix('#F5F5F5', '#A0651C', 0.25),
|
||||||
|
|
||||||
|
label: '#7A5A0F',
|
||||||
|
ok: '#2E7D32',
|
||||||
|
error: '#C62828',
|
||||||
|
warn: '#E65100',
|
||||||
|
|
||||||
|
prompt: '#2B2014',
|
||||||
|
sessionLabel: '#7A5A0F',
|
||||||
|
sessionBorder: '#7A5A0F',
|
||||||
|
|
||||||
|
statusBg: '#F5F5F5',
|
||||||
|
statusFg: '#333333',
|
||||||
|
statusGood: '#2E7D32',
|
||||||
|
statusWarn: '#8B6914',
|
||||||
|
statusBad: '#D84315',
|
||||||
|
statusCritical: '#B71C1C',
|
||||||
|
selectionBg: '#D4E4F7',
|
||||||
|
|
||||||
|
diffAdded: 'rgb(200,240,200)',
|
||||||
|
diffRemoved: 'rgb(240,200,200)',
|
||||||
|
diffAddedWord: 'rgb(27,94,32)',
|
||||||
|
diffRemovedWord: 'rgb(183,28,28)',
|
||||||
|
shellDollar: '#1565C0'
|
||||||
|
},
|
||||||
|
|
||||||
|
brand: BRAND,
|
||||||
|
|
||||||
|
bannerLogo: '',
|
||||||
|
bannerHero: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const LIGHT_MODE = /^(?:1|true|yes|on)$/i.test((process.env.HERMES_TUI_LIGHT ?? '').trim())
|
||||||
|
|
||||||
|
export const DEFAULT_THEME: Theme = LIGHT_MODE ? LIGHT_THEME : DARK_THEME
|
||||||
|
|
||||||
// ── Skin → Theme ─────────────────────────────────────────────────────
|
// ── Skin → Theme ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
export function fromSkin(
|
export function fromSkin(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue