/** * KHAELOR * File: src/tui/doctor.ts * Description: `khaelor --doctor-tui` — detected terminal capabilities and why, turning display bugs into self-diagnosed tickets (TUI v2 §7). * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai */ import { detectColorDepth } from "./renderer/capabilities.js"; export interface DoctorEnv { TERM?: string; COLORTERM?: string; NO_COLOR?: string; LANG?: string; LC_ALL?: string; TERM_PROGRAM?: string; } /** Terminals known to support OSC 8 hyperlinks / OSC 52 clipboard. */ const OSC8_TERMINALS = new Set(["iTerm.app", "WezTerm", "kitty", "ghostty", "Hyper", "vscode"]); const OSC52_TERMINALS = new Set(["iTerm.app", "WezTerm", "kitty", "ghostty", "Apple_Terminal"]); /** Build the --doctor-tui report: what was detected, and the reason. */ export function doctorReport(env: DoctorEnv, isTty: boolean, columns: number): string[] { const colorDepth = detectColorDepth(env as NodeJS.ProcessEnv, isTty); const utf8 = /utf-?8/i.test(env.LC_ALL ?? env.LANG ?? ""); const program = env.TERM_PROGRAM ?? ""; const osc8 = OSC8_TERMINALS.has(program); const osc52 = OSC52_TERMINALS.has(program); const line = (name: string, value: string, why: string): string => ` ${name.padEnd(16)} ${value.padEnd(18)} ${why}`; return [ "", " doctor-tui · detected capabilities", line("tty", String(isTty), isTty ? "stdout is a terminal" : "stdout is piped — TUI disabled"), line( "colors", colorDepth, env.NO_COLOR !== undefined ? "NO_COLOR is set" : `COLORTERM=${env.COLORTERM ?? "(unset)"} · TERM=${env.TERM ?? "(unset)"}`, ), line("unicode", utf8 ? "utf-8" : "ascii-fallback", `LANG=${env.LANG ?? "(unset)"}`), line("width", String(columns), columns < 100 ? "narrow layout: 2-line status bar, unified diffs" : "full layout"), line("osc8 links", osc8 ? "yes" : "unknown", `TERM_PROGRAM=${program || "(unset)"} — fallback: text (url)`), line("osc52 clipboard", osc52 ? "yes" : "unknown", "fallback: copy hint hidden"), "", " theme: khaelis (obsidian + magma) · degradation: truecolor → 256 → 16 → mono", " report display bugs with this block attached.", ]; }