Enables sortSubcommands on the root program, sessions group, gateway group, and mission group so all subcommand listings render A-Z. Appends a Command Groups section via addHelpText to group commands by role (Runtime, Gateway, Framework, Platform, Runtimes). Implements CU-04-01, CU-04-02, CU-04-03 from mission cli-unification-20260404. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
154 lines
6.2 KiB
TypeScript
154 lines
6.2 KiB
TypeScript
import type { Command } from 'commander';
|
|
import {
|
|
getDaemonPid,
|
|
readMeta,
|
|
startDaemon,
|
|
stopDaemon,
|
|
waitForHealth,
|
|
} from './gateway/daemon.js';
|
|
|
|
interface GatewayParentOpts {
|
|
host: string;
|
|
port: string;
|
|
token?: string;
|
|
}
|
|
|
|
function resolveOpts(raw: GatewayParentOpts): { host: string; port: number; token?: string } {
|
|
const meta = readMeta();
|
|
return {
|
|
host: raw.host ?? meta?.host ?? 'localhost',
|
|
port: parseInt(raw.port, 10) || meta?.port || 14242,
|
|
token: raw.token ?? meta?.adminToken,
|
|
};
|
|
}
|
|
|
|
export function registerGatewayCommand(program: Command): void {
|
|
const gw = program
|
|
.command('gateway')
|
|
.description('Manage the Mosaic gateway daemon')
|
|
.helpOption('--help', 'Display help')
|
|
.option('-h, --host <host>', 'Gateway host', 'localhost')
|
|
.option('-p, --port <port>', 'Gateway port', '14242')
|
|
.option('-t, --token <token>', 'Admin API token')
|
|
.configureHelp({ sortSubcommands: true })
|
|
.action(() => {
|
|
gw.outputHelp();
|
|
});
|
|
|
|
// ─── install ────────────────────────────────────────────────────────────
|
|
|
|
gw.command('install')
|
|
.description('Install and configure the gateway daemon')
|
|
.option('--skip-install', 'Skip npm package installation (use local build)')
|
|
.action(async (cmdOpts: { skipInstall?: boolean }) => {
|
|
const opts = resolveOpts(gw.opts() as GatewayParentOpts);
|
|
const { runInstall } = await import('./gateway/install.js');
|
|
await runInstall({ ...opts, skipInstall: cmdOpts.skipInstall });
|
|
});
|
|
|
|
// ─── start ──────────────────────────────────────────────────────────────
|
|
|
|
gw.command('start')
|
|
.description('Start the gateway daemon')
|
|
.action(async () => {
|
|
const opts = resolveOpts(gw.opts() as GatewayParentOpts);
|
|
try {
|
|
const pid = startDaemon();
|
|
console.log(`Gateway started (PID ${pid.toString()})`);
|
|
console.log('Waiting for health...');
|
|
const healthy = await waitForHealth(opts.host, opts.port);
|
|
if (healthy) {
|
|
console.log(`Gateway ready at http://${opts.host}:${opts.port.toString()}`);
|
|
} else {
|
|
console.warn('Gateway started but health check timed out. Check logs.');
|
|
}
|
|
} catch (err) {
|
|
console.error(err instanceof Error ? err.message : String(err));
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
// ─── stop ───────────────────────────────────────────────────────────────
|
|
|
|
gw.command('stop')
|
|
.description('Stop the gateway daemon')
|
|
.action(async () => {
|
|
try {
|
|
await stopDaemon();
|
|
console.log('Gateway stopped.');
|
|
} catch (err) {
|
|
console.error(err instanceof Error ? err.message : String(err));
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
// ─── restart ────────────────────────────────────────────────────────────
|
|
|
|
gw.command('restart')
|
|
.description('Restart the gateway daemon')
|
|
.action(async () => {
|
|
const opts = resolveOpts(gw.opts() as GatewayParentOpts);
|
|
const pid = getDaemonPid();
|
|
if (pid !== null) {
|
|
console.log('Stopping gateway...');
|
|
await stopDaemon();
|
|
}
|
|
console.log('Starting gateway...');
|
|
try {
|
|
const newPid = startDaemon();
|
|
console.log(`Gateway started (PID ${newPid.toString()})`);
|
|
const healthy = await waitForHealth(opts.host, opts.port);
|
|
if (healthy) {
|
|
console.log(`Gateway ready at http://${opts.host}:${opts.port.toString()}`);
|
|
} else {
|
|
console.warn('Gateway started but health check timed out. Check logs.');
|
|
}
|
|
} catch (err) {
|
|
console.error(err instanceof Error ? err.message : String(err));
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
// ─── status ─────────────────────────────────────────────────────────────
|
|
|
|
gw.command('status')
|
|
.description('Show gateway daemon status and health')
|
|
.action(async () => {
|
|
const opts = resolveOpts(gw.opts() as GatewayParentOpts);
|
|
const { runStatus } = await import('./gateway/status.js');
|
|
await runStatus(opts);
|
|
});
|
|
|
|
// ─── config ─────────────────────────────────────────────────────────────
|
|
|
|
gw.command('config')
|
|
.description('View or modify gateway configuration')
|
|
.option('--set <KEY=VALUE>', 'Set a configuration value')
|
|
.option('--unset <KEY>', 'Remove a configuration key')
|
|
.option('--edit', 'Open config in $EDITOR')
|
|
.action(async (cmdOpts: { set?: string; unset?: string; edit?: boolean }) => {
|
|
const { runConfig } = await import('./gateway/config.js');
|
|
await runConfig(cmdOpts);
|
|
});
|
|
|
|
// ─── logs ───────────────────────────────────────────────────────────────
|
|
|
|
gw.command('logs')
|
|
.description('View gateway daemon logs')
|
|
.option('-f, --follow', 'Follow log output')
|
|
.option('-n, --lines <count>', 'Number of lines to show', '50')
|
|
.action(async (cmdOpts: { follow?: boolean; lines?: string }) => {
|
|
const { runLogs } = await import('./gateway/logs.js');
|
|
runLogs({ follow: cmdOpts.follow, lines: parseInt(cmdOpts.lines ?? '50', 10) });
|
|
});
|
|
|
|
// ─── uninstall ──────────────────────────────────────────────────────────
|
|
|
|
gw.command('uninstall')
|
|
.description('Uninstall the gateway daemon and optionally remove data')
|
|
.action(async () => {
|
|
const { runUninstall } = await import('./gateway/uninstall.js');
|
|
await runUninstall();
|
|
});
|
|
}
|