mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-29 01:25:33 +08:00
81af0a57f9
Register AppType::Hermes across the entire Rust backend: - Add Hermes variant to AppType enum with additive mode and MCP support - Add hermes field to McpApps, SkillApps, CommonConfigSnippets, and all per-app structs (McpRoot, PromptRoot, VisibleApps, AppSettings) - Create minimal hermes_config.rs with get_hermes_dir() respecting settings override, matching the pattern of other app config modules - Update all match arms in commands, services, deeplink, proxy, mcp, session_manager, and test files - Extract shared build_additive_app_settings() to eliminate duplication between OpenClaw and Hermes deep link handling - Combine identical OpenClaw/Hermes proxy match arms into unified arms
144 lines
4.4 KiB
Rust
144 lines
4.4 KiB
Rust
//! Gemini MCP 同步和导入模块
|
||
|
||
use serde_json::Value;
|
||
use std::collections::HashMap;
|
||
|
||
use crate::app_config::{McpApps, McpConfig, McpServer, MultiAppConfig};
|
||
use crate::error::AppError;
|
||
|
||
use super::validation::{extract_server_spec, validate_server_spec};
|
||
|
||
fn should_sync_gemini_mcp() -> bool {
|
||
// Gemini 未安装/未初始化时:~/.gemini 目录不存在。
|
||
// 按用户偏好:目录缺失时跳过写入/删除,不创建任何文件或目录。
|
||
crate::gemini_config::get_gemini_dir().exists()
|
||
}
|
||
|
||
/// 返回已启用的 MCP 服务器(过滤 enabled==true)
|
||
fn collect_enabled_servers(cfg: &McpConfig) -> HashMap<String, Value> {
|
||
let mut out = HashMap::new();
|
||
for (id, entry) in cfg.servers.iter() {
|
||
let enabled = entry
|
||
.get("enabled")
|
||
.and_then(|v| v.as_bool())
|
||
.unwrap_or(false);
|
||
if !enabled {
|
||
continue;
|
||
}
|
||
match extract_server_spec(entry) {
|
||
Ok(spec) => {
|
||
out.insert(id.clone(), spec);
|
||
}
|
||
Err(err) => {
|
||
log::warn!("跳过无效的 MCP 条目 '{id}': {err}");
|
||
}
|
||
}
|
||
}
|
||
out
|
||
}
|
||
|
||
/// 将 config.json 中 Gemini 的 enabled==true 项写入 Gemini MCP 配置
|
||
pub fn sync_enabled_to_gemini(config: &MultiAppConfig) -> Result<(), AppError> {
|
||
if !should_sync_gemini_mcp() {
|
||
return Ok(());
|
||
}
|
||
let enabled = collect_enabled_servers(&config.mcp.gemini);
|
||
crate::gemini_mcp::set_mcp_servers_map(&enabled)
|
||
}
|
||
|
||
/// 从 Gemini MCP 配置导入到统一结构(v3.7.0+)
|
||
/// 已存在的服务器将启用 Gemini 应用,不覆盖其他字段和应用状态
|
||
pub fn import_from_gemini(config: &mut MultiAppConfig) -> Result<usize, AppError> {
|
||
let map = crate::gemini_mcp::read_mcp_servers_map()?;
|
||
if map.is_empty() {
|
||
return Ok(0);
|
||
}
|
||
|
||
// 确保新结构存在
|
||
let servers = config.mcp.servers.get_or_insert_with(HashMap::new);
|
||
|
||
let mut changed = 0;
|
||
let mut errors = Vec::new();
|
||
|
||
for (id, spec) in map.iter() {
|
||
// 校验:单项失败不中止,收集错误继续处理
|
||
if let Err(e) = validate_server_spec(spec) {
|
||
log::warn!("跳过无效 MCP 服务器 '{id}': {e}");
|
||
errors.push(format!("{id}: {e}"));
|
||
continue;
|
||
}
|
||
|
||
if let Some(existing) = servers.get_mut(id) {
|
||
// 已存在:仅启用 Gemini 应用
|
||
if !existing.apps.gemini {
|
||
existing.apps.gemini = true;
|
||
changed += 1;
|
||
log::info!("MCP 服务器 '{id}' 已启用 Gemini 应用");
|
||
}
|
||
} else {
|
||
// 新建服务器:默认仅启用 Gemini
|
||
servers.insert(
|
||
id.clone(),
|
||
McpServer {
|
||
id: id.clone(),
|
||
name: id.clone(),
|
||
server: spec.clone(),
|
||
apps: McpApps {
|
||
claude: false,
|
||
codex: false,
|
||
gemini: true,
|
||
opencode: false,
|
||
hermes: false,
|
||
},
|
||
description: None,
|
||
homepage: None,
|
||
docs: None,
|
||
tags: Vec::new(),
|
||
},
|
||
);
|
||
changed += 1;
|
||
log::info!("导入新 MCP 服务器 '{id}'");
|
||
}
|
||
}
|
||
|
||
if !errors.is_empty() {
|
||
log::warn!("导入完成,但有 {} 项失败: {:?}", errors.len(), errors);
|
||
}
|
||
|
||
Ok(changed)
|
||
}
|
||
|
||
/// 将单个 MCP 服务器同步到 Gemini live 配置
|
||
pub fn sync_single_server_to_gemini(
|
||
_config: &MultiAppConfig,
|
||
id: &str,
|
||
server_spec: &Value,
|
||
) -> Result<(), AppError> {
|
||
if !should_sync_gemini_mcp() {
|
||
return Ok(());
|
||
}
|
||
// 读取现有的 MCP 配置
|
||
let mut current = crate::gemini_mcp::read_mcp_servers_map()?;
|
||
|
||
// 添加/更新当前服务器
|
||
current.insert(id.to_string(), server_spec.clone());
|
||
|
||
// 写回
|
||
crate::gemini_mcp::set_mcp_servers_map(¤t)
|
||
}
|
||
|
||
/// 从 Gemini live 配置中移除单个 MCP 服务器
|
||
pub fn remove_server_from_gemini(id: &str) -> Result<(), AppError> {
|
||
if !should_sync_gemini_mcp() {
|
||
return Ok(());
|
||
}
|
||
// 读取现有的 MCP 配置
|
||
let mut current = crate::gemini_mcp::read_mcp_servers_map()?;
|
||
|
||
// 移除指定服务器
|
||
current.remove(id);
|
||
|
||
// 写回
|
||
crate::gemini_mcp::set_mcp_servers_map(¤t)
|
||
}
|