fix: ManifestGenerator now recursively scans for agents

- Updated getAgentsFromDir to search subdirectories for .md files
- Fixed installPath construction to include nested directory structure
- This ensures agents in subdirectories (like cbt-coach/cbt-coach.md) get added to agent-manifest.csv
- All agents now get proper CLI slash commands regardless of nesting depth
This commit is contained in:
Brian Madison 2025-12-06 16:31:32 -06:00
parent aad7a71718
commit 86e2daabba

View File

@ -220,18 +220,23 @@ class ManifestGenerator {
} }
/** /**
* Get agents from a directory * Get agents from a directory recursively
* Only includes compiled .md files (not .agent.yaml source files) * Only includes compiled .md files (not .agent.yaml source files)
*/ */
async getAgentsFromDir(dirPath, moduleName) { async getAgentsFromDir(dirPath, moduleName, relativePath = '') {
const agents = []; const agents = [];
const files = await fs.readdir(dirPath); const entries = await fs.readdir(dirPath, { withFileTypes: true });
for (const file of files) { for (const entry of entries) {
// Only include .md files, skip .agent.yaml source files and README.md const fullPath = path.join(dirPath, entry.name);
if (file.endsWith('.md') && !file.endsWith('.agent.yaml') && file.toLowerCase() !== 'readme.md') {
const filePath = path.join(dirPath, file); if (entry.isDirectory()) {
const content = await fs.readFile(filePath, 'utf8'); // Recurse into subdirectories
const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
const subDirAgents = await this.getAgentsFromDir(fullPath, moduleName, newRelativePath);
agents.push(...subDirAgents);
} else if (entry.name.endsWith('.md') && !entry.name.endsWith('.agent.yaml') && entry.name.toLowerCase() !== 'readme.md') {
const content = await fs.readFile(fullPath, 'utf8');
// Skip files that don't contain <agent> tag (e.g., README files) // Skip files that don't contain <agent> tag (e.g., README files)
if (!content.includes('<agent')) { if (!content.includes('<agent')) {
@ -255,8 +260,11 @@ class ManifestGenerator {
const principlesMatch = content.match(/<principles>([\s\S]*?)<\/principles>/); const principlesMatch = content.match(/<principles>([\s\S]*?)<\/principles>/);
// Build relative path for installation // Build relative path for installation
const fileRelativePath = relativePath ? `${relativePath}/${file}` : file;
const installPath = const installPath =
moduleName === 'core' ? `${this.bmadFolderName}/core/agents/${file}` : `${this.bmadFolderName}/${moduleName}/agents/${file}`; moduleName === 'core'
? `${this.bmadFolderName}/core/agents/${fileRelativePath}`
: `${this.bmadFolderName}/${moduleName}/agents/${fileRelativePath}`;
const agentName = file.replace('.md', ''); const agentName = file.replace('.md', '');