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
This commit is contained in:
YoVinchen
2025-11-22 23:27:27 +08:00
parent 2b34dc4ec9
commit 23a407544a
6 changed files with 82 additions and 111 deletions

View File

@@ -141,11 +141,10 @@ pub async fn open_app_config_folder(handle: AppHandle) -> Result<bool, String> {
pub async fn get_claude_common_config_snippet(
state: tauri::State<'_, crate::store::AppState>,
) -> Result<Option<String>, 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::<serde_json::Value>(&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<Option<String>, 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::<serde_json::Value>(&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() {
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(())
}

View File

@@ -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<Value, String> {
// 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<Value, String> {
pub async fn sync_current_providers_live(_state: State<'_, AppState>) -> Result<Value, String> {
// 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<V
"success": true,
"message": "Live configuration synchronized"
}))
*/
}
/// 保存文件对话框

View File

@@ -1,5 +1,6 @@
#![allow(non_snake_case)]
use indexmap::IndexMap;
use std::collections::HashMap;
use serde::Serialize;
@@ -82,12 +83,8 @@ pub async fn upsert_mcp_server_in_config(
// 读取现有的服务器(如果存在)
let existing_server = {
let cfg = state.config.read().map_err(|e| e.to_string())?;
if let Some(servers) = &cfg.mcp.servers {
let servers = state.db.get_all_mcp_servers().map_err(|e| e.to_string())?;
servers.get(&id).cloned()
} else {
None
}
};
// 构建新的统一服务器结构
@@ -165,7 +162,7 @@ use crate::app_config::McpServer;
#[tauri::command]
pub async fn get_mcp_servers(
state: State<'_, AppState>,
) -> Result<HashMap<String, McpServer>, String> {
) -> Result<IndexMap<String, McpServer>, String> {
McpService::get_all_servers(&state).map_err(|e| e.to_string())
}

View File

@@ -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<HashMap<String, Prompt>, String> {
) -> Result<IndexMap<String, Prompt>, 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())
}

View File

@@ -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<HashMap<String, Provider>, String> {
) -> Result<IndexMap<String, Provider>, 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())
}

View File

@@ -13,10 +13,7 @@ pub async fn get_skills(
service: State<'_, SkillServiceState>,
app_state: State<'_, AppState>,
) -> Result<Vec<Skill>, 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<bool, 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())?;
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<Vec<SkillRepo>, 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<bool, String> {
{
let mut config = app_state.config.write().map_err(|e| e.to_string())?;
service
.0
.add_repo(&mut config.skills, repo)
app_state
.db
.save_skill_repo(&repo)
.map_err(|e| e.to_string())?;
}
app_state.save().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<bool, String> {
{
let mut config = app_state.config.write().map_err(|e| e.to_string())?;
service
.0
.remove_repo(&mut config.skills, owner, name)
app_state
.db
.delete_skill_repo(&owner, &name)
.map_err(|e| e.to_string())?;
}
app_state.save().map_err(|e| e.to_string())?;
Ok(true)
}