mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
fix(codex): stabilize code review window labeling
This commit is contained in:
@@ -103,44 +103,59 @@ function getCodexWindowKind(label: string): CodexWindowKind {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
function getCodexWindowCadence(
|
||||
resetAfterSeconds: number | null | undefined
|
||||
): '5h' | 'weekly' | null {
|
||||
if (
|
||||
typeof resetAfterSeconds !== 'number' ||
|
||||
!isFinite(resetAfterSeconds) ||
|
||||
resetAfterSeconds <= 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
type CodexWindowSummary = Pick<CodexQuotaResult['windows'][number], 'label' | 'resetAfterSeconds'>;
|
||||
|
||||
if (resetAfterSeconds <= 6 * 60 * 60) return '5h';
|
||||
if (resetAfterSeconds >= 24 * 60 * 60) return 'weekly';
|
||||
return null;
|
||||
function inferCodeReviewCadence(
|
||||
window: CodexWindowSummary,
|
||||
allWindows: CodexWindowSummary[]
|
||||
): '5h' | 'weekly' | null {
|
||||
const kind = getCodexWindowKind(window.label);
|
||||
if (kind === 'code-review-weekly') return 'weekly';
|
||||
|
||||
const reset = window.resetAfterSeconds;
|
||||
if (typeof reset !== 'number' || !isFinite(reset) || reset <= 0) return null;
|
||||
|
||||
const usage5h = allWindows.find(
|
||||
(w) =>
|
||||
getCodexWindowKind(w.label) === 'usage-5h' &&
|
||||
typeof w.resetAfterSeconds === 'number' &&
|
||||
isFinite(w.resetAfterSeconds) &&
|
||||
w.resetAfterSeconds > 0
|
||||
);
|
||||
const usageWeekly = allWindows.find(
|
||||
(w) =>
|
||||
getCodexWindowKind(w.label) === 'usage-weekly' &&
|
||||
typeof w.resetAfterSeconds === 'number' &&
|
||||
isFinite(w.resetAfterSeconds) &&
|
||||
w.resetAfterSeconds > 0
|
||||
);
|
||||
|
||||
if (!usage5h || !usageWeekly) return null;
|
||||
|
||||
const diffTo5h = Math.abs(reset - (usage5h.resetAfterSeconds as number));
|
||||
const diffToWeekly = Math.abs(reset - (usageWeekly.resetAfterSeconds as number));
|
||||
return diffToWeekly <= diffTo5h ? 'weekly' : '5h';
|
||||
}
|
||||
|
||||
function getCodexWindowDisplayLabel(
|
||||
window: Pick<CodexQuotaResult['windows'][number], 'label' | 'resetAfterSeconds'>
|
||||
window: CodexWindowSummary,
|
||||
allWindows: CodexWindowSummary[] = []
|
||||
): string {
|
||||
const cadence = getCodexWindowCadence(window.resetAfterSeconds);
|
||||
const context = allWindows.length > 0 ? allWindows : [window];
|
||||
|
||||
switch (getCodexWindowKind(window.label)) {
|
||||
case 'usage-5h':
|
||||
if (cadence === 'weekly') return 'Weekly usage limit';
|
||||
return '5h usage limit';
|
||||
case 'usage-weekly':
|
||||
if (cadence === '5h') return '5h usage limit';
|
||||
return 'Weekly usage limit';
|
||||
case 'code-review-5h':
|
||||
if (cadence === 'weekly') return 'Code review (weekly)';
|
||||
return 'Code review (5h)';
|
||||
case 'code-review-weekly':
|
||||
if (cadence === '5h') return 'Code review (5h)';
|
||||
return 'Code review (weekly)';
|
||||
case 'code-review':
|
||||
if (cadence === '5h') return 'Code review (5h)';
|
||||
if (cadence === 'weekly') return 'Code review (weekly)';
|
||||
case 'code-review': {
|
||||
const inferred = inferCodeReviewCadence(window, context);
|
||||
if (inferred === '5h') return 'Code review (5h)';
|
||||
if (inferred === 'weekly') return 'Code review (weekly)';
|
||||
return 'Code review';
|
||||
}
|
||||
case 'unknown':
|
||||
return window.label;
|
||||
}
|
||||
@@ -281,7 +296,7 @@ function displayCodexQuotaSection(results: { account: string; quota: CodexQuotaR
|
||||
? dim(` Resets ${formatResetTime(window.resetAfterSeconds)}`)
|
||||
: '';
|
||||
console.log(
|
||||
` ${getCodexWindowDisplayLabel(window).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}%${resetLabel}`
|
||||
` ${getCodexWindowDisplayLabel(window, orderedWindows).padEnd(24)} ${bar} ${window.remainingPercent.toFixed(0)}%${resetLabel}`
|
||||
);
|
||||
}
|
||||
console.log('');
|
||||
|
||||
@@ -87,7 +87,7 @@ export function QuotaTooltipContent({ quota, resetTime }: QuotaTooltipContentPro
|
||||
className="flex justify-between gap-4"
|
||||
>
|
||||
<span className={cn(w.remainingPercent < 20 && 'text-red-500')}>
|
||||
{getCodexWindowDisplayLabel(w)}
|
||||
{getCodexWindowDisplayLabel(w, orderedWindows)}
|
||||
</span>
|
||||
<span className="font-mono">{w.remainingPercent}%</span>
|
||||
</div>
|
||||
|
||||
+47
-30
@@ -334,51 +334,68 @@ export function getCodexWindowKind(label: string): CodexWindowKind {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert raw Codex window labels into user-facing labels.
|
||||
*/
|
||||
function getCodexWindowCadence(
|
||||
resetAfterSeconds: number | null | undefined
|
||||
): '5h' | 'weekly' | null {
|
||||
if (
|
||||
typeof resetAfterSeconds !== 'number' ||
|
||||
!isFinite(resetAfterSeconds) ||
|
||||
resetAfterSeconds <= 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
type CodexWindowSummary = Pick<CodexQuotaWindow, 'label' | 'resetAfterSeconds'>;
|
||||
|
||||
if (resetAfterSeconds <= 6 * 60 * 60) return '5h';
|
||||
if (resetAfterSeconds >= 24 * 60 * 60) return 'weekly';
|
||||
return null;
|
||||
/**
|
||||
* Infer code-review window cadence by comparing against usage windows.
|
||||
* This keeps labels stable as countdown values decrease over time.
|
||||
*/
|
||||
function inferCodeReviewCadence(
|
||||
window: CodexWindowSummary,
|
||||
allWindows: CodexWindowSummary[]
|
||||
): '5h' | 'weekly' | null {
|
||||
const kind = getCodexWindowKind(window.label);
|
||||
if (kind === 'code-review-weekly') return 'weekly';
|
||||
|
||||
const reset = window.resetAfterSeconds;
|
||||
if (typeof reset !== 'number' || !isFinite(reset) || reset <= 0) return null;
|
||||
|
||||
const usage5h = allWindows.find(
|
||||
(w) =>
|
||||
getCodexWindowKind(w.label) === 'usage-5h' &&
|
||||
typeof w.resetAfterSeconds === 'number' &&
|
||||
isFinite(w.resetAfterSeconds) &&
|
||||
w.resetAfterSeconds > 0
|
||||
);
|
||||
const usageWeekly = allWindows.find(
|
||||
(w) =>
|
||||
getCodexWindowKind(w.label) === 'usage-weekly' &&
|
||||
typeof w.resetAfterSeconds === 'number' &&
|
||||
isFinite(w.resetAfterSeconds) &&
|
||||
w.resetAfterSeconds > 0
|
||||
);
|
||||
|
||||
if (!usage5h || !usageWeekly) return null;
|
||||
|
||||
const diffTo5h = Math.abs(reset - (usage5h.resetAfterSeconds as number));
|
||||
const diffToWeekly = Math.abs(reset - (usageWeekly.resetAfterSeconds as number));
|
||||
return diffToWeekly <= diffTo5h ? 'weekly' : '5h';
|
||||
}
|
||||
|
||||
export function getCodexWindowDisplayLabel(
|
||||
labelOrWindow: string | Pick<CodexQuotaWindow, 'label' | 'resetAfterSeconds'>,
|
||||
resetAfterSecondsOverride?: number | null
|
||||
labelOrWindow: string | CodexWindowSummary,
|
||||
allWindows: CodexWindowSummary[] = []
|
||||
): string {
|
||||
const label = typeof labelOrWindow === 'string' ? labelOrWindow : labelOrWindow.label;
|
||||
const cadence = getCodexWindowCadence(
|
||||
typeof labelOrWindow === 'string' ? resetAfterSecondsOverride : labelOrWindow.resetAfterSeconds
|
||||
);
|
||||
const currentWindow: CodexWindowSummary =
|
||||
typeof labelOrWindow === 'string'
|
||||
? { label, resetAfterSeconds: null }
|
||||
: { label, resetAfterSeconds: labelOrWindow.resetAfterSeconds };
|
||||
const context = allWindows.length > 0 ? allWindows : [currentWindow];
|
||||
|
||||
switch (getCodexWindowKind(label)) {
|
||||
case 'usage-5h':
|
||||
if (cadence === 'weekly') return 'Weekly usage limit';
|
||||
return '5h usage limit';
|
||||
case 'usage-weekly':
|
||||
if (cadence === '5h') return '5h usage limit';
|
||||
return 'Weekly usage limit';
|
||||
case 'code-review-5h':
|
||||
if (cadence === 'weekly') return 'Code review (weekly)';
|
||||
return 'Code review (5h)';
|
||||
case 'code-review-weekly':
|
||||
if (cadence === '5h') return 'Code review (5h)';
|
||||
return 'Code review (weekly)';
|
||||
case 'code-review':
|
||||
if (cadence === '5h') return 'Code review (5h)';
|
||||
if (cadence === 'weekly') return 'Code review (weekly)';
|
||||
case 'code-review': {
|
||||
const inferred = inferCodeReviewCadence(currentWindow, context);
|
||||
if (inferred === '5h') return 'Code review (5h)';
|
||||
if (inferred === 'weekly') return 'Code review (weekly)';
|
||||
return 'Code review';
|
||||
}
|
||||
case 'unknown':
|
||||
return label;
|
||||
}
|
||||
|
||||
@@ -528,21 +528,37 @@ describe('getCodexResetTime', () => {
|
||||
});
|
||||
|
||||
describe('getCodexWindowDisplayLabel', () => {
|
||||
it('labels code review primary window as weekly when reset cadence is weekly', () => {
|
||||
it('labels code review primary as weekly when it matches usage weekly window', () => {
|
||||
const windows: Array<{ label: string; resetAfterSeconds: number | null }> = [
|
||||
{ label: 'Primary', resetAfterSeconds: 18000 },
|
||||
{ label: 'Secondary', resetAfterSeconds: 604800 },
|
||||
{ label: 'Code Review (Primary)', resetAfterSeconds: 600000 },
|
||||
];
|
||||
expect(
|
||||
getCodexWindowDisplayLabel({
|
||||
label: 'Code Review (Primary)',
|
||||
resetAfterSeconds: 604800,
|
||||
})
|
||||
getCodexWindowDisplayLabel(
|
||||
{
|
||||
label: 'Code Review (Primary)',
|
||||
resetAfterSeconds: 600000,
|
||||
},
|
||||
windows
|
||||
)
|
||||
).toBe('Code review (weekly)');
|
||||
});
|
||||
|
||||
it('labels code review primary window as 5h when reset cadence is short', () => {
|
||||
it('labels code review primary as 5h when it matches usage 5h window', () => {
|
||||
const windows: Array<{ label: string; resetAfterSeconds: number | null }> = [
|
||||
{ label: 'Primary', resetAfterSeconds: 18000 },
|
||||
{ label: 'Secondary', resetAfterSeconds: 604800 },
|
||||
{ label: 'Code Review (Primary)', resetAfterSeconds: 17000 },
|
||||
];
|
||||
expect(
|
||||
getCodexWindowDisplayLabel({
|
||||
label: 'Code Review (Primary)',
|
||||
resetAfterSeconds: 18000,
|
||||
})
|
||||
getCodexWindowDisplayLabel(
|
||||
{
|
||||
label: 'Code Review (Primary)',
|
||||
resetAfterSeconds: 17000,
|
||||
},
|
||||
windows
|
||||
)
|
||||
).toBe('Code review (5h)');
|
||||
});
|
||||
|
||||
@@ -550,8 +566,13 @@ describe('getCodexWindowDisplayLabel', () => {
|
||||
expect(getCodexWindowDisplayLabel('Secondary')).toBe('Weekly usage limit');
|
||||
});
|
||||
|
||||
it('uses cadence override when provided with string label', () => {
|
||||
expect(getCodexWindowDisplayLabel('Primary', 604800)).toBe('Weekly usage limit');
|
||||
it('falls back to generic code review label when cadence cannot be inferred', () => {
|
||||
expect(
|
||||
getCodexWindowDisplayLabel({
|
||||
label: 'Code Review (Primary)',
|
||||
resetAfterSeconds: 604800,
|
||||
})
|
||||
).toBe('Code review');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user