feat(cli): expand cron commands
This commit is contained in:
@@ -76,8 +76,7 @@ Each job is a JSON object with stable keys (unknown keys ignored for forward com
|
||||
- `{"kind":"systemEvent","text":string}` (enqueue as `System:`)
|
||||
- `{"kind":"agentTurn","message":string,"deliver"?:boolean,"channel"?: "last"|"whatsapp"|"telegram","to"?:string,"timeoutSeconds"?:number}`
|
||||
- `isolation` (optional; only meaningful for isolated jobs)
|
||||
- `{"postToMain"?: boolean, "postToMainPrefix"?: string}`
|
||||
- Note: `postToMain` is deprecated (no-op). Isolated jobs always post a summary; only the prefix is configurable.
|
||||
- `{"postToMainPrefix"?: string}`
|
||||
- `runtime` (optional)
|
||||
- `{"maxAttempts"?:number,"retryBackoffMs"?:number}` (best-effort retries; defaults off)
|
||||
- `state` (runtime-maintained)
|
||||
@@ -177,6 +176,7 @@ When due:
|
||||
- Optionally deliver output (`payload.deliver === true`) to the configured channel/to.
|
||||
- Isolated jobs always enqueue a summary system event to the main session when they finish (derived from the last agent text output).
|
||||
- Prefix defaults to `Cron`, and can be customized via `isolation.postToMainPrefix`.
|
||||
- If `deliver` is omitted/false, nothing is sent to external providers; you still get the main-session summary and can inspect the full isolated transcript in `cron:<jobId>`.
|
||||
|
||||
### “Run in parallel to main”
|
||||
|
||||
@@ -215,6 +215,8 @@ Path rules:
|
||||
Retention:
|
||||
- Best-effort pruning when the file grows beyond ~2MB; keep the newest ~2000 lines.
|
||||
|
||||
Each log line includes (at minimum) job id, status/error, timing, and a `summary` string (systemEvent text for main jobs, and the last agent text output for isolated jobs).
|
||||
|
||||
## Gateway API
|
||||
|
||||
New methods (names can be bikeshed; `cron.*` is suggested):
|
||||
@@ -269,6 +271,7 @@ Add a `cron` command group (all commands should also support `--json` where sens
|
||||
- `clawdis cron rm <id>`
|
||||
- `clawdis cron enable <id>` / `clawdis cron disable <id>`
|
||||
- `clawdis cron run <id> [--force]` (debug)
|
||||
- `clawdis cron runs [--id <id>] [--limit <n>]` (run history)
|
||||
- `clawdis cron status` (scheduler enabled + next wake)
|
||||
|
||||
Additionally:
|
||||
|
||||
@@ -163,7 +163,6 @@ export function registerCronCli(program: Command) {
|
||||
"Do not fail the job if delivery fails",
|
||||
false,
|
||||
)
|
||||
.option("--post-to-main", "Deprecated (no-op)", false)
|
||||
.option(
|
||||
"--post-prefix <prefix>",
|
||||
"Prefix for summary system event",
|
||||
@@ -261,14 +260,15 @@ export function registerCronCli(program: Command) {
|
||||
};
|
||||
})();
|
||||
|
||||
if (sessionTarget === "main" && payload.kind !== "systemEvent") {
|
||||
throw new Error("Main jobs require --system-event (systemEvent).");
|
||||
}
|
||||
if (sessionTarget === "isolated" && payload.kind !== "agentTurn") {
|
||||
throw new Error(
|
||||
"Isolated jobs require --message (agentTurn payload).",
|
||||
);
|
||||
throw new Error("Isolated jobs require --message (agentTurn).");
|
||||
}
|
||||
|
||||
const isolation =
|
||||
payload.kind === "agentTurn"
|
||||
sessionTarget === "isolated"
|
||||
? {
|
||||
postToMainPrefix:
|
||||
typeof opts.postPrefix === "string" &&
|
||||
@@ -318,6 +318,71 @@ export function registerCronCli(program: Command) {
|
||||
}),
|
||||
);
|
||||
|
||||
addGatewayClientOptions(
|
||||
cron
|
||||
.command("enable")
|
||||
.description("Enable a cron job")
|
||||
.argument("<id>", "Job id")
|
||||
.action(async (id, opts) => {
|
||||
try {
|
||||
const res = await callGatewayFromCli("cron.update", opts, {
|
||||
id,
|
||||
patch: { enabled: true },
|
||||
});
|
||||
defaultRuntime.log(JSON.stringify(res, null, 2));
|
||||
await warnIfCronSchedulerDisabled(opts);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
addGatewayClientOptions(
|
||||
cron
|
||||
.command("disable")
|
||||
.description("Disable a cron job")
|
||||
.argument("<id>", "Job id")
|
||||
.action(async (id, opts) => {
|
||||
try {
|
||||
const res = await callGatewayFromCli("cron.update", opts, {
|
||||
id,
|
||||
patch: { enabled: false },
|
||||
});
|
||||
defaultRuntime.log(JSON.stringify(res, null, 2));
|
||||
await warnIfCronSchedulerDisabled(opts);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
addGatewayClientOptions(
|
||||
cron
|
||||
.command("runs")
|
||||
.description("Show cron run history (JSONL-backed)")
|
||||
.option("--id <id>", "Job id (required when store is jobs.json)")
|
||||
.option("--limit <n>", "Max entries (default 50)", "50")
|
||||
.action(async (opts) => {
|
||||
try {
|
||||
const limitRaw = Number.parseInt(String(opts.limit ?? "50"), 10);
|
||||
const limit =
|
||||
Number.isFinite(limitRaw) && limitRaw > 0 ? limitRaw : 50;
|
||||
const id =
|
||||
typeof opts.id === "string" && opts.id.trim() ? opts.id : undefined;
|
||||
const res = await callGatewayFromCli("cron.runs", opts, {
|
||||
id,
|
||||
limit,
|
||||
});
|
||||
defaultRuntime.log(JSON.stringify(res, null, 2));
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
addGatewayClientOptions(
|
||||
cron
|
||||
.command("edit")
|
||||
@@ -347,10 +412,23 @@ export function registerCronCli(program: Command) {
|
||||
"Do not fail job if delivery fails",
|
||||
false,
|
||||
)
|
||||
.option("--post-to-main", "Deprecated (no-op)", false)
|
||||
.option("--post-prefix <prefix>", "Prefix for summary system event")
|
||||
.action(async (id, opts) => {
|
||||
try {
|
||||
if (opts.session === "main" && opts.message) {
|
||||
throw new Error(
|
||||
"Main jobs cannot use --message; use --system-event or --session isolated.",
|
||||
);
|
||||
}
|
||||
if (opts.session === "isolated" && opts.systemEvent) {
|
||||
throw new Error(
|
||||
"Isolated jobs cannot use --system-event; use --message or --session main.",
|
||||
);
|
||||
}
|
||||
if (opts.session === "main" && typeof opts.postPrefix === "string") {
|
||||
throw new Error("--post-prefix only applies to isolated jobs.");
|
||||
}
|
||||
|
||||
const patch: Record<string, unknown> = {};
|
||||
if (typeof opts.name === "string") patch.name = opts.name;
|
||||
if (opts.enable && opts.disable)
|
||||
|
||||
Reference in New Issue
Block a user