mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 12:19:35 +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
|
* labels must be constrained to safe, printable strings before they reach the
|
||||||
* terminal.
|
* terminal.
|
||||||
*/
|
*/
|
||||||
export function sanitizeCodexFeatureLabel(value: unknown): string {
|
export function sanitizeCodexFeatureLabelOrNull(value: unknown): string | null {
|
||||||
if (typeof value !== 'string') return CODEX_FEATURE_LABEL_FALLBACK;
|
if (typeof value !== 'string') return null;
|
||||||
|
|
||||||
const sanitized = value
|
const sanitized = value
|
||||||
.replace(TERMINAL_ESCAPE_SEQUENCE_REGEX, '')
|
.replace(TERMINAL_ESCAPE_SEQUENCE_REGEX, '')
|
||||||
@@ -21,5 +21,9 @@ export function sanitizeCodexFeatureLabel(value: unknown): string {
|
|||||||
.slice(0, CODEX_FEATURE_LABEL_MAX_LENGTH)
|
.slice(0, CODEX_FEATURE_LABEL_MAX_LENGTH)
|
||||||
.trimEnd();
|
.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';
|
} from '../../cliproxy/accounts/account-manager';
|
||||||
import { fetchAllProviderQuotas } from '../../cliproxy/quota/quota-fetcher';
|
import { fetchAllProviderQuotas } from '../../cliproxy/quota/quota-fetcher';
|
||||||
import { fetchAllCodexQuotas } from '../../cliproxy/quota/quota-fetcher-codex';
|
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 { fetchAllClaudeQuotas } from '../../cliproxy/quota/quota-fetcher-claude';
|
||||||
import { pickMostRestrictiveClaudeWeeklyWindow } from '../../cliproxy/quota/quota-fetcher-claude-normalizer';
|
import { pickMostRestrictiveClaudeWeeklyWindow } from '../../cliproxy/quota/quota-fetcher-claude-normalizer';
|
||||||
import { fetchAllGeminiCliQuotas } from '../../cliproxy/quota/quota-fetcher-gemini-cli';
|
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
|
* 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.
|
* remainder into a Codex-prefixed display name. Other labels pass through unchanged.
|
||||||
*/
|
*/
|
||||||
function prettifyCodexFeatureLabel(featureLabel: unknown): string {
|
function prettifyCodexFeatureLabel(featureLabel: unknown, fallbackLabel?: unknown): string {
|
||||||
const trimmed = sanitizeCodexFeatureLabel(featureLabel);
|
const trimmed =
|
||||||
if (!trimmed) return 'Additional';
|
sanitizeCodexFeatureLabelOrNull(featureLabel) ??
|
||||||
|
(fallbackLabel === undefined
|
||||||
|
? sanitizeCodexFeatureLabel(featureLabel)
|
||||||
|
: sanitizeCodexFeatureLabel(fallbackLabel));
|
||||||
const stripped = trimmed.replace(/^GPT-[\d.]+-Codex-/i, '');
|
const stripped = trimmed.replace(/^GPT-[\d.]+-Codex-/i, '');
|
||||||
if (stripped !== trimmed && stripped.length > 0) {
|
if (stripped !== trimmed && stripped.length > 0) {
|
||||||
return `Codex ${stripped}`;
|
return `Codex ${stripped}`;
|
||||||
@@ -303,7 +309,7 @@ function getCodexWindowDisplayLabel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window.category === 'additional') {
|
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 === '5h') return `${pretty} (5h)`;
|
||||||
if (window.cadence === 'weekly') return `${pretty} (weekly)`;
|
if (window.cadence === 'weekly') return `${pretty} (weekly)`;
|
||||||
return pretty;
|
return pretty;
|
||||||
|
|||||||
@@ -86,18 +86,31 @@ describe('cliproxy quota subcommand failure formatting', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('cliproxy quota subcommand Codex label 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 { getCodexWindowDisplayLabel } = await loadQuotaCommandTestExports();
|
||||||
|
|
||||||
const label = getCodexWindowDisplayLabel({
|
const cases = [
|
||||||
label: 'ignored',
|
{ featureLabel: '', cadence: '5h', expected: 'Codex Spark (5h)' },
|
||||||
resetAfterSeconds: 3600,
|
{ featureLabel: ' ', cadence: 'weekly', expected: 'Codex Spark (weekly)' },
|
||||||
category: 'additional',
|
{
|
||||||
cadence: '5h',
|
featureLabel: '\u001b[2J\u001b]52;c;payload\u0007',
|
||||||
featureLabel: { unexpected: true },
|
cadence: '5h',
|
||||||
} as never);
|
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 () => {
|
it('removes terminal control characters from cached Codex feature labels', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user