(root: &Path)
| 154 | } |
| 155 | |
| 156 | fn scan_skill_root(root: &Path) -> Vec<SkillInfo> { |
| 157 | if !root.exists() || !root.is_dir() { |
| 158 | return Vec::new(); |
| 159 | } |
| 160 | |
| 161 | let mut skill_files: Vec<PathBuf> = WalkDir::new(root) |
| 162 | .follow_links(true) |
| 163 | .into_iter() |
| 164 | .filter_map(Result::ok) |
| 165 | .filter(|entry| entry.file_type().is_file()) |
| 166 | .map(|entry| entry.path().to_path_buf()) |
| 167 | .filter(|path| { |
| 168 | path.file_name() |
| 169 | .and_then(|name| name.to_str()) |
| 170 | .map(|name| name == "SKILL.md") |
| 171 | .unwrap_or(false) |
| 172 | }) |
| 173 | .collect(); |
| 174 | skill_files.sort(); |
| 175 | |
| 176 | skill_files |
| 177 | .into_iter() |
| 178 | .filter_map(|path| parse_skill_file(&path)) |
| 179 | .collect() |
| 180 | } |
| 181 | |
| 182 | fn discover_skills(base: &Path) -> Vec<SkillInfo> { |
| 183 | let mut by_name: HashMap<String, SkillInfo> = HashMap::new(); |
no test coverage detected