From 0aeaa5b2eabc535aef016c44f03ebbf49ffca725 Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Sat, 22 Nov 2025 16:38:08 -0600 Subject: [PATCH] fix: compile agents now checks multiple source locations ## Problem Compile Agents ignored custom agents in source locations like: - {project-root}/custom/src/agents/ - {bmad-folder}/custom/src/agents/ ## Solution Update reinstallCustomAgents to check all locations: 1. _cfg/custom/agents/ (backup location) 2. {bmad-folder}/custom/src/agents/ (source in BMAD folder) 3. {project-root}/custom/src/agents/ (source at project root) ## Changes - Search multiple locations for agents during compile - Avoid duplicate processing with Set tracking - Auto-backup source YAML to _cfg/custom/agents/ if needed - Works with any custom bmad_folder name from config Now 'Compile Agents' works with agents in any source location! --- tools/cli/installers/lib/core/installer.js | 65 +++++++++++++++------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 2bea3cd1..186ab2a7 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -2265,45 +2265,58 @@ class Installer { } /** - * Reinstall custom agents from _cfg/custom/agents/ sources + * Reinstall custom agents from backup and source locations * This preserves custom agents across quick updates/reinstalls * @param {string} projectDir - Project directory * @param {string} bmadDir - BMAD installation directory * @returns {Object} Result with count and agent names */ async reinstallCustomAgents(projectDir, bmadDir) { - const customAgentsCfgDir = path.join(bmadDir, '_cfg', 'custom', 'agents'); + const { + discoverAgents, + loadAgentConfig, + extractManifestData, + addToManifest, + createIdeSlashCommands, + updateManifestYaml, + } = require('../../../lib/agent/installer'); + const { compileAgent } = require('../../../lib/agent/compiler'); + const results = { count: 0, agents: [] }; - if (!(await fs.pathExists(customAgentsCfgDir))) { + // Check multiple locations for custom agents + const sourceLocations = [ + path.join(bmadDir, '_cfg', 'custom', 'agents'), // Backup location + path.join(bmadDir, 'custom', 'src', 'agents'), // BMAD folder source location + path.join(projectDir, 'custom', 'src', 'agents'), // Project root source location + ]; + + let foundAgents = []; + let processedAgents = new Set(); // Track to avoid duplicates + + // Discover agents from all locations + for (const location of sourceLocations) { + if (await fs.pathExists(location)) { + const agents = discoverAgents(location); + // Only add agents we haven't processed yet + const newAgents = agents.filter((agent) => !processedAgents.has(agent.name)); + foundAgents.push(...newAgents); + for (const agent of newAgents) processedAgents.add(agent.name); + } + } + + if (foundAgents.length === 0) { return results; } try { - const { - discoverAgents, - loadAgentConfig, - extractManifestData, - addToManifest, - createIdeSlashCommands, - updateManifestYaml, - } = require('../../../lib/agent/installer'); - const { compileAgent } = require('../../../lib/agent/compiler'); - - // Discover custom agents in _cfg/custom/agents/ - const agents = discoverAgents(customAgentsCfgDir); - - if (agents.length === 0) { - return results; - } - const customAgentsDir = path.join(bmadDir, 'custom', 'agents'); await fs.ensureDir(customAgentsDir); const manifestFile = path.join(bmadDir, '_cfg', 'agent-manifest.csv'); const manifestYamlFile = path.join(bmadDir, '_cfg', 'manifest.yaml'); - for (const agent of agents) { + for (const agent of foundAgents) { try { const agentConfig = loadAgentConfig(agent.yamlFile); const finalAgentName = agent.name; // Already named correctly from save @@ -2338,6 +2351,16 @@ class Installer { // Write compiled agent await fs.writeFile(compiledPath, xml, 'utf8'); + // Backup source YAML to _cfg/custom/agents if not already there + const cfgAgentsBackupDir = path.join(bmadDir, '_cfg', 'custom', 'agents'); + await fs.ensureDir(cfgAgentsBackupDir); + const backupYamlPath = path.join(cfgAgentsBackupDir, `${finalAgentName}.agent.yaml`); + + // Only backup if source is not already in backup location + if (agent.yamlFile !== backupYamlPath) { + await fs.copy(agent.yamlFile, backupYamlPath); + } + // Copy sidecar files if expert agent if (agent.hasSidecar && agent.type === 'expert') { const { copySidecarFiles } = require('../../../lib/agent/installer');