fix(installer): resolve url-source custom modules from custom-modules cache
resolveInstalledModuleYaml previously only searched ~/.bmad/cache/external-modules/, so modules installed via --custom-source <git-url> (cached at ~/.bmad/cache/custom-modules/<host>/<owner>/<repo>/) could not be located on re-install runs. This caused warnings during npx bmad-method install: [warn] collectAgentsFromModuleYaml: could not locate module.yaml for '<name>' [warn] writeCentralConfig: could not locate module.yaml for '<name>' Adds a fallback that walks the custom-modules cache via _findCacheRepoRoots (identifying repo roots by .bmad-source.json or .claude-plugin/, not marketplace.json, so direct-mode modules are also covered), reuses the same searchRoot candidate-path logic, and matches by the discovered yaml's code or name field. Works without needing _resolutionCache to be populated, which fixes the re-install scenario where no --custom-source flag is passed. Closes #2312
This commit is contained in:
parent
be85e5b4a0
commit
b695d1e1bd
|
|
@ -1,5 +1,6 @@
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const os = require('node:os');
|
const os = require('node:os');
|
||||||
|
const yaml = require('yaml');
|
||||||
const fs = require('./fs-native');
|
const fs = require('./fs-native');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,8 +87,11 @@ function getExternalModuleCachePath(moduleName, ...segments) {
|
||||||
* Built-in modules (core, bmm) live under <src>. External official modules are
|
* Built-in modules (core, bmm) live under <src>. External official modules are
|
||||||
* cloned into ~/.bmad/cache/external-modules/<name>/ with varying internal
|
* cloned into ~/.bmad/cache/external-modules/<name>/ with varying internal
|
||||||
* layouts (some at src/module.yaml, some at skills/module.yaml, some nested).
|
* layouts (some at src/module.yaml, some at skills/module.yaml, some nested).
|
||||||
* Local custom-source modules are not cached; their path is read from the
|
* Url-source custom modules are cloned into ~/.bmad/cache/custom-modules/<host>/<owner>/<repo>/
|
||||||
* CustomModuleManager resolution cache set during the same install run.
|
* and are resolved by walking the cache and matching `code` or `name` from the
|
||||||
|
* discovered module.yaml. Local custom-source modules are not cached; their
|
||||||
|
* path is read from the CustomModuleManager resolution cache set during the
|
||||||
|
* same install run.
|
||||||
* This mirrors the candidate-path search in
|
* This mirrors the candidate-path search in
|
||||||
* ExternalModuleManager.findExternalModuleSource but performs no git/network
|
* ExternalModuleManager.findExternalModuleSource but performs no git/network
|
||||||
* work, which keeps it safe to call during manifest writing.
|
* work, which keeps it safe to call during manifest writing.
|
||||||
|
|
@ -150,6 +154,35 @@ async function resolveInstalledModuleYaml(moduleName) {
|
||||||
// Resolution cache unavailable — continue
|
// Resolution cache unavailable — continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback: url-source custom modules cloned to ~/.bmad/cache/custom-modules/.
|
||||||
|
// Walk every cached repo, locate its module.yaml via searchRoot, and match by
|
||||||
|
// the yaml's `code` or `name` field. This works on re-install runs where
|
||||||
|
// _resolutionCache is empty and covers both discovery-mode (with marketplace.json)
|
||||||
|
// and direct-mode modules, since we identify repo roots by .bmad-source.json
|
||||||
|
// (written by cloneRepo) or .claude-plugin/ rather than by marketplace.json.
|
||||||
|
try {
|
||||||
|
const customCacheDir = path.join(os.homedir(), '.bmad', 'cache', 'custom-modules');
|
||||||
|
if (await fs.pathExists(customCacheDir)) {
|
||||||
|
const { CustomModuleManager } = require('./modules/custom-module-manager');
|
||||||
|
const customMgr = new CustomModuleManager();
|
||||||
|
const repoRoots = await customMgr._findCacheRepoRoots(customCacheDir);
|
||||||
|
for (const { repoPath } of repoRoots) {
|
||||||
|
const candidate = await searchRoot(repoPath);
|
||||||
|
if (!candidate) continue;
|
||||||
|
try {
|
||||||
|
const parsed = yaml.parse(await fs.readFile(candidate, 'utf8'));
|
||||||
|
if (parsed && (parsed.code === moduleName || parsed.name === moduleName)) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Malformed yaml — skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Custom-modules cache walk failed — continue
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue