fix(tui): drop main-screen banner flash, widen alt-screen clear on entry

- entry.tsx no longer writes bootBanner() to the main screen before the
  alt-screen enters. The <Banner> renders inside the alt screen via the
  seeded intro row, so nothing is lost — just the flash that preceded it.
  Fixes the torn first frame reported on Alacritty (blitz row 5 #17) and
  shaves the 'starting agent' hang perception (row 5 #1) since the UI
  paints straight into the steady-state view
- AlternateScreen prefixes ERASE_SCROLLBACK (\x1b[3J) to its entry so
  strict emulators start from a pristine grid; named constants replace
  the inline sequences for clarity
- bootBanner.ts deleted — dead code
This commit is contained in:
Brooklyn Nicholson 2026-04-22 15:04:24 -05:00
parent 6fb98f343a
commit 3ef6992edf
3 changed files with 4 additions and 30 deletions

View file

@ -2,6 +2,7 @@ import React, { type PropsWithChildren, useContext, useInsertionEffect } from 'r
import { c as _c } from 'react/compiler-runtime'
import instances from '../instances.js'
import { CURSOR_HOME, ERASE_SCREEN, ERASE_SCROLLBACK } from '../termio/csi.js'
import { DISABLE_MOUSE_TRACKING, ENABLE_MOUSE_TRACKING, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN } from '../termio/dec.js'
import { TerminalWriteContext } from '../useTerminalNotification.js'
@ -51,7 +52,9 @@ export function AlternateScreen(t0: Props) {
return
}
writeRaw(ENTER_ALT_SCREEN + '\x1B[2J\x1B[H' + (mouseTracking ? ENABLE_MOUSE_TRACKING : ''))
writeRaw(
ENTER_ALT_SCREEN + ERASE_SCROLLBACK + ERASE_SCREEN + CURSOR_HOME + (mouseTracking ? ENABLE_MOUSE_TRACKING : '')
)
ink?.setAltScreenActive(true, mouseTracking)
return () => {

View file

@ -1,26 +0,0 @@
const GOLD = '\x1b[38;2;255;215;0m'
const AMBER = '\x1b[38;2;255;191;0m'
const BRONZE = '\x1b[38;2;205;127;50m'
const DIM = '\x1b[38;2;184;134;11m'
const RESET = '\x1b[0m'
const LOGO = [
'██╗ ██╗███████╗██████╗ ███╗ ███╗███████╗███████╗ █████╗ ██████╗ ███████╗███╗ ██╗████████╗',
'██║ ██║██╔════╝██╔══██╗████╗ ████║██╔════╝██╔════╝ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝',
'███████║█████╗ ██████╔╝██╔████╔██║█████╗ ███████╗█████╗███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ',
'██╔══██║██╔══╝ ██╔══██╗██║╚██╔╝██║██╔══╝ ╚════██║╚════╝██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ',
'██║ ██║███████╗██║ ██║██║ ╚═╝ ██║███████╗███████║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ',
'╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ '
]
const GRADIENT = [GOLD, GOLD, AMBER, AMBER, BRONZE, BRONZE] as const
const LOGO_WIDTH = 98
const TAGLINE = `${DIM}⚕ Nous Research · Messenger of the Digital Gods${RESET}`
const FALLBACK = `\x1b[1m${GOLD}⚕ NOUS HERMES${RESET}`
export function bootBanner(cols: number = process.stdout.columns || 80): string {
const body = cols >= LOGO_WIDTH ? LOGO.map((text, i) => `${GRADIENT[i]}${text}${RESET}`).join('\n') : FALLBACK
return `\n${body}\n${TAGLINE}\n\n`
}

View file

@ -1,5 +1,4 @@
#!/usr/bin/env -S node --max-old-space-size=8192 --expose-gc
import { bootBanner } from './bootBanner.js'
import { GatewayClient } from './gatewayClient.js'
import { setupGracefulExit } from './lib/gracefulExit.js'
import { formatBytes, type HeapDumpResult, performHeapDump } from './lib/memory.js'
@ -10,8 +9,6 @@ if (!process.stdin.isTTY) {
process.exit(0)
}
process.stdout.write(bootBanner())
const gw = new GatewayClient()
gw.start()