Merge pull request #1074 from kaitranntt/kai/feat/1073-adaptive-proxy-ports

feat(proxy): add adaptive local port selection for OpenAI-compatible profiles
This commit is contained in:
Kai (Tam Nhu) Tran
2026-04-23 16:37:05 -04:00
committed by GitHub
11 changed files with 429 additions and 111 deletions
+14 -2
View File
@@ -64,7 +64,7 @@ function showHelp(): number {
console.log(' activate [profile] Print shell exports for the running proxy');
console.log('');
console.log('Options:');
console.log(' --port <n> Override the local proxy port (default: 3456)');
console.log(' --port <n> Pin an exact local proxy port for this launch');
console.log(' --host <addr> Bind the proxy server to a specific host (default: 127.0.0.1)');
console.log(' --shell <name> activate only: auto|bash|zsh|fish|powershell');
console.log(' --fish activate only: shorthand for --shell fish');
@@ -104,7 +104,19 @@ async function handleStart(args: string[]): Promise<number> {
const portValue = parseOptionValue(args, '--port');
const host = parseOptionValue(args, '--host');
const port = portValue ? Number.parseInt(portValue, 10) || 3456 : undefined;
const parsedPort = portValue ? Number(portValue) : undefined;
if (
portValue &&
(parsedPort === undefined ||
!/^\d+$/.test(portValue) ||
!Number.isInteger(parsedPort) ||
parsedPort < 1 ||
parsedPort > 65535)
) {
console.error(fail(`Invalid port: ${portValue}`));
return 1;
}
const port = parsedPort;
let profile;
try {
profile = resolveProfile(profileName);
-1
View File
@@ -1006,7 +1006,6 @@ export const DEFAULT_CLIPROXY_SERVER_CONFIG: CliproxyServerConfig = {
};
export const DEFAULT_OPENAI_COMPAT_PROXY_CONFIG: OpenAICompatProxyConfig = {
port: 3456,
profile_ports: {},
routing: {
longContextThreshold: 60_000,
+2 -1
View File
@@ -1,5 +1,6 @@
import { loadSettings } from '../utils/config-manager';
import { resolveOpenAICompatProfileConfig } from './profile-router';
import { OPENAI_COMPAT_PROXY_DEFAULT_PORT } from './proxy-daemon-paths';
import { startOpenAICompatProxyServer } from './server/proxy-server';
interface RuntimeOptions {
@@ -12,7 +13,7 @@ interface RuntimeOptions {
}
function parseArgs(argv: string[]): RuntimeOptions {
let port = 3456;
let port = OPENAI_COMPAT_PROXY_DEFAULT_PORT;
let host = '127.0.0.1';
let profileName = '';
let settingsPath = '';
+4 -1
View File
@@ -1,7 +1,10 @@
import * as path from 'path';
import { getCcsDir } from '../utils/config-manager';
export const OPENAI_COMPAT_PROXY_DEFAULT_PORT = 3456;
export const OPENAI_COMPAT_PROXY_LEGACY_DEFAULT_PORT = 3456;
export const OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START = 43_456;
export const OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_END = 43_555;
export const OPENAI_COMPAT_PROXY_DEFAULT_PORT = OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START;
export const OPENAI_COMPAT_PROXY_SERVICE_NAME = 'ccs-openai-compat-proxy';
export function getOpenAICompatProxyDir(): string {
+28 -25
View File
@@ -6,7 +6,8 @@ import * as lockfile from 'proper-lockfile';
import { verifyProcessOwnership } from '../cursor/daemon-process-ownership';
import type { OpenAICompatProfileConfig } from './profile-router';
import {
OPENAI_COMPAT_PROXY_DEFAULT_PORT,
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_END,
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START,
OPENAI_COMPAT_PROXY_SERVICE_NAME,
getOpenAICompatProxyDir,
} from './proxy-daemon-paths';
@@ -25,7 +26,10 @@ import {
writeOpenAICompatProxyPid,
writeOpenAICompatProxySession,
} from './proxy-daemon-state';
import { resolveOpenAICompatProxyPortPreference } from './proxy-port-resolver';
import {
listOpenAICompatProxyCandidatePorts as listFlexibleOpenAICompatProxyCandidatePorts,
resolveOpenAICompatProxyPortPreference,
} from './proxy-port-resolver';
export interface OpenAICompatProxyStatus extends Partial<OpenAICompatProxySession> {
running: boolean;
@@ -131,6 +135,7 @@ async function terminateDaemonProcess(pid?: number): Promise<void> {
}
function listOpenAICompatProxyCandidatePorts(
profileName: string,
preferredPort: number,
exact: boolean,
excludedPorts: ReadonlySet<number> = new Set()
@@ -139,22 +144,7 @@ function listOpenAICompatProxyCandidatePorts(
return excludedPorts.has(preferredPort) ? [] : [preferredPort];
}
const candidates = new Set<number>();
if (!excludedPorts.has(preferredPort)) {
candidates.add(preferredPort);
}
for (
let candidate = OPENAI_COMPAT_PROXY_DEFAULT_PORT;
candidate <= OPENAI_COMPAT_PROXY_DEFAULT_PORT + 10;
candidate += 1
) {
if (!excludedPorts.has(candidate)) {
candidates.add(candidate);
}
}
return [...candidates];
return listFlexibleOpenAICompatProxyCandidatePorts(profileName, preferredPort, excludedPorts);
}
function isPortBindConflictMessage(message?: string): boolean {
@@ -494,12 +484,24 @@ export async function startOpenAICompatProxy(
const host = options.host?.trim() || status.host || '127.0.0.1';
const portPreference = resolveOpenAICompatProxyPortPreference(profile.profileName);
const explicitPort = typeof options.port === 'number' ? options.port : undefined;
const preferredPort =
explicitPort ??
(portPreference.source === 'profile'
? portPreference.port
: status.port || portPreference.port);
const requiresExactPort = explicitPort !== undefined || portPreference.source === 'profile';
if (
status.running &&
explicitPort === undefined &&
portPreference.source !== 'profile' &&
status.port &&
(status.host || '127.0.0.1') === host
) {
return {
success: true,
alreadyRunning: true,
pid: status.pid,
port: status.port,
authToken: status.authToken,
};
}
const preferredPort = explicitPort ?? portPreference.port;
if (status.running && status.port === preferredPort && (status.host || '127.0.0.1') === host) {
return {
success: true,
@@ -670,6 +672,7 @@ export async function startOpenAICompatProxy(
const attemptedPorts = new Set<number>();
let lastResult: OpenAICompatProxyLaunchResult | null = null;
const candidates = listOpenAICompatProxyCandidatePorts(
profile.profileName,
preferredPort,
requiresExactPort,
attemptedPorts
@@ -678,7 +681,7 @@ export async function startOpenAICompatProxy(
return {
success: false,
port: preferredPort,
error: `No free proxy port found in range ${OPENAI_COMPAT_PROXY_DEFAULT_PORT}-${OPENAI_COMPAT_PROXY_DEFAULT_PORT + 10}`,
error: `No free proxy port found in adaptive range ${OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START}-${OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_END}`,
};
}
@@ -707,7 +710,7 @@ export async function startOpenAICompatProxy(
port: preferredPort,
error: requiresExactPort
? `Requested proxy port ${preferredPort} is already in use`
: 'No free proxy port found in the proxy port range',
: 'No free proxy port found in the adaptive proxy port range',
}
);
};
+60 -4
View File
@@ -1,9 +1,55 @@
import { loadOrCreateUnifiedConfig } from '../config/unified-config-loader';
import { OPENAI_COMPAT_PROXY_DEFAULT_PORT } from './proxy-daemon-paths';
import {
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_END,
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START,
OPENAI_COMPAT_PROXY_LEGACY_DEFAULT_PORT,
} from './proxy-daemon-paths';
export interface OpenAICompatProxyPortPreference {
port: number;
source: 'default' | 'profile';
source: 'adaptive' | 'profile' | 'shared';
}
const ADAPTIVE_PORT_RANGE_SIZE =
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_END - OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START + 1;
function hashProfileName(profileName: string): number {
let hash = 0;
for (const char of profileName.trim()) {
hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
}
return hash;
}
export function resolveOpenAICompatProxyAdaptivePort(profileName: string): number {
return (
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START +
(hashProfileName(profileName) % ADAPTIVE_PORT_RANGE_SIZE)
);
}
export function listOpenAICompatProxyCandidatePorts(
profileName: string,
preferredPort: number,
excludedPorts: ReadonlySet<number> = new Set()
): number[] {
const candidates = new Set<number>();
if (!excludedPorts.has(preferredPort)) {
candidates.add(preferredPort);
}
const adaptiveStart = resolveOpenAICompatProxyAdaptivePort(profileName);
for (let offset = 0; offset < ADAPTIVE_PORT_RANGE_SIZE; offset += 1) {
const candidate =
OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START +
((adaptiveStart - OPENAI_COMPAT_PROXY_ADAPTIVE_PORT_START + offset) %
ADAPTIVE_PORT_RANGE_SIZE);
if (!excludedPorts.has(candidate)) {
candidates.add(candidate);
}
}
return [...candidates];
}
export function resolveOpenAICompatProxyPortPreference(
@@ -14,9 +60,19 @@ export function resolveOpenAICompatProxyPortPreference(
if (typeof profilePort === 'number') {
return { port: profilePort, source: 'profile' };
}
const sharedPort = config.proxy?.port;
if (typeof sharedPort === 'number') {
if (sharedPort === OPENAI_COMPAT_PROXY_LEGACY_DEFAULT_PORT) {
return {
port: resolveOpenAICompatProxyAdaptivePort(profileName),
source: 'adaptive',
};
}
return { port: sharedPort, source: 'shared' };
}
return {
port: config.proxy?.port ?? OPENAI_COMPAT_PROXY_DEFAULT_PORT,
source: 'default',
port: resolveOpenAICompatProxyAdaptivePort(profileName),
source: 'adaptive',
};
}