import * as plugins from '../../../plugins.js'; import * as paths from '../../../paths.js'; import { tspmIpcClient } from '../../../classes.ipcclient.js'; import { Logger } from '../../../utils.errorhandler.js'; import type { CliArguments } from '../../types.js'; import { formatMemory } from '../../helpers/memory.js'; export function registerDaemonCommand(smartcli: plugins.smartcli.Smartcli) { const cliLogger = new Logger('CLI'); smartcli.addCommand('daemon').subscribe({ next: async (argvArg: CliArguments) => { const subCommand = argvArg._[1]; switch (subCommand) { case 'start': try { const status = await tspmIpcClient.getDaemonStatus(); if (status) { console.log('TSPM daemon is already running'); console.log(` PID: ${status.pid}`); console.log( ` Uptime: ${Math.floor((status.uptime || 0) / 1000)}s`, ); console.log(` Processes: ${status.processCount}`); return; } console.log('Starting TSPM daemon manually...'); // Import spawn to start daemon process const { spawn } = await import('child_process'); const daemonScript = plugins.path.join( paths.packageDir, 'dist_ts', 'daemon.js', ); // Start daemon as a detached background process const daemonProcess = spawn(process.execPath, [daemonScript], { detached: true, stdio: 'ignore', env: { ...process.env, TSPM_DAEMON_MODE: 'true', }, }); // Detach the daemon so it continues running after CLI exits daemonProcess.unref(); console.log(`Started daemon with PID: ${daemonProcess.pid}`); // Wait for daemon to be ready await new Promise((resolve) => setTimeout(resolve, 2000)); const newStatus = await tspmIpcClient.getDaemonStatus(); if (newStatus) { console.log('✓ TSPM daemon started successfully'); console.log(` PID: ${newStatus.pid}`); console.log( '\nNote: This daemon will run until you stop it or logout.', ); console.log('For automatic startup, use "tspm enable" instead.'); } // Disconnect from the daemon after starting await tspmIpcClient.disconnect(); } catch (error) { console.error('Error starting daemon:', error.message); process.exit(1); } break; case 'start-service': // This is called by systemd - start the daemon directly console.log('Starting TSPM daemon for systemd service...'); const { startDaemon } = await import('../../../classes.daemon.js'); await startDaemon(); break; case 'stop': try { console.log('Stopping TSPM daemon...'); await tspmIpcClient.stopDaemon(true); console.log('✓ TSPM daemon stopped successfully'); // Disconnect from the daemon after stopping await tspmIpcClient.disconnect(); } catch (error) { console.error('Error stopping daemon:', error.message); process.exit(1); } break; case 'status': try { const status = await tspmIpcClient.getDaemonStatus(); if (!status) { console.log('TSPM daemon is not running'); console.log('Use "tspm daemon start" to start it'); return; } console.log('TSPM Daemon Status:'); console.log('─'.repeat(40)); console.log(`Status: ${status.status}`); console.log(`PID: ${status.pid}`); console.log( `Uptime: ${Math.floor((status.uptime || 0) / 1000)}s`, ); console.log(`Processes: ${status.processCount}`); console.log( `Memory: ${formatMemory(status.memoryUsage || 0)}`, ); console.log(`CPU: ${status.cpuUsage?.toFixed(1) || 0}s`); // Disconnect from daemon after getting status await tspmIpcClient.disconnect(); } catch (error) { console.error('Error getting daemon status:', error.message); process.exit(1); } break; default: console.log('Usage: tspm daemon '); console.log('\nCommands:'); console.log(' start Start the TSPM daemon'); console.log(' stop Stop the TSPM daemon'); console.log(' status Show daemon status'); break; } }, error: (err) => { cliLogger.error(err); }, complete: () => {}, }); }