Skip to content

Commit 767d9d9

Browse files
committed
fix(ai): Provider 列表锁内 I/O 释放与入参净化(v0.11.6 M1)
1 parent c80c1f0 commit 767d9d9

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

‎app/src-tauri/src/commands_ai_providers.rs‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,27 @@ pub fn ai_provider_presets() -> Vec<AiProviderView> {
5959
/// 当前 Provider 列表(含默认标记与密钥存在性)。
6060
#[tauri::command]
6161
pub fn ai_provider_list(state: State<'_, AppState>) -> Result<Vec<AiProviderView>, String> {
62-
let store = state.ai_providers.lock().map_err(|e| format!("AI Provider 存储锁中毒: {}", e))?;
63-
let default_id = store.effective_default_id();
62+
// 快照后释放锁——load_key 为 DPAPI 文件 I/O,不持配置锁(短锁契约)
63+
let snapshot = {
64+
let store = state.ai_providers.lock().map_err(|e| format!("AI Provider 存储锁中毒: {}", e))?;
65+
let default_id = store.effective_default_id();
66+
let ids: Vec<(String, bool)> = store
67+
.providers
68+
.iter()
69+
.map(|p| (p.id.clone(), Some(p.id.as_str()) == default_id.as_deref()))
70+
.collect();
71+
(store.providers.clone(), ids)
72+
};
6473
let mut views = Vec::new();
65-
for p in &store.providers {
74+
for (id, is_default) in &snapshot.1 {
6675
let has_key = state
6776
.ai_credentials
68-
.load_key(&provider_scope(&p.id))
77+
.load_key(&provider_scope(id))
6978
.map(|k| k.is_some())
7079
.unwrap_or(false);
71-
views.push(to_view(p, has_key, Some(p.id.as_str()) == default_id.as_deref()));
80+
if let Some(p) = snapshot.0.iter().find(|p| &p.id == id) {
81+
views.push(to_view(p, has_key, *is_default));
82+
}
7283
}
7384
Ok(views)
7485
}
@@ -82,6 +93,9 @@ pub fn ai_provider_add(state: State<'_, AppState>, input: AiProviderInput) -> Re
8293
});
8394
provider.validate()?;
8495
let mut store = state.ai_providers.lock().map_err(|e| format!("AI Provider 存储锁中毒: {}", e))?;
96+
// 持锁跨 save_key + save:保证凭据与配置写入原子性(凭据先写——
97+
// 若 JSON 写入失败,凭据已存的残留可通过重试修复;反向序会留下
98+
// 无凭据的 Provider)
8599
if store.get(&provider.id).is_some() {
86100
return Err(format!("Provider id 已存在: {}", provider.id));
87101
}
@@ -215,7 +229,10 @@ fn resolve_input(input: &AiProviderInput) -> Result<AiProviderConfig, String> {
215229
models: input.models.iter().map(|m| m.trim().to_string()).filter(|m| !m.is_empty()).collect(),
216230
default_model: input.default_model.trim().to_string(),
217231
enabled: input.enabled,
218-
fallback_order: input.fallback_order.clone(),
232+
fallback_order: input.fallback_order.iter()
233+
.map(|s| s.trim().to_string())
234+
.filter(|s| !s.is_empty())
235+
.collect(),
219236
})
220237
}
221238

0 commit comments

Comments
 (0)