refactor(cron): extract delivery tool policy helpers

This commit is contained in:
Peter Steinberger 2026-03-08 00:31:30 +00:00
parent 45d3e62f50
commit 9b99787c31

View File

@ -142,6 +142,54 @@ function buildCronAgentDefaultsConfig(params: {
});
}
type ResolvedCronDeliveryTarget = Awaited<ReturnType<typeof resolveDeliveryTarget>>;
function resolveCronToolPolicy(params: {
deliveryRequested: boolean;
resolvedDelivery: ResolvedCronDeliveryTarget;
}) {
return {
// Only enforce an explicit message target when the cron delivery target
// was successfully resolved. When resolution fails the agent should not
// be blocked by a target it cannot satisfy (#27898).
requireExplicitMessageTarget: params.deliveryRequested && params.resolvedDelivery.ok,
disableMessageTool: params.deliveryRequested,
};
}
async function resolveCronDeliveryContext(params: {
cfg: OpenClawConfig;
job: CronJob;
agentId: string;
}) {
const deliveryPlan = resolveCronDeliveryPlan(params.job);
const resolvedDelivery = await resolveDeliveryTarget(params.cfg, params.agentId, {
channel: deliveryPlan.channel ?? "last",
to: deliveryPlan.to,
accountId: deliveryPlan.accountId,
sessionKey: params.job.sessionKey,
});
return {
deliveryPlan,
deliveryRequested: deliveryPlan.requested,
resolvedDelivery,
toolPolicy: resolveCronToolPolicy({
deliveryRequested: deliveryPlan.requested,
resolvedDelivery,
}),
};
}
function appendCronDeliveryInstruction(params: {
commandBody: string;
deliveryRequested: boolean;
}) {
if (!params.deliveryRequested) {
return params.commandBody;
}
return `${params.commandBody}\n\nReturn your summary as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`.trim();
}
export async function runCronIsolatedAgentTurn(params: {
cfg: OpenClawConfig;
deps: CliDeps;
@ -373,14 +421,10 @@ export async function runCronIsolatedAgentTurn(params: {
});
const agentPayload = params.job.payload.kind === "agentTurn" ? params.job.payload : null;
const deliveryPlan = resolveCronDeliveryPlan(params.job);
const deliveryRequested = deliveryPlan.requested;
const resolvedDelivery = await resolveDeliveryTarget(cfgWithAgentDefaults, agentId, {
channel: deliveryPlan.channel ?? "last",
to: deliveryPlan.to,
accountId: deliveryPlan.accountId,
sessionKey: params.job.sessionKey,
const { deliveryRequested, resolvedDelivery, toolPolicy } = await resolveCronDeliveryContext({
cfg: cfgWithAgentDefaults,
job: params.job,
agentId,
});
const { formattedTime, timeLine } = resolveCronStyleNow(params.cfg, now);
@ -422,10 +466,7 @@ export async function runCronIsolatedAgentTurn(params: {
// Internal/trusted source - use original format
commandBody = `${base}\n${timeLine}`.trim();
}
if (deliveryRequested) {
commandBody =
`${commandBody}\n\nReturn your summary as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`.trim();
}
commandBody = appendCronDeliveryInstruction({ commandBody, deliveryRequested });
const existingSkillsSnapshot = cronSession.sessionEntry.skillsSnapshot;
const skillsSnapshot = resolveCronSkillsSnapshot({
@ -566,11 +607,8 @@ export async function runCronIsolatedAgentTurn(params: {
bootstrapContextMode: agentPayload?.lightContext ? "lightweight" : undefined,
bootstrapContextRunKind: "cron",
runId: cronSession.sessionEntry.sessionId,
// Only enforce an explicit message target when the cron delivery target
// was successfully resolved. When resolution fails the agent should not
// be blocked by a target it cannot satisfy (#27898).
requireExplicitMessageTarget: deliveryRequested && resolvedDelivery.ok,
disableMessageTool: deliveryRequested,
requireExplicitMessageTarget: toolPolicy.requireExplicitMessageTarget,
disableMessageTool: toolPolicy.disableMessageTool,
allowTransientCooldownProbe: runOptions?.allowTransientCooldownProbe,
abortSignal,
bootstrapPromptWarningSignaturesSeen,