mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 13:18:09 +00:00
fix(cron): add cron edit --clear-model
Completes the CLI half of #91298.
This commit is contained in:
@@ -157,6 +157,9 @@ If stdout is non-empty, that text is the delivered result. If stdout is empty an
|
||||
<ParamField path="--model" type="string">
|
||||
Model override; uses the selected allowed model for the job.
|
||||
</ParamField>
|
||||
<ParamField path="--clear-model" type="boolean">
|
||||
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`.
|
||||
</ParamField>
|
||||
<ParamField path="--thinking" type="string">
|
||||
Thinking level override.
|
||||
</ParamField>
|
||||
@@ -471,6 +474,7 @@ Model override note:
|
||||
- If the model is allowed, that exact provider/model reaches the isolated agent run.
|
||||
- If it is not allowed or cannot be resolved, cron fails the run with an explicit validation error.
|
||||
- API `cron.update` payload patches can set `model: null` to clear a stored job model override.
|
||||
- `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`.
|
||||
- Configured fallback chains still apply because cron `--model` is a job primary, not a session `/model` override.
|
||||
- Payload `fallbacks` replaces configured fallbacks for that job; `fallbacks: []` disables fallback and makes the run strict.
|
||||
- A plain `--model` with no explicit or configured fallback list does not fall through to the agent primary as a silent extra retry target.
|
||||
|
||||
@@ -168,7 +168,7 @@ Use `--due` when you want the manual command to run only if the job is currently
|
||||
|
||||
## Models
|
||||
|
||||
`cron add|edit --model <ref>` selects an allowed model for the job.
|
||||
`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`.
|
||||
|
||||
<Warning>
|
||||
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.
|
||||
|
||||
@@ -200,4 +200,32 @@ describe("cron edit command", () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("clears the model override with --clear-model (CLI parity with cron.update model:null)", async () => {
|
||||
const program = createCronProgram();
|
||||
|
||||
await program.parseAsync(["edit", "job-1", "--clear-model"], { from: "user" });
|
||||
|
||||
expect(callGatewayFromCli).toHaveBeenCalledWith(
|
||||
"cron.update",
|
||||
expect.objectContaining({ clearModel: true }),
|
||||
{
|
||||
id: "job-1",
|
||||
patch: {
|
||||
payload: {
|
||||
kind: "agentTurn",
|
||||
model: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("documents the --clear-model flag alongside the sibling --clear-tools", () => {
|
||||
const editCommand = createCronProgram().commands.find((command) => command.name() === "edit");
|
||||
const help = editCommand?.helpInformation() ?? "";
|
||||
|
||||
expect(help).toContain("--clear-model");
|
||||
expect(help).toContain("--clear-tools");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -115,6 +115,11 @@ export function registerCronEditCommand(cron: Command) {
|
||||
"Thinking level for agent jobs (off|minimal|low|medium|high|xhigh)",
|
||||
)
|
||||
.option("--model <model>", "Model override for agent jobs")
|
||||
.option(
|
||||
"--clear-model",
|
||||
"Remove the per-job model override (restore normal cron model precedence)",
|
||||
false,
|
||||
)
|
||||
.option("--timeout-seconds <n>", "Timeout seconds for agent or command jobs")
|
||||
.option("--no-output-timeout-seconds <n>", "No-output timeout seconds for command jobs")
|
||||
.option("--output-max-bytes <n>", "Maximum captured stdout/stderr bytes for command jobs")
|
||||
@@ -279,6 +284,9 @@ export function registerCronEditCommand(cron: Command) {
|
||||
);
|
||||
}
|
||||
const model = normalizeOptionalString(opts.model);
|
||||
if (model && opts.clearModel) {
|
||||
throw new Error("Use --model or --clear-model, not both");
|
||||
}
|
||||
const thinking = normalizeOptionalString(opts.thinking);
|
||||
const toolsAllow = parseCronToolsAllow(opts.tools);
|
||||
const rawTimeoutSeconds =
|
||||
@@ -346,6 +354,7 @@ export function registerCronEditCommand(cron: Command) {
|
||||
const hasAgentTurnPayloadField =
|
||||
typeof opts.message === "string" ||
|
||||
Boolean(model) ||
|
||||
Boolean(opts.clearModel) ||
|
||||
Boolean(thinking) ||
|
||||
(hasTimeoutSeconds &&
|
||||
!hasCommandSpecificPayloadField &&
|
||||
@@ -373,7 +382,11 @@ export function registerCronEditCommand(cron: Command) {
|
||||
} else if (hasAgentTurnPatch) {
|
||||
const payload: Record<string, unknown> = { kind: "agentTurn" };
|
||||
assignIf(payload, "message", String(opts.message), typeof opts.message === "string");
|
||||
assignIf(payload, "model", model, Boolean(model));
|
||||
if (opts.clearModel) {
|
||||
payload.model = null;
|
||||
} else {
|
||||
assignIf(payload, "model", model, Boolean(model));
|
||||
}
|
||||
assignIf(payload, "thinking", thinking, Boolean(thinking));
|
||||
assignIf(payload, "timeoutSeconds", timeoutSeconds, hasTimeoutSeconds);
|
||||
assignIf(
|
||||
|
||||
Reference in New Issue
Block a user