From 103c71ac36c6ebbf929ecf52daaef02350296c09 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 22 Apr 2026 16:32:48 -0500 Subject: [PATCH] =?UTF-8?q?refactor(tui):=20/clean=20pass=20on=20tui-polis?= =?UTF-8?q?h=20=E2=80=94=20data=20tables,=20tighter=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - normalizeStatusBar: replace Set + early-returns + cast with a single alias lookup table. Handles legacy `false`, trims/lowercases strings, maps `on` → `top` in one pass. One expression, no `as` hacks. - Tab title block: drop the narrative comment, fold blockedOnInput/titleStatus/cwdTag/terminalTitle into inline expressions inside useTerminalTitle. Avoids shadowing the outer `cwd`. - tui_gateway statusbar set branch: read `display` once instead of `cfg0.get("display")` twice. --- tui_gateway/server.py | 4 ++-- ui-tui/src/app/useConfigSync.ts | 23 ++++++++--------------- ui-tui/src/app/useMainApp.ts | 21 ++++++++++----------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 7e0bef9a1..3aac77192 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -2528,8 +2528,8 @@ def _(rid, params: dict) -> dict: if key == "statusbar": raw = str(value or "").strip().lower() - cfg0 = _load_cfg() - d0 = cfg0.get("display") if isinstance(cfg0.get("display"), dict) else {} + display = _load_cfg().get("display") + d0 = display if isinstance(display, dict) else {} current = _coerce_statusbar(d0.get("tui_statusbar", "top")) if raw in ("", "toggle"): diff --git a/ui-tui/src/app/useConfigSync.ts b/ui-tui/src/app/useConfigSync.ts index fb0e679a1..63b0100cc 100644 --- a/ui-tui/src/app/useConfigSync.ts +++ b/ui-tui/src/app/useConfigSync.ts @@ -14,23 +14,16 @@ import type { StatusBarMode } from './interfaces.js' import { turnController } from './turnController.js' import { patchUiState } from './uiStore.js' -const STATUSBAR_MODES = new Set(['bottom', 'off', 'top']) - -export const normalizeStatusBar = (raw: unknown): StatusBarMode => { - if (raw === false) { - return 'off' - } - - if (typeof raw !== 'string') { - return 'top' - } - - const v = raw.trim().toLowerCase() - const mode = (v === 'on' ? 'top' : v) as StatusBarMode - - return STATUSBAR_MODES.has(mode) ? mode : 'top' +const STATUSBAR_ALIAS: Record = { + bottom: 'bottom', + off: 'off', + on: 'top', + top: 'top' } +export const normalizeStatusBar = (raw: unknown): StatusBarMode => + raw === false ? 'off' : typeof raw === 'string' ? STATUSBAR_ALIAS[raw.trim().toLowerCase()] ?? 'top' : 'top' + const MTIME_POLL_MS = 5000 const quietRpc = async = Record>( diff --git a/ui-tui/src/app/useMainApp.ts b/ui-tui/src/app/useMainApp.ts index 2a25aacf7..36b1e0179 100644 --- a/ui-tui/src/app/useMainApp.ts +++ b/ui-tui/src/app/useMainApp.ts @@ -1,4 +1,4 @@ -import { type ScrollBoxHandle, useApp, useHasSelection, useSelection, useStdout, useTerminalTitle } from '@hermes/ink' +import { useApp, useHasSelection, useSelection, useStdout, useTerminalTitle, type ScrollBoxHandle } from '@hermes/ink' import { useStore } from '@nanostores/react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -314,16 +314,15 @@ export function useMainApp(gw: GatewayClient) { useConfigSync({ gw, setBellOnComplete, setVoiceEnabled, sid: ui.sid }) - // ── Terminal tab title ───────────────────────────────────────────── - // model + cwd + 3-state marker so multi-instance users can spot which tab - // is working, which is idle, and which is waiting on them. - // `⚠` blocked on approval/sudo/secret/clarify, `⏳` busy, `✓` idle. - const shortModel = ui.info?.model?.replace(/^.*\//, '') ?? '' - const blockedOnInput = !!(overlay.approval || overlay.sudo || overlay.secret || overlay.clarify) - const titleStatus = blockedOnInput ? '⚠' : ui.busy ? '⏳' : '✓' - const cwdTag = ui.info?.cwd ? ` · ${shortCwd(ui.info.cwd, 24)}` : '' - const terminalTitle = shortModel ? `${titleStatus} ${shortModel}${cwdTag}` : 'Hermes' - useTerminalTitle(terminalTitle) + // Tab title: `⚠` waiting on approval/sudo/secret/clarify, `⏳` busy, `✓` idle. + const model = ui.info?.model?.replace(/^.*\//, '') ?? '' + const marker = + overlay.approval || overlay.sudo || overlay.secret || overlay.clarify ? '⚠' : ui.busy ? '⏳' : '✓' + const tabCwd = ui.info?.cwd + + useTerminalTitle( + model ? `${marker} ${model}${tabCwd ? ` · ${shortCwd(tabCwd, 24)}` : ''}` : 'Hermes' + ) useEffect(() => { if (!ui.sid || !stdout) {