Merge pull request #1452 from kaitranntt/codex/propose-fix-for-codex-target-rejection

Mark Codex as a persisted target and align UI/validation
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-05-30 16:12:03 -04:00
commit e7db1d65f5
8 files changed
+20 -20

No files matched your search

+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;
}
+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`);
+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();
});