From 25c11ed0a59652d8fcb71dc2f9df5788a4861bd8 Mon Sep 17 00:00:00 2001 From: jnjpng Date: Thu, 12 Feb 2026 14:03:20 -0800 Subject: [PATCH] fix: /context double render on short terminals and stale loading text (#934) Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com> Co-authored-by: Letta --- src/cli/App.tsx | 23 ++++++----------------- src/cli/helpers/contextChart.ts | 21 ++++++++++++++------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/cli/App.tsx b/src/cli/App.tsx index e1d3dc6..f222d72 100644 --- a/src/cli/App.tsx +++ b/src/cli/App.tsx @@ -6171,23 +6171,12 @@ export default function App({ const usedTokens = contextTrackerRef.current.lastContextTokens; const history = contextTrackerRef.current.contextTokensHistory; - // Phase 1: Show single-color bar + chart + "Fetching breakdown..." - // Stays in dynamic area ("running" phase) so it can be updated - const initialOutput = renderContextUsage({ - usedTokens, - contextWindow, - model, - history, - }); + const cmd = commandRunner.start( + trimmed, + "Fetching context breakdown...", + ); - const cmd = commandRunner.start(trimmed, ""); - cmd.update({ - output: initialOutput, - phase: "running", - preformatted: true, - }); - - // Phase 2: Fetch breakdown (5s timeout), then finish with color-coded bar + // Fetch breakdown (5s timeout) let breakdown: ContextWindowOverview | undefined; try { const settings = @@ -6215,7 +6204,7 @@ export default function App({ // Timeout or network error — proceed without breakdown } - // Finish with breakdown (bar colors + legend) or fallback + // Render the full chart once, directly into the finished output cmd.finish( renderContextUsage({ usedTokens, diff --git a/src/cli/helpers/contextChart.ts b/src/cli/helpers/contextChart.ts index a7d789e..a93cb2e 100644 --- a/src/cli/helpers/contextChart.ts +++ b/src/cli/helpers/contextChart.ts @@ -24,11 +24,14 @@ interface ContextChartOptions { compacted?: boolean; }>; breakdown?: ContextWindowOverview; + /** When true, breakdown is still being fetched (show placeholder). */ + loading?: boolean; } /** Renders the /context command output with usage bar, legend, and braille chart. */ export function renderContextUsage(opts: ContextChartOptions): string { - const { usedTokens, contextWindow, model, history, breakdown } = opts; + const { usedTokens, contextWindow, model, history, breakdown, loading } = + opts; if (usedTokens === 0) { return "Context data not available yet. Run a turn to see context usage."; @@ -175,12 +178,16 @@ export function renderContextUsage(opts: ContextChartOptions): string { } else { const barColor = hexToFgAnsi(brandColors.primaryAccent); bar = `${barColor}${"▰".repeat(filledFromUsage)}${reset}${"▱".repeat(totalSegments - filledFromUsage)}`; - // Reserve same line count as breakdown legend to avoid layout shift - const placeholderLines = [ - `${dim} Fetching breakdown...${reset}`, - ...new Array(6).fill(""), - ]; - legend = `\n${placeholderLines.join("\n")}`; + if (loading) { + const placeholderLines = [ + `${dim} Fetching breakdown...${reset}`, + ...new Array(6).fill(""), + ]; + legend = `\n${placeholderLines.join("\n")}`; + } else { + // Fetch completed without breakdown — show nothing instead of stale placeholder + legend = ""; + } } let output = `${bold}Context Usage${reset}\n\n`;