Skip to content

Commit 9d2c7bc

Browse files
committed
docs: document cron delivery helpers
1 parent a10dfb7 commit 9d2c7bc

7 files changed

Lines changed: 21 additions & 0 deletions

File tree

src/cron/active-jobs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Tracks in-process cron executions so schedulers and wake paths avoid duplicate runs. */
12
import { resolveGlobalSingleton } from "../shared/global-singleton.js";
23

34
type CronActiveJobState = {

src/cron/delivery-context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Converts live or stored session routing into cron delivery config. */
12
import { extractDeliveryInfo } from "../config/sessions/delivery-info.js";
23
import type { OpenClawConfig } from "../config/types.openclaw.js";
34
import {

src/cron/delivery-field-schemas.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Parses user-provided cron delivery fields into narrow runtime values. */
12
import { normalizeOptionalLowercaseString } from "@openclaw/normalization-core/string-coerce";
23
import { z, type ZodType } from "zod";
34

@@ -8,6 +9,7 @@ const trimLowercaseStringPreprocess = (value: unknown) =>
89

910
const DeliveryModeFieldSchema = z
1011
.preprocess(trimLowercaseStringPreprocess, z.enum(["deliver", "announce", "none", "webhook"]))
12+
// "deliver" is the historical CLI spelling; runtime delivery uses announce.
1113
.transform((value) => (value === "deliver" ? "announce" : value));
1214

1315
/** Accepts non-empty string fields after trimming and lowercasing user-provided delivery input. */

src/cron/delivery-plan.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Resolves cron delivery and failure-notification routing from job config. */
12
import {
23
normalizeLowercaseStringOrEmpty,
34
normalizeOptionalLowercaseString,
@@ -42,6 +43,8 @@ function resolveAnnounceChannel(params: {
4243
if (params.channel && params.channel !== "last") {
4344
return params.channel;
4445
}
46+
// A prefixed recipient like "slack:C123" is enough to infer the channel when
47+
// the cron config intentionally leaves channel at "last" or unset.
4548
return (
4649
(resolveTargetPrefixedChannel(params.to) as CronMessageChannel | undefined) ??
4750
params.channel ??
@@ -101,6 +104,8 @@ export function resolveCronDeliveryPlan(job: CronJob): CronDeliveryPlan {
101104
(job.sessionTarget === "isolated" ||
102105
job.sessionTarget === "current" ||
103106
job.sessionTarget.startsWith("session:"));
107+
// Isolated/current/session cron jobs default to announce delivery so their
108+
// output reaches the initiating session unless the job opts out.
104109
const resolvedMode = isIsolatedAgentTurn ? "announce" : "none";
105110

106111
return {
@@ -196,6 +201,7 @@ export function resolveFailureDestination(
196201

197202
const resolvedMode = mode ?? "announce";
198203
if (resolvedMode === "webhook" && !to) {
204+
// Webhook failure destinations are only useful with a concrete URL/target.
199205
return null;
200206
}
201207

@@ -207,6 +213,7 @@ export function resolveFailureDestination(
207213
};
208214

209215
if (delivery && isSameDeliveryTarget(delivery, result)) {
216+
// Avoid sending the same failure text through the primary delivery route twice.
210217
return null;
211218
}
212219

src/cron/delivery-preview.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Builds dry-run cron delivery labels for CLI/UI list surfaces. */
12
import { resolveDefaultAgentId } from "../agents/agent-scope-config.js";
23
import type { OpenClawConfig } from "../config/types.openclaw.js";
34
import { hasExplicitCronDeliveryTarget, resolveCronDeliveryPlan } from "./delivery-plan.js";
@@ -45,6 +46,7 @@ export async function resolveCronDeliveryPreview(params: {
4546
return { label: "not requested", detail: "not requested" };
4647
}
4748
if (plan.mode === "webhook") {
49+
// Webhook previews do not resolve channel targets; runtime only needs the configured URL.
4850
const target = plan.to ? `webhook:${plan.to}` : "webhook";
4951
return { label: target, detail: plan.to ? "webhook" : "webhook target missing" };
5052
}

src/cron/delivery.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Sends cron announce payloads and best-effort failure notifications. */
12
import { sendDurableMessageBatch } from "../channels/message/runtime.js";
23
import type { CliDeps } from "../cli/deps.types.js";
34
import { createOutboundSendDeps } from "../cli/outbound-send-deps.js";
@@ -55,6 +56,8 @@ async function resolveCronAnnounceDelivery(params: {
5556
}
5657
| { ok: false; error: Error }
5758
> {
59+
// Resolve the target before building outbound identity/session so send errors
60+
// report the configured route, not only the cron job id.
5861
const resolvedTarget = await resolveDeliveryTarget(params.cfg, params.agentId, {
5962
channel: params.target.channel as CronMessageChannel | undefined,
6063
to: params.target.to,
@@ -95,6 +98,8 @@ async function deliverCronAnnouncePayload(params: {
9598
message: string;
9699
abortSignal: AbortSignal;
97100
}): Promise<void> {
101+
// Cron delivery is durable and non-best-effort for primary announces; partial
102+
// channel failure must surface as a cron run failure.
98103
const send = await sendDurableMessageBatch({
99104
cfg: params.cfg,
100105
channel: params.delivery.resolvedTarget.channel,

src/cron/heartbeat-policy.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Decides when cron heartbeat acknowledgements should stay out of visible delivery. */
12
import { hasOutboundReplyContent } from "openclaw/plugin-sdk/reply-payload";
23
import { stripHeartbeatToken } from "../auto-reply/heartbeat.js";
34

@@ -24,6 +25,8 @@ export function shouldSkipHeartbeatOnlyDelivery(
2425
if (hasAnyNonTextContent) {
2526
return false;
2627
}
28+
// Heartbeat acks may include tiny punctuation/noise; strip the token before
29+
// deciding whether there is user-visible text worth delivering.
2730
return payloads.some((payload) => {
2831
const result = stripHeartbeatToken(payload.text, {
2932
mode: "heartbeat",

0 commit comments

Comments
 (0)