fix(tui): termux-gate composer rendering tweaks for Ink TUI

Salvaged from #28942 (adybag14-cyber). Only the Ink TUI half is taken
here — the bundled "termux compatibility note" added to skills_tool.py
in the original PR did not address the actual user-reported bug
(skill_matches_platform() filtering Linux skills out on Termux) and
also regressed the EXCLUDED_SKILL_DIRS set used to prune nested
.venv/site-packages skills.

Changes:
- ui-tui/src/lib/prompt.ts: single-cell ASCII '>' marker in Termux mode
  to avoid ambiguous-width glyph artifacts while typing.
- ui-tui/src/components/appLayout.tsx: suppress profile prefix on
  narrow Termux panes (>=90 cols still shows it).
- ui-tui/src/lib/inputMetrics.ts + components/messageLine.tsx +
  lib/virtualHeights.ts: termux-aware transcript body width — drop
  the desktop 20-col floor on narrow mobile layouts, align virtual
  heights with actual rendered width.
- ui-tui/src/components/textInput.tsx: disable fast-echo bypass by
  default in Termux to avoid ghosting at soft-wrap boundaries.
  HERMES_TUI_TERMUX_FAST_ECHO=1 opts back in.

Tests: ui-tui/src/__tests__/{prompt,termuxComposerLayout,textInputFastEcho}.test.ts
(12 PR-added tests pass; 3 pre-existing wrapAnsi-bundling failures on
main are unrelated.)

The real skill-listing fix on Termux ('android' platform matching
Linux skills) ships as a follow-up commit on this branch.
This commit is contained in:
adybag14-cyber
2026-05-21 19:08:38 -07:00
committed by Teknium
parent 0e2873a77d
commit d08c2a016a
9 changed files with 134 additions and 13 deletions
+18 -1
View File
@@ -13,6 +13,7 @@ import {
isVoiceToggleKey,
type ParsedVoiceRecordKey
} from '../lib/platform.js'
import { isTermuxTuiMode } from '../lib/termux.js'
type InkExt = typeof Ink & {
stringWidth: (s: string) => number
@@ -298,7 +299,23 @@ export function canFastBackspaceShape(current: string, cursor: number, columns?:
export function supportsFastEchoTerminal(env: NodeJS.ProcessEnv = process.env): boolean {
// Terminal.app still shows paint/cursor artifacts under the fast-echo
// bypass path. Fall back to the normal Ink render path there.
return (env.TERM_PROGRAM ?? '').trim() !== 'Apple_Terminal'
if ((env.TERM_PROGRAM ?? '').trim() === 'Apple_Terminal') {
return false
}
// Termux terminals are especially sensitive to bypass-path cursor drift and
// stale paints at soft-wrap boundaries on tall/narrow viewports. Keep this
// off by default in Termux mode; allow explicit opt-in for local debugging.
if (isTermuxTuiMode(env)) {
const override = String(env.HERMES_TUI_TERMUX_FAST_ECHO ?? '').trim().toLowerCase()
if (override) {
return /^(?:1|true|yes|on)$/i.test(override)
}
return false
}
return true
}
function renderWithCursor(value: string, cursor: number) {