"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.allAgents = void 0; exports.revertAllAgentConfigs = revertAllAgentConfigs; const path = __importStar(require("path")); const fs_1 = require("fs"); const FileSystemUtils = __importStar(require("./core/FileSystemUtils")); const ConfigLoader_1 = require("./core/ConfigLoader"); const agents_1 = require("./agents"); Object.defineProperty(exports, "allAgents", { enumerable: true, get: function () { return agents_1.allAgents; } }); const constants_1 = require("./constants"); const revert_engine_1 = require("./core/revert-engine"); const agent_selection_1 = require("./core/agent-selection"); const config_utils_1 = require("./core/config-utils"); const agents = agents_1.allAgents; /** * Reverts ruler configurations for selected AI agents. */ async function revertAllAgentConfigs(projectRoot, includedAgents, configPath, keepBackups = false, verbose = false, dryRun = false, localOnly = false) { (0, constants_1.logVerbose)(`Loading configuration for revert from project root: ${projectRoot}`, verbose); const config = await (0, ConfigLoader_1.loadConfig)({ projectRoot, cliAgents: includedAgents, configPath, }); const rulerDir = await FileSystemUtils.findRulerDir(projectRoot, !localOnly); if (!rulerDir) { throw (0, constants_1.createRulerError)(`.ruler directory not found`, `Searched from: ${projectRoot}`); } (0, constants_1.logVerbose)(`Found .ruler directory at: ${rulerDir}`, verbose); // Normalize per-agent config keys to agent identifiers config.agentConfigs = (0, config_utils_1.mapRawAgentConfigs)(config.agentConfigs, agents); // Select agents to revert (same logic as apply, but with backward compatibility for invalid agents) let selected; try { selected = (0, agent_selection_1.resolveSelectedAgents)(config, agents); } catch (error) { // For backward compatibility, revert continues with available agents if some are invalid // This preserves the original behavior where invalid agents were silently ignored if (error instanceof Error && error.message.includes('Invalid agent specified')) { (0, constants_1.logVerbose)(`Warning: ${error.message} - continuing with valid agents only`, verbose); // Fall back to the old logic without validation if (config.cliAgents && config.cliAgents.length > 0) { const filters = config.cliAgents.map((n) => n.toLowerCase()); selected = agents.filter((agent) => filters.some((f) => agent.getIdentifier() === f || agent.getName().toLowerCase().includes(f))); } else if (config.defaultAgents && config.defaultAgents.length > 0) { const defaults = config.defaultAgents.map((n) => n.toLowerCase()); selected = agents.filter((agent) => { const identifier = agent.getIdentifier(); const override = config.agentConfigs[identifier]?.enabled; if (override !== undefined) { return override; } return defaults.some((d) => identifier === d || agent.getName().toLowerCase().includes(d)); }); } else { selected = agents.filter((agent) => config.agentConfigs[agent.getIdentifier()]?.enabled !== false); } } else { throw error; } } (0, constants_1.logVerbose)(`Selected agents: ${selected.map((a) => a.getName()).join(', ')}`, verbose); // Revert configurations for each agent let totalFilesProcessed = 0; let totalFilesRestored = 0; let totalFilesRemoved = 0; let totalBackupsRemoved = 0; for (const agent of selected) { const prefix = (0, constants_1.actionPrefix)(dryRun); console.log(`${prefix} Reverting ${agent.getName()}...`); const agentConfig = config.agentConfigs[agent.getIdentifier()]; const result = await (0, revert_engine_1.revertAgentConfiguration)(agent, projectRoot, agentConfig, keepBackups, verbose, dryRun); totalFilesProcessed += result.restored + result.removed; totalFilesRestored += result.restored; totalFilesRemoved += result.removed; totalBackupsRemoved += result.backupsRemoved; } // Clean up auxiliary files and directories const cleanupResult = await (0, revert_engine_1.cleanUpAuxiliaryFiles)(projectRoot, verbose, dryRun); totalFilesRemoved += cleanupResult.additionalFilesRemoved; // Clean .gitignore if reverting all agents const gitignoreCleaned = !config.cliAgents || config.cliAgents.length === 0 ? await cleanGitignore(projectRoot, verbose, dryRun) : false; // Display summary const prefix = (0, constants_1.actionPrefix)(dryRun); if (dryRun) { console.log(`${prefix} Revert summary (dry run):`); } else { console.log(`${prefix} Revert completed successfully.`); } console.log(` Files processed: ${totalFilesProcessed}`); console.log(` Files restored from backup: ${totalFilesRestored}`); console.log(` Generated files removed: ${totalFilesRemoved}`); if (!keepBackups) { console.log(` Backup files removed: ${totalBackupsRemoved}`); } if (cleanupResult.directoriesRemoved > 0) { console.log(` Empty directories removed: ${cleanupResult.directoriesRemoved}`); } if (gitignoreCleaned) { console.log(` .gitignore cleaned: yes`); } } /** * Removes the ruler-managed block from .gitignore file. */ async function cleanGitignore(projectRoot, verbose, dryRun) { const gitignorePath = path.join(projectRoot, '.gitignore'); try { await fs_1.promises.access(gitignorePath); } catch { (0, constants_1.logVerbose)('No .gitignore file found', verbose); return false; } const content = await fs_1.promises.readFile(gitignorePath, 'utf8'); const startMarker = '# START Ruler Generated Files'; const endMarker = '# END Ruler Generated Files'; const startIndex = content.indexOf(startMarker); const endIndex = content.indexOf(endMarker); if (startIndex === -1 || endIndex === -1) { (0, constants_1.logVerbose)('No ruler-managed block found in .gitignore', verbose); return false; } const prefix = (0, constants_1.actionPrefix)(dryRun); if (dryRun) { (0, constants_1.logVerbose)(`${prefix} Would remove ruler block from .gitignore`, verbose); } else { const beforeBlock = content.substring(0, startIndex); const afterBlock = content.substring(endIndex + endMarker.length); let newContent = beforeBlock + afterBlock; newContent = newContent.replace(/\n{3,}/g, '\n\n'); // Replace 3+ newlines with 2 if (newContent.trim() === '') { await fs_1.promises.unlink(gitignorePath); (0, constants_1.logVerbose)(`${prefix} Removed empty .gitignore file`, verbose); } else { await fs_1.promises.writeFile(gitignorePath, newContent); (0, constants_1.logVerbose)(`${prefix} Removed ruler block from .gitignore`, verbose); } } return true; }