mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
0f959112b1
Remove the skillsPath field from SkillRepo and Skill structs since recursive scanning now automatically discovers skills in all directories. Simplify the UI by removing the path input field.
117 lines
4.1 KiB
Rust
117 lines
4.1 KiB
Rust
//! Deep link import functionality for CC Switch
|
|
//!
|
|
//! This module implements the ccswitch:// protocol for importing configurations
|
|
//! via deep links. Supports importing:
|
|
//! - Provider configurations (Claude/Codex/Gemini)
|
|
//! - MCP server configurations
|
|
//! - Prompts
|
|
//! - Skills
|
|
//!
|
|
//! See docs/ccswitch-deeplink-design.md for detailed design.
|
|
|
|
mod mcp;
|
|
mod parser;
|
|
mod prompt;
|
|
mod provider;
|
|
mod skill;
|
|
mod utils;
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
// Re-export public API
|
|
pub use mcp::import_mcp_from_deeplink;
|
|
pub use parser::parse_deeplink_url;
|
|
pub use prompt::import_prompt_from_deeplink;
|
|
pub use provider::{import_provider_from_deeplink, parse_and_merge_config};
|
|
pub use skill::import_skill_from_deeplink;
|
|
|
|
/// Deep link import request model
|
|
///
|
|
/// Represents a parsed ccswitch:// URL ready for processing.
|
|
/// This struct contains all possible fields for all resource types.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct DeepLinkImportRequest {
|
|
/// Protocol version (e.g., "v1")
|
|
pub version: String,
|
|
/// Resource type to import: "provider" | "prompt" | "mcp" | "skill"
|
|
pub resource: String,
|
|
|
|
// ============ Common fields ============
|
|
/// Target application (claude/codex/gemini) - for provider, prompt, skill
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub app: Option<String>,
|
|
/// Resource name
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub name: Option<String>,
|
|
/// Whether to enable after import (default: false)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub enabled: Option<bool>,
|
|
|
|
// ============ Provider-specific fields ============
|
|
/// Provider homepage URL
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub homepage: Option<String>,
|
|
/// API endpoint/base URL
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub endpoint: Option<String>,
|
|
/// API key
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub api_key: Option<String>,
|
|
/// Optional provider icon name (maps to built-in SVG)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub icon: Option<String>,
|
|
/// Optional model name
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub model: Option<String>,
|
|
/// Optional notes/description
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub notes: Option<String>,
|
|
/// Optional Haiku model (Claude only, v3.7.1+)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub haiku_model: Option<String>,
|
|
/// Optional Sonnet model (Claude only, v3.7.1+)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub sonnet_model: Option<String>,
|
|
/// Optional Opus model (Claude only, v3.7.1+)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub opus_model: Option<String>,
|
|
|
|
// ============ Prompt-specific fields ============
|
|
/// Base64 encoded Markdown content
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub content: Option<String>,
|
|
/// Prompt description
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub description: Option<String>,
|
|
|
|
// ============ MCP-specific fields ============
|
|
/// Target applications for MCP (comma-separated: "claude,codex,gemini")
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub apps: Option<String>,
|
|
|
|
// ============ Skill-specific fields ============
|
|
/// GitHub repository (format: "owner/name")
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub repo: Option<String>,
|
|
/// Skill directory name
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub directory: Option<String>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub branch: Option<String>,
|
|
|
|
// ============ Config file fields (v3.8+) ============
|
|
/// Base64 encoded config content
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub config: Option<String>,
|
|
/// Config format (json/toml)
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub config_format: Option<String>,
|
|
/// Remote config URL
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub config_url: Option<String>,
|
|
}
|