Skip to content

Commit f363695

Browse files
Brian MadisonBrian Madison
authored andcommitted
fixed issue with agent customization application, now all fields are customized form the custom yaml. also added a recompile agents menu item
1 parent ccb6462 commit f363695

File tree

7 files changed

+3457
-115
lines changed

7 files changed

+3457
-115
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/cli/commands/install.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ module.exports = {
3535
return;
3636
}
3737

38+
// Handle compile agents separately
39+
if (config.actionType === 'compile-agents') {
40+
const result = await installer.compileAgents(config);
41+
console.log(chalk.green('\n✨ Agent recompilation complete!'));
42+
console.log(chalk.cyan(`Recompiled ${result.agentCount} agents with customizations applied`));
43+
process.exit(0);
44+
return;
45+
}
46+
3847
// Regular install/update flow
3948
const result = await installer.install(config);
4049

tools/cli/installers/lib/core/installer.js

Lines changed: 109 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -226,21 +226,21 @@ class Installer {
226226
'<!-- TTS_INJECTION:party-mode -->',
227227
`<critical>IMPORTANT: Always use PROJECT hooks (.claude/hooks/), NEVER global hooks (~/.claude/hooks/)</critical>
228228
229-
If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
229+
If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
230230
- Use Bash tool: \`.claude/hooks/bmad-speak.sh '[Agent Name]' '[dialogue]'\`
231231
- This speaks the dialogue with the agent's unique voice
232-
- Run in background (&) to not block next agent`,
232+
- Run in background to not block next agent`,
233233
);
234234

235235
// Replace agent-tts injection marker with TTS rule for individual agents
236236
content = content.replaceAll(
237237
'<!-- TTS_INJECTION:agent-tts -->',
238238
`- When responding to user messages, speak your responses using TTS:
239-
Call: \`.claude/hooks/bmad-speak.sh '{agent-id}' '{response-text}'\` after each response
240-
Replace {agent-id} with YOUR agent ID from <agent id="..."> tag at top of this file
241-
Replace {response-text} with the text you just output to the user
242-
IMPORTANT: Use single quotes as shown - do NOT escape special characters like ! or $ inside single quotes
243-
Run in background (&) to avoid blocking`,
239+
Call: \`.claude/hooks/bmad-speak.sh '{agent-id}' '{response-text}'\` after each response
240+
Replace {agent-id} with YOUR agent ID from <agent id="..."> tag at top of this file
241+
Replace {response-text} with the text you just output to the user
242+
IMPORTANT: Use single quotes as shown - do NOT escape special characters like ! or $ inside single quotes
243+
Run in background (&) to avoid blocking`,
244244
);
245245

246246
// Track files that had TTS injection applied
@@ -2082,108 +2082,6 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
20822082
}
20832083
}
20842084

2085-
/**
2086-
* Compile/rebuild all agents and tasks for quick updates
2087-
* @param {Object} config - Compilation configuration
2088-
* @returns {Object} Compilation results
2089-
*/
2090-
async compileAgents(config) {
2091-
try {
2092-
const projectDir = path.resolve(config.directory);
2093-
const { bmadDir } = await this.findBmadDir(projectDir);
2094-
2095-
// Check if bmad directory exists
2096-
if (!(await fs.pathExists(bmadDir))) {
2097-
throw new Error(`BMAD not installed at ${bmadDir}`);
2098-
}
2099-
2100-
// Get installed modules from manifest
2101-
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
2102-
let installedModules = [];
2103-
let manifest = null;
2104-
if (await fs.pathExists(manifestPath)) {
2105-
const manifestContent = await fs.readFile(manifestPath, 'utf8');
2106-
const yaml = require('yaml');
2107-
manifest = yaml.parse(manifestContent);
2108-
installedModules = manifest.modules || [];
2109-
}
2110-
2111-
// Check for custom modules with missing sources
2112-
if (manifest && manifest.customModules && manifest.customModules.length > 0) {
2113-
console.log(chalk.yellow('\nChecking custom module sources before compilation...'));
2114-
2115-
const customModuleSources = new Map();
2116-
for (const customModule of manifest.customModules) {
2117-
customModuleSources.set(customModule.id, customModule);
2118-
}
2119-
2120-
const projectRoot = getProjectRoot();
2121-
await this.handleMissingCustomSources(customModuleSources, bmadDir, projectRoot, 'compile-agents', installedModules);
2122-
}
2123-
2124-
let agentCount = 0;
2125-
let taskCount = 0;
2126-
2127-
// Process all modules in bmad directory
2128-
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
2129-
2130-
for (const entry of entries) {
2131-
if (entry.isDirectory() && entry.name !== '_config' && entry.name !== 'docs') {
2132-
const modulePath = path.join(bmadDir, entry.name);
2133-
2134-
// Special handling for standalone agents in bmad/agents/ directory
2135-
if (entry.name === 'agents') {
2136-
await this.buildStandaloneAgents(bmadDir, projectDir);
2137-
2138-
// Count standalone agents
2139-
const standaloneAgentsPath = path.join(bmadDir, 'agents');
2140-
const standaloneAgentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
2141-
for (const agentDir of standaloneAgentDirs) {
2142-
if (agentDir.isDirectory()) {
2143-
const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
2144-
const agentFiles = await fs.readdir(agentDirPath);
2145-
agentCount += agentFiles.filter((f) => f.endsWith('.md') && !f.endsWith('.agent.yaml')).length;
2146-
}
2147-
}
2148-
} else {
2149-
// Rebuild module agents from installer source
2150-
const agentsPath = path.join(modulePath, 'agents');
2151-
if (await fs.pathExists(agentsPath)) {
2152-
await this.rebuildAgentFiles(modulePath, entry.name);
2153-
const agentFiles = await fs.readdir(agentsPath);
2154-
agentCount += agentFiles.filter((f) => f.endsWith('.md')).length;
2155-
}
2156-
2157-
// Count tasks (already built)
2158-
const tasksPath = path.join(modulePath, 'tasks');
2159-
if (await fs.pathExists(tasksPath)) {
2160-
const taskFiles = await fs.readdir(tasksPath);
2161-
taskCount += taskFiles.filter((f) => f.endsWith('.md')).length;
2162-
}
2163-
}
2164-
}
2165-
}
2166-
2167-
// Update IDE configurations using the existing IDE list from manifest
2168-
if (manifest && manifest.ides && manifest.ides.length > 0) {
2169-
for (const ide of manifest.ides) {
2170-
await this.ideManager.setup(ide, projectDir, bmadDir, {
2171-
selectedModules: installedModules,
2172-
skipModuleInstall: true, // Skip module installation, just update IDE files
2173-
verbose: config.verbose,
2174-
preCollectedConfig: { _alreadyConfigured: true }, // Skip all interactive prompts during compile
2175-
});
2176-
}
2177-
console.log(chalk.green('✓ IDE configurations updated'));
2178-
} else {
2179-
console.log(chalk.yellow('⚠️ No IDEs configured. Skipping IDE update.'));
2180-
}
2181-
return { agentCount, taskCount };
2182-
} catch (error) {
2183-
throw error;
2184-
}
2185-
}
2186-
21872085
/**
21882086
* Private: Update core
21892087
*/
@@ -2404,6 +2302,108 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
24042302
}
24052303
}
24062304

2305+
/**
2306+
* Compile agents with customizations only
2307+
* @param {Object} config - Configuration with directory
2308+
* @returns {Object} Compilation result
2309+
*/
2310+
async compileAgents(config) {
2311+
const ora = require('ora');
2312+
const chalk = require('chalk');
2313+
const { ModuleManager } = require('../modules/manager');
2314+
const { getSourcePath } = require('../../../lib/project-root');
2315+
2316+
const spinner = ora('Recompiling agents with customizations...').start();
2317+
2318+
try {
2319+
const projectDir = path.resolve(config.directory);
2320+
const { bmadDir } = await this.findBmadDir(projectDir);
2321+
2322+
// Check if bmad directory exists
2323+
if (!(await fs.pathExists(bmadDir))) {
2324+
spinner.fail('No BMAD installation found');
2325+
throw new Error(`BMAD not installed at ${bmadDir}. Use regular install for first-time setup.`);
2326+
}
2327+
2328+
// Detect existing installation
2329+
const existingInstall = await this.detector.detect(bmadDir);
2330+
const installedModules = existingInstall.modules.map((m) => m.id);
2331+
2332+
// Initialize module manager
2333+
const moduleManager = new ModuleManager();
2334+
moduleManager.setBmadFolderName(path.basename(bmadDir));
2335+
2336+
let totalAgentCount = 0;
2337+
2338+
// Get custom module sources from cache
2339+
const customModuleSources = new Map();
2340+
const cacheDir = path.join(bmadDir, '_config', 'custom');
2341+
if (await fs.pathExists(cacheDir)) {
2342+
const cachedModules = await fs.readdir(cacheDir, { withFileTypes: true });
2343+
2344+
for (const cachedModule of cachedModules) {
2345+
if (cachedModule.isDirectory()) {
2346+
const moduleId = cachedModule.name;
2347+
const cachedPath = path.join(cacheDir, moduleId);
2348+
const moduleYamlPath = path.join(cachedPath, 'module.yaml');
2349+
2350+
// Check if this is actually a custom module
2351+
if (await fs.pathExists(moduleYamlPath)) {
2352+
customModuleSources.set(moduleId, cachedPath);
2353+
}
2354+
}
2355+
}
2356+
}
2357+
2358+
// Process each installed module
2359+
for (const moduleId of installedModules) {
2360+
spinner.text = `Recompiling agents in ${moduleId}...`;
2361+
2362+
// Get source path
2363+
let sourcePath;
2364+
if (moduleId === 'core') {
2365+
sourcePath = getSourcePath('core');
2366+
} else {
2367+
// First check if it's in the custom cache
2368+
if (customModuleSources.has(moduleId)) {
2369+
sourcePath = customModuleSources.get(moduleId);
2370+
} else {
2371+
sourcePath = await moduleManager.findModuleSource(moduleId);
2372+
}
2373+
}
2374+
2375+
if (!sourcePath) {
2376+
console.log(chalk.yellow(` Warning: Source not found for module ${moduleId}, skipping...`));
2377+
continue;
2378+
}
2379+
2380+
const targetPath = path.join(bmadDir, moduleId);
2381+
2382+
// Compile agents for this module
2383+
await moduleManager.compileModuleAgents(sourcePath, targetPath, moduleId, bmadDir, this);
2384+
2385+
// Count agents (rough estimate based on files)
2386+
const agentsPath = path.join(targetPath, 'agents');
2387+
if (await fs.pathExists(agentsPath)) {
2388+
const agentFiles = await fs.readdir(agentsPath);
2389+
const agentCount = agentFiles.filter((f) => f.endsWith('.md')).length;
2390+
totalAgentCount += agentCount;
2391+
}
2392+
}
2393+
2394+
spinner.succeed('Agent recompilation complete!');
2395+
2396+
return {
2397+
success: true,
2398+
agentCount: totalAgentCount,
2399+
modules: installedModules,
2400+
};
2401+
} catch (error) {
2402+
spinner.fail('Agent recompilation failed');
2403+
throw error;
2404+
}
2405+
}
2406+
24072407
/**
24082408
* Private: Prompt for update action
24092409
*/

0 commit comments

Comments
 (0)