Files
DevFlow/src-tauri/src/commands/ai/secret.rs
T

44 lines
2.3 KiB
Rust

//! FR-S1 api_key 密钥管理 — **转发壳(方案 B 下沉,2026-06-16)**
//!
//! 纯密钥逻辑(get/set/delete/resolve/ensure/migrate + failcount sidecar)已下沉到
//! `df_storage::secret`(密钥解析唯一源,供 df-nodes AiNode 与本转发壳共用,DRY)。
//!
//! 本文件保留两项职责:
//! 1. **转发**:`pub use df_storage::secret::*;` —— 保 src-tauri 内调用路径
//! `crate::commands::ai::secret::*` / `super::secret::*` 不变(12 调用点零改动)。
//! 2. **`build_provider_for`**:消费点统一入口(resolve→ensure→`df_ai::build_provider` 三步打包)。
//! 此函数依赖 `df_ai::build_provider`,**不下沉** —— df-storage 不依赖 df-ai,
//! 下沉会引 df-storage→df-ai 反向依赖(循环)。src-tauri 既依赖 df-storage 又依赖 df-ai,
//! 天然适合拼装,故留 app 层。
//!
//! 下沉前原文件全貌见 git 历史(commit c10adaf 前 src-tauri/src/commands/ai/secret.rs:1-228)。
// 转发所有下沉的纯密钥函数,保 src-tauri 内调用路径不变。
// 不再额外 `use df_storage::secret::{...}` 显式导入 —— 会与 glob re-export 冲突
// (编译器判 private function import)。build_provider_for 内用全限定路径调即可。
#[allow(unused_imports)]
pub use df_storage::secret::*;
use df_storage::models::AiProviderRecord;
/// 消费点统一入口:resolve_provider_secret → ensure_resolved_key → build_provider 三步打包。
///
/// 替代散落各处的「resolve + build_provider」二件套复制(漏 ensure_resolved_key → keyring 读不到时
/// 空 key 照发请求吃 401,用户看「key 已保存」反复重试无解)。返 Result 让调用方按场景处理:
/// - 主链(agentic loop):空 key 早失败 emit AiError
/// - 后台 task(title/knowledge 提炼/embedding):Err 上层降级/记 log
///
/// **不下沉原因**:依赖 `df_ai::build_provider`,下沉 df-storage 会引 df-storage→df-ai 循环依赖。
pub fn build_provider_for(
record: &AiProviderRecord,
) -> Result<Box<dyn df_ai::provider::LlmProvider>, String> {
let api_key = df_storage::secret::resolve_provider_secret(record);
let api_key = df_storage::secret::ensure_resolved_key(&record.name, &api_key)?;
Ok(df_ai::build_provider(
&record.provider_type,
&record.base_url,
&api_key,
&record.default_model,
))
}