mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
Cron: suppress fallback main summary for delivery-target errors (openclaw#24074) thanks @Takhoffman
Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: Takhoffman <781889+Takhoffman@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -78,6 +78,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Cron/Timer: keep a watchdog recheck timer armed while `onTimer` is actively executing so the scheduler continues polling even if a due-run tick stalls for an extended period. (#23628) Thanks @dsgraves.
|
||||
- Cron/Run log: clean up settled per-path run-log write queue entries so long-running cron uptime does not retain stale promise bookkeeping in memory.
|
||||
- Cron/Run log: harden `cron.runs` run-log path resolution by rejecting path-separator `id`/`jobId` inputs and enforcing reads within the per-cron `runs/` directory.
|
||||
- Cron/Announce: when announce delivery target resolution fails (for example multiple configured channels with no explicit target), skip injecting fallback `Cron (error): ...` into the main session so runs fail cleanly without accidental last-route sends. (#24074)
|
||||
- Cron/Isolation: force fresh session IDs for isolated cron runs so `sessionTarget="isolated"` executions never reuse prior run context. (#23470) Thanks @echoVic.
|
||||
- Plugins/Install: strip `workspace:*` devDependency entries from copied plugin manifests before `npm install --omit=dev`, preventing `EUNSUPPORTEDPROTOCOL` install failures for npm-published channel plugins (including Feishu and MS Teams).
|
||||
- Feishu/Plugins: restore bundled Feishu SDK availability for global installs and strip `openclaw: workspace:*` from plugin `devDependencies` during plugin-version sync so npm-installed Feishu plugins do not fail dependency install. (#23611, #23645, #23603)
|
||||
|
||||
@@ -635,29 +635,26 @@ 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;
|
||||
const failDeliveryTarget = (error: string) =>
|
||||
withRunSession({
|
||||
status: "error",
|
||||
error,
|
||||
errorKind: "delivery-target",
|
||||
summary,
|
||||
outputText,
|
||||
...telemetry,
|
||||
});
|
||||
if (deliveryRequested && !skipHeartbeatDelivery && !skipMessagingToolDelivery) {
|
||||
if (resolvedDelivery.error) {
|
||||
if (!deliveryBestEffort) {
|
||||
return withRunSession({
|
||||
status: "error",
|
||||
error: resolvedDelivery.error.message,
|
||||
summary,
|
||||
outputText,
|
||||
...telemetry,
|
||||
});
|
||||
return failDeliveryTarget(resolvedDelivery.error.message);
|
||||
}
|
||||
logWarn(`[cron:${params.job.id}] ${resolvedDelivery.error.message}`);
|
||||
return withRunSession({ status: "ok", summary, outputText, ...telemetry });
|
||||
}
|
||||
const failOrWarnMissingDeliveryField = (message: string) => {
|
||||
if (!deliveryBestEffort) {
|
||||
return withRunSession({
|
||||
status: "error",
|
||||
error: message,
|
||||
summary,
|
||||
outputText,
|
||||
...telemetry,
|
||||
});
|
||||
return failDeliveryTarget(message);
|
||||
}
|
||||
logWarn(`[cron:${params.job.id}] ${message}`);
|
||||
return withRunSession({ status: "ok", summary, outputText, ...telemetry });
|
||||
|
||||
@@ -680,6 +680,28 @@ describe("CronService", () => {
|
||||
await store.cleanup();
|
||||
});
|
||||
|
||||
it("does not post fallback main summary for isolated delivery-target errors", async () => {
|
||||
const runIsolatedAgentJob = vi.fn(async () => ({
|
||||
status: "error" as const,
|
||||
summary: "last output",
|
||||
error: "Channel is required when multiple channels are configured: telegram, discord",
|
||||
errorKind: "delivery-target" as const,
|
||||
}));
|
||||
const { store, cron, enqueueSystemEvent, requestHeartbeatNow, events } =
|
||||
await createIsolatedAnnounceHarness(runIsolatedAgentJob);
|
||||
await runIsolatedAnnounceJobAndWait({
|
||||
cron,
|
||||
events,
|
||||
name: "isolated delivery target error test",
|
||||
status: "error",
|
||||
});
|
||||
|
||||
expect(enqueueSystemEvent).not.toHaveBeenCalled();
|
||||
expect(requestHeartbeatNow).not.toHaveBeenCalled();
|
||||
cron.stop();
|
||||
await store.cleanup();
|
||||
});
|
||||
|
||||
it("rejects unsupported session/payload combinations", async () => {
|
||||
ensureDir(fixturesRoot);
|
||||
const store = await makeStorePath();
|
||||
|
||||
@@ -737,7 +737,9 @@ export async function executeJobCore(
|
||||
// See: https://github.com/openclaw/openclaw/issues/15692
|
||||
const summaryText = res.summary?.trim();
|
||||
const deliveryPlan = resolveCronDeliveryPlan(job);
|
||||
if (summaryText && deliveryPlan.requested && !res.delivered) {
|
||||
const suppressMainSummary =
|
||||
res.status === "error" && res.errorKind === "delivery-target" && deliveryPlan.requested;
|
||||
if (summaryText && deliveryPlan.requested && !res.delivered && !suppressMainSummary) {
|
||||
const prefix = "Cron";
|
||||
const label =
|
||||
res.status === "error" ? `${prefix} (error): ${summaryText}` : `${prefix}: ${summaryText}`;
|
||||
|
||||
@@ -47,6 +47,8 @@ export type CronRunTelemetry = {
|
||||
export type CronRunOutcome = {
|
||||
status: CronRunStatus;
|
||||
error?: string;
|
||||
/** Optional classifier for execution errors to guide fallback behavior. */
|
||||
errorKind?: "delivery-target";
|
||||
summary?: string;
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
|
||||
Reference in New Issue
Block a user