From c58de43f35af54f59ed9a99d6123b395e563a874 Mon Sep 17 00:00:00 2001 From: Cypherm <28184436+Cypherm@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:30:14 +0800 Subject: [PATCH] fix(ui): prevent double-qualifying already-qualified model values When the server returns a model string that already contains a provider prefix (e.g. "ollama/gpt-oss:120b-cloud"), buildQualifiedChatModelValue would blindly prepend the session's default provider, producing invalid refs like "anthropic/ollama/gpt-oss:120b-cloud". Skip provider prepending when the model string already contains "/". Closes #51139 Closes #51306 Co-Authored-By: Claude Opus 4.6 (1M context) --- ui/src/ui/chat-model-ref.test.ts | 12 ++++++++++++ ui/src/ui/chat-model-ref.ts | 5 +++++ vitest.config.ts | 1 + 3 files changed, 18 insertions(+) diff --git a/ui/src/ui/chat-model-ref.test.ts b/ui/src/ui/chat-model-ref.test.ts index 86b46f3fe7f..544bea8333c 100644 --- a/ui/src/ui/chat-model-ref.test.ts +++ b/ui/src/ui/chat-model-ref.test.ts @@ -47,4 +47,16 @@ describe("chat-model-ref helpers", () => { expect(resolveServerChatModelValue("gpt-5-mini", "openai")).toBe("openai/gpt-5-mini"); expect(resolveServerChatModelValue("alias-only", null)).toBe("alias-only"); }); + + it("does not double-qualify already-qualified model values", () => { + expect(resolveServerChatModelValue("ollama/gpt-oss:120b-cloud", "anthropic")).toBe( + "ollama/gpt-oss:120b-cloud", + ); + }); + + it("preserves nested vendor/model identifiers", () => { + expect( + resolveServerChatModelValue("openrouter/anthropic/claude-sonnet-4-6", "openrouter"), + ).toBe("openrouter/anthropic/claude-sonnet-4-6"); + }); }); diff --git a/ui/src/ui/chat-model-ref.ts b/ui/src/ui/chat-model-ref.ts index 351b8544bad..f4c4c8f4ad5 100644 --- a/ui/src/ui/chat-model-ref.ts +++ b/ui/src/ui/chat-model-ref.ts @@ -15,6 +15,11 @@ export function buildQualifiedChatModelValue(model: string, provider?: string | if (!trimmedModel) { return ""; } + // If the model string already contains "/" it is already provider-qualified + // (e.g. "ollama/gpt-oss:120b-cloud"); return as-is to avoid double-qualifying. + if (trimmedModel.includes("/")) { + return trimmedModel; + } const trimmedProvider = provider?.trim(); return trimmedProvider ? `${trimmedProvider}/${trimmedModel}` : trimmedModel; } diff --git a/vitest.config.ts b/vitest.config.ts index f254bcdf0a7..1be0080aa7c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -37,6 +37,7 @@ export default defineConfig({ "src/**/*.test.ts", "extensions/**/*.test.ts", "test/**/*.test.ts", + "ui/src/ui/chat-model-ref.test.ts", "ui/src/ui/app-chat.test.ts", "ui/src/ui/views/agents-utils.test.ts", "ui/src/ui/views/chat.test.ts",