fix(cron): suppress fallback summary after attempted announce delivery

This commit is contained in:
Peter Steinberger
2026-02-26 03:07:27 +00:00
parent e16e8f5af2
commit b37dc42240
7 changed files with 108 additions and 11 deletions

View File

@@ -80,6 +80,11 @@ export type CronServiceDeps = {
* https://github.com/openclaw/openclaw/issues/15692
*/
delivered?: boolean;
/**
* `true` when announce/direct delivery was attempted for this run, even
* if the final per-message ack status is uncertain.
*/
deliveryAttempted?: boolean;
} & CronRunOutcome &
CronRunTelemetry
>;

View File

@@ -41,6 +41,7 @@ type TimedCronRunOutcome = CronRunOutcome &
CronRunTelemetry & {
jobId: string;
delivered?: boolean;
deliveryAttempted?: boolean;
startedAt: number;
endedAt: number;
};
@@ -606,7 +607,9 @@ export async function executeJobCore(
state: CronServiceState,
job: CronJob,
abortSignal?: AbortSignal,
): Promise<CronRunOutcome & CronRunTelemetry & { delivered?: boolean }> {
): Promise<
CronRunOutcome & CronRunTelemetry & { delivered?: boolean; deliveryAttempted?: boolean }
> {
const resolveAbortError = () => ({
status: "error" as const,
error: timeoutErrorMessage(),
@@ -729,17 +732,22 @@ export async function executeJobCore(
return { status: "error", error: timeoutErrorMessage() };
}
// Post a short summary back to the main session — but only when the
// isolated run did NOT already deliver its output to the target channel.
// When `res.delivered` is true the announce flow (or direct outbound
// delivery) already sent the result, so posting the summary to main
// would wake the main agent and cause a duplicate message.
// Post a short summary back to the main session only when announce
// delivery was requested and we are confident no outbound delivery path
// ran. If delivery was attempted but final ack is uncertain, suppress the
// main summary to avoid duplicate user-facing sends.
// See: https://github.com/openclaw/openclaw/issues/15692
const summaryText = res.summary?.trim();
const deliveryPlan = resolveCronDeliveryPlan(job);
const suppressMainSummary =
res.status === "error" && res.errorKind === "delivery-target" && deliveryPlan.requested;
if (summaryText && deliveryPlan.requested && !res.delivered && !suppressMainSummary) {
if (
summaryText &&
deliveryPlan.requested &&
!res.delivered &&
res.deliveryAttempted !== true &&
!suppressMainSummary
) {
const prefix = "Cron";
const label =
res.status === "error" ? `${prefix} (error): ${summaryText}` : `${prefix}: ${summaryText}`;
@@ -762,6 +770,7 @@ export async function executeJobCore(
error: res.error,
summary: res.summary,
delivered: res.delivered,
deliveryAttempted: res.deliveryAttempted,
sessionId: res.sessionId,
sessionKey: res.sessionKey,
model: res.model,