fix installer to discover and install local src/modules
- listAvailable() now scans src/modules/ so local modules appear in the UI
- findModuleSource() checks src/modules/{code} before falling back to GitHub
- Handle menu object format (menu.items) alongside legacy flat array in
vendorCrossModuleWorkflows, agent compiler, and agent analyzer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ab8f412c3c
commit
7d6180b6a2
|
|
@ -204,6 +204,21 @@ class ModuleManager {
|
|||
}
|
||||
}
|
||||
|
||||
// Scan src/modules/ for locally-defined modules
|
||||
const localModulesPath = getSourcePath('modules');
|
||||
if (await fs.pathExists(localModulesPath)) {
|
||||
const moduleEntries = await fs.readdir(localModulesPath, { withFileTypes: true });
|
||||
for (const entry of moduleEntries) {
|
||||
if (entry.isDirectory()) {
|
||||
const modulePath = path.join(localModulesPath, entry.name);
|
||||
const moduleInfo = await this.getModuleInfo(modulePath, entry.name, 'src/modules');
|
||||
if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id)) {
|
||||
modules.push(moduleInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for cached custom modules in _config/custom/
|
||||
if (this.bmadDir) {
|
||||
const customCacheDir = path.join(this.bmadDir, '_config', 'custom');
|
||||
|
|
@ -308,6 +323,12 @@ class ModuleManager {
|
|||
}
|
||||
}
|
||||
|
||||
// Check src/modules/{moduleCode} for locally-defined modules (takes priority over external)
|
||||
const localModulePath = getModulePath(moduleCode);
|
||||
if (await fs.pathExists(localModulePath)) {
|
||||
return localModulePath;
|
||||
}
|
||||
|
||||
// Check external official modules
|
||||
const externalSource = await this.findExternalModuleSource(moduleCode, options);
|
||||
if (externalSource) {
|
||||
|
|
@ -1150,7 +1171,9 @@ class ModuleManager {
|
|||
const agentYaml = yaml.parse(await fs.readFile(agentPath, 'utf8'));
|
||||
|
||||
// Check if agent has menu items with workflow-install
|
||||
const menuItems = agentYaml?.agent?.menu || [];
|
||||
// menu can be an array OR an object with an `items` array
|
||||
const menu = agentYaml?.agent?.menu;
|
||||
const menuItems = Array.isArray(menu) ? menu : menu?.items || [];
|
||||
const workflowInstallItems = menuItems.filter((item) => item['workflow-install']);
|
||||
|
||||
if (workflowInstallItems.length === 0) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ class AgentAnalyzer {
|
|||
}
|
||||
|
||||
// Analyze menu items (support both 'menu' and legacy 'commands')
|
||||
const menuItems = agentYaml.agent?.menu || agentYaml.agent?.commands || [];
|
||||
// menu can be an array or an object with an `items` array
|
||||
const rawMenu = agentYaml.agent?.menu || agentYaml.agent?.commands;
|
||||
const menuItems = Array.isArray(rawMenu) ? rawMenu : rawMenu?.items || [];
|
||||
|
||||
for (const item of menuItems) {
|
||||
// Track the menu item
|
||||
|
|
|
|||
|
|
@ -309,8 +309,10 @@ async function compileToXml(agentYaml, agentName = '', targetPath = '') {
|
|||
xml += buildMemoriesXml(agent.memories);
|
||||
}
|
||||
|
||||
// Menu section
|
||||
xml += buildMenuXml(agent.menu || []);
|
||||
// Menu section — menu can be an array or an object with an `items` array
|
||||
const menuData = agent.menu;
|
||||
const menuItems = Array.isArray(menuData) ? menuData : menuData?.items || [];
|
||||
xml += buildMenuXml(menuItems);
|
||||
|
||||
// Closing agent tag
|
||||
xml += '</agent>\n';
|
||||
|
|
@ -397,7 +399,8 @@ async function compileAgent(yamlContent, answers = {}, agentName = '', targetPat
|
|||
|
||||
// For menu: append to existing or create new
|
||||
if (customizations.menu) {
|
||||
const existing = agentYaml.agent.menu || [];
|
||||
const existingMenu = agentYaml.agent.menu;
|
||||
const existing = Array.isArray(existingMenu) ? existingMenu : existingMenu?.items || [];
|
||||
agentYaml.agent.menu = [...existing, ...customizations.menu];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue