Compare commits

...

5 Commits

Author SHA1 Message Date
Jonah Schulte 4f5e24dda1
Merge 98a24fe4a7 into b815410904 2026-02-12 21:42:48 -08:00
Adam Biggs b815410904
fix(opencode): remove incorrect mode: primary and restore name field in templates (#1644)
Remove hallucinated mode: primary from opencode-agent template - OpenCode
defaults to mode: all and mode: primary does not enable Tab-switching as
the original PR #1556 claimed. Restore the name frontmatter field across
all OpenCode templates to match the standard pattern used by other IDEs.
2026-02-12 18:58:13 -06:00
Davor Racic 98a24fe4a7
Merge branch 'main' into fix/cli-custom-content-config 2026-02-11 18:39:58 +01:00
Jonah Schulte b9b51cd3fe fix: address PR review feedback for CLI --custom-content config
- Use module display name in sources (name: moduleMeta.name || code)
- Add null guard for empty module.yaml (yaml.parse returns null)
- Remove unused paths property to match promptCustomContentSource shape
2026-02-11 10:17:20 -05:00
Jonah Schulte eeeea6f204 fix: add missing sources/selectedFiles to CLI --custom-content config
The non-interactive --custom-content CLI flag builds a customContentConfig
object missing the `sources`, `selected`, and `selectedFiles` properties
that the installer expects. This causes findModuleSource() to fail with
"Source for module X is not available" because customModulePaths is never
populated.

Align both CLI code paths (modify and fresh install flows) with the config
shape produced by the interactive promptCustomContentSource() method.

Fixes #1623
2026-02-10 22:03:36 -05:00
6 changed files with 39 additions and 3 deletions

View File

@ -1,5 +1,5 @@
--- ---
mode: primary name: '{{name}}'
description: '{{description}}' description: '{{description}}'
--- ---

View File

@ -1,10 +1,12 @@
--- ---
name: '{{name}}'
description: '{{description}}' description: '{{description}}'
--- ---
Execute the BMAD '{{name}}' task. Execute the BMAD '{{name}}' task.
TASK INSTRUCTIONS: TASK INSTRUCTIONS:
1. LOAD the task file from {project-root}/{{bmadFolderName}}/{{path}} 1. LOAD the task file from {project-root}/{{bmadFolderName}}/{{path}}
2. READ its entire contents 2. READ its entire contents
3. FOLLOW every instruction precisely as specified 3. FOLLOW every instruction precisely as specified

View File

@ -1,10 +1,12 @@
--- ---
name: '{{name}}'
description: '{{description}}' description: '{{description}}'
--- ---
Execute the BMAD '{{name}}' tool. Execute the BMAD '{{name}}' tool.
TOOL INSTRUCTIONS: TOOL INSTRUCTIONS:
1. LOAD the tool file from {project-root}/{{bmadFolderName}}/{{path}} 1. LOAD the tool file from {project-root}/{{bmadFolderName}}/{{path}}
2. READ its entire contents 2. READ its entire contents
3. FOLLOW every instruction precisely as specified 3. FOLLOW every instruction precisely as specified

View File

@ -1,4 +1,5 @@
--- ---
name: '{{name}}'
description: '{{description}}' description: '{{description}}'
--- ---
@ -7,6 +8,7 @@ Execute the BMAD '{{name}}' workflow.
CRITICAL: You must load and follow the workflow definition exactly. CRITICAL: You must load and follow the workflow definition exactly.
WORKFLOW INSTRUCTIONS: WORKFLOW INSTRUCTIONS:
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} 1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}}
2. READ its entire contents 2. READ its entire contents
3. FOLLOW every step precisely as specified 3. FOLLOW every step precisely as specified

View File

@ -1,4 +1,5 @@
--- ---
name: '{{name}}'
description: '{{description}}' description: '{{description}}'
--- ---
@ -7,6 +8,7 @@ Execute the BMAD '{{name}}' workflow.
CRITICAL: You must load and follow the workflow definition exactly. CRITICAL: You must load and follow the workflow definition exactly.
WORKFLOW INSTRUCTIONS: WORKFLOW INSTRUCTIONS:
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}} 1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}}
2. READ its entire contents 2. READ its entire contents
3. FOLLOW every step precisely as specified 3. FOLLOW every step precisely as specified

View File

@ -305,6 +305,7 @@ class UI {
// Build custom content config similar to promptCustomContentSource // Build custom content config similar to promptCustomContentSource
const customPaths = []; const customPaths = [];
const selectedModuleIds = []; const selectedModuleIds = [];
const selectedModuleMetas = [];
for (const customPath of paths) { for (const customPath of paths) {
const expandedPath = this.expandUserPath(customPath); const expandedPath = this.expandUserPath(customPath);
@ -326,6 +327,11 @@ class UI {
continue; continue;
} }
if (!moduleMeta) {
await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml is empty`);
continue;
}
if (!moduleMeta.code) { if (!moduleMeta.code) {
await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`); await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`);
continue; continue;
@ -333,14 +339,22 @@ class UI {
customPaths.push(expandedPath); customPaths.push(expandedPath);
selectedModuleIds.push(moduleMeta.code); selectedModuleIds.push(moduleMeta.code);
selectedModuleMetas.push(moduleMeta);
} }
if (customPaths.length > 0) { if (customPaths.length > 0) {
const sources = customPaths.map((p, i) => ({
path: p,
id: selectedModuleIds[i],
name: selectedModuleMetas[i].name || selectedModuleIds[i],
}));
customModuleResult = { customModuleResult = {
selectedCustomModules: selectedModuleIds, selectedCustomModules: selectedModuleIds,
customContentConfig: { customContentConfig: {
hasCustomContent: true, hasCustomContent: true,
paths: customPaths, selected: true,
sources: sources,
selectedFiles: customPaths.map((p) => path.join(p, 'module.yaml')),
selectedModuleIds: selectedModuleIds, selectedModuleIds: selectedModuleIds,
}, },
}; };
@ -446,6 +460,7 @@ class UI {
// Build custom content config similar to promptCustomContentSource // Build custom content config similar to promptCustomContentSource
const customPaths = []; const customPaths = [];
const selectedModuleIds = []; const selectedModuleIds = [];
const selectedModuleMetas = [];
for (const customPath of paths) { for (const customPath of paths) {
const expandedPath = this.expandUserPath(customPath); const expandedPath = this.expandUserPath(customPath);
@ -467,6 +482,11 @@ class UI {
continue; continue;
} }
if (!moduleMeta) {
await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml is empty`);
continue;
}
if (!moduleMeta.code) { if (!moduleMeta.code) {
await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`); await prompts.log.warn(`Skipping custom content path: ${customPath} - module.yaml missing 'code' field`);
continue; continue;
@ -474,12 +494,20 @@ class UI {
customPaths.push(expandedPath); customPaths.push(expandedPath);
selectedModuleIds.push(moduleMeta.code); selectedModuleIds.push(moduleMeta.code);
selectedModuleMetas.push(moduleMeta);
} }
if (customPaths.length > 0) { if (customPaths.length > 0) {
const sources = customPaths.map((p, i) => ({
path: p,
id: selectedModuleIds[i],
name: selectedModuleMetas[i].name || selectedModuleIds[i],
}));
customContentConfig = { customContentConfig = {
hasCustomContent: true, hasCustomContent: true,
paths: customPaths, selected: true,
sources: sources,
selectedFiles: customPaths.map((p) => path.join(p, 'module.yaml')),
selectedModuleIds: selectedModuleIds, selectedModuleIds: selectedModuleIds,
}; };
} }