Skip to content

Commit d694f28

Browse files
authored
Merge 5eff2ff into d1b33a6
2 parents d1b33a6 + 5eff2ff commit d694f28

4 files changed

Lines changed: 47 additions & 2 deletions

File tree

docs/automation/cron-jobs.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ If stdout is non-empty, that text is the delivered result. If stdout is empty an
157157
<ParamField path="--model" type="string">
158158
Model override; uses the selected allowed model for the job.
159159
</ParamField>
160+
<ParamField path="--clear-model" type="boolean">
161+
On `cron edit`, removes the per-job model override so the job follows normal cron model-selection precedence (a stored cron-session override if set, otherwise the agent/default model). Cannot be combined with `--model`.
162+
</ParamField>
160163
<ParamField path="--thinking" type="string">
161164
Thinking level override.
162165
</ParamField>
@@ -471,6 +474,7 @@ Model override note:
471474
- If the model is allowed, that exact provider/model reaches the isolated agent run.
472475
- If it is not allowed or cannot be resolved, cron fails the run with an explicit validation error.
473476
- API `cron.update` payload patches can set `model: null` to clear a stored job model override.
477+
- `openclaw cron edit <job-id> --clear-model` clears that override from the CLI (same effect as the `model: null` patch) and cannot be combined with `--model`.
474478
- Configured fallback chains still apply because cron `--model` is a job primary, not a session `/model` override.
475479
- Payload `fallbacks` replaces configured fallbacks for that job; `fallbacks: []` disables fallback and makes the run strict.
476480
- A plain `--model` with no explicit or configured fallback list does not fall through to the agent primary as a silent extra retry target.

docs/cli/cron.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ Use `--due` when you want the manual command to run only if the job is currently
168168

169169
## Models
170170

171-
`cron add|edit --model <ref>` selects an allowed model for the job.
171+
`cron add|edit --model <ref>` selects an allowed model for the job. `cron edit <job-id> --clear-model` removes the per-job model override so the job follows normal cron model-selection precedence (a stored cron-session override if present, otherwise the agent/default model); it cannot be combined with `--model`.
172172

173173
<Warning>
174174
If the model is not allowed or cannot be resolved, cron fails the run with an explicit validation error instead of falling back to the job's agent or default model selection.

src/cli/cron-cli/register.cron-edit.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,32 @@ describe("cron edit command", () => {
200200
},
201201
);
202202
});
203+
204+
it("clears the model override with --clear-model (CLI parity with cron.update model:null)", async () => {
205+
const program = createCronProgram();
206+
207+
await program.parseAsync(["edit", "job-1", "--clear-model"], { from: "user" });
208+
209+
expect(callGatewayFromCli).toHaveBeenCalledWith(
210+
"cron.update",
211+
expect.objectContaining({ clearModel: true }),
212+
{
213+
id: "job-1",
214+
patch: {
215+
payload: {
216+
kind: "agentTurn",
217+
model: null,
218+
},
219+
},
220+
},
221+
);
222+
});
223+
224+
it("documents the --clear-model flag alongside the sibling --clear-tools", () => {
225+
const editCommand = createCronProgram().commands.find((command) => command.name() === "edit");
226+
const help = editCommand?.helpInformation() ?? "";
227+
228+
expect(help).toContain("--clear-model");
229+
expect(help).toContain("--clear-tools");
230+
});
203231
});

src/cli/cron-cli/register.cron-edit.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ export function registerCronEditCommand(cron: Command) {
115115
"Thinking level for agent jobs (off|minimal|low|medium|high|xhigh)",
116116
)
117117
.option("--model <model>", "Model override for agent jobs")
118+
.option(
119+
"--clear-model",
120+
"Remove the per-job model override (restore normal cron model precedence)",
121+
false,
122+
)
118123
.option("--timeout-seconds <n>", "Timeout seconds for agent or command jobs")
119124
.option("--no-output-timeout-seconds <n>", "No-output timeout seconds for command jobs")
120125
.option("--output-max-bytes <n>", "Maximum captured stdout/stderr bytes for command jobs")
@@ -279,6 +284,9 @@ export function registerCronEditCommand(cron: Command) {
279284
);
280285
}
281286
const model = normalizeOptionalString(opts.model);
287+
if (model && opts.clearModel) {
288+
throw new Error("Use --model or --clear-model, not both");
289+
}
282290
const thinking = normalizeOptionalString(opts.thinking);
283291
const toolsAllow = parseCronToolsAllow(opts.tools);
284292
const rawTimeoutSeconds =
@@ -346,6 +354,7 @@ export function registerCronEditCommand(cron: Command) {
346354
const hasAgentTurnPayloadField =
347355
typeof opts.message === "string" ||
348356
Boolean(model) ||
357+
Boolean(opts.clearModel) ||
349358
Boolean(thinking) ||
350359
(hasTimeoutSeconds &&
351360
!hasCommandSpecificPayloadField &&
@@ -373,7 +382,11 @@ export function registerCronEditCommand(cron: Command) {
373382
} else if (hasAgentTurnPatch) {
374383
const payload: Record<string, unknown> = { kind: "agentTurn" };
375384
assignIf(payload, "message", String(opts.message), typeof opts.message === "string");
376-
assignIf(payload, "model", model, Boolean(model));
385+
if (opts.clearModel) {
386+
payload.model = null;
387+
} else {
388+
assignIf(payload, "model", model, Boolean(model));
389+
}
377390
assignIf(payload, "thinking", thinking, Boolean(thinking));
378391
assignIf(payload, "timeoutSeconds", timeoutSeconds, hasTimeoutSeconds);
379392
assignIf(

0 commit comments

Comments
 (0)