daemon.ts
1 /** 2 * CLI commands for daemon lifecycle: 3 * opencli daemon status — show daemon state 4 * opencli daemon stop — graceful shutdown 5 */ 6 7 import { styleText } from 'node:util'; 8 import { fetchDaemonStatus, requestDaemonShutdown } from '../browser/daemon-client.js'; 9 import { formatDuration } from '../download/progress.js'; 10 import { log } from '../logger.js'; 11 12 export async function daemonStatus(): Promise<void> { 13 const status = await fetchDaemonStatus(); 14 if (!status) { 15 console.log(`Daemon: ${styleText('dim', 'not running')}`); 16 return; 17 } 18 19 const extensionLabel = !status.extensionConnected 20 ? styleText('yellow', 'disconnected') 21 : status.extensionVersion 22 ? `${styleText('green', 'connected')} ${styleText('dim', `(v${status.extensionVersion})`)}` 23 : `${styleText('yellow', 'connected')} ${styleText('dim', '(version unknown)')}`; 24 25 console.log(`Daemon: ${styleText('green', 'running')} (PID ${status.pid})`); 26 console.log(`Uptime: ${formatDuration(Math.round(status.uptime * 1000))}`); 27 console.log(`Extension: ${extensionLabel}`); 28 console.log(`Memory: ${status.memoryMB} MB`); 29 console.log(`Port: ${status.port}`); 30 } 31 32 export async function daemonStop(): Promise<void> { 33 const status = await fetchDaemonStatus(); 34 if (!status) { 35 log.info('Daemon is not running.'); 36 return; 37 } 38 39 const ok = await requestDaemonShutdown(); 40 if (ok) { 41 log.success('Daemon stopped.'); 42 } else { 43 log.error('Failed to stop daemon.'); 44 process.exitCode = 1; 45 } 46 }