feat(cliproxy): add variant port isolation for concurrent proxy instances

Enables running multiple CLIProxy variants simultaneously on different
ports. Each variant now gets a unique port in the 18100-18199 range,
allowing concurrent use of providers like Gemini + Codex + custom variants.

Key changes:
- Add port field to variant config schema
- Implement automatic port allocation (18100 + variant index)
- Support variant-specific settings paths in config generator
- Display port in dashboard UI for debugging
- Show all models in variant editor dropdown
- Add comprehensive tests for port allocation edge cases

Closes related variant isolation work.
This commit is contained in:
kaitranntt committed 2025-12-24 04:15:04 -05:00
1 parent 9d8268b0f6
commit 0bcaf4bc68
23 files changed
+1999 -244

No files matched your search

+8 -3
View File
@@ -256,9 +256,10 @@ async function handleCreate(args: string[]): Promise<void> {
const settingsDisplay = isUnifiedMode()
? '~/.ccs/config.yaml'
: `~/.ccs/${path.basename(result.settingsPath || '')}`;
const portInfo = result.variant?.port ? `Port: ${result.variant.port}\n` : '';
console.log(
infoBox(
`Variant: ${name}\nProvider: ${provider}\nModel: ${model}\n${account ? `Account: ${account}\n` : ''}${isUnifiedMode() ? 'Config' : 'Settings'}: ${settingsDisplay}`,
`Variant: ${name}\nProvider: ${provider}\nModel: ${model}\n${portInfo}${account ? `Account: ${account}\n` : ''}${isUnifiedMode() ? 'Config' : 'Settings'}: ${settingsDisplay}`,
configType
)
);
@@ -303,10 +304,11 @@ async function handleList(): Promise<void> {
console.log(subheader('Custom Variants'));
const rows = variantNames.map((name) => {
const variant = variants[name];
return [name, variant.provider, variant.settings || '-'];
const portStr = variant.port ? String(variant.port) : '-';
return [name, variant.provider, portStr, variant.settings || '-'];
});
console.log(
table(rows, { head: ['Variant', 'Provider', 'Settings'], colWidths: [15, 12, 35] })
table(rows, { head: ['Variant', 'Provider', 'Port', 'Settings'], colWidths: [15, 12, 8, 30] })
);
console.log('');
console.log(dim(`Total: ${variantNames.length} custom variant(s)`));
@@ -357,6 +359,9 @@ async function handleRemove(args: string[]): Promise<void> {
console.log('');
console.log(`Variant '${color(name, 'command')}' will be removed.`);
console.log(` Provider: ${variant.provider}`);
if (variant.port) {
console.log(` Port: ${variant.port}`);
}
console.log(` Settings: ${variant.settings || '-'}`);
console.log('');