//! 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 //! 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, Default, 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, /// Resource name #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, /// Whether to enable after import (default: false) #[serde(skip_serializing_if = "Option::is_none")] pub enabled: Option, // ============ Provider-specific fields ============ /// Provider homepage URL #[serde(skip_serializing_if = "Option::is_none")] pub homepage: Option, /// API endpoint/base URL (supports comma-separated multiple URLs) #[serde(skip_serializing_if = "Option::is_none")] pub endpoint: Option, /// API key #[serde(skip_serializing_if = "Option::is_none")] pub api_key: Option, /// Optional provider icon name (maps to built-in SVG) #[serde(skip_serializing_if = "Option::is_none")] pub icon: Option, /// Optional model name #[serde(skip_serializing_if = "Option::is_none")] pub model: Option, /// Optional notes/description #[serde(skip_serializing_if = "Option::is_none")] pub notes: Option, /// Optional Haiku model (Claude only, v3.7.1+) #[serde(skip_serializing_if = "Option::is_none")] pub haiku_model: Option, /// Optional Sonnet model (Claude only, v3.7.1+) #[serde(skip_serializing_if = "Option::is_none")] pub sonnet_model: Option, /// Optional Opus model (Claude only, v3.7.1+) #[serde(skip_serializing_if = "Option::is_none")] pub opus_model: Option, // ============ Prompt-specific fields ============ /// Base64 encoded Markdown content #[serde(skip_serializing_if = "Option::is_none")] pub content: Option, /// Prompt description #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, // ============ MCP-specific fields ============ /// Target applications for MCP (comma-separated: "claude,codex,gemini") #[serde(skip_serializing_if = "Option::is_none")] pub apps: Option, // ============ Skill-specific fields ============ /// GitHub repository (format: "owner/name") #[serde(skip_serializing_if = "Option::is_none")] pub repo: Option, /// Skill directory name #[serde(skip_serializing_if = "Option::is_none")] pub directory: Option, #[serde(skip_serializing_if = "Option::is_none")] pub branch: Option, // ============ Config file fields (v3.8+) ============ /// Base64 encoded config content #[serde(skip_serializing_if = "Option::is_none")] pub config: Option, /// Config format (json/toml) #[serde(skip_serializing_if = "Option::is_none")] pub config_format: Option, /// Remote config URL #[serde(skip_serializing_if = "Option::is_none")] pub config_url: Option, // ============ Usage script fields (v3.9+) ============ /// Whether to enable usage query (default: true if usage_script is provided) #[serde(skip_serializing_if = "Option::is_none")] pub usage_enabled: Option, /// Base64 encoded usage query script code #[serde(skip_serializing_if = "Option::is_none")] pub usage_script: Option, /// Usage query API key (if different from provider API key) #[serde(skip_serializing_if = "Option::is_none")] pub usage_api_key: Option, /// Usage query base URL (if different from provider endpoint) #[serde(skip_serializing_if = "Option::is_none")] pub usage_base_url: Option, /// Usage query access token (for NewAPI template) #[serde(skip_serializing_if = "Option::is_none")] pub usage_access_token: Option, /// Usage query user ID (for NewAPI template) #[serde(skip_serializing_if = "Option::is_none")] pub usage_user_id: Option, /// Auto query interval in minutes (0 to disable) #[serde(skip_serializing_if = "Option::is_none")] pub usage_auto_interval: Option, }