mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
feat(cliproxy): add explicit start and restart commands
This commit is contained in:
@@ -229,6 +229,15 @@ ccs cliproxy doctor # Check quota status for all agy accounts
|
||||
|
||||
**Auto-Failover**: When an Antigravity account runs out of quota, CCS automatically switches to another account with remaining capacity. Shared GCP project accounts are excluded (pooled quota).
|
||||
|
||||
### CLIProxy Lifecycle
|
||||
|
||||
```bash
|
||||
ccs cliproxy start # Start CLIProxy background service
|
||||
ccs cliproxy status # Check running status
|
||||
ccs cliproxy restart # Restart CLIProxy service
|
||||
ccs cliproxy stop # Stop running CLIProxy service
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -22,10 +22,12 @@ export {
|
||||
export {
|
||||
getProxyStatus,
|
||||
stopProxy,
|
||||
startProxy,
|
||||
isProxyRunning,
|
||||
getActiveSessionCount,
|
||||
type ProxyStatusResult,
|
||||
type StopProxyResult,
|
||||
type StartProxyResult,
|
||||
} from './proxy-lifecycle-service';
|
||||
|
||||
// Binary management
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
* CLIProxy Proxy Lifecycle Service
|
||||
*
|
||||
* Handles start/stop/status operations for CLIProxy instances.
|
||||
* Delegates to session-tracker for actual process management.
|
||||
* Delegates to session-tracker and service-manager for actual process management.
|
||||
*/
|
||||
|
||||
import {
|
||||
stopProxy as stopProxySession,
|
||||
getProxyStatus as getProxyStatusSession,
|
||||
} from '../session-tracker';
|
||||
import { ensureCliproxyService } from '../service-manager';
|
||||
import { CLIPROXY_DEFAULT_PORT } from '../config-generator';
|
||||
|
||||
/** Proxy status result */
|
||||
export interface ProxyStatusResult {
|
||||
@@ -27,6 +29,15 @@ export interface StopProxyResult {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/** Start proxy result */
|
||||
export interface StartProxyResult {
|
||||
started: boolean;
|
||||
alreadyRunning: boolean;
|
||||
port: number;
|
||||
configRegenerated?: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current proxy status
|
||||
*/
|
||||
@@ -41,6 +52,16 @@ export async function stopProxy(): Promise<StopProxyResult> {
|
||||
return stopProxySession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start CLIProxy service (or reuse existing running instance)
|
||||
*/
|
||||
export async function startProxy(
|
||||
port: number = CLIPROXY_DEFAULT_PORT,
|
||||
verbose: boolean = false
|
||||
): Promise<StartProxyResult> {
|
||||
return ensureCliproxyService(port, verbose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if proxy is currently running
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,8 @@ export async function showHelp(): Promise<void> {
|
||||
[
|
||||
'Proxy Lifecycle:',
|
||||
[
|
||||
['start', 'Start CLIProxy instance in background'],
|
||||
['restart', 'Restart CLIProxy instance'],
|
||||
['status', 'Show running CLIProxy status'],
|
||||
['stop', 'Stop running CLIProxy instance'],
|
||||
['doctor', 'Quota diagnostics and shared project detection'],
|
||||
|
||||
@@ -20,7 +20,12 @@ import {
|
||||
handleResumeAccount,
|
||||
} from './quota-subcommand';
|
||||
import { handleCreate, handleRemove, handleEdit } from './variant-subcommand';
|
||||
import { handleProxyStatus, handleStop } from './proxy-lifecycle-subcommand';
|
||||
import {
|
||||
handleProxyStatus,
|
||||
handleStart,
|
||||
handleStop,
|
||||
handleRestart,
|
||||
} from './proxy-lifecycle-subcommand';
|
||||
import { showStatus, handleInstallVersion, handleInstallLatest } from './install-subcommand';
|
||||
import { showHelp } from './help-subcommand';
|
||||
import {
|
||||
@@ -198,11 +203,21 @@ export async function handleCliproxyCommand(args: string[]): Promise<void> {
|
||||
}
|
||||
|
||||
// Proxy lifecycle commands
|
||||
if (command === 'start') {
|
||||
await handleStart(verbose);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'stop') {
|
||||
await handleStop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'restart') {
|
||||
await handleRestart(verbose);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'status') {
|
||||
await handleProxyStatus();
|
||||
return;
|
||||
|
||||
@@ -2,15 +2,68 @@
|
||||
* CLIProxy Lifecycle Management
|
||||
*
|
||||
* Handles:
|
||||
* - ccs cliproxy start
|
||||
* - ccs cliproxy restart
|
||||
* - ccs cliproxy status
|
||||
* - ccs cliproxy stop
|
||||
*/
|
||||
|
||||
import { initUI, header, color, dim, ok, warn, info } from '../../utils/ui';
|
||||
import { getProxyStatus, stopProxy } from '../../cliproxy/services';
|
||||
import { getProxyStatus, startProxy, stopProxy } from '../../cliproxy/services';
|
||||
import { detectRunningProxy } from '../../cliproxy/proxy-detector';
|
||||
import { CLIPROXY_DEFAULT_PORT } from '../../cliproxy/config-generator';
|
||||
|
||||
export async function handleStart(verbose = false): Promise<void> {
|
||||
await initUI();
|
||||
console.log(header('Start CLIProxy'));
|
||||
console.log('');
|
||||
|
||||
const result = await startProxy(CLIPROXY_DEFAULT_PORT, verbose);
|
||||
if (result.started) {
|
||||
if (result.alreadyRunning) {
|
||||
console.log(info(`CLIProxy already running on port ${result.port}`));
|
||||
if (result.configRegenerated) {
|
||||
console.log(warn('Config updated - restart CLIProxy to apply changes'));
|
||||
}
|
||||
} else {
|
||||
console.log(ok(`CLIProxy started on port ${result.port}`));
|
||||
}
|
||||
console.log(dim('To stop: ccs cliproxy stop'));
|
||||
} else {
|
||||
console.log(warn(result.error || 'Failed to start CLIProxy'));
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
|
||||
export async function handleRestart(verbose = false): Promise<void> {
|
||||
await initUI();
|
||||
console.log(header('Restart CLIProxy'));
|
||||
console.log('');
|
||||
|
||||
const stopResult = await stopProxy();
|
||||
if (stopResult.stopped) {
|
||||
console.log(ok(`CLIProxy stopped (PID ${stopResult.pid})`));
|
||||
} else if (stopResult.error === 'No active CLIProxy session found') {
|
||||
console.log(info('No active CLIProxy session found, starting a new instance'));
|
||||
} else {
|
||||
console.log(warn(stopResult.error || 'Failed to stop existing CLIProxy'));
|
||||
console.log(info('Attempting to start a fresh instance...'));
|
||||
}
|
||||
|
||||
const startResult = await startProxy(CLIPROXY_DEFAULT_PORT, verbose);
|
||||
if (startResult.started) {
|
||||
if (startResult.alreadyRunning) {
|
||||
console.log(info(`CLIProxy already running on port ${startResult.port}`));
|
||||
} else {
|
||||
console.log(ok(`CLIProxy started on port ${startResult.port}`));
|
||||
}
|
||||
} else {
|
||||
console.log(warn(startResult.error || 'Failed to restart CLIProxy'));
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
export async function handleProxyStatus(): Promise<void> {
|
||||
await initUI();
|
||||
console.log(header('CLIProxy Status'));
|
||||
|
||||
@@ -491,6 +491,18 @@ describe('CLIProxy Command - Proxy Lifecycle', () => {
|
||||
});
|
||||
|
||||
describe('Command Routing', () => {
|
||||
it('routes "start" subcommand correctly', () => {
|
||||
const args = ['cliproxy', 'start'];
|
||||
const subcommand = args[1];
|
||||
assert.strictEqual(subcommand, 'start');
|
||||
});
|
||||
|
||||
it('routes "restart" subcommand correctly', () => {
|
||||
const args = ['cliproxy', 'restart'];
|
||||
const subcommand = args[1];
|
||||
assert.strictEqual(subcommand, 'restart');
|
||||
});
|
||||
|
||||
it('routes "stop" subcommand correctly', () => {
|
||||
const args = ['cliproxy', 'stop'];
|
||||
const subcommand = args[1];
|
||||
@@ -504,7 +516,7 @@ describe('CLIProxy Command - Proxy Lifecycle', () => {
|
||||
});
|
||||
|
||||
it('handles unknown subcommand', () => {
|
||||
const validSubcommands = ['stop', 'status', 'create', 'list', 'remove'];
|
||||
const validSubcommands = ['start', 'restart', 'stop', 'status', 'create', 'list', 'remove'];
|
||||
const unknownCommand = 'invalid';
|
||||
assert.strictEqual(validSubcommands.includes(unknownCommand), false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user