getTerminalBackgroundColor() always returns "dark" due to double color normalization
Affected versions
v1.4.4 through v1.4.6 (introduced by #22297)
Description
The refactoring in #22297 moved getTerminalBackgroundColor() from an inline function in app.tsx to Terminal.getTerminalBackgroundColor() in terminal.ts. The new implementation uses RGBA.fromInts() to parse the terminal's background color, but the mode() helper still divides by 255 — a leftover from the old code where r, g, b were raw 0–255 integers.
RGBA.fromInts() already normalizes to the 0.0–1.0 range internally:
// @opentui/core RGBA.ts
static fromInts(r: number, g: number, b: number, a: number = 255) {
return new RGBA(new Float32Array([r / 255, g / 255, b / 255, a / 255]))
}
But mode() divides by 255 again:
// packages/opencode/src/cli/cmd/tui/util/terminal.ts
function mode(bg: RGBA | null): "dark" | "light" {
if (!bg) return "dark"
const luminance = (0.299 * bg.r + 0.587 * bg.g + 0.114 * bg.b) / 255
// ^^^
return luminance > 0.5 ? "light" : "dark"
}
The maximum possible luminance (for pure white #ffffff) is 1.0 / 255 ≈ 0.004, which can never exceed 0.5. The function returns "dark" for every terminal background color.
Impact
Any theme with dark/light variants (gruvbox, catppuccin, nord, etc.) always selects the dark palette, even on a light terminal. The system theme is unaffected because it works directly with raw RGBA values and never calls mode().
Steps to reproduce
- Use a terminal with a light background
- Set theme to
gruvbox (or any theme with light/dark variants)
- Run
opencode on v1.4.4+
- Observe the dark variant is selected instead of light
Fix
Remove the / 255 from the luminance calculation in mode():
function mode(bg: RGBA | null): "dark" | "light" {
if (!bg) return "dark"
const luminance = 0.299 * bg.r + 0.587 * bg.g + 0.114 * bg.b
return luminance > 0.5 ? "light" : "dark"
}
getTerminalBackgroundColor()always returns "dark" due to double color normalizationAffected versions
v1.4.4 through v1.4.6 (introduced by #22297)
Description
The refactoring in #22297 moved
getTerminalBackgroundColor()from an inline function inapp.tsxtoTerminal.getTerminalBackgroundColor()interminal.ts. The new implementation usesRGBA.fromInts()to parse the terminal's background color, but themode()helper still divides by 255 — a leftover from the old code wherer,g,bwere raw 0–255 integers.RGBA.fromInts()already normalizes to the 0.0–1.0 range internally:But
mode()divides by 255 again:The maximum possible luminance (for pure white
#ffffff) is1.0 / 255 ≈ 0.004, which can never exceed 0.5. The function returns"dark"for every terminal background color.Impact
Any theme with
dark/lightvariants (gruvbox, catppuccin, nord, etc.) always selects the dark palette, even on a light terminal. Thesystemtheme is unaffected because it works directly with raw RGBA values and never callsmode().Steps to reproduce
gruvbox(or any theme with light/dark variants)opencodeon v1.4.4+Fix
Remove the
/ 255from the luminance calculation inmode():