bmad-method 6.2.3-next.31 → 6.2.3-next.32
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 +1 -1
- package/tools/installer/commands/install.js +1 -0
- package/tools/installer/core/installer.js +8 -3
- package/tools/installer/core/manifest-generator.js +4 -2
- package/tools/installer/core/manifest.js +17 -10
- package/tools/installer/modules/custom-module-manager.js +430 -94
- package/tools/installer/modules/official-modules.js +80 -0
- package/tools/installer/modules/plugin-resolver.js +398 -0
- package/tools/installer/ui.js +248 -33
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@ module.exports = {
|
|
|
22
22
|
['--communication-language <lang>', 'Language for agent communication (default: English)'],
|
|
23
23
|
['--document-output-language <lang>', 'Language for document output (default: English)'],
|
|
24
24
|
['--output-folder <path>', 'Output folder path relative to project root (default: _bmad-output)'],
|
|
25
|
+
['--custom-source <sources>', 'Comma-separated Git URLs or local paths to install custom modules from'],
|
|
25
26
|
['-y, --yes', 'Accept all defaults and skip prompts where possible'],
|
|
26
27
|
],
|
|
27
28
|
action: async (options) => {
|
|
@@ -569,6 +569,7 @@ class Installer {
|
|
|
569
569
|
*/
|
|
570
570
|
async _installOfficialModules(config, paths, officialModuleIds, addResult, isQuickUpdate, officialModules, ctx) {
|
|
571
571
|
const { message, installedModuleNames } = ctx;
|
|
572
|
+
const { CustomModuleManager } = require('../modules/custom-module-manager');
|
|
572
573
|
|
|
573
574
|
for (const moduleName of officialModuleIds) {
|
|
574
575
|
if (installedModuleNames.has(moduleName)) continue;
|
|
@@ -591,11 +592,15 @@ class Installer {
|
|
|
591
592
|
},
|
|
592
593
|
);
|
|
593
594
|
|
|
594
|
-
// Get display name from source module.yaml; version from marketplace.json
|
|
595
|
+
// Get display name from source module.yaml; version from resolution cache or marketplace.json
|
|
595
596
|
const sourcePath = await officialModules.findModuleSource(moduleName, { silent: true });
|
|
596
597
|
const moduleInfo = sourcePath ? await officialModules.getModuleInfo(sourcePath, moduleName, '') : null;
|
|
597
598
|
const displayName = moduleInfo?.name || moduleName;
|
|
598
|
-
|
|
599
|
+
|
|
600
|
+
// Prefer version from resolution cache (accurate for custom/local modules),
|
|
601
|
+
// fall back to marketplace.json walk-up for official modules
|
|
602
|
+
const cachedResolution = CustomModuleManager._resolutionCache.get(moduleName);
|
|
603
|
+
const version = cachedResolution?.version || (sourcePath ? await this._getMarketplaceVersion(sourcePath) : '');
|
|
599
604
|
addResult(displayName, 'ok', '', { moduleCode: moduleName, newVersion: version });
|
|
600
605
|
}
|
|
601
606
|
}
|
|
@@ -1189,7 +1194,7 @@ class Installer {
|
|
|
1189
1194
|
const customMgr = new CustomModuleManager();
|
|
1190
1195
|
for (const moduleId of installedModules) {
|
|
1191
1196
|
if (!availableModules.some((m) => m.id === moduleId)) {
|
|
1192
|
-
const customSource = await customMgr.findModuleSourceByCode(moduleId);
|
|
1197
|
+
const customSource = await customMgr.findModuleSourceByCode(moduleId, { bmadDir });
|
|
1193
1198
|
if (customSource) {
|
|
1194
1199
|
availableModules.push({
|
|
1195
1200
|
id: moduleId,
|
|
@@ -412,7 +412,7 @@ class ManifestGenerator {
|
|
|
412
412
|
// Get existing install date if available
|
|
413
413
|
const existing = existingModulesMap.get(moduleName);
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
const moduleEntry = {
|
|
416
416
|
name: moduleName,
|
|
417
417
|
version: versionInfo.version,
|
|
418
418
|
installDate: existing?.installDate || new Date().toISOString(),
|
|
@@ -420,7 +420,9 @@ class ManifestGenerator {
|
|
|
420
420
|
source: versionInfo.source,
|
|
421
421
|
npmPackage: versionInfo.npmPackage,
|
|
422
422
|
repoUrl: versionInfo.repoUrl,
|
|
423
|
-
}
|
|
423
|
+
};
|
|
424
|
+
if (versionInfo.localPath) moduleEntry.localPath = versionInfo.localPath;
|
|
425
|
+
updatedModules.push(moduleEntry);
|
|
424
426
|
}
|
|
425
427
|
|
|
426
428
|
const manifest = {
|
|
@@ -181,10 +181,10 @@ class Manifest {
|
|
|
181
181
|
|
|
182
182
|
// Handle adding a new module with version info
|
|
183
183
|
if (updates.addModule) {
|
|
184
|
-
const { name, version, source, npmPackage, repoUrl } = updates.addModule;
|
|
184
|
+
const { name, version, source, npmPackage, repoUrl, localPath } = updates.addModule;
|
|
185
185
|
const existing = manifest.modules.find((m) => m.name === name);
|
|
186
186
|
if (!existing) {
|
|
187
|
-
|
|
187
|
+
const entry = {
|
|
188
188
|
name,
|
|
189
189
|
version: version || null,
|
|
190
190
|
installDate: new Date().toISOString(),
|
|
@@ -192,7 +192,9 @@ class Manifest {
|
|
|
192
192
|
source: source || 'external',
|
|
193
193
|
npmPackage: npmPackage || null,
|
|
194
194
|
repoUrl: repoUrl || null,
|
|
195
|
-
}
|
|
195
|
+
};
|
|
196
|
+
if (localPath) entry.localPath = localPath;
|
|
197
|
+
manifest.modules.push(entry);
|
|
196
198
|
}
|
|
197
199
|
}
|
|
198
200
|
|
|
@@ -280,7 +282,7 @@ class Manifest {
|
|
|
280
282
|
|
|
281
283
|
if (existingIndex === -1) {
|
|
282
284
|
// Module doesn't exist, add it
|
|
283
|
-
|
|
285
|
+
const entry = {
|
|
284
286
|
name: moduleName,
|
|
285
287
|
version: options.version || null,
|
|
286
288
|
installDate: new Date().toISOString(),
|
|
@@ -288,7 +290,9 @@ class Manifest {
|
|
|
288
290
|
source: options.source || 'unknown',
|
|
289
291
|
npmPackage: options.npmPackage || null,
|
|
290
292
|
repoUrl: options.repoUrl || null,
|
|
291
|
-
}
|
|
293
|
+
};
|
|
294
|
+
if (options.localPath) entry.localPath = options.localPath;
|
|
295
|
+
manifest.modules.push(entry);
|
|
292
296
|
} else {
|
|
293
297
|
// Module exists, update its version info
|
|
294
298
|
const existing = manifest.modules[existingIndex];
|
|
@@ -298,6 +302,7 @@ class Manifest {
|
|
|
298
302
|
source: options.source || existing.source,
|
|
299
303
|
npmPackage: options.npmPackage === undefined ? existing.npmPackage : options.npmPackage,
|
|
300
304
|
repoUrl: options.repoUrl === undefined ? existing.repoUrl : options.repoUrl,
|
|
305
|
+
localPath: options.localPath === undefined ? existing.localPath : options.localPath,
|
|
301
306
|
lastUpdated: new Date().toISOString(),
|
|
302
307
|
};
|
|
303
308
|
}
|
|
@@ -832,17 +837,19 @@ class Manifest {
|
|
|
832
837
|
};
|
|
833
838
|
}
|
|
834
839
|
|
|
835
|
-
// Check if this is a custom module (from user-provided URL)
|
|
840
|
+
// Check if this is a custom module (from user-provided URL or local path)
|
|
836
841
|
const { CustomModuleManager } = require('../modules/custom-module-manager');
|
|
837
842
|
const customMgr = new CustomModuleManager();
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
843
|
+
const resolved = customMgr.getResolution(moduleName);
|
|
844
|
+
const customSource = await customMgr.findModuleSourceByCode(moduleName, { bmadDir });
|
|
845
|
+
if (customSource || resolved) {
|
|
846
|
+
const customVersion = resolved?.version || (await this._readMarketplaceVersion(moduleName, moduleSourcePath));
|
|
841
847
|
return {
|
|
842
848
|
version: customVersion,
|
|
843
849
|
source: 'custom',
|
|
844
850
|
npmPackage: null,
|
|
845
|
-
repoUrl: null,
|
|
851
|
+
repoUrl: resolved?.repoUrl || null,
|
|
852
|
+
localPath: resolved?.localPath || null,
|
|
846
853
|
};
|
|
847
854
|
}
|
|
848
855
|
|