Spaces:
Paused
Paused
File size: 3,669 Bytes
fb4d8fe | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import type { GatewayRequestHandlers } from "./types.js";
import { resolveOpenClawPackageRoot } from "../../infra/openclaw-root.js";
import {
formatDoctorNonInteractiveHint,
type RestartSentinelPayload,
writeRestartSentinel,
} from "../../infra/restart-sentinel.js";
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
import { runGatewayUpdate } from "../../infra/update-runner.js";
import {
ErrorCodes,
errorShape,
formatValidationErrors,
validateUpdateRunParams,
} from "../protocol/index.js";
export const updateHandlers: GatewayRequestHandlers = {
"update.run": async ({ params, respond }) => {
if (!validateUpdateRunParams(params)) {
respond(
false,
undefined,
errorShape(
ErrorCodes.INVALID_REQUEST,
`invalid update.run params: ${formatValidationErrors(validateUpdateRunParams.errors)}`,
),
);
return;
}
const sessionKey =
typeof (params as { sessionKey?: unknown }).sessionKey === "string"
? (params as { sessionKey?: string }).sessionKey?.trim() || undefined
: undefined;
const note =
typeof (params as { note?: unknown }).note === "string"
? (params as { note?: string }).note?.trim() || undefined
: undefined;
const restartDelayMsRaw = (params as { restartDelayMs?: unknown }).restartDelayMs;
const restartDelayMs =
typeof restartDelayMsRaw === "number" && Number.isFinite(restartDelayMsRaw)
? Math.max(0, Math.floor(restartDelayMsRaw))
: undefined;
const timeoutMsRaw = (params as { timeoutMs?: unknown }).timeoutMs;
const timeoutMs =
typeof timeoutMsRaw === "number" && Number.isFinite(timeoutMsRaw)
? Math.max(1000, Math.floor(timeoutMsRaw))
: undefined;
let result: Awaited<ReturnType<typeof runGatewayUpdate>>;
try {
const root =
(await resolveOpenClawPackageRoot({
moduleUrl: import.meta.url,
argv1: process.argv[1],
cwd: process.cwd(),
})) ?? process.cwd();
result = await runGatewayUpdate({
timeoutMs,
cwd: root,
argv1: process.argv[1],
});
} catch (err) {
result = {
status: "error",
mode: "unknown",
reason: String(err),
steps: [],
durationMs: 0,
};
}
const payload: RestartSentinelPayload = {
kind: "update",
status: result.status,
ts: Date.now(),
sessionKey,
message: note ?? null,
doctorHint: formatDoctorNonInteractiveHint(),
stats: {
mode: result.mode,
root: result.root ?? undefined,
before: result.before ?? null,
after: result.after ?? null,
steps: result.steps.map((step) => ({
name: step.name,
command: step.command,
cwd: step.cwd,
durationMs: step.durationMs,
log: {
stdoutTail: step.stdoutTail ?? null,
stderrTail: step.stderrTail ?? null,
exitCode: step.exitCode ?? null,
},
})),
reason: result.reason ?? null,
durationMs: result.durationMs,
},
};
let sentinelPath: string | null = null;
try {
sentinelPath = await writeRestartSentinel(payload);
} catch {
sentinelPath = null;
}
const restart = scheduleGatewaySigusr1Restart({
delayMs: restartDelayMs,
reason: "update.run",
});
respond(
true,
{
ok: true,
result,
restart,
sentinel: {
path: sentinelPath,
payload,
},
},
undefined,
);
},
};
|