mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 00:41:36 +00:00
fix(reply): suppress unscheduled-reminder note when session already has active cron
Before appending the "I did not schedule a reminder" guard note, check the cron store for enabled jobs matching the current session key. This prevents false positives when the agent references an existing cron created in a prior turn (e.g. "I'll ping you when it's done" while a monitoring cron is already running). The check only fires on the rare path where the text matches commitment patterns AND no cron was added in the current turn, so the added I/O is negligible. Closes #32228 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
55f04636f3
commit
abb0252a1a
@@ -67,6 +67,15 @@ vi.mock("./queue.js", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
const loadCronStoreMock = vi.fn();
|
||||
vi.mock("../../cron/store.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../../cron/store.js")>("../../cron/store.js");
|
||||
return {
|
||||
...actual,
|
||||
loadCronStore: (...args: unknown[]) => loadCronStoreMock(...args),
|
||||
};
|
||||
});
|
||||
|
||||
import { runReplyAgent } from "./agent-runner.js";
|
||||
|
||||
type RunWithModelFallbackParams = {
|
||||
@@ -80,6 +89,9 @@ beforeEach(() => {
|
||||
runCliAgentMock.mockClear();
|
||||
runWithModelFallbackMock.mockClear();
|
||||
runtimeErrorMock.mockClear();
|
||||
loadCronStoreMock.mockClear();
|
||||
// Default: no cron jobs in store.
|
||||
loadCronStoreMock.mockResolvedValue({ version: 1, jobs: [] });
|
||||
resetSystemEventsForTest();
|
||||
|
||||
// Default: no provider switch; execute the chosen provider+model.
|
||||
@@ -1180,6 +1192,87 @@ describe("runReplyAgent reminder commitment guard", () => {
|
||||
text: "I'll remind you tomorrow morning.",
|
||||
});
|
||||
});
|
||||
|
||||
it("suppresses guard note when session already has an active cron job", async () => {
|
||||
loadCronStoreMock.mockResolvedValueOnce({
|
||||
version: 1,
|
||||
jobs: [
|
||||
{
|
||||
id: "existing-job",
|
||||
name: "monitor-task",
|
||||
enabled: true,
|
||||
sessionKey: "main",
|
||||
createdAtMs: Date.now() - 60_000,
|
||||
updatedAtMs: Date.now() - 60_000,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
runEmbeddedPiAgentMock.mockResolvedValueOnce({
|
||||
payloads: [{ text: "I'll ping you when it's done." }],
|
||||
meta: {},
|
||||
successfulCronAdds: 0,
|
||||
});
|
||||
|
||||
const result = await createRun();
|
||||
expect(result).toMatchObject({
|
||||
text: "I'll ping you when it's done.",
|
||||
});
|
||||
});
|
||||
|
||||
it("still appends guard note when cron jobs exist but not for the current session", async () => {
|
||||
loadCronStoreMock.mockResolvedValueOnce({
|
||||
version: 1,
|
||||
jobs: [
|
||||
{
|
||||
id: "unrelated-job",
|
||||
name: "daily-news",
|
||||
enabled: true,
|
||||
sessionKey: "other-session",
|
||||
createdAtMs: Date.now() - 60_000,
|
||||
updatedAtMs: Date.now() - 60_000,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
runEmbeddedPiAgentMock.mockResolvedValueOnce({
|
||||
payloads: [{ text: "I'll remind you tomorrow morning." }],
|
||||
meta: {},
|
||||
successfulCronAdds: 0,
|
||||
});
|
||||
|
||||
const result = await createRun();
|
||||
expect(result).toMatchObject({
|
||||
text: "I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
||||
});
|
||||
});
|
||||
|
||||
it("still appends guard note when cron jobs for session exist but are disabled", async () => {
|
||||
loadCronStoreMock.mockResolvedValueOnce({
|
||||
version: 1,
|
||||
jobs: [
|
||||
{
|
||||
id: "disabled-job",
|
||||
name: "old-monitor",
|
||||
enabled: false,
|
||||
sessionKey: "main",
|
||||
createdAtMs: Date.now() - 60_000,
|
||||
updatedAtMs: Date.now() - 60_000,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
runEmbeddedPiAgentMock.mockResolvedValueOnce({
|
||||
payloads: [{ text: "I'll check back in an hour." }],
|
||||
meta: {},
|
||||
successfulCronAdds: 0,
|
||||
});
|
||||
|
||||
const result = await createRun();
|
||||
expect(result).toMatchObject({
|
||||
text: "I'll check back in an hour.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("runReplyAgent fallback reasoning tags", () => {
|
||||
|
||||
Reference in New Issue
Block a user