Files
CC-Switch/src-tauri/src/prompt_files.rs
T
Jason 8b3ad9caf9 feat(claude-desktop): add 3P provider switching with proxy gateway
Adds a new ClaudeDesktop AppType that writes Claude Desktop's third-party
inference profile under configLibrary/, sharing _meta.json with other
launchers (Ollama-compatible) so cc-switch can coexist with them.

Two switch modes:
- direct: provider already exposes claude-* / anthropic/claude-* model
  ids on Anthropic Messages, Claude Desktop connects to it directly.
- proxy: cc-switch's local proxy acts as the inference gateway,
  presenting only claude-* route names to Claude Desktop and mapping
  them to real upstream models. Required after Anthropic restricted
  Claude Desktop to claude-family ids.

Backend:
- New module claude_desktop_config with snapshot/rollback, official seed
  bypass, /claude-desktop/v1/{models,messages} routes, and a single
  source of truth for default proxy routes.
- Gateway token persisted in SQLite, validated on every proxied request.
- get_claude_desktop_status surfaces drift signals (stale models,
  missing routes, proxy stopped, base URL mismatch, missing token).

Frontend:
- Slim ClaudeDesktopProviderForm independent from ProviderForm,
  controlled by a top-level appId guard.
- ProviderList banner consumes the status query (5s polling) and
  renders actionable diagnostics.
- ClaudeDesktopRouteToggle in the header to start/stop the local
  gateway without touching takeover state.
- Three-locale i18n synchronised.
2026-05-08 22:34:46 +08:00

58 lines
2.1 KiB
Rust

use std::path::PathBuf;
use crate::app_config::AppType;
use crate::codex_config::get_codex_auth_path;
use crate::config::get_claude_settings_path;
use crate::error::AppError;
use crate::gemini_config::get_gemini_dir;
use crate::openclaw_config::get_openclaw_dir;
use crate::opencode_config::get_opencode_dir;
/// 返回指定应用所使用的提示词文件路径。
pub fn prompt_file_path(app: &AppType) -> Result<PathBuf, AppError> {
if matches!(app, AppType::ClaudeDesktop) {
return Err(AppError::localized(
"claude_desktop.prompts_unsupported",
"Claude Desktop 暂不支持 Prompts",
"Claude Desktop does not support Prompts",
));
}
let base_dir: PathBuf = match app {
AppType::Claude => get_base_dir_with_fallback(get_claude_settings_path(), ".claude")?,
AppType::Codex => get_base_dir_with_fallback(get_codex_auth_path(), ".codex")?,
AppType::Gemini => get_gemini_dir(),
AppType::OpenCode => get_opencode_dir(),
AppType::OpenClaw => get_openclaw_dir(),
AppType::Hermes => crate::hermes_config::get_hermes_dir(),
AppType::ClaudeDesktop => unreachable!("handled above"),
};
let filename = match app {
AppType::Claude => "CLAUDE.md",
AppType::Codex => "AGENTS.md",
AppType::Gemini => "GEMINI.md",
AppType::OpenCode | AppType::OpenClaw | AppType::Hermes => "AGENTS.md",
AppType::ClaudeDesktop => unreachable!("handled above"),
};
Ok(base_dir.join(filename))
}
fn get_base_dir_with_fallback(
primary_path: PathBuf,
fallback_dir: &str,
) -> Result<PathBuf, AppError> {
primary_path
.parent()
.map(|p| p.to_path_buf())
.or_else(|| dirs::home_dir().map(|h| h.join(fallback_dir)))
.ok_or_else(|| {
AppError::localized(
"home_dir_not_found",
format!("无法确定 {fallback_dir} 配置目录:用户主目录不存在"),
format!("Cannot determine {fallback_dir} config directory: user home not found"),
)
})
}