mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 08:21:26 +00:00
fix(cron): share isolated announce flow + harden cron scheduling/delivery (#11641)
* fix(cron): comprehensive cron scheduling and delivery fixes - Fix delivery target resolution for isolated agent cron jobs - Improve schedule parsing and validation - Add job retry logic and error handling - Enhance cron ops with better state management - Add timer improvements for more reliable cron execution - Add cron event type to protocol schema - Support cron events in heartbeat runner (skip empty-heartbeat check, use dedicated CRON_EVENT_PROMPT for relay) * fix: remove cron debug test and add changelog/docs notes (#11641) (thanks @tyler6204)
This commit is contained in:
@@ -245,7 +245,7 @@ describe("openclaw-tools: subagents", () => {
|
||||
| undefined;
|
||||
expect(second?.sessionKey).toBe("discord:group:req");
|
||||
expect(second?.deliver).toBe(true);
|
||||
expect(second?.message).toContain("background task");
|
||||
expect(second?.message).toContain("subagent task");
|
||||
|
||||
const sendCalls = calls.filter((c) => c.method === "send");
|
||||
expect(sendCalls.length).toBe(0);
|
||||
|
||||
@@ -153,7 +153,7 @@ describe("openclaw-tools: subagents", () => {
|
||||
// Second call: main agent trigger (not "Sub-agent announce step." anymore)
|
||||
const second = agentCalls[1]?.params as { sessionKey?: string; message?: string } | undefined;
|
||||
expect(second?.sessionKey).toBe("main");
|
||||
expect(second?.message).toContain("background task");
|
||||
expect(second?.message).toContain("subagent task");
|
||||
|
||||
// No direct send to external channel (main agent handles delivery)
|
||||
const sendCalls = calls.filter((c) => c.method === "send");
|
||||
|
||||
@@ -94,7 +94,7 @@ describe("subagent announce formatting", () => {
|
||||
};
|
||||
const msg = call?.params?.message as string;
|
||||
expect(call?.params?.sessionKey).toBe("agent:main:main");
|
||||
expect(msg).toContain("background task");
|
||||
expect(msg).toContain("subagent task");
|
||||
expect(msg).toContain("failed");
|
||||
expect(msg).toContain("boom");
|
||||
expect(msg).toContain("Findings:");
|
||||
@@ -155,7 +155,7 @@ describe("subagent announce formatting", () => {
|
||||
expect(didAnnounce).toBe(true);
|
||||
expect(embeddedRunMock.queueEmbeddedPiMessage).toHaveBeenCalledWith(
|
||||
"session-123",
|
||||
expect.stringContaining("background task"),
|
||||
expect.stringContaining("subagent task"),
|
||||
);
|
||||
expect(agentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -345,6 +345,8 @@ export type SubagentRunOutcome = {
|
||||
error?: string;
|
||||
};
|
||||
|
||||
export type SubagentAnnounceType = "subagent task" | "cron job";
|
||||
|
||||
export async function runSubagentAnnounceFlow(params: {
|
||||
childSessionKey: string;
|
||||
childRunId: string;
|
||||
@@ -360,6 +362,7 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
endedAt?: number;
|
||||
label?: string;
|
||||
outcome?: SubagentRunOutcome;
|
||||
announceType?: SubagentAnnounceType;
|
||||
}): Promise<boolean> {
|
||||
let didAnnounce = false;
|
||||
try {
|
||||
@@ -433,9 +436,10 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
: "finished with unknown status";
|
||||
|
||||
// Build instructional message for main agent
|
||||
const taskLabel = params.label || params.task || "background task";
|
||||
const announceType = params.announceType ?? "subagent task";
|
||||
const taskLabel = params.label || params.task || "task";
|
||||
const triggerMessage = [
|
||||
`A background task "${taskLabel}" just ${statusLabel}.`,
|
||||
`A ${announceType} "${taskLabel}" just ${statusLabel}.`,
|
||||
"",
|
||||
"Findings:",
|
||||
reply || "(no output)",
|
||||
@@ -443,7 +447,7 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
statsLine,
|
||||
"",
|
||||
"Summarize this naturally for the user. Keep it brief (1-2 sentences). Flow it into the conversation naturally.",
|
||||
"Do not mention technical details like tokens, stats, or that this was a background task.",
|
||||
`Do not mention technical details like tokens, stats, or that this was a ${announceType}.`,
|
||||
"You can respond with NO_REPLY if no announcement is needed (e.g., internal task with no user-facing result).",
|
||||
].join("\n");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user