fix: auto-repair gateway watch startup

This commit is contained in:
Peter Steinberger
2026-05-03 17:11:07 +01:00
parent 0636442cde
commit e7f1b10ff8
5 changed files with 120 additions and 2 deletions

View File

@@ -15,8 +15,10 @@ const WATCH_IGNORED_PATH_SEGMENTS = new Set([".git", "dist", "node_modules"]);
const WATCH_LOCK_WAIT_MS = 5_000;
const WATCH_LOCK_POLL_MS = 100;
const WATCH_LOCK_DIR = path.join(".local", "watch-node");
const AUTO_DOCTOR_DISABLE_VALUES = new Set(["0", "false", "no", "off"]);
const buildRunnerArgs = (args) => [WATCH_NODE_RUNNER, ...args];
const buildDoctorRunnerArgs = () => [WATCH_NODE_RUNNER, "doctor", "--fix", "--non-interactive"];
const normalizePath = (filePath) =>
String(filePath ?? "")
@@ -69,6 +71,15 @@ const shouldRestartAfterChildExit = (exitCode, exitSignal) =>
(typeof exitCode === "number" && WATCH_RESTARTABLE_CHILD_EXIT_CODES.has(exitCode)) ||
(typeof exitSignal === "string" && WATCH_RESTARTABLE_CHILD_SIGNALS.has(exitSignal));
const isGatewayWatchCommand = (args) => args[0] === "gateway";
const shouldRunAutoDoctor = (deps, autoDoctorAttempted) =>
!autoDoctorAttempted &&
isGatewayWatchCommand(deps.args) &&
!AUTO_DOCTOR_DISABLE_VALUES.has(
String(deps.env.OPENCLAW_GATEWAY_WATCH_AUTO_DOCTOR ?? "").toLowerCase(),
);
const isProcessAlive = (pid, signalProcess) => {
if (!Number.isInteger(pid) || pid <= 0) {
return false;
@@ -288,6 +299,7 @@ export async function runWatchMain(params = {}) {
let restartRequested = false;
let watchProcess = null;
let lockHandle = null;
let autoDoctorAttempted = false;
let onSigInt;
let onSigTerm;
@@ -334,6 +346,44 @@ export async function runWatchMain(params = {}) {
startRunner();
return;
}
if (shouldRunAutoDoctor(deps, autoDoctorAttempted)) {
runAutoDoctorAndRestart();
return;
}
settle(exitSignal ? 1 : (exitCode ?? 1));
});
};
const runAutoDoctorAndRestart = () => {
autoDoctorAttempted = true;
logWatcher(
"Gateway exited early; running `openclaw doctor --fix --non-interactive` once.",
deps,
);
watchProcess = deps.spawn(deps.process.execPath, buildDoctorRunnerArgs(), {
cwd: deps.cwd,
env: childEnv,
stdio: "inherit",
});
watchProcess.on("error", (error) => {
watchProcess = null;
logWatcher(`Failed to spawn doctor repair: ${error?.message ?? "unknown error"}`, deps);
settle(1);
});
watchProcess.on("exit", (exitCode, exitSignal) => {
watchProcess = null;
if (shuttingDown) {
return;
}
if (exitCode === 0 && !exitSignal) {
logWatcher("Doctor repair completed; restarting gateway watch child.", deps);
startRunner();
return;
}
logWatcher(
`Doctor repair failed; gateway:watch exiting with code ${exitSignal ? 1 : (exitCode ?? 1)}.`,
deps,
);
settle(exitSignal ? 1 : (exitCode ?? 1));
});
};