bmad-method 6.3.1-next.18 → 6.3.1-next.19
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
CHANGED
|
@@ -2,7 +2,7 @@ const path = require('node:path');
|
|
|
2
2
|
const fs = require('../fs-native');
|
|
3
3
|
const yaml = require('yaml');
|
|
4
4
|
const crypto = require('node:crypto');
|
|
5
|
-
const {
|
|
5
|
+
const { resolveInstalledModuleYaml } = require('../project-root');
|
|
6
6
|
const prompts = require('../prompts');
|
|
7
7
|
|
|
8
8
|
// Load package.json for version info
|
|
@@ -244,8 +244,17 @@ class ManifestGenerator {
|
|
|
244
244
|
const debug = process.env.BMAD_DEBUG_MANIFEST === 'true';
|
|
245
245
|
|
|
246
246
|
for (const moduleName of this.updatedModules) {
|
|
247
|
-
const moduleYamlPath =
|
|
248
|
-
if (!
|
|
247
|
+
const moduleYamlPath = await resolveInstalledModuleYaml(moduleName);
|
|
248
|
+
if (!moduleYamlPath) {
|
|
249
|
+
// External modules live in ~/.bmad/cache/external-modules, not src/modules.
|
|
250
|
+
// Warn rather than silently skip so missing agent rosters don't vanish
|
|
251
|
+
// from config.toml without notice.
|
|
252
|
+
console.warn(
|
|
253
|
+
`[warn] collectAgentsFromModuleYaml: could not locate module.yaml for '${moduleName}'. ` +
|
|
254
|
+
`Agents declared by this module will not be written to config.toml.`,
|
|
255
|
+
);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
249
258
|
|
|
250
259
|
let moduleDef;
|
|
251
260
|
try {
|
|
@@ -271,7 +280,9 @@ class ManifestGenerator {
|
|
|
271
280
|
}
|
|
272
281
|
|
|
273
282
|
if (debug) {
|
|
274
|
-
console.log(
|
|
283
|
+
console.log(
|
|
284
|
+
`[DEBUG] collectAgentsFromModuleYaml: ${moduleName} contributed ${moduleDef.agents.length} agents from ${moduleYamlPath}`,
|
|
285
|
+
);
|
|
275
286
|
}
|
|
276
287
|
}
|
|
277
288
|
|
|
@@ -410,8 +421,14 @@ class ManifestGenerator {
|
|
|
410
421
|
// team config, so the operator should notice.
|
|
411
422
|
const scopeByModuleKey = {};
|
|
412
423
|
for (const moduleName of this.updatedModules) {
|
|
413
|
-
const moduleYamlPath =
|
|
414
|
-
if (!
|
|
424
|
+
const moduleYamlPath = await resolveInstalledModuleYaml(moduleName);
|
|
425
|
+
if (!moduleYamlPath) {
|
|
426
|
+
console.warn(
|
|
427
|
+
`[warn] writeCentralConfig: could not locate module.yaml for '${moduleName}'. ` +
|
|
428
|
+
`Answers from this module will default to team scope — user-scoped keys may mis-file into config.toml.`,
|
|
429
|
+
);
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
415
432
|
try {
|
|
416
433
|
const parsed = yaml.parse(await fs.readFile(moduleYamlPath, 'utf8'));
|
|
417
434
|
if (!parsed || typeof parsed !== 'object') continue;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
|
+
const os = require('node:os');
|
|
2
3
|
const fs = require('./fs-native');
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -69,9 +70,62 @@ function getModulePath(moduleName, ...segments) {
|
|
|
69
70
|
return getSourcePath('modules', moduleName, ...segments);
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Path to the local external-module clone cache.
|
|
75
|
+
* External official modules (bmb, cis, gds, tea, wds, etc.) are cloned here
|
|
76
|
+
* by ExternalModuleManager during install and are not copied into <src>/modules/.
|
|
77
|
+
*/
|
|
78
|
+
function getExternalModuleCachePath(moduleName, ...segments) {
|
|
79
|
+
const base = process.env.BMAD_EXTERNAL_MODULES_CACHE || path.join(os.homedir(), '.bmad', 'cache', 'external-modules');
|
|
80
|
+
return path.join(base, moduleName, ...segments);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Locate an installed module's `module.yaml` by filesystem lookup only.
|
|
85
|
+
*
|
|
86
|
+
* Built-in modules (core, bmm) live under <src>. External official modules are
|
|
87
|
+
* cloned into ~/.bmad/cache/external-modules/<name>/ with varying internal
|
|
88
|
+
* layouts (some at src/module.yaml, some at skills/module.yaml, some nested).
|
|
89
|
+
* This mirrors the candidate-path search in
|
|
90
|
+
* ExternalModuleManager.findExternalModuleSource but performs no git/network
|
|
91
|
+
* work, which keeps it safe to call during manifest writing.
|
|
92
|
+
*
|
|
93
|
+
* @param {string} moduleName
|
|
94
|
+
* @returns {Promise<string|null>} Absolute path to module.yaml, or null if not found.
|
|
95
|
+
*/
|
|
96
|
+
async function resolveInstalledModuleYaml(moduleName) {
|
|
97
|
+
const builtIn = path.join(getModulePath(moduleName), 'module.yaml');
|
|
98
|
+
if (await fs.pathExists(builtIn)) return builtIn;
|
|
99
|
+
|
|
100
|
+
const cacheRoot = getExternalModuleCachePath(moduleName);
|
|
101
|
+
if (!(await fs.pathExists(cacheRoot))) return null;
|
|
102
|
+
|
|
103
|
+
for (const dir of ['skills', 'src']) {
|
|
104
|
+
const direct = path.join(cacheRoot, dir, 'module.yaml');
|
|
105
|
+
if (await fs.pathExists(direct)) return direct;
|
|
106
|
+
|
|
107
|
+
const dirPath = path.join(cacheRoot, dir);
|
|
108
|
+
if (await fs.pathExists(dirPath)) {
|
|
109
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (!entry.isDirectory()) continue;
|
|
112
|
+
const nested = path.join(dirPath, entry.name, 'module.yaml');
|
|
113
|
+
if (await fs.pathExists(nested)) return nested;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const atRoot = path.join(cacheRoot, 'module.yaml');
|
|
119
|
+
if (await fs.pathExists(atRoot)) return atRoot;
|
|
120
|
+
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
72
124
|
module.exports = {
|
|
73
125
|
getProjectRoot,
|
|
74
126
|
getSourcePath,
|
|
75
127
|
getModulePath,
|
|
128
|
+
getExternalModuleCachePath,
|
|
129
|
+
resolveInstalledModuleYaml,
|
|
76
130
|
findProjectRoot,
|
|
77
131
|
};
|