fix(cron): show rejected model allowlist

This commit is contained in:
Peter Steinberger
2026-05-07 22:35:49 +01:00
parent e74347bbe7
commit 139122f655
3 changed files with 23 additions and 4 deletions

View File

@@ -154,6 +154,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Cron: make rejected `payload.model` errors show the configured `agents.defaults.models` allowlist instead of echoing the rejected model twice. Fixes #79058.
- Agents/subagents: retry parent wake announces when the announce-summary model run fails with fallback cooldown exhaustion instead of dropping the wake on the first transient provider overload. Refs #78581.
- Providers/network: honor IPv4 CIDR and octet-wildcard `NO_PROXY` entries such as `100.64.0.0/10` and `100.64.*` before enabling trusted env-proxy mode for model-provider requests. Fixes #79030.
- Docs/Docker: document a local Compose override for Docker Desktop DNS failures in the shared-network `openclaw-cli` sidecar, keeping the default compose setup hardened while unblocking `openclaw plugins install` when users opt in. Fixes #79018. Thanks @Jason-Vaughan.

View File

@@ -42,10 +42,23 @@ export type ResolveCronModelSelectionResult =
error: string;
};
function formatCronPayloadModelRejection(modelOverride: string, error: string): string {
function formatAllowedModelRefs(params: { cfg: OpenClawConfig }): string {
const configured = params.cfg.agents?.defaults?.models;
if (configured && typeof configured === "object" && Object.keys(configured).length > 0) {
return Object.keys(configured).sort().join(", ");
}
return "(none configured)";
}
function formatCronPayloadModelRejection(params: {
cfg: OpenClawConfig;
modelOverride: string;
error: string;
}): string {
const { modelOverride, error } = params;
if (error.startsWith("model not allowed:")) {
const modelRef = error.slice("model not allowed:".length).trim();
return `cron payload.model '${modelOverride}' rejected by agents.defaults.models allowlist: ${modelRef}`;
return `cron payload.model '${modelOverride}' rejected by agents.defaults.models allowlist: ${modelRef} is not in [${formatAllowedModelRefs({ cfg: params.cfg })}]`;
}
return `cron payload.model '${modelOverride}' rejected: ${error}`;
}
@@ -122,7 +135,11 @@ export async function resolveCronModelSelection(
if ("error" in resolvedOverride) {
return {
ok: false,
error: formatCronPayloadModelRejection(modelOverride, resolvedOverride.error),
error: formatCronPayloadModelRejection({
cfg: params.cfgWithAgentDefaults,
modelOverride,
error: resolvedOverride.error,
}),
};
}
provider = resolvedOverride.ref.provider;

View File

@@ -222,6 +222,7 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
agents: {
defaults: {
model: { primary: "openai-codex/gpt-5.4", fallbacks: defaultFallbacks },
models: { "openai-codex/gpt-5.4": {} },
},
},
},
@@ -237,7 +238,7 @@ describe("runCronIsolatedAgentTurn — skill filter", () => {
expect(result.status).toBe("error");
expect(result.error).toBe(
"cron payload.model 'anthropic/claude-sonnet-4-6' rejected by agents.defaults.models allowlist: anthropic/claude-sonnet-4-6",
"cron payload.model 'anthropic/claude-sonnet-4-6' rejected by agents.defaults.models allowlist: anthropic/claude-sonnet-4-6 is not in [openai-codex/gpt-5.4]",
);
expect(logWarnMock).not.toHaveBeenCalled();
expect(runWithModelFallbackMock).not.toHaveBeenCalled();