From c6ed61430a56a6d6c860afd7574ffc34479d9629 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 16 Apr 2026 14:58:12 -0500 Subject: [PATCH] perf(tui): paint banner on first frame, don't wait on session.create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously `historyItems` was seeded empty and the intro (with Banner + SessionPanel) was only pushed after Python's `session.create` returned — ~1.8s of agent + tools + MCP init with nothing on screen. Base CLI feels instant because it prints the banner as its first action. Seed `historyItems` with an info-less intro on mount. `appLayout` now renders the Banner unconditionally for `kind === 'intro'` and gates only the SessionPanel on `info` being present. Gateway.ready swaps the skin (~200ms) and session.info fills in the panel when the agent is ready. Net: first usable frame drops from ~2s to ~300ms (node + module graph + React mount). No behavior change — intro message is replaced in place by `introMsg(info)` when `newSession()` / `resumeById()` resolve. --- ui-tui/src/app/useMainApp.ts | 5 ++++- ui-tui/src/components/appLayout.tsx | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ui-tui/src/app/useMainApp.ts b/ui-tui/src/app/useMainApp.ts index f2827dfdfa..e6e8cfe1f4 100644 --- a/ui-tui/src/app/useMainApp.ts +++ b/ui-tui/src/app/useMainApp.ts @@ -93,7 +93,10 @@ export function useMainApp(gw: GatewayClient) { } }, [stdout]) - const [historyItems, setHistoryItems] = useState([]) + // Seed with an info-less intro so the banner paints on the first frame, + // before gateway.ready / session.create resolve. Replaced by + // `introMsg(info)` as soon as session.info arrives. + const [historyItems, setHistoryItems] = useState(() => [{ kind: 'intro', role: 'system', text: '' }]) const [lastUserMsg, setLastUserMsg] = useState('') const [stickyPrompt, setStickyPrompt] = useState('') const [catalog, setCatalog] = useState(null) diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index d517fa7a74..48cf1c5b89 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -33,11 +33,11 @@ const TranscriptPane = memo(function TranscriptPane({ {visibleHistory.map(row => ( - {row.msg.kind === 'intro' && row.msg.info ? ( + {row.msg.kind === 'intro' ? ( - + {row.msg.info && } ) : row.msg.kind === 'panel' && row.msg.panelData ? (