* Move a skill to a different mode * @param name - Skill name to move * @param source - Where the skill is located ("global" or "project") * @param currentMode - Current mode (undefined for generic skills) * @param newMode - Target mode (undefined for generic skills)
( name: string, source: "global" | "project", currentMode: string | undefined, newMode: string | undefined, )
| 455 | * @param newMode - Target mode (undefined for generic skills) |
| 456 | */ |
| 457 | async moveSkill( |
| 458 | name: string, |
| 459 | source: "global" | "project", |
| 460 | currentMode: string | undefined, |
| 461 | newMode: string | undefined, |
| 462 | ): Promise<void> { |
| 463 | // Don't move if source and destination are the same |
| 464 | if (currentMode === newMode) { |
| 465 | return |
| 466 | } |
| 467 | |
| 468 | // Find the skill at its current location |
| 469 | const skill = this.getSkill(name, source, currentMode) |
| 470 | if (!skill) { |
| 471 | const modeInfo = currentMode ? ` (mode: ${currentMode})` : "" |
| 472 | throw new Error(t("skills:errors.not_found", { name, source, modeInfo })) |
| 473 | } |
| 474 | |
| 475 | // Determine base directory |
| 476 | let baseDir: string |
| 477 | if (source === "global") { |
| 478 | baseDir = getGlobalRooDirectory() |
| 479 | } else { |
| 480 | const provider = this.providerRef.deref() |
| 481 | if (!provider?.cwd) { |
| 482 | throw new Error(t("skills:errors.no_workspace")) |
| 483 | } |
| 484 | baseDir = path.join(provider.cwd, ".roo") |
| 485 | } |
| 486 | |
| 487 | // Determine source and destination directories |
| 488 | const sourceDirName = currentMode ? `skills-${currentMode}` : "skills" |
| 489 | const destDirName = newMode ? `skills-${newMode}` : "skills" |
| 490 | const sourceDir = path.join(baseDir, sourceDirName, name) |
| 491 | const destSkillsDir = path.join(baseDir, destDirName) |
| 492 | const destDir = path.join(destSkillsDir, name) |
| 493 | const destSkillMdPath = path.join(destDir, "SKILL.md") |
| 494 | |
| 495 | // Check if skill already exists at destination |
| 496 | if (await fileExists(destSkillMdPath)) { |
| 497 | throw new Error(t("skills:errors.already_exists", { name, path: destSkillMdPath })) |
| 498 | } |
| 499 | |
| 500 | // Ensure destination skills directory exists |
| 501 | await fs.mkdir(destSkillsDir, { recursive: true }) |
| 502 | |
| 503 | // Move the skill directory |
| 504 | await fs.rename(sourceDir, destDir) |
| 505 | |
| 506 | // Clean up empty source skills directory |
| 507 | const sourceSkillsDir = path.join(baseDir, sourceDirName) |
| 508 | try { |
| 509 | const entries = await fs.readdir(sourceSkillsDir) |
| 510 | if (entries.length === 0) { |
| 511 | await fs.rmdir(sourceSkillsDir) |
| 512 | } |
| 513 | } catch { |
| 514 | // Ignore errors - directory might not exist or have permission issues |
no test coverage detected