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
This commit is contained in:
Jason
2026-01-15 16:20:03 +08:00
parent b8538b211d
commit 7997b2c7b3
4 changed files with 58 additions and 5 deletions

View File

@@ -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<usize, S
total += McpService::import_from_claude(&state).unwrap_or(0);
total += McpService::import_from_codex(&state).unwrap_or(0);
total += McpService::import_from_gemini(&state).unwrap_or(0);
total += McpService::import_from_opencode(&state).unwrap_or(0);
Ok(total)
}

View File

@@ -325,3 +325,17 @@ pub fn sync_universal_provider(
Ok(result)
}
// ============================================================================
// OpenCode 专属命令
// ============================================================================
/// 从 OpenCode live 配置导入供应商到数据库
///
/// 这是 OpenCode 特有的功能,因为 OpenCode 使用累加模式,
/// 用户可能已经在 opencode.json 中配置了供应商。
#[tauri::command]
pub fn import_opencode_providers_from_live(state: State<'_, AppState>) -> Result<usize, String> {
crate::services::provider::import_opencode_providers_from_live(state.inner())
.map_err(|e| e.to_string())
}

View File

@@ -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,

View File

@@ -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 导入 MCPv3.9.2+ 新增)
pub fn import_from_opencode(state: &AppState) -> Result<usize, AppError> {
// 创建临时 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)
}
}