mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
fix(daemon): normalize schtasks runtime from numeric result only (#39153, thanks @scoootscooob)
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
This commit is contained in:
@@ -284,6 +284,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Daemon/Windows PATH freeze fix: stop persisting install-time `PATH` snapshots into Scheduled Task scripts so runtime tool lookup follows current host PATH updates; also refresh local TUI history on silent local finals. (#39139) Thanks @Narcooo.
|
||||
- Gateway/systemd service restart hardening: clear stale gateway listeners by explicit run-port before service bind, add restart stale-pid port-override support, tune systemd start/stop/exit handling, and disable detached child mode only in service-managed runtime so cgroup stop semantics clean up descendants reliably. (#38463) Thanks @spirittechie.
|
||||
- Discord/plugin native command aliases: let plugins declare provider-specific slash names so native Discord registration can avoid built-in command collisions; the bundled Talk voice plugin now uses `/talkvoice` natively on Discord while keeping text `/voice`.
|
||||
- Daemon/Windows schtasks status normalization: derive runtime state from locale-neutral numeric `Last Run Result` codes only (without language string matching) and surface unknown when numeric result data is unavailable, preventing locale-specific misclassification drift. (#39153) Thanks @scoootscooob.
|
||||
|
||||
## 2026.3.2
|
||||
|
||||
|
||||
@@ -44,15 +44,18 @@ describe("scheduled task runtime derivation", () => {
|
||||
).toEqual({ status: "running" });
|
||||
});
|
||||
|
||||
it("treats Running without last result as running", () => {
|
||||
it("treats Running without numeric result as unknown", () => {
|
||||
expect(
|
||||
deriveScheduledTaskRuntimeStatus({
|
||||
status: "Running",
|
||||
}),
|
||||
).toEqual({ status: "running" });
|
||||
).toEqual({
|
||||
status: "unknown",
|
||||
detail: "Task status is locale-dependent and no numeric Last Run Result was available.",
|
||||
});
|
||||
});
|
||||
|
||||
it("downgrades stale Running status when last result is not a running code", () => {
|
||||
it("treats non-running result codes as stopped", () => {
|
||||
expect(
|
||||
deriveScheduledTaskRuntimeStatus({
|
||||
status: "Running",
|
||||
@@ -60,7 +63,7 @@ describe("scheduled task runtime derivation", () => {
|
||||
}),
|
||||
).toEqual({
|
||||
status: "stopped",
|
||||
detail: "Task reports Running but Last Run Result=0x0; treating as stale runtime state.",
|
||||
detail: "Task Last Run Result=0x0; treating as not running.",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,15 +91,21 @@ describe("scheduled task runtime derivation", () => {
|
||||
status: "Wird ausgeführt",
|
||||
lastRunResult: "0x0",
|
||||
}),
|
||||
).toEqual({ status: "stopped" });
|
||||
).toEqual({
|
||||
status: "stopped",
|
||||
detail: "Task Last Run Result=0x0; treating as not running.",
|
||||
});
|
||||
});
|
||||
|
||||
it("treats localized status without result code as stopped", () => {
|
||||
it("treats localized status without result code as unknown", () => {
|
||||
expect(
|
||||
deriveScheduledTaskRuntimeStatus({
|
||||
status: "Wird ausgeführt",
|
||||
}),
|
||||
).toEqual({ status: "stopped" });
|
||||
).toEqual({
|
||||
status: "unknown",
|
||||
detail: "Task status is locale-dependent and no numeric Last Run Result was available.",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -152,41 +152,31 @@ function normalizeTaskResultCode(value?: string): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
return raw;
|
||||
return null;
|
||||
}
|
||||
|
||||
const RUNNING_RESULT_CODES = new Set(["0x41301"]);
|
||||
const UNKNOWN_STATUS_DETAIL =
|
||||
"Task status is locale-dependent and no numeric Last Run Result was available.";
|
||||
|
||||
export function deriveScheduledTaskRuntimeStatus(parsed: ScheduledTaskInfo): {
|
||||
status: GatewayServiceRuntime["status"];
|
||||
detail?: string;
|
||||
} {
|
||||
const statusRaw = parsed.status?.trim().toLowerCase();
|
||||
if (!statusRaw) {
|
||||
return { status: "unknown" };
|
||||
}
|
||||
|
||||
const normalizedResult = normalizeTaskResultCode(parsed.lastRunResult);
|
||||
const runningCodes = new Set(["0x41301"]);
|
||||
const isRunningByCode = normalizedResult != null && runningCodes.has(normalizedResult);
|
||||
const isRunningByStatus = statusRaw === "running";
|
||||
|
||||
// schtasks.exe localizes its Status field ("Running" in English,
|
||||
// "Wird ausgeführt" in German, "En cours" in French, etc.).
|
||||
// Prefer the locale-invariant Last Run Result code 0x41301
|
||||
// ("task is currently running") over string matching. (#39057)
|
||||
if (!isRunningByStatus && !isRunningByCode) {
|
||||
return { status: "stopped" };
|
||||
}
|
||||
|
||||
// Cross-check: if the English status says "running" but the result
|
||||
// code disagrees, the runtime state is likely stale.
|
||||
if (isRunningByStatus && normalizedResult && !isRunningByCode) {
|
||||
if (normalizedResult != null) {
|
||||
if (RUNNING_RESULT_CODES.has(normalizedResult)) {
|
||||
return { status: "running" };
|
||||
}
|
||||
return {
|
||||
status: "stopped",
|
||||
detail: `Task reports Running but Last Run Result=${parsed.lastRunResult}; treating as stale runtime state.`,
|
||||
detail: `Task Last Run Result=${parsed.lastRunResult}; treating as not running.`,
|
||||
};
|
||||
}
|
||||
|
||||
return { status: "running" };
|
||||
if (parsed.status?.trim()) {
|
||||
return { status: "unknown", detail: UNKNOWN_STATUS_DETAIL };
|
||||
}
|
||||
return { status: "unknown" };
|
||||
}
|
||||
|
||||
function buildTaskScript({
|
||||
|
||||
Reference in New Issue
Block a user