Skip to content

Commit 4d89548

Browse files
steipeteSuko
andcommitted
fix(ui): inherit default model fallbacks in agents overview (#25729)
Land PR #25729 from @Suko. Use shared fallback-resolution helper and add regression coverage for default, override, and explicit-empty cases. Co-authored-by: suko <[email protected]>
1 parent 43f318c commit 4d89548

File tree

5 files changed

+56
-2
lines changed

5 files changed

+56
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Docs: https://docs.openclaw.ai
3333
- Models/Bedrock auth: normalize additional Bedrock provider aliases (`bedrock`, `aws-bedrock`, `aws_bedrock`, `amazon bedrock`) to canonical `amazon-bedrock`, ensuring auth-mode resolution consistently selects AWS SDK fallback. (#25756) Thanks @fwhite13.
3434
- Providers/SiliconFlow: normalize `thinking="off"` to `thinking: null` for `Pro/*` model payloads to avoid provider-side 400 loops and misleading compaction retries. (#25435) Thanks @Zjianru.
3535
- Gateway/Models: honor explicit `agents.defaults.models` allowlist refs even when bundled model catalog data is stale, synthesize missing allowlist entries in `models.list`, and allow `sessions.patch`/`/model` selection for those refs without false `model not allowed` errors. (#20291) Thanks @kensipe, @nikolasdehor, and @vincentkoc.
36+
- Control UI/Agents: inherit `agents.defaults.model.fallbacks` in the Overview fallback input when no per-agent model entry exists, while preserving explicit per-agent fallback overrides (including empty lists). (#25729, #25710) Thanks @Suko.
3637
- Automation/Subagent/Cron reliability: honor `ANNOUNCE_SKIP` in `sessions_spawn` completion/direct announce flows (no user-visible token leaks), add transient direct-announce retries for channel unavailability (for example WhatsApp listener reconnect windows), and include `cron` in the `coding` tool profile so `/tools/invoke` can execute cron actions when explicitly allowed by gateway policy. (#25800, #25656, #25842, #25813, #25822, #25821) Thanks @astra-fer, @aaajiao, @dwight11232-coder, @kevinWangSheng, @widingmarcus-cyber, and @stakeswky.
3738
- Discord/Proxy + reactions + model picker: thread channel proxy fetch into inbound media/sticker downloads, use proxy-aware gateway metadata fetch for WSL/corporate proxy setups, wire `messages.statusReactions.{emojis,timing}` into Discord reaction lifecycle control, and compact model-picker `custom_id` keys to stay under Discord's 100-char limit while keeping backward-compatible parsing. (#25232, #25507, #25564, #25695) Thanks @openperf, @chilu18, @Yipsh, @lbo728, and @s1korrrr.
3839
- Discord/Block streaming: restore block-streamed reply delivery by suppressing only reasoning payloads (instead of all `block` payloads), fixing missing Discord replies in `channels.discord.streaming=block` mode. (#25839, #25836, #25792) Thanks @pewallin.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { describe, expect, it } from "vitest";
2+
import { resolveEffectiveModelFallbacks } from "./agents-utils.ts";
3+
4+
describe("resolveEffectiveModelFallbacks", () => {
5+
it("inherits defaults when no entry fallbacks are configured", () => {
6+
const entryModel = undefined;
7+
const defaultModel = {
8+
primary: "openai/gpt-5-nano",
9+
fallbacks: ["google/gemini-2.0-flash"],
10+
};
11+
12+
expect(resolveEffectiveModelFallbacks(entryModel, defaultModel)).toEqual([
13+
"google/gemini-2.0-flash",
14+
]);
15+
});
16+
17+
it("prefers entry fallbacks over defaults", () => {
18+
const entryModel = {
19+
primary: "openai/gpt-5-mini",
20+
fallbacks: ["openai/gpt-5-nano"],
21+
};
22+
const defaultModel = {
23+
primary: "openai/gpt-5",
24+
fallbacks: ["google/gemini-2.0-flash"],
25+
};
26+
27+
expect(resolveEffectiveModelFallbacks(entryModel, defaultModel)).toEqual(["openai/gpt-5-nano"]);
28+
});
29+
30+
it("keeps explicit empty entry fallback lists", () => {
31+
const entryModel = {
32+
primary: "openai/gpt-5-mini",
33+
fallbacks: [],
34+
};
35+
const defaultModel = {
36+
primary: "openai/gpt-5",
37+
fallbacks: ["google/gemini-2.0-flash"],
38+
};
39+
40+
expect(resolveEffectiveModelFallbacks(entryModel, defaultModel)).toEqual([]);
41+
});
42+
});

ui/src/ui/views/agents-utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,13 @@ export function resolveModelFallbacks(model?: unknown): string[] | null {
244244
return null;
245245
}
246246

247+
export function resolveEffectiveModelFallbacks(
248+
entryModel?: unknown,
249+
defaultModel?: unknown,
250+
): string[] | null {
251+
return resolveModelFallbacks(entryModel) ?? resolveModelFallbacks(defaultModel);
252+
}
253+
247254
export function parseFallbackList(value: string): string[] {
248255
return value
249256
.split(",")

ui/src/ui/views/agents.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
parseFallbackList,
2525
resolveAgentConfig,
2626
resolveAgentEmoji,
27-
resolveModelFallbacks,
27+
resolveEffectiveModelFallbacks,
2828
resolveModelLabel,
2929
resolveModelPrimary,
3030
} from "./agents-utils.ts";
@@ -390,7 +390,10 @@ function renderAgentOverview(params: {
390390
resolveModelPrimary(config.defaults?.model) ||
391391
(defaultModel !== "-" ? normalizeModelValue(defaultModel) : null);
392392
const effectivePrimary = modelPrimary ?? defaultPrimary ?? null;
393-
const modelFallbacks = resolveModelFallbacks(config.entry?.model);
393+
const modelFallbacks = resolveEffectiveModelFallbacks(
394+
config.entry?.model,
395+
config.defaults?.model,
396+
);
394397
const fallbackText = modelFallbacks ? modelFallbacks.join(", ") : "";
395398
const identityName =
396399
agentIdentity?.name?.trim() ||

vitest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export default defineConfig({
3737
"src/**/*.test.ts",
3838
"extensions/**/*.test.ts",
3939
"test/**/*.test.ts",
40+
"ui/src/ui/views/agents-utils.test.ts",
4041
"ui/src/ui/views/usage-render-details.test.ts",
4142
"ui/src/ui/controllers/agents.test.ts",
4243
],

0 commit comments

Comments
 (0)