mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(daemon): also enable LaunchAgent in repairLaunchAgentBootstrap
The repair/recovery path had the same missing `enable` guard as `restartLaunchAgent`. If launchd persists a "disabled" state after a previous `bootout`, the `bootstrap` call in `repairLaunchAgentBootstrap` fails silently, leaving the gateway unloaded in the recovery flow. Add the same `enable` guard before `bootstrap` that was already applied to `installLaunchAgent` and (in this PR) `restartLaunchAgent`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
30990d73b2
commit
1a74d50578
@@ -156,7 +156,7 @@ describe("launchctl list detection", () => {
|
||||
});
|
||||
|
||||
describe("launchd bootstrap repair", () => {
|
||||
it("bootstraps and kickstarts the resolved label", async () => {
|
||||
it("enables, bootstraps, and kickstarts the resolved label", async () => {
|
||||
const env: Record<string, string | undefined> = {
|
||||
HOME: "/Users/test",
|
||||
OPENCLAW_PROFILE: "default",
|
||||
@@ -167,9 +167,23 @@ describe("launchd bootstrap repair", () => {
|
||||
const domain = typeof process.getuid === "function" ? `gui/${process.getuid()}` : "gui/501";
|
||||
const label = "ai.openclaw.gateway";
|
||||
const plistPath = resolveLaunchAgentPlistPath(env);
|
||||
const serviceId = `${domain}/${label}`;
|
||||
|
||||
expect(state.launchctlCalls).toContainEqual(["bootstrap", domain, plistPath]);
|
||||
expect(state.launchctlCalls).toContainEqual(["kickstart", "-k", `${domain}/${label}`]);
|
||||
const enableIndex = state.launchctlCalls.findIndex(
|
||||
(c) => c[0] === "enable" && c[1] === serviceId,
|
||||
);
|
||||
const bootstrapIndex = state.launchctlCalls.findIndex(
|
||||
(c) => c[0] === "bootstrap" && c[1] === domain && c[2] === plistPath,
|
||||
);
|
||||
const kickstartIndex = state.launchctlCalls.findIndex(
|
||||
(c) => c[0] === "kickstart" && c[1] === "-k" && c[2] === serviceId,
|
||||
);
|
||||
|
||||
expect(enableIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(bootstrapIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(kickstartIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(enableIndex).toBeLessThan(bootstrapIndex);
|
||||
expect(bootstrapIndex).toBeLessThan(kickstartIndex);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -207,6 +207,9 @@ export async function repairLaunchAgentBootstrap(args: {
|
||||
const domain = resolveGuiDomain();
|
||||
const label = resolveLaunchAgentLabel({ env });
|
||||
const plistPath = resolveLaunchAgentPlistPath(env);
|
||||
// launchd can persist "disabled" state after bootout; clear it before bootstrap
|
||||
// (matches the same guard in installLaunchAgent and restartLaunchAgent).
|
||||
await execLaunchctl(["enable", `${domain}/${label}`]);
|
||||
const boot = await execLaunchctl(["bootstrap", domain, plistPath]);
|
||||
if (boot.code !== 0) {
|
||||
return { ok: false, detail: (boot.stderr || boot.stdout).trim() || undefined };
|
||||
|
||||
Reference in New Issue
Block a user