From b63bf9d067efb458ebbc1f4618dd9f22c69ef10d Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Wed, 12 Nov 2025 22:40:45 -0600 Subject: [PATCH] installer update to quick install and agent rebuild --- tools/cli/installers/lib/core/installer.js | 27 ++++++++++++++-------- tools/cli/lib/ui.js | 18 +++++++++++---- tools/cli/lib/yaml-xml-builder.js | 22 ++++++++++++++++-- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 97eb8c19..25aab3b6 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -1627,26 +1627,33 @@ class Installer { }); 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' - const { UI } = require('../../../lib/ui'); - const ui = new UI(); - const toolConfig = await ui.promptToolSelection(projectDir, []); - - if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) { + // Update IDE configurations using the existing IDE list from manifest + if (existingIdes && existingIdes.length > 0) { spinner.start('Updating IDE configurations...'); - for (const ide of toolConfig.ides) { + for (const ide of existingIdes) { spinner.text = `Updating ${ide}...`; + + // Stop spinner before IDE setup to prevent blocking any potential prompts + // However, we pass _alreadyConfigured to skip all prompts during compile + spinner.stop(); + await this.ideManager.setup(ide, projectDir, bmadDir, { selectedModules: installedModules, skipModuleInstall: true, // Skip module installation, just update IDE files verbose: config.verbose, + preCollectedConfig: { _alreadyConfigured: true }, // Skip all interactive prompts during compile }); + + // Restart spinner for next IDE + if (existingIdes.indexOf(ide) < existingIdes.length - 1) { + spinner.start('Updating IDE configurations...'); + } } - spinner.succeed('IDE configurations updated'); + console.log(chalk.green('✓ IDE configurations updated')); + } else { + console.log(chalk.yellow('⚠️ No IDEs configured. Skipping IDE update.')); } return { agentCount, taskCount }; diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index e0115103..323fdaaf 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -124,10 +124,12 @@ class UI { * @returns {Object} Tool configuration */ async promptToolSelection(projectDir, selectedModules) { - // Check for existing configured IDEs + // Check for existing configured IDEs - use findBmadDir to detect custom folder names const { Detector } = require('../installers/lib/core/detector'); + const { Installer } = require('../installers/lib/core/installer'); const detector = new Detector(); - const bmadDir = path.join(projectDir || process.cwd(), 'bmad'); + const installer = new Installer(); + const bmadDir = await installer.findBmadDir(projectDir || process.cwd()); const existingInstall = await detector.detect(bmadDir); const configuredIdes = existingInstall.ides || []; @@ -332,8 +334,10 @@ class UI { */ async getExistingInstallation(directory) { const { Detector } = require('../installers/lib/core/detector'); + const { Installer } = require('../installers/lib/core/installer'); const detector = new Detector(); - const bmadDir = path.join(directory, 'bmad'); + const installer = new Installer(); + const bmadDir = await installer.findBmadDir(directory); const existingInstall = await detector.detect(bmadDir); const installedModuleIds = new Set(existingInstall.modules.map((mod) => mod.id)); @@ -431,9 +435,15 @@ class UI { if (stats.isDirectory()) { const files = await fs.readdir(directory); if (files.length > 0) { + // Check for any bmad installation (any folder with _cfg/manifest.yaml) + const { Installer } = require('../installers/lib/core/installer'); + const installer = new Installer(); + const bmadDir = await installer.findBmadDir(directory); + const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_cfg', 'manifest.yaml'))); + console.log( chalk.gray(`Directory exists and contains ${files.length} item(s)`) + - (files.includes('bmad') ? chalk.yellow(' including existing bmad installation') : ''), + (hasBmadInstall ? chalk.yellow(` including existing BMAD installation (${path.basename(bmadDir)})`) : ''), ); } else { console.log(chalk.gray('Directory exists and is empty')); diff --git a/tools/cli/lib/yaml-xml-builder.js b/tools/cli/lib/yaml-xml-builder.js index f7742a82..3f32aa00 100644 --- a/tools/cli/lib/yaml-xml-builder.js +++ b/tools/cli/lib/yaml-xml-builder.js @@ -270,13 +270,31 @@ class YamlXmlBuilder { /** * Build prompts XML section + * Handles both array format and object/dictionary format */ buildPromptsXml(prompts) { - if (!prompts || prompts.length === 0) return ''; + if (!prompts) return ''; + + // Handle object/dictionary format: { promptId: 'content', ... } + // Convert to array format for processing + let promptsArray = prompts; + if (!Array.isArray(prompts)) { + // Check if it's an object with no length property (dictionary format) + if (typeof prompts === 'object' && prompts.length === undefined) { + promptsArray = Object.entries(prompts).map(([id, content]) => ({ + id: id, + content: content, + })); + } else { + return ''; // Not a valid prompts format + } + } + + if (promptsArray.length === 0) return ''; let xml = ' \n'; - for (const prompt of prompts) { + for (const prompt of promptsArray) { xml += ` \n`; xml += `