Files
hermes-agent/ui-tui/src/entry.tsx
T
Brooklyn Nicholson 9503896aa2 perf(tui): paint banner to stdout in ~2ms, before Ink loads
Dynamic-importing @hermes/ink + App costs ~170ms on cold start — during
that window the terminal was blank. Now `entry.tsx` writes a raw-ANSI
banner to stdout immediately after the TTY check, using hardcoded
DEFAULT_THEME colors. Ink's `<AlternateScreen>` wipes the normal-screen
buffer when it mounts, so the boot banner is replaced seamlessly by the
real React render a moment later — no double-banner, no flash.

  T=2ms    banner visible (vs. ~170ms before)
  T=~170ms React + Ink mounts
  T=~200ms alt screen takes over, Banner component repaints

Palette drift between `bootBanner.ts` and the live theme is harmless —
the live render overrides after ~200ms. Narrow terminals (cols < 98)
fall back to the one-line "⚕ NOUS HERMES" marker.
2026-04-16 15:48:41 -05:00

23 lines
784 B
TypeScript

#!/usr/bin/env node
// Import order matters for cold start: `GatewayClient` + `bootBanner` have
// only node-builtin deps (<20ms), so we can paint the banner and spawn the
// python gateway before loading @hermes/ink + App (~170ms combined).
// `<AlternateScreen>` wipes the normal-screen buffer on Ink mount, so the
// boot banner is replaced seamlessly by the real React render.
import { bootBanner } from './bootBanner.js'
import { GatewayClient } from './gatewayClient.js'
if (!process.stdin.isTTY) {
console.log('hermes-tui: no TTY')
process.exit(0)
}
process.stdout.write(bootBanner())
const gw = new GatewayClient()
gw.start()
const [{ render }, { App }] = await Promise.all([import('@hermes/ink'), import('./app.js')])
render(<App gw={gw} />, { exitOnCtrlC: false })