import type { ThemeColor } from "@earendil-works/pi-coding-agent"; /** Cap on sub-items listed per section in the overview. */ export const MAX_LISTED = 5; /** Compact number formatting: 1.50M / 12.3k / 42. */ export const fmt = (n: number): string => { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(2)}M`; if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`; return `${Math.round(n)}`; }; /** Token count as a percentage of the window (0 when window is unknown). */ export const percent = (tokens: number, window: number): number => window > 0 ? (tokens / window) * 100 : 0; /** Theme color for a token count relative to the window + compaction threshold. */ export const themeColorFor = ( tokens: number, window: number, threshold: number, ): ThemeColor => { const p = percent(tokens, window); if (tokens >= threshold || p >= 95) return "error"; if (p >= 75) return "warning"; if (p >= 50) return "accent"; return "success"; }; /** ASCII progress bar with a `┃` marker at the compaction threshold. */ export const bar = (tokens: number, window: number, threshold: number, width = 20): string => { const p = percent(tokens, window); const filled = Math.round((p / 100) * width); const thresholdPos = Math.min( Math.round((Math.min(threshold, window) / window) * width), width - 1, ); const cells: string[] = Array.from({ length: width }, (_, i) => i < filled ? "█" : "░", ); if (thresholdPos >= 0) cells[thresholdPos] = "┃"; return cells.join(""); }; /** Compact "a 2.1k · b 1.1k · +3 more" list, largest first, capped. */ export const compactList = ( items: { label: string; tokens: number }[], cap = MAX_LISTED, ): string => { const sorted = [...items].sort((a, b) => b.tokens - a.tokens); const shown = sorted.slice(0, cap); const rest = sorted.length - shown.length; const parts = shown.map((i) => `${i.label} ${fmt(i.tokens)}`); if (rest > 0) parts.push(`+${rest} more`); return parts.join(" · "); };