From cb6f993b4c3821021d2afedd82b3559f3bd476fc Mon Sep 17 00:00:00 2001 From: wangchunyue <80630709+openperf@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:47:32 +0800 Subject: [PATCH] =?UTF-8?q?fix(cli):=20cron=20list=20Agent=20column=20show?= =?UTF-8?q?s=20agentId=20not=20model=20=E2=80=94=20add=20Model=20column=20?= =?UTF-8?q?(openclaw#26259)=20thanks=20@openperf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: openperf <80630709+openperf@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --- CHANGELOG.md | 1 + src/cli/cron-cli/shared.test.ts | 77 +++++++++++++++++++++++++++++++++ src/cli/cron-cli/shared.ts | 16 ++++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93f16bd94bf..4fa84f322e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Web UI/Cron: include configured agent model defaults/fallbacks in cron model suggestions so scheduled-job model autocomplete reflects configured models. (#29709) +- CLI/Cron: clarify `cron list` output by renaming `Agent` to `Agent ID` and adding a `Model` column for isolated agent-turn jobs. (#26259) - Cron/Delivery: disable the agent messaging tool when `delivery.mode` is `"none"` so cron output is not sent to Telegram or other channels. (#21808) - Feishu/Reply media attachments: send Feishu reply `mediaUrl`/`mediaUrls` payloads as attachments alongside text/streamed replies in the reply dispatcher, including legacy fallback when `mediaUrls` is empty. (#28959) - Feishu/Reaction notifications: add `channels.feishu.reactionNotifications` (`off | own | all`, default `own`) so operators can disable reaction ingress or allow all verified reaction events (not only bot-authored message reactions). (#28529) diff --git a/src/cli/cron-cli/shared.test.ts b/src/cli/cron-cli/shared.test.ts index 0ecfb86355e..22437d18080 100644 --- a/src/cli/cron-cli/shared.test.ts +++ b/src/cli/cron-cli/shared.test.ts @@ -75,6 +75,83 @@ describe("printCronList", () => { expect(logs.some((line) => line.includes("(stagger 5m)"))).toBe(true); }); + it("shows dash for unset agentId instead of default", () => { + const { logs, runtime } = createRuntimeLogCapture(); + const job = createBaseJob({ + id: "no-agent-job", + name: "No Agent", + agentId: undefined, + sessionTarget: "isolated", + payload: { kind: "agentTurn", message: "hello", model: "sonnet" }, + }); + + printCronList([job], runtime); + // Header should say "Agent ID" not "Agent" + expect(logs[0]).toContain("Agent ID"); + // Data row should show "-" for missing agentId, not "default" + const dataLine = logs[1] ?? ""; + expect(dataLine).not.toContain("default"); + }); + + it("shows Model column with payload.model for agentTurn jobs", () => { + const { logs, runtime } = createRuntimeLogCapture(); + const job = createBaseJob({ + id: "model-job", + name: "With Model", + agentId: "ops", + sessionTarget: "isolated", + payload: { kind: "agentTurn", message: "hello", model: "sonnet" }, + }); + + printCronList([job], runtime); + expect(logs[0]).toContain("Model"); + const dataLine = logs[1] ?? ""; + expect(dataLine).toContain("sonnet"); + }); + + it("shows dash in Model column for systemEvent jobs", () => { + const { logs, runtime } = createRuntimeLogCapture(); + const job = createBaseJob({ + id: "sys-event-job", + name: "System Event", + sessionTarget: "main", + payload: { kind: "systemEvent", text: "tick" }, + }); + + printCronList([job], runtime); + expect(logs[0]).toContain("Model"); + }); + + it("shows dash in Model column for agentTurn jobs without model override", () => { + const { logs, runtime } = createRuntimeLogCapture(); + const job = createBaseJob({ + id: "no-model-job", + name: "No Model", + sessionTarget: "isolated", + payload: { kind: "agentTurn", message: "hello" }, + }); + + printCronList([job], runtime); + const dataLine = logs[1] ?? ""; + expect(dataLine).not.toContain("undefined"); + }); + + it("shows explicit agentId when set", () => { + const { logs, runtime } = createRuntimeLogCapture(); + const job = createBaseJob({ + id: "agent-set-job", + name: "Agent Set", + agentId: "ops", + sessionTarget: "isolated", + payload: { kind: "agentTurn", message: "hello", model: "opus" }, + }); + + printCronList([job], runtime); + const dataLine = logs[1] ?? ""; + expect(dataLine).toContain("ops"); + expect(dataLine).toContain("opus"); + }); + it("shows exact label for cron schedules with stagger disabled", () => { const { logs, runtime } = createRuntimeLogCapture(); const job = createBaseJob({ diff --git a/src/cli/cron-cli/shared.ts b/src/cli/cron-cli/shared.ts index 8c50ebcdb9e..b9b1dda2a5e 100644 --- a/src/cli/cron-cli/shared.ts +++ b/src/cli/cron-cli/shared.ts @@ -86,6 +86,7 @@ const CRON_LAST_PAD = 10; const CRON_STATUS_PAD = 9; const CRON_TARGET_PAD = 9; const CRON_AGENT_PAD = 10; +const CRON_MODEL_PAD = 20; const pad = (value: string, width: number) => value.padEnd(width); @@ -171,7 +172,8 @@ export function printCronList(jobs: CronJob[], runtime = defaultRuntime) { pad("Last", CRON_LAST_PAD), pad("Status", CRON_STATUS_PAD), pad("Target", CRON_TARGET_PAD), - pad("Agent", CRON_AGENT_PAD), + pad("Agent ID", CRON_AGENT_PAD), + pad("Model", CRON_MODEL_PAD), ].join(" "); runtime.log(rich ? theme.heading(header) : header); @@ -192,7 +194,14 @@ export function printCronList(jobs: CronJob[], runtime = defaultRuntime) { const statusRaw = formatStatus(job); const statusLabel = pad(statusRaw, CRON_STATUS_PAD); const targetLabel = pad(job.sessionTarget ?? "-", CRON_TARGET_PAD); - const agentLabel = pad(truncate(job.agentId ?? "default", CRON_AGENT_PAD), CRON_AGENT_PAD); + const agentLabel = pad(truncate(job.agentId ?? "-", CRON_AGENT_PAD), CRON_AGENT_PAD); + const modelLabel = pad( + truncate( + (job.payload.kind === "agentTurn" ? job.payload.model : undefined) ?? "-", + CRON_MODEL_PAD, + ), + CRON_MODEL_PAD, + ); const coloredStatus = (() => { if (statusRaw === "ok") { @@ -227,6 +236,9 @@ export function printCronList(jobs: CronJob[], runtime = defaultRuntime) { coloredStatus, coloredTarget, coloredAgent, + job.payload.kind === "agentTurn" && job.payload.model + ? colorize(rich, theme.info, modelLabel) + : colorize(rich, theme.muted, modelLabel), ].join(" "); runtime.log(line.trimEnd());