diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 9089775d..005e1faf 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -167,50 +167,31 @@ class Installer { if (newlySelectedIdes.length > 0) { console.log('\n'); // Add spacing before IDE questions + // Use IdeManager to get handlers (supports both config-driven and custom IDEs) + await this.ideManager.ensureInitialized(); + for (const ide of newlySelectedIdes) { - // List of IDEs that have interactive prompts - //TODO: Why is this here, hardcoding this list here is bad, fix me! - const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini', 'rovo-dev'].includes( - ide, - ); + try { + const handler = this.ideManager.handlers.get(ide); - if (needsPrompts) { - // Get IDE handler and collect configuration - try { - // Dynamically load the IDE setup module - const ideModule = require(`../ide/${ide}`); - - // Get the setup class (handle different export formats) - let SetupClass; - const className = - ide - .split('-') - .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join('') + 'Setup'; - - if (ideModule[className]) { - SetupClass = ideModule[className]; - } else if (ideModule.default) { - SetupClass = ideModule.default; - } else { - continue; - } - - const ideSetup = new SetupClass(); - - // Check if this IDE has a collectConfiguration method - if (typeof ideSetup.collectConfiguration === 'function') { - console.log(chalk.cyan(`\nConfiguring ${ide}...`)); - ideConfigurations[ide] = await ideSetup.collectConfiguration({ - selectedModules: selectedModules || [], - projectDir, - bmadDir, - }); - } - } catch { - // IDE doesn't have a setup file or collectConfiguration method - console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`)); + if (!handler) { + // IDE not recognized - skip silently + continue; } + + // Check if this IDE handler has a collectConfiguration method + if (typeof handler.collectConfiguration === 'function') { + console.log(chalk.cyan(`\nConfiguring ${ide}...`)); + ideConfigurations[ide] = await handler.collectConfiguration({ + selectedModules: selectedModules || [], + projectDir, + bmadDir, + }); + } + // Most config-driven IDEs don't need configuration - silently skip + } catch { + // IDE doesn't have collectConfiguration or had an error - skip + continue; } } } diff --git a/tools/cli/installers/lib/ide/shared/path-utils.js b/tools/cli/installers/lib/ide/shared/path-utils.js index 488d2811..80b632ca 100644 --- a/tools/cli/installers/lib/ide/shared/path-utils.js +++ b/tools/cli/installers/lib/ide/shared/path-utils.js @@ -15,13 +15,10 @@ const AGENT_SEGMENT = 'agents'; /** * Artifact type to suffix mapping - * Used for new suffix-based naming convention + * Only agents get the .agent suffix; workflows/tasks/tools use standard .md extension */ const ARTIFACT_SUFFIXES = { agent: '.agent', - workflow: '.workflow', - task: '.task', - tool: '.tool', }; /** @@ -216,10 +213,11 @@ function toDashPath(relativePath, fileExtension = DEFAULT_FILE_EXTENSION) { /** * Convert relative path to suffix-based name (NEW UNIVERSAL STANDARD) + * Only applies .agent suffix to agents; workflows/tasks/tools get standard .md extension. * Converts: 'cis/agents/storymaster.md' → 'bmad-cis-storymaster.agent.md' - * Converts: 'bmm/workflows/plan-project.md' → 'bmad-bmm-plan-project.workflow.md' - * Converts: 'bmm/tasks/create-story.md' → 'bmad-bmm-create-story.task.md' - * Converts: 'bmm/tools/file-ops.md' → 'bmad-bmm-file-ops.tool.md' + * Converts: 'bmm/workflows/plan-project.md' → 'bmad-bmm-plan-project.md' + * Converts: 'bmm/tasks/create-story.md' → 'bmad-bmm-create-story.md' + * Converts: 'bmm/tools/file-ops.md' → 'bmad-bmm-file-ops.md' * Converts: 'core/agents/brainstorming.md' → 'bmad-brainstorming.agent.md' (core items skip module prefix) * * @param {string} relativePath - Path like 'cis/agents/storymaster.md' @@ -237,7 +235,8 @@ function toSuffixBasedName(relativePath, artifactType, fileExtension = DEFAULT_F const type = parts[1]; // agents, workflows, tasks, tools const name = parts.slice(2).join('-'); - const suffix = ARTIFACT_SUFFIXES[artifactType] || ''; + // Only add .agent suffix for agents; workflows/tasks/tools use standard extension + const suffix = artifactType === 'agent' ? ARTIFACT_SUFFIXES.agent : ''; // For core module, skip the module prefix (use 'bmad-name.suffix.md') if (module === 'core') { @@ -261,7 +260,7 @@ function getArtifactSuffix(artifactType) { /** * Parse artifact type from suffix-based filename * Parses: 'bmad-cis-storymaster.agent.md' → 'agent' - * Parses: 'bmad-bmm-plan-project.workflow.md' → 'workflow' + * Returns null for workflows/tasks/tools (no suffix) * * @param {string} filename - Suffix-based filename * @returns {string|null} Artifact type or null if not found