| 176 | } |
| 177 | |
| 178 | async function syncSubmodules() { |
| 179 | const spinner = p.spinner() |
| 180 | |
| 181 | // Update all submodules |
| 182 | spinner.start('Updating submodules...') |
| 183 | try { |
| 184 | exec('git submodule update --remote --merge') |
| 185 | spinner.stop('Submodules updated') |
| 186 | } |
| 187 | catch (e) { |
| 188 | spinner.stop(`Failed to update submodules: ${e}`) |
| 189 | return |
| 190 | } |
| 191 | |
| 192 | // Sync Type 2 skills |
| 193 | for (const [vendorName, config] of Object.entries(vendors)) { |
| 194 | const vendorConfig = config as VendorConfig |
| 195 | const vendorPath = join(root, 'vendor', vendorName) |
| 196 | const skillsBasePath = vendorConfig.skillsPath || 'skills' |
| 197 | const vendorSkillsPath = join(vendorPath, skillsBasePath) |
| 198 | |
| 199 | if (!existsSync(vendorPath)) { |
| 200 | p.log.warn(`Vendor submodule not found: ${vendorName}. Run init first.`) |
| 201 | continue |
| 202 | } |
| 203 | |
| 204 | if (!existsSync(vendorSkillsPath)) { |
| 205 | p.log.warn(`No skills directory in vendor/${vendorName}/${skillsBasePath}/`) |
| 206 | continue |
| 207 | } |
| 208 | |
| 209 | // Sync each specified skill |
| 210 | for (const [sourceSkillName, outputSkillName] of Object.entries(vendorConfig.skills)) { |
| 211 | const sourceSkillPath = join(vendorSkillsPath, sourceSkillName) |
| 212 | const outputPath = join(root, 'skills', outputSkillName) |
| 213 | |
| 214 | if (!existsSync(sourceSkillPath)) { |
| 215 | p.log.warn(`Skill not found: vendor/${vendorName}/skills/${sourceSkillName}`) |
| 216 | continue |
| 217 | } |
| 218 | |
| 219 | spinner.start(`Syncing skill: ${sourceSkillName} → ${outputSkillName}`) |
| 220 | |
| 221 | // Remove existing output directory to ensure clean sync |
| 222 | if (existsSync(outputPath)) { |
| 223 | rmSync(outputPath, { recursive: true }) |
| 224 | } |
| 225 | mkdirSync(outputPath, { recursive: true }) |
| 226 | |
| 227 | // Copy all files from source skill to output |
| 228 | const files = readdirSync(sourceSkillPath, { recursive: true, withFileTypes: true }) |
| 229 | for (const file of files) { |
| 230 | if (file.isFile()) { |
| 231 | const fullPath = join(file.parentPath, file.name) |
| 232 | const relativePath = fullPath.replace(sourceSkillPath, '') |
| 233 | const destPath = join(outputPath, relativePath) |
| 234 | |
| 235 | // Ensure destination directory exists |