mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 10:16:49 +00:00
fix(cliproxy): fall back from invalid Codex feature labels
This commit is contained in:
@@ -11,8 +11,8 @@ const TERMINAL_CONTROL_CHARS_REGEX = /[\u0000-\u001f\u007f-\u009f]/g;
|
||||
* labels must be constrained to safe, printable strings before they reach the
|
||||
* terminal.
|
||||
*/
|
||||
export function sanitizeCodexFeatureLabel(value: unknown): string {
|
||||
if (typeof value !== 'string') return CODEX_FEATURE_LABEL_FALLBACK;
|
||||
export function sanitizeCodexFeatureLabelOrNull(value: unknown): string | null {
|
||||
if (typeof value !== 'string') return null;
|
||||
|
||||
const sanitized = value
|
||||
.replace(TERMINAL_ESCAPE_SEQUENCE_REGEX, '')
|
||||
@@ -21,5 +21,9 @@ export function sanitizeCodexFeatureLabel(value: unknown): string {
|
||||
.slice(0, CODEX_FEATURE_LABEL_MAX_LENGTH)
|
||||
.trimEnd();
|
||||
|
||||
return sanitized.length > 0 ? sanitized : CODEX_FEATURE_LABEL_FALLBACK;
|
||||
return sanitized.length > 0 ? sanitized : null;
|
||||
}
|
||||
|
||||
export function sanitizeCodexFeatureLabel(value: unknown): string {
|
||||
return sanitizeCodexFeatureLabelOrNull(value) ?? CODEX_FEATURE_LABEL_FALLBACK;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@ import {
|
||||
} from '../../cliproxy/accounts/account-manager';
|
||||
import { fetchAllProviderQuotas } from '../../cliproxy/quota/quota-fetcher';
|
||||
import { fetchAllCodexQuotas } from '../../cliproxy/quota/quota-fetcher-codex';
|
||||
import { sanitizeCodexFeatureLabel } from '../../cliproxy/quota/quota-label-sanitizer';
|
||||
import {
|
||||
sanitizeCodexFeatureLabel,
|
||||
sanitizeCodexFeatureLabelOrNull,
|
||||
} from '../../cliproxy/quota/quota-label-sanitizer';
|
||||
import { fetchAllClaudeQuotas } from '../../cliproxy/quota/quota-fetcher-claude';
|
||||
import { pickMostRestrictiveClaudeWeeklyWindow } from '../../cliproxy/quota/quota-fetcher-claude-normalizer';
|
||||
import { fetchAllGeminiCliQuotas } from '../../cliproxy/quota/quota-fetcher-gemini-cli';
|
||||
@@ -280,9 +283,12 @@ function inferCodeReviewCadence(
|
||||
* Strip a leading "GPT-X.Y-Codex-" prefix from a feature label and turn the
|
||||
* remainder into a Codex-prefixed display name. Other labels pass through unchanged.
|
||||
*/
|
||||
function prettifyCodexFeatureLabel(featureLabel: unknown): string {
|
||||
const trimmed = sanitizeCodexFeatureLabel(featureLabel);
|
||||
if (!trimmed) return 'Additional';
|
||||
function prettifyCodexFeatureLabel(featureLabel: unknown, fallbackLabel?: unknown): string {
|
||||
const trimmed =
|
||||
sanitizeCodexFeatureLabelOrNull(featureLabel) ??
|
||||
(fallbackLabel === undefined
|
||||
? sanitizeCodexFeatureLabel(featureLabel)
|
||||
: sanitizeCodexFeatureLabel(fallbackLabel));
|
||||
const stripped = trimmed.replace(/^GPT-[\d.]+-Codex-/i, '');
|
||||
if (stripped !== trimmed && stripped.length > 0) {
|
||||
return `Codex ${stripped}`;
|
||||
@@ -303,7 +309,7 @@ function getCodexWindowDisplayLabel(
|
||||
}
|
||||
|
||||
if (window.category === 'additional') {
|
||||
const pretty = prettifyCodexFeatureLabel(window.featureLabel ?? window.label);
|
||||
const pretty = prettifyCodexFeatureLabel(window.featureLabel, window.label);
|
||||
if (window.cadence === '5h') return `${pretty} (5h)`;
|
||||
if (window.cadence === 'weekly') return `${pretty} (weekly)`;
|
||||
return pretty;
|
||||
|
||||
@@ -86,18 +86,31 @@ describe('cliproxy quota subcommand failure formatting', () => {
|
||||
});
|
||||
|
||||
describe('cliproxy quota subcommand Codex label formatting', () => {
|
||||
it('falls back for non-string cached Codex feature labels', async () => {
|
||||
it('falls back to the cached window label for invalid Codex feature labels', async () => {
|
||||
const { getCodexWindowDisplayLabel } = await loadQuotaCommandTestExports();
|
||||
|
||||
const label = getCodexWindowDisplayLabel({
|
||||
label: 'ignored',
|
||||
resetAfterSeconds: 3600,
|
||||
category: 'additional',
|
||||
cadence: '5h',
|
||||
featureLabel: { unexpected: true },
|
||||
} as never);
|
||||
const cases = [
|
||||
{ featureLabel: '', cadence: '5h', expected: 'Codex Spark (5h)' },
|
||||
{ featureLabel: ' ', cadence: 'weekly', expected: 'Codex Spark (weekly)' },
|
||||
{
|
||||
featureLabel: '\u001b[2J\u001b]52;c;payload\u0007',
|
||||
cadence: '5h',
|
||||
expected: 'Codex Spark (5h)',
|
||||
},
|
||||
{ featureLabel: { unexpected: true }, cadence: '5h', expected: 'Codex Spark (5h)' },
|
||||
] as const;
|
||||
|
||||
expect(label).toBe('Additional (5h)');
|
||||
for (const { featureLabel, cadence, expected } of cases) {
|
||||
const label = getCodexWindowDisplayLabel({
|
||||
label: 'GPT-5.3-Codex-Spark',
|
||||
resetAfterSeconds: 3600,
|
||||
category: 'additional',
|
||||
cadence,
|
||||
featureLabel,
|
||||
} as never);
|
||||
|
||||
expect(label).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it('removes terminal control characters from cached Codex feature labels', async () => {
|
||||
|
||||
Reference in New Issue
Block a user