Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions src-tauri/src/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub struct McpApps {
pub opencode: bool,
#[serde(default)]
pub hermes: bool,
#[serde(default)]
pub kimi: bool,
}

impl McpApps {
Expand All @@ -30,6 +32,7 @@ impl McpApps {
AppType::Hermes => self.hermes,
AppType::OpenClaw => false,
AppType::Pi => false,
AppType::Kimi => self.kimi,
}
}

Expand All @@ -43,6 +46,7 @@ impl McpApps {
AppType::Hermes => self.hermes = enabled,
AppType::OpenClaw => {}
AppType::Pi => {}
AppType::Kimi => self.kimi = enabled,
}
}

Expand All @@ -64,12 +68,15 @@ impl McpApps {
if self.hermes {
apps.push(AppType::Hermes);
}
if self.kimi {
apps.push(AppType::Kimi);
}
apps
}

/// 检查是否所有应用都未启用
pub fn is_empty(&self) -> bool {
!self.claude && !self.codex && !self.gemini && !self.opencode && !self.hermes
!self.claude && !self.codex && !self.gemini && !self.opencode && !self.hermes && !self.kimi
}
}

Expand All @@ -88,6 +95,8 @@ pub struct SkillApps {
pub hermes: bool,
#[serde(default)]
pub pi: bool,
#[serde(default)]
pub kimi: bool,
}

impl SkillApps {
Expand All @@ -100,6 +109,7 @@ impl SkillApps {
AppType::Hermes => self.hermes,
AppType::OpenClaw => false,
AppType::Pi => self.pi,
AppType::Kimi => self.kimi,
}
}

Expand All @@ -112,11 +122,12 @@ impl SkillApps {
AppType::Hermes => self.hermes = enabled,
AppType::OpenClaw => {}
AppType::Pi => self.pi = enabled,
AppType::Kimi => self.kimi = enabled,
}
}

pub fn is_empty(&self) -> bool {
!self.claude && !self.codex && !self.gemini && !self.opencode && !self.hermes && !self.pi
!self.claude && !self.codex && !self.gemini && !self.opencode && !self.hermes && !self.pi && !self.kimi
}

pub fn only(app: &AppType) -> Self {
Expand All @@ -142,6 +153,7 @@ impl SkillApps {
self.opencode |= other.opencode;
self.hermes |= other.hermes;
self.pi |= other.pi;
self.kimi |= other.kimi;
}
}

Expand Down Expand Up @@ -252,6 +264,8 @@ pub struct McpRoot {
pub hermes: McpConfig,
#[serde(default, skip_serializing_if = "McpConfig::is_empty")]
pub openclaw: McpConfig,
#[serde(default, skip_serializing_if = "McpConfig::is_empty")]
pub kimi: McpConfig,
#[serde(skip)]
pub pi: McpConfig,
}
Expand All @@ -268,6 +282,7 @@ impl Default for McpRoot {
opencode: McpConfig::default(),
hermes: McpConfig::default(),
openclaw: McpConfig::default(),
kimi: McpConfig::default(),
pi: McpConfig::default(),
}
}
Expand Down Expand Up @@ -297,6 +312,8 @@ pub struct PromptRoot {
pub openclaw: PromptConfig,
#[serde(default)]
pub pi: PromptConfig,
#[serde(default)]
pub kimi: PromptConfig,
}

use crate::config::{copy_file, get_app_config_dir, get_app_config_path, write_json_file};
Expand All @@ -315,6 +332,7 @@ pub enum AppType {
Hermes,
OpenClaw,
Pi,
Kimi,
}

impl AppType {
Expand All @@ -327,13 +345,14 @@ impl AppType {
AppType::Hermes => "hermes",
AppType::OpenClaw => "openclaw",
AppType::Pi => "pi",
AppType::Kimi => "kimi",
}
}

pub fn is_additive_mode(&self) -> bool {
matches!(
self,
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi | AppType::Kimi
)
}

Expand All @@ -350,6 +369,7 @@ impl AppType {
AppType::Hermes,
AppType::OpenClaw,
AppType::Pi,
AppType::Kimi,
]
.into_iter()
}
Expand All @@ -374,13 +394,14 @@ impl FromStr for AppType {
"hermes" => Ok(AppType::Hermes),
"openclaw" => Ok(AppType::OpenClaw),
"pi" => Ok(AppType::Pi),
"kimi" => Ok(AppType::Kimi),
other => Err(AppError::localized(
"unsupported_app",
format!(
"不支持的应用标识: '{other}'。可选值: claude, codex, gemini, opencode, hermes, openclaw, pi。"
"不支持的应用标识: '{other}'。可选值: claude, codex, gemini, opencode, hermes, openclaw, pi, kimi。"
),
format!(
"Unsupported app id: '{other}'. Allowed: claude, codex, gemini, opencode, hermes, openclaw, pi."
"Unsupported app id: '{other}'. Allowed: claude, codex, gemini, opencode, hermes, openclaw, pi, kimi."
),
)),
}
Expand All @@ -407,6 +428,9 @@ pub struct CommonConfigSnippets {

#[serde(default, skip_serializing_if = "Option::is_none")]
pub openclaw: Option<String>,

#[serde(default, skip_serializing_if = "Option::is_none")]
pub kimi: Option<String>,
}

impl CommonConfigSnippets {
Expand All @@ -420,6 +444,7 @@ impl CommonConfigSnippets {
AppType::Hermes => self.hermes.as_ref(),
AppType::OpenClaw => self.openclaw.as_ref(),
AppType::Pi => None,
AppType::Kimi => self.kimi.as_ref(),
}
}

Expand All @@ -433,6 +458,7 @@ impl CommonConfigSnippets {
AppType::Hermes => self.hermes = snippet,
AppType::OpenClaw => self.openclaw = snippet,
AppType::Pi => {}
AppType::Kimi => self.kimi = snippet,
}
}
}
Expand Down Expand Up @@ -476,6 +502,7 @@ impl Default for MultiAppConfig {
apps.insert("hermes".to_string(), ProviderManager::default());
apps.insert("openclaw".to_string(), ProviderManager::default());
apps.insert("pi".to_string(), ProviderManager::default());
apps.insert("kimi".to_string(), ProviderManager::default());

Self {
version: 2,
Expand Down Expand Up @@ -590,6 +617,13 @@ impl MultiAppConfig {
updated = true;
}

if !config.apps.contains_key("kimi") {
config
.apps
.insert("kimi".to_string(), ProviderManager::default());
updated = true;
}

// 执行 MCP 迁移(v3.6.x → v3.7.0)
let migrated = config.migrate_mcp_to_unified()?;
if migrated {
Expand Down Expand Up @@ -657,6 +691,7 @@ impl MultiAppConfig {
AppType::Hermes => &self.mcp.hermes,
AppType::OpenClaw => &self.mcp.openclaw,
AppType::Pi => &self.mcp.pi,
AppType::Kimi => &self.mcp.kimi,
}
}

Expand All @@ -670,6 +705,7 @@ impl MultiAppConfig {
AppType::Hermes => &mut self.mcp.hermes,
AppType::OpenClaw => &mut self.mcp.openclaw,
AppType::Pi => &mut self.mcp.pi,
AppType::Kimi => &mut self.mcp.kimi,
}
}

Expand Down Expand Up @@ -699,13 +735,15 @@ impl MultiAppConfig {
AppType::Gemini,
AppType::OpenCode,
AppType::Hermes,
AppType::Kimi,
] {
let old_servers = match app {
AppType::Claude => &self.mcp.claude.servers,
AppType::Codex => &self.mcp.codex.servers,
AppType::Gemini => &self.mcp.gemini.servers,
AppType::OpenCode => &self.mcp.opencode.servers,
AppType::Hermes => &self.mcp.hermes.servers,
AppType::Kimi => &self.mcp.kimi.servers,
AppType::OpenClaw => continue,
AppType::Pi => continue,
};
Expand Down Expand Up @@ -812,6 +850,7 @@ impl MultiAppConfig {
self.mcp.gemini = McpConfig::default();
self.mcp.opencode = McpConfig::default();
self.mcp.hermes = McpConfig::default();
self.mcp.kimi = McpConfig::default();

Ok(true)
}
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/cli/commands/config_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ fn canonical_common_snippet(app_type: AppType, raw: &str) -> Result<Option<Strin
| AppType::OpenCode
| AppType::Hermes
| AppType::OpenClaw
| AppType::Pi => {
| AppType::Pi
| AppType::Kimi => {
let value: serde_json::Value = serde_json::from_str(raw).map_err(|e| {
AppError::InvalidInput(texts::tui_toast_invalid_json(&e.to_string()))
})?;
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/cli/commands/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fn run_app_doctor(app_type: &AppType) -> Result<(), AppError> {
AppType::Claude => check_claude_doctor(),
AppType::Codex => check_codex_doctor(),
AppType::Gemini => check_gemini_doctor(),
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi => {
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi | AppType::Kimi => {
println!(
"{}",
info(&format!(
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/cli/commands/failover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ fn takeover_enabled_for(takeovers: &ProxyTakeoverStatus, app_type: &AppType) ->
AppType::Claude => takeovers.claude,
AppType::Codex => takeovers.codex,
AppType::Gemini => takeovers.gemini,
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi => false,
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi | AppType::Kimi => false,
}
}

Expand Down
10 changes: 7 additions & 3 deletions src-tauri/src/cli/commands/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ fn prompt_and_apply_provider_api_format(
match app_type {
AppType::Claude => prompt_and_apply_claude_api_format(app_type, provider),
AppType::Codex => prompt_and_apply_codex_api_format(app_type, provider),
AppType::Gemini | AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi => {
AppType::Gemini | AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi | AppType::Kimi => {
Ok(())
}
}
Expand Down Expand Up @@ -1441,7 +1441,7 @@ fn build_add_settings_config(
}
Ok(settings)
}
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw => {
AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Kimi => {
let current = current.ok_or_else(|| add_additive_requires_config_error(app_type))?;
let api_key = non_empty(args.api_key.clone());
let base_url = non_empty(args.base_url.clone());
Expand Down Expand Up @@ -1528,7 +1528,7 @@ fn apply_add_provider_api_format(
};
apply_codex_api_format(provider, format);
}
AppType::Gemini | AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi => {
AppType::Gemini | AppType::OpenCode | AppType::Hermes | AppType::OpenClaw | AppType::Pi | AppType::Kimi => {
}
}
Ok(())
Expand Down Expand Up @@ -1854,6 +1854,10 @@ fn existing_provider_ids_for_duplicate(
.into_iter()
.map(|(id, _)| id)
.collect::<Vec<_>>(),
AppType::Kimi => crate::kimi_config::get_providers()?
.into_iter()
.map(|(id, _)| id)
.collect::<Vec<_>>(),
_ => Vec::new(),
};
ids.extend(live_ids);
Expand Down
Loading