* Discovers skills from a skills directory. * Looks for / /SKILL.md files.
( skillsDir: string, verbose: boolean, )
| 108 | * Looks for <skillsDir>/<skill-name>/SKILL.md files. |
| 109 | */ |
| 110 | function discoverSkillsFromDirectory( |
| 111 | skillsDir: string, |
| 112 | verbose: boolean, |
| 113 | ): SkillsMap { |
| 114 | const skills: SkillsMap = {} |
| 115 | |
| 116 | let entries: string[] |
| 117 | try { |
| 118 | entries = fs.readdirSync(skillsDir) |
| 119 | } catch { |
| 120 | return skills |
| 121 | } |
| 122 | |
| 123 | for (const entry of entries) { |
| 124 | const skillDir = path.join(skillsDir, entry) |
| 125 | |
| 126 | // Skip non-directories and invalid skill names |
| 127 | try { |
| 128 | const stat = fs.statSync(skillDir) |
| 129 | if (!stat.isDirectory()) continue |
| 130 | } catch { |
| 131 | continue |
| 132 | } |
| 133 | |
| 134 | if (!isValidSkillName(entry)) { |
| 135 | if (verbose) { |
| 136 | console.warn(`Skipping invalid skill directory name: ${entry}`) |
| 137 | } |
| 138 | continue |
| 139 | } |
| 140 | |
| 141 | const skillFilePath = path.join(skillDir, SKILL_FILE_NAME) |
| 142 | |
| 143 | // Check if SKILL.md exists |
| 144 | try { |
| 145 | fs.statSync(skillFilePath) |
| 146 | } catch { |
| 147 | continue |
| 148 | } |
| 149 | |
| 150 | const skill = loadSkillFromFile(skillDir, skillFilePath, verbose) |
| 151 | if (skill) { |
| 152 | skills[skill.name] = skill |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | return skills |
| 157 | } |
| 158 | |
| 159 | /** |
| 160 | * Gets the default skills directories to search. |
no test coverage detected