From b58e84f3c94c88903c21a08d0a0b810bdc6bea10 Mon Sep 17 00:00:00 2001 From: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 00:12:54 +0000 Subject: [PATCH] fix(cron): route CLI-runtime cron models through compatible backend --- CHANGELOG.md | 2 +- .../isolated-agent.model-formatting.test.ts | 55 ++++++++++++++++++- src/cron/isolated-agent/model-selection.ts | 2 + src/cron/isolated-agent/run.ts | 1 + 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c0b68a7d08..1cd997d0091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,7 +60,7 @@ Docs: https://docs.openclaw.ai - Gateway: avoid repeated plugin tool descriptor config hashing so large runtime configs do not block reply startup and trigger reconnect/timeouts. (#75944) Thanks @joshavant. - Plugins/externalization: keep diagnostics ClawHub packages and persisted bundled-plugin relocation on npm-first install metadata for launch, and omit Discord from the core package now that its external package is published. Thanks @vincentkoc. - Setup/TUI: bound the Terminal hatch bootstrap run so a stalled provider request times out instead of leaving first-run hatching stuck behind the watchdog. (#76241) Thanks @joshavant. -- Cron/CLI runtimes: route isolated cron jobs through configured CLI runtimes only when the resolved model provider is compatible, so OpenAI job overrides no longer inherit a mismatched Claude CLI backend. Thanks @vishutdhar. +- Cron/CLI runtimes: route isolated cron jobs through configured per-agent CLI runtimes only when the resolved model provider is compatible, so OpenAI job overrides no longer inherit a mismatched Claude CLI backend. Thanks @vishutdhar. - Plugins/Codex: allow the official npm Codex plugin to install without the unsafe-install override, keep `/codex` command ownership, and cover the real npm Docker live path through managed `.openclaw/npm` dependencies plus uninstall failure proof. - Gateway/status: add concrete service, config, listener-owner, and log collection next steps when gateway probes fail and Bonjour finds no local gateway, so frozen or port-conflict reports include the data needed for root-cause triage. Refs #49012. Thanks @vincentkoc. - Codex harness: forward OpenClaw workspace bootstrap files such as `SOUL.md` through native Codex config instructions while leaving `AGENTS.md` to Codex project-doc discovery. Fixes #76273. Thanks @zknicker. diff --git a/src/cron/isolated-agent.model-formatting.test.ts b/src/cron/isolated-agent.model-formatting.test.ts index 8988f627de9..e1f382ba286 100644 --- a/src/cron/isolated-agent.model-formatting.test.ts +++ b/src/cron/isolated-agent.model-formatting.test.ts @@ -65,6 +65,7 @@ type SelectModelOptions = { providerOverride?: string; }; isGmailHook?: boolean; + agentId?: string; }; function parseModelRef(raw: string): { provider: string; model: string } | { error: string } { @@ -126,6 +127,7 @@ async function selectModel(options: SelectModelOptions = {}) { sessionEntry: options.sessionEntry ?? {}, payload: options.payload ?? defaultPayload(), isGmailHook: options.isGmailHook ?? false, + agentId: options.agentId, }); } @@ -402,7 +404,56 @@ describe("cron model formatting and precedence edge cases", () => { }); describe("CLI runtime compatibility", () => { - it("uses a configured Claude CLI runtime for resolved Anthropic models", async () => { + it("uses a configured per-agent Claude CLI runtime for resolved Anthropic models", async () => { + await expectSelectedModel( + { + cfg: { + agents: { + defaults: { + model: "anthropic/claude-opus-4-6", + }, + list: [ + { + id: "scheduler", + agentRuntime: { id: "claude-cli" }, + }, + ], + }, + }, + agentId: "scheduler", + }, + { provider: "claude-cli", model: "claude-opus-4-6" }, + ); + }); + + it("keeps an OpenAI payload override on OpenAI when per-agent Claude CLI is configured", async () => { + await expectSelectedModel( + { + cfg: { + agents: { + defaults: { + model: "anthropic/claude-opus-4-6", + }, + list: [ + { + id: "scheduler", + agentRuntime: { id: "claude-cli" }, + }, + ], + }, + }, + agentId: "scheduler", + payload: { + kind: "agentTurn", + message: DEFAULT_MESSAGE, + model: "openai/gpt-4.1-mini", + }, + }, + { provider: "openai", model: "gpt-4.1-mini" }, + ); + }); + + it("uses a configured default Claude CLI runtime for resolved Anthropic models", async () => { await expectSelectedModel( { cfg: { @@ -418,7 +469,7 @@ describe("cron model formatting and precedence edge cases", () => { ); }); - it("keeps an OpenAI payload override on OpenAI when Claude CLI is configured", async () => { + it("keeps an OpenAI payload override on OpenAI when default Claude CLI is configured", async () => { await expectSelectedModel( { cfg: { diff --git a/src/cron/isolated-agent/model-selection.ts b/src/cron/isolated-agent/model-selection.ts index dffe7ae5099..9a41d93ad11 100644 --- a/src/cron/isolated-agent/model-selection.ts +++ b/src/cron/isolated-agent/model-selection.ts @@ -29,6 +29,7 @@ export type ResolveCronModelSelectionParams = { sessionEntry: CronSessionModelOverrides; payload: CronJob["payload"]; isGmailHook: boolean; + agentId?: string; }; export type ResolveCronModelSelectionResult = @@ -152,6 +153,7 @@ export async function resolveCronModelSelection( resolveCliRuntimeExecutionProvider({ provider, cfg: params.cfgWithAgentDefaults, + agentId: params.agentId, }) ?? provider; return { ok: true, provider: executionProvider, model }; diff --git a/src/cron/isolated-agent/run.ts b/src/cron/isolated-agent/run.ts index e6f5c2bd898..c85cbb32a5f 100644 --- a/src/cron/isolated-agent/run.ts +++ b/src/cron/isolated-agent/run.ts @@ -561,6 +561,7 @@ async function prepareCronRunContext(params: { sessionEntry: cronSession.sessionEntry, payload: input.job.payload, isGmailHook, + agentId, }); if (!resolvedModelSelection.ok) { return {