mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-17 17:55:34 +00:00
agents now are not duplicated and isntead cli commmands load from installed agent files
This commit is contained in:
parent
7eb52520fa
commit
f49a4731e7
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Auggie CLI setup handler
|
||||
@ -27,8 +28,11 @@ class AuggieSetup extends BaseIdeSetup {
|
||||
// Clean up old BMAD installation first
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only)
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only)
|
||||
const tasks = await this.getTasks(bmadDir, true);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
@ -44,13 +48,10 @@ class AuggieSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(toolsDir);
|
||||
await this.ensureDir(workflowsDir);
|
||||
|
||||
// Install agents
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const commandContent = await this.createAgentCommand(agent, content);
|
||||
|
||||
const targetPath = path.join(agentsDir, `${agent.module}-${agent.name}.md`);
|
||||
await this.writeFile(targetPath, commandContent);
|
||||
// Install agent launchers
|
||||
for (const artifact of agentArtifacts) {
|
||||
const targetPath = path.join(agentsDir, `${artifact.module}-${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, artifact.content);
|
||||
}
|
||||
|
||||
// Install tasks
|
||||
@ -80,10 +81,10 @@ class AuggieSetup extends BaseIdeSetup {
|
||||
await this.writeFile(targetPath, commandContent);
|
||||
}
|
||||
|
||||
const totalInstalled = agents.length + tasks.length + tools.length + workflows.length;
|
||||
const totalInstalled = agentArtifacts.length + tasks.length + tools.length + workflows.length;
|
||||
|
||||
console.log(chalk.green(`✓ ${this.name} configured:`));
|
||||
console.log(chalk.dim(` - ${agents.length} agents installed`));
|
||||
console.log(chalk.dim(` - ${agentArtifacts.length} agents installed`));
|
||||
console.log(chalk.dim(` - ${tasks.length} tasks installed`));
|
||||
console.log(chalk.dim(` - ${tools.length} tools installed`));
|
||||
console.log(chalk.dim(` - ${workflows.length} workflows installed`));
|
||||
@ -92,42 +93,13 @@ class AuggieSetup extends BaseIdeSetup {
|
||||
|
||||
return {
|
||||
success: true,
|
||||
agents: agents.length,
|
||||
agents: agentArtifacts.length,
|
||||
tasks: tasks.length,
|
||||
tools: tools.length,
|
||||
workflows: workflows.length,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create agent command content
|
||||
*/
|
||||
async createAgentCommand(agent, content) {
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
|
||||
// Extract description from agent if available
|
||||
const whenToUseMatch = content.match(/whenToUse="([^"]+)"/);
|
||||
const description = whenToUseMatch ? whenToUseMatch[1] : `Activate the ${title} agent`;
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
|
||||
return `---
|
||||
description: "${description}"
|
||||
---
|
||||
|
||||
# ${title} Agent
|
||||
|
||||
${activationHeader}
|
||||
|
||||
${content}
|
||||
|
||||
## Module
|
||||
BMAD ${agent.module.toUpperCase()} module
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create task command content
|
||||
*/
|
||||
|
||||
@ -4,6 +4,7 @@ const chalk = require('chalk');
|
||||
const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/project-root');
|
||||
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
|
||||
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
const {
|
||||
loadModuleInjectionConfig,
|
||||
shouldApplyInjection,
|
||||
@ -117,33 +118,24 @@ class ClaudeCodeSetup extends BaseIdeSetup {
|
||||
|
||||
await this.ensureDir(bmadCommandsDir);
|
||||
|
||||
// Get agents from INSTALLED bmad/ directory
|
||||
// Base installer has already built .md files from .agent.yaml sources
|
||||
const agents = await getAgentsFromBmad(bmadDir, options.selectedModules || []);
|
||||
// Generate agent launchers using AgentCommandGenerator
|
||||
// This creates small launcher files that reference the actual agents in .bmad/
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts, counts: agentCounts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Create directories for each module (including standalone)
|
||||
// Create directories for each module
|
||||
const modules = new Set();
|
||||
for (const item of agents) modules.add(item.module);
|
||||
for (const artifact of agentArtifacts) {
|
||||
modules.add(artifact.module);
|
||||
}
|
||||
|
||||
for (const module of modules) {
|
||||
await this.ensureDir(path.join(bmadCommandsDir, module));
|
||||
await this.ensureDir(path.join(bmadCommandsDir, module, 'agents'));
|
||||
}
|
||||
|
||||
// Copy agents from bmad/ to .claude/commands/
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const sourcePath = agent.path;
|
||||
const targetPath = path.join(bmadCommandsDir, agent.module, 'agents', `${agent.name}.md`);
|
||||
|
||||
const content = await this.readAndProcess(sourcePath, {
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
});
|
||||
|
||||
await this.writeFile(targetPath, content);
|
||||
agentCount++;
|
||||
}
|
||||
// Write agent launcher files
|
||||
const agentCount = await agentGen.writeAgentLaunchers(bmadCommandsDir, agentArtifacts);
|
||||
|
||||
// Process Claude Code specific injections for installed modules
|
||||
// Use pre-collected configuration if available, or skip if already configured
|
||||
|
||||
@ -3,6 +3,7 @@ const fs = require('fs-extra');
|
||||
const chalk = require('chalk');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
const { getAgentsFromBmad, getTasksFromBmad } = require('./shared/bmad-artifacts');
|
||||
|
||||
/**
|
||||
@ -88,23 +89,19 @@ class ClineSetup extends BaseIdeSetup {
|
||||
const selectedModules = options.selectedModules || [];
|
||||
const artifacts = [];
|
||||
|
||||
// Get agents
|
||||
const agents = await getAgentsFromBmad(bmadDir, selectedModules);
|
||||
for (const agent of agents) {
|
||||
const content = await this.readAndProcessWithProject(
|
||||
agent.path,
|
||||
{
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
},
|
||||
projectDir,
|
||||
);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, selectedModules);
|
||||
|
||||
// Process agent launchers with project-specific paths
|
||||
for (const agentArtifact of agentArtifacts) {
|
||||
const content = agentArtifact.content;
|
||||
|
||||
artifacts.push({
|
||||
type: 'agent',
|
||||
module: agent.module,
|
||||
sourcePath: agent.path,
|
||||
relativePath: path.join(agent.module, 'agents', `${agent.name}.md`),
|
||||
module: agentArtifact.module,
|
||||
sourcePath: agentArtifact.sourcePath,
|
||||
relativePath: agentArtifact.relativePath,
|
||||
content,
|
||||
});
|
||||
}
|
||||
@ -138,7 +135,7 @@ class ClineSetup extends BaseIdeSetup {
|
||||
return {
|
||||
artifacts,
|
||||
counts: {
|
||||
agents: agents.length,
|
||||
agents: agentArtifacts.length,
|
||||
tasks: tasks.length,
|
||||
workflows: workflowCounts.commands,
|
||||
workflowLaunchers: workflowCounts.launchers,
|
||||
|
||||
@ -4,7 +4,8 @@ const os = require('node:os');
|
||||
const chalk = require('chalk');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
|
||||
const { getAgentsFromBmad, getTasksFromBmad } = require('./shared/bmad-artifacts');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
const { getTasksFromBmad } = require('./shared/bmad-artifacts');
|
||||
|
||||
/**
|
||||
* Codex setup handler (CLI mode)
|
||||
@ -92,23 +93,17 @@ class CodexSetup extends BaseIdeSetup {
|
||||
const selectedModules = options.selectedModules || [];
|
||||
const artifacts = [];
|
||||
|
||||
const agents = await getAgentsFromBmad(bmadDir, selectedModules);
|
||||
for (const agent of agents) {
|
||||
const content = await this.readAndProcessWithProject(
|
||||
agent.path,
|
||||
{
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
},
|
||||
projectDir,
|
||||
);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, selectedModules);
|
||||
|
||||
for (const artifact of agentArtifacts) {
|
||||
artifacts.push({
|
||||
type: 'agent',
|
||||
module: agent.module,
|
||||
sourcePath: agent.path,
|
||||
relativePath: path.join(agent.module, 'agents', `${agent.name}.md`),
|
||||
content,
|
||||
module: artifact.module,
|
||||
sourcePath: artifact.sourcePath,
|
||||
relativePath: artifact.relativePath,
|
||||
content: artifact.content,
|
||||
});
|
||||
}
|
||||
|
||||
@ -139,7 +134,7 @@ class CodexSetup extends BaseIdeSetup {
|
||||
return {
|
||||
artifacts,
|
||||
counts: {
|
||||
agents: agents.length,
|
||||
agents: agentArtifacts.length,
|
||||
tasks: tasks.length,
|
||||
workflows: workflowCounts.commands,
|
||||
workflowLaunchers: workflowCounts.launchers,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Crush IDE setup handler
|
||||
@ -28,14 +29,17 @@ class CrushSetup extends BaseIdeSetup {
|
||||
|
||||
await this.ensureDir(commandsDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only)
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only)
|
||||
const tasks = await this.getTasks(bmadDir, true);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
|
||||
// Organize by module
|
||||
const agentCount = await this.organizeByModule(commandsDir, agents, tasks, tools, workflows, projectDir);
|
||||
const agentCount = await this.organizeByModule(commandsDir, agentArtifacts, tasks, tools, workflows, projectDir);
|
||||
|
||||
console.log(chalk.green(`✓ ${this.name} configured:`));
|
||||
console.log(chalk.dim(` - ${agentCount.agents} agent commands created`));
|
||||
@ -54,10 +58,10 @@ class CrushSetup extends BaseIdeSetup {
|
||||
/**
|
||||
* Organize commands by module
|
||||
*/
|
||||
async organizeByModule(commandsDir, agents, tasks, tools, workflows, projectDir) {
|
||||
async organizeByModule(commandsDir, agentArtifacts, tasks, tools, workflows, projectDir) {
|
||||
// Get unique modules
|
||||
const modules = new Set();
|
||||
for (const agent of agents) modules.add(agent.module);
|
||||
for (const artifact of agentArtifacts) modules.add(artifact.module);
|
||||
for (const task of tasks) modules.add(task.module);
|
||||
for (const tool of tools) modules.add(tool.module);
|
||||
for (const workflow of workflows) modules.add(workflow.module);
|
||||
@ -80,13 +84,11 @@ class CrushSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(moduleToolsDir);
|
||||
await this.ensureDir(moduleWorkflowsDir);
|
||||
|
||||
// Copy module-specific agents
|
||||
const moduleAgents = agents.filter((a) => a.module === module);
|
||||
for (const agent of moduleAgents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const commandContent = await this.createAgentCommand(agent, content, projectDir);
|
||||
const targetPath = path.join(moduleAgentsDir, `${agent.name}.md`);
|
||||
await this.writeFile(targetPath, commandContent);
|
||||
// Write module-specific agent launchers
|
||||
const moduleAgents = agentArtifacts.filter((a) => a.module === module);
|
||||
for (const artifact of moduleAgents) {
|
||||
const targetPath = path.join(moduleAgentsDir, `${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, artifact.content);
|
||||
agentCount++;
|
||||
}
|
||||
|
||||
@ -129,44 +131,6 @@ class CrushSetup extends BaseIdeSetup {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create agent command content
|
||||
*/
|
||||
async createAgentCommand(agent, content, projectDir) {
|
||||
// Extract metadata
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
|
||||
const iconMatch = content.match(/icon="([^"]+)"/);
|
||||
const icon = iconMatch ? iconMatch[1] : '🤖';
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
|
||||
// Get relative path
|
||||
const relativePath = path.relative(projectDir, agent.path).replaceAll('\\', '/');
|
||||
|
||||
let commandContent = `# /${agent.name} Command
|
||||
|
||||
${activationHeader}
|
||||
|
||||
## ${icon} ${title} Agent
|
||||
|
||||
${content}
|
||||
|
||||
## Command Usage
|
||||
|
||||
This command activates the ${title} agent from the BMAD ${agent.module.toUpperCase()} module.
|
||||
|
||||
## File Reference
|
||||
|
||||
Complete agent definition: [${relativePath}](${relativePath})
|
||||
|
||||
`;
|
||||
|
||||
return commandContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create task command content
|
||||
*/
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Cursor IDE setup handler
|
||||
@ -45,8 +46,14 @@ class CursorSetup extends BaseIdeSetup {
|
||||
|
||||
await this.ensureDir(bmadRulesDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only)
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers first
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Convert artifacts to agent format for index creation
|
||||
const agents = agentArtifacts.map((a) => ({ module: a.module, name: a.name }));
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only)
|
||||
const tasks = await this.getTasks(bmadDir, true);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
@ -63,15 +70,16 @@ class CursorSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(path.join(bmadRulesDir, module, 'workflows'));
|
||||
}
|
||||
|
||||
// Process and copy agents
|
||||
// Process and write agent launchers with MDC format
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readAndProcess(agent.path, {
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
for (const artifact of agentArtifacts) {
|
||||
// Add MDC metadata header to launcher (but don't call processContent which adds activation headers)
|
||||
const content = this.wrapLauncherWithMDC(artifact.content, {
|
||||
module: artifact.module,
|
||||
name: artifact.name,
|
||||
});
|
||||
|
||||
const targetPath = path.join(bmadRulesDir, agent.module, 'agents', `${agent.name}.mdc`);
|
||||
const targetPath = path.join(bmadRulesDir, artifact.module, 'agents', `${artifact.name}.mdc`);
|
||||
|
||||
await this.writeFile(targetPath, content);
|
||||
agentCount++;
|
||||
@ -311,6 +319,34 @@ alwaysApply: false
|
||||
// Add the MDC header to the processed content
|
||||
return mdcHeader + processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap launcher content with MDC metadata (without base processing)
|
||||
* Launchers are already complete and should not have activation headers injected
|
||||
*/
|
||||
wrapLauncherWithMDC(launcherContent, metadata = {}) {
|
||||
// Strip the launcher's frontmatter - we'll replace it with MDC frontmatter
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
const contentWithoutFrontmatter = launcherContent.replace(frontmatterRegex, '');
|
||||
|
||||
// Extract metadata from launcher frontmatter for MDC description
|
||||
const nameMatch = launcherContent.match(/name:\s*"([^"]+)"/);
|
||||
const name = nameMatch ? nameMatch[1] : metadata.name;
|
||||
|
||||
const description = `BMAD ${metadata.module.toUpperCase()} Agent: ${name}`;
|
||||
|
||||
// Create MDC metadata header
|
||||
const mdcHeader = `---
|
||||
description: ${description}
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
`;
|
||||
|
||||
// Return MDC header + launcher content (without its original frontmatter)
|
||||
return mdcHeader + contentWithoutFrontmatter;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { CursorSetup };
|
||||
|
||||
@ -3,6 +3,7 @@ const fs = require('fs-extra');
|
||||
const yaml = require('js-yaml');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Gemini CLI setup handler
|
||||
@ -63,22 +64,24 @@ class GeminiSetup extends BaseIdeSetup {
|
||||
// Clean up any existing BMAD files before reinstalling
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Get agents and tasks
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Get tasks
|
||||
const tasks = await this.getTasks(bmadDir);
|
||||
|
||||
// Install agents as TOML files with bmad- prefix (flat structure)
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const tomlContent = await this.createAgentToml(agent, content);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const tomlContent = await this.createAgentLauncherToml(artifact);
|
||||
|
||||
// Flat structure: bmad-agent-{module}-{name}.toml
|
||||
const tomlPath = path.join(commandsDir, `bmad-agent-${agent.module}-${agent.name}.toml`);
|
||||
const tomlPath = path.join(commandsDir, `bmad-agent-${artifact.module}-${artifact.name}.toml`);
|
||||
await this.writeFile(tomlPath, tomlContent);
|
||||
agentCount++;
|
||||
|
||||
console.log(chalk.green(` ✓ Added agent: /bmad:agents:${agent.module}:${agent.name}`));
|
||||
console.log(chalk.green(` ✓ Added agent: /bmad:agents:${artifact.module}:${artifact.name}`));
|
||||
}
|
||||
|
||||
// Install tasks as TOML files with bmad- prefix (flat structure)
|
||||
@ -109,6 +112,28 @@ class GeminiSetup extends BaseIdeSetup {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create agent launcher TOML content from artifact
|
||||
*/
|
||||
async createAgentLauncherToml(artifact) {
|
||||
// Strip frontmatter from launcher content
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
const contentWithoutFrontmatter = artifact.content.replace(frontmatterRegex, '').trim();
|
||||
|
||||
// Extract title from launcher frontmatter
|
||||
const titleMatch = artifact.content.match(/description:\s*"([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(artifact.name);
|
||||
|
||||
// Create TOML wrapper around launcher content (without frontmatter)
|
||||
const description = `BMAD ${artifact.module.toUpperCase()} Agent: ${title}`;
|
||||
|
||||
return `description = "${description}"
|
||||
prompt = """
|
||||
${contentWithoutFrontmatter}
|
||||
"""
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create agent TOML content using template
|
||||
*/
|
||||
|
||||
@ -2,6 +2,7 @@ const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const inquirer = require('inquirer');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* GitHub Copilot setup handler
|
||||
@ -104,21 +105,22 @@ class GitHubCopilotSetup extends BaseIdeSetup {
|
||||
// Clean up any existing BMAD files before reinstalling
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Get agents
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Create chat mode files with bmad- prefix
|
||||
let modeCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const chatmodeContent = await this.createChatmodeContent(agent, content);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const content = artifact.content;
|
||||
const chatmodeContent = await this.createChatmodeContent({ module: artifact.module, name: artifact.name }, content);
|
||||
|
||||
// Use bmad- prefix: bmad-agent-{module}-{name}.chatmode.md
|
||||
const targetPath = path.join(chatmodesDir, `bmad-agent-${agent.module}-${agent.name}.chatmode.md`);
|
||||
const targetPath = path.join(chatmodesDir, `bmad-agent-${artifact.module}-${artifact.name}.chatmode.md`);
|
||||
await this.writeFile(targetPath, chatmodeContent);
|
||||
modeCount++;
|
||||
|
||||
console.log(chalk.green(` ✓ Created chat mode: bmad-agent-${agent.module}-${agent.name}`));
|
||||
console.log(chalk.green(` ✓ Created chat mode: bmad-agent-${artifact.module}-${artifact.name}`));
|
||||
}
|
||||
|
||||
console.log(chalk.green(`✓ ${this.name} configured:`));
|
||||
@ -207,21 +209,17 @@ class GitHubCopilotSetup extends BaseIdeSetup {
|
||||
* Create chat mode content
|
||||
*/
|
||||
async createChatmodeContent(agent, content) {
|
||||
// Extract metadata
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
// Extract metadata from launcher frontmatter if present
|
||||
const descMatch = content.match(/description:\s*"([^"]+)"/);
|
||||
const title = descMatch ? descMatch[1] : this.formatTitle(agent.name);
|
||||
|
||||
const whenToUseMatch = content.match(/whenToUse="([^"]+)"/);
|
||||
const description = whenToUseMatch ? whenToUseMatch[1] : `Activates the ${title} agent persona.`;
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
const description = `Activates the ${title} agent persona.`;
|
||||
|
||||
// Strip any existing frontmatter from the content
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
let cleanContent = content;
|
||||
if (frontmatterRegex.test(content)) {
|
||||
cleanContent = content.replace(frontmatterRegex, '');
|
||||
cleanContent = content.replace(frontmatterRegex, '').trim();
|
||||
}
|
||||
|
||||
// Available GitHub Copilot tools (November 2025 - Official VS Code Documentation)
|
||||
@ -258,8 +256,6 @@ tools: ${JSON.stringify(tools)}
|
||||
|
||||
# ${title} Agent
|
||||
|
||||
${activationHeader}
|
||||
|
||||
${cleanContent}
|
||||
|
||||
`;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* iFlow CLI setup handler
|
||||
@ -31,21 +32,23 @@ class IFlowSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(agentsDir);
|
||||
await this.ensureDir(tasksDir);
|
||||
|
||||
// Get agents and tasks
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
const tasks = await this.getTasks(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Setup agents as commands
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const commandContent = await this.createAgentCommand(agent, content);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const commandContent = await this.createAgentCommand(artifact);
|
||||
|
||||
const targetPath = path.join(agentsDir, `${agent.module}-${agent.name}.md`);
|
||||
const targetPath = path.join(agentsDir, `${artifact.module}-${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, commandContent);
|
||||
agentCount++;
|
||||
}
|
||||
|
||||
// Get tasks
|
||||
const tasks = await this.getTasks(bmadDir);
|
||||
|
||||
// Setup tasks as commands
|
||||
let taskCount = 0;
|
||||
for (const task of tasks) {
|
||||
@ -72,29 +75,9 @@ class IFlowSetup extends BaseIdeSetup {
|
||||
/**
|
||||
* Create agent command content
|
||||
*/
|
||||
async createAgentCommand(agent, content) {
|
||||
// Extract metadata
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
|
||||
let commandContent = `# /${agent.name} Command
|
||||
|
||||
${activationHeader}
|
||||
|
||||
## ${title} Agent
|
||||
|
||||
${content}
|
||||
|
||||
## Usage
|
||||
|
||||
This command activates the ${title} agent from the BMAD ${agent.module.toUpperCase()} module.
|
||||
|
||||
`;
|
||||
|
||||
return commandContent;
|
||||
async createAgentCommand(artifact) {
|
||||
// The launcher content is already complete - just return it as-is
|
||||
return artifact.content;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* KiloCode IDE setup handler
|
||||
@ -36,16 +37,17 @@ class KiloSetup extends BaseIdeSetup {
|
||||
console.log(chalk.yellow(`Found existing .kilocodemodes file with ${existingModes.length} modes`));
|
||||
}
|
||||
|
||||
// Get agents
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Create modes content
|
||||
let newModesContent = '';
|
||||
let addedCount = 0;
|
||||
let skippedCount = 0;
|
||||
|
||||
for (const agent of agents) {
|
||||
const slug = `bmad-${agent.module}-${agent.name}`;
|
||||
for (const artifact of agentArtifacts) {
|
||||
const slug = `bmad-${artifact.module}-${artifact.name}`;
|
||||
|
||||
// Skip if already exists
|
||||
if (existingModes.includes(slug)) {
|
||||
@ -54,8 +56,7 @@ class KiloSetup extends BaseIdeSetup {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = await this.readFile(agent.path);
|
||||
const modeEntry = await this.createModeEntry(agent, content, projectDir);
|
||||
const modeEntry = await this.createModeEntry(artifact, projectDir);
|
||||
|
||||
newModesContent += modeEntry;
|
||||
addedCount++;
|
||||
@ -90,30 +91,30 @@ class KiloSetup extends BaseIdeSetup {
|
||||
/**
|
||||
* Create a mode entry for an agent
|
||||
*/
|
||||
async createModeEntry(agent, content, projectDir) {
|
||||
// Extract metadata
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
async createModeEntry(artifact, projectDir) {
|
||||
// Extract metadata from launcher content
|
||||
const titleMatch = artifact.content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(artifact.name);
|
||||
|
||||
const iconMatch = content.match(/icon="([^"]+)"/);
|
||||
const iconMatch = artifact.content.match(/icon="([^"]+)"/);
|
||||
const icon = iconMatch ? iconMatch[1] : '🤖';
|
||||
|
||||
const whenToUseMatch = content.match(/whenToUse="([^"]+)"/);
|
||||
const whenToUseMatch = artifact.content.match(/whenToUse="([^"]+)"/);
|
||||
const whenToUse = whenToUseMatch ? whenToUseMatch[1] : `Use for ${title} tasks`;
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
|
||||
const roleDefinitionMatch = content.match(/roleDefinition="([^"]+)"/);
|
||||
const roleDefinitionMatch = artifact.content.match(/roleDefinition="([^"]+)"/);
|
||||
const roleDefinition = roleDefinitionMatch
|
||||
? roleDefinitionMatch[1]
|
||||
: `You are a ${title} specializing in ${title.toLowerCase()} tasks.`;
|
||||
|
||||
// Get relative path
|
||||
const relativePath = path.relative(projectDir, agent.path).replaceAll('\\', '/');
|
||||
const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
|
||||
|
||||
// Build mode entry (KiloCode uses same schema as Roo)
|
||||
const slug = `bmad-${agent.module}-${agent.name}`;
|
||||
const slug = `bmad-${artifact.module}-${artifact.name}`;
|
||||
let modeEntry = ` - slug: ${slug}\n`;
|
||||
modeEntry += ` name: '${icon} ${title}'\n`;
|
||||
modeEntry += ` roleDefinition: ${roleDefinition}\n`;
|
||||
|
||||
@ -6,8 +6,7 @@ const yaml = require('js-yaml');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
|
||||
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
|
||||
|
||||
const { getAgentsFromBmad } = require('./shared/bmad-artifacts');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* OpenCode IDE setup handler
|
||||
@ -33,20 +32,17 @@ class OpenCodeSetup extends BaseIdeSetup {
|
||||
// Clean up any existing BMAD files before reinstalling
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Install primary agents with flat naming: bmad-agent-{module}-{name}.md
|
||||
// OpenCode agents go in the agent folder (not command folder)
|
||||
const agents = await getAgentsFromBmad(bmadDir, options.selectedModules || []);
|
||||
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const processed = await this.readAndProcess(agent.path, {
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
});
|
||||
|
||||
const agentContent = await this.createAgentContent(processed, agent);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const agentContent = artifact.content;
|
||||
// Flat structure in agent folder: bmad-agent-{module}-{name}.md
|
||||
const targetPath = path.join(agentsBaseDir, `bmad-agent-${agent.module}-${agent.name}.md`);
|
||||
const targetPath = path.join(agentsBaseDir, `bmad-agent-${artifact.module}-${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, agentContent);
|
||||
agentCount++;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { getAgentsFromBmad, getTasksFromBmad } = require('./shared/bmad-artifacts');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Qwen Code setup handler
|
||||
@ -37,15 +38,18 @@ class QwenSetup extends BaseIdeSetup {
|
||||
// Clean up old configuration if exists
|
||||
await this.cleanupOldConfig(qwenDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only for tools/workflows)
|
||||
const agents = await getAgentsFromBmad(bmadDir, options.selectedModules || []);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only for tools/workflows)
|
||||
const tasks = await getTasksFromBmad(bmadDir, options.selectedModules || []);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
|
||||
// Create directories for each module (including standalone)
|
||||
const modules = new Set();
|
||||
for (const item of [...agents, ...tasks, ...tools, ...workflows]) modules.add(item.module);
|
||||
for (const item of [...agentArtifacts, ...tasks, ...tools, ...workflows]) modules.add(item.module);
|
||||
|
||||
for (const module of modules) {
|
||||
await this.ensureDir(path.join(bmadCommandsDir, module));
|
||||
@ -55,20 +59,21 @@ class QwenSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(path.join(bmadCommandsDir, module, 'workflows'));
|
||||
}
|
||||
|
||||
// Create TOML files for each agent
|
||||
// Create TOML files for each agent launcher
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readAndProcess(agent.path, {
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
for (const artifact of agentArtifacts) {
|
||||
// Convert markdown launcher content to TOML format
|
||||
const tomlContent = this.processAgentLauncherContent(artifact.content, {
|
||||
module: artifact.module,
|
||||
name: artifact.name,
|
||||
});
|
||||
|
||||
const targetPath = path.join(bmadCommandsDir, agent.module, 'agents', `${agent.name}.toml`);
|
||||
const targetPath = path.join(bmadCommandsDir, artifact.module, 'agents', `${artifact.name}.toml`);
|
||||
|
||||
await this.writeFile(targetPath, content);
|
||||
await this.writeFile(targetPath, tomlContent);
|
||||
|
||||
agentCount++;
|
||||
console.log(chalk.green(` ✓ Added agent: /bmad:${agent.module}:agents:${agent.name}`));
|
||||
console.log(chalk.green(` ✓ Added agent: /bmad:${artifact.module}:agents:${artifact.name}`));
|
||||
}
|
||||
|
||||
// Create TOML files for each task
|
||||
@ -204,6 +209,29 @@ class QwenSetup extends BaseIdeSetup {
|
||||
return this.processContent(content, metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process agent launcher content and convert to TOML format
|
||||
* @param {string} launcherContent - Launcher markdown content
|
||||
* @param {Object} metadata - File metadata
|
||||
* @returns {string} TOML formatted content
|
||||
*/
|
||||
processAgentLauncherContent(launcherContent, metadata = {}) {
|
||||
// Strip frontmatter from launcher content
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
const contentWithoutFrontmatter = launcherContent.replace(frontmatterRegex, '');
|
||||
|
||||
// Extract title for TOML description
|
||||
const titleMatch = launcherContent.match(/description:\s*"([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : metadata.name;
|
||||
|
||||
// Create TOML with launcher content (without frontmatter)
|
||||
return `description = "BMAD ${metadata.module.toUpperCase()} Agent: ${title}"
|
||||
prompt = """
|
||||
${contentWithoutFrontmatter.trim()}
|
||||
"""
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override processContent to add TOML metadata header for Qwen
|
||||
* @param {string} content - File content
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Roo IDE setup handler
|
||||
@ -58,8 +59,9 @@ class RooSetup extends BaseIdeSetup {
|
||||
console.log(chalk.yellow(`Found existing .roomodes file with ${existingModes.length} modes`));
|
||||
}
|
||||
|
||||
// Get agents
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers (though Roo will reference the actual .bmad agents)
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Always use 'all' permissions - users can customize in .roomodes file
|
||||
const permissionChoice = 'all';
|
||||
@ -69,8 +71,8 @@ class RooSetup extends BaseIdeSetup {
|
||||
let addedCount = 0;
|
||||
let skippedCount = 0;
|
||||
|
||||
for (const agent of agents) {
|
||||
const slug = `bmad-${agent.module}-${agent.name}`;
|
||||
for (const artifact of agentArtifacts) {
|
||||
const slug = `bmad-${artifact.module}-${artifact.name}`;
|
||||
|
||||
// Skip if already exists
|
||||
if (existingModes.includes(slug)) {
|
||||
@ -79,8 +81,17 @@ class RooSetup extends BaseIdeSetup {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = await this.readFile(agent.path);
|
||||
const modeEntry = await this.createModeEntry(agent, content, permissionChoice, projectDir);
|
||||
// Read the actual agent file from .bmad for metadata extraction
|
||||
const agentPath = path.join(bmadDir, artifact.module, 'agents', `${artifact.name}.md`);
|
||||
const content = await this.readFile(agentPath);
|
||||
|
||||
// Create mode entry that references the actual .bmad agent
|
||||
const modeEntry = await this.createModeEntry(
|
||||
{ module: artifact.module, name: artifact.name, path: agentPath },
|
||||
content,
|
||||
permissionChoice,
|
||||
projectDir,
|
||||
);
|
||||
|
||||
newModesContent += modeEntry;
|
||||
addedCount++;
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const chalk = require('chalk');
|
||||
|
||||
/**
|
||||
* Generates launcher command files for each agent
|
||||
* Similar to WorkflowCommandGenerator but for agents
|
||||
*/
|
||||
class AgentCommandGenerator {
|
||||
constructor(bmadFolderName = 'bmad') {
|
||||
this.templatePath = path.join(__dirname, '../templates/agent-command-template.md');
|
||||
this.bmadFolderName = bmadFolderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect agent artifacts for IDE installation
|
||||
* @param {string} bmadDir - BMAD installation directory
|
||||
* @param {Array} selectedModules - Modules to include
|
||||
* @returns {Object} Artifacts array with metadata
|
||||
*/
|
||||
async collectAgentArtifacts(bmadDir, selectedModules = []) {
|
||||
const { getAgentsFromBmad } = require('./bmad-artifacts');
|
||||
|
||||
// Get agents from INSTALLED bmad/ directory
|
||||
const agents = await getAgentsFromBmad(bmadDir, selectedModules);
|
||||
|
||||
const artifacts = [];
|
||||
|
||||
for (const agent of agents) {
|
||||
const launcherContent = await this.generateLauncherContent(agent);
|
||||
artifacts.push({
|
||||
type: 'agent-launcher',
|
||||
module: agent.module,
|
||||
name: agent.name,
|
||||
relativePath: path.join(agent.module, 'agents', `${agent.name}.md`),
|
||||
content: launcherContent,
|
||||
sourcePath: agent.path,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
artifacts,
|
||||
counts: {
|
||||
agents: agents.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate launcher content for an agent
|
||||
* @param {Object} agent - Agent metadata
|
||||
* @returns {string} Launcher file content
|
||||
*/
|
||||
async generateLauncherContent(agent) {
|
||||
// Load the template
|
||||
const template = await fs.readFile(this.templatePath, 'utf8');
|
||||
|
||||
// Replace template variables
|
||||
return template
|
||||
.replaceAll('{{name}}', agent.name)
|
||||
.replaceAll('{{module}}', agent.module)
|
||||
.replaceAll('{{description}}', agent.description || `${agent.name} agent`)
|
||||
.replaceAll('{bmad_folder}', this.bmadFolderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write agent launcher artifacts to IDE commands directory
|
||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||
* @param {Array} artifacts - Agent launcher artifacts
|
||||
* @returns {number} Count of launchers written
|
||||
*/
|
||||
async writeAgentLaunchers(baseCommandsDir, artifacts) {
|
||||
let writtenCount = 0;
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
if (artifact.type === 'agent-launcher') {
|
||||
const moduleAgentsDir = path.join(baseCommandsDir, artifact.module, 'agents');
|
||||
await fs.ensureDir(moduleAgentsDir);
|
||||
|
||||
const launcherPath = path.join(moduleAgentsDir, `${artifact.name}.md`);
|
||||
await fs.writeFile(launcherPath, artifact.content);
|
||||
writtenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return writtenCount;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { AgentCommandGenerator };
|
||||
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
||||
|
||||
<agent-activation CRITICAL="TRUE">
|
||||
1. LOAD the FULL agent file from @{bmad_folder}/{{module}}/agents/{{name}}.md
|
||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
||||
3. Execute ALL activation steps exactly as written in the agent file
|
||||
4. Follow the agent's persona and menu system precisely
|
||||
5. Stay in character throughout the session
|
||||
</agent-activation>
|
||||
@ -5,8 +5,8 @@ description: '{{description}}'
|
||||
IT IS CRITICAL THAT YOU FOLLOW THESE STEPS - while staying in character as the current agent persona you may have loaded:
|
||||
|
||||
<steps CRITICAL="TRUE">
|
||||
1. Always LOAD the FULL {project-root}/{bmad_folder}/core/tasks/workflow.xml
|
||||
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config {{workflow_path}}
|
||||
1. Always LOAD the FULL @{bmad_folder}/core/tasks/workflow.xml
|
||||
2. READ its entire contents - this is the CORE OS for EXECUTING the specific workflow-config @{{workflow_path}}
|
||||
3. Pass the yaml path {{workflow_path}} as 'workflow-config' parameter to the workflow.xml instructions
|
||||
4. Follow workflow.xml instructions EXACTLY as written to process and follow the specific workflow config and its instructions
|
||||
5. Save outputs after EACH section when generating any documents from templates
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Trae IDE setup handler
|
||||
@ -30,20 +31,22 @@ class TraeSetup extends BaseIdeSetup {
|
||||
// Clean up any existing BMAD files before reinstalling
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only)
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only)
|
||||
const tasks = await this.getTasks(bmadDir, true);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
|
||||
// Process agents as rules with bmad- prefix
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const processedContent = await this.createAgentRule(agent, content, bmadDir, projectDir);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const processedContent = await this.createAgentRule(artifact, bmadDir, projectDir);
|
||||
|
||||
// Use bmad- prefix: bmad-agent-{module}-{name}.md
|
||||
const targetPath = path.join(rulesDir, `bmad-agent-${agent.module}-${agent.name}.md`);
|
||||
const targetPath = path.join(rulesDir, `bmad-agent-${artifact.module}-${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, processedContent);
|
||||
agentCount++;
|
||||
}
|
||||
@ -108,46 +111,29 @@ class TraeSetup extends BaseIdeSetup {
|
||||
/**
|
||||
* Create rule content for an agent
|
||||
*/
|
||||
async createAgentRule(agent, content, bmadDir, projectDir) {
|
||||
// Extract metadata from agent content
|
||||
const titleMatch = content.match(/title="([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(agent.name);
|
||||
async createAgentRule(artifact, bmadDir, projectDir) {
|
||||
// Strip frontmatter from launcher
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
const contentWithoutFrontmatter = artifact.content.replace(frontmatterRegex, '').trim();
|
||||
|
||||
const iconMatch = content.match(/icon="([^"]+)"/);
|
||||
const icon = iconMatch ? iconMatch[1] : '🤖';
|
||||
|
||||
// Get the activation header from central template
|
||||
const activationHeader = await this.getAgentCommandHeader();
|
||||
|
||||
// Extract YAML content if available
|
||||
const yamlMatch = content.match(/```ya?ml\r?\n([\s\S]*?)```/);
|
||||
const yamlContent = yamlMatch ? yamlMatch[1] : content;
|
||||
// Extract metadata from launcher content
|
||||
const titleMatch = artifact.content.match(/description:\s*"([^"]+)"/);
|
||||
const title = titleMatch ? titleMatch[1] : this.formatTitle(artifact.name);
|
||||
|
||||
// Calculate relative path for reference
|
||||
const relativePath = path.relative(projectDir, agent.path).replaceAll('\\', '/');
|
||||
const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
|
||||
|
||||
let ruleContent = `# ${title} Agent Rule
|
||||
|
||||
This rule is triggered when the user types \`@${agent.name}\` and activates the ${title} agent persona.
|
||||
This rule is triggered when the user types \`@${artifact.name}\` and activates the ${title} agent persona.
|
||||
|
||||
## Agent Activation
|
||||
|
||||
${activationHeader}
|
||||
|
||||
Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:
|
||||
|
||||
\`\`\`yaml
|
||||
${yamlContent}
|
||||
\`\`\`
|
||||
${contentWithoutFrontmatter}
|
||||
|
||||
## File Reference
|
||||
|
||||
The complete agent definition is available in [${relativePath}](${relativePath}).
|
||||
|
||||
## Usage
|
||||
|
||||
When the user types \`@${agent.name}\`, activate this ${title} persona and follow all instructions defined in the YAML configuration above.
|
||||
|
||||
The full agent definition is located at: \`${relativePath}\`
|
||||
`;
|
||||
|
||||
return ruleContent;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const path = require('node:path');
|
||||
const { BaseIdeSetup } = require('./_base-ide');
|
||||
const chalk = require('chalk');
|
||||
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
|
||||
|
||||
/**
|
||||
* Windsurf IDE setup handler
|
||||
@ -31,8 +32,14 @@ class WindsurfSetup extends BaseIdeSetup {
|
||||
// Clean up any existing BMAD workflows before reinstalling
|
||||
await this.cleanup(projectDir);
|
||||
|
||||
// Get agents, tasks, tools, and workflows (standalone only)
|
||||
const agents = await this.getAgents(bmadDir);
|
||||
// Generate agent launchers
|
||||
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
|
||||
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
|
||||
|
||||
// Convert artifacts to agent format for module organization
|
||||
const agents = agentArtifacts.map((a) => ({ module: a.module, name: a.name }));
|
||||
|
||||
// Get tasks, tools, and workflows (standalone only)
|
||||
const tasks = await this.getTasks(bmadDir, true);
|
||||
const tools = await this.getTools(bmadDir, true);
|
||||
const workflows = await this.getWorkflows(bmadDir, true);
|
||||
@ -49,14 +56,13 @@ class WindsurfSetup extends BaseIdeSetup {
|
||||
await this.ensureDir(path.join(bmadWorkflowsDir, module, 'workflows'));
|
||||
}
|
||||
|
||||
// Process agents as workflows with organized structure
|
||||
// Process agent launchers as workflows with organized structure
|
||||
let agentCount = 0;
|
||||
for (const agent of agents) {
|
||||
const content = await this.readFile(agent.path);
|
||||
const processedContent = this.createWorkflowContent(agent, content);
|
||||
for (const artifact of agentArtifacts) {
|
||||
const processedContent = this.createWorkflowContent({ module: artifact.module, name: artifact.name }, artifact.content);
|
||||
|
||||
// Organized path: bmad/module/agents/agent-name.md
|
||||
const targetPath = path.join(bmadWorkflowsDir, agent.module, 'agents', `${agent.name}.md`);
|
||||
const targetPath = path.join(bmadWorkflowsDir, artifact.module, 'agents', `${artifact.name}.md`);
|
||||
await this.writeFile(targetPath, processedContent);
|
||||
agentCount++;
|
||||
}
|
||||
@ -127,13 +133,17 @@ class WindsurfSetup extends BaseIdeSetup {
|
||||
* Create workflow content for an agent
|
||||
*/
|
||||
createWorkflowContent(agent, content) {
|
||||
// Strip existing frontmatter from launcher
|
||||
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
|
||||
const contentWithoutFrontmatter = content.replace(frontmatterRegex, '');
|
||||
|
||||
// Create simple Windsurf frontmatter matching original format
|
||||
let workflowContent = `---
|
||||
description: ${agent.name}
|
||||
auto_execution_mode: 3
|
||||
---
|
||||
|
||||
${content}`;
|
||||
${contentWithoutFrontmatter}`;
|
||||
|
||||
return workflowContent;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user