* feat: add expansion pack installation system with game dev and infrastructure expansion packs - Added expansion pack discovery and installation to BMAD installer - Supports interactive and CLI installation of expansion packs - Expansion pack files install to destination root (.bmad-core) - Added game development expansion pack (.bmad-2d-phaser-game-dev) - Game designer, developer, and scrum master agents - Game-specific templates, tasks, workflows, and guidelines - Specialized for Phaser 3 + TypeScript development - Added infrastructure devops expansion pack (.bmad-infrastructure-devops) - Platform engineering agent and infrastructure templates - Expansion pack agents automatically integrate with IDE rules - Added list:expansions command and --expansion-packs CLI option 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> * alpha expansion packs and installer update to support installing expansion packs optionally * node20 --------- Co-authored-by: Brian Madison <brianmadison@Brians-MacBook-Pro.local> Co-authored-by: Claude <noreply@anthropic.com>
126 lines
4.0 KiB
JavaScript
126 lines
4.0 KiB
JavaScript
const fs = require('fs-extra');
|
|
const path = require('path');
|
|
const yaml = require('js-yaml');
|
|
|
|
class ConfigLoader {
|
|
constructor() {
|
|
this.configPath = path.join(__dirname, '..', 'config', 'install.config.yml');
|
|
this.config = null;
|
|
}
|
|
|
|
async load() {
|
|
if (this.config) return this.config;
|
|
|
|
try {
|
|
const configContent = await fs.readFile(this.configPath, 'utf8');
|
|
this.config = yaml.load(configContent);
|
|
return this.config;
|
|
} catch (error) {
|
|
throw new Error(`Failed to load configuration: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
async getInstallationOptions() {
|
|
const config = await this.load();
|
|
return config['installation-options'] || {};
|
|
}
|
|
|
|
async getAvailableAgents() {
|
|
const config = await this.load();
|
|
return config['available-agents'] || [];
|
|
}
|
|
|
|
async getAvailableExpansionPacks() {
|
|
const expansionPacksDir = path.join(this.getBmadCorePath(), '..', 'expansion-packs');
|
|
|
|
try {
|
|
const entries = await fs.readdir(expansionPacksDir, { withFileTypes: true });
|
|
const expansionPacks = [];
|
|
|
|
for (const entry of entries) {
|
|
if (entry.isDirectory()) {
|
|
const manifestPath = path.join(expansionPacksDir, entry.name, 'manifest.yml');
|
|
|
|
try {
|
|
const manifestContent = await fs.readFile(manifestPath, 'utf8');
|
|
const manifest = yaml.load(manifestContent);
|
|
|
|
expansionPacks.push({
|
|
id: entry.name,
|
|
name: manifest.name || entry.name,
|
|
description: manifest.description || 'No description available',
|
|
version: manifest.version || '1.0.0',
|
|
author: manifest.author || 'Unknown',
|
|
manifestPath: manifestPath,
|
|
dependencies: manifest.dependencies || []
|
|
});
|
|
} catch (error) {
|
|
console.warn(`Failed to read manifest for expansion pack ${entry.name}: ${error.message}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
return expansionPacks;
|
|
} catch (error) {
|
|
console.warn(`Failed to read expansion packs directory: ${error.message}`);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async getAgentDependencies(agentId) {
|
|
// Use DependencyResolver to dynamically parse agent dependencies
|
|
const DependencyResolver = require('../../lib/dependency-resolver');
|
|
const resolver = new DependencyResolver(path.join(__dirname, '..', '..', '..'));
|
|
|
|
try {
|
|
const agentDeps = await resolver.resolveAgentDependencies(agentId);
|
|
|
|
// Convert to flat list of file paths
|
|
const depPaths = [];
|
|
|
|
// Add core files
|
|
const config = await this.load();
|
|
const coreFiles = config['agent-dependencies']?.['core-files'] || [];
|
|
depPaths.push(...coreFiles);
|
|
|
|
// Add agent file itself is already handled by installer
|
|
|
|
// Add all resolved resources
|
|
for (const resource of agentDeps.resources) {
|
|
const filePath = `.bmad-core/${resource.type}/${resource.id}.md`;
|
|
if (!depPaths.includes(filePath)) {
|
|
depPaths.push(filePath);
|
|
}
|
|
}
|
|
|
|
return depPaths;
|
|
} catch (error) {
|
|
console.warn(`Failed to dynamically resolve dependencies for ${agentId}: ${error.message}`);
|
|
|
|
// Fall back to static config
|
|
const config = await this.load();
|
|
const dependencies = config['agent-dependencies'] || {};
|
|
const coreFiles = dependencies['core-files'] || [];
|
|
const agentDeps = dependencies[agentId] || [];
|
|
|
|
return [...coreFiles, ...agentDeps];
|
|
}
|
|
}
|
|
|
|
async getIdeConfiguration(ide) {
|
|
const config = await this.load();
|
|
const ideConfigs = config['ide-configurations'] || {};
|
|
return ideConfigs[ide] || null;
|
|
}
|
|
|
|
getBmadCorePath() {
|
|
// Get the path to bmad-core relative to the installer (now under tools)
|
|
return path.join(__dirname, '..', '..', '..', 'bmad-core');
|
|
}
|
|
|
|
getAgentPath(agentId) {
|
|
return path.join(this.getBmadCorePath(), 'agents', `${agentId}.md`);
|
|
}
|
|
}
|
|
|
|
module.exports = new ConfigLoader(); |