From 694fbf224d9406a4c4170aca7bedcedd4320744a Mon Sep 17 00:00:00 2001 From: liuxiaocs7 Date: Sun, 30 Aug 2026 04:12:29 +0800 Subject: [PATCH] fix(desktop): report the model actually tested when Test Connection falls back MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An OpenCode Free connection probes the enabled models then the provider fallbacks and returns the first that answers, so a selected model that is rate-limited or returns an empty completion made "测试连接" silently report success for a fallback model (e.g. nemotron-3-ultra-free) the user never enabled — reading as if the selection never took. Detect this in runTest by comparing result.modelTested against the enabled model ids: when the answering model isn't one the user selected, show a warning toast naming the unresponsive selection and the model used to verify, instead of a plain success. The resilient fallback probe is left intact. Fixes #4222 Generated-by: Claude Code (Opus 4.8) --- .../locales/settings-provider-copy.ts | 6 ++++ .../settings/use-connection-detail.ts | 30 ++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/renderer/locales/settings-provider-copy.ts b/apps/desktop/src/renderer/locales/settings-provider-copy.ts index 20a7c71ce0..6a2633bd39 100644 --- a/apps/desktop/src/renderer/locales/settings-provider-copy.ts +++ b/apps/desktop/src/renderer/locales/settings-provider-copy.ts @@ -149,6 +149,9 @@ const zhCopy = { : '', ].filter(Boolean).join(' '), connectionSuccess: (name: string) => `连接成功 · ${name}`, connectionFailed: (name: string) => `连接失败 · ${name}`, + connectionFallbackTitle: (name: string) => `连接可用 · ${name}`, + connectionFallbackDetail: (selected: readonly string[], tested: string) => + `你选择的 ${selected.join('、')} 当前未响应,已改用 ${tested} 验证连接可用;任务中继续使用你选择的模型可能会失败。`, connectionTestError: (name: string) => `连接测试出错 · ${name}`, modelsFetched: (count: number, name: string) => `已拉取 ${count} 个模型 · ${name}`, modelsFetchFailed: (name: string) => `拉取模型失败 · ${name}`, modelsFetchFailedDetail: (message: string, troubleshooting: string) => `${message} · 当前继续显示静态列表,请确认 ${troubleshooting} 后重试。`, @@ -299,6 +302,9 @@ const enCopy: ProviderSettingsCopy = { : '', ].filter(Boolean).join(' '), connectionSuccess: (name: string) => `Connected · ${name}`, connectionFailed: (name: string) => `Connection failed · ${name}`, + connectionFallbackTitle: (name: string) => `Connection works · ${name}`, + connectionFallbackDetail: (selected: readonly string[], tested: string) => + `Your selected ${selected.join(', ')} didn't respond; verified the connection with ${tested} instead. Tasks using your selected model may fail.`, connectionTestError: (name: string) => `Connection test error · ${name}`, modelsFetched: (count: number, name: string) => `Fetched ${count} ${count === 1 ? 'model' : 'models'} · ${name}`, modelsFetchFailed: (name: string) => `Failed to fetch models · ${name}`, modelsFetchFailedDetail: (message: string, troubleshooting: string) => `${message} · The static list remains visible. Check ${troubleshooting} and try again.`, diff --git a/apps/desktop/src/renderer/settings/use-connection-detail.ts b/apps/desktop/src/renderer/settings/use-connection-detail.ts index 824a4d7278..956bcd8e23 100644 --- a/apps/desktop/src/renderer/settings/use-connection-detail.ts +++ b/apps/desktop/src/renderer/settings/use-connection-detail.ts @@ -638,10 +638,32 @@ export function useConnectionDetail(props: ConnectionDetailProps) { const result: ConnectionTestResult = await props.bridge.test(connection.slug); if (!isConnectionDetailCurrent(lifecycle)) return; if (result.ok) { - toast.success( - copy.connectionSuccess(connection.name), - `${result.modelTested} · ${result.latencyMs} ms`, - ); + // The backend probes the enabled models first, then the provider + // fallbacks (opencode-free tries each in turn until one answers). When + // the model that actually answered isn't one the user enabled, a plain + // "connection succeeded · " reads as if their selection never + // took — and hides that their chosen model is currently down. Name both + // facts instead. + const testedId = result.modelTested; + const modelLabel = (id: string): string => + models.find((model) => model.id === id)?.displayName ?? id; + // Inline the `testedId !== undefined` check so it narrows `testedId` to + // string for `modelLabel(testedId)` below. + if ( + testedId !== undefined && + enabledModelIds.length > 0 && + !enabledModelIds.includes(testedId) + ) { + toast.warning( + copy.connectionFallbackTitle(connection.name), + copy.connectionFallbackDetail(enabledModelIds.map(modelLabel), modelLabel(testedId)), + ); + } else { + toast.success( + copy.connectionSuccess(connection.name), + `${result.modelTested} · ${result.latencyMs} ms`, + ); + } } else { reportHostError( copy.connectionFailed(connection.name),