feat(doctor): repair launch agent bootstrap
Co-authored-by: Dr Alexander Mikhalev <alex@metacortex.engineer>
This commit is contained in:
@@ -170,9 +170,22 @@ export async function isLaunchAgentLoaded(args: {
|
||||
return res.code === 0;
|
||||
}
|
||||
|
||||
async function hasLaunchAgentPlist(env: Record<string, string | undefined>): Promise<boolean> {
|
||||
const plistPath = resolveLaunchAgentPlistPath(env);
|
||||
export async function isLaunchAgentListed(args: {
|
||||
env?: Record<string, string | undefined>;
|
||||
}): Promise<boolean> {
|
||||
const label = resolveLaunchAgentLabel({ env: args.env });
|
||||
const res = await execLaunchctl(["list"]);
|
||||
if (res.code !== 0) return false;
|
||||
return res.stdout
|
||||
.split(/\r?\n/)
|
||||
.some((line) => line.trim().split(/\s+/).at(-1) === label);
|
||||
}
|
||||
|
||||
export async function launchAgentPlistExists(
|
||||
env: Record<string, string | undefined>,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const plistPath = resolveLaunchAgentPlistPath(env);
|
||||
await fs.access(plistPath);
|
||||
return true;
|
||||
} catch {
|
||||
@@ -194,7 +207,7 @@ export async function readLaunchAgentRuntime(
|
||||
};
|
||||
}
|
||||
const parsed = parseLaunchctlPrint(res.stdout || res.stderr || "");
|
||||
const plistExists = await hasLaunchAgentPlist(env);
|
||||
const plistExists = await launchAgentPlistExists(env);
|
||||
const state = parsed.state?.toLowerCase();
|
||||
const status = state === "running" || parsed.pid ? "running" : state ? "stopped" : "unknown";
|
||||
return {
|
||||
@@ -207,6 +220,24 @@ export async function readLaunchAgentRuntime(
|
||||
};
|
||||
}
|
||||
|
||||
export async function repairLaunchAgentBootstrap(args: {
|
||||
env?: Record<string, string | undefined>;
|
||||
}): Promise<{ ok: boolean; detail?: string }> {
|
||||
const env = args.env ?? (process.env as Record<string, string | undefined>);
|
||||
const domain = resolveGuiDomain();
|
||||
const label = resolveLaunchAgentLabel({ env });
|
||||
const plistPath = resolveLaunchAgentPlistPath(env);
|
||||
const boot = await execLaunchctl(["bootstrap", domain, plistPath]);
|
||||
if (boot.code !== 0) {
|
||||
return { ok: false, detail: (boot.stderr || boot.stdout).trim() || undefined };
|
||||
}
|
||||
const kick = await execLaunchctl(["kickstart", "-k", `${domain}/${label}`]);
|
||||
if (kick.code !== 0) {
|
||||
return { ok: false, detail: (kick.stderr || kick.stdout).trim() || undefined };
|
||||
}
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
export type LegacyLaunchAgent = {
|
||||
label: string;
|
||||
plistPath: string;
|
||||
|
||||
Reference in New Issue
Block a user