Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60c147aa75 | ||
|
|
ba91cb17cf | ||
|
|
b82978fd38 | ||
|
|
50d17ed65d |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
# [4.19.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.18.0...v4.19.0) (2025-06-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* expansion install config ([50d17ed](https://github.com/bmadcode/BMAD-METHOD/commit/50d17ed65d40f6688f3b6e62732fb2280b6b116e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* install for ide now sets up rules also for expansion agents! ([b82978f](https://github.com/bmadcode/BMAD-METHOD/commit/b82978fd38ea789a799ccc1373cfb61a2001c1e0))
|
||||
|
||||
# [4.18.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.17.0...v4.18.0) (2025-06-28)
|
||||
|
||||
|
||||
|
||||
@@ -17,4 +17,3 @@ devLoadAlwaysFiles:
|
||||
- docs/architecture/source-tree.md
|
||||
devDebugLog: .ai/debug-log.md
|
||||
devStoryLocation: docs/stories
|
||||
agentCoreDump: .ai/core-dump{n}.md
|
||||
|
||||
5
expansion-packs/bmad-2d-phaser-game-dev/config.yml
Normal file
5
expansion-packs/bmad-2d-phaser-game-dev/config.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
name: bmad-2d-phaser-game-dev
|
||||
version: 1.1.0
|
||||
short-title: 2D game development with Phaser 3 & TypeScript
|
||||
description: 2D Game Development expansion pack for BMAD Method - Phaser 3 & TypeScript focused
|
||||
author: Brian (BMad)
|
||||
@@ -1,45 +0,0 @@
|
||||
name: bmad-2d-phaser-game-dev
|
||||
version: 1.0.0
|
||||
description: 2D Game Development expansion pack for BMAD Method - Phaser 3 & TypeScript focused
|
||||
author: BMAD Team
|
||||
files:
|
||||
- source: agents/game-designer.md
|
||||
destination: .bmad-core/agents/game-designer.md
|
||||
- source: agents/game-developer.md
|
||||
destination: .bmad-core/agents/game-developer.md
|
||||
- source: agents/game-sm.md
|
||||
destination: .bmad-core/agents/game-sm.md
|
||||
- source: team-game-dev.yml
|
||||
destination: .bmad-core/agent-teams/team-game-dev.yml
|
||||
- source: templates/game-design-doc-tmpl.md
|
||||
destination: .bmad-core/templates/game-design-doc-tmpl.md
|
||||
- source: templates/game-architecture-tmpl.md
|
||||
destination: .bmad-core/templates/game-architecture-tmpl.md
|
||||
- source: templates/level-design-doc-tmpl.md
|
||||
destination: .bmad-core/templates/level-design-doc-tmpl.md
|
||||
- source: templates/game-story-tmpl.md
|
||||
destination: .bmad-core/templates/game-story-tmpl.md
|
||||
- source: templates/game-brief-tmpl.md
|
||||
destination: .bmad-core/templates/game-brief-tmpl.md
|
||||
- source: tasks/create-game-story.md
|
||||
destination: .bmad-core/tasks/create-game-story.md
|
||||
- source: tasks/game-design-brainstorming.md
|
||||
destination: .bmad-core/tasks/game-design-brainstorming.md
|
||||
- source: tasks/advanced-elicitation.md
|
||||
destination: .bmad-core/tasks/advanced-elicitation.md
|
||||
- source: checklists/game-story-dod-checklist.md
|
||||
destination: .bmad-core/checklists/game-story-dod-checklist.md
|
||||
- source: checklists/game-design-checklist.md
|
||||
destination: .bmad-core/checklists/game-design-checklist.md
|
||||
- source: data/bmad-kb.md
|
||||
destination: .bmad-core/data/bmad-kb.md
|
||||
- source: data/development-guidelines.md
|
||||
destination: .bmad-core/data/development-guidelines.md
|
||||
- source: workflows/game-dev-greenfield.yml
|
||||
destination: .bmad-core/workflows/game-dev-greenfield.yml
|
||||
- source: workflows/game-prototype.yml
|
||||
destination: .bmad-core/workflows/game-prototype.yml
|
||||
dependencies:
|
||||
- architect
|
||||
- developer
|
||||
- sm
|
||||
5
expansion-packs/bmad-creator-tools/config.yml
Normal file
5
expansion-packs/bmad-creator-tools/config.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
name: bmad-creator-tools
|
||||
version: 1.0.0
|
||||
short-title: Tools for creating BMAD framework components
|
||||
description: Tools for creating and extending BMAD framework components.
|
||||
author: Brian (BMad)
|
||||
5
expansion-packs/bmad-infrastructure-devops/config.yml
Normal file
5
expansion-packs/bmad-infrastructure-devops/config.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
name: bmad-infrastructure-devops
|
||||
version: 1.0.0
|
||||
short-title: Infrastructure and DevOps capabilities
|
||||
description: This expansion pack extends BMAD Method with comprehensive infrastructure and DevOps capabilities. It's designed for teams that need to define, implement, and manage cloud infrastructure alongside their application development.
|
||||
author: Brian (BMad)
|
||||
@@ -1,23 +0,0 @@
|
||||
name: bmad-infrastructure-devops
|
||||
version: 1.0.0
|
||||
description: Infrastructure & DevOps expansion pack for BMAD Method - Platform engineering and cloud infrastructure focused
|
||||
author: BMAD Team
|
||||
files:
|
||||
- source: agents/infra-devops-platform.md
|
||||
destination: .bmad-core/agents/infra-devops-platform.md
|
||||
- source: templates/infrastructure-architecture-tmpl.md
|
||||
destination: .bmad-core/templates/infrastructure-architecture-tmpl.md
|
||||
- source: templates/infrastructure-platform-from-arch-tmpl.md
|
||||
destination: .bmad-core/templates/infrastructure-platform-from-arch-tmpl.md
|
||||
- source: tasks/create-doc.md
|
||||
destination: .bmad-core/tasks/create-doc.md
|
||||
- source: tasks/review-infrastructure.md
|
||||
destination: .bmad-core/tasks/review-infrastructure.md
|
||||
- source: tasks/validate-infrastructure.md
|
||||
destination: .bmad-core/tasks/validate-infrastructure.md
|
||||
- source: checklists/infrastructure-checklist.md
|
||||
destination: .bmad-core/checklists/infrastructure-checklist.md
|
||||
dependencies:
|
||||
- architect
|
||||
- operations-specialist
|
||||
- security-specialist
|
||||
@@ -1,12 +0,0 @@
|
||||
name: bmad-creator-tools
|
||||
version: 1.0.0
|
||||
description: Tools for creating and extending BMAD framework components
|
||||
type: creator-tools
|
||||
compatibility:
|
||||
bmad-version: '>=4.0.0'
|
||||
components:
|
||||
agents:
|
||||
- bmad-the-creator
|
||||
tasks:
|
||||
- create-agent
|
||||
- generate-expansion-pack
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.18.0",
|
||||
"version": "4.19.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bmad-method",
|
||||
"version": "4.18.0",
|
||||
"version": "4.19.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kayvan/markdown-tree-parser": "^1.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.18.0",
|
||||
"version": "4.19.0",
|
||||
"description": "Breakthrough Method of Agile AI-driven Development",
|
||||
"main": "tools/cli.js",
|
||||
"bin": {
|
||||
|
||||
41
test-ide-paths.js
Normal file
41
test-ide-paths.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// Test script to verify IDE setup paths for expansion pack agents
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
// Simulate the findAgentPath logic
|
||||
function simulateFindAgentPath(agentId, installDir) {
|
||||
const possiblePaths = [
|
||||
path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
|
||||
path.join(installDir, "agents", `${agentId}.md`),
|
||||
// Expansion pack paths
|
||||
path.join(installDir, ".bmad-2d-phaser-game-dev", "agents", `${agentId}.md`),
|
||||
path.join(installDir, ".bmad-infrastructure-devops", "agents", `${agentId}.md`),
|
||||
path.join(installDir, ".bmad-creator-tools", "agents", `${agentId}.md`)
|
||||
];
|
||||
|
||||
// Simulate finding the agent in an expansion pack
|
||||
if (agentId === 'game-developer') {
|
||||
return path.join(installDir, ".bmad-2d-phaser-game-dev", "agents", `${agentId}.md`);
|
||||
}
|
||||
|
||||
// Default to core
|
||||
return path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
}
|
||||
|
||||
// Test different scenarios
|
||||
const testDir = '/project';
|
||||
const agents = ['dev', 'game-developer', 'infra-devops-platform'];
|
||||
|
||||
console.log('Testing IDE path references:\n');
|
||||
|
||||
agents.forEach(agentId => {
|
||||
const agentPath = simulateFindAgentPath(agentId, testDir);
|
||||
const relativePath = path.relative(testDir, agentPath).replace(/\\/g, '/');
|
||||
|
||||
console.log(`Agent: ${agentId}`);
|
||||
console.log(` Full path: ${agentPath}`);
|
||||
console.log(` Relative path: ${relativePath}`);
|
||||
console.log(` Roo customInstructions: CRITICAL Read the full YML from ${relativePath} ...`);
|
||||
console.log(` Cursor MDC reference: [${relativePath}](mdc:${relativePath})`);
|
||||
console.log('');
|
||||
});
|
||||
58
tools/installer/config/ide-agent-config.yml
Normal file
58
tools/installer/config/ide-agent-config.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
# IDE-specific agent configurations
|
||||
# This file defines agent-specific settings for different IDEs
|
||||
|
||||
# Roo Code file permissions
|
||||
# Each agent can have restricted file access based on regex patterns
|
||||
# If an agent is not listed here, it gets full edit access
|
||||
roo-permissions:
|
||||
# Core agents
|
||||
analyst:
|
||||
fileRegex: "\\.(md|txt)$"
|
||||
description: "Documentation and text files"
|
||||
pm:
|
||||
fileRegex: "\\.(md|txt)$"
|
||||
description: "Product documentation"
|
||||
architect:
|
||||
fileRegex: "\\.(md|txt|yml|yaml|json)$"
|
||||
description: "Architecture docs and configs"
|
||||
qa:
|
||||
fileRegex: "\\.(test|spec)\\.(js|ts|jsx|tsx)$|\\.md$"
|
||||
description: "Test files and documentation"
|
||||
ux-expert:
|
||||
fileRegex: "\\.(md|css|scss|html|jsx|tsx)$"
|
||||
description: "Design-related files"
|
||||
po:
|
||||
fileRegex: "\\.(md|txt)$"
|
||||
description: "Story and requirement docs"
|
||||
sm:
|
||||
fileRegex: "\\.(md|txt)$"
|
||||
description: "Process and planning docs"
|
||||
# Expansion pack agents
|
||||
game-designer:
|
||||
fileRegex: "\\.(md|txt|json|yaml|yml)$"
|
||||
description: "Game design documents and configs"
|
||||
game-sm:
|
||||
fileRegex: "\\.(md|txt)$"
|
||||
description: "Game project management docs"
|
||||
|
||||
# Cline agent ordering
|
||||
# Lower numbers appear first in the list
|
||||
# Agents not listed get order 99
|
||||
cline-order:
|
||||
# Core agents
|
||||
bmad-master: 1
|
||||
bmad-orchestrator: 2
|
||||
pm: 3
|
||||
analyst: 4
|
||||
architect: 5
|
||||
po: 6
|
||||
sm: 7
|
||||
dev: 8
|
||||
qa: 9
|
||||
ux-expert: 10
|
||||
# Expansion pack agents
|
||||
bmad-the-creator: 11
|
||||
game-designer: 12
|
||||
game-developer: 13
|
||||
game-sm: 14
|
||||
infra-devops-platform: 15
|
||||
@@ -77,24 +77,45 @@ class ConfigLoader {
|
||||
const expansionPacks = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const manifestPath = path.join(expansionPacksDir, entry.name, 'manifest.yml');
|
||||
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
||||
const packPath = path.join(expansionPacksDir, entry.name);
|
||||
const configPath = path.join(packPath, 'config.yml');
|
||||
|
||||
try {
|
||||
const manifestContent = await fs.readFile(manifestPath, 'utf8');
|
||||
const manifest = yaml.load(manifestContent);
|
||||
// Read config.yml
|
||||
const configContent = await fs.readFile(configPath, 'utf8');
|
||||
const config = yaml.load(configContent);
|
||||
|
||||
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 || []
|
||||
name: config.name || entry.name,
|
||||
description: config['short-title'] || config.description || 'No description available',
|
||||
fullDescription: config.description || config['short-title'] || 'No description available',
|
||||
version: config.version || '1.0.0',
|
||||
author: config.author || 'BMAD Team',
|
||||
packPath: packPath,
|
||||
dependencies: config.dependencies?.agents || []
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn(`Failed to read manifest for expansion pack ${entry.name}: ${error.message}`);
|
||||
// Fallback if config.yml doesn't exist or can't be read
|
||||
console.warn(`Failed to read config for expansion pack ${entry.name}: ${error.message}`);
|
||||
|
||||
// Try to derive info from directory name as fallback
|
||||
const name = entry.name
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
|
||||
expansionPacks.push({
|
||||
id: entry.name,
|
||||
name: name,
|
||||
description: 'No description available',
|
||||
fullDescription: 'No description available',
|
||||
version: '1.0.0',
|
||||
author: 'BMAD Team',
|
||||
packPath: packPath,
|
||||
dependencies: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const yaml = require("js-yaml");
|
||||
const fileManager = require("./file-manager");
|
||||
const configLoader = require("./config-loader");
|
||||
|
||||
@@ -13,6 +15,27 @@ async function initializeModules() {
|
||||
}
|
||||
|
||||
class IdeSetup {
|
||||
constructor() {
|
||||
this.ideAgentConfig = null;
|
||||
}
|
||||
|
||||
async loadIdeAgentConfig() {
|
||||
if (this.ideAgentConfig) return this.ideAgentConfig;
|
||||
|
||||
try {
|
||||
const configPath = path.join(__dirname, '..', 'config', 'ide-agent-config.yml');
|
||||
const configContent = await fs.readFile(configPath, 'utf8');
|
||||
this.ideAgentConfig = yaml.load(configContent);
|
||||
return this.ideAgentConfig;
|
||||
} catch (error) {
|
||||
console.warn('Failed to load IDE agent configuration, using defaults');
|
||||
return {
|
||||
'roo-permissions': {},
|
||||
'cline-order': {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async setup(ide, installDir, selectedAgent = null) {
|
||||
await initializeModules();
|
||||
const ideConfig = await configLoader.getIdeConfiguration(ide);
|
||||
@@ -48,13 +71,10 @@ class IdeSetup {
|
||||
await fileManager.ensureDirectory(cursorRulesDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
// Find the agent file
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`);
|
||||
|
||||
@@ -83,7 +103,8 @@ class IdeSetup {
|
||||
}
|
||||
mdcContent += "\n```\n\n";
|
||||
mdcContent += "## File Reference\n\n";
|
||||
mdcContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](mdc:.bmad-core/agents/${agentId}.md).\n\n`;
|
||||
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
||||
mdcContent += `The complete agent definition is available in [${relativePath}](mdc:${relativePath}).\n\n`;
|
||||
mdcContent += "## Usage\n\n";
|
||||
mdcContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
|
||||
agentId,
|
||||
@@ -107,14 +128,11 @@ class IdeSetup {
|
||||
await fileManager.ensureDirectory(commandsDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
// Find the agent file
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
const commandPath = path.join(commandsDir, `${agentId}.md`);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
// Create command file with agent content
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
|
||||
@@ -140,13 +158,10 @@ class IdeSetup {
|
||||
await fileManager.ensureDirectory(windsurfRulesDir);
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
// Find the agent file
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const mdPath = path.join(windsurfRulesDir, `${agentId}.md`);
|
||||
|
||||
@@ -170,7 +185,8 @@ class IdeSetup {
|
||||
}
|
||||
mdContent += "\n```\n\n";
|
||||
mdContent += "## File Reference\n\n";
|
||||
mdContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md).\n\n`;
|
||||
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
||||
mdContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
|
||||
mdContent += "## Usage\n\n";
|
||||
mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
|
||||
agentId,
|
||||
@@ -187,39 +203,86 @@ class IdeSetup {
|
||||
return true;
|
||||
}
|
||||
|
||||
async findAgentPath(agentId, installDir) {
|
||||
// Try to find the agent file in various locations
|
||||
const possiblePaths = [
|
||||
path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
|
||||
path.join(installDir, "agents", `${agentId}.md`)
|
||||
];
|
||||
|
||||
// Also check expansion pack directories
|
||||
const glob = require("glob");
|
||||
const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
|
||||
for (const expDir of expansionDirs) {
|
||||
possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
|
||||
}
|
||||
|
||||
for (const agentPath of possiblePaths) {
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
return agentPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async getAllAgentIds(installDir) {
|
||||
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
const glob = require("glob");
|
||||
const allAgentIds = [];
|
||||
|
||||
// Check core agents in .bmad-core or root
|
||||
let agentsDir = path.join(installDir, ".bmad-core", "agents");
|
||||
if (!(await fileManager.pathExists(agentsDir))) {
|
||||
agentsDir = path.join(installDir, "agents");
|
||||
}
|
||||
|
||||
const glob = require("glob");
|
||||
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
||||
return agentFiles.map((file) => path.basename(file, ".md"));
|
||||
|
||||
if (await fileManager.pathExists(agentsDir)) {
|
||||
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
||||
allAgentIds.push(...agentFiles.map((file) => path.basename(file, ".md")));
|
||||
}
|
||||
|
||||
// Also check for expansion pack agents in dot folders
|
||||
const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
|
||||
for (const expDir of expansionDirs) {
|
||||
const fullExpDir = path.join(installDir, expDir);
|
||||
const expAgentFiles = glob.sync("*.md", { cwd: fullExpDir });
|
||||
allAgentIds.push(...expAgentFiles.map((file) => path.basename(file, ".md")));
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
return [...new Set(allAgentIds)];
|
||||
}
|
||||
|
||||
async getAgentTitle(agentId, installDir) {
|
||||
// Try to read the actual agent file to get the title
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
// Try to find the agent file in various locations
|
||||
const possiblePaths = [
|
||||
path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
|
||||
path.join(installDir, "agents", `${agentId}.md`)
|
||||
];
|
||||
|
||||
// Also check expansion pack directories
|
||||
const glob = require("glob");
|
||||
const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
|
||||
for (const expDir of expansionDirs) {
|
||||
possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
|
||||
}
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
try {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
||||
|
||||
if (yamlMatch) {
|
||||
const yaml = yamlMatch[1];
|
||||
const titleMatch = yaml.match(/title:\s*(.+)/);
|
||||
if (titleMatch) {
|
||||
return titleMatch[1].trim();
|
||||
for (const agentPath of possiblePaths) {
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
try {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
||||
|
||||
if (yamlMatch) {
|
||||
const yaml = yamlMatch[1];
|
||||
const titleMatch = yaml.match(/title:\s*(.+)/);
|
||||
if (titleMatch) {
|
||||
return titleMatch[1].trim();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to read agent title for ${agentId}: ${error.message}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to read agent title for ${agentId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,40 +313,9 @@ class IdeSetup {
|
||||
// Create new modes content
|
||||
let newModesContent = "";
|
||||
|
||||
// Define file permissions for each agent type
|
||||
const agentPermissions = {
|
||||
analyst: {
|
||||
fileRegex: "\\.(md|txt)$",
|
||||
description: "Documentation and text files",
|
||||
},
|
||||
pm: {
|
||||
fileRegex: "\\.(md|txt)$",
|
||||
description: "Product documentation",
|
||||
},
|
||||
architect: {
|
||||
fileRegex: "\\.(md|txt|yml|yaml|json)$",
|
||||
description: "Architecture docs and configs",
|
||||
},
|
||||
dev: null, // Full edit access
|
||||
qa: {
|
||||
fileRegex: "\\.(test|spec)\\.(js|ts|jsx|tsx)$|\\.md$",
|
||||
description: "Test files and documentation",
|
||||
},
|
||||
"ux-expert": {
|
||||
fileRegex: "\\.(md|css|scss|html|jsx|tsx)$",
|
||||
description: "Design-related files",
|
||||
},
|
||||
po: {
|
||||
fileRegex: "\\.(md|txt)$",
|
||||
description: "Story and requirement docs",
|
||||
},
|
||||
sm: {
|
||||
fileRegex: "\\.(md|txt)$",
|
||||
description: "Process and planning docs",
|
||||
},
|
||||
"bmad-orchestrator": null, // Full edit access
|
||||
"bmad-master": null, // Full edit access
|
||||
};
|
||||
// Load dynamic agent permissions from configuration
|
||||
const config = await this.loadIdeAgentConfig();
|
||||
const agentPermissions = config['roo-permissions'] || {};
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Skip if already exists
|
||||
@@ -293,12 +325,9 @@ class IdeSetup {
|
||||
}
|
||||
|
||||
// Read agent file to extract all information
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
|
||||
// Extract YAML content
|
||||
@@ -324,7 +353,9 @@ class IdeSetup {
|
||||
newModesContent += ` name: '${icon} ${title}'\n`;
|
||||
newModesContent += ` roleDefinition: ${roleDefinition}\n`;
|
||||
newModesContent += ` whenToUse: ${whenToUse}\n`;
|
||||
newModesContent += ` customInstructions: CRITICAL Read the full YML from .bmad-core/agents/${agentId}.md start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`;
|
||||
// Get relative path from installDir to agent file
|
||||
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
||||
newModesContent += ` customInstructions: CRITICAL Read the full YML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`;
|
||||
newModesContent += ` groups:\n`;
|
||||
newModesContent += ` - read\n`;
|
||||
|
||||
@@ -369,28 +400,15 @@ class IdeSetup {
|
||||
|
||||
await fileManager.ensureDirectory(clineRulesDir);
|
||||
|
||||
// Define agent order for numeric prefixes
|
||||
const agentOrder = {
|
||||
'bmad-master': 1,
|
||||
'bmad-orchestrator': 2,
|
||||
'pm': 3,
|
||||
'analyst': 4,
|
||||
'architect': 5,
|
||||
'po': 6,
|
||||
'sm': 7,
|
||||
'dev': 8,
|
||||
'qa': 9,
|
||||
'ux-expert': 10
|
||||
};
|
||||
// Load dynamic agent ordering from configuration
|
||||
const config = await this.loadIdeAgentConfig();
|
||||
const agentOrder = config['cline-order'] || {};
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
// Find the agent file
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
|
||||
// Get numeric prefix for ordering
|
||||
@@ -418,7 +436,8 @@ class IdeSetup {
|
||||
mdContent += `- Always maintain consistency with project documentation in .bmad-core/\n`;
|
||||
mdContent += `- Follow the agent's specific guidelines and constraints\n`;
|
||||
mdContent += `- Update relevant project files when making changes\n`;
|
||||
mdContent += `- Reference the complete agent definition in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md)\n\n`;
|
||||
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
||||
mdContent += `- Reference the complete agent definition in [${relativePath}](${relativePath})\n\n`;
|
||||
mdContent += "## Usage\n\n";
|
||||
mdContent += `Type \`@${agentId}\` to activate this ${await this.getAgentTitle(agentId, installDir)} persona.\n`;
|
||||
|
||||
@@ -444,12 +463,9 @@ class IdeSetup {
|
||||
|
||||
for (const agentId of agents) {
|
||||
// Find the source agent file
|
||||
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
||||
if (!(await fileManager.pathExists(agentPath))) {
|
||||
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
||||
}
|
||||
const agentPath = await this.findAgentPath(agentId, installDir);
|
||||
|
||||
if (await fileManager.pathExists(agentPath)) {
|
||||
if (agentPath) {
|
||||
const agentContent = await fileManager.readFile(agentPath);
|
||||
const contextFilePath = path.join(agentsContextDir, `${agentId}.md`);
|
||||
|
||||
|
||||
@@ -817,7 +817,7 @@ class Installer {
|
||||
continue;
|
||||
}
|
||||
|
||||
const expansionPackDir = path.dirname(pack.manifestPath);
|
||||
const expansionPackDir = pack.packPath;
|
||||
|
||||
// Create dedicated dot folder for this expansion pack
|
||||
const expansionDotFolder = path.join(installDir, `.${packId}`);
|
||||
@@ -860,10 +860,22 @@ class Installer {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy manifest to the expansion pack's dot folder
|
||||
const manifestDestPath = path.join(expansionDotFolder, 'manifest.yml');
|
||||
if (await fileManager.copyFile(pack.manifestPath, manifestDestPath)) {
|
||||
installedFiles.push(path.join(`.${packId}`, 'manifest.yml'));
|
||||
// Copy config.yml
|
||||
const configPath = path.join(expansionPackDir, 'config.yml');
|
||||
if (await fileManager.pathExists(configPath)) {
|
||||
const configDestPath = path.join(expansionDotFolder, 'config.yml');
|
||||
if (await fileManager.copyFile(configPath, configDestPath)) {
|
||||
installedFiles.push(path.join(`.${packId}`, 'config.yml'));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy README if it exists
|
||||
const readmePath = path.join(expansionPackDir, 'README.md');
|
||||
if (await fileManager.pathExists(readmePath)) {
|
||||
const readmeDestPath = path.join(expansionDotFolder, 'README.md');
|
||||
if (await fileManager.copyFile(readmePath, readmeDestPath)) {
|
||||
installedFiles.push(path.join(`.${packId}`, 'README.md'));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy common/ items to expansion pack folder
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bmad-method",
|
||||
"version": "4.18.0",
|
||||
"version": "4.19.0",
|
||||
"description": "BMAD Method installer - AI-powered Agile development framework",
|
||||
"main": "lib/installer.js",
|
||||
"bin": {
|
||||
|
||||
Reference in New Issue
Block a user