fix: extend Windows daemon onboarding health budget

This commit is contained in:
Peter Steinberger
2026-04-05 20:48:14 +01:00
parent 8806ef804e
commit 791c083c0a
2 changed files with 80 additions and 3 deletions

View File

@@ -520,6 +520,49 @@ describe("onboard (non-interactive): gateway and remote auth", () => {
});
}, 60_000);
it("uses a longer Windows health deadline when daemon install was requested", async () => {
await withStateDir("state-local-daemon-health-win-", async (stateDir) => {
let capturedDeadlineMs: number | undefined;
let capturedProbeTimeoutMs: number | undefined;
waitForGatewayReachableMock = vi.fn(
async (params: {
url: string;
token?: string;
password?: string;
deadlineMs?: number;
probeTimeoutMs?: number;
}) => {
capturedDeadlineMs = params.deadlineMs;
capturedProbeTimeoutMs = params.probeTimeoutMs;
return { ok: true };
},
);
const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32");
try {
await runNonInteractiveSetup(
{
nonInteractive: true,
mode: "local",
workspace: path.join(stateDir, "openclaw"),
authChoice: "skip",
skipSkills: true,
skipHealth: false,
installDaemon: true,
gatewayBind: "loopback",
},
runtime,
);
} finally {
platformSpy.mockRestore();
}
expect(installGatewayDaemonNonInteractiveMock).toHaveBeenCalledTimes(1);
expect(capturedDeadlineMs).toBe(90_000);
expect(capturedProbeTimeoutMs).toBe(15_000);
});
}, 60_000);
it("emits a daemon-install failure when Linux user systemd is unavailable", async () => {
await withStateDir("state-local-daemon-install-json-fail-", async (stateDir) => {
installGatewayDaemonNonInteractiveMock.mockResolvedValueOnce({

View File

@@ -26,6 +26,29 @@ import { resolveNonInteractiveWorkspaceDir } from "./local/workspace.js";
const INSTALL_DAEMON_HEALTH_DEADLINE_MS = 45_000;
const ATTACH_EXISTING_GATEWAY_HEALTH_DEADLINE_MS = 15_000;
const INSTALL_DAEMON_HEALTH_PROBE_TIMEOUT_MS = 10_000;
const WINDOWS_INSTALL_DAEMON_HEALTH_DEADLINE_MS = 90_000;
const WINDOWS_INSTALL_DAEMON_HEALTH_PROBE_TIMEOUT_MS = 15_000;
const INSTALL_DAEMON_HEALTH_COMMAND_TIMEOUT_MS = 10_000;
const WINDOWS_INSTALL_DAEMON_HEALTH_COMMAND_TIMEOUT_MS = 30_000;
function resolveInstallDaemonGatewayHealthTiming(): {
deadlineMs: number;
probeTimeoutMs: number;
healthCommandTimeoutMs: number;
} {
if (process.platform === "win32") {
return {
deadlineMs: WINDOWS_INSTALL_DAEMON_HEALTH_DEADLINE_MS,
probeTimeoutMs: WINDOWS_INSTALL_DAEMON_HEALTH_PROBE_TIMEOUT_MS,
healthCommandTimeoutMs: WINDOWS_INSTALL_DAEMON_HEALTH_COMMAND_TIMEOUT_MS,
};
}
return {
deadlineMs: INSTALL_DAEMON_HEALTH_DEADLINE_MS,
probeTimeoutMs: INSTALL_DAEMON_HEALTH_PROBE_TIMEOUT_MS,
healthCommandTimeoutMs: INSTALL_DAEMON_HEALTH_COMMAND_TIMEOUT_MS,
};
}
async function collectGatewayHealthFailureDiagnostics(): Promise<
GatewayHealthFailureDiagnostics | undefined
@@ -206,13 +229,16 @@ export async function runNonInteractiveLocalSetup(params: {
customBindHost: nextConfig.gateway?.customBindHost,
basePath: undefined,
});
const installDaemonGatewayHealthTiming = resolveInstallDaemonGatewayHealthTiming();
const probe = await waitForGatewayReachable({
url: links.wsUrl,
token: gatewayResult.gatewayToken,
deadlineMs: opts.installDaemon
? INSTALL_DAEMON_HEALTH_DEADLINE_MS
? installDaemonGatewayHealthTiming.deadlineMs
: ATTACH_EXISTING_GATEWAY_HEALTH_DEADLINE_MS,
probeTimeoutMs: opts.installDaemon ? INSTALL_DAEMON_HEALTH_PROBE_TIMEOUT_MS : undefined,
probeTimeoutMs: opts.installDaemon
? installDaemonGatewayHealthTiming.probeTimeoutMs
: undefined,
});
if (!probe.ok) {
const diagnostics = opts.installDaemon
@@ -246,7 +272,15 @@ export async function runNonInteractiveLocalSetup(params: {
runtime.exit(1);
return;
}
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
await healthCommand(
{
json: false,
timeoutMs: opts.installDaemon
? installDaemonGatewayHealthTiming.healthCommandTimeoutMs
: 10_000,
},
runtime,
);
}
logNonInteractiveOnboardingJson({