mirror of https://github.com/openclaw/openclaw.git
fix(ui): resolve model provider from catalog instead of stale session default
When the server returns a bare model name (e.g. "deepseek-chat") with a session-level modelProvider (e.g. "zai"), the UI blindly prepends the provider — producing "zai/deepseek-chat" instead of the correct "deepseek/deepseek-chat". This causes "model not allowed" errors when switching between models from different providers. Root cause: resolveModelOverrideValue() and resolveDefaultModelValue() in app-render.helpers.ts, plus the /model slash command handler in slash-command-executor.ts, all call resolveServerChatModelValue() which trusts the session's default provider. The session provider reflects the PREVIOUS model, not the newly selected one. Fix: for bare model names, create a raw ChatModelOverride and resolve through normalizeChatModelOverrideValue() which looks up the correct provider from the model catalog. Falls back to server-provided provider only if the catalog lookup fails. All 3 call sites are fixed. Closes #53031 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: HCL <chenglunhu@gmail.com>
This commit is contained in:
parent
5ab3782215
commit
be20eebc21
|
|
@ -536,9 +536,19 @@ function resolveModelOverrideValue(state: AppViewState): string {
|
|||
return "";
|
||||
}
|
||||
// No local override recorded yet — fall back to server data.
|
||||
// Include provider prefix so the value matches option keys (provider/model).
|
||||
// Use the bare model name and resolve provider from the catalog rather than
|
||||
// trusting the session's modelProvider, which may be the session default and
|
||||
// not the model's actual provider (e.g. "zai" for a "deepseek-chat" model).
|
||||
const activeRow = resolveActiveSessionRow(state);
|
||||
if (activeRow && typeof activeRow.model === "string" && activeRow.model.trim()) {
|
||||
const rawOverride = createChatModelOverride(activeRow.model.trim());
|
||||
if (rawOverride) {
|
||||
const normalized = normalizeChatModelOverrideValue(rawOverride, state.chatModelCatalog ?? []);
|
||||
if (normalized) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
// Fallback: use server-provided provider if catalog lookup fails.
|
||||
return resolveServerChatModelValue(activeRow.model, activeRow.modelProvider);
|
||||
}
|
||||
return "";
|
||||
|
|
@ -546,7 +556,18 @@ function resolveModelOverrideValue(state: AppViewState): string {
|
|||
|
||||
function resolveDefaultModelValue(state: AppViewState): string {
|
||||
const defaults = state.sessionsResult?.defaults;
|
||||
return resolveServerChatModelValue(defaults?.model, defaults?.modelProvider);
|
||||
const model = defaults?.model;
|
||||
if (typeof model !== "string" || !model.trim()) {
|
||||
return "";
|
||||
}
|
||||
const rawOverride = createChatModelOverride(model.trim());
|
||||
if (rawOverride) {
|
||||
const normalized = normalizeChatModelOverrideValue(rawOverride, state.chatModelCatalog ?? []);
|
||||
if (normalized) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
return resolveServerChatModelValue(model, defaults?.modelProvider);
|
||||
}
|
||||
|
||||
function buildChatModelOptions(
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
isSubagentSessionKey,
|
||||
parseAgentSessionKey,
|
||||
} from "../../../../src/routing/session-key.js";
|
||||
import { createChatModelOverride, resolveServerChatModelValue } from "../chat-model-ref.ts";
|
||||
import { createChatModelOverride, normalizeChatModelOverrideValue, resolveServerChatModelValue } from "../chat-model-ref.ts";
|
||||
import type { GatewayBrowserClient } from "../gateway.ts";
|
||||
import type {
|
||||
AgentsListResult,
|
||||
|
|
@ -155,10 +155,12 @@ async function executeModel(
|
|||
key: sessionKey,
|
||||
model: args.trim(),
|
||||
});
|
||||
const resolvedValue = resolveServerChatModelValue(
|
||||
patched.resolved?.model ?? args.trim(),
|
||||
patched.resolved?.modelProvider,
|
||||
);
|
||||
const patchedModel = patched.resolved?.model ?? args.trim();
|
||||
const rawOverride = createChatModelOverride(patchedModel.trim());
|
||||
const resolvedValue = rawOverride
|
||||
? (normalizeChatModelOverrideValue(rawOverride, state.chatModelCatalog ?? []) ||
|
||||
resolveServerChatModelValue(patchedModel, patched.resolved?.modelProvider))
|
||||
: resolveServerChatModelValue(patchedModel, patched.resolved?.modelProvider);
|
||||
return {
|
||||
content: `Model set to \`${args.trim()}\`.`,
|
||||
action: "refresh",
|
||||
|
|
|
|||
Loading…
Reference in New Issue