/** * Pure renderer for the live dashboard: a snapshot of account state in, a * terminal frame string out. Kept pure (no I/O, no clock) so it is fully * testable; the live loop supplies the snapshot and prints the frame. */ export interface DashboardAccount { name: string; email?: string; plan?: string; loggedIn: boolean; active: boolean; enabled: boolean; /** Epoch ms the account is capped until, if currently capped. */ cappedUntil?: number; priority: number; /** * Subscription usage (0..1 per window), including per-model weekly windows and * when each window comes back. The reset times are carried through so the * detail line can answer "when can I use this again" without another lookup. */ usage?: { fiveHour: number | null; sevenDay: number | null; fiveHourReset?: number | null; sevenDayReset?: number | null; models?: Array<{ name: string; utilization: number; resetsAt?: number | null; }> | null; }; } export interface DashboardSnapshot { accounts: DashboardAccount[]; /** Recent activity lines, oldest first. */ events: string[]; now: number; refreshMs: number; /** The model in use, when anything pins one. Shown beside the active account. */ model?: string; /** Which ccx is drawing this, shown in the title. */ version?: string; /** * Where rotation would go next, already in words. * * Computed by the caller, which has the policy and the ledger, so this * renderer stays a pure function of what it is given. It is the one thing on * this screen that no other tool can show: not the state, but the * consequence of it. */ nextUp?: string; } export interface RenderOptions { color?: boolean; /** Interactive key hints in the footer (off for a plain one-shot print). */ interactive?: boolean; /** Index of the currently-selected row (for the live cursor). */ selected?: number; /** A message to show above the key hints (an error, or what just happened). */ notice?: string; /** A yes/no question waiting for an answer, shown instead of the key hints. */ confirm?: string; /** The name prompt, when the dashboard is asking for one. */ prompt?: { label: string; text: string; error?: string; }; /** * How many columns there are to draw in. * * The table fitted an 80-column terminal with one character to spare, which * is not fitting, it is luck: a longer account name or a longer wait pushed * it over and the whole row wrapped. The bars are the elastic part, so they * give up width first and the numbers, names and statuses stay whole. */ width?: number; } /** Render the full dashboard frame for the given snapshot. */ export declare function renderDashboard(snapshot: DashboardSnapshot, options?: RenderOptions): string;