chore: checkpoint current worktree state

This commit is contained in:
Mohamed Boudra
2026-04-11 13:09:51 +07:00
parent 3b8cfcbec6
commit aa1d33f0a0
7 changed files with 246 additions and 301 deletions
+51 -19
View File
@@ -209,6 +209,8 @@ async function resolveStatus(): Promise<DesktopDaemonStatus> {
error: null,
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logDesktopDaemonLifecycle("resolveStatus CLI command failed", { error: errorMessage });
return {
serverId: "",
status: "stopped",
@@ -218,7 +220,7 @@ async function resolveStatus(): Promise<DesktopDaemonStatus> {
home,
version: null,
desktopManaged: false,
error: error instanceof Error ? error.message : String(error),
error: errorMessage,
};
}
}
@@ -231,6 +233,14 @@ function normalizeVersion(version: string | null): string | null {
async function startDaemon(): Promise<DesktopDaemonStatus> {
const current = await resolveStatus();
logDesktopDaemonLifecycle("initial status check before start", {
status: current.status,
pid: current.pid,
listen: current.listen,
serverId: current.serverId || null,
error: current.error,
desktopManaged: current.desktopManaged,
});
if (current.status === "running") {
const appVersion = normalizeVersion(resolveDesktopAppVersion());
const daemonVersion = normalizeVersion(current.version);
@@ -269,7 +279,16 @@ async function startDaemon(): Promise<DesktopDaemonStatus> {
const child: ChildProcess = spawnProcess(invocation.command, invocation.args, {
detached: true,
env: { ...invocation.env, PASEO_DESKTOP_MANAGED: "1" },
stdio: ["ignore", "ignore", "ignore"],
stdio: ["ignore", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
child.stdout!.on("data", (data: Buffer) => {
stdout += data.toString();
});
child.stderr!.on("data", (data: Buffer) => {
stderr += data.toString();
});
logDesktopDaemonLifecycle("detached spawn returned", {
@@ -280,41 +299,54 @@ async function startDaemon(): Promise<DesktopDaemonStatus> {
child.unref();
// Wait for process to survive the grace period
const exitedEarly = await new Promise<boolean>((resolve) => {
type GraceResult =
| { exitedEarly: false }
| { exitedEarly: true; code: number | null; signal: string | null; error?: Error };
const result = await new Promise<GraceResult>((resolve) => {
let settled = false;
const finish = (value: boolean) => {
const finish = (value: GraceResult) => {
if (settled) return;
settled = true;
resolve(value);
};
const timer = setTimeout(() => finish(false), DETACHED_STARTUP_GRACE_MS);
const timer = setTimeout(() => finish({ exitedEarly: false }), DETACHED_STARTUP_GRACE_MS);
child.once("error", () => {
logDesktopDaemonLifecycle("detached child emitted error during grace period", {
childPid: child.pid ?? null,
});
child.once("error", (error) => {
clearTimeout(timer);
finish(true);
finish({ exitedEarly: true, code: null, signal: null, error });
});
child.once("exit", () => {
logDesktopDaemonLifecycle("detached child emitted exit during grace period", {
childPid: child.pid ?? null,
});
child.once("exit", (code, signal) => {
clearTimeout(timer);
finish(true);
finish({ exitedEarly: true, code, signal });
});
});
logDesktopDaemonLifecycle("detached startup grace period completed", {
childPid: child.pid ?? null,
exitedEarly,
exitedEarly: result.exitedEarly,
...(result.exitedEarly
? {
exitCode: result.code,
signal: result.signal,
error: result.error?.message ?? null,
stdout: stdout.slice(0, 2000),
stderr: stderr.slice(0, 2000),
}
: {}),
});
if (exitedEarly) {
if (result.exitedEarly) {
const reason = result.error
? result.error.message
: `exit code ${result.code ?? "unknown"}${result.signal ? ` (${result.signal})` : ""}`;
const parts = [`Daemon failed to start: ${reason}`];
if (stderr.trim()) parts.push(`stderr:\n${stderr.trim()}`);
if (stdout.trim()) parts.push(`stdout:\n${stdout.trim()}`);
const logs = tailFile(logFilePath(), 15);
throw new Error(`Daemon failed to start.${logs ? `\n\nRecent logs:\n${logs}` : ""}`);
if (logs) parts.push(`Recent logs (${logFilePath()}):\n${logs}`);
throw new Error(parts.join("\n\n"));
}
// Poll for PID file with server ID
+32 -3
View File
@@ -4,6 +4,7 @@ import { spawnProcess } from "@getpaseo/server";
import { createRequire } from "node:module";
import path from "node:path";
import { app } from "electron";
import log from "electron-log/main";
import {
DESKTOP_CLI_ENV,
createNodeEntrypointInvocation as createSharedNodeEntrypointInvocation,
@@ -284,7 +285,18 @@ export async function runCliTextCommand(args: string[]): Promise<string> {
if (result.exitCode !== 0) {
const stderr = result.stderr.trim();
throw new Error(stderr.length > 0 ? stderr : `CLI command failed with exit code ${result.exitCode}`);
const stdout = result.stdout.trim();
log.warn("[desktop cli]", `CLI text command failed`, {
args,
exitCode: result.exitCode,
stdout: stdout.slice(0, 500),
stderr: stderr.slice(0, 500),
});
throw new Error(
stderr.length > 0
? stderr
: `CLI command failed with exit code ${result.exitCode}${stdout.length > 0 ? `\nstdout: ${stdout.slice(0, 200)}` : ""}`,
);
}
return result.stdout.trimEnd();
@@ -298,11 +310,24 @@ export async function runCliJsonCommand(args: string[]): Promise<unknown> {
if (result.exitCode !== 0) {
const stderr = result.stderr.trim();
throw new Error(stderr.length > 0 ? stderr : `CLI command failed with exit code ${result.exitCode}`);
const stdout = result.stdout.trim();
log.warn("[desktop cli]", `CLI command failed`, {
args,
exitCode: result.exitCode,
stdout: stdout.slice(0, 500),
stderr: stderr.slice(0, 500),
command: invocation.command,
});
throw new Error(
stderr.length > 0
? stderr
: `CLI command failed with exit code ${result.exitCode}${stdout.length > 0 ? `\nstdout: ${stdout.slice(0, 200)}` : ""}`,
);
}
const stdout = result.stdout.trim();
if (stdout.length === 0) {
log.warn("[desktop cli]", `CLI command produced no output`, { args });
throw new Error("CLI command did not produce JSON output.");
}
@@ -310,7 +335,11 @@ export async function runCliJsonCommand(args: string[]): Promise<unknown> {
// Extract the first valid JSON object or array from the output.
const jsonStart = stdout.search(/[{[]/);
if (jsonStart < 0) {
throw new Error("CLI command output contained no JSON.");
log.warn("[desktop cli]", `CLI command output contained no JSON`, {
args,
stdout: stdout.slice(0, 500),
});
throw new Error(`CLI command output contained no JSON. Output: ${stdout.slice(0, 200)}`);
}
const jsonText = stdout.slice(jsonStart);