diff --git a/.changeset/faster-agent-manager-terminal.md b/.changeset/faster-agent-manager-terminal.md new file mode 100644 index 00000000000..d16d0263fd9 --- /dev/null +++ b/.changeset/faster-agent-manager-terminal.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Show the first Agent Manager terminal prompt sooner by deferring optional terminal enhancements until after initial paint. diff --git a/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx b/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx index 8ae231cacb4..606c8fa47ec 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx @@ -158,39 +158,6 @@ export const TerminalTab: Component = (props) => { }) const fit = new FitAddon() term.loadAddon(fit) - // Clickable URLs in terminal output (Cmd/Ctrl+click to open). - // WebLinksAddon's default handler calls `window.open`, which VS Code - // webviews intercept and silently drop โ€” so we pass an explicit - // handler that posts an `openExternal` message. The message falls - // through `AgentManagerProvider.onMessage` to the underlying - // `KiloProvider.handleWebviewMessage` path which already calls - // `vscode.env.openExternal` for sidebar + settings links. - term.loadAddon( - new WebLinksAddon((_event, url) => { - vscode.postMessage({ type: "openExternal", url }) - }), - ) - // OSC 52 clipboard support โ€” lets shell programs (tmux, neovim, etc.) - // copy to the system clipboard via escape sequences. Writes always - // work in the webview; reads require the clipboard-read permission, - // which VS Code does not grant by default, so paste-from-escape - // silently falls back to no-op. Acceptable trade-off. - term.loadAddon(new ClipboardAddon()) - // Unicode 15 grapheme-aware width tables. Fixes cell width for - // emoji introduced in Unicode 12-15 (๐Ÿซ  melting face, ๐Ÿซก salute, - // ๐ŸงŒ troll, and ~400 others) plus ZWJ grapheme sequences like - // ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ and ๐Ÿณ๏ธโ€๐ŸŒˆ. The older `@xterm/addon-unicode11` (which VS - // Code's integrated terminal still uses) stops at Unicode 11 - // (2018), leaving all post-2020 emoji rendered with wrong width โ€” - // the canvas cuts them off in the DOM renderer and cursor math - // drifts by one cell per emoji. VS Code hides this visually with - // WebGL; in a webview we don't have that fallback, so we fix it - // at the buffer-width layer instead. Addon is marked - // "experimental" in its README but has been stable on npm since - // 2023, is shipped by the same maintainer as the core xterm.js - // package, and has no open bugs as of v0.4.0. - term.loadAddon(new UnicodeGraphemesAddon()) - term.unicode.activeVersion = "15-graphemes" term.open(host) // Fit on the next frame โ€” `host` might still have 0px dimensions // during the initial layout pass otherwise. @@ -232,6 +199,8 @@ export const TerminalTab: Component = (props) => { let fallbackTimer: ReturnType | undefined let streamed = false let socketEnded = false + let frame: number | undefined + let deferred: number | undefined // The failure line must not depend on event ordering: the stream can // close before the exited snapshot lands (fast failures), or stay open // when a background child outlives the script. Write it exactly once, @@ -358,6 +327,34 @@ export const TerminalTab: Component = (props) => { } const disposeData = term.onData(send) open(props.wsUrl) + + // These addons are not needed to paint the initial prompt. Defer them + // until after the first frame so their startup work, especially the + // Unicode 15 width tables, does not delay the shell connection. + const loadAddons = () => { + deferred = undefined + if (closed) return + + // Clickable URLs in terminal output (Cmd/Ctrl+click to open). + // WebLinksAddon's default handler calls `window.open`, which VS Code + // webviews intercept and silently drop, so post an explicit message. + term.loadAddon( + new WebLinksAddon((_event, url) => { + vscode.postMessage({ type: "openExternal", url }) + }), + ) + // OSC 52 clipboard support for shell programs such as tmux and neovim. + term.loadAddon(new ClipboardAddon()) + // Use grapheme-aware width tables for newer emoji and ZWJ sequences. + term.loadAddon(new UnicodeGraphemesAddon()) + term.unicode.activeVersion = "15-graphemes" + term.refresh(0, Math.max(0, term.rows - 1)) + } + frame = requestAnimationFrame(() => { + frame = undefined + deferred = requestAnimationFrame(loadAddons) + }) + const restarted = (url: string) => { open(url) } @@ -525,6 +522,8 @@ export const TerminalTab: Component = (props) => { onCleanup(() => { closed = true if (pendingFrame !== null) cancelAnimationFrame(pendingFrame) + if (frame !== undefined) cancelAnimationFrame(frame) + if (deferred !== undefined) cancelAnimationFrame(deferred) document.removeEventListener("visibilitychange", onVisibilityChange) window.removeEventListener("focus", onWindowFocus) host.removeEventListener("focusin", onFocusIn)