From e85878e95a6961049571281d24cb10ae1aceca91 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 1 Feb 2026 20:31:21 +0800 Subject: [PATCH] feat(services): add OpenClaw branches to backend services - Add OpenClaw branches to proxy service (not supported) - Add OpenClaw to MCP service (skip sync, MCP still in development) - Add OpenClaw skills directory path - Update ProxyTakeoverStatus with openclaw field - Add OpenClaw to stream check (not supported) --- src-tauri/src/proxy/providers/mod.rs | 8 ++++++ src-tauri/src/proxy/types.rs | 2 ++ src-tauri/src/services/config.rs | 4 +++ src-tauri/src/services/mcp.rs | 9 ++++++ src-tauri/src/services/proxy.rs | 38 ++++++++++++++++++++++++++ src-tauri/src/services/skill.rs | 8 ++++++ src-tauri/src/services/stream_check.rs | 28 +++++++++++++++++++ 7 files changed, 97 insertions(+) diff --git a/src-tauri/src/proxy/providers/mod.rs b/src-tauri/src/proxy/providers/mod.rs index 61be1087e..a4bb3de76 100644 --- a/src-tauri/src/proxy/providers/mod.rs +++ b/src-tauri/src/proxy/providers/mod.rs @@ -136,6 +136,10 @@ impl ProviderType { // OpenCode doesn't support proxy, but return a default type for completeness ProviderType::Codex // Fallback to Codex-like type } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy, but return a default type for completeness + ProviderType::Codex // Fallback to Codex-like type + } } } @@ -184,6 +188,10 @@ pub fn get_adapter(app_type: &AppType) -> Box { // OpenCode doesn't support proxy, fallback to Codex adapter Box::new(CodexAdapter::new()) } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy, fallback to Codex adapter + Box::new(CodexAdapter::new()) + } } } diff --git a/src-tauri/src/proxy/types.rs b/src-tauri/src/proxy/types.rs index cf8dd7c8c..5118c2bbe 100644 --- a/src-tauri/src/proxy/types.rs +++ b/src-tauri/src/proxy/types.rs @@ -113,6 +113,8 @@ pub struct ProxyTakeoverStatus { pub claude: bool, pub codex: bool, pub gemini: bool, + pub opencode: bool, + pub openclaw: bool, } /// API 格式类型(预留,当前不需要格式转换) diff --git a/src-tauri/src/services/config.rs b/src-tauri/src/services/config.rs index a226e93ae..d354cccb1 100644 --- a/src-tauri/src/services/config.rs +++ b/src-tauri/src/services/config.rs @@ -126,6 +126,10 @@ impl ConfigService { // OpenCode uses additive mode, no live sync needed // OpenCode providers are managed directly in the config file } + AppType::OpenClaw => { + // OpenClaw uses additive mode, no live sync needed + // OpenClaw providers are managed directly in the config file + } } Ok(()) diff --git a/src-tauri/src/services/mcp.rs b/src-tauri/src/services/mcp.rs index 8d1211bbc..1080480b3 100644 --- a/src-tauri/src/services/mcp.rs +++ b/src-tauri/src/services/mcp.rs @@ -123,6 +123,11 @@ impl McpService { &server.server, )?; } + AppType::OpenClaw => { + // OpenClaw MCP support is still in development (Issue #4834) + // Skip for now + log::debug!("OpenClaw MCP support is still in development, skipping sync"); + } } Ok(()) } @@ -148,6 +153,10 @@ impl McpService { AppType::OpenCode => { mcp::remove_server_from_opencode(id)?; } + AppType::OpenClaw => { + // OpenClaw MCP support is still in development + log::debug!("OpenClaw MCP support is still in development, skipping remove"); + } } Ok(()) } diff --git a/src-tauri/src/services/proxy.rs b/src-tauri/src/services/proxy.rs index 0f429b030..5325f4af1 100644 --- a/src-tauri/src/services/proxy.rs +++ b/src-tauri/src/services/proxy.rs @@ -210,11 +210,16 @@ impl ProxyService { .await .map(|c| c.enabled) .unwrap_or(false); + // OpenCode and OpenClaw don't support proxy features, always return false + let opencode_enabled = false; + let openclaw_enabled = false; Ok(ProxyTakeoverStatus { claude: claude_enabled, codex: codex_enabled, gemini: gemini_enabled, + opencode: opencode_enabled, + openclaw: openclaw_enabled, }) } @@ -372,6 +377,10 @@ impl ProxyService { // OpenCode doesn't support proxy features return Err("OpenCode 不支持代理功能".to_string()); } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features + return Err("OpenClaw 不支持代理功能".to_string()); + } }; self.sync_live_config_to_provider(app_type, &live_config) @@ -588,6 +597,9 @@ impl ProxyService { AppType::OpenCode => { // OpenCode doesn't support proxy features, skip silently } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features, skip silently + } } Ok(()) @@ -770,6 +782,10 @@ impl ProxyService { // OpenCode doesn't support proxy features return Err("OpenCode 不支持代理功能".to_string()); } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features + return Err("OpenClaw 不支持代理功能".to_string()); + } }; let json_str = serde_json::to_string(&config) @@ -982,6 +998,10 @@ impl ProxyService { // OpenCode doesn't support proxy features return Err("OpenCode 不支持代理功能".to_string()); } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features + return Err("OpenClaw 不支持代理功能".to_string()); + } } Ok(()) @@ -1068,6 +1088,9 @@ impl ProxyService { AppType::OpenCode => { // OpenCode doesn't support proxy features, skip silently } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features, skip silently + } } Ok(()) @@ -1103,6 +1126,9 @@ impl ProxyService { AppType::OpenCode => { // OpenCode doesn't support proxy features, skip silently } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features, skip silently + } } Ok(()) @@ -1186,6 +1212,10 @@ impl ProxyService { // OpenCode doesn't support proxy features Err("OpenCode 不支持代理功能".to_string()) } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features + Err("OpenClaw 不支持代理功能".to_string()) + } } } @@ -1207,6 +1237,10 @@ impl ProxyService { // OpenCode doesn't support proxy takeover false } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy takeover + false + } } } @@ -1250,6 +1284,10 @@ impl ProxyService { // OpenCode doesn't support proxy features Ok(()) } + AppType::OpenClaw => { + // OpenClaw doesn't support proxy features + Ok(()) + } } } diff --git a/src-tauri/src/services/skill.rs b/src-tauri/src/services/skill.rs index 4a2e671ef..f02136075 100644 --- a/src-tauri/src/services/skill.rs +++ b/src-tauri/src/services/skill.rs @@ -230,6 +230,11 @@ impl SkillService { return Ok(custom.join("skills")); } } + AppType::OpenClaw => { + if let Some(custom) = crate::settings::get_openclaw_override_dir() { + return Ok(custom.join("skills")); + } + } } // 默认路径:回退到用户主目录下的标准位置 @@ -244,6 +249,7 @@ impl SkillService { AppType::Codex => home.join(".codex").join("skills"), AppType::Gemini => home.join(".gemini").join("skills"), AppType::OpenCode => home.join(".config").join("opencode").join("skills"), + AppType::OpenClaw => home.join(".openclaw").join("skills"), }) } @@ -562,6 +568,7 @@ impl SkillService { AppType::Codex => "codex", AppType::Gemini => "gemini", AppType::OpenCode => "opencode", + AppType::OpenClaw => "openclaw", }; unmanaged @@ -611,6 +618,7 @@ impl SkillService { AppType::Codex => "codex", AppType::Gemini => "gemini", AppType::OpenCode => "opencode", + AppType::OpenClaw => "openclaw", }; found_in.push(app_str.to_string()); } diff --git a/src-tauri/src/services/stream_check.rs b/src-tauri/src/services/stream_check.rs index c7afaa55e..b5bf88887 100644 --- a/src-tauri/src/services/stream_check.rs +++ b/src-tauri/src/services/stream_check.rs @@ -240,6 +240,14 @@ impl StreamCheckService { "OpenCode does not support health check yet", )); } + AppType::OpenClaw => { + // OpenClaw doesn't support stream check yet + return Err(AppError::localized( + "openclaw_no_stream_check", + "OpenClaw 暂不支持健康检查", + "OpenClaw does not support health check yet", + )); + } }; let response_time = start.elapsed().as_millis() as u64; @@ -567,6 +575,11 @@ impl StreamCheckService { // Try to extract first model from the models object Self::extract_opencode_model(provider).unwrap_or_else(|| "gpt-4o".to_string()) } + AppType::OpenClaw => { + // OpenClaw uses models array in settings_config + // Try to extract first model from the models array + Self::extract_openclaw_model(provider).unwrap_or_else(|| "gpt-4o".to_string()) + } } } @@ -580,6 +593,21 @@ impl StreamCheckService { models.keys().next().map(|s| s.to_string()) } + fn extract_openclaw_model(provider: &Provider) -> Option { + // OpenClaw uses models array: [{ "id": "model-id", "name": "Model Name" }] + let models = provider + .settings_config + .get("models") + .and_then(|m| m.as_array())?; + + // Return the first model ID from the models array + models + .first() + .and_then(|m| m.get("id")) + .and_then(|id| id.as_str()) + .map(|s| s.to_string()) + } + fn extract_env_model(provider: &Provider, key: &str) -> Option { provider .settings_config