fix(agents): fall back to agents.defaults.model when agent has no model config (#24210)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 0f272b1027
Co-authored-by: bianbiandashen <16240681+bianbiandashen@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
边黎安
2026-02-23 16:18:55 +08:00
committed by GitHub
parent db32677f1d
commit a4c373935f
39 changed files with 434 additions and 251 deletions

View File

@@ -4,6 +4,10 @@ import path from "node:path";
import type { OAuthCredentials } from "@mariozechner/pi-ai";
import { afterEach, describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import {
resolveAgentModelFallbackValues,
resolveAgentModelPrimaryValue,
} from "../config/model-input.js";
import {
applyAuthProfileConfig,
applyLitellmProviderConfig,
@@ -84,11 +88,15 @@ function createConfigWithFallbacks() {
}
function expectFallbacksPreserved(cfg: ReturnType<typeof applyMinimaxApiConfig>) {
expect(cfg.agents?.defaults?.model?.fallbacks).toEqual([...EXPECTED_FALLBACKS]);
expect(resolveAgentModelFallbackValues(cfg.agents?.defaults?.model)).toEqual([
...EXPECTED_FALLBACKS,
]);
}
function expectPrimaryModelPreserved(cfg: ReturnType<typeof applyMinimaxApiProviderConfig>) {
expect(cfg.agents?.defaults?.model?.primary).toBe("anthropic/claude-opus-4-5");
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(
"anthropic/claude-opus-4-5",
);
}
function expectAllowlistContains(
@@ -431,7 +439,7 @@ describe("applyZaiConfig", () => {
for (const modelId of ["glm-4.7-flash", "glm-4.7-flashx"] as const) {
const cfg = applyZaiConfig({}, { endpoint: "coding-cn", modelId });
expect(cfg.models?.providers?.zai?.baseUrl).toBe(ZAI_CODING_CN_BASE_URL);
expect(cfg.agents?.defaults?.model?.primary).toBe(`zai/${modelId}`);
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(`zai/${modelId}`);
}
});
});
@@ -479,7 +487,7 @@ describe("primary model defaults", () => {
] as const;
for (const { getConfig, primaryModel } of configCases) {
const cfg = getConfig();
expect(cfg.agents?.defaults?.model?.primary).toBe(primaryModel);
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(primaryModel);
}
});
});
@@ -491,7 +499,7 @@ describe("applyXiaomiConfig", () => {
baseUrl: "https://api.xiaomimimo.com/anthropic",
api: "anthropic-messages",
});
expect(cfg.agents?.defaults?.model?.primary).toBe("xiaomi/mimo-v2-flash");
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe("xiaomi/mimo-v2-flash");
});
it("merges Xiaomi models and keeps existing provider overrides", () => {
@@ -521,7 +529,7 @@ describe("applyXaiConfig", () => {
baseUrl: "https://api.x.ai/v1",
api: "openai-completions",
});
expect(cfg.agents?.defaults?.model?.primary).toBe(XAI_DEFAULT_MODEL_REF);
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(XAI_DEFAULT_MODEL_REF);
});
});
@@ -550,7 +558,9 @@ describe("applyMistralConfig", () => {
baseUrl: "https://api.mistral.ai/v1",
api: "openai-completions",
});
expect(cfg.agents?.defaults?.model?.primary).toBe(MISTRAL_DEFAULT_MODEL_REF);
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(
MISTRAL_DEFAULT_MODEL_REF,
);
});
});
@@ -685,7 +695,7 @@ describe("default-model config helpers", () => {
] as const;
for (const { applyConfig, primaryModel } of configCases) {
const cfg = applyConfig({});
expect(cfg.agents?.defaults?.model?.primary).toBe(primaryModel);
expect(resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)).toBe(primaryModel);
const cfgWithFallbacks = applyConfig(createConfigWithFallbacks());
expectFallbacksPreserved(cfgWithFallbacks);