mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-31 07:16:51 +00:00
fix(cron): consolidate announce delivery, fire-and-forget trigger, and minimal prompt mode (#40204)
* fix(cron): consolidate announce delivery and detach manual runs * fix: queue detached cron runs (#40204)
This commit is contained in:
@@ -135,9 +135,15 @@ describe("resolvePromptModeForSession", () => {
|
||||
expect(resolvePromptModeForSession("agent:main:subagent:child")).toBe("minimal");
|
||||
});
|
||||
|
||||
it("uses full mode for cron sessions", () => {
|
||||
expect(resolvePromptModeForSession("agent:main:cron:job-1")).toBe("full");
|
||||
expect(resolvePromptModeForSession("agent:main:cron:job-1:run:run-abc")).toBe("full");
|
||||
it("uses minimal mode for cron sessions", () => {
|
||||
expect(resolvePromptModeForSession("agent:main:cron:job-1")).toBe("minimal");
|
||||
expect(resolvePromptModeForSession("agent:main:cron:job-1:run:run-abc")).toBe("minimal");
|
||||
});
|
||||
|
||||
it("uses full mode for regular and undefined sessions", () => {
|
||||
expect(resolvePromptModeForSession(undefined)).toBe("full");
|
||||
expect(resolvePromptModeForSession("agent:main")).toBe("full");
|
||||
expect(resolvePromptModeForSession("agent:main:thread:abc")).toBe("full");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import type {
|
||||
PluginHookBeforeAgentStartResult,
|
||||
PluginHookBeforePromptBuildResult,
|
||||
} from "../../../plugins/types.js";
|
||||
import { isSubagentSessionKey } from "../../../routing/session-key.js";
|
||||
import { isCronSessionKey, isSubagentSessionKey } from "../../../routing/session-key.js";
|
||||
import { joinPresentTextSegments } from "../../../shared/text/join-segments.js";
|
||||
import { resolveSignalReactionLevel } from "../../../signal/reaction-level.js";
|
||||
import { resolveTelegramInlineButtonsScope } from "../../../telegram/inline-buttons.js";
|
||||
@@ -613,7 +613,7 @@ export function resolvePromptModeForSession(sessionKey?: string): "minimal" | "f
|
||||
if (!sessionKey) {
|
||||
return "full";
|
||||
}
|
||||
return isSubagentSessionKey(sessionKey) ? "minimal" : "full";
|
||||
return isSubagentSessionKey(sessionKey) || isCronSessionKey(sessionKey) ? "minimal" : "full";
|
||||
}
|
||||
|
||||
export function resolveAttemptFsWorkspaceOnly(params: {
|
||||
|
||||
@@ -197,6 +197,25 @@ describe("subagent announce timeout config", () => {
|
||||
expect(internalEvents[0]?.announceType).toBe("cron job");
|
||||
});
|
||||
|
||||
it("regression, keeps child announce internal when requester is a cron run session", async () => {
|
||||
const cronSessionKey = "agent:main:cron:daily-check:run:run-123";
|
||||
|
||||
await runAnnounceFlowForTest("run-cron-internal", {
|
||||
requesterSessionKey: cronSessionKey,
|
||||
requesterDisplayKey: cronSessionKey,
|
||||
requesterOrigin: { channel: "discord", to: "channel:cron-results", accountId: "acct-1" },
|
||||
});
|
||||
|
||||
const directAgentCall = findGatewayCall(
|
||||
(call) => call.method === "agent" && call.expectFinal === true,
|
||||
);
|
||||
expect(directAgentCall?.params?.sessionKey).toBe(cronSessionKey);
|
||||
expect(directAgentCall?.params?.deliver).toBe(false);
|
||||
expect(directAgentCall?.params?.channel).toBeUndefined();
|
||||
expect(directAgentCall?.params?.to).toBeUndefined();
|
||||
expect(directAgentCall?.params?.accountId).toBeUndefined();
|
||||
});
|
||||
|
||||
it("regression, routes child announce to parent session instead of grandparent when parent session still exists", async () => {
|
||||
const parentSessionKey = "agent:main:subagent:parent";
|
||||
requesterDepthResolver = (sessionKey?: string) =>
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { ConversationRef } from "../infra/outbound/session-binding-service.
|
||||
import { getGlobalHookRunner } from "../plugins/hook-runner-global.js";
|
||||
import { normalizeAccountId, normalizeMainKey } from "../routing/session-key.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { isCronSessionKey } from "../sessions/session-key-utils.js";
|
||||
import { extractTextFromChatContent } from "../shared/chat-content.js";
|
||||
import {
|
||||
type DeliveryContext,
|
||||
@@ -78,6 +79,10 @@ function resolveSubagentAnnounceTimeoutMs(cfg: ReturnType<typeof loadConfig>): n
|
||||
return Math.min(Math.max(1, Math.floor(configured)), MAX_TIMER_SAFE_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
function isInternalAnnounceRequesterSession(sessionKey: string | undefined): boolean {
|
||||
return getSubagentDepthFromSessionStore(sessionKey) >= 1 || isCronSessionKey(sessionKey);
|
||||
}
|
||||
|
||||
function summarizeDeliveryError(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return error.message || "error";
|
||||
@@ -580,8 +585,7 @@ async function resolveSubagentCompletionOrigin(params: {
|
||||
async function sendAnnounce(item: AnnounceQueueItem) {
|
||||
const cfg = loadConfig();
|
||||
const announceTimeoutMs = resolveSubagentAnnounceTimeoutMs(cfg);
|
||||
const requesterDepth = getSubagentDepthFromSessionStore(item.sessionKey);
|
||||
const requesterIsSubagent = requesterDepth >= 1;
|
||||
const requesterIsSubagent = isInternalAnnounceRequesterSession(item.sessionKey);
|
||||
const origin = item.origin;
|
||||
const threadId =
|
||||
origin?.threadId != null && origin.threadId !== "" ? String(origin.threadId) : undefined;
|
||||
@@ -1216,6 +1220,8 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
}
|
||||
|
||||
let requesterDepth = getSubagentDepthFromSessionStore(targetRequesterSessionKey);
|
||||
const requesterIsInternalSession = () =>
|
||||
requesterDepth >= 1 || isCronSessionKey(targetRequesterSessionKey);
|
||||
|
||||
let childCompletionFindings: string | undefined;
|
||||
let subagentRegistryRuntime:
|
||||
@@ -1339,7 +1345,7 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
const announceSessionId = childSessionId || "unknown";
|
||||
const findings = childCompletionFindings || reply || "(no output)";
|
||||
|
||||
let requesterIsSubagent = requesterDepth >= 1;
|
||||
let requesterIsSubagent = requesterIsInternalSession();
|
||||
if (requesterIsSubagent) {
|
||||
const {
|
||||
isSubagentSessionRunActive,
|
||||
@@ -1363,7 +1369,7 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
targetRequesterOrigin =
|
||||
normalizeDeliveryContext(fallback.requesterOrigin) ?? targetRequesterOrigin;
|
||||
requesterDepth = getSubagentDepthFromSessionStore(targetRequesterSessionKey);
|
||||
requesterIsSubagent = requesterDepth >= 1;
|
||||
requesterIsSubagent = requesterIsInternalSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user