addressed PR request from Brian

This commit is contained in:
murat 2026-02-14 10:24:50 -06:00
parent 1943ca2ad1
commit 2165c56e91
2 changed files with 41 additions and 82 deletions

View File

@ -5,62 +5,3 @@
For external official modules to be discoverable during install, ensure an entry for the external repo is added to external-official-modules.yaml.
For community modules - this will be handled in a different way. This file is only for registration of modules under the bmad-code-org.
## Post-Install Configuration Notes for Module Authors
The installer can display setup guidance to users after a module's configuration is collected. This is handled by the `displayModulePostConfigNotes(moduleName)` method in `installers/lib/core/config-collector.js`.
### When It Runs
The method is called in two places:
- After `collectModuleConfig()` completes (full interactive configuration)
- After `collectModuleConfigQuick()` completes (quick mode with existing config)
This ensures users see relevant setup instructions regardless of installation path.
### Guards
Output is suppressed when:
- **Silent mode** (`this._silentConfig`) — non-interactive installations skip all output
- **Feature disabled** — e.g., if the config value is `'none'`, no guidance is needed
### Adding Support for a New Module
To add post-config notes for your module, add a conditional block in `displayModulePostConfigNotes()`:
```javascript
async displayModulePostConfigNotes(moduleName) {
if (this._silentConfig) return;
// Existing: TEA module handler
if (moduleName !== 'tea') return;
// ...
// To add your module, replace the early return above with:
if (moduleName === 'your-module') {
const config = this.collectedConfig[moduleName];
if (!config || !config.your_config_key) return;
const value = config.your_config_key;
if (value === 'none') return;
const color = await prompts.getColor();
await prompts.log.message('');
await prompts.log.info(color.bold('Your Setup Instructions:'));
await prompts.log.message(color.dim(' Instructions based on selected value...'));
}
}
```
### Key Details
- Read config values from `this.collectedConfig[moduleName]`
- Use `prompts.log.info()` for headers and `prompts.log.message()` for details
- Use `color.bold()` and `color.dim()` for visual hierarchy
- The config question that drives the output is defined in the module's `module.yaml`
### Working Example: TEA Module
The TEA module defines a `tea_browser_automation` config question with options: `auto`, `cli`, `mcp`, `none`. After configuration, the handler at lines 1207-1235 displays Playwright CLI install commands and/or MCP setup links based on the user's selection.

View File

@ -550,7 +550,7 @@ class ConfigCollector {
}
}
await this.displayModulePostConfigNotes(moduleName);
await this.displayModulePostConfigNotes(moduleName, moduleConfig);
return newKeys.length > 0 || newStaticKeys.length > 0; // Return true if we had any new fields (interactive or static)
}
@ -926,7 +926,7 @@ class ConfigCollector {
}
}
await this.displayModulePostConfigNotes(moduleName);
await this.displayModulePostConfigNotes(moduleName, moduleConfig);
}
/**
@ -1202,35 +1202,53 @@ class ConfigCollector {
/**
* Display post-configuration notes for a module
* Shows prerequisite guidance based on collected config values
* Reads notes from the module's `post-install-notes` section in module.yaml
* Supports two formats:
* - Simple string: always displayed
* - Object keyed by config field name, with value-specific messages
* @param {string} moduleName - Module name
* @param {Object} moduleConfig - Parsed module.yaml content
*/
async displayModulePostConfigNotes(moduleName) {
async displayModulePostConfigNotes(moduleName, moduleConfig) {
if (this._silentConfig) return;
if (moduleName !== 'tea') return;
const teaConfig = this.collectedConfig[moduleName];
if (!teaConfig || !teaConfig.tea_browser_automation) return;
const mode = teaConfig.tea_browser_automation;
if (mode === 'none') return;
if (!moduleConfig || !moduleConfig['post-install-notes']) return;
const notes = moduleConfig['post-install-notes'];
const color = await prompts.getColor();
await prompts.log.message('');
if (mode === 'cli' || mode === 'auto') {
await prompts.log.info(color.bold('Playwright CLI Setup:'));
await prompts.log.message(color.dim(' npm install -g @playwright/cli@latest'));
await prompts.log.message(color.dim(' playwright-cli install --skills # Run from project root'));
await prompts.log.message(color.dim(' Node.js 18+ required.'));
// Format 1: Simple string - always display
if (typeof notes === 'string') {
await prompts.log.message('');
for (const line of notes.trim().split('\n')) {
await prompts.log.message(color.dim(line));
}
return;
}
if (mode === 'mcp' || mode === 'auto') {
if (mode === 'auto') await prompts.log.message('');
await prompts.log.info(color.bold('Playwright MCP Setup:'));
await prompts.log.message(color.dim(' Configure MCP servers in your IDE'));
await prompts.log.message(color.dim(' See: https://github.com/microsoft/playwright-mcp'));
// Format 2: Conditional on config values
if (typeof notes === 'object') {
const config = this.collectedConfig[moduleName];
if (!config) return;
let hasOutput = false;
for (const [configKey, valueMessages] of Object.entries(notes)) {
const selectedValue = config[configKey];
if (!selectedValue || !valueMessages[selectedValue]) continue;
if (hasOutput) await prompts.log.message('');
hasOutput = true;
const message = valueMessages[selectedValue];
await prompts.log.message('');
for (const line of message.trim().split('\n')) {
const trimmedLine = line.trim();
if (trimmedLine.endsWith(':') && !trimmedLine.startsWith(' ')) {
await prompts.log.info(color.bold(trimmedLine));
} else {
await prompts.log.message(color.dim(' ' + trimmedLine));
}
}
}
}
}