hermes-agent/ui-tui/src/__tests__/termuxComposerLayout.test.ts
adybag14-cyber d08c2a016a 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.
2026-05-21 19:08:38 -07:00

40 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from 'vitest'
import { stableComposerColumns, transcriptBodyWidth } from '../lib/inputMetrics.js'
import { composerPromptText } from '../lib/prompt.js'
describe('Termux composer prompt + width guards', () => {
it('uses a single-cell ASCII prompt marker in Termux mode', () => {
expect(composerPromptText('', 'coder', false, true, 50)).toBe('>')
})
it('suppresses profile prefixes on narrow Termux panes', () => {
expect(composerPromptText('', 'upstr', false, true, 72)).toBe('>')
})
it('keeps profile context on very wide Termux panes', () => {
expect(composerPromptText('', 'upstr', false, true, 120)).toBe('upstr >')
})
it('reserves fewer columns for gutter on narrow Termux widths', () => {
// 32 columns after prompt: desktop reserves 2 for transcript scrollbar,
// Termux keeps those 2 columns for the active composer.
expect(stableComposerColumns(40, 8, false)).toBe(28)
expect(stableComposerColumns(40, 8, true)).toBe(30)
// With ample room, Termux still reserves the gutter for alignment.
expect(stableComposerColumns(60, 8, true)).toBe(48)
})
it('never over-allocates transcript body width on narrow panes', () => {
// Old behavior hard-minned to 20 columns and overflowed narrow layouts.
expect(transcriptBodyWidth(24, 'assistant', '>', true)).toBe(19)
expect(transcriptBodyWidth(24, 'user', 'upstr >', true)).toBe(14)
expect(transcriptBodyWidth(10, 'user', '>', true)).toBeGreaterThanOrEqual(1)
})
it('keeps legacy desktop floor outside Termux mode', () => {
expect(transcriptBodyWidth(24, 'assistant', '>')).toBe(20)
expect(transcriptBodyWidth(24, 'user', 'upstr >')).toBe(20)
})
})