fix(cron): warn when --agent is not specified on cron add (#42245)

* fix(cron): warn when --agent is not specified on cron add

Warn users when creating a cron job without specifying the --agent flag,
so they know the job will run with the default agent (main).

Fixes #42196

* fix(cron): warn when cron add omits --agent

* fix(cron): name default agent in warning

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
ethanclaw
2026-04-30 15:45:41 +08:00
committed by GitHub
parent 83753535eb
commit dc0c54c7f1
3 changed files with 116 additions and 1 deletions

View File

@@ -49,6 +49,7 @@ Docs: https://docs.openclaw.ai
- Media: treat legacy Word/OLE attachments with `application/msword` or `application/x-cfb` MIME as binary so printable-looking `.doc` files are not embedded into prompts as text. Fixes #54176; carries forward #54380. Thanks @andyliu.
- Config: accept documented `browser.tabCleanup` keys in strict root config validation, so configured tab cleanup no longer fails before runtime reads it. Fixes #74577. Thanks @lonexreb and @ezdlp.
- Cron: validate disabled job schedule edits before persisting updates, so invalid cron changes no longer partially mutate stored jobs. Fixes #74459. Thanks @yfge.
- CLI/cron: warn when `openclaw cron add --message` omits a nonblank `--agent`, including blank agent values and session-key jobs, so scheduled agent-turn jobs make default-agent fallback explicit while system events stay quiet. Fixes #42196; carries forward #42245. Thanks @ethanclaw.
- Channels/status: keep Telegram, Slack, and Google Chat read-only allowlist/default-target accessors on config-only paths, so status and channel summaries do not resolve SecretRef-backed runtime credentials. Thanks @eusine.
- Active Memory: clarify the deprecated `modelFallbackPolicy` warning and config help so `modelFallback` is described as a chain-resolution last resort, not runtime failover. (#74602) Thanks @jeffrey701.
- Channels/Discord: keep read-only allowlist/default-target accessors from resolving SecretRef-backed bot tokens, so status and channel summaries no longer fail when tokens are only available in gateway runtime. (#74737) Thanks @eusine.

View File

@@ -12,7 +12,7 @@ const mocks = vi.hoisted(() => {
defaultRuntime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
}),
writeJson: vi.fn((value: unknown, space = 2) => {
defaultRuntime.log(JSON.stringify(value, null, space > 0 ? space : undefined));
defaultRuntime.writeStdout(JSON.stringify(value, null, space > 0 ? space : undefined));
}),
exit: vi.fn((code: number) => {
throw new Error(`__exit__:${code}`);
@@ -548,6 +548,110 @@ describe("cron cli", () => {
const addCall = callGatewayFromCli.mock.calls.find((call) => call[0] === "cron.add");
const params = addCall?.[2] as { agentId?: string };
expect(params?.agentId).toBe("ops");
expect(defaultRuntime.error).not.toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
});
it("warns when --agent is not specified on cron add with --message", async () => {
await runCronCommand([
"cron",
"add",
"--name",
"No agent",
"--cron",
"* * * * *",
"--message",
"hello",
]);
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining("default agent (main)"),
);
});
it("keeps the missing --agent warning off cron add JSON stdout", async () => {
await runCronCommand([
"cron",
"add",
"--name",
"No agent JSON",
"--cron",
"* * * * *",
"--message",
"hello",
"--json",
]);
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
const stdout = defaultRuntime.writeStdout.mock.calls.map(([value]) => value).join("\n");
expect(stdout).not.toContain("No --agent specified");
expect(JSON.parse(stdout)).toMatchObject({
ok: true,
params: {
name: "No agent JSON",
payload: { kind: "agentTurn", message: "hello" },
},
});
});
it("warns when --agent is blank on cron add with --message", async () => {
const params = await runCronAddAndGetParams([
"--name",
"Blank agent",
"--cron",
"* * * * *",
"--message",
"hello",
"--agent",
" ",
]);
expect(params?.agentId).toBeUndefined();
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
});
it("does not warn when --system-event is used (no agent needed)", async () => {
await runCronCommand([
"cron",
"add",
"--name",
"System event",
"--cron",
"* * * * *",
"--system-event",
"tick",
]);
expect(defaultRuntime.error).not.toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
});
it("warns even when --session-key is provided (user should still specify agent explicitly)", async () => {
await runCronCommand([
"cron",
"add",
"--name",
"With session key",
"--cron",
"* * * * *",
"--message",
"hello",
"--session-key",
"agent:my-agent:my-session",
]);
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining("No --agent specified"),
);
});
it("sets lightContext on cron add when --light-context is passed", async () => {

View File

@@ -6,6 +6,7 @@ import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
} from "../../shared/string-coerce.js";
import { theme } from "../../terminal/theme.js";
import type { GatewayRpcOpts } from "../gateway-rpc.js";
import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
import { parsePositiveIntOrUndefined } from "../program/helpers.js";
@@ -231,6 +232,15 @@ export function registerCronAddCommand(cron: Command) {
const sessionKey = normalizeOptionalString(opts.sessionKey);
if (payload.kind === "agentTurn" && !agentId) {
defaultRuntime.error(
theme.warn(
"No --agent specified; the job will run with the default agent (main). " +
"Specify --agent to choose a specific agent.",
),
);
}
const params = {
name,
description,