add custom content installation question to indicate location of custom content

This commit is contained in:
Brian Madison
2025-12-07 13:39:03 -06:00
parent 987f81ff64
commit b68e5c0225
4 changed files with 231 additions and 17 deletions

View File

@@ -798,6 +798,53 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
}
}
// Install custom content if provided AND selected
if (
config.customContent &&
config.customContent.hasCustomContent &&
config.customContent.customPath &&
config.customContent.selected &&
config.customContent.selectedFiles
) {
spinner.start('Installing custom content...');
const { CustomHandler } = require('../custom/handler');
const customHandler = new CustomHandler();
// Use the selected files instead of finding all files
const customFiles = config.customContent.selectedFiles;
if (customFiles.length > 0) {
console.log(chalk.cyan(`\n Found ${customFiles.length} custom content file(s):`));
for (const customFile of customFiles) {
const customInfo = await customHandler.getCustomInfo(customFile, projectDir);
if (customInfo) {
console.log(chalk.dim(`${customInfo.name} (${customInfo.relativePath})`));
// Install the custom content
const result = await customHandler.install(
customInfo.path,
bmadDir,
{ ...config.coreConfig, ...customInfo.config },
(filePath) => {
// Track installed files
this.installedFiles.push(filePath);
},
);
if (result.errors.length > 0) {
console.log(chalk.yellow(` ⚠️ ${result.errors.length} error(s) occurred`));
for (const error of result.errors) {
console.log(chalk.dim(` - ${error}`));
}
} else {
console.log(chalk.green(` ✓ Installed ${result.agentsInstalled} agents, ${result.workflowsInstalled} workflows`));
}
}
}
}
spinner.succeed('Custom content installed');
}
// Generate clean config.yaml files for each installed module
spinner.start('Generating module configurations...');
await this.generateModuleConfigs(bmadDir, moduleConfigs);

View File

@@ -68,9 +68,10 @@ class CustomHandler {
/**
* Get custom content info from a custom.yaml file
* @param {string} customYamlPath - Path to custom.yaml file
* @param {string} projectRoot - Project root directory for calculating relative paths
* @returns {Object|null} Custom content info
*/
async getCustomInfo(customYamlPath) {
async getCustomInfo(customYamlPath, projectRoot = null) {
try {
const configContent = await fs.readFile(customYamlPath, 'utf8');
@@ -84,7 +85,9 @@ class CustomHandler {
}
const customDir = path.dirname(customYamlPath);
const relativePath = path.relative(process.cwd(), customDir);
// Use provided projectRoot or fall back to process.cwd()
const basePath = projectRoot || process.cwd();
const relativePath = path.relative(basePath, customDir);
return {
id: config.code || path.basename(customDir),
@@ -236,13 +239,20 @@ class CustomHandler {
// Copy with placeholder replacement for text files
const textExtensions = ['.md', '.yaml', '.yml', '.txt', '.json'];
if (textExtensions.some((ext) => entry.name.endsWith(ext))) {
await this.fileOps.copyFile(sourcePath, targetPath, {
bmadFolder: config.bmad_folder || 'bmad',
userName: config.user_name || 'User',
communicationLanguage: config.communication_language || 'English',
outputFolder: config.output_folder || 'docs',
});
// Read source content
let content = await fs.readFile(sourcePath, 'utf8');
// Replace placeholders
content = content.replaceAll('{bmad_folder}', config.bmad_folder || 'bmad');
content = content.replaceAll('{user_name}', config.user_name || 'User');
content = content.replaceAll('{communication_language}', config.communication_language || 'English');
content = content.replaceAll('{output_folder}', config.output_folder || 'docs');
// Write to target
await fs.ensureDir(path.dirname(targetPath));
await fs.writeFile(targetPath, content, 'utf8');
} else {
// Copy binary files as-is
await fs.copy(sourcePath, targetPath);
}