diff --git a/.tspm_home/.npmextra/kv/@git.zone__tspm.json b/.tspm_home/.npmextra/kv/@git.zone__tspm.json new file mode 100644 index 0000000..e69de29 diff --git a/changelog.md b/changelog.md index 3bbc9fb..010b42c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-08-29 - 4.4.2 - fix(daemon) +Fix daemon IPC id handling, reload configs on demand and correct CLI daemon start path + +- Normalize process IDs in daemon IPC handlers (trim strings) to avoid lookup mismatches +- Attempt to reload saved process configurations when a startById request cannot find a config (handles races/stale state) +- Use normalized IDs in responses and messages for stop/restart/delete/remove/describe handlers +- Fix CLI daemon start path to point at dist_ts/daemon/tspm.daemon.js when launching the background daemon +- Ensure the IPC client disconnects after showing CLI version/status to avoid leaked connections + ## 2025-08-29 - 4.4.1 - fix(cli) Use server-side start-by-id flow for starting processes diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index d7eaac4..afc6976 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tspm', - version: '4.4.1', + version: '4.4.2', description: 'a no fuzz process manager' } diff --git a/ts/cli/commands/daemon/index.ts b/ts/cli/commands/daemon/index.ts index e00ca2a..ce7842a 100644 --- a/ts/cli/commands/daemon/index.ts +++ b/ts/cli/commands/daemon/index.ts @@ -33,7 +33,8 @@ export function registerDaemonCommand(smartcli: plugins.smartcli.Smartcli) { const daemonScript = plugins.path.join( paths.packageDir, 'dist_ts', - 'daemon.js', + 'daemon', + 'tspm.daemon.js', ); // Start daemon as a detached background process diff --git a/ts/cli/index.ts b/ts/cli/index.ts index 2cedf86..eb637c6 100644 --- a/ts/cli/index.ts +++ b/ts/cli/index.ts @@ -52,6 +52,8 @@ export const run = async (): Promise => { } else { console.log('Daemon: not running'); } + // Ensure we disconnect any IPC client connection used for status + try { await tspmIpcClient.disconnect(); } catch {} return; // do not start parser } // Keep Smartcli version info for help output but not used for -v now diff --git a/ts/daemon/tspm.daemon.ts b/ts/daemon/tspm.daemon.ts index 3faedc7..dfa48ed 100644 --- a/ts/daemon/tspm.daemon.ts +++ b/ts/daemon/tspm.daemon.ts @@ -141,15 +141,21 @@ export class TspmDaemon { 'startById', async (request: RequestForMethod<'startById'>) => { try { - const config = this.tspmInstance.processConfigs.get(request.id); + const id = String(request.id).trim(); + let config = this.tspmInstance.processConfigs.get(id); if (!config) { - throw new Error(`Process ${request.id} not found`); + // Try to reload configs if not found (handles races or stale state) + await this.tspmInstance.loadProcessConfigs(); + config = this.tspmInstance.processConfigs.get(id) || null as any; } - await this.tspmInstance.setDesiredState(request.id, 'online'); + if (!config) { + throw new Error(`Process ${id} not found`); + } + await this.tspmInstance.setDesiredState(id, 'online'); await this.tspmInstance.start(config); - const processInfo = this.tspmInstance.processInfo.get(request.id); + const processInfo = this.tspmInstance.processInfo.get(id); return { - processId: request.id, + processId: id, pid: processInfo?.pid, status: processInfo?.status || 'stopped', }; @@ -163,11 +169,12 @@ export class TspmDaemon { 'stop', async (request: RequestForMethod<'stop'>) => { try { - await this.tspmInstance.setDesiredState(request.id, 'stopped'); - await this.tspmInstance.stop(request.id); + const id = String(request.id).trim(); + await this.tspmInstance.setDesiredState(id, 'stopped'); + await this.tspmInstance.stop(id); return { success: true, - message: `Process ${request.id} stopped successfully`, + message: `Process ${id} stopped successfully`, }; } catch (error) { throw new Error(`Failed to stop process: ${error.message}`); @@ -179,11 +186,12 @@ export class TspmDaemon { 'restart', async (request: RequestForMethod<'restart'>) => { try { - await this.tspmInstance.setDesiredState(request.id, 'online'); - await this.tspmInstance.restart(request.id); - const processInfo = this.tspmInstance.processInfo.get(request.id); + const id = String(request.id).trim(); + await this.tspmInstance.setDesiredState(id, 'online'); + await this.tspmInstance.restart(id); + const processInfo = this.tspmInstance.processInfo.get(id); return { - processId: request.id, + processId: id, pid: processInfo?.pid, status: processInfo?.status || 'stopped', }; @@ -197,10 +205,11 @@ export class TspmDaemon { 'delete', async (request: RequestForMethod<'delete'>) => { try { - await this.tspmInstance.delete(request.id); + const id = String(request.id).trim(); + await this.tspmInstance.delete(id); return { success: true, - message: `Process ${request.id} deleted successfully`, + message: `Process ${id} deleted successfully`, }; } catch (error) { throw new Error(`Failed to delete process: ${error.message}`); @@ -226,8 +235,9 @@ export class TspmDaemon { 'remove', async (request: RequestForMethod<'remove'>) => { try { - await this.tspmInstance.delete(request.id); - return { success: true, message: `Process ${request.id} deleted successfully` }; + const id = String(request.id).trim(); + await this.tspmInstance.delete(id); + return { success: true, message: `Process ${id} deleted successfully` }; } catch (error) { throw new Error(`Failed to remove process: ${error.message}`); } @@ -245,9 +255,10 @@ export class TspmDaemon { this.ipcServer.onMessage( 'describe', async (request: RequestForMethod<'describe'>) => { - const result = await this.tspmInstance.describe(request.id); + const id = String(request.id).trim(); + const result = await this.tspmInstance.describe(id); if (!result) { - throw new Error(`Process ${request.id} not found`); + throw new Error(`Process ${id} not found`); } // Return correctly shaped response return {