diff --git a/packages/desktop/src/daemon/daemon-manager.test.ts b/packages/desktop/src/daemon/daemon-manager.test.ts index 4da4e5319e..d18a8cd48c 100644 --- a/packages/desktop/src/daemon/daemon-manager.test.ts +++ b/packages/desktop/src/daemon/daemon-manager.test.ts @@ -125,6 +125,36 @@ describe("daemon-manager commands", () => { }); }); + it("reports a stopped daemon without launching the CLI when no local daemon runs", async () => { + mkdirSync(mocks.paseoHome); + writeFileSync(path.join(mocks.paseoHome, "server-id"), "srv_existing\n"); + mocks.runExternalCliJsonCommand.mockResolvedValue({ + home: mocks.paseoHome, + pid: null, + startedAt: null, + listen: null, + hostname: null, + localDaemon: "stopped", + desktopManaged: false, + connectedDaemon: "not_probed", + }); + + const status = await createDaemonCommandHandlers().desktop_daemon_status(); + + expect(status).toMatchObject({ serverId: "", status: "stopped", pid: null }); + expect(mocks.runExternalCliJsonCommand).not.toHaveBeenCalled(); + }); + + it("reports an errored daemon when the local daemon state cannot be read", async () => { + mkdirSync(mocks.paseoHome); + writeFileSync(path.join(mocks.paseoHome, "paseo.pid"), "garbage"); + + const status = await createDaemonCommandHandlers().desktop_daemon_status(); + + expect(status).toMatchObject({ serverId: "", status: "errored", pid: null }); + expect(status.error).toBeTruthy(); + }); + it("returns a local credential only for its live managed daemon listen", async () => { mkdirSync(mocks.paseoHome); const token = "a".repeat(43); diff --git a/packages/desktop/src/daemon/daemon-manager.ts b/packages/desktop/src/daemon/daemon-manager.ts index 8c1cf8dcc8..5f3f5394c6 100644 --- a/packages/desktop/src/daemon/daemon-manager.ts +++ b/packages/desktop/src/daemon/daemon-manager.ts @@ -224,6 +224,12 @@ export async function resolveDesktopDaemonStatus(): Promise const home = getPaseoHome(); try { + // The app polls this while no local daemon runs. Answer that case in-process, + // since launching the CLI once per poll keeps spawning processes while idle. + if (!(await readDaemonInstance(home))) { + return statusFromDaemonProbe({ localDaemon: "stopped" }, home); + } + const payload = (await runExternalCliJsonCommand([ "daemon", "status", @@ -234,7 +240,7 @@ export async function resolveDesktopDaemonStatus(): Promise return statusFromDaemonProbe(payload, home); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); - logDesktopDaemonLifecycle("resolveStatus CLI command failed", { error: errorMessage }); + logDesktopDaemonLifecycle("resolveStatus failed", { error: errorMessage }); return { serverId: "", status: "errored",