bmad-method 6.2.3-next.0 → 6.2.3-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -8
- package/src/core-skills/bmad-distillator/resources/distillate-format-reference.md +1 -1
- package/tools/{cli → installer}/bmad-cli.js +3 -1
- package/tools/{cli/lib → installer}/cli-utils.js +3 -4
- package/tools/{cli → installer}/commands/install.js +3 -3
- package/tools/{cli → installer}/commands/status.js +4 -4
- package/tools/{cli → installer}/commands/uninstall.js +5 -5
- package/tools/installer/core/config.js +52 -0
- package/tools/{cli/installers/lib → installer}/core/custom-module-cache.js +1 -1
- package/tools/installer/core/existing-install.js +127 -0
- package/tools/installer/core/install-paths.js +129 -0
- package/tools/installer/core/installer.js +1790 -0
- package/tools/{cli/installers/lib → installer}/core/manifest-generator.js +3 -3
- package/tools/{cli/installers/lib → installer}/core/manifest.js +2 -2
- package/tools/{cli/installers/lib/custom/handler.js → installer/custom-handler.js} +1 -1
- package/tools/{cli → installer}/external-official-modules.yaml +1 -1
- package/tools/{cli/installers/lib → installer}/ide/_config-driven.js +30 -397
- package/tools/{cli/installers/lib → installer}/ide/manager.js +1 -53
- package/tools/installer/ide/platform-codes.js +37 -0
- package/tools/installer/ide/platform-codes.yaml +190 -0
- package/tools/{cli/installers/lib → installer}/ide/shared/module-injections.js +1 -1
- package/tools/{cli/installers/lib → installer}/message-loader.js +2 -2
- package/tools/installer/modules/custom-modules.js +197 -0
- package/tools/installer/modules/external-manager.js +323 -0
- package/tools/{cli/installers/lib/core/config-collector.js → installer/modules/official-modules.js} +714 -43
- package/tools/{cli/lib → installer}/ui.js +65 -299
- package/tools/javascript-conventions.md +5 -0
- package/tools/bmad-npx-wrapper.js +0 -38
- package/tools/cli/installers/lib/core/dependency-resolver.js +0 -743
- package/tools/cli/installers/lib/core/detector.js +0 -223
- package/tools/cli/installers/lib/core/ide-config-manager.js +0 -157
- package/tools/cli/installers/lib/core/installer.js +0 -3002
- package/tools/cli/installers/lib/ide/_base-ide.js +0 -657
- package/tools/cli/installers/lib/ide/platform-codes.js +0 -100
- package/tools/cli/installers/lib/ide/platform-codes.yaml +0 -341
- package/tools/cli/installers/lib/modules/external-manager.js +0 -136
- package/tools/cli/installers/lib/modules/manager.js +0 -928
- package/tools/cli/lib/config.js +0 -213
- package/tools/cli/lib/platform-codes.js +0 -116
- package/tools/lib/xml-utils.js +0 -13
- /package/tools/{cli → installer}/README.md +0 -0
- /package/tools/{cli/lib → installer}/file-ops.js +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/shared/agent-command-generator.js +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/shared/bmad-artifacts.js +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/shared/path-utils.js +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/shared/skill-manifest.js +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/agent-command-template.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/antigravity.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-agent.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-task.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-tool.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-workflow.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-agent.toml +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-task.toml +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-tool.toml +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow-yaml.toml +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow.toml +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-agent.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-task.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-tool.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-workflow.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-agent.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-task.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-tool.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow-yaml.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/rovodev.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/trae.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/combined/windsurf-workflow.md +0 -0
- /package/tools/{cli/installers/lib → installer}/ide/templates/split/.gitkeep +0 -0
- /package/tools/{cli/installers → installer}/install-messages.yaml +0 -0
- /package/tools/{cli/lib → installer}/project-root.js +0 -0
- /package/tools/{cli/lib → installer}/prompts.js +0 -0
- /package/tools/{cli/lib → installer}/yaml-format.js +0 -0
package/tools/cli/lib/config.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const yaml = require('yaml');
|
|
3
|
-
const path = require('node:path');
|
|
4
|
-
const packageJson = require('../../../package.json');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Configuration utility class
|
|
8
|
-
*/
|
|
9
|
-
class Config {
|
|
10
|
-
/**
|
|
11
|
-
* Load a YAML configuration file
|
|
12
|
-
* @param {string} configPath - Path to config file
|
|
13
|
-
* @returns {Object} Parsed configuration
|
|
14
|
-
*/
|
|
15
|
-
async loadYaml(configPath) {
|
|
16
|
-
if (!(await fs.pathExists(configPath))) {
|
|
17
|
-
throw new Error(`Configuration file not found: ${configPath}`);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const content = await fs.readFile(configPath, 'utf8');
|
|
21
|
-
return yaml.parse(content);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Save configuration to YAML file
|
|
26
|
-
* @param {string} configPath - Path to config file
|
|
27
|
-
* @param {Object} config - Configuration object
|
|
28
|
-
*/
|
|
29
|
-
async saveYaml(configPath, config) {
|
|
30
|
-
const yamlContent = yaml.dump(config, {
|
|
31
|
-
indent: 2,
|
|
32
|
-
lineWidth: 120,
|
|
33
|
-
noRefs: true,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
await fs.ensureDir(path.dirname(configPath));
|
|
37
|
-
// Ensure POSIX-compliant final newline
|
|
38
|
-
const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
|
|
39
|
-
await fs.writeFile(configPath, content, 'utf8');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Process configuration file (replace placeholders)
|
|
44
|
-
* @param {string} configPath - Path to config file
|
|
45
|
-
* @param {Object} replacements - Replacement values
|
|
46
|
-
*/
|
|
47
|
-
async processConfig(configPath, replacements = {}) {
|
|
48
|
-
let content = await fs.readFile(configPath, 'utf8');
|
|
49
|
-
|
|
50
|
-
// Standard replacements
|
|
51
|
-
const standardReplacements = {
|
|
52
|
-
'{project-root}': replacements.root || '',
|
|
53
|
-
'{module}': replacements.module || '',
|
|
54
|
-
'{version}': replacements.version || packageJson.version,
|
|
55
|
-
'{date}': new Date().toISOString().split('T')[0],
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Apply all replacements
|
|
59
|
-
const allReplacements = { ...standardReplacements, ...replacements };
|
|
60
|
-
|
|
61
|
-
for (const [placeholder, value] of Object.entries(allReplacements)) {
|
|
62
|
-
if (typeof placeholder === 'string' && typeof value === 'string') {
|
|
63
|
-
const regex = new RegExp(placeholder.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`), 'g');
|
|
64
|
-
content = content.replace(regex, value);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
await fs.writeFile(configPath, content, 'utf8');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Merge configurations
|
|
73
|
-
* @param {Object} base - Base configuration
|
|
74
|
-
* @param {Object} override - Override configuration
|
|
75
|
-
* @returns {Object} Merged configuration
|
|
76
|
-
*/
|
|
77
|
-
mergeConfigs(base, override) {
|
|
78
|
-
return this.deepMerge(base, override);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Deep merge two objects
|
|
83
|
-
* @param {Object} target - Target object
|
|
84
|
-
* @param {Object} source - Source object
|
|
85
|
-
* @returns {Object} Merged object
|
|
86
|
-
*/
|
|
87
|
-
deepMerge(target, source) {
|
|
88
|
-
const output = { ...target };
|
|
89
|
-
|
|
90
|
-
if (this.isObject(target) && this.isObject(source)) {
|
|
91
|
-
for (const key of Object.keys(source)) {
|
|
92
|
-
if (this.isObject(source[key])) {
|
|
93
|
-
if (key in target) {
|
|
94
|
-
output[key] = this.deepMerge(target[key], source[key]);
|
|
95
|
-
} else {
|
|
96
|
-
output[key] = source[key];
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
output[key] = source[key];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return output;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Check if value is an object
|
|
109
|
-
* @param {*} item - Item to check
|
|
110
|
-
* @returns {boolean} True if object
|
|
111
|
-
*/
|
|
112
|
-
isObject(item) {
|
|
113
|
-
return item && typeof item === 'object' && !Array.isArray(item);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Validate configuration against schema
|
|
118
|
-
* @param {Object} config - Configuration to validate
|
|
119
|
-
* @param {Object} schema - Validation schema
|
|
120
|
-
* @returns {Object} Validation result
|
|
121
|
-
*/
|
|
122
|
-
validateConfig(config, schema) {
|
|
123
|
-
const errors = [];
|
|
124
|
-
const warnings = [];
|
|
125
|
-
|
|
126
|
-
// Check required fields
|
|
127
|
-
if (schema.required) {
|
|
128
|
-
for (const field of schema.required) {
|
|
129
|
-
if (!(field in config)) {
|
|
130
|
-
errors.push(`Missing required field: ${field}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Check field types
|
|
136
|
-
if (schema.properties) {
|
|
137
|
-
for (const [field, spec] of Object.entries(schema.properties)) {
|
|
138
|
-
if (field in config) {
|
|
139
|
-
const value = config[field];
|
|
140
|
-
const expectedType = spec.type;
|
|
141
|
-
|
|
142
|
-
if (expectedType === 'array' && !Array.isArray(value)) {
|
|
143
|
-
errors.push(`Field '${field}' should be an array`);
|
|
144
|
-
} else if (expectedType === 'object' && !this.isObject(value)) {
|
|
145
|
-
errors.push(`Field '${field}' should be an object`);
|
|
146
|
-
} else if (expectedType === 'string' && typeof value !== 'string') {
|
|
147
|
-
errors.push(`Field '${field}' should be a string`);
|
|
148
|
-
} else if (expectedType === 'number' && typeof value !== 'number') {
|
|
149
|
-
errors.push(`Field '${field}' should be a number`);
|
|
150
|
-
} else if (expectedType === 'boolean' && typeof value !== 'boolean') {
|
|
151
|
-
errors.push(`Field '${field}' should be a boolean`);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Check enum values
|
|
155
|
-
if (spec.enum && !spec.enum.includes(value)) {
|
|
156
|
-
errors.push(`Field '${field}' must be one of: ${spec.enum.join(', ')}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
valid: errors.length === 0,
|
|
164
|
-
errors,
|
|
165
|
-
warnings,
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Get configuration value with fallback
|
|
171
|
-
* @param {Object} config - Configuration object
|
|
172
|
-
* @param {string} path - Dot-notation path to value
|
|
173
|
-
* @param {*} defaultValue - Default value if not found
|
|
174
|
-
* @returns {*} Configuration value
|
|
175
|
-
*/
|
|
176
|
-
getValue(config, path, defaultValue = null) {
|
|
177
|
-
const keys = path.split('.');
|
|
178
|
-
let current = config;
|
|
179
|
-
|
|
180
|
-
for (const key of keys) {
|
|
181
|
-
if (current && typeof current === 'object' && key in current) {
|
|
182
|
-
current = current[key];
|
|
183
|
-
} else {
|
|
184
|
-
return defaultValue;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return current;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Set configuration value
|
|
193
|
-
* @param {Object} config - Configuration object
|
|
194
|
-
* @param {string} path - Dot-notation path to value
|
|
195
|
-
* @param {*} value - Value to set
|
|
196
|
-
*/
|
|
197
|
-
setValue(config, path, value) {
|
|
198
|
-
const keys = path.split('.');
|
|
199
|
-
const lastKey = keys.pop();
|
|
200
|
-
let current = config;
|
|
201
|
-
|
|
202
|
-
for (const key of keys) {
|
|
203
|
-
if (!(key in current) || typeof current[key] !== 'object') {
|
|
204
|
-
current[key] = {};
|
|
205
|
-
}
|
|
206
|
-
current = current[key];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
current[lastKey] = value;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
module.exports = { Config };
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const path = require('node:path');
|
|
3
|
-
const yaml = require('yaml');
|
|
4
|
-
const { getProjectRoot } = require('./project-root');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Platform Codes Manager
|
|
8
|
-
* Loads and provides access to the centralized platform codes configuration
|
|
9
|
-
*/
|
|
10
|
-
class PlatformCodes {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.configPath = path.join(getProjectRoot(), 'tools', 'platform-codes.yaml');
|
|
13
|
-
this.loadConfig();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Load the platform codes configuration
|
|
18
|
-
*/
|
|
19
|
-
loadConfig() {
|
|
20
|
-
try {
|
|
21
|
-
if (fs.existsSync(this.configPath)) {
|
|
22
|
-
const content = fs.readFileSync(this.configPath, 'utf8');
|
|
23
|
-
this.config = yaml.parse(content);
|
|
24
|
-
} else {
|
|
25
|
-
console.warn(`Platform codes config not found at ${this.configPath}`);
|
|
26
|
-
this.config = { platforms: {} };
|
|
27
|
-
}
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.error(`Error loading platform codes: ${error.message}`);
|
|
30
|
-
this.config = { platforms: {} };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get all platform codes
|
|
36
|
-
* @returns {Object} All platform configurations
|
|
37
|
-
*/
|
|
38
|
-
getAllPlatforms() {
|
|
39
|
-
return this.config.platforms || {};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get a specific platform configuration
|
|
44
|
-
* @param {string} code - Platform code
|
|
45
|
-
* @returns {Object|null} Platform configuration or null if not found
|
|
46
|
-
*/
|
|
47
|
-
getPlatform(code) {
|
|
48
|
-
return this.config.platforms[code] || null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Check if a platform code is valid
|
|
53
|
-
* @param {string} code - Platform code to validate
|
|
54
|
-
* @returns {boolean} True if valid
|
|
55
|
-
*/
|
|
56
|
-
isValidPlatform(code) {
|
|
57
|
-
return code in this.config.platforms;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get all preferred platforms
|
|
62
|
-
* @returns {Array} Array of preferred platform codes
|
|
63
|
-
*/
|
|
64
|
-
getPreferredPlatforms() {
|
|
65
|
-
return Object.entries(this.config.platforms)
|
|
66
|
-
.filter(([, config]) => config.preferred)
|
|
67
|
-
.map(([code]) => code);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get platforms by category
|
|
72
|
-
* @param {string} category - Category to filter by
|
|
73
|
-
* @returns {Array} Array of platform codes in the category
|
|
74
|
-
*/
|
|
75
|
-
getPlatformsByCategory(category) {
|
|
76
|
-
return Object.entries(this.config.platforms)
|
|
77
|
-
.filter(([, config]) => config.category === category)
|
|
78
|
-
.map(([code]) => code);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get platform display name
|
|
83
|
-
* @param {string} code - Platform code
|
|
84
|
-
* @returns {string} Display name or code if not found
|
|
85
|
-
*/
|
|
86
|
-
getDisplayName(code) {
|
|
87
|
-
const platform = this.getPlatform(code);
|
|
88
|
-
return platform ? platform.name : code;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Validate platform code format
|
|
93
|
-
* @param {string} code - Platform code to validate
|
|
94
|
-
* @returns {boolean} True if format is valid
|
|
95
|
-
*/
|
|
96
|
-
isValidFormat(code) {
|
|
97
|
-
const conventions = this.config.conventions || {};
|
|
98
|
-
const pattern = conventions.allowed_characters || 'a-z0-9-';
|
|
99
|
-
const maxLength = conventions.max_code_length || 20;
|
|
100
|
-
|
|
101
|
-
const regex = new RegExp(`^[${pattern}]+$`);
|
|
102
|
-
return regex.test(code) && code.length <= maxLength;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Get all platform codes as array
|
|
107
|
-
* @returns {Array} Array of platform codes
|
|
108
|
-
*/
|
|
109
|
-
getCodes() {
|
|
110
|
-
return Object.keys(this.config.platforms);
|
|
111
|
-
}
|
|
112
|
-
config = null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Export singleton instance
|
|
116
|
-
module.exports = new PlatformCodes();
|
package/tools/lib/xml-utils.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Escape XML special characters in a string
|
|
3
|
-
* @param {string} text - The text to escape
|
|
4
|
-
* @returns {string} The escaped text
|
|
5
|
-
*/
|
|
6
|
-
function escapeXml(text) {
|
|
7
|
-
if (!text) return '';
|
|
8
|
-
return text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", ''');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
module.exports = {
|
|
12
|
-
escapeXml,
|
|
13
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow-yaml.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow-yaml.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|