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.
23 lines
784 B
TypeScript
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 })
|