mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-24 12:04:27 +00:00
* fix(cron): pass heartbeat target=last for main-session cron jobs When a cron job with sessionTarget=main and wakeMode=now fires, it triggers a heartbeat via runHeartbeatOnce. Sincee2362d35changed the default heartbeat target from "last" to "none", these cron-triggered heartbeats silently discard their responses instead of delivering them to the last active channel (e.g. Telegram). Fix: pass heartbeat: { target: "last" } from the cron timer to runHeartbeatOnce for main-session jobs, and wire the override through the gateway cron service builder. This restores delivery for sessionTarget=main cron jobs without reverting the intentional default change for regular heartbeats. Regression introduced in:e2362d35(2026-02-25) Fixes #28508 * Cron: align server-cron wake routing expectations for main-target jobs --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -40,7 +40,7 @@ describe("buildGatewayCronService", () => {
|
||||
fetchWithSsrFGuardMock.mockClear();
|
||||
});
|
||||
|
||||
it("canonicalizes non-agent sessionKey to agent store key for enqueue + wake", async () => {
|
||||
it("routes main-target jobs to the main session for enqueue + wake", async () => {
|
||||
const tmpDir = path.join(os.tmpdir(), `server-cron-${Date.now()}`);
|
||||
const cfg = {
|
||||
session: {
|
||||
@@ -73,12 +73,12 @@ describe("buildGatewayCronService", () => {
|
||||
expect(enqueueSystemEventMock).toHaveBeenCalledWith(
|
||||
"hello",
|
||||
expect.objectContaining({
|
||||
sessionKey: "agent:main:discord:channel:ops",
|
||||
sessionKey: "agent:main:main",
|
||||
}),
|
||||
);
|
||||
expect(requestHeartbeatNowMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
sessionKey: "agent:main:discord:channel:ops",
|
||||
sessionKey: undefined,
|
||||
}),
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -182,11 +182,29 @@ export function buildGatewayCronService(params: {
|
||||
},
|
||||
runHeartbeatOnce: async (opts) => {
|
||||
const { runtimeConfig, agentId, sessionKey } = resolveCronWakeTarget(opts);
|
||||
// Merge cron-supplied heartbeat overrides (e.g. target: "last") with the
|
||||
// fully resolved agent heartbeat config so cron-triggered heartbeats
|
||||
// respect agent-specific overrides (agents.list[].heartbeat) before
|
||||
// falling back to agents.defaults.heartbeat.
|
||||
const agentEntry =
|
||||
Array.isArray(runtimeConfig.agents?.list) &&
|
||||
runtimeConfig.agents.list.find(
|
||||
(entry) =>
|
||||
entry && typeof entry.id === "string" && normalizeAgentId(entry.id) === agentId,
|
||||
);
|
||||
const baseHeartbeat = {
|
||||
...runtimeConfig.agents?.defaults?.heartbeat,
|
||||
...agentEntry?.heartbeat,
|
||||
};
|
||||
const heartbeatOverride = opts?.heartbeat
|
||||
? { ...baseHeartbeat, ...opts.heartbeat }
|
||||
: undefined;
|
||||
return await runHeartbeatOnce({
|
||||
cfg: runtimeConfig,
|
||||
reason: opts?.reason,
|
||||
agentId,
|
||||
sessionKey,
|
||||
heartbeat: heartbeatOverride,
|
||||
deps: { ...params.deps, runtime: defaultRuntime },
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user