mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-29 16:14:59 +00:00
installer fixes
This commit is contained in:
119
tools/cli/installers/lib/ide/task-tool-command-generator.js
Normal file
119
tools/cli/installers/lib/ide/task-tool-command-generator.js
Normal file
@@ -0,0 +1,119 @@
|
||||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const csv = require('csv-parse/sync');
|
||||
const chalk = require('chalk');
|
||||
|
||||
/**
|
||||
* Generates Claude Code command files for standalone tasks and tools
|
||||
*/
|
||||
class TaskToolCommandGenerator {
|
||||
/**
|
||||
* Generate task and tool commands from manifest CSVs
|
||||
* @param {string} projectDir - Project directory
|
||||
* @param {string} bmadDir - BMAD installation directory
|
||||
* @param {string} baseCommandsDir - Optional base commands directory (defaults to .claude/commands/bmad)
|
||||
*/
|
||||
async generateTaskToolCommands(projectDir, bmadDir, baseCommandsDir = null) {
|
||||
const tasks = await this.loadTaskManifest(bmadDir);
|
||||
const tools = await this.loadToolManifest(bmadDir);
|
||||
|
||||
// Filter to only standalone items
|
||||
const standaloneTasks = tasks ? tasks.filter((t) => t.standalone === 'true' || t.standalone === true) : [];
|
||||
const standaloneTools = tools ? tools.filter((t) => t.standalone === 'true' || t.standalone === true) : [];
|
||||
|
||||
// Base commands directory - use provided or default to Claude Code structure
|
||||
const commandsDir = baseCommandsDir || path.join(projectDir, '.claude', 'commands', 'bmad');
|
||||
|
||||
let generatedCount = 0;
|
||||
|
||||
// Generate command files for tasks
|
||||
for (const task of standaloneTasks) {
|
||||
const moduleTasksDir = path.join(commandsDir, task.module, 'tasks');
|
||||
await fs.ensureDir(moduleTasksDir);
|
||||
|
||||
const commandContent = this.generateCommandContent(task, 'task');
|
||||
const commandPath = path.join(moduleTasksDir, `${task.name}.md`);
|
||||
|
||||
await fs.writeFile(commandPath, commandContent);
|
||||
generatedCount++;
|
||||
}
|
||||
|
||||
// Generate command files for tools
|
||||
for (const tool of standaloneTools) {
|
||||
const moduleToolsDir = path.join(commandsDir, tool.module, 'tools');
|
||||
await fs.ensureDir(moduleToolsDir);
|
||||
|
||||
const commandContent = this.generateCommandContent(tool, 'tool');
|
||||
const commandPath = path.join(moduleToolsDir, `${tool.name}.md`);
|
||||
|
||||
await fs.writeFile(commandPath, commandContent);
|
||||
generatedCount++;
|
||||
}
|
||||
|
||||
return {
|
||||
generated: generatedCount,
|
||||
tasks: standaloneTasks.length,
|
||||
tools: standaloneTools.length,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate command content for a task or tool
|
||||
*/
|
||||
generateCommandContent(item, type) {
|
||||
const description = item.description || `Execute ${item.displayName || item.name}`;
|
||||
|
||||
// Convert path to use {project-root} placeholder
|
||||
let itemPath = item.path;
|
||||
if (itemPath.startsWith('bmad/')) {
|
||||
itemPath = `{project-root}/${itemPath}`;
|
||||
}
|
||||
|
||||
return `---
|
||||
description: '${description.replaceAll("'", "''")}'
|
||||
---
|
||||
|
||||
# ${item.displayName || item.name}
|
||||
|
||||
LOAD and execute the ${type} at: ${itemPath}
|
||||
|
||||
Follow all instructions in the ${type} file exactly as written.
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load task manifest CSV
|
||||
*/
|
||||
async loadTaskManifest(bmadDir) {
|
||||
const manifestPath = path.join(bmadDir, '_cfg', 'task-manifest.csv');
|
||||
|
||||
if (!(await fs.pathExists(manifestPath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const csvContent = await fs.readFile(manifestPath, 'utf8');
|
||||
return csv.parse(csvContent, {
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load tool manifest CSV
|
||||
*/
|
||||
async loadToolManifest(bmadDir) {
|
||||
const manifestPath = path.join(bmadDir, '_cfg', 'tool-manifest.csv');
|
||||
|
||||
if (!(await fs.pathExists(manifestPath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const csvContent = await fs.readFile(manifestPath, 'utf8');
|
||||
return csv.parse(csvContent, {
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { TaskToolCommandGenerator };
|
||||
Reference in New Issue
Block a user