feat(cliproxy): clarify quota percentages are remaining in CLI output

Closes #1714
This commit is contained in:
Tam Nhu Tran committed 2026-08-25 15:35:23 -04:00
1 parent 65dc902299
commit eca266ad30
5 files changed
+107 -4

No files matched your search

@@ -138,7 +138,7 @@ export async function handleDoctor(verbose = false): Promise<void> {
for (const model of quota.models) {
const bar = formatQuotaBar(model.percentage);
console.log(` ${model.name.padEnd(20)} ${bar} ${model.percentage.toFixed(0)}%`);
console.log(` ${model.name.padEnd(20)} ${bar} ${model.percentage.toFixed(0)}% remaining`);
}
console.log('');
}
@@ -93,7 +93,7 @@ export function displayClaudeQuotaSection(
? dim(' [warning]')
: '';
console.log(
` ${getClaudeWindowDisplayLabel(window).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}%${statusLabel}${resetLabel}`
` ${getClaudeWindowDisplayLabel(window).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}% remaining${statusLabel}${resetLabel}`
);
}
console.log('');
@@ -94,7 +94,7 @@ export function displayCodexQuotaSection(
const resetValue = formatCodexWindowReset(window);
const resetLabel = resetValue ? dim(` Resets ${resetValue}`) : '';
console.log(
` ${getCodexWindowDisplayLabel(window, orderedWindows).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}%${resetLabel}`
` ${getCodexWindowDisplayLabel(window, orderedWindows).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}% remaining${resetLabel}`
);
}
console.log('');
@@ -67,7 +67,7 @@ export function displayGeminiCliQuotaSection(
? dim(` Resets ${formatResetTimeISO(bucket.resetTime)}`)
: '';
console.log(
` ${bucket.label.padEnd(24)} ${bar} ${bucket.remainingPercent.toFixed(0)}%${tokenLabel}${amountLabel}${resetLabel}`
` ${bucket.label.padEnd(24)} ${bar} ${bucket.remainingPercent.toFixed(0)}% remaining${tokenLabel}${amountLabel}${resetLabel}`
);
}
console.log('');
@@ -1,5 +1,7 @@
import { describe, expect, it } from 'bun:test';
import { displayClaudeQuotaSection } from '../../../src/commands/cliproxy/quota-subcommand/sections/claude';
import { displayCodexQuotaSection } from '../../../src/commands/cliproxy/quota-subcommand/sections/codex';
import { displayGeminiCliQuotaSection } from '../../../src/commands/cliproxy/quota-subcommand/sections/gemini-cli';
async function loadQuotaCommandTestExports() {
const moduleId = Date.now() + Math.random();
@@ -167,3 +169,104 @@ describe('cliproxy quota subcommand Codex label formatting', () => {
expect(label).not.toContain('\u0007');
});
});
function captureConsoleLog(fn: () => void): string {
const output: string[] = [];
const originalLog = console.log;
console.log = (...args: unknown[]) => output.push(args.map(String).join(' '));
try {
fn();
} finally {
console.log = originalLog;
}
return output.join('\n');
}
describe('cliproxy quota remaining percent labels', () => {
it('renders Claude remaining percent with a remaining suffix', () => {
const text = captureConsoleLog(() => {
displayClaudeQuotaSection([
{
account: 'claude@example.com',
quota: {
success: true,
windows: [
{
rateLimitType: 'five_hour',
label: '5h usage limit',
status: 'allowed',
utilization: 0.28,
usedPercent: 28,
remainingPercent: 72,
resetAt: null,
},
],
coreUsage: { fiveHour: null, weekly: null },
lastUpdated: 1,
accountId: 'claude@example.com',
},
},
]);
});
expect(text).toContain('72% remaining');
});
it('renders Codex remaining percent with a remaining suffix', () => {
const text = captureConsoleLog(() => {
displayCodexQuotaSection([
{
account: 'codex@example.com',
quota: {
success: true,
windows: [
{
label: 'Primary',
usedPercent: 28,
remainingPercent: 72,
resetAfterSeconds: null,
resetAt: null,
category: 'usage',
cadence: '5h',
},
],
planType: 'pro',
lastUpdated: 1,
accountId: 'codex@example.com',
},
},
]);
});
expect(text).toContain('72% remaining');
});
it('renders Gemini CLI remaining percent with a remaining suffix', () => {
const text = captureConsoleLog(() => {
displayGeminiCliQuotaSection([
{
account: 'gemini@example.com',
quota: {
success: true,
buckets: [
{
id: 'gemini-flash-series',
label: 'Gemini Flash Series',
tokenType: null,
remainingFraction: 0.72,
remainingPercent: 72,
resetTime: null,
modelIds: ['gemini-flash'],
},
],
projectId: null,
lastUpdated: 1,
accountId: 'gemini@example.com',
},
},
]);
});
expect(text).toContain('72% remaining');
});
});