Merge ce96e01ebbbbcd480cc46e661921b2254e1e9271 into 598f1826d8b2bc969aace2c6459824737667218c

This commit is contained in:
HollyChou 2026-03-20 21:26:55 -07:00 committed by GitHub
commit 9c5b12d1b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 2 deletions

View File

@ -23,11 +23,30 @@ function makeJob(payload: CronJob["payload"]): CronJob {
}
describe("timeout-policy", () => {
it("uses default timeout for non-agent jobs", () => {
it("uses default timeout for systemEvent jobs with wakeMode=next-heartbeat", () => {
const timeout = resolveCronJobTimeoutMs(makeJob({ kind: "systemEvent", text: "hello" }));
expect(timeout).toBe(DEFAULT_JOB_TIMEOUT_MS);
});
it("uses expanded safety timeout for systemEvent jobs targeting main with wakeMode=now", () => {
// wakeMode="now" + sessionTarget="main" blocks until the full agent turn completes
// via runHeartbeatOnce(), so it needs the same generous ceiling as agentTurn jobs.
const job: CronJob = {
id: "job-1",
name: "job",
createdAtMs: 0,
updatedAtMs: 0,
enabled: true,
schedule: { kind: "every", everyMs: 60_000 },
sessionTarget: "main",
wakeMode: "now",
payload: { kind: "systemEvent", text: "check in" },
state: {},
};
const timeout = resolveCronJobTimeoutMs(job);
expect(timeout).toBe(AGENT_TURN_SAFETY_TIMEOUT_MS);
});
it("uses expanded safety timeout for agentTurn jobs without explicit timeout", () => {
const timeout = resolveCronJobTimeoutMs(makeJob({ kind: "agentTurn", message: "hi" }));
expect(timeout).toBe(AGENT_TURN_SAFETY_TIMEOUT_MS);

View File

@ -19,7 +19,25 @@ export function resolveCronJobTimeoutMs(job: CronJob): number | undefined {
? Math.floor(job.payload.timeoutSeconds * 1_000)
: undefined;
if (configuredTimeoutMs === undefined) {
return job.payload.kind === "agentTurn" ? AGENT_TURN_SAFETY_TIMEOUT_MS : DEFAULT_JOB_TIMEOUT_MS;
// agentTurn jobs get the large safety ceiling since turns can run for a long time.
if (job.payload.kind === "agentTurn") {
return AGENT_TURN_SAFETY_TIMEOUT_MS;
}
// systemEvent jobs targeting "main" with wakeMode="now" call runHeartbeatOnce(),
// which blocks until the full agent turn completes. The turn duration is
// unbounded, so apply the same generous ceiling as agentTurn jobs instead of
// the short DEFAULT_JOB_TIMEOUT_MS that was incorrectly timing out long-running
// main-session heartbeats. See: https://github.com/openclaw/openclaw/issues/50621
if (
job.payload.kind === "systemEvent" &&
job.sessionTarget === "main" &&
job.wakeMode === "now"
) {
return AGENT_TURN_SAFETY_TIMEOUT_MS;
}
// All other systemEvent jobs (wakeMode !== "now") are fire-and-forget:
// they enqueue the event and return immediately, so the short default is fine.
return DEFAULT_JOB_TIMEOUT_MS;
}
return configuredTimeoutMs <= 0 ? undefined : configuredTimeoutMs;
}