Cron: preserve session scope for main-target reminders

This commit is contained in:
Vignesh Natarajan
2026-02-28 14:53:10 -08:00
parent 61989091a4
commit 2050fd7539
4 changed files with 12 additions and 10 deletions

View File

@@ -509,7 +509,7 @@ describe("CronService", () => {
await store.cleanup();
});
it("passes agentId and resolves main session for wakeMode now main jobs", async () => {
it("passes agentId and preserves scoped session for wakeMode now main jobs", async () => {
const runHeartbeatOnce = vi.fn(async () => ({ status: "ran" as const, durationMs: 1 }));
const { store, cron, enqueueSystemEvent, requestHeartbeatNow } =
@@ -534,13 +534,13 @@ describe("CronService", () => {
expect.objectContaining({
reason: `cron:${job.id}`,
agentId: "ops",
sessionKey: undefined,
sessionKey,
}),
);
expect(requestHeartbeatNow).not.toHaveBeenCalled();
expect(enqueueSystemEvent).toHaveBeenCalledWith(
"hello",
expect.objectContaining({ agentId: "ops", sessionKey: undefined }),
expect.objectContaining({ agentId: "ops", sessionKey }),
);
cron.stop();
@@ -578,7 +578,7 @@ describe("CronService", () => {
expect(requestHeartbeatNow).toHaveBeenCalledWith(
expect.objectContaining({
reason: `cron:${job.id}`,
sessionKey: undefined,
sessionKey,
}),
);
expect(job.state.lastStatus).toBe("ok");

View File

@@ -640,9 +640,10 @@ export async function executeJobCore(
: 'main job requires payload.kind="systemEvent"',
};
}
// main-target cron jobs should always resolve via the agent's main session.
// Avoid forwarding persisted channel session keys from legacy records.
const targetMainSessionKey = undefined;
// Preserve the job session namespace for main-target reminders so heartbeat
// routing can deliver follow-through in the originating channel/thread.
// Downstream gateway wiring canonicalizes/guards this key per agent.
const targetMainSessionKey = job.sessionKey;
state.deps.enqueueSystemEvent(text, {
agentId: job.agentId,
sessionKey: targetMainSessionKey,