diff --git a/packages/cli/src/config/footerItems.test.ts b/packages/cli/src/config/footerItems.test.ts index 0f784c5517..c43ea7be0e 100644 --- a/packages/cli/src/config/footerItems.test.ts +++ b/packages/cli/src/config/footerItems.test.ts @@ -19,7 +19,7 @@ describe('deriveItemsFromLegacySettings', () => { 'git-branch', 'sandbox-status', 'model-name', - 'usage-limit', + 'quota', ]); }); @@ -39,14 +39,14 @@ describe('deriveItemsFromLegacySettings', () => { expect(items).not.toContain('sandbox-status'); }); - it('removes model-name, context-remaining, and usage-limit when hideModelInfo is true', () => { + it('removes model-name, context-remaining, and quota when hideModelInfo is true', () => { const settings = createMockSettings({ ui: { footer: { hideModelInfo: true, hideContextPercentage: true } }, }).merged; const items = deriveItemsFromLegacySettings(settings); expect(items).not.toContain('model-name'); expect(items).not.toContain('context-remaining'); - expect(items).not.toContain('usage-limit'); + expect(items).not.toContain('quota'); }); it('includes context-remaining when hideContextPercentage is false', () => { diff --git a/packages/cli/src/config/footerItems.ts b/packages/cli/src/config/footerItems.ts index ba3c4a1307..0716478eb5 100644 --- a/packages/cli/src/config/footerItems.ts +++ b/packages/cli/src/config/footerItems.ts @@ -33,7 +33,7 @@ export const ALL_ITEMS = [ description: 'Percentage of context window remaining', }, { - id: 'usage-limit', + id: 'quota', header: '/stats', description: 'Remaining usage on daily limit (not shown when unavailable)', }, @@ -67,7 +67,7 @@ export const DEFAULT_ORDER = [ 'sandbox-status', 'model-name', 'context-remaining', - 'usage-limit', + 'quota', 'memory-usage', 'session-id', 'code-changes', @@ -82,7 +82,7 @@ export function deriveItemsFromLegacySettings( 'git-branch', 'sandbox-status', 'model-name', - 'usage-limit', + 'quota', ]; const items = [...defaults]; @@ -96,7 +96,7 @@ export function deriveItemsFromLegacySettings( if (settings.ui.footer.hideModelInfo) { remove(items, 'model-name'); remove(items, 'context-remaining'); - remove(items, 'usage-limit'); + remove(items, 'quota'); } if ( !settings.ui.footer.hideContextPercentage && diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index d3b3bb5c31..c153f8e86a 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -17,10 +17,7 @@ import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js'; import process from 'node:process'; import { MemoryUsageDisplay } from './MemoryUsageDisplay.js'; import { ContextUsageDisplay } from './ContextUsageDisplay.js'; -import { - QUOTA_THRESHOLD_HIGH, - QUOTA_THRESHOLD_MEDIUM, -} from '../utils/displayUtils.js'; +import { QuotaDisplay } from './QuotaDisplay.js'; import { DebugProfiler } from './DebugProfiler.js'; import { useUIState } from '../contexts/UIStateContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; @@ -312,24 +309,22 @@ export const Footer: React.FC = () => { ); break; } - case 'usage-limit': { + case 'quota': { if (quotaStats?.remaining !== undefined && quotaStats.limit) { - const percentage = (quotaStats.remaining / quotaStats.limit) * 100; - let color = itemColor; - if (percentage < QUOTA_THRESHOLD_MEDIUM) { - color = theme.status.error; - } else if (percentage < QUOTA_THRESHOLD_HIGH) { - color = theme.status.warning; - } - const text = - quotaStats.remaining === 0 - ? 'limit reached' - : `daily ${percentage.toFixed(0)}%`; addCol( id, header, - () => {text}, - text.length, + () => ( + + ), + 10, // "daily 100%" is 10 chars, but terse is "100%" (4 chars) ); } break; @@ -375,18 +370,16 @@ export const Footer: React.FC = () => { for (const m of Object.values(uiState.sessionStats.metrics.models)) total += m.tokens.total; if (total > 0) { - const formatted = - new Intl.NumberFormat('en-US', { - notation: 'compact', - maximumFractionDigits: 1, - }) - .format(total) - .toLowerCase() + ' tokens'; + const formatter = new Intl.NumberFormat('en-US', { + notation: 'compact', + maximumFractionDigits: 1, + }); + const formatted = formatter.format(total).toLowerCase(); addCol( id, header, - () => {formatted}, - formatted.length, + () => {formatted} tokens, + formatted.length + 7, ); } break; diff --git a/packages/cli/src/ui/components/FooterConfigDialog.tsx b/packages/cli/src/ui/components/FooterConfigDialog.tsx index 7652e01973..4a9ca3d55f 100644 --- a/packages/cli/src/ui/components/FooterConfigDialog.tsx +++ b/packages/cli/src/ui/components/FooterConfigDialog.tsx @@ -285,9 +285,7 @@ export const FooterConfigDialog: React.FC = ({ 'context-remaining': ( 85% left ), - 'usage-limit': ( - daily 97% - ), + quota: 97%, 'memory-usage': ( 260 MB ), diff --git a/packages/cli/src/ui/components/QuotaDisplay.tsx b/packages/cli/src/ui/components/QuotaDisplay.tsx index d20291580a..881f4c77fd 100644 --- a/packages/cli/src/ui/components/QuotaDisplay.tsx +++ b/packages/cli/src/ui/components/QuotaDisplay.tsx @@ -18,6 +18,8 @@ interface QuotaDisplayProps { limit: number | undefined; resetTime?: string; terse?: boolean; + forceShow?: boolean; + lowercase?: boolean; } export const QuotaDisplay: React.FC = ({ @@ -25,6 +27,8 @@ export const QuotaDisplay: React.FC = ({ limit, resetTime, terse = false, + forceShow = false, + lowercase = false, }) => { if (remaining === undefined || limit === undefined || limit === 0) { return null; @@ -32,7 +36,7 @@ export const QuotaDisplay: React.FC = ({ const percentage = (remaining / limit) * 100; - if (percentage > QUOTA_THRESHOLD_HIGH) { + if (!forceShow && percentage > QUOTA_THRESHOLD_HIGH) { return null; } @@ -45,20 +49,17 @@ export const QuotaDisplay: React.FC = ({ !terse && resetTime ? `, ${formatResetTime(resetTime)}` : ''; if (remaining === 0) { - return ( - - {terse - ? 'Limit reached' - : `/stats Limit reached${resetInfo}${!terse && '. /auth to continue.'}`} - - ); + let text = terse + ? 'Limit reached' + : `/stats Limit reached${resetInfo}${!terse && '. /auth to continue.'}`; + if (lowercase) text = text.toLowerCase(); + return {text}; } - return ( - - {terse - ? `${percentage.toFixed(0)}%` - : `/stats ${percentage.toFixed(0)}% usage remaining${resetInfo}`} - - ); + let text = terse + ? `${percentage.toFixed(0)}%` + : `/stats ${percentage.toFixed(0)}% usage remaining${resetInfo}`; + if (lowercase) text = text.toLowerCase(); + + return {text}; }; diff --git a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap index 6a59ce6dfc..f5090725ef 100644 --- a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap @@ -8,7 +8,7 @@ exports[`