feat(cron): introduce delivery modes for isolated jobs
- Added support for new delivery modes in cron jobs: `announce`, `deliver`, and `none`. - Updated documentation to reflect changes in delivery options and usage examples. - Enhanced the cron job schema to include delivery configuration. - Refactored related CLI commands and UI components to accommodate the new delivery settings. - Improved handling of legacy delivery fields for backward compatibility. This update allows users to choose how output from isolated jobs is delivered, enhancing flexibility in job management.
This commit is contained in:
committed by
Peter Steinberger
parent
3a03e38378
commit
511c656cbc
@@ -80,11 +80,12 @@ export function registerCronAddCommand(cron: Command) {
|
||||
.option("--thinking <level>", "Thinking level for agent jobs (off|minimal|low|medium|high)")
|
||||
.option("--model <model>", "Model override for agent jobs (provider/model or alias)")
|
||||
.option("--timeout-seconds <n>", "Timeout seconds for agent jobs")
|
||||
.option("--announce", "Announce summary to a chat (subagent-style)", false)
|
||||
.option(
|
||||
"--deliver",
|
||||
"Deliver agent output (required when using last-route delivery without --to)",
|
||||
false,
|
||||
"Deliver full output to a chat (required when using last-route delivery without --to)",
|
||||
)
|
||||
.option("--no-deliver", "Disable delivery and skip main-session summary")
|
||||
.option("--channel <channel>", `Delivery channel (${getCronChannelOptions()})`, "last")
|
||||
.option(
|
||||
"--to <dest>",
|
||||
@@ -158,6 +159,15 @@ export function registerCronAddCommand(cron: Command) {
|
||||
return { kind: "systemEvent" as const, text: systemEvent };
|
||||
}
|
||||
const timeoutSeconds = parsePositiveIntOrUndefined(opts.timeoutSeconds);
|
||||
const hasAnnounce = Boolean(opts.announce);
|
||||
const hasDeliver = opts.deliver === true;
|
||||
const hasNoDeliver = opts.deliver === false;
|
||||
const deliveryFlagCount = [hasAnnounce, hasDeliver, hasNoDeliver].filter(
|
||||
Boolean,
|
||||
).length;
|
||||
if (deliveryFlagCount > 1) {
|
||||
throw new Error("Choose at most one of --announce, --deliver, or --no-deliver");
|
||||
}
|
||||
return {
|
||||
kind: "agentTurn" as const,
|
||||
message,
|
||||
@@ -169,10 +179,15 @@ export function registerCronAddCommand(cron: Command) {
|
||||
: undefined,
|
||||
timeoutSeconds:
|
||||
timeoutSeconds && Number.isFinite(timeoutSeconds) ? timeoutSeconds : undefined,
|
||||
deliver: opts.deliver ? true : undefined,
|
||||
channel: typeof opts.channel === "string" ? opts.channel : "last",
|
||||
channel:
|
||||
typeof opts.channel === "string" && opts.channel.trim()
|
||||
? opts.channel.trim()
|
||||
: "last",
|
||||
to: typeof opts.to === "string" && opts.to.trim() ? opts.to.trim() : undefined,
|
||||
bestEffortDeliver: opts.bestEffortDeliver ? true : undefined,
|
||||
bestEffortDeliver:
|
||||
!hasAnnounce && !hasDeliver && !hasNoDeliver && opts.bestEffortDeliver
|
||||
? true
|
||||
: undefined,
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -182,6 +197,12 @@ export function registerCronAddCommand(cron: Command) {
|
||||
if (sessionTarget === "isolated" && payload.kind !== "agentTurn") {
|
||||
throw new Error("Isolated jobs require --message (agentTurn).");
|
||||
}
|
||||
if (
|
||||
(opts.announce || typeof opts.deliver === "boolean") &&
|
||||
(sessionTarget !== "isolated" || payload.kind !== "agentTurn")
|
||||
) {
|
||||
throw new Error("--announce/--deliver/--no-deliver require --session isolated.");
|
||||
}
|
||||
|
||||
const isolation =
|
||||
sessionTarget === "isolated"
|
||||
@@ -222,6 +243,20 @@ export function registerCronAddCommand(cron: Command) {
|
||||
sessionTarget,
|
||||
wakeMode,
|
||||
payload,
|
||||
delivery:
|
||||
payload.kind === "agentTurn" &&
|
||||
sessionTarget === "isolated" &&
|
||||
(opts.announce || typeof opts.deliver === "boolean")
|
||||
? {
|
||||
mode: opts.announce ? "announce" : opts.deliver === true ? "deliver" : "none",
|
||||
channel:
|
||||
typeof opts.channel === "string" && opts.channel.trim()
|
||||
? opts.channel.trim()
|
||||
: "last",
|
||||
to: typeof opts.to === "string" && opts.to.trim() ? opts.to.trim() : undefined,
|
||||
bestEffort: opts.bestEffortDeliver ? true : undefined,
|
||||
}
|
||||
: undefined,
|
||||
isolation,
|
||||
};
|
||||
|
||||
|
||||
@@ -46,9 +46,10 @@ export function registerCronEditCommand(cron: Command) {
|
||||
.option("--thinking <level>", "Thinking level for agent jobs")
|
||||
.option("--model <model>", "Model override for agent jobs")
|
||||
.option("--timeout-seconds <n>", "Timeout seconds for agent jobs")
|
||||
.option("--announce", "Announce summary to a chat (subagent-style)")
|
||||
.option(
|
||||
"--deliver",
|
||||
"Deliver agent output (required when using last-route delivery without --to)",
|
||||
"Deliver full output to a chat (required when using last-route delivery without --to)",
|
||||
)
|
||||
.option("--no-deliver", "Disable delivery")
|
||||
.option("--channel <channel>", `Delivery channel (${getCronChannelOptions()})`)
|
||||
@@ -74,6 +75,9 @@ export function registerCronEditCommand(cron: Command) {
|
||||
if (opts.session === "main" && typeof opts.postPrefix === "string") {
|
||||
throw new Error("--post-prefix only applies to isolated jobs.");
|
||||
}
|
||||
if (opts.announce && typeof opts.deliver === "boolean") {
|
||||
throw new Error("Choose --announce, --deliver, or --no-deliver (not multiple).");
|
||||
}
|
||||
|
||||
const patch: Record<string, unknown> = {};
|
||||
if (typeof opts.name === "string") {
|
||||
@@ -151,15 +155,16 @@ export function registerCronEditCommand(cron: Command) {
|
||||
? Number.parseInt(String(opts.timeoutSeconds), 10)
|
||||
: undefined;
|
||||
const hasTimeoutSeconds = Boolean(timeoutSeconds && Number.isFinite(timeoutSeconds));
|
||||
const hasDeliveryModeFlag = opts.announce || typeof opts.deliver === "boolean";
|
||||
const hasDeliveryTarget = typeof opts.channel === "string" || typeof opts.to === "string";
|
||||
const hasBestEffort = typeof opts.bestEffortDeliver === "boolean";
|
||||
const hasAgentTurnPatch =
|
||||
typeof opts.message === "string" ||
|
||||
Boolean(model) ||
|
||||
Boolean(thinking) ||
|
||||
hasTimeoutSeconds ||
|
||||
typeof opts.deliver === "boolean" ||
|
||||
typeof opts.channel === "string" ||
|
||||
typeof opts.to === "string" ||
|
||||
typeof opts.bestEffortDeliver === "boolean";
|
||||
hasDeliveryModeFlag ||
|
||||
(!hasDeliveryModeFlag && (hasDeliveryTarget || hasBestEffort));
|
||||
if (hasSystemEventPatch && hasAgentTurnPatch) {
|
||||
throw new Error("Choose at most one payload change");
|
||||
}
|
||||
@@ -174,15 +179,21 @@ export function registerCronEditCommand(cron: Command) {
|
||||
assignIf(payload, "model", model, Boolean(model));
|
||||
assignIf(payload, "thinking", thinking, Boolean(thinking));
|
||||
assignIf(payload, "timeoutSeconds", timeoutSeconds, hasTimeoutSeconds);
|
||||
assignIf(payload, "deliver", opts.deliver, typeof opts.deliver === "boolean");
|
||||
assignIf(payload, "channel", opts.channel, typeof opts.channel === "string");
|
||||
assignIf(payload, "to", opts.to, typeof opts.to === "string");
|
||||
assignIf(
|
||||
payload,
|
||||
"bestEffortDeliver",
|
||||
opts.bestEffortDeliver,
|
||||
typeof opts.bestEffortDeliver === "boolean",
|
||||
);
|
||||
if (!hasDeliveryModeFlag) {
|
||||
const channel =
|
||||
typeof opts.channel === "string" && opts.channel.trim()
|
||||
? opts.channel.trim()
|
||||
: undefined;
|
||||
const to = typeof opts.to === "string" && opts.to.trim() ? opts.to.trim() : undefined;
|
||||
assignIf(payload, "channel", channel, Boolean(channel));
|
||||
assignIf(payload, "to", to, Boolean(to));
|
||||
assignIf(
|
||||
payload,
|
||||
"bestEffortDeliver",
|
||||
opts.bestEffortDeliver,
|
||||
typeof opts.bestEffortDeliver === "boolean",
|
||||
);
|
||||
}
|
||||
patch.payload = payload;
|
||||
}
|
||||
|
||||
@@ -192,6 +203,24 @@ export function registerCronEditCommand(cron: Command) {
|
||||
};
|
||||
}
|
||||
|
||||
if (hasDeliveryModeFlag) {
|
||||
const deliveryMode = opts.announce
|
||||
? "announce"
|
||||
: opts.deliver === true
|
||||
? "deliver"
|
||||
: "none";
|
||||
patch.delivery = {
|
||||
mode: deliveryMode,
|
||||
channel:
|
||||
typeof opts.channel === "string" && opts.channel.trim()
|
||||
? opts.channel.trim()
|
||||
: undefined,
|
||||
to: typeof opts.to === "string" && opts.to.trim() ? opts.to.trim() : undefined,
|
||||
bestEffort:
|
||||
typeof opts.bestEffortDeliver === "boolean" ? opts.bestEffortDeliver : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const res = await callGatewayFromCli("cron.update", opts, {
|
||||
id,
|
||||
patch,
|
||||
|
||||
Reference in New Issue
Block a user