From b4cc5790096cfac3b537e03d5cd2daa340d6c38c Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Thu, 9 Oct 2025 23:07:12 -0500 Subject: [PATCH] create-agent now adds agent to ide agents list also --- .github/ISSUE_TEMPLATE/config.yaml | 4 +++ .github/ISSUE_TEMPLATE/idea_submission.md | 4 +-- tools/cli/installers/lib/core/installer.js | 24 ++++++++++++- .../installers/lib/core/manifest-generator.js | 14 ++++++++ tools/cli/installers/lib/ide/_base-ide.js | 35 +++++++++++++++++-- tools/cli/installers/lib/ide/claude-code.js | 2 +- .../lib/ide/shared/bmad-artifacts.js | 31 ++++++++++++++++ 7 files changed, 108 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml index 3ba13e0c..4c0f247e 100644 --- a/.github/ISSUE_TEMPLATE/config.yaml +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -1 +1,5 @@ blank_issues_enabled: false +contact_links: + - name: Discord Community Support + url: https://discord.gg/gk8jAdXWmj + about: Please join our Discord server for general questions and community discussion before opening an issue. diff --git a/.github/ISSUE_TEMPLATE/idea_submission.md b/.github/ISSUE_TEMPLATE/idea_submission.md index 62bd2b7a..a915cdc8 100644 --- a/.github/ISSUE_TEMPLATE/idea_submission.md +++ b/.github/ISSUE_TEMPLATE/idea_submission.md @@ -1,6 +1,6 @@ --- -name: V5 Idea Submission -about: Suggest an idea for v5 +name: V6 Idea Submission +about: Suggest an idea for v6 title: '' labels: '' assignees: '' diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 4df58c6d..6df7b66a 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -1282,6 +1282,28 @@ class Installer { } } + // Regenerate manifests after compilation + spinner.start('Regenerating manifests...'); + const installedModules = entries + .filter((e) => e.isDirectory() && e.name !== '_cfg' && e.name !== 'docs' && e.name !== 'agents' && e.name !== 'core') + .map((e) => e.name); + const manifestGen = new ManifestGenerator(); + + // Get existing IDE list from manifest + const existingManifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + let existingIdes = []; + if (await fs.pathExists(existingManifestPath)) { + const manifestContent = await fs.readFile(existingManifestPath, 'utf8'); + const yaml = require('js-yaml'); + const manifest = yaml.load(manifestContent); + existingIdes = manifest.ides || []; + } + + await manifestGen.generateManifests(bmadDir, installedModules, [], { + ides: existingIdes, + }); + spinner.succeed('Manifests regenerated'); + // Ask for IDE to update spinner.stop(); // Note: UI lives in tools/cli/lib/ui.js; from installers/lib/core use '../../../lib/ui' @@ -1295,7 +1317,7 @@ class Installer { for (const ide of toolConfig.ides) { spinner.text = `Updating ${ide}...`; await this.ideManager.setup(ide, projectDir, bmadDir, { - selectedModules: entries.filter((e) => e.isDirectory() && e.name !== '_cfg').map((e) => e.name), + selectedModules: installedModules, skipModuleInstall: true, // Skip module installation, just update IDE files verbose: config.verbose, }); diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index 1cf2b0f6..2e1c759a 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -179,6 +179,20 @@ class ManifestGenerator { this.agents.push(...moduleAgents); } } + + // Get standalone agents from bmad/agents/ directory + const standaloneAgentsDir = path.join(this.bmadDir, 'agents'); + if (await fs.pathExists(standaloneAgentsDir)) { + const agentDirs = await fs.readdir(standaloneAgentsDir, { withFileTypes: true }); + + for (const agentDir of agentDirs) { + if (!agentDir.isDirectory()) continue; + + const agentDirPath = path.join(standaloneAgentsDir, agentDir.name); + const standaloneAgents = await this.getAgentsFromDir(agentDirPath, 'standalone'); + this.agents.push(...standaloneAgents); + } + } } /** diff --git a/tools/cli/installers/lib/ide/_base-ide.js b/tools/cli/installers/lib/ide/_base-ide.js index 03ee39de..50dc43a4 100644 --- a/tools/cli/installers/lib/ide/_base-ide.js +++ b/tools/cli/installers/lib/ide/_base-ide.js @@ -105,7 +105,7 @@ class BaseIdeSetup { // Get module agents const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents'); if (await fs.pathExists(moduleAgentsPath)) { const moduleAgents = await this.scanDirectory(moduleAgentsPath, '.md'); @@ -119,6 +119,37 @@ class BaseIdeSetup { } } + // Get standalone agents from bmad/agents/ directory + const standaloneAgentsDir = path.join(bmadDir, 'agents'); + if (await fs.pathExists(standaloneAgentsDir)) { + const agentDirs = await fs.readdir(standaloneAgentsDir, { withFileTypes: true }); + + for (const agentDir of agentDirs) { + if (!agentDir.isDirectory()) continue; + + const agentDirPath = path.join(standaloneAgentsDir, agentDir.name); + const agentFiles = await fs.readdir(agentDirPath); + + for (const file of agentFiles) { + if (!file.endsWith('.md')) continue; + if (file.includes('.customize.')) continue; + + const filePath = path.join(agentDirPath, file); + const content = await fs.readFile(filePath, 'utf8'); + + if (content.includes('localskip="true"')) continue; + + agents.push({ + name: file.replace('.md', ''), + path: filePath, + relativePath: path.relative(standaloneAgentsDir, filePath), + filename: file, + module: 'standalone', // Mark as standalone agent + }); + } + } + } + return agents; } @@ -145,7 +176,7 @@ class BaseIdeSetup { // Get module tasks const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { const moduleTasksPath = path.join(bmadDir, entry.name, 'tasks'); if (await fs.pathExists(moduleTasksPath)) { const moduleTasks = await this.scanDirectory(moduleTasksPath, '.md'); diff --git a/tools/cli/installers/lib/ide/claude-code.js b/tools/cli/installers/lib/ide/claude-code.js index eb05d634..c9de87bc 100644 --- a/tools/cli/installers/lib/ide/claude-code.js +++ b/tools/cli/installers/lib/ide/claude-code.js @@ -104,7 +104,7 @@ class ClaudeCodeSetup extends BaseIdeSetup { const agents = await getAgentsFromBmad(bmadDir, options.selectedModules || []); const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []); - // Create directories for each module + // Create directories for each module (including standalone) const modules = new Set(); for (const item of [...agents, ...tasks]) modules.add(item.module); diff --git a/tools/cli/installers/lib/ide/shared/bmad-artifacts.js b/tools/cli/installers/lib/ide/shared/bmad-artifacts.js index 732d7807..27184bc9 100644 --- a/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +++ b/tools/cli/installers/lib/ide/shared/bmad-artifacts.js @@ -8,11 +8,13 @@ const fs = require('fs-extra'); async function getAgentsFromBmad(bmadDir, selectedModules = []) { const agents = []; + // Get core agents if (await fs.pathExists(path.join(bmadDir, 'core', 'agents'))) { const coreAgents = await getAgentsFromDir(path.join(bmadDir, 'core', 'agents'), 'core'); agents.push(...coreAgents); } + // Get module agents for (const moduleName of selectedModules) { const agentsPath = path.join(bmadDir, moduleName, 'agents'); @@ -22,6 +24,35 @@ async function getAgentsFromBmad(bmadDir, selectedModules = []) { } } + // Get standalone agents from bmad/agents/ directory + const standaloneAgentsDir = path.join(bmadDir, 'agents'); + if (await fs.pathExists(standaloneAgentsDir)) { + const agentDirs = await fs.readdir(standaloneAgentsDir, { withFileTypes: true }); + + for (const agentDir of agentDirs) { + if (!agentDir.isDirectory()) continue; + + const agentDirPath = path.join(standaloneAgentsDir, agentDir.name); + const agentFiles = await fs.readdir(agentDirPath); + + for (const file of agentFiles) { + if (!file.endsWith('.md')) continue; + if (file.includes('.customize.')) continue; + + const filePath = path.join(agentDirPath, file); + const content = await fs.readFile(filePath, 'utf8'); + + if (content.includes('localskip="true"')) continue; + + agents.push({ + path: filePath, + name: file.replace('.md', ''), + module: 'standalone', // Mark as standalone agent + }); + } + } + } + return agents; }