From 7997b2c7b3e2a3e1c9e1bebd052d975306c496fb Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 15 Jan 2026 16:20:03 +0800 Subject: [PATCH] feat(opencode): Phase 6 - Tauri command extensions for OpenCode - Add import_opencode_providers_from_live command to provider.rs - Register new command in lib.rs invoke_handler - Update commands/mcp.rs: include OpenCode in sync_other_side logic - Add McpService::import_from_opencode to import_mcp_from_apps - Implement MCP sync/remove for OpenCode in services/mcp.rs - sync_server_to_app_no_config now calls sync_single_server_to_opencode - remove_server_from_app now calls remove_server_from_opencode --- src-tauri/src/commands/mcp.rs | 2 ++ src-tauri/src/commands/provider.rs | 14 ++++++++++ src-tauri/src/lib.rs | 2 ++ src-tauri/src/services/mcp.rs | 45 ++++++++++++++++++++++++++---- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/commands/mcp.rs b/src-tauri/src/commands/mcp.rs index 299fed6b..8963584c 100644 --- a/src-tauri/src/commands/mcp.rs +++ b/src-tauri/src/commands/mcp.rs @@ -122,6 +122,7 @@ pub async fn upsert_mcp_server_in_config( new_server.apps.claude = true; new_server.apps.codex = true; new_server.apps.gemini = true; + new_server.apps.opencode = true; } McpService::upsert_server(&state, new_server) @@ -200,5 +201,6 @@ pub async fn import_mcp_from_apps(state: State<'_, AppState>) -> Result) -> Result { + crate::services::provider::import_opencode_providers_from_live(state.inner()) + .map_err(|e| e.to_string()) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d39c83c4..ceab5e32 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -875,6 +875,8 @@ pub fn run() { commands::upsert_universal_provider, commands::delete_universal_provider, commands::sync_universal_provider, + // OpenCode specific + commands::import_opencode_providers_from_live, // Global upstream proxy commands::get_global_proxy_url, commands::set_global_proxy_url, diff --git a/src-tauri/src/services/mcp.rs b/src-tauri/src/services/mcp.rs index 81decbac..602765d2 100644 --- a/src-tauri/src/services/mcp.rs +++ b/src-tauri/src/services/mcp.rs @@ -114,9 +114,7 @@ impl McpService { mcp::sync_single_server_to_gemini(&Default::default(), &server.id, &server.server)?; } AppType::OpenCode => { - // OpenCode MCP sync will be implemented in Phase 4 - // For now, skip silently - log::debug!("OpenCode MCP sync not yet implemented, skipping"); + mcp::sync_single_server_to_opencode(&Default::default(), &server.id, &server.server)?; } } Ok(()) @@ -141,8 +139,7 @@ impl McpService { AppType::Codex => mcp::remove_server_from_codex(id)?, AppType::Gemini => mcp::remove_server_from_gemini(id)?, AppType::OpenCode => { - // OpenCode MCP removal will be implemented in Phase 4 - log::debug!("OpenCode MCP removal not yet implemented, skipping"); + mcp::remove_server_from_opencode(id)?; } } Ok(()) @@ -320,4 +317,42 @@ impl McpService { Ok(new_count) } + + /// 从 OpenCode 导入 MCP(v3.9.2+ 新增) + pub fn import_from_opencode(state: &AppState) -> Result { + // 创建临时 MultiAppConfig 用于导入 + let mut temp_config = crate::app_config::MultiAppConfig::default(); + + // 调用原有的导入逻辑(从 mcp/opencode.rs) + let count = crate::mcp::import_from_opencode(&mut temp_config)?; + + let mut new_count = 0; + + // 如果有导入的服务器,保存到数据库 + if count > 0 { + if let Some(servers) = &temp_config.mcp.servers { + let mut existing = state.db.get_all_mcp_servers()?; + for server in servers.values() { + // 已存在:仅启用 OpenCode,不覆盖其他字段(与导入模块语义保持一致) + let to_save = if let Some(existing_server) = existing.get(&server.id) { + let mut merged = existing_server.clone(); + merged.apps.opencode = true; + merged + } else { + // 真正的新服务器 + new_count += 1; + server.clone() + }; + + state.db.save_mcp_server(&to_save)?; + existing.insert(to_save.id.clone(), to_save.clone()); + + // 同步到对应应用 live 配置 + Self::sync_server_to_apps(state, &to_save)?; + } + } + } + + Ok(new_count) + } }