feat(cron): enhance delivery modes and job configuration
- Updated isolated cron jobs to support new delivery modes: `announce` and `none`, improving output management. - Refactored job configuration to remove legacy fields and streamline delivery settings. - Enhanced the `CronJobEditor` UI to reflect changes in delivery options, including a new segmented control for delivery mode selection. - Updated documentation to clarify the new delivery configurations and their implications for job execution. - Improved tests to validate the new delivery behavior and ensure backward compatibility with legacy settings. This update provides users with greater flexibility in managing how isolated jobs deliver their outputs, enhancing overall usability and clarity in job configurations.
This commit is contained in:
committed by
Peter Steinberger
parent
ab9f06f4ff
commit
3f82daefd8
@@ -29,5 +29,4 @@ export const DEFAULT_CRON_FORM: CronFormState = {
|
||||
deliveryChannel: "last",
|
||||
deliveryTo: "",
|
||||
timeoutSeconds: "",
|
||||
postToMainPrefix: "Cron",
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ export function buildCronSchedule(form: CronFormState) {
|
||||
if (!Number.isFinite(ms)) {
|
||||
throw new Error("Invalid run time.");
|
||||
}
|
||||
return { kind: "at" as const, atMs: ms };
|
||||
return { kind: "at" as const, at: new Date(ms).toISOString() };
|
||||
}
|
||||
if (form.scheduleKind === "every") {
|
||||
const amount = toNumber(form.everyAmount, 0);
|
||||
@@ -109,19 +109,13 @@ export async function addCronJob(state: CronState) {
|
||||
const delivery =
|
||||
state.cronForm.sessionTarget === "isolated" &&
|
||||
state.cronForm.payloadKind === "agentTurn" &&
|
||||
state.cronForm.deliveryMode !== "legacy"
|
||||
state.cronForm.deliveryMode
|
||||
? {
|
||||
mode:
|
||||
state.cronForm.deliveryMode === "announce"
|
||||
? "announce"
|
||||
: state.cronForm.deliveryMode === "deliver"
|
||||
? "deliver"
|
||||
: "none",
|
||||
mode: state.cronForm.deliveryMode === "announce" ? "announce" : "none",
|
||||
channel: state.cronForm.deliveryChannel.trim() || "last",
|
||||
to: state.cronForm.deliveryTo.trim() || undefined,
|
||||
}
|
||||
: undefined;
|
||||
const legacyPrefix = state.cronForm.postToMainPrefix.trim() || "Cron";
|
||||
const agentId = state.cronForm.agentId.trim();
|
||||
const job = {
|
||||
name: state.cronForm.name.trim(),
|
||||
@@ -133,10 +127,6 @@ export async function addCronJob(state: CronState) {
|
||||
wakeMode: state.cronForm.wakeMode,
|
||||
payload,
|
||||
delivery,
|
||||
isolation:
|
||||
state.cronForm.sessionTarget === "isolated" && state.cronForm.deliveryMode === "legacy"
|
||||
? { postToMainPrefix: legacyPrefix }
|
||||
: undefined,
|
||||
};
|
||||
if (!job.name) {
|
||||
throw new Error("Name required.");
|
||||
|
||||
@@ -53,7 +53,8 @@ export function formatCronState(job: CronJob) {
|
||||
export function formatCronSchedule(job: CronJob) {
|
||||
const s = job.schedule;
|
||||
if (s.kind === "at") {
|
||||
return `At ${formatMs(s.atMs)}`;
|
||||
const atMs = Date.parse(s.at);
|
||||
return Number.isFinite(atMs) ? `At ${formatMs(atMs)}` : `At ${s.at}`;
|
||||
}
|
||||
if (s.kind === "every") {
|
||||
return `Every ${formatDurationMs(s.everyMs)}`;
|
||||
@@ -75,9 +76,5 @@ export function formatCronPayload(job: CronJob) {
|
||||
: "";
|
||||
return `${base} · ${delivery.mode}${target}`;
|
||||
}
|
||||
if (!delivery && (p.deliver || p.to)) {
|
||||
const target = p.channel || p.to ? ` (${p.channel ?? "last"}${p.to ? ` -> ${p.to}` : ""})` : "";
|
||||
return `${base} · deliver${target}`;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ export type SessionsPatchResult = {
|
||||
};
|
||||
|
||||
export type CronSchedule =
|
||||
| { kind: "at"; atMs: number }
|
||||
| { kind: "at"; at: string }
|
||||
| { kind: "every"; everyMs: number; anchorMs?: number }
|
||||
| { kind: "cron"; expr: string; tz?: string };
|
||||
|
||||
@@ -439,31 +439,15 @@ export type CronPayload =
|
||||
message: string;
|
||||
thinking?: string;
|
||||
timeoutSeconds?: number;
|
||||
deliver?: boolean;
|
||||
channel?:
|
||||
| "last"
|
||||
| "whatsapp"
|
||||
| "telegram"
|
||||
| "discord"
|
||||
| "slack"
|
||||
| "signal"
|
||||
| "imessage"
|
||||
| "msteams";
|
||||
to?: string;
|
||||
bestEffortDeliver?: boolean;
|
||||
};
|
||||
|
||||
export type CronDelivery = {
|
||||
mode: "none" | "announce" | "deliver";
|
||||
mode: "none" | "announce";
|
||||
channel?: string;
|
||||
to?: string;
|
||||
bestEffort?: boolean;
|
||||
};
|
||||
|
||||
export type CronIsolation = {
|
||||
postToMainPrefix?: string;
|
||||
};
|
||||
|
||||
export type CronJobState = {
|
||||
nextRunAtMs?: number;
|
||||
runningAtMs?: number;
|
||||
@@ -487,7 +471,6 @@ export type CronJob = {
|
||||
wakeMode: CronWakeMode;
|
||||
payload: CronPayload;
|
||||
delivery?: CronDelivery;
|
||||
isolation?: CronIsolation;
|
||||
state?: CronJobState;
|
||||
};
|
||||
|
||||
|
||||
@@ -29,9 +29,8 @@ export type CronFormState = {
|
||||
wakeMode: "next-heartbeat" | "now";
|
||||
payloadKind: "systemEvent" | "agentTurn";
|
||||
payloadText: string;
|
||||
deliveryMode: "legacy" | "none" | "announce" | "deliver";
|
||||
deliveryMode: "none" | "announce";
|
||||
deliveryChannel: string;
|
||||
deliveryTo: string;
|
||||
timeoutSeconds: string;
|
||||
postToMainPrefix: string;
|
||||
};
|
||||
|
||||
@@ -211,9 +211,7 @@ export function renderCron(props: CronProps) {
|
||||
.value as CronFormState["deliveryMode"],
|
||||
})}
|
||||
>
|
||||
<option value="legacy">Main summary (legacy)</option>
|
||||
<option value="announce">Announce summary (default)</option>
|
||||
<option value="deliver">Deliver full output</option>
|
||||
<option value="none">None (internal)</option>
|
||||
</select>
|
||||
</label>
|
||||
@@ -228,7 +226,7 @@ export function renderCron(props: CronProps) {
|
||||
/>
|
||||
</label>
|
||||
${
|
||||
props.form.deliveryMode === "announce" || props.form.deliveryMode === "deliver"
|
||||
props.form.deliveryMode === "announce"
|
||||
? html`
|
||||
<label class="field">
|
||||
<span>Channel</span>
|
||||
@@ -261,22 +259,6 @@ export function renderCron(props: CronProps) {
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
${
|
||||
props.form.sessionTarget === "isolated" && props.form.deliveryMode === "legacy"
|
||||
? html`
|
||||
<label class="field">
|
||||
<span>Post to main prefix</span>
|
||||
<input
|
||||
.value=${props.form.postToMainPrefix}
|
||||
@input=${(e: Event) =>
|
||||
props.onFormChange({
|
||||
postToMainPrefix: (e.target as HTMLInputElement).value,
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
`
|
||||
: nothing
|
||||
}
|
||||
</div>
|
||||
`
|
||||
: nothing
|
||||
|
||||
Reference in New Issue
Block a user