Ensure ASR connection check validates the configured model

Issue #242 asks ASR to reach parity with LLM availability checks. Validation now requires a configured ASR model and verifies it exists in the provider model list, instead of only checking endpoint/auth reachability.

Constraint: Keep existing settings flow and IPC shape with minimal UI change

Rejected: Add a new ASR test-audio transcription request | adds latency and provider-specific request complexity

Confidence: high

Scope-risk: narrow

Directive: Keep validate and fetch-models semantics aligned; validate should fail when configured model cannot actually be selected

Tested: npm run build; cargo check -q

Not-tested: Manual Settings UI interaction against live third-party ASR endpoints
This commit is contained in:
H-Chris233 committed 2026-05-04 20:27:08 +08:00
1 parent ac2edbe961
commit 2438c901eb
4 files changed
+32 -7

No files matched your search

+21 -6
View File
@@ -155,12 +155,9 @@ pub async fn validate_provider_credentials(kind: String) -> Result<ProviderCheck
"llm" => validate_llm_provider()
.await
.map(|()| ProviderCheckResult { ok: true }),
"asr" => {
let config = read_openai_provider_config(&kind)?;
fetch_provider_models(&config)
.await
.map(|_| ProviderCheckResult { ok: true })
}
"asr" => validate_asr_provider()
.await
.map(|()| ProviderCheckResult { ok: true }),
_ => Err(format!("unknown provider kind: {kind}")),
}
}
@@ -232,6 +229,24 @@ async fn validate_llm_provider() -> Result<(), String> {
})
}
async fn validate_asr_provider() -> Result<(), String> {
let config = read_openai_provider_config("asr")?;
let model = CredentialsVault::get(CredentialAccount::AsrModel)
.map_err(|e| e.to_string())?
.filter(|s| !s.trim().is_empty())
.ok_or_else(|| "asrModelMissing".to_string())?;
let models = fetch_provider_models(&config).await?;
if models.is_empty() {
return Err("modelsEmpty".to_string());
}
let model = model.trim();
if models.iter().any(|m| m == model) {
Ok(())
} else {
Err("asrModelUnavailable".to_string())
}
}
async fn fetch_provider_models(config: &ProviderConfig) -> Result<Vec<String>, String> {
let url = models_url(&config.base_url);
log::info!("[provider-check] GET {url}");
+1
View File
@@ -322,6 +322,7 @@ export const en: typeof zhCN = {
fetchModels: 'Fetch models',
loadingModels: 'Fetching models…',
modelMissing: 'No model is configured. Please enter a model ID first.',
asrModelUnavailable: 'Current ASR model is not in the provider model list. Please select or enter a valid model.',
modelsEmpty: 'Credentials are valid, but no models were returned.',
modelsLoaded: 'Fetched {{count}} models.',
selectModel: 'Select a model to fill the field above',
+1
View File
@@ -320,6 +320,7 @@ export const zhCN = {
fetchModels: '拉取模型',
loadingModels: '拉取模型中…',
modelMissing: '未配置模型,请先填写模型 ID。',
asrModelUnavailable: '当前 ASR 模型不在供应商返回列表中,请选择或填写有效模型。',
modelsEmpty: '鉴权成功,但没有返回可用模型。',
modelsLoaded: '已拉取 {{count}} 个模型。',
selectModel: '选择一个模型写入上方字段',
+9 -1
View File
@@ -593,10 +593,18 @@ function ProviderTools({ kind, modelAccount, onModelSelected }: { kind: 'llm' |
setResult(result.ok ? 'success' : 'error', t('settings.providers.validateSuccess'));
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (kind === 'llm' && message === 'llmModelMissing') {
if ((kind === 'llm' && message === 'llmModelMissing') || (kind === 'asr' && message === 'asrModelMissing')) {
setResult('empty', t('settings.providers.modelMissing'));
return;
}
if (kind === 'asr' && message === 'asrModelUnavailable') {
setResult('empty', t('settings.providers.asrModelUnavailable'));
return;
}
if (message === 'modelsEmpty') {
setResult('empty', t('settings.providers.modelsEmpty'));
return;
}
setResult('error', providerErrorMessage(error, t));
}
};