fix: persist codex target selections

This commit is contained in:
Kai (Tam Nhu) Tran
2026-05-30 14:57:07 -04:00
parent c21f589247
commit 04dc97aaa4
10 changed files with 26 additions and 29 deletions
+1 -1
View File
@@ -136,7 +136,7 @@ export function resolveTargetType(
// 4. Check profile config
if (profileConfig?.target) {
// Persisted targets intentionally exclude runtime-only codex.
// Persisted targets are validated before profile configuration is saved.
return profileConfig.target;
}
+4 -6
View File
@@ -483,9 +483,8 @@ export async function reconcileExhaustedRotationAccounts(
return [];
}
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = await import(
'../accounts/account-safety'
);
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } =
await import('../accounts/account-safety');
restoreExpiredQuotaPauses();
const config = loadOrCreateUnifiedConfig();
@@ -593,9 +592,8 @@ export async function preflightCheck(provider: CLIProxyProvider): Promise<Prefli
return { proceed: true, accountId: defaultAccount?.id || '' };
}
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = await import(
'../accounts/account-safety'
);
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } =
await import('../accounts/account-safety');
restoreExpiredQuotaPauses();
const config = loadOrCreateUnifiedConfig();
+1 -1
View File
@@ -62,7 +62,7 @@ export async function showApiCommandHelp(writeLine: HelpWriter = console.log): P
` ${color('--1m / --no-1m', 'command')} Write or clear [1m] on compatible Claude mappings`
);
writeLine(
` ${color('--target <cli>', 'command')} Default target: claude or droid (create)`
` ${color('--target <cli>', 'command')} Default target: claude, droid, or codex (create)`
);
writeLine(` ${color('--register', 'command')} Register discovered orphan settings`);
writeLine(` ${color('--json', 'command')} JSON output for discover command`);
@@ -112,9 +112,8 @@ export async function runImageAnalysisCheck(results: HealthCheck): Promise<void>
* Fix image analysis configuration issues
*/
export async function fixImageAnalysisConfig(): Promise<boolean> {
const { updateConfig, loadOrCreateUnifiedConfig } = await import(
'../../config/config-loader-facade'
);
const { updateConfig, loadOrCreateUnifiedConfig } =
await import('../../config/config-loader-facade');
const config = loadOrCreateUnifiedConfig();
let fixed = false;
+1 -1
View File
@@ -23,7 +23,7 @@ export const TARGET_METADATA: Record<TargetType, TargetMetadata> = {
displayName: 'Codex CLI',
runtimeAliases: ['ccs-codex', 'ccsx', 'ccsxp'],
legacyAliasEnvVar: 'CCS_CODEX_ALIASES',
persistedTarget: false,
persistedTarget: true,
},
} satisfies Record<TargetType, TargetMetadata>;
+6 -6
View File
@@ -56,7 +56,7 @@ describe('profile reader target sanitization', () => {
}
});
it('normalizes legacy stored codex targets back to claude for profiles and variants', async () => {
it('normalizes legacy invalid stored targets back to claude for profiles and variants', async () => {
const ccsDir = getScopedCcsDir();
fs.mkdirSync(ccsDir, { recursive: true });
fs.writeFileSync(
@@ -64,12 +64,12 @@ describe('profile reader target sanitization', () => {
JSON.stringify(
{
profiles: { demo: '~/.ccs/demo.settings.json' },
profile_targets: { demo: 'codex' },
profile_targets: { demo: 'glm' },
cliproxy: {
routed: {
provider: 'codex',
settings: '~/.ccs/routed.settings.json',
target: 'codex',
target: 'glm',
},
},
},
@@ -94,7 +94,7 @@ describe('profile reader target sanitization', () => {
expect(result.variants[0]?.target).toBe('claude');
});
it('normalizes unified stored codex targets back to claude for profiles and variants', async () => {
it('normalizes unified invalid stored targets back to claude for profiles and variants', async () => {
const ccsDir = getScopedCcsDir();
fs.mkdirSync(ccsDir, { recursive: true });
process.env.CCS_UNIFIED_CONFIG = '1';
@@ -106,7 +106,7 @@ describe('profile reader target sanitization', () => {
' demo:',
' type: api',
' settings: ~/.ccs/demo.settings.json',
' target: codex',
' target: glm',
'cliproxy:',
' oauth_accounts: {}',
' providers: []',
@@ -114,7 +114,7 @@ describe('profile reader target sanitization', () => {
' routed:',
' provider: codex',
' settings: ~/.ccs/routed.settings.json',
' target: codex',
' target: glm',
'',
].join('\n'),
'utf8'
+4 -4
View File
@@ -71,15 +71,15 @@ describe('api-command arg parser', () => {
expect(parsed.target).toBeUndefined();
expect(parsed.errors).toEqual([
'Invalid --target value "invalid-target". Use: claude or droid',
'Invalid --target value "invalid-target". Use: claude, droid, or codex',
]);
});
test('rejects runtime-only codex as a persisted API target value', () => {
test('accepts codex as a persisted API target value', () => {
const parsed = parseApiCommandArgs(['my-api', '--target', 'codex']);
expect(parsed.target).toBeUndefined();
expect(parsed.errors).toEqual(['Invalid --target value "codex". Use: claude or droid']);
expect(parsed.target).toBe('codex');
expect(parsed.errors).toEqual([]);
});
test('collects missing-value error for --target with no value', () => {
@@ -26,11 +26,11 @@ describe('cliproxy variant arg parser', () => {
expect(parsed.errors).toEqual(['Missing value for --target']);
});
test('rejects runtime-only codex as a persisted variant target value', () => {
test('accepts codex as a persisted variant target value', () => {
const parsed = parseProfileArgs(['variant-a', '--target', 'codex']);
expect(parsed.target).toBeUndefined();
expect(parsed.errors).toEqual(['Invalid --target value "codex". Use: claude or droid']);
expect(parsed.target).toBe('codex');
expect(parsed.errors).toEqual([]);
});
test('uses last --target value when repeated', () => {
+2 -2
View File
@@ -68,9 +68,9 @@ describe('resolveTargetType', () => {
expect(resolveTargetType([], { target: 'invalid-target' as never })).toBe('claude');
});
it('should ignore runtime-only codex target when it appears in persisted profile config', () => {
it('should use codex from persisted profile config', () => {
process.argv = ['node', 'ccs'];
expect(resolveTargetType([], { target: 'codex' })).toBe('claude');
expect(resolveTargetType([], { target: 'codex' })).toBe('codex');
});
it('should prioritize --target flag over profile config', () => {
@@ -7,16 +7,16 @@ describe('route target parsing', () => {
it('accepts valid target values', () => {
expect(parseProfileTarget('claude')).toBe('claude');
expect(parseProfileTarget('DROID')).toBe('droid');
expect(parseProfileTarget('codex')).toBe('codex');
expect(parseVariantTarget(' claude ')).toBe('claude');
expect(parseVariantTarget('droid')).toBe('droid');
expect(parseVariantTarget(' codex ')).toBe('codex');
});
it('returns null for invalid target values', () => {
expect(parseProfileTarget('glm')).toBeNull();
expect(parseProfileTarget('codex')).toBeNull();
expect(parseProfileTarget('')).toBeNull();
expect(parseVariantTarget('factory')).toBeNull();
expect(parseVariantTarget('codex')).toBeNull();
expect(parseVariantTarget(' ')).toBeNull();
});