From 23a407544ad1c2690378dafa00578e6a9b1e6758 Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Sat, 22 Nov 2025 23:27:27 +0800 Subject: [PATCH] refactor(commands): update command layer to use database API - Update config commands to query database for providers and settings - Modify provider commands to pass database handle to services - Update MCP commands to use database-backed operations - Refactor prompt and skill commands to leverage database storage - Simplify import/export commands with database integration --- src-tauri/src/commands/config.rs | 71 ++++++++------------- src-tauri/src/commands/import_export.rs | 20 +++++- src-tauri/src/commands/mcp.rs | 11 ++-- src-tauri/src/commands/prompt.rs | 4 +- src-tauri/src/commands/provider.rs | 4 +- src-tauri/src/commands/skill.rs | 83 +++++++++---------------- 6 files changed, 82 insertions(+), 111 deletions(-) diff --git a/src-tauri/src/commands/config.rs b/src-tauri/src/commands/config.rs index 2f81def..29ee9c6 100644 --- a/src-tauri/src/commands/config.rs +++ b/src-tauri/src/commands/config.rs @@ -141,11 +141,10 @@ pub async fn open_app_config_folder(handle: AppHandle) -> Result { pub async fn get_claude_common_config_snippet( state: tauri::State<'_, crate::store::AppState>, ) -> Result, String> { - let guard = state - .config - .read() - .map_err(|e| format!("读取配置锁失败: {e}"))?; - Ok(guard.common_config_snippets.claude.clone()) + state + .db + .get_config_snippet("claude") + .map_err(|e| e.to_string()) } /// 设置 Claude 通用配置片段(已废弃,使用 set_common_config_snippet) @@ -154,24 +153,22 @@ pub async fn set_claude_common_config_snippet( snippet: String, state: tauri::State<'_, crate::store::AppState>, ) -> Result<(), String> { - let mut guard = state - .config - .write() - .map_err(|e| format!("写入配置锁失败: {e}"))?; - // 验证是否为有效的 JSON(如果不为空) if !snippet.trim().is_empty() { serde_json::from_str::(&snippet) .map_err(|e| format!("无效的 JSON 格式: {e}"))?; } - guard.common_config_snippets.claude = if snippet.trim().is_empty() { + let value = if snippet.trim().is_empty() { None } else { Some(snippet) }; - guard.save().map_err(|e| e.to_string())?; + state + .db + .set_config_snippet("claude", value) + .map_err(|e| e.to_string())?; Ok(()) } @@ -181,17 +178,10 @@ pub async fn get_common_config_snippet( app_type: String, state: tauri::State<'_, crate::store::AppState>, ) -> Result, String> { - use crate::app_config::AppType; - use std::str::FromStr; - - let app = AppType::from_str(&app_type).map_err(|e| format!("无效的应用类型: {e}"))?; - - let guard = state - .config - .read() - .map_err(|e| format!("读取配置锁失败: {e}"))?; - - Ok(guard.common_config_snippets.get(&app).cloned()) + state + .db + .get_config_snippet(&app_type) + .map_err(|e| e.to_string()) } /// 设置通用配置片段(统一接口) @@ -201,40 +191,31 @@ pub async fn set_common_config_snippet( snippet: String, state: tauri::State<'_, crate::store::AppState>, ) -> Result<(), String> { - use crate::app_config::AppType; - use std::str::FromStr; - - let app = AppType::from_str(&app_type).map_err(|e| format!("无效的应用类型: {e}"))?; - - let mut guard = state - .config - .write() - .map_err(|e| format!("写入配置锁失败: {e}"))?; - // 验证格式(根据应用类型) if !snippet.trim().is_empty() { - match app { - AppType::Claude | AppType::Gemini => { + match app_type.as_str() { + "claude" | "gemini" => { // 验证 JSON 格式 serde_json::from_str::(&snippet) .map_err(|e| format!("无效的 JSON 格式: {e}"))?; } - AppType::Codex => { + "codex" => { // TOML 格式暂不验证(或可使用 toml crate) // 注意:TOML 验证较为复杂,暂时跳过 } + _ => {} } } - guard.common_config_snippets.set( - &app, - if snippet.trim().is_empty() { - None - } else { - Some(snippet) - }, - ); + let value = if snippet.trim().is_empty() { + None + } else { + Some(snippet) + }; - guard.save().map_err(|e| e.to_string())?; + state + .db + .set_config_snippet(&app_type, value) + .map_err(|e| e.to_string())?; Ok(()) } diff --git a/src-tauri/src/commands/import_export.rs b/src-tauri/src/commands/import_export.rs index a16787d..9d237a9 100644 --- a/src-tauri/src/commands/import_export.rs +++ b/src-tauri/src/commands/import_export.rs @@ -29,11 +29,17 @@ pub async fn export_config_to_file( } /// 从文件导入配置 +/// TODO: 需要重构以使用数据库而不是 JSON 配置 #[tauri::command] pub async fn import_config_from_file( - #[allow(non_snake_case)] filePath: String, - state: State<'_, AppState>, + #[allow(non_snake_case)] _filePath: String, + _state: State<'_, AppState>, ) -> Result { + // TODO: 实现基于数据库的导入逻辑 + // 当前暂时禁用此功能 + Err("配置导入功能正在重构中,暂时不可用".to_string()) + + /* 旧的实现,需要重构: let (new_config, backup_id) = tauri::async_runtime::spawn_blocking(move || { let path_buf = PathBuf::from(&filePath); ConfigService::load_config_for_import(&path_buf) @@ -55,11 +61,18 @@ pub async fn import_config_from_file( "message": "Configuration imported successfully", "backupId": backup_id })) + */ } /// 同步当前供应商配置到对应的 live 文件 +/// TODO: 需要重构以使用数据库而不是 JSON 配置 #[tauri::command] -pub async fn sync_current_providers_live(state: State<'_, AppState>) -> Result { +pub async fn sync_current_providers_live(_state: State<'_, AppState>) -> Result { + // TODO: 实现基于数据库的同步逻辑 + // 当前暂时禁用此功能 + Err("配置同步功能正在重构中,暂时不可用".to_string()) + + /* 旧的实现,需要重构: { let mut config_state = state .config @@ -73,6 +86,7 @@ pub async fn sync_current_providers_live(state: State<'_, AppState>) -> Result, -) -> Result, String> { +) -> Result, String> { McpService::get_all_servers(&state).map_err(|e| e.to_string()) } diff --git a/src-tauri/src/commands/prompt.rs b/src-tauri/src/commands/prompt.rs index 6064e2f..20bd9f2 100644 --- a/src-tauri/src/commands/prompt.rs +++ b/src-tauri/src/commands/prompt.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use indexmap::IndexMap; use std::str::FromStr; use tauri::State; @@ -12,7 +12,7 @@ use crate::store::AppState; pub async fn get_prompts( app: String, state: State<'_, AppState>, -) -> Result, String> { +) -> Result, String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; PromptService::get_prompts(&state, app_type).map_err(|e| e.to_string()) } diff --git a/src-tauri/src/commands/provider.rs b/src-tauri/src/commands/provider.rs index 7f51389..280d744 100644 --- a/src-tauri/src/commands/provider.rs +++ b/src-tauri/src/commands/provider.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use indexmap::IndexMap; use tauri::State; use crate::app_config::AppType; @@ -13,7 +13,7 @@ use std::str::FromStr; pub fn get_providers( state: State<'_, AppState>, app: String, -) -> Result, String> { +) -> Result, String> { let app_type = AppType::from_str(&app).map_err(|e| e.to_string())?; ProviderService::list(state.inner(), app_type).map_err(|e| e.to_string()) } diff --git a/src-tauri/src/commands/skill.rs b/src-tauri/src/commands/skill.rs index 3ed526c..d9731c0 100644 --- a/src-tauri/src/commands/skill.rs +++ b/src-tauri/src/commands/skill.rs @@ -13,10 +13,7 @@ pub async fn get_skills( service: State<'_, SkillServiceState>, app_state: State<'_, AppState>, ) -> Result, String> { - let repos = { - let config = app_state.config.read().map_err(|e| e.to_string())?; - config.skills.repos.clone() - }; + let repos = app_state.db.get_skill_repos().map_err(|e| e.to_string())?; service .0 @@ -32,10 +29,7 @@ pub async fn install_skill( app_state: State<'_, AppState>, ) -> Result { // 先在不持有写锁的情况下收集仓库与技能信息 - let repos = { - let config = app_state.config.read().map_err(|e| e.to_string())?; - config.skills.repos.clone() - }; + let repos = app_state.db.get_skill_repos().map_err(|e| e.to_string())?; let skills = service .0 @@ -85,19 +79,16 @@ pub async fn install_skill( .map_err(|e| e.to_string())?; } - { - let mut config = app_state.config.write().map_err(|e| e.to_string())?; - - config.skills.skills.insert( - directory.clone(), - SkillState { + app_state + .db + .update_skill_state( + &directory, + &SkillState { installed: true, installed_at: Utc::now(), }, - ); - } - - app_state.save().map_err(|e| e.to_string())?; + ) + .map_err(|e| e.to_string())?; Ok(true) } @@ -113,13 +104,17 @@ pub fn uninstall_skill( .uninstall_skill(directory.clone()) .map_err(|e| e.to_string())?; - { - let mut config = app_state.config.write().map_err(|e| e.to_string())?; - - config.skills.skills.remove(&directory); - } - - app_state.save().map_err(|e| e.to_string())?; + // Remove from database by setting installed = false + app_state + .db + .update_skill_state( + &directory, + &SkillState { + installed: false, + installed_at: Utc::now(), + }, + ) + .map_err(|e| e.to_string())?; Ok(true) } @@ -129,28 +124,19 @@ pub fn get_skill_repos( _service: State<'_, SkillServiceState>, app_state: State<'_, AppState>, ) -> Result, String> { - let config = app_state.config.read().map_err(|e| e.to_string())?; - - Ok(config.skills.repos.clone()) + app_state.db.get_skill_repos().map_err(|e| e.to_string()) } #[tauri::command] pub fn add_skill_repo( repo: SkillRepo, - service: State<'_, SkillServiceState>, + _service: State<'_, SkillServiceState>, app_state: State<'_, AppState>, ) -> Result { - { - let mut config = app_state.config.write().map_err(|e| e.to_string())?; - - service - .0 - .add_repo(&mut config.skills, repo) - .map_err(|e| e.to_string())?; - } - - app_state.save().map_err(|e| e.to_string())?; - + app_state + .db + .save_skill_repo(&repo) + .map_err(|e| e.to_string())?; Ok(true) } @@ -158,19 +144,12 @@ pub fn add_skill_repo( pub fn remove_skill_repo( owner: String, name: String, - service: State<'_, SkillServiceState>, + _service: State<'_, SkillServiceState>, app_state: State<'_, AppState>, ) -> Result { - { - let mut config = app_state.config.write().map_err(|e| e.to_string())?; - - service - .0 - .remove_repo(&mut config.skills, owner, name) - .map_err(|e| e.to_string())?; - } - - app_state.save().map_err(|e| e.to_string())?; - + app_state + .db + .delete_skill_repo(&owner, &name) + .map_err(|e| e.to_string())?; Ok(true) }