diff --git a/src-tauri/src/commands/skill.rs b/src-tauri/src/commands/skill.rs index 64ea9506..b81c5096 100644 --- a/src-tauri/src/commands/skill.rs +++ b/src-tauri/src/commands/skill.rs @@ -90,7 +90,6 @@ pub async fn install_skill( .clone() .unwrap_or_else(|| "main".to_string()), enabled: true, - skills_path: skill.skills_path.clone(), // 使用技能记录的 skills_path }; service diff --git a/src-tauri/src/database/dao/skills.rs b/src-tauri/src/database/dao/skills.rs index 59c90d72..5fc02ee0 100644 --- a/src-tauri/src/database/dao/skills.rs +++ b/src-tauri/src/database/dao/skills.rs @@ -58,7 +58,9 @@ impl Database { pub fn get_skill_repos(&self) -> Result, AppError> { let conn = lock_conn!(self.conn); let mut stmt = conn - .prepare("SELECT owner, name, branch, enabled, skills_path FROM skill_repos ORDER BY owner ASC, name ASC") + .prepare( + "SELECT owner, name, branch, enabled FROM skill_repos ORDER BY owner ASC, name ASC", + ) .map_err(|e| AppError::Database(e.to_string()))?; let repo_iter = stmt @@ -68,7 +70,6 @@ impl Database { name: row.get(1)?, branch: row.get(2)?, enabled: row.get(3)?, - skills_path: row.get(4)?, }) }) .map_err(|e| AppError::Database(e.to_string()))?; @@ -84,8 +85,8 @@ impl Database { pub fn save_skill_repo(&self, repo: &SkillRepo) -> Result<(), AppError> { let conn = lock_conn!(self.conn); conn.execute( - "INSERT OR REPLACE INTO skill_repos (owner, name, branch, enabled, skills_path) VALUES (?1, ?2, ?3, ?4, ?5)", - params![repo.owner, repo.name, repo.branch, repo.enabled, repo.skills_path], + "INSERT OR REPLACE INTO skill_repos (owner, name, branch, enabled) VALUES (?1, ?2, ?3, ?4)", + params![repo.owner, repo.name, repo.branch, repo.enabled], ).map_err(|e| AppError::Database(e.to_string()))?; Ok(()) } diff --git a/src-tauri/src/database/migration.rs b/src-tauri/src/database/migration.rs index c96eb4e2..44c9dc14 100644 --- a/src-tauri/src/database/migration.rs +++ b/src-tauri/src/database/migration.rs @@ -202,8 +202,8 @@ impl Database { for repo in &config.skills.repos { tx.execute( - "INSERT OR REPLACE INTO skill_repos (owner, name, branch, enabled, skills_path) VALUES (?1, ?2, ?3, ?4, ?5)", - params![repo.owner, repo.name, repo.branch, repo.enabled, repo.skills_path], + "INSERT OR REPLACE INTO skill_repos (owner, name, branch, enabled) VALUES (?1, ?2, ?3, ?4)", + params![repo.owner, repo.name, repo.branch, repo.enabled], ).map_err(|e| AppError::Database(format!("Migrate skill repo failed: {e}")))?; } diff --git a/src-tauri/src/database/schema.rs b/src-tauri/src/database/schema.rs index fd75818b..58005148 100644 --- a/src-tauri/src/database/schema.rs +++ b/src-tauri/src/database/schema.rs @@ -104,7 +104,6 @@ impl Database { name TEXT NOT NULL, branch TEXT NOT NULL DEFAULT 'main', enabled BOOLEAN NOT NULL DEFAULT 1, - skills_path TEXT, PRIMARY KEY (owner, name) )", [], @@ -233,7 +232,7 @@ impl Database { "TEXT NOT NULL DEFAULT 'main'", )?; Self::add_column_if_missing(conn, "skill_repos", "enabled", "BOOLEAN NOT NULL DEFAULT 1")?; - Self::add_column_if_missing(conn, "skill_repos", "skills_path", "TEXT")?; + // 注意: skills_path 字段已被移除,因为现在支持全仓库递归扫描 Ok(()) } diff --git a/src-tauri/src/deeplink/mod.rs b/src-tauri/src/deeplink/mod.rs index feb6fc58..5c1e1a72 100644 --- a/src-tauri/src/deeplink/mod.rs +++ b/src-tauri/src/deeplink/mod.rs @@ -100,12 +100,8 @@ pub struct DeepLinkImportRequest { /// Skill directory name #[serde(skip_serializing_if = "Option::is_none")] pub directory: Option, - /// Repository branch (default: "main") #[serde(skip_serializing_if = "Option::is_none")] pub branch: Option, - /// Skills subdirectory path (e.g., "skills") - #[serde(skip_serializing_if = "Option::is_none")] - pub skills_path: Option, // ============ Config file fields (v3.8+) ============ /// Base64 encoded config content diff --git a/src-tauri/src/deeplink/parser.rs b/src-tauri/src/deeplink/parser.rs index fb0bedf5..316af003 100644 --- a/src-tauri/src/deeplink/parser.rs +++ b/src-tauri/src/deeplink/parser.rs @@ -143,7 +143,6 @@ fn parse_provider_deeplink( repo: None, directory: None, branch: None, - skills_path: None, config, config_format, config_url, @@ -204,7 +203,6 @@ fn parse_prompt_deeplink( repo: None, directory: None, branch: None, - skills_path: None, config: None, config_format: None, config_url: None, @@ -262,7 +260,6 @@ fn parse_mcp_deeplink( repo: None, directory: None, branch: None, - skills_path: None, config_url: None, }) } @@ -287,10 +284,6 @@ fn parse_skill_deeplink( let directory = params.get("directory").cloned(); let branch = params.get("branch").cloned(); - let skills_path = params - .get("skills_path") - .or_else(|| params.get("skillsPath")) - .cloned(); Ok(DeepLinkImportRequest { version, @@ -298,7 +291,6 @@ fn parse_skill_deeplink( repo: Some(repo), directory, branch, - skills_path, icon: None, app: Some("claude".to_string()), // Skills are Claude-only name: None, diff --git a/src-tauri/src/deeplink/skill.rs b/src-tauri/src/deeplink/skill.rs index 8dc3c8de..d4369eaf 100644 --- a/src-tauri/src/deeplink/skill.rs +++ b/src-tauri/src/deeplink/skill.rs @@ -40,7 +40,6 @@ pub fn import_skill_from_deeplink( name: name.clone(), branch: request.branch.unwrap_or_else(|| "main".to_string()), enabled: request.enabled.unwrap_or(true), - skills_path: request.skills_path, }; // Save using Database diff --git a/src-tauri/src/deeplink/tests.rs b/src-tauri/src/deeplink/tests.rs index 40568154..b20fa55c 100644 --- a/src-tauri/src/deeplink/tests.rs +++ b/src-tauri/src/deeplink/tests.rs @@ -142,7 +142,6 @@ fn test_build_gemini_provider_with_model() { repo: None, directory: None, branch: None, - skills_path: None, content: None, description: None, enabled: None, @@ -189,7 +188,6 @@ fn test_build_gemini_provider_without_model() { repo: None, directory: None, branch: None, - skills_path: None, content: None, description: None, enabled: None, @@ -231,7 +229,6 @@ fn test_parse_and_merge_config_claude() { repo: None, directory: None, branch: None, - skills_path: None, content: None, description: None, enabled: None, @@ -275,7 +272,6 @@ fn test_parse_and_merge_config_url_override() { repo: None, directory: None, branch: None, - skills_path: None, content: None, description: None, enabled: None, @@ -372,12 +368,11 @@ fn test_parse_mcp_deeplink() { #[test] fn test_parse_skill_deeplink() { - let url = "ccswitch://v1/import?resource=skill&repo=owner/repo&directory=skills&branch=dev&skills_path=src"; + let url = "ccswitch://v1/import?resource=skill&repo=owner/repo&directory=skills&branch=dev"; let request = parse_deeplink_url(&url).unwrap(); assert_eq!(request.resource, "skill"); assert_eq!(request.repo.unwrap(), "owner/repo"); assert_eq!(request.directory.unwrap(), "skills"); assert_eq!(request.branch.unwrap(), "dev"); - assert_eq!(request.skills_path.unwrap(), "src"); } diff --git a/src-tauri/src/services/skill.rs b/src-tauri/src/services/skill.rs index 23a3e4d2..3130affd 100644 --- a/src-tauri/src/services/skill.rs +++ b/src-tauri/src/services/skill.rs @@ -34,9 +34,6 @@ pub struct Skill { /// 分支名称 #[serde(rename = "repoBranch")] pub repo_branch: Option, - /// 技能所在的子目录路径 (可选, 如 "skills") - #[serde(rename = "skillsPath")] - pub skills_path: Option, } /// 仓库配置 @@ -50,9 +47,6 @@ pub struct SkillRepo { pub branch: String, /// 是否启用 pub enabled: bool, - /// 技能所在的子目录路径 (可选, 如 "skills", "my-skills/subdir") - #[serde(rename = "skillsPath")] - pub skills_path: Option, } /// 技能安装状态 @@ -84,21 +78,18 @@ impl Default for SkillStore { name: "awesome-claude-skills".to_string(), branch: "main".to_string(), enabled: true, - skills_path: None, // 扫描根目录 }, SkillRepo { owner: "anthropics".to_string(), name: "skills".to_string(), branch: "main".to_string(), enabled: true, - skills_path: None, // 扫描根目录 }, SkillRepo { owner: "cexll".to_string(), name: "myclaude".to_string(), branch: "master".to_string(), enabled: true, - skills_path: Some("skills".to_string()), // 扫描 skills 子目录 }, ], } @@ -194,25 +185,8 @@ impl SkillService { })??; let mut skills = Vec::new(); - // 确定要扫描的目录路径 - let scan_dir = if let Some(ref skills_path) = repo.skills_path { - // 如果指定了 skillsPath,则扫描该子目录 - let subdir = temp_dir.join(skills_path.trim_matches('/')); - if !subdir.exists() { - log::warn!( - "仓库 {}/{} 中指定的技能路径 '{}' 不存在", - repo.owner, - repo.name, - skills_path - ); - let _ = fs::remove_dir_all(&temp_dir); - return Ok(skills); - } - subdir - } else { - // 否则扫描仓库根目录 - temp_dir.clone() - }; + // 扫描仓库根目录(支持全仓库递归扫描) + let scan_dir = temp_dir.clone(); // 递归扫描目录查找所有技能 self.scan_dir_recursive(&scan_dir, &scan_dir, repo, &mut skills)?; @@ -284,11 +258,7 @@ impl SkillService { let meta = self.parse_skill_metadata(skill_md)?; // 构建 README URL - let readme_path = if let Some(ref skills_path) = repo.skills_path { - format!("{}/{}", skills_path.trim_matches('/'), directory) - } else { - directory.to_string() - }; + let readme_path = directory.to_string(); Ok(Skill { key: format!("{}/{}:{}", repo.owner, repo.name, directory), @@ -303,7 +273,6 @@ impl SkillService { repo_owner: Some(repo.owner.clone()), repo_name: Some(repo.name.clone()), repo_branch: Some(repo.branch.clone()), - skills_path: repo.skills_path.clone(), }) } @@ -405,7 +374,6 @@ impl SkillService { repo_owner: None, repo_name: None, repo_branch: None, - skills_path: None, }); } @@ -574,16 +542,8 @@ impl SkillService { )) })??; - // 根据 skills_path 确定源目录路径 - let source = if let Some(ref skills_path) = repo.skills_path { - // 如果指定了 skills_path,源路径为: temp_dir/skills_path/directory - temp_dir - .join(skills_path.trim_matches('/')) - .join(&directory) - } else { - // 否则源路径为: temp_dir/directory - temp_dir.join(&directory) - }; + // 确定源目录路径(技能相对于仓库根目录的路径) + let source = temp_dir.join(&directory); if !source.exists() { let _ = fs::remove_dir_all(&temp_dir); diff --git a/src/components/deeplink/SkillConfirmation.tsx b/src/components/deeplink/SkillConfirmation.tsx index 265379c8..40b2fa8a 100644 --- a/src/components/deeplink/SkillConfirmation.tsx +++ b/src/components/deeplink/SkillConfirmation.tsx @@ -30,22 +30,11 @@ export function SkillConfirmation({ -
-
- -
{request.branch || "main"}
-
- - {request.skillsPath && ( -
- -
{request.skillsPath}
-
- )} +
+ +
{request.branch || "main"}
diff --git a/src/components/skills/RepoManager.tsx b/src/components/skills/RepoManager.tsx index fdadf4eb..7a4839c4 100644 --- a/src/components/skills/RepoManager.tsx +++ b/src/components/skills/RepoManager.tsx @@ -34,7 +34,6 @@ export function RepoManager({ const { t } = useTranslation(); const [repoUrl, setRepoUrl] = useState(""); const [branch, setBranch] = useState(""); - const [skillsPath, setSkillsPath] = useState(""); const [error, setError] = useState(""); const getSkillCount = (repo: SkillRepo) => @@ -80,12 +79,10 @@ export function RepoManager({ name: parsed.name, branch: branch || "main", enabled: true, - skillsPath: skillsPath.trim() || undefined, // 仅在有值时传递 }); setRepoUrl(""); setBranch(""); - setSkillsPath(""); } catch (e) { setError(e instanceof Error ? e.message : t("skills.repo.addFailed")); } @@ -130,13 +127,6 @@ export function RepoManager({ onChange={(e) => setBranch(e.target.value)} className="flex-1" /> - setSkillsPath(e.target.value)} - className="flex-1" - />