mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 04:18:05 +00:00
fix(proxy): disambiguate activate without profile
This commit is contained in:
@@ -22,6 +22,20 @@ function parseOptionValue(args: string[], key: string): string | undefined {
|
||||
return withEquals ? withEquals.slice(prefix.length) : undefined;
|
||||
}
|
||||
|
||||
function findPositionalArg(args: string[], optionsWithValues: string[] = []): string | undefined {
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const arg = args[i];
|
||||
if (arg.startsWith('-')) {
|
||||
if (optionsWithValues.includes(arg)) {
|
||||
i += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function showHelp(): number {
|
||||
console.log('OpenAI-Compatible Proxy');
|
||||
console.log('');
|
||||
@@ -63,7 +77,7 @@ function resolveProfile(profileName: string) {
|
||||
}
|
||||
|
||||
async function handleStart(args: string[]): Promise<number> {
|
||||
const profileName = args.find((arg) => !arg.startsWith('-'));
|
||||
const profileName = findPositionalArg(args, ['--port', '--host']);
|
||||
if (!profileName) {
|
||||
console.error(
|
||||
fail('Usage: ccs proxy start <profile> [--port <n>] [--host <addr>] [--insecure]')
|
||||
@@ -102,7 +116,7 @@ async function handleStart(args: string[]): Promise<number> {
|
||||
}
|
||||
|
||||
async function handleStatus(args: string[] = []): Promise<number> {
|
||||
const profileName = args.find((arg) => !arg.startsWith('-'));
|
||||
const profileName = findPositionalArg(args);
|
||||
const running = profileName
|
||||
? [await getOpenAICompatProxyStatus(profileName)].filter((status) => status.running)
|
||||
: (await listOpenAICompatProxyStatuses()).filter((status) => status.running);
|
||||
@@ -130,12 +144,7 @@ async function handleStatus(args: string[] = []): Promise<number> {
|
||||
}
|
||||
|
||||
async function handleActivate(args: string[]): Promise<number> {
|
||||
const profileName = args.find((arg) => !arg.startsWith('-'));
|
||||
const status = await getOpenAICompatProxyStatus(profileName);
|
||||
if (!status.running || !status.profileName || !status.port || !status.authToken) {
|
||||
console.error(fail('Proxy is not running. Start it with: ccs proxy start <profile>'));
|
||||
return 1;
|
||||
}
|
||||
const profileName = findPositionalArg(args, ['--shell']);
|
||||
if (!profileName) {
|
||||
const running = (await listOpenAICompatProxyStatuses()).filter((entry) => entry.running);
|
||||
if (running.length > 1) {
|
||||
@@ -145,6 +154,11 @@ async function handleActivate(args: string[]): Promise<number> {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
const status = await getOpenAICompatProxyStatus(profileName);
|
||||
if (!status.running || !status.profileName || !status.port || !status.authToken) {
|
||||
console.error(fail('Proxy is not running. Start it with: ccs proxy start <profile>'));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const shell = detectShell(args.includes('--fish') ? 'fish' : parseOptionValue(args, '--shell'));
|
||||
let profile;
|
||||
|
||||
@@ -185,7 +185,7 @@ export async function getOpenAICompatProxyStatus(
|
||||
const statuses = await listOpenAICompatProxyStatuses();
|
||||
const running = statuses.filter((status) => status.running);
|
||||
if (running.length === 1) {
|
||||
return running[0] || { running: false };
|
||||
return running[0];
|
||||
}
|
||||
if (running.length > 1) {
|
||||
return { running: true };
|
||||
|
||||
@@ -107,4 +107,50 @@ describe('proxy command e2e', () => {
|
||||
const stopped = runCli(['proxy', 'stop']);
|
||||
expect(stopped.status).toBe(0);
|
||||
}, 35000);
|
||||
|
||||
it('requires an explicit profile when activating with multiple running proxies', async () => {
|
||||
const firstPort = await getPort();
|
||||
const ccsDir = path.join(tempDir, '.ccs');
|
||||
fs.mkdirSync(ccsDir, { recursive: true });
|
||||
const firstSettingsPath = path.join(ccsDir, 'ccg.settings.json');
|
||||
const secondSettingsPath = path.join(ccsDir, 'ccgm.settings.json');
|
||||
fs.writeFileSync(
|
||||
path.join(ccsDir, 'config.json'),
|
||||
JSON.stringify({ profiles: { ccg: firstSettingsPath, ccgm: secondSettingsPath } }, null, 2),
|
||||
'utf8'
|
||||
);
|
||||
fs.writeFileSync(
|
||||
firstSettingsPath,
|
||||
JSON.stringify({
|
||||
env: {
|
||||
ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
|
||||
ANTHROPIC_AUTH_TOKEN: 'ollama-ccg',
|
||||
ANTHROPIC_MODEL: 'qwen3-coder',
|
||||
CCS_DROID_PROVIDER: 'generic-chat-completion-api',
|
||||
},
|
||||
}),
|
||||
'utf8'
|
||||
);
|
||||
fs.writeFileSync(
|
||||
secondSettingsPath,
|
||||
JSON.stringify({
|
||||
env: {
|
||||
ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
|
||||
ANTHROPIC_AUTH_TOKEN: 'sk-ccgm',
|
||||
ANTHROPIC_MODEL: 'gpt-4.1',
|
||||
},
|
||||
}),
|
||||
'utf8'
|
||||
);
|
||||
|
||||
expect(runCli(['proxy', 'start', 'ccg', '--port', String(firstPort)]).status).toBe(0);
|
||||
const secondPort = await getPort();
|
||||
expect(runCli(['proxy', 'start', 'ccgm', '--port', String(secondPort)]).status).toBe(0);
|
||||
|
||||
const activate = runCli(['proxy', 'activate', '--shell', 'bash']);
|
||||
expect(activate.status).toBe(1);
|
||||
expect(activate.stderr).toContain(
|
||||
'Multiple proxies are running. Specify a profile: ccs proxy activate <profile>'
|
||||
);
|
||||
}, 35000);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user