refactor(cron): extract delivery dispatch + harden reset notices

This commit is contained in:
Peter Steinberger
2026-02-23 19:24:58 +00:00
parent fe62711342
commit 7a40d99b1d
3 changed files with 481 additions and 302 deletions

View File

@@ -221,4 +221,32 @@ describe("runPreparedReply media-only handling", () => {
expect(resetNoticeCall?.payload?.text).not.toContain("api-key");
expect(resetNoticeCall?.payload?.text).not.toContain("env:");
});
it("skips reset notice when only webchat fallback routing is available", async () => {
await runPreparedReply(
baseParams({
resetTriggered: true,
ctx: {
Body: "",
RawBody: "",
CommandBody: "",
ThreadHistoryBody: "Earlier message in this thread",
OriginatingChannel: undefined,
OriginatingTo: undefined,
ChatType: "group",
},
command: {
isAuthorizedSender: true,
abortKey: "session-key",
ownerList: [],
senderIsOwner: false,
channel: "webchat",
from: undefined,
to: undefined,
} as never,
}),
);
expect(vi.mocked(routeReply)).not.toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,414 @@
import { runSubagentAnnounceFlow } from "../../agents/subagent-announce.js";
import { countActiveDescendantRuns } from "../../agents/subagent-registry.js";
import { SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
import type { ReplyPayload } from "../../auto-reply/types.js";
import { createOutboundSendDeps, type CliDeps } from "../../cli/outbound-send-deps.js";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveAgentMainSessionKey } from "../../config/sessions.js";
import { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
import { resolveAgentOutboundIdentity } from "../../infra/outbound/identity.js";
import { resolveOutboundSessionRoute } from "../../infra/outbound/outbound-session.js";
import { logWarn } from "../../logger.js";
import type { CronJob, CronRunTelemetry } from "../types.js";
import type { DeliveryTargetResolution } from "./delivery-target.js";
import { pickSummaryFromOutput } from "./helpers.js";
import type { RunCronAgentTurnResult } from "./run.js";
import {
expectsSubagentFollowup,
isLikelyInterimCronMessage,
readDescendantSubagentFallbackReply,
waitForDescendantSubagentSummary,
} from "./subagent-followup.js";
export function matchesMessagingToolDeliveryTarget(
target: { provider?: string; to?: string; accountId?: string },
delivery: { channel?: string; to?: string; accountId?: string },
): boolean {
if (!delivery.channel || !delivery.to || !target.to) {
return false;
}
const channel = delivery.channel.trim().toLowerCase();
const provider = target.provider?.trim().toLowerCase();
if (provider && provider !== "message" && provider !== channel) {
return false;
}
if (target.accountId && delivery.accountId && target.accountId !== delivery.accountId) {
return false;
}
return target.to === delivery.to;
}
export function resolveCronDeliveryBestEffort(job: CronJob): boolean {
if (typeof job.delivery?.bestEffort === "boolean") {
return job.delivery.bestEffort;
}
if (job.payload.kind === "agentTurn" && typeof job.payload.bestEffortDeliver === "boolean") {
return job.payload.bestEffortDeliver;
}
return false;
}
async function resolveCronAnnounceSessionKey(params: {
cfg: OpenClawConfig;
agentId: string;
fallbackSessionKey: string;
delivery: {
channel: NonNullable<DeliveryTargetResolution["channel"]>;
to?: string;
accountId?: string;
threadId?: string | number;
};
}): Promise<string> {
const to = params.delivery.to?.trim();
if (!to) {
return params.fallbackSessionKey;
}
try {
const route = await resolveOutboundSessionRoute({
cfg: params.cfg,
channel: params.delivery.channel,
agentId: params.agentId,
accountId: params.delivery.accountId,
target: to,
threadId: params.delivery.threadId,
});
const resolved = route?.sessionKey?.trim();
if (resolved) {
return resolved;
}
} catch {
// Fall back to main session routing if announce session resolution fails.
}
return params.fallbackSessionKey;
}
export type SuccessfulDeliveryTarget = Extract<DeliveryTargetResolution, { ok: true }>;
type DispatchCronDeliveryParams = {
cfg: OpenClawConfig;
cfgWithAgentDefaults: OpenClawConfig;
deps: CliDeps;
job: CronJob;
agentId: string;
agentSessionKey: string;
runSessionId: string;
runStartedAt: number;
runEndedAt: number;
timeoutMs: number;
resolvedDelivery: DeliveryTargetResolution;
deliveryRequested: boolean;
skipHeartbeatDelivery: boolean;
skipMessagingToolDelivery: boolean;
deliveryBestEffort: boolean;
deliveryPayloadHasStructuredContent: boolean;
deliveryPayloads: ReplyPayload[];
synthesizedText?: string;
summary?: string;
outputText?: string;
telemetry?: CronRunTelemetry;
abortSignal?: AbortSignal;
isAborted: () => boolean;
abortReason: () => string;
withRunSession: (
result: Omit<RunCronAgentTurnResult, "sessionId" | "sessionKey">,
) => RunCronAgentTurnResult;
};
export type DispatchCronDeliveryState = {
result?: RunCronAgentTurnResult;
delivered: boolean;
summary?: string;
outputText?: string;
synthesizedText?: string;
deliveryPayloads: ReplyPayload[];
};
export async function dispatchCronDelivery(
params: DispatchCronDeliveryParams,
): Promise<DispatchCronDeliveryState> {
let summary = params.summary;
let outputText = params.outputText;
let synthesizedText = params.synthesizedText;
let deliveryPayloads = params.deliveryPayloads;
// `true` means we confirmed at least one outbound send reached the target.
// Keep this strict so timer fallback can safely decide whether to wake main.
let delivered = params.skipMessagingToolDelivery;
const failDeliveryTarget = (error: string) =>
params.withRunSession({
status: "error",
error,
errorKind: "delivery-target",
summary,
outputText,
...params.telemetry,
});
const deliverViaDirect = async (
delivery: SuccessfulDeliveryTarget,
): Promise<RunCronAgentTurnResult | null> => {
const identity = resolveAgentOutboundIdentity(params.cfgWithAgentDefaults, params.agentId);
try {
const payloadsForDelivery =
deliveryPayloads.length > 0
? deliveryPayloads
: synthesizedText
? [{ text: synthesizedText }]
: [];
if (payloadsForDelivery.length === 0) {
return null;
}
if (params.isAborted()) {
return params.withRunSession({
status: "error",
error: params.abortReason(),
...params.telemetry,
});
}
const deliveryResults = await deliverOutboundPayloads({
cfg: params.cfgWithAgentDefaults,
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
payloads: payloadsForDelivery,
agentId: params.agentId,
identity,
bestEffort: params.deliveryBestEffort,
deps: createOutboundSendDeps(params.deps),
abortSignal: params.abortSignal,
});
delivered = deliveryResults.length > 0;
return null;
} catch (err) {
if (!params.deliveryBestEffort) {
return params.withRunSession({
status: "error",
summary,
outputText,
error: String(err),
...params.telemetry,
});
}
return null;
}
};
const deliverViaAnnounce = async (
delivery: SuccessfulDeliveryTarget,
): Promise<RunCronAgentTurnResult | null> => {
if (!synthesizedText) {
return null;
}
const announceMainSessionKey = resolveAgentMainSessionKey({
cfg: params.cfg,
agentId: params.agentId,
});
const announceSessionKey = await resolveCronAnnounceSessionKey({
cfg: params.cfgWithAgentDefaults,
agentId: params.agentId,
fallbackSessionKey: announceMainSessionKey,
delivery: {
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
},
});
const taskLabel =
typeof params.job.name === "string" && params.job.name.trim()
? params.job.name.trim()
: `cron:${params.job.id}`;
const initialSynthesizedText = synthesizedText.trim();
let activeSubagentRuns = countActiveDescendantRuns(params.agentSessionKey);
const expectedSubagentFollowup = expectsSubagentFollowup(initialSynthesizedText);
const hadActiveDescendants = activeSubagentRuns > 0;
if (activeSubagentRuns > 0 || expectedSubagentFollowup) {
let finalReply = await waitForDescendantSubagentSummary({
sessionKey: params.agentSessionKey,
initialReply: initialSynthesizedText,
timeoutMs: params.timeoutMs,
observedActiveDescendants: activeSubagentRuns > 0 || expectedSubagentFollowup,
});
activeSubagentRuns = countActiveDescendantRuns(params.agentSessionKey);
if (
!finalReply &&
activeSubagentRuns === 0 &&
(hadActiveDescendants || expectedSubagentFollowup)
) {
finalReply = await readDescendantSubagentFallbackReply({
sessionKey: params.agentSessionKey,
runStartedAt: params.runStartedAt,
});
}
if (finalReply && activeSubagentRuns === 0) {
outputText = finalReply;
summary = pickSummaryFromOutput(finalReply) ?? summary;
synthesizedText = finalReply;
deliveryPayloads = [{ text: finalReply }];
}
}
if (activeSubagentRuns > 0) {
// Parent orchestration is still in progress; avoid announcing a partial
// update to the main requester.
return params.withRunSession({ status: "ok", summary, outputText, ...params.telemetry });
}
if (
(hadActiveDescendants || expectedSubagentFollowup) &&
synthesizedText.trim() === initialSynthesizedText &&
isLikelyInterimCronMessage(initialSynthesizedText) &&
initialSynthesizedText.toUpperCase() !== SILENT_REPLY_TOKEN.toUpperCase()
) {
// Descendants existed but no post-orchestration synthesis arrived, so
// suppress stale parent text like "on it, pulling everything together".
return params.withRunSession({ status: "ok", summary, outputText, ...params.telemetry });
}
if (synthesizedText.toUpperCase() === SILENT_REPLY_TOKEN.toUpperCase()) {
return params.withRunSession({
status: "ok",
summary,
outputText,
delivered: true,
...params.telemetry,
});
}
try {
if (params.isAborted()) {
return params.withRunSession({
status: "error",
error: params.abortReason(),
...params.telemetry,
});
}
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: params.agentSessionKey,
childRunId: `${params.job.id}:${params.runSessionId}:${params.runStartedAt}`,
requesterSessionKey: announceSessionKey,
requesterOrigin: {
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
},
requesterDisplayKey: announceSessionKey,
task: taskLabel,
timeoutMs: params.timeoutMs,
cleanup: params.job.deleteAfterRun ? "delete" : "keep",
roundOneReply: synthesizedText,
// Keep delivery outcome truthful for cron state: if outbound send fails,
// announce flow must report false so caller can apply best-effort policy.
bestEffortDeliver: false,
waitForCompletion: false,
startedAt: params.runStartedAt,
endedAt: params.runEndedAt,
outcome: { status: "ok" },
announceType: "cron job",
signal: params.abortSignal,
});
if (didAnnounce) {
delivered = true;
} else {
const message = "cron announce delivery failed";
if (!params.deliveryBestEffort) {
return params.withRunSession({
status: "error",
summary,
outputText,
error: message,
...params.telemetry,
});
}
logWarn(`[cron:${params.job.id}] ${message}`);
}
} catch (err) {
if (!params.deliveryBestEffort) {
return params.withRunSession({
status: "error",
summary,
outputText,
error: String(err),
...params.telemetry,
});
}
logWarn(`[cron:${params.job.id}] ${String(err)}`);
}
return null;
};
if (
params.deliveryRequested &&
!params.skipHeartbeatDelivery &&
!params.skipMessagingToolDelivery
) {
if (!params.resolvedDelivery.ok) {
if (!params.deliveryBestEffort) {
return {
result: failDeliveryTarget(params.resolvedDelivery.error.message),
delivered,
summary,
outputText,
synthesizedText,
deliveryPayloads,
};
}
logWarn(`[cron:${params.job.id}] ${params.resolvedDelivery.error.message}`);
return {
result: params.withRunSession({
status: "ok",
summary,
outputText,
...params.telemetry,
}),
delivered,
summary,
outputText,
synthesizedText,
deliveryPayloads,
};
}
// Route text-only cron announce output back through the main session so it
// follows the same system-message injection path as subagent completions.
// Keep direct outbound delivery only for structured payloads (media/channel
// data), which cannot be represented by the shared announce flow.
//
// Forum/topic targets should also use direct delivery. Announce flow can
// be swallowed by ANNOUNCE_SKIP/NO_REPLY in the target agent turn, which
// silently drops cron output for topic-bound sessions.
const useDirectDelivery =
params.deliveryPayloadHasStructuredContent || params.resolvedDelivery.threadId != null;
if (useDirectDelivery) {
const directResult = await deliverViaDirect(params.resolvedDelivery);
if (directResult) {
return {
result: directResult,
delivered,
summary,
outputText,
synthesizedText,
deliveryPayloads,
};
}
} else {
const announceResult = await deliverViaAnnounce(params.resolvedDelivery);
if (announceResult) {
return {
result: announceResult,
delivered,
summary,
outputText,
synthesizedText,
deliveryPayloads,
};
}
}
}
return {
delivered,
summary,
outputText,
synthesizedText,
deliveryPayloads,
};
}

View File

@@ -21,10 +21,7 @@ import {
resolveHooksGmailModel,
resolveThinkingDefault,
} from "../../agents/model-selection.js";
import type { MessagingToolSend } from "../../agents/pi-embedded-messaging.js";
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
import { runSubagentAnnounceFlow } from "../../agents/subagent-announce.js";
import { countActiveDescendantRuns } from "../../agents/subagent-registry.js";
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
import { deriveSessionTotalTokens, hasNonzeroUsage } from "../../agents/usage.js";
import { ensureAgentWorkspace } from "../../agents/workspace.js";
@@ -33,19 +30,11 @@ import {
normalizeVerboseLevel,
supportsXHighThinking,
} from "../../auto-reply/thinking.js";
import { SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
import { createOutboundSendDeps, type CliDeps } from "../../cli/outbound-send-deps.js";
import type { CliDeps } from "../../cli/outbound-send-deps.js";
import type { OpenClawConfig } from "../../config/config.js";
import {
resolveAgentMainSessionKey,
resolveSessionTranscriptPath,
updateSessionStore,
} from "../../config/sessions.js";
import { resolveSessionTranscriptPath, updateSessionStore } from "../../config/sessions.js";
import type { AgentDefaultsConfig } from "../../config/types.js";
import { registerAgentRunContext } from "../../infra/agent-events.js";
import { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
import { resolveAgentOutboundIdentity } from "../../infra/outbound/identity.js";
import { resolveOutboundSessionRoute } from "../../infra/outbound/outbound-session.js";
import { logWarn } from "../../logger.js";
import { buildAgentMainSessionKey, normalizeAgentId } from "../../routing/session-key.js";
import {
@@ -56,6 +45,11 @@ import {
} from "../../security/external-content.js";
import { resolveCronDeliveryPlan } from "../delivery.js";
import type { CronJob, CronRunOutcome, CronRunTelemetry } from "../types.js";
import {
dispatchCronDelivery,
matchesMessagingToolDeliveryTarget,
resolveCronDeliveryBestEffort,
} from "./delivery-dispatch.js";
import { resolveDeliveryTarget } from "./delivery-target.js";
import {
isHeartbeatOnlyResponse,
@@ -67,74 +61,6 @@ import {
} from "./helpers.js";
import { resolveCronSession } from "./session.js";
import { resolveCronSkillsSnapshot } from "./skills-snapshot.js";
import {
expectsSubagentFollowup,
isLikelyInterimCronMessage,
readDescendantSubagentFallbackReply,
waitForDescendantSubagentSummary,
} from "./subagent-followup.js";
function matchesMessagingToolDeliveryTarget(
target: MessagingToolSend,
delivery: { channel?: string; to?: string; accountId?: string },
): boolean {
if (!delivery.channel || !delivery.to || !target.to) {
return false;
}
const channel = delivery.channel.trim().toLowerCase();
const provider = target.provider?.trim().toLowerCase();
if (provider && provider !== "message" && provider !== channel) {
return false;
}
if (target.accountId && delivery.accountId && target.accountId !== delivery.accountId) {
return false;
}
return target.to === delivery.to;
}
function resolveCronDeliveryBestEffort(job: CronJob): boolean {
if (typeof job.delivery?.bestEffort === "boolean") {
return job.delivery.bestEffort;
}
if (job.payload.kind === "agentTurn" && typeof job.payload.bestEffortDeliver === "boolean") {
return job.payload.bestEffortDeliver;
}
return false;
}
async function resolveCronAnnounceSessionKey(params: {
cfg: OpenClawConfig;
agentId: string;
fallbackSessionKey: string;
delivery: {
channel: Parameters<typeof resolveOutboundSessionRoute>[0]["channel"];
to?: string;
accountId?: string;
threadId?: string | number;
};
}): Promise<string> {
const to = params.delivery.to?.trim();
if (!to) {
return params.fallbackSessionKey;
}
try {
const route = await resolveOutboundSessionRoute({
cfg: params.cfg,
channel: params.delivery.channel,
agentId: params.agentId,
accountId: params.delivery.accountId,
target: to,
threadId: params.delivery.threadId,
});
const resolved = route?.sessionKey?.trim();
if (resolved) {
return resolved;
}
} catch {
// Fall back to main session routing if announce session resolution fails.
}
return params.fallbackSessionKey;
}
export type RunCronAgentTurnResult = {
/** Last non-empty agent text output (not truncated). */
@@ -632,228 +558,39 @@ export async function runCronIsolatedAgentTurn(params: {
}),
);
// `true` means we confirmed at least one outbound send reached the target.
// Keep this strict so timer fallback can safely decide whether to wake main.
let delivered = skipMessagingToolDelivery;
type SuccessfulDeliveryTarget = Extract<
Awaited<ReturnType<typeof resolveDeliveryTarget>>,
{ ok: true }
>;
const failDeliveryTarget = (error: string) =>
withRunSession({
status: "error",
error,
errorKind: "delivery-target",
summary,
outputText,
...telemetry,
});
const deliverViaDirect = async (
delivery: SuccessfulDeliveryTarget,
): Promise<RunCronAgentTurnResult | null> => {
const identity = resolveAgentOutboundIdentity(cfgWithAgentDefaults, agentId);
try {
const payloadsForDelivery =
deliveryPayloads.length > 0
? deliveryPayloads
: synthesizedText
? [{ text: synthesizedText }]
: [];
if (payloadsForDelivery.length === 0) {
return null;
}
if (isAborted()) {
return withRunSession({ status: "error", error: abortReason(), ...telemetry });
}
const deliveryResults = await deliverOutboundPayloads({
cfg: cfgWithAgentDefaults,
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
payloads: payloadsForDelivery,
agentId,
identity,
bestEffort: deliveryBestEffort,
deps: createOutboundSendDeps(params.deps),
abortSignal,
});
delivered = deliveryResults.length > 0;
return null;
} catch (err) {
if (!deliveryBestEffort) {
return withRunSession({
status: "error",
summary,
outputText,
error: String(err),
...telemetry,
});
}
return null;
}
};
const deliverViaAnnounce = async (
delivery: SuccessfulDeliveryTarget,
): Promise<RunCronAgentTurnResult | null> => {
if (!synthesizedText) {
return null;
}
const announceMainSessionKey = resolveAgentMainSessionKey({
cfg: params.cfg,
agentId,
});
const announceSessionKey = await resolveCronAnnounceSessionKey({
cfg: cfgWithAgentDefaults,
agentId,
fallbackSessionKey: announceMainSessionKey,
delivery: {
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
},
});
const taskLabel =
typeof params.job.name === "string" && params.job.name.trim()
? params.job.name.trim()
: `cron:${params.job.id}`;
const initialSynthesizedText = synthesizedText.trim();
let activeSubagentRuns = countActiveDescendantRuns(agentSessionKey);
const expectedSubagentFollowup = expectsSubagentFollowup(initialSynthesizedText);
const hadActiveDescendants = activeSubagentRuns > 0;
if (activeSubagentRuns > 0 || expectedSubagentFollowup) {
let finalReply = await waitForDescendantSubagentSummary({
sessionKey: agentSessionKey,
initialReply: initialSynthesizedText,
timeoutMs,
observedActiveDescendants: activeSubagentRuns > 0 || expectedSubagentFollowup,
});
activeSubagentRuns = countActiveDescendantRuns(agentSessionKey);
if (
!finalReply &&
activeSubagentRuns === 0 &&
(hadActiveDescendants || expectedSubagentFollowup)
) {
finalReply = await readDescendantSubagentFallbackReply({
sessionKey: agentSessionKey,
runStartedAt,
});
}
if (finalReply && activeSubagentRuns === 0) {
outputText = finalReply;
summary = pickSummaryFromOutput(finalReply) ?? summary;
synthesizedText = finalReply;
deliveryPayloads = [{ text: finalReply }];
}
}
if (activeSubagentRuns > 0) {
// Parent orchestration is still in progress; avoid announcing a partial
// update to the main requester.
return withRunSession({ status: "ok", summary, outputText, ...telemetry });
}
if (
(hadActiveDescendants || expectedSubagentFollowup) &&
synthesizedText.trim() === initialSynthesizedText &&
isLikelyInterimCronMessage(initialSynthesizedText) &&
initialSynthesizedText.toUpperCase() !== SILENT_REPLY_TOKEN.toUpperCase()
) {
// Descendants existed but no post-orchestration synthesis arrived, so
// suppress stale parent text like "on it, pulling everything together".
return withRunSession({ status: "ok", summary, outputText, ...telemetry });
}
if (synthesizedText.toUpperCase() === SILENT_REPLY_TOKEN.toUpperCase()) {
return withRunSession({ status: "ok", summary, outputText, delivered: true, ...telemetry });
}
try {
if (isAborted()) {
return withRunSession({ status: "error", error: abortReason(), ...telemetry });
}
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: agentSessionKey,
childRunId: `${params.job.id}:${runSessionId}:${runStartedAt}`,
requesterSessionKey: announceSessionKey,
requesterOrigin: {
channel: delivery.channel,
to: delivery.to,
accountId: delivery.accountId,
threadId: delivery.threadId,
},
requesterDisplayKey: announceSessionKey,
task: taskLabel,
timeoutMs,
cleanup: params.job.deleteAfterRun ? "delete" : "keep",
roundOneReply: synthesizedText,
// Keep delivery outcome truthful for cron state: if outbound send fails,
// announce flow must report false so caller can apply best-effort policy.
bestEffortDeliver: false,
waitForCompletion: false,
startedAt: runStartedAt,
endedAt: runEndedAt,
outcome: { status: "ok" },
announceType: "cron job",
signal: abortSignal,
});
if (didAnnounce) {
delivered = true;
} else {
const message = "cron announce delivery failed";
if (!deliveryBestEffort) {
return withRunSession({
status: "error",
summary,
outputText,
error: message,
...telemetry,
});
}
logWarn(`[cron:${params.job.id}] ${message}`);
}
} catch (err) {
if (!deliveryBestEffort) {
return withRunSession({
status: "error",
summary,
outputText,
error: String(err),
...telemetry,
});
}
logWarn(`[cron:${params.job.id}] ${String(err)}`);
}
return null;
};
if (deliveryRequested && !skipHeartbeatDelivery && !skipMessagingToolDelivery) {
if (!resolvedDelivery.ok) {
if (!deliveryBestEffort) {
return failDeliveryTarget(resolvedDelivery.error.message);
}
logWarn(`[cron:${params.job.id}] ${resolvedDelivery.error.message}`);
return withRunSession({ status: "ok", summary, outputText, ...telemetry });
}
// Route text-only cron announce output back through the main session so it
// follows the same system-message injection path as subagent completions.
// Keep direct outbound delivery only for structured payloads (media/channel
// data), which cannot be represented by the shared announce flow.
//
// Forum/topic targets should also use direct delivery. Announce flow can
// be swallowed by ANNOUNCE_SKIP/NO_REPLY in the target agent turn, which
// silently drops cron output for topic-bound sessions.
const useDirectDelivery =
deliveryPayloadHasStructuredContent || resolvedDelivery.threadId != null;
if (useDirectDelivery) {
const directResult = await deliverViaDirect(resolvedDelivery);
if (directResult) {
return directResult;
}
} else {
const announceResult = await deliverViaAnnounce(resolvedDelivery);
if (announceResult) {
return announceResult;
}
}
const deliveryResult = await dispatchCronDelivery({
cfg: params.cfg,
cfgWithAgentDefaults,
deps: params.deps,
job: params.job,
agentId,
agentSessionKey,
runSessionId,
runStartedAt,
runEndedAt,
timeoutMs,
resolvedDelivery,
deliveryRequested,
skipHeartbeatDelivery,
skipMessagingToolDelivery,
deliveryBestEffort,
deliveryPayloadHasStructuredContent,
deliveryPayloads,
synthesizedText,
summary,
outputText,
telemetry,
abortSignal,
isAborted,
abortReason,
withRunSession,
});
if (deliveryResult.result) {
return deliveryResult.result;
}
const delivered = deliveryResult.delivered;
summary = deliveryResult.summary;
outputText = deliveryResult.outputText;
return withRunSession({ status: "ok", summary, outputText, delivered, ...telemetry });
}