bmad-method 6.0.0-alpha.16 → 6.0.0-alpha.17
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/.coderabbit.yaml +7 -3
- package/.github/scripts/discord-helpers.sh +21 -2
- package/.github/workflows/discord.yaml +31 -7
- package/.github/workflows/manual-release.yaml +12 -42
- package/.markdownlint-cli2.yaml +2 -2
- package/.prettierignore +2 -2
- package/.vscode/settings.json +1 -1
- package/CHANGELOG.md +96 -2
- package/LICENSE +1 -1
- package/README.md +29 -2
- package/docs/agent-customization-guide.md +10 -10
- package/docs/custom-content-installation.md +100 -196
- package/docs/custom-content.md +122 -0
- package/docs/ide-info/crush.md +1 -1
- package/docs/ide-info/cursor.md +7 -7
- package/docs/ide-info/iflow.md +3 -3
- package/docs/ide-info/opencode.md +1 -1
- package/docs/ide-info/rovo-dev.md +1 -1
- package/docs/index.md +2 -2
- package/docs/installers-bundlers/ide-injections.md +2 -2
- package/docs/installers-bundlers/installers-modules-platforms-reference.md +13 -13
- package/docs/sample-custom-modules/README.md +11 -0
- package/docs/sample-custom-modules/sample-unitary-module/README.md +8 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/commit-poet/commit-poet.agent.yaml +129 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/instructions.md +70 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/bundlers.md +111 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/deploy.md +70 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/docs.md +114 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/installers.md +134 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/modules.md +161 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/knowledge/tests.md +103 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith-sidecar/memories.md +17 -0
- package/docs/sample-custom-modules/sample-unitary-module/agents/toolsmith/toolsmith.agent.yaml +109 -0
- package/docs/sample-custom-modules/sample-unitary-module/module.yaml +8 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-01-init.md +168 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-02-q1.md +155 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-03-q2.md +89 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-04-q3.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-05-q4.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-06-q5.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-07-q6.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-08-q7.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-09-q8.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-10-q9.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-11-q10.md +36 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/steps/step-12-results.md +150 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/templates/csv-headers.template +1 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/quiz-master/workflow.md +54 -0
- package/docs/sample-custom-modules/sample-unitary-module/workflows/wassup/workflow.md +26 -0
- package/docs/sample-custom-modules/sample-wellness-module/README.md +6 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/meditation-guide.agent.yaml +136 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/foo.md +3 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/addition1.md +1 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/insights.md +13 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/instructions.md +30 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/memories.md +13 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion-sidecar/patterns.md +17 -0
- package/docs/sample-custom-modules/sample-wellness-module/agents/wellness-companion/wellness-companion.agent.yaml +120 -0
- package/docs/sample-custom-modules/sample-wellness-module/module.yaml +17 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/daily-checkin/README.md +32 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/daily-checkin/workflow.md +45 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/guided-meditation/README.md +31 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/guided-meditation/workflow.md +45 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/wellness-journal/README.md +31 -0
- package/docs/sample-custom-modules/sample-wellness-module/workflows/wellness-journal/workflow.md +45 -0
- package/docs/v4-to-v6-upgrade.md +27 -27
- package/docs/web-bundles-gemini-gpt-guide.md +6 -458
- package/eslint.config.mjs +2 -2
- package/package.json +1 -1
- package/src/core/agents/bmad-master.agent.yaml +6 -11
- package/src/core/module.yaml +11 -18
- package/src/core/resources/excalidraw/README.md +6 -6
- package/src/core/tasks/advanced-elicitation.xml +3 -3
- package/src/core/tasks/index-docs.xml +1 -1
- package/src/core/tasks/validate-workflow.xml +1 -1
- package/src/core/tasks/workflow.xml +4 -4
- package/src/core/tools/shard-doc.xml +12 -12
- package/src/core/workflows/brainstorming/workflow.md +3 -3
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +2 -2
- package/src/core/workflows/party-mode/workflow.md +4 -4
- package/src/modules/bmb/agents/bmad-builder.agent.yaml +15 -15
- package/src/modules/bmb/{README.md → docs/README.md} +15 -27
- package/src/modules/bmb/docs/agents/agent-compilation.md +3 -3
- package/src/modules/bmb/docs/agents/agent-menu-patterns.md +23 -24
- package/src/modules/bmb/docs/agents/expert-agent-architecture.md +20 -21
- package/src/modules/bmb/docs/agents/simple-agent-architecture.md +17 -52
- package/src/modules/bmb/docs/agents/understanding-agent-types.md +6 -6
- package/src/modules/bmb/docs/workflows/architecture.md +1 -1
- package/src/modules/bmb/docs/workflows/common-workflow-tools.csv +3 -3
- package/src/modules/bmb/docs/workflows/templates/step-01-init-continuable-template.md +1 -1
- package/src/modules/bmb/docs/workflows/templates/step-1b-template.md +1 -1
- package/src/modules/bmb/docs/workflows/templates/step-file.md +3 -3
- package/src/modules/bmb/docs/workflows/templates/step-template.md +3 -3
- package/src/modules/bmb/docs/workflows/templates/workflow-template.md +2 -2
- package/src/modules/bmb/docs/workflows/templates/workflow.md +1 -1
- package/src/modules/bmb/module.yaml +6 -15
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper.agent.yaml +7 -7
- package/src/modules/bmb/reference/agents/module-examples/README.md +3 -4
- package/src/modules/bmb/reference/agents/module-examples/security-engineer.agent.yaml +5 -5
- package/src/modules/bmb/reference/agents/module-examples/trend-analyst.agent.yaml +7 -7
- package/src/modules/bmb/reference/agents/simple-examples/README.md +1 -1
- package/src/modules/bmb/reference/agents/simple-examples/commit-poet.agent.yaml +1 -1
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-01-init.md +1 -1
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-01b-continue.md +1 -1
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-02-profile.md +3 -3
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-03-assessment.md +3 -3
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-04-strategy.md +5 -5
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-05-shopping.md +5 -5
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/steps/step-06-prep-schedule.md +5 -5
- package/src/modules/bmb/reference/workflows/meal-prep-nutrition/workflow.md +2 -2
- package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/README.md +1 -3
- package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/security-engineer.agent.yaml +6 -6
- package/src/modules/bmb/workflows/create-agent/data/reference/agents/module-examples/trend-analyst.agent.yaml +7 -7
- package/src/modules/bmb/workflows/create-agent/data/reference/agents/simple-examples/README.md +1 -1
- package/src/modules/bmb/workflows/create-agent/data/reference/agents/simple-examples/commit-poet.agent.yaml +1 -1
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-01-init.md +1 -1
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-01b-continue.md +1 -1
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-02-profile.md +3 -3
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-03-assessment.md +3 -3
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-04-strategy.md +5 -5
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-05-shopping.md +5 -5
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/steps/step-06-prep-schedule.md +5 -5
- package/src/modules/bmb/workflows/create-agent/data/reference/workflows/meal-prep-nutrition/workflow.md +2 -2
- package/src/modules/bmb/workflows/create-agent/data/validation-complete.md +3 -3
- package/src/modules/bmb/workflows/create-agent/steps/step-01-brainstorm.md +4 -4
- package/src/modules/bmb/workflows/create-agent/steps/step-02-discover.md +6 -10
- package/src/modules/bmb/workflows/create-agent/steps/step-03-persona.md +6 -6
- package/src/modules/bmb/workflows/create-agent/steps/step-04-commands.md +9 -9
- package/src/modules/bmb/workflows/create-agent/steps/step-05-name.md +6 -5
- package/src/modules/bmb/workflows/create-agent/steps/step-06-build.md +19 -57
- package/src/modules/bmb/workflows/create-agent/steps/step-07-validate.md +5 -5
- package/src/modules/bmb/workflows/create-agent/steps/{step-11-celebrate.md → step-08-celebrate.md} +2 -6
- package/src/modules/bmb/workflows/create-agent/templates/agent-plan.template.md +3 -0
- package/src/modules/bmb/workflows/create-agent/templates/expert-agent.template.md +364 -0
- package/src/modules/bmb/workflows/create-agent/templates/simple-agent.template.md +257 -0
- package/src/modules/bmb/workflows/create-agent/workflow.md +2 -35
- package/src/modules/bmb/workflows/create-module/steps/step-01-init.md +4 -4
- package/src/modules/bmb/workflows/create-module/steps/step-01b-continue.md +2 -2
- package/src/modules/bmb/workflows/create-module/steps/step-02-concept.md +4 -4
- package/src/modules/bmb/workflows/create-module/steps/step-03-components.md +4 -4
- package/src/modules/bmb/workflows/create-module/steps/step-04-structure.md +6 -6
- package/src/modules/bmb/workflows/create-module/steps/step-05-config.md +5 -5
- package/src/modules/bmb/workflows/create-module/steps/step-06-agents.md +8 -8
- package/src/modules/bmb/workflows/create-module/steps/step-07-workflows.md +5 -5
- package/src/modules/bmb/workflows/create-module/steps/step-08-installer.md +8 -8
- package/src/modules/bmb/workflows/create-module/steps/step-09-documentation.md +7 -7
- package/src/modules/bmb/workflows/create-module/steps/step-10-roadmap.md +7 -7
- package/src/modules/bmb/workflows/create-module/steps/step-11-validate.md +6 -6
- package/src/modules/bmb/workflows/create-module/templates/agent.template.md +15 -19
- package/src/modules/bmb/workflows/create-module/templates/module.template.yaml +1 -1
- package/src/modules/bmb/workflows/create-module/workflow.md +3 -3
- package/src/modules/bmb/workflows/create-workflow/steps/step-01-init.md +4 -4
- package/src/modules/bmb/workflows/create-workflow/steps/step-02-gather.md +6 -6
- package/src/modules/bmb/workflows/create-workflow/steps/step-03-tools-configuration.md +5 -5
- package/src/modules/bmb/workflows/create-workflow/steps/step-04-plan-review.md +4 -4
- package/src/modules/bmb/workflows/create-workflow/steps/step-05-output-format-design.md +4 -4
- package/src/modules/bmb/workflows/create-workflow/steps/step-06-design.md +11 -11
- package/src/modules/bmb/workflows/create-workflow/steps/step-07-build.md +14 -14
- package/src/modules/bmb/workflows/create-workflow/steps/step-08-review.md +4 -4
- package/src/modules/bmb/workflows/create-workflow/steps/step-09-complete.md +2 -2
- package/src/modules/bmb/workflows/create-workflow/workflow.md +2 -2
- package/src/modules/bmb/workflows/edit-agent/steps/step-01-discover-intent.md +2 -2
- package/src/modules/bmb/workflows/edit-agent/steps/step-02-analyze-agent.md +12 -12
- package/src/modules/bmb/workflows/edit-agent/steps/step-03-propose-changes.md +4 -4
- package/src/modules/bmb/workflows/edit-agent/steps/step-04-apply-changes.md +2 -2
- package/src/modules/bmb/workflows/edit-agent/steps/step-05-validate.md +4 -4
- package/src/modules/bmb/workflows/edit-agent/workflow.md +1 -1
- package/src/modules/bmb/workflows/edit-workflow/steps/step-01-analyze.md +4 -4
- package/src/modules/bmb/workflows/edit-workflow/steps/step-02-discover.md +3 -3
- package/src/modules/bmb/workflows/edit-workflow/steps/step-03-improve.md +6 -6
- package/src/modules/bmb/workflows/edit-workflow/steps/step-04-validate.md +3 -3
- package/src/modules/bmb/workflows/edit-workflow/steps/step-05-compliance-check.md +3 -3
- package/src/modules/bmb/workflows/edit-workflow/workflow.md +1 -1
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-01-validate-goal.md +3 -3
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-02-workflow-validation.md +5 -5
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-03-step-validation.md +6 -6
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-04-file-validation.md +4 -4
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-05-intent-spectrum-validation.md +4 -4
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-06-web-subprocess-validation.md +4 -4
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-07-holistic-analysis.md +4 -4
- package/src/modules/bmb/workflows/workflow-compliance-check/steps/step-08-generate-report.md +3 -3
- package/src/modules/bmb/workflows/workflow-compliance-check/workflow.md +1 -1
- package/src/modules/bmb/workflows-legacy/edit-module/README.md +1 -17
- package/src/modules/bmb/workflows-legacy/edit-module/checklist.md +3 -4
- package/src/modules/bmb/workflows-legacy/edit-module/instructions.md +4 -5
- package/src/modules/bmb/workflows-legacy/edit-module/workflow.yaml +10 -10
- package/src/modules/bmb/workflows-legacy/module-brief/README.md +2 -2
- package/src/modules/bmb/workflows-legacy/module-brief/instructions.md +2 -2
- package/src/modules/bmb/workflows-legacy/module-brief/workflow.yaml +4 -4
- package/src/modules/bmgd/README.md +1 -1
- package/src/modules/bmgd/agents/game-architect.agent.yaml +6 -6
- package/src/modules/bmgd/agents/game-designer.agent.yaml +7 -7
- package/src/modules/bmgd/agents/game-dev.agent.yaml +10 -10
- package/src/modules/bmgd/agents/game-scrum-master.agent.yaml +21 -21
- package/src/modules/bmgd/module.yaml +2 -7
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/instructions.md +1 -1
- package/src/modules/bmgd/workflows/1-preproduction/brainstorm-game/workflow.yaml +9 -9
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/instructions.md +1 -1
- package/src/modules/bmgd/workflows/1-preproduction/game-brief/workflow.yaml +8 -8
- package/src/modules/bmgd/workflows/2-design/gdd/instructions-gdd.md +4 -4
- package/src/modules/bmgd/workflows/2-design/gdd/workflow.yaml +30 -30
- package/src/modules/bmgd/workflows/2-design/narrative/instructions-narrative.md +1 -1
- package/src/modules/bmgd/workflows/2-design/narrative/workflow.yaml +5 -5
- package/src/modules/bmgd/workflows/3-technical/game-architecture/instructions.md +1 -1
- package/src/modules/bmgd/workflows/3-technical/game-architecture/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/code-review/instructions.md +4 -4
- package/src/modules/bmgd/workflows/4-production/code-review/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/correct-course/checklist.md +1 -1
- package/src/modules/bmgd/workflows/4-production/correct-course/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/correct-course/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/create-story/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/create-story/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/dev-story/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/dev-story/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/checklist.md +1 -1
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/epic-tech-context/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/retrospective/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +3 -3
- package/src/modules/bmgd/workflows/4-production/sprint-planning/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/sprint-planning/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/story-context/checklist.md +1 -1
- package/src/modules/bmgd/workflows/4-production/story-context/context-template.xml +2 -2
- package/src/modules/bmgd/workflows/4-production/story-context/instructions.md +2 -2
- package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/story-done/instructions.md +1 -1
- package/src/modules/bmgd/workflows/4-production/story-done/workflow.yaml +2 -2
- package/src/modules/bmgd/workflows/4-production/story-ready/instructions.md +1 -1
- package/src/modules/bmgd/workflows/4-production/story-ready/workflow.yaml +2 -2
- package/src/modules/bmm/README.md +1 -1
- package/src/modules/bmm/agents/analyst.agent.yaml +9 -9
- package/src/modules/bmm/agents/architect.agent.yaml +8 -8
- package/src/modules/bmm/agents/dev.agent.yaml +5 -5
- package/src/modules/bmm/agents/pm.agent.yaml +8 -8
- package/src/modules/bmm/agents/quick-flow-solo-dev.agent.yaml +5 -5
- package/src/modules/bmm/agents/sm.agent.yaml +11 -11
- package/src/modules/bmm/agents/tea.agent.yaml +13 -13
- package/src/modules/bmm/agents/tech-writer.agent.yaml +9 -9
- package/src/modules/bmm/agents/ux-designer.agent.yaml +6 -6
- package/src/modules/bmm/docs/agents-guide.md +16 -14
- package/src/modules/bmm/docs/brownfield-guide.md +6 -6
- package/src/modules/bmm/docs/enterprise-agentic-development.md +3 -3
- package/src/modules/bmm/docs/faq.md +5 -18
- package/src/modules/bmm/docs/glossary.md +3 -4
- package/src/modules/bmm/docs/images/README.md +1 -1
- package/src/modules/bmm/docs/images/workflow-method-greenfield.excalidraw +8 -8
- package/src/modules/bmm/docs/party-mode.md +3 -3
- package/src/modules/bmm/docs/quick-flow-solo-dev.md +5 -5
- package/src/modules/bmm/docs/quick-spec-flow.md +2 -16
- package/src/modules/bmm/docs/quick-start.md +3 -3
- package/src/modules/bmm/docs/test-architecture.md +15 -23
- package/src/modules/bmm/docs/troubleshooting.md +6 -25
- package/src/modules/bmm/docs/workflow-document-project-reference.md +1 -1
- package/src/modules/bmm/docs/workflows-implementation.md +3 -4
- package/src/modules/bmm/module.yaml +25 -23
- package/src/modules/bmm/testarch/knowledge/overview.md +0 -1
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-01-init.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-01b-continue.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-02-vision.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-03-users.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-04-metrics.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-05-scope.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/steps/step-06-complete.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/workflow.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/research/workflow.md +2 -2
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +4 -4
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.md +2 -2
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-01-init.md +1 -1
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-01b-continue.md +1 -1
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-02-discovery.md +3 -3
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-03-success.md +7 -7
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-04-journeys.md +8 -8
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-05-domain.md +12 -12
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-06-innovation.md +12 -12
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-07-project-type.md +10 -10
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-08-scoping.md +7 -7
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-09-functional.md +9 -9
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-10-nonfunctional.md +9 -9
- package/src/modules/bmm/workflows/2-plan-workflows/prd/steps/step-11-complete.md +1 -1
- package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.md +2 -2
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-01-document-discovery.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-02-prd-analysis.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-03-epic-coverage-validation.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-04-ux-alignment.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-05-epic-quality-review.md +2 -2
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/steps/step-06-final-assessment.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/workflow.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-01-init.md +1 -1
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-02-context.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-03-starter.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-04-decisions.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-05-patterns.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-06-structure.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-07-validation.md +4 -4
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-08-complete.md +3 -3
- package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/workflow.md +2 -2
- package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +3 -3
- package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +3 -3
- package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +3 -3
- package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +3 -3
- package/src/modules/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.md +3 -3
- package/src/modules/bmm/workflows/4-implementation/code-review/instructions.xml +4 -3
- package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +1 -1
- package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +2 -2
- package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +2 -2
- package/src/modules/bmm/workflows/4-implementation/create-story/instructions.xml +5 -5
- package/src/modules/bmm/workflows/4-implementation/create-story/template.md +3 -5
- package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +2 -2
- package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.xml +11 -8
- package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +3 -3
- package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +3 -3
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +15 -22
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +4 -5
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/4-implementation/sprint-status/instructions.md +90 -35
- package/src/modules/bmm/workflows/4-implementation/sprint-status/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/bmad-quick-flow/create-tech-spec/workflow.yaml +5 -5
- package/src/modules/bmm/workflows/bmad-quick-flow/quick-dev/workflow.yaml +7 -7
- package/src/modules/bmm/workflows/document-project/instructions.md +5 -5
- package/src/modules/bmm/workflows/document-project/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +5 -5
- package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +5 -5
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/instructions.md +1 -1
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/workflow.yaml +6 -6
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/instructions.md +2 -2
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/workflow.yaml +6 -6
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/instructions.md +2 -2
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/workflow.yaml +6 -6
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/instructions.md +1 -1
- package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/workflow.yaml +6 -6
- package/src/modules/bmm/workflows/generate-project-context/steps/step-01-discover.md +2 -2
- package/src/modules/bmm/workflows/generate-project-context/steps/step-02-generate.md +3 -3
- package/src/modules/bmm/workflows/generate-project-context/steps/step-03-complete.md +2 -2
- package/src/modules/bmm/workflows/generate-project-context/workflow.md +5 -5
- package/src/modules/bmm/workflows/testarch/atdd/instructions.md +2 -2
- package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/automate/instructions.md +2 -2
- package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/ci/instructions.md +1 -1
- package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/framework/instructions.md +3 -3
- package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +1 -1
- package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/test-design/instructions.md +3 -3
- package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +1 -1
- package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +10 -4
- package/src/modules/bmm/workflows/testarch/test-review/instructions.md +1 -1
- package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/testarch/trace/instructions.md +6 -6
- package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +2 -2
- package/src/modules/bmm/workflows/workflow-status/init/instructions.md +1 -1
- package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +4 -4
- package/src/modules/bmm/workflows/workflow-status/instructions.md +3 -3
- package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +1 -1
- package/src/modules/bmm/workflows/workflow-status/workflow.yaml +2 -2
- package/src/modules/cis/agents/brainstorming-coach.agent.yaml +4 -4
- package/src/modules/cis/agents/creative-problem-solver.agent.yaml +4 -4
- package/src/modules/cis/agents/design-thinking-coach.agent.yaml +4 -4
- package/src/modules/cis/agents/innovation-strategist.agent.yaml +4 -4
- package/src/modules/cis/agents/presentation-master.agent.yaml +3 -3
- package/src/modules/cis/agents/storyteller/storyteller-sidecar/stories-told.md +7 -0
- package/src/modules/cis/agents/storyteller/storyteller-sidecar/story-preferences.md +7 -0
- package/src/modules/cis/agents/{storyteller.agent.yaml → storyteller/storyteller.agent.yaml} +9 -4
- package/src/modules/cis/module.yaml +3 -7
- package/src/modules/cis/{README.md → readme.md} +1 -1
- package/src/modules/cis/workflows/README.md +1 -1
- package/src/modules/cis/workflows/design-thinking/instructions.md +2 -2
- package/src/modules/cis/workflows/design-thinking/workflow.yaml +7 -7
- package/src/modules/cis/workflows/innovation-strategy/instructions.md +2 -2
- package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +7 -7
- package/src/modules/cis/workflows/problem-solving/instructions.md +2 -2
- package/src/modules/cis/workflows/problem-solving/workflow.yaml +7 -7
- package/src/modules/cis/workflows/storytelling/instructions.md +2 -2
- package/src/modules/cis/workflows/storytelling/workflow.yaml +7 -7
- package/src/utility/agent-components/activation-rules.txt +7 -0
- package/src/utility/agent-components/activation-steps.txt +13 -0
- package/src/utility/agent-components/agent-command-header.md +1 -0
- package/src/utility/{templates → agent-components}/agent.customize.template.yaml +0 -1
- package/src/utility/agent-components/handler-action.txt +4 -0
- package/src/utility/agent-components/handler-exec.txt +6 -0
- package/src/utility/agent-components/handler-multi.txt +14 -0
- package/src/utility/agent-components/handler-tmpl.txt +5 -0
- package/src/utility/agent-components/handler-validate-workflow.txt +7 -0
- package/src/utility/agent-components/handler-workflow.txt +10 -0
- package/src/utility/agent-components/menu-handlers.txt +6 -0
- package/test/README.md +1 -1
- package/test/test-agent-schema.js +2 -2
- package/tools/cli/README.md +1 -607
- package/tools/cli/commands/build.js +7 -7
- package/tools/cli/commands/install.js +9 -20
- package/tools/cli/commands/list.js +13 -1
- package/tools/cli/installers/lib/core/config-collector.js +224 -59
- package/tools/cli/installers/lib/core/custom-module-cache.js +18 -10
- package/tools/cli/installers/lib/core/dependency-resolver.js +2 -2
- package/tools/cli/installers/lib/core/detector.js +16 -16
- package/tools/cli/installers/lib/core/ide-config-manager.js +9 -7
- package/tools/cli/installers/lib/core/installer.js +540 -946
- package/tools/cli/installers/lib/core/manifest-generator.js +43 -40
- package/tools/cli/installers/lib/core/manifest.js +23 -20
- package/tools/cli/installers/lib/custom/handler.js +16 -46
- package/tools/cli/installers/lib/ide/_base-ide.js +26 -33
- package/tools/cli/installers/lib/ide/antigravity.js +3 -3
- package/tools/cli/installers/lib/ide/claude-code.js +3 -3
- package/tools/cli/installers/lib/ide/codex.js +2 -2
- package/tools/cli/installers/lib/ide/gemini.js +6 -6
- package/tools/cli/installers/lib/ide/kiro-cli.js +2 -2
- package/tools/cli/installers/lib/ide/opencode.js +2 -2
- package/tools/cli/installers/lib/ide/roo.js +15 -5
- package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +2 -2
- package/tools/cli/installers/lib/ide/shared/module-injections.js +2 -2
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +2 -2
- package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +4 -4
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
- package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +3 -3
- package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +3 -3
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +1 -1
- package/tools/cli/installers/lib/modules/manager.js +304 -313
- package/tools/cli/lib/activation-builder.js +8 -13
- package/tools/cli/lib/agent/compiler.js +68 -168
- package/tools/cli/lib/agent/installer.js +8 -128
- package/tools/cli/lib/agent-analyzer.js +2 -2
- package/tools/cli/lib/agent-party-generator.js +5 -17
- package/tools/cli/lib/config.js +2 -2
- package/tools/cli/lib/platform-codes.js +2 -2
- package/tools/cli/lib/ui.js +631 -568
- package/tools/cli/lib/xml-handler.js +3 -55
- package/tools/cli/lib/yaml-format.js +4 -6
- package/tools/cli/lib/yaml-xml-builder.js +14 -26
- package/tools/flattener/ignoreRules.js +1 -1
- package/tools/flattener/xml.js +1 -7
- package/tools/lib/xml-utils.js +13 -0
- package/tools/migrate-custom-module-paths.js +2 -2
- package/tools/validate-agent-schema.js +2 -2
- package/docs/v6-open-items.md +0 -17
- package/src/core/agents/bmad-web-orchestrator.agent.xml +0 -113
- package/src/modules/bmb/_module-installer/installer.js +0 -76
- package/src/modules/bmb/docs/agents/module-agent-architecture.md +0 -366
- package/src/modules/bmb/workflows/create-agent/steps/step-08-setup.md +0 -179
- package/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md +0 -197
- package/src/modules/bmb/workflows/create-agent/steps/step-10-build-tools.md +0 -180
- package/src/modules/bmb/workflows/create-agent/templates/agent_commands.md +0 -21
- package/src/modules/bmb/workflows/create-agent/templates/agent_persona.md +0 -25
- package/src/modules/bmb/workflows/create-agent/templates/agent_purpose_and_type.md +0 -23
- package/src/modules/bmm/tasks/daily-standup.xml +0 -85
- package/src/modules/cis/agents/README.md +0 -104
- package/src/utility/models/action-command-header.md +0 -0
- package/src/utility/models/agent-activation-ide.xml +0 -51
- package/src/utility/models/agent-activation-web.xml +0 -50
- package/src/utility/models/agent-command-header.md +0 -1
- package/src/utility/models/agent-config-template.md +0 -23
- package/src/utility/models/agent-in-team-activation.xml +0 -3
- package/src/utility/models/fragments/activation-rules.xml +0 -7
- package/src/utility/models/fragments/activation-steps.xml +0 -16
- package/src/utility/models/fragments/handler-action.xml +0 -4
- package/src/utility/models/fragments/handler-exec.xml +0 -6
- package/src/utility/models/fragments/handler-multi.xml +0 -14
- package/src/utility/models/fragments/handler-tmpl.xml +0 -5
- package/src/utility/models/fragments/handler-validate-workflow.xml +0 -7
- package/src/utility/models/fragments/handler-workflow.xml +0 -9
- package/src/utility/models/fragments/menu-handlers.xml +0 -6
- package/src/utility/models/fragments/web-bundle-activation-steps.xml +0 -32
- package/tools/cli/bundlers/bundle-web.js +0 -179
- package/tools/cli/bundlers/test-analyst.js +0 -28
- package/tools/cli/bundlers/test-bundler.js +0 -118
- package/tools/cli/bundlers/web-bundler.js +0 -1754
- package/tools/cli/installers/lib/core/post-install-sidecar-replacement.js +0 -79
- package/tools/cli/lib/replace-project-root.js +0 -239
- package/tools/cli/regenerate-manifests.js +0 -27
- package/tools/cli/test-yaml-builder.js +0 -43
- /package/src/modules/bmgd/workflows/4-production/code-review/{backlog_template.md → backlog-template.md} +0 -0
- /package/src/modules/bmm/workflows/1-analysis/{product-brief → create-product-brief}/product-brief.template.md +0 -0
- /package/src/modules/bmm/workflows/3-solutioning/{implementation-readiness → check-implementation-readiness}/templates/readiness-report-template.md +0 -0
- /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/architecture-decision-template.md +0 -0
- /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/data/domain-complexity.csv +0 -0
- /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/data/project-types.csv +0 -0
- /package/src/modules/bmm/workflows/3-solutioning/{architecture → create-architecture}/steps/step-01b-continue.md +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/_shared/excalidraw-library.json +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/_shared/excalidraw-templates.yaml +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-dataflow/checklist.md +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-diagram/checklist.md +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-flowchart/checklist.md +0 -0
- /package/src/modules/bmm/workflows/{diagrams → excalidraw-diagrams}/create-wireframe/checklist.md +0 -0
- /package/src/utility/{models/fragments/handler-data.xml → agent-components/handler-data.txt} +0 -0
package/tools/cli/lib/ui.js
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File: tools/cli/lib/ui.js
|
|
3
|
-
*
|
|
4
|
-
* BMAD Method - Business Model Agile Development Method
|
|
5
|
-
* Repository: https://github.com/paulpreibisch/BMAD-METHOD
|
|
6
|
-
*
|
|
7
|
-
* Copyright (c) 2025 Paul Preibisch
|
|
8
|
-
* Licensed under the Apache License, Version 2.0
|
|
9
|
-
*
|
|
10
|
-
* ---
|
|
11
|
-
*
|
|
12
|
-
* @fileoverview Interactive installation prompts and user input collection for BMAD CLI
|
|
13
|
-
* @context Guides users through installation configuration including core settings, modules, IDEs, and optional AgentVibes TTS
|
|
14
|
-
* @architecture Facade pattern - presents unified installation flow, delegates to Detector/ConfigCollector/IdeManager for specifics
|
|
15
|
-
* @dependencies inquirer (prompts), chalk (formatting), detector.js (existing installation detection)
|
|
16
|
-
* @entrypoints Called by install.js command via ui.promptInstall(), returns complete configuration object
|
|
17
|
-
* @patterns Progressive disclosure (prompts in order), early IDE selection (Windows compat), AgentVibes auto-detection
|
|
18
|
-
* @related installer.js (consumes config), AgentVibes#34 (TTS integration), promptAgentVibes()
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
1
|
const chalk = require('chalk');
|
|
22
2
|
const inquirer = require('inquirer');
|
|
23
3
|
const path = require('node:path');
|
|
@@ -30,16 +10,15 @@ const { CustomHandler } = require('../installers/lib/custom/handler');
|
|
|
30
10
|
* UI utilities for the installer
|
|
31
11
|
*/
|
|
32
12
|
class UI {
|
|
33
|
-
constructor() {}
|
|
34
|
-
|
|
35
13
|
/**
|
|
36
14
|
* Prompt for installation configuration
|
|
37
15
|
* @returns {Object} Installation configuration
|
|
38
16
|
*/
|
|
39
17
|
async promptInstall() {
|
|
40
18
|
CLIUtils.displayLogo();
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
|
|
20
|
+
// Display changelog link
|
|
21
|
+
console.log(chalk.cyan('\n📋 Read the latest updates: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md\n'));
|
|
43
22
|
|
|
44
23
|
const confirmedDirectory = await this.getConfirmedDirectory();
|
|
45
24
|
|
|
@@ -53,21 +32,138 @@ class UI {
|
|
|
53
32
|
await installer.handleLegacyV4Migration(confirmedDirectory, legacyV4);
|
|
54
33
|
}
|
|
55
34
|
|
|
56
|
-
// Check
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
// Check for legacy folders and prompt for rename before showing any menus
|
|
36
|
+
let hasLegacyCfg = false;
|
|
37
|
+
let hasLegacyBmadFolder = false;
|
|
38
|
+
let bmadDir = null;
|
|
39
|
+
let legacyBmadPath = null;
|
|
40
|
+
|
|
41
|
+
// First check for legacy .bmad folder (instead of _bmad)
|
|
42
|
+
// Only check if directory exists
|
|
43
|
+
if (await fs.pathExists(confirmedDirectory)) {
|
|
44
|
+
const entries = await fs.readdir(confirmedDirectory, { withFileTypes: true });
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
if (entry.isDirectory() && entry.name === '.bmad') {
|
|
47
|
+
hasLegacyBmadFolder = true;
|
|
48
|
+
legacyBmadPath = path.join(confirmedDirectory, '.bmad');
|
|
49
|
+
bmadDir = legacyBmadPath;
|
|
50
|
+
|
|
51
|
+
// Check if it has _cfg folder
|
|
52
|
+
const cfgPath = path.join(legacyBmadPath, '_cfg');
|
|
53
|
+
if (await fs.pathExists(cfgPath)) {
|
|
54
|
+
hasLegacyCfg = true;
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If no .bmad found, check for current installations
|
|
62
|
+
if (!hasLegacyBmadFolder) {
|
|
63
|
+
const bmadResult = await installer.findBmadDir(confirmedDirectory);
|
|
64
|
+
bmadDir = bmadResult.bmadDir;
|
|
65
|
+
hasLegacyCfg = bmadResult.hasLegacyCfg;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (hasLegacyBmadFolder || hasLegacyCfg) {
|
|
69
|
+
console.log(chalk.yellow('\n⚠️ Legacy folder structure detected'));
|
|
70
|
+
|
|
71
|
+
let message = 'The following folders need to be renamed:\n';
|
|
72
|
+
if (hasLegacyBmadFolder) {
|
|
73
|
+
message += chalk.dim(` • ".bmad" → "_bmad"\n`);
|
|
74
|
+
}
|
|
75
|
+
if (hasLegacyCfg) {
|
|
76
|
+
message += chalk.dim(` • "_cfg" → "_config"\n`);
|
|
77
|
+
}
|
|
78
|
+
console.log(message);
|
|
79
|
+
|
|
80
|
+
const { shouldRename } = await inquirer.prompt([
|
|
81
|
+
{
|
|
82
|
+
type: 'confirm',
|
|
83
|
+
name: 'shouldRename',
|
|
84
|
+
message: 'Would you like the installer to rename these folders for you?',
|
|
85
|
+
default: true,
|
|
86
|
+
},
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
if (!shouldRename) {
|
|
90
|
+
console.log(chalk.red('\n❌ Installation cancelled'));
|
|
91
|
+
console.log(chalk.dim('You must manually rename the folders before proceeding:'));
|
|
92
|
+
if (hasLegacyBmadFolder) {
|
|
93
|
+
console.log(chalk.dim(` • Rename ".bmad" to "_bmad"`));
|
|
94
|
+
}
|
|
95
|
+
if (hasLegacyCfg) {
|
|
96
|
+
console.log(chalk.dim(` • Rename "_cfg" to "_config"`));
|
|
97
|
+
}
|
|
98
|
+
process.exit(0);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Perform the renames
|
|
103
|
+
const ora = require('ora');
|
|
104
|
+
const spinner = ora('Updating folder structure...').start();
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
// First rename .bmad to _bmad if needed
|
|
108
|
+
if (hasLegacyBmadFolder) {
|
|
109
|
+
const newBmadPath = path.join(confirmedDirectory, '_bmad');
|
|
110
|
+
await fs.move(legacyBmadPath, newBmadPath);
|
|
111
|
+
bmadDir = newBmadPath;
|
|
112
|
+
spinner.succeed('Renamed ".bmad" to "_bmad"');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Then rename _cfg to _config if needed
|
|
116
|
+
if (hasLegacyCfg) {
|
|
117
|
+
spinner.start('Renaming configuration folder...');
|
|
118
|
+
const oldCfgPath = path.join(bmadDir, '_cfg');
|
|
119
|
+
const newCfgPath = path.join(bmadDir, '_config');
|
|
120
|
+
await fs.move(oldCfgPath, newCfgPath);
|
|
121
|
+
spinner.succeed('Renamed "_cfg" to "_config"');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
spinner.succeed('Folder structure updated successfully');
|
|
125
|
+
} catch (error) {
|
|
126
|
+
spinner.fail('Failed to update folder structure');
|
|
127
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check if there's an existing BMAD installation (after any folder renames)
|
|
61
133
|
const hasExistingInstall = await fs.pathExists(bmadDir);
|
|
62
134
|
|
|
63
|
-
//
|
|
135
|
+
// Collect IDE tool selection early - we need this to know if we should ask about TTS
|
|
136
|
+
let toolSelection;
|
|
137
|
+
let agentVibesConfig = { enabled: false, alreadyInstalled: false };
|
|
138
|
+
let claudeCodeSelected = false;
|
|
139
|
+
|
|
140
|
+
if (!hasExistingInstall) {
|
|
141
|
+
// For new installations, collect IDE selection first
|
|
142
|
+
// We don't have modules yet, so pass empty array
|
|
143
|
+
toolSelection = await this.promptToolSelection(confirmedDirectory, []);
|
|
144
|
+
|
|
145
|
+
// Check if Claude Code was selected
|
|
146
|
+
claudeCodeSelected = toolSelection.ides && toolSelection.ides.includes('claude-code');
|
|
147
|
+
|
|
148
|
+
// If Claude Code was selected, ask about TTS
|
|
149
|
+
if (claudeCodeSelected) {
|
|
150
|
+
const { enableTts } = await inquirer.prompt([
|
|
151
|
+
{
|
|
152
|
+
type: 'confirm',
|
|
153
|
+
name: 'enableTts',
|
|
154
|
+
message: 'Claude Code supports TTS (Text-to-Speech). Would you like to enable it?',
|
|
155
|
+
default: false,
|
|
156
|
+
},
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
if (enableTts) {
|
|
160
|
+
agentVibesConfig = { enabled: true, alreadyInstalled: false };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
64
165
|
let customContentConfig = { hasCustomContent: false };
|
|
65
|
-
if (hasExistingInstall) {
|
|
66
|
-
// Existing installation - prompt to add/update custom content
|
|
67
|
-
customContentConfig = await this.promptCustomContentForExisting();
|
|
68
|
-
} else {
|
|
69
|
-
// New installation - we'll prompt after creating the directory structure
|
|
70
|
-
// For now, set a flag to indicate we should ask later
|
|
166
|
+
if (!hasExistingInstall) {
|
|
71
167
|
customContentConfig._shouldAsk = true;
|
|
72
168
|
}
|
|
73
169
|
|
|
@@ -76,19 +172,33 @@ class UI {
|
|
|
76
172
|
|
|
77
173
|
// Only show action menu if there's an existing installation
|
|
78
174
|
if (hasExistingInstall) {
|
|
175
|
+
// Get version information
|
|
176
|
+
const { existingInstall } = await this.getExistingInstallation(confirmedDirectory);
|
|
177
|
+
const packageJsonPath = path.join(__dirname, '../../../package.json');
|
|
178
|
+
const currentVersion = require(packageJsonPath).version;
|
|
179
|
+
const installedVersion = existingInstall.version || 'unknown';
|
|
180
|
+
|
|
181
|
+
// Build menu choices dynamically
|
|
182
|
+
const choices = [];
|
|
183
|
+
|
|
184
|
+
// Always show Quick Update first (allows refreshing installation even on same version)
|
|
185
|
+
if (installedVersion !== 'unknown') {
|
|
186
|
+
choices.push({
|
|
187
|
+
name: `Quick Update (v${installedVersion} → v${currentVersion})`,
|
|
188
|
+
value: 'quick-update',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Common actions
|
|
193
|
+
choices.push({ name: 'Modify BMAD Installation', value: 'update' });
|
|
194
|
+
|
|
79
195
|
const promptResult = await inquirer.prompt([
|
|
80
196
|
{
|
|
81
197
|
type: 'list',
|
|
82
198
|
name: 'actionType',
|
|
83
199
|
message: 'What would you like to do?',
|
|
84
|
-
choices:
|
|
85
|
-
|
|
86
|
-
{ name: 'Modify BMAD Installation (Confirm or change each setting)', value: 'update' },
|
|
87
|
-
{ name: 'Remove BMad Folder and Reinstall (Full clean install - BMad Customization Will Be Lost)', value: 'reinstall' },
|
|
88
|
-
{ name: 'Compile Agents (Quick rebuild of all agent .md files)', value: 'compile' },
|
|
89
|
-
{ name: 'Cancel', value: 'cancel' },
|
|
90
|
-
],
|
|
91
|
-
default: 'quick-update',
|
|
200
|
+
choices: choices,
|
|
201
|
+
default: choices[0].value, // Use the first option as default
|
|
92
202
|
},
|
|
93
203
|
]);
|
|
94
204
|
|
|
@@ -105,163 +215,141 @@ class UI {
|
|
|
105
215
|
};
|
|
106
216
|
}
|
|
107
217
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
218
|
+
// If actionType === 'update', handle it with the new flow
|
|
219
|
+
// Return early with modify configuration
|
|
220
|
+
if (actionType === 'update') {
|
|
221
|
+
// Get existing installation info
|
|
222
|
+
const { installedModuleIds } = await this.getExistingInstallation(confirmedDirectory);
|
|
223
|
+
|
|
224
|
+
console.log(chalk.dim(` Found existing modules: ${[...installedModuleIds].join(', ')}`));
|
|
225
|
+
const { changeModuleSelection } = await inquirer.prompt([
|
|
226
|
+
{
|
|
227
|
+
type: 'confirm',
|
|
228
|
+
name: 'changeModuleSelection',
|
|
229
|
+
message: 'Modify official module selection (BMad Method, BMad Builder, Creative Innovation Suite)?',
|
|
230
|
+
default: false,
|
|
231
|
+
},
|
|
232
|
+
]);
|
|
233
|
+
|
|
234
|
+
let selectedModules = [];
|
|
235
|
+
if (changeModuleSelection) {
|
|
236
|
+
// Show module selection with existing modules pre-selected
|
|
237
|
+
const moduleChoices = await this.getModuleChoices(new Set(installedModuleIds), { hasCustomContent: false });
|
|
238
|
+
selectedModules = await this.selectModules(moduleChoices, [...installedModuleIds]);
|
|
239
|
+
} else {
|
|
240
|
+
selectedModules = [...installedModuleIds];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// After module selection, ask about custom modules
|
|
244
|
+
const customModuleResult = await this.handleCustomModulesInModifyFlow(confirmedDirectory, selectedModules);
|
|
245
|
+
|
|
246
|
+
// Merge any selected custom modules
|
|
247
|
+
if (customModuleResult.selectedCustomModules.length > 0) {
|
|
248
|
+
selectedModules.push(...customModuleResult.selectedCustomModules);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Get tool selection
|
|
252
|
+
const toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
|
|
253
|
+
|
|
254
|
+
// TTS configuration - ask right after tool selection (matches new install flow)
|
|
255
|
+
const hasClaudeCode = toolSelection.ides && toolSelection.ides.includes('claude-code');
|
|
256
|
+
let enableTts = false;
|
|
257
|
+
|
|
258
|
+
if (hasClaudeCode) {
|
|
259
|
+
const { enableTts: enable } = await inquirer.prompt([
|
|
260
|
+
{
|
|
261
|
+
type: 'confirm',
|
|
262
|
+
name: 'enableTts',
|
|
263
|
+
message: 'Claude Code supports TTS (Text-to-Speech). Would you like to enable it?',
|
|
264
|
+
default: false,
|
|
265
|
+
},
|
|
266
|
+
]);
|
|
267
|
+
enableTts = enable;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Core config with existing defaults (ask after TTS)
|
|
271
|
+
const coreConfig = await this.collectCoreConfig(confirmedDirectory);
|
|
115
272
|
|
|
116
|
-
// Handle cancel
|
|
117
|
-
if (actionType === 'cancel') {
|
|
118
273
|
return {
|
|
119
|
-
actionType: '
|
|
274
|
+
actionType: 'update',
|
|
120
275
|
directory: confirmedDirectory,
|
|
276
|
+
installCore: true,
|
|
277
|
+
modules: selectedModules,
|
|
278
|
+
ides: toolSelection.ides,
|
|
279
|
+
skipIde: toolSelection.skipIde,
|
|
280
|
+
coreConfig: coreConfig,
|
|
281
|
+
customContent: customModuleResult.customContentConfig,
|
|
282
|
+
enableAgentVibes: enableTts,
|
|
283
|
+
agentVibesInstalled: false,
|
|
121
284
|
};
|
|
122
285
|
}
|
|
123
|
-
|
|
124
|
-
// Handle reinstall - DON'T return early, let it flow through configuration collection
|
|
125
|
-
// The installer will handle deletion when it sees actionType === 'reinstall'
|
|
126
|
-
// For now, just note that we're in reinstall mode and continue below
|
|
127
|
-
|
|
128
|
-
// If actionType === 'update' or 'reinstall', continue with normal flow below
|
|
129
286
|
}
|
|
130
287
|
|
|
288
|
+
// This section is only for new installations (update returns early above)
|
|
131
289
|
const { installedModuleIds } = await this.getExistingInstallation(confirmedDirectory);
|
|
132
|
-
const coreConfig = await this.collectCoreConfig(confirmedDirectory);
|
|
133
|
-
|
|
134
|
-
// For new installations, create the directory structure first so we can cache custom content
|
|
135
|
-
if (!hasExistingInstall && customContentConfig._shouldAsk) {
|
|
136
|
-
// Create the bmad directory based on core config
|
|
137
|
-
const path = require('node:path');
|
|
138
|
-
const fs = require('fs-extra');
|
|
139
|
-
const bmadFolderName = '.bmad';
|
|
140
|
-
const bmadDir = path.join(confirmedDirectory, bmadFolderName);
|
|
141
|
-
|
|
142
|
-
await fs.ensureDir(bmadDir);
|
|
143
|
-
await fs.ensureDir(path.join(bmadDir, '_cfg'));
|
|
144
|
-
await fs.ensureDir(path.join(bmadDir, '_cfg', 'custom'));
|
|
145
|
-
|
|
146
|
-
// Now prompt for custom content
|
|
147
|
-
customContentConfig = await this.promptCustomContentLocation();
|
|
148
|
-
|
|
149
|
-
// If custom content found, cache it
|
|
150
|
-
if (customContentConfig.hasCustomContent) {
|
|
151
|
-
const { CustomModuleCache } = require('../installers/lib/core/custom-module-cache');
|
|
152
|
-
const cache = new CustomModuleCache(bmadDir);
|
|
153
|
-
|
|
154
|
-
const customHandler = new CustomHandler();
|
|
155
|
-
const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
|
|
156
|
-
|
|
157
|
-
for (const customFile of customFiles) {
|
|
158
|
-
const customInfo = await customHandler.getCustomInfo(customFile);
|
|
159
|
-
if (customInfo && customInfo.id) {
|
|
160
|
-
// Cache the module source
|
|
161
|
-
await cache.cacheModule(customInfo.id, customInfo.path, {
|
|
162
|
-
name: customInfo.name,
|
|
163
|
-
type: 'custom',
|
|
164
|
-
});
|
|
165
290
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
291
|
+
// Ask about official modules for new installations
|
|
292
|
+
const { wantsOfficialModules } = await inquirer.prompt([
|
|
293
|
+
{
|
|
294
|
+
type: 'confirm',
|
|
295
|
+
name: 'wantsOfficialModules',
|
|
296
|
+
message: 'Will you be installing any official BMad modules (BMad Method, BMad Builder, Creative Innovation Suite)?',
|
|
297
|
+
default: true,
|
|
298
|
+
},
|
|
299
|
+
]);
|
|
169
300
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
customContentConfig.cachedModules.push({
|
|
176
|
-
id: customInfo.id,
|
|
177
|
-
cachePath: path.join(bmadDir, '_cfg', 'custom', customInfo.id),
|
|
178
|
-
// Store relative path from cache for the manifest
|
|
179
|
-
relativePath: path.join('_cfg', 'custom', customInfo.id),
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
301
|
+
let selectedOfficialModules = [];
|
|
302
|
+
if (wantsOfficialModules) {
|
|
303
|
+
const moduleChoices = await this.getModuleChoices(installedModuleIds, { hasCustomContent: false });
|
|
304
|
+
selectedOfficialModules = await this.selectModules(moduleChoices);
|
|
305
|
+
}
|
|
183
306
|
|
|
184
|
-
|
|
185
|
-
|
|
307
|
+
// Ask about custom content
|
|
308
|
+
const { wantsCustomContent } = await inquirer.prompt([
|
|
309
|
+
{
|
|
310
|
+
type: 'confirm',
|
|
311
|
+
name: 'wantsCustomContent',
|
|
312
|
+
message: 'Would you like to install a local custom module (this includes custom agents and workflows also)?',
|
|
313
|
+
default: false,
|
|
314
|
+
},
|
|
315
|
+
]);
|
|
186
316
|
|
|
187
|
-
|
|
188
|
-
|
|
317
|
+
if (wantsCustomContent) {
|
|
318
|
+
customContentConfig = await this.promptCustomContentSource();
|
|
189
319
|
}
|
|
190
320
|
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
if (actionType === 'update' || actionType === 'reinstall') {
|
|
194
|
-
// Keep all existing installed modules during update/reinstall
|
|
195
|
-
selectedModules = [...installedModuleIds];
|
|
196
|
-
console.log(chalk.cyan('\n📦 Keeping existing modules: ') + selectedModules.join(', '));
|
|
197
|
-
} else {
|
|
198
|
-
// Only show module selection for new installs
|
|
199
|
-
const moduleChoices = await this.getModuleChoices(installedModuleIds, customContentConfig);
|
|
200
|
-
selectedModules = await this.selectModules(moduleChoices);
|
|
201
|
-
|
|
202
|
-
// Check which custom content items were selected
|
|
203
|
-
const selectedCustomContent = selectedModules.filter((mod) => mod.startsWith('__CUSTOM_CONTENT__'));
|
|
204
|
-
|
|
205
|
-
// For cached modules (new installs), check if any cached modules were selected
|
|
206
|
-
let selectedCachedModules = [];
|
|
207
|
-
if (customContentConfig.cachedModules) {
|
|
208
|
-
selectedCachedModules = selectedModules.filter(
|
|
209
|
-
(mod) => !mod.startsWith('__CUSTOM_CONTENT__') && customContentConfig.cachedModules.some((cm) => cm.id === mod),
|
|
210
|
-
);
|
|
211
|
-
}
|
|
321
|
+
// Store the selected modules for later
|
|
322
|
+
customContentConfig._selectedOfficialModules = selectedOfficialModules;
|
|
212
323
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Handle directory-based custom content (existing installs)
|
|
217
|
-
if (selectedCustomContent.length > 0) {
|
|
218
|
-
customContentConfig.selectedFiles = selectedCustomContent.map((mod) => mod.replace('__CUSTOM_CONTENT__', ''));
|
|
219
|
-
// Convert custom content to module IDs for installation
|
|
220
|
-
const customContentModuleIds = [];
|
|
221
|
-
const customHandler = new CustomHandler();
|
|
222
|
-
for (const customFile of customContentConfig.selectedFiles) {
|
|
223
|
-
// Get the module info to extract the ID
|
|
224
|
-
const customInfo = await customHandler.getCustomInfo(customFile);
|
|
225
|
-
if (customInfo) {
|
|
226
|
-
customContentModuleIds.push(customInfo.id);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
// Filter out custom content markers and add module IDs
|
|
230
|
-
selectedModules = [...selectedModules.filter((mod) => !mod.startsWith('__CUSTOM_CONTENT__')), ...customContentModuleIds];
|
|
231
|
-
}
|
|
324
|
+
// Build the final list of selected modules
|
|
325
|
+
let selectedModules = customContentConfig._selectedOfficialModules || [];
|
|
232
326
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// No need to filter since they're already proper module IDs
|
|
237
|
-
}
|
|
238
|
-
} else if (customContentConfig.hasCustomContent) {
|
|
239
|
-
// User provided custom content but didn't select any
|
|
240
|
-
customContentConfig.selected = false;
|
|
241
|
-
customContentConfig.selectedFiles = [];
|
|
242
|
-
customContentConfig.selectedCachedModules = [];
|
|
243
|
-
}
|
|
327
|
+
// Add custom content modules if any were selected
|
|
328
|
+
if (customContentConfig && customContentConfig.selectedModuleIds) {
|
|
329
|
+
selectedModules = [...selectedModules, ...customContentConfig.selectedModuleIds];
|
|
244
330
|
}
|
|
245
331
|
|
|
246
|
-
//
|
|
247
|
-
|
|
332
|
+
// Remove core if it's in the list (it's always installed)
|
|
333
|
+
selectedModules = selectedModules.filter((m) => m !== 'core');
|
|
248
334
|
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
335
|
+
// Tool selection (already done for new installs at the beginning)
|
|
336
|
+
if (!toolSelection) {
|
|
337
|
+
toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules);
|
|
338
|
+
}
|
|
252
339
|
|
|
253
|
-
//
|
|
340
|
+
// Collect configurations for new installations
|
|
341
|
+
const coreConfig = await this.collectCoreConfig(confirmedDirectory);
|
|
342
|
+
|
|
343
|
+
// TTS already handled at the beginning for new installs
|
|
254
344
|
|
|
255
345
|
return {
|
|
256
|
-
actionType:
|
|
346
|
+
actionType: 'install',
|
|
257
347
|
directory: confirmedDirectory,
|
|
258
|
-
installCore: true,
|
|
348
|
+
installCore: true,
|
|
259
349
|
modules: selectedModules,
|
|
260
|
-
// IDE selection collected after config, will be configured later
|
|
261
350
|
ides: toolSelection.ides,
|
|
262
351
|
skipIde: toolSelection.skipIde,
|
|
263
|
-
coreConfig: coreConfig,
|
|
264
|
-
// Custom content configuration
|
|
352
|
+
coreConfig: coreConfig,
|
|
265
353
|
customContent: customContentConfig,
|
|
266
354
|
enableAgentVibes: agentVibesConfig.enabled,
|
|
267
355
|
agentVibesInstalled: agentVibesConfig.alreadyInstalled,
|
|
@@ -280,7 +368,8 @@ class UI {
|
|
|
280
368
|
const { Installer } = require('../installers/lib/core/installer');
|
|
281
369
|
const detector = new Detector();
|
|
282
370
|
const installer = new Installer();
|
|
283
|
-
const
|
|
371
|
+
const bmadResult = await installer.findBmadDir(projectDir || process.cwd());
|
|
372
|
+
const bmadDir = bmadResult.bmadDir;
|
|
284
373
|
const existingInstall = await detector.detect(bmadDir);
|
|
285
374
|
const configuredIdes = existingInstall.ides || [];
|
|
286
375
|
|
|
@@ -350,8 +439,6 @@ class UI {
|
|
|
350
439
|
}
|
|
351
440
|
}
|
|
352
441
|
|
|
353
|
-
CLIUtils.displaySection('Tool Integration', 'Select AI coding assistants and IDEs to configure');
|
|
354
|
-
|
|
355
442
|
let answers;
|
|
356
443
|
let userConfirmedNoTools = false;
|
|
357
444
|
|
|
@@ -363,7 +450,7 @@ class UI {
|
|
|
363
450
|
name: 'ides',
|
|
364
451
|
message: 'Select tools to configure:',
|
|
365
452
|
choices: ideChoices,
|
|
366
|
-
pageSize:
|
|
453
|
+
pageSize: 30,
|
|
367
454
|
},
|
|
368
455
|
]);
|
|
369
456
|
|
|
@@ -389,9 +476,8 @@ class UI {
|
|
|
389
476
|
]);
|
|
390
477
|
|
|
391
478
|
if (goBack) {
|
|
392
|
-
// Re-display
|
|
479
|
+
// Re-display a message before looping back
|
|
393
480
|
console.log();
|
|
394
|
-
CLIUtils.displaySection('Tool Integration', 'Select AI coding assistants and IDEs to configure');
|
|
395
481
|
} else {
|
|
396
482
|
// User explicitly chose to proceed without tools
|
|
397
483
|
userConfirmedNoTools = true;
|
|
@@ -481,69 +567,33 @@ class UI {
|
|
|
481
567
|
* @param {Object} result - Installation result
|
|
482
568
|
*/
|
|
483
569
|
showInstallSummary(result) {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const summary = [
|
|
487
|
-
`📁 Installation Path: ${result.path}`,
|
|
488
|
-
`📦 Modules Installed: ${result.modules?.length > 0 ? result.modules.join(', ') : 'core only'}`,
|
|
489
|
-
`🔧 Tools Configured: ${result.ides?.length > 0 ? result.ides.join(', ') : 'none'}`,
|
|
490
|
-
];
|
|
570
|
+
// Clean, simple completion message
|
|
571
|
+
console.log('\n' + chalk.green.bold('✨ BMAD is ready to use!'));
|
|
491
572
|
|
|
492
|
-
//
|
|
573
|
+
// Show installation summary in a simple format
|
|
574
|
+
console.log(chalk.dim(`Installed to: ${result.path}`));
|
|
575
|
+
if (result.modules && result.modules.length > 0) {
|
|
576
|
+
console.log(chalk.dim(`Modules: ${result.modules.join(', ')}`));
|
|
577
|
+
}
|
|
493
578
|
if (result.agentVibesEnabled) {
|
|
494
|
-
|
|
579
|
+
console.log(chalk.dim(`TTS: Enabled`));
|
|
495
580
|
}
|
|
496
581
|
|
|
497
|
-
|
|
498
|
-
borderColor: 'green',
|
|
499
|
-
borderStyle: 'round',
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
// Display TTS injection details if present
|
|
582
|
+
// TTS injection info (simplified)
|
|
503
583
|
if (result.ttsInjectedFiles && result.ttsInjectedFiles.length > 0) {
|
|
504
|
-
console.log(
|
|
505
|
-
console.log(chalk.
|
|
506
|
-
console.log(chalk.cyan.bold('═══════════════════════════════════════════════════\n'));
|
|
507
|
-
|
|
508
|
-
// Explain what TTS injection is
|
|
509
|
-
console.log(chalk.white.bold('What is TTS Injection?\n'));
|
|
510
|
-
console.log(chalk.dim(' TTS (Text-to-Speech) injection adds voice instructions to BMAD agents,'));
|
|
511
|
-
console.log(chalk.dim(' enabling them to speak their responses aloud using AgentVibes.\n'));
|
|
512
|
-
console.log(chalk.dim(' Example: When you activate the PM agent, it will greet you with'));
|
|
513
|
-
console.log(chalk.dim(' spoken audio like "Hey! I\'m your Project Manager. How can I help?"\n'));
|
|
514
|
-
|
|
515
|
-
console.log(chalk.green(`✅ TTS injection applied to ${result.ttsInjectedFiles.length} file(s):\n`));
|
|
516
|
-
|
|
517
|
-
// Group by type
|
|
518
|
-
const partyModeFiles = result.ttsInjectedFiles.filter((f) => f.type === 'party-mode');
|
|
519
|
-
const agentTTSFiles = result.ttsInjectedFiles.filter((f) => f.type === 'agent-tts');
|
|
520
|
-
|
|
521
|
-
if (partyModeFiles.length > 0) {
|
|
522
|
-
console.log(chalk.yellow(' Party Mode (multi-agent conversations):'));
|
|
523
|
-
for (const file of partyModeFiles) {
|
|
524
|
-
console.log(chalk.dim(` • ${file.path}`));
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
if (agentTTSFiles.length > 0) {
|
|
529
|
-
console.log(chalk.yellow(' Agent TTS (individual agent voices):'));
|
|
530
|
-
for (const file of agentTTSFiles) {
|
|
531
|
-
console.log(chalk.dim(` • ${file.path}`));
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// Show backup info and restore command
|
|
536
|
-
console.log('\n' + chalk.white.bold('Backups & Recovery:\n'));
|
|
537
|
-
console.log(chalk.dim(' Pre-injection backups are stored in:'));
|
|
538
|
-
console.log(chalk.cyan(' ~/.bmad-tts-backups/\n'));
|
|
539
|
-
console.log(chalk.dim(' To restore original files (removes TTS instructions):'));
|
|
540
|
-
console.log(chalk.cyan(` bmad-tts-injector.sh --restore ${result.path}\n`));
|
|
541
|
-
|
|
542
|
-
console.log(chalk.cyan('💡 BMAD agents will now speak when activated!'));
|
|
543
|
-
console.log(chalk.dim(' Ensure AgentVibes is installed: https://agentvibes.org'));
|
|
584
|
+
console.log(chalk.dim(`\n💡 TTS enabled for ${result.ttsInjectedFiles.length} agent(s)`));
|
|
585
|
+
console.log(chalk.dim(' Agents will now speak when using AgentVibes'));
|
|
544
586
|
}
|
|
545
587
|
|
|
546
|
-
console.log(
|
|
588
|
+
console.log(chalk.yellow('\nThank you for helping test the early release version of the new BMad Core and BMad Method!'));
|
|
589
|
+
console.log(chalk.cyan('Stable Beta coming soon - please read the full README.md and linked documentation to get started!'));
|
|
590
|
+
|
|
591
|
+
// Add changelog link at the end
|
|
592
|
+
console.log(
|
|
593
|
+
chalk.magenta(
|
|
594
|
+
"\n📋 Want to see what's new? Check out the changelog: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md",
|
|
595
|
+
),
|
|
596
|
+
);
|
|
547
597
|
}
|
|
548
598
|
|
|
549
599
|
/**
|
|
@@ -573,8 +623,8 @@ class UI {
|
|
|
573
623
|
const { Installer } = require('../installers/lib/core/installer');
|
|
574
624
|
const detector = new Detector();
|
|
575
625
|
const installer = new Installer();
|
|
576
|
-
const
|
|
577
|
-
const existingInstall = await detector.detect(bmadDir);
|
|
626
|
+
const bmadDirResult = await installer.findBmadDir(directory);
|
|
627
|
+
const existingInstall = await detector.detect(bmadDirResult.bmadDir);
|
|
578
628
|
const installedModuleIds = new Set(existingInstall.modules.map((mod) => mod.id));
|
|
579
629
|
|
|
580
630
|
return { existingInstall, installedModuleIds };
|
|
@@ -593,7 +643,9 @@ class UI {
|
|
|
593
643
|
// Now collect with existing values as defaults (false = don't skip loading, true = skip completion message)
|
|
594
644
|
await configCollector.collectModuleConfig('core', directory, false, true);
|
|
595
645
|
|
|
596
|
-
|
|
646
|
+
const coreConfig = configCollector.collectedConfig.core;
|
|
647
|
+
// Ensure we always have a core config object, even if empty
|
|
648
|
+
return coreConfig || {};
|
|
597
649
|
}
|
|
598
650
|
|
|
599
651
|
/**
|
|
@@ -610,81 +662,28 @@ class UI {
|
|
|
610
662
|
const hasCustomContentItems = false;
|
|
611
663
|
|
|
612
664
|
// Add custom content items
|
|
613
|
-
if (customContentConfig && customContentConfig.hasCustomContent) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
path.
|
|
626
|
-
|
|
627
|
-
];
|
|
628
|
-
|
|
629
|
-
let moduleData = null;
|
|
630
|
-
let foundPath = null;
|
|
631
|
-
|
|
632
|
-
for (const configPath of possibleConfigPaths) {
|
|
633
|
-
if (await fs.pathExists(configPath)) {
|
|
634
|
-
try {
|
|
635
|
-
const yamlContent = await fs.readFile(configPath, 'utf8');
|
|
636
|
-
moduleData = yaml.load(yamlContent);
|
|
637
|
-
foundPath = configPath;
|
|
638
|
-
break;
|
|
639
|
-
} catch (error) {
|
|
640
|
-
throw new Error(`Failed to parse config at ${configPath}: ${error.message}`);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
if (moduleData) {
|
|
646
|
-
// Use the name from the custom info if we have it
|
|
647
|
-
const moduleName = cachedModule.name || moduleData.name || cachedModule.id;
|
|
648
|
-
|
|
649
|
-
customContentItems.push({
|
|
650
|
-
name: `${chalk.cyan('✓')} ${moduleName} ${chalk.gray('(cached)')}`,
|
|
651
|
-
value: cachedModule.id, // Use module ID directly
|
|
652
|
-
checked: true, // Default to selected
|
|
653
|
-
cached: true,
|
|
654
|
-
});
|
|
655
|
-
} else {
|
|
656
|
-
// Module config not found - skip silently (non-critical)
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
} else if (customContentConfig.customPath) {
|
|
660
|
-
// Existing installation - show from directory
|
|
661
|
-
const customHandler = new CustomHandler();
|
|
662
|
-
const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
|
|
663
|
-
|
|
664
|
-
for (const customFile of customFiles) {
|
|
665
|
-
const customInfo = await customHandler.getCustomInfo(customFile);
|
|
666
|
-
if (customInfo) {
|
|
667
|
-
customContentItems.push({
|
|
668
|
-
name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
|
|
669
|
-
value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content
|
|
670
|
-
checked: true, // Default to selected since user chose to provide custom content
|
|
671
|
-
path: customInfo.path, // Track path to avoid duplicates
|
|
672
|
-
});
|
|
673
|
-
}
|
|
665
|
+
if (customContentConfig && customContentConfig.hasCustomContent && customContentConfig.customPath) {
|
|
666
|
+
// Existing installation - show from directory
|
|
667
|
+
const customHandler = new CustomHandler();
|
|
668
|
+
const customFiles = await customHandler.findCustomContent(customContentConfig.customPath);
|
|
669
|
+
|
|
670
|
+
for (const customFile of customFiles) {
|
|
671
|
+
const customInfo = await customHandler.getCustomInfo(customFile);
|
|
672
|
+
if (customInfo) {
|
|
673
|
+
customContentItems.push({
|
|
674
|
+
name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
|
|
675
|
+
value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content
|
|
676
|
+
checked: true, // Default to selected since user chose to provide custom content
|
|
677
|
+
path: customInfo.path, // Track path to avoid duplicates
|
|
678
|
+
});
|
|
674
679
|
}
|
|
675
680
|
}
|
|
676
681
|
}
|
|
677
682
|
|
|
678
683
|
// Add official modules
|
|
679
684
|
const { ModuleManager } = require('../installers/lib/modules/manager');
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
const shouldScanProject =
|
|
683
|
-
!isNewInstallation && customContentConfig && customContentConfig.hasCustomContent && customContentConfig.selected;
|
|
684
|
-
const moduleManager = new ModuleManager({
|
|
685
|
-
scanProjectForModules: shouldScanProject,
|
|
686
|
-
});
|
|
687
|
-
const { modules: availableModules, customModules: customModulesFromProject } = await moduleManager.listAvailable();
|
|
685
|
+
const moduleManager = new ModuleManager();
|
|
686
|
+
const { modules: availableModules, customModules: customModulesFromCache } = await moduleManager.listAvailable();
|
|
688
687
|
|
|
689
688
|
// First, add all items to appropriate sections
|
|
690
689
|
const allCustomModules = [];
|
|
@@ -692,14 +691,14 @@ class UI {
|
|
|
692
691
|
// Add custom content items from directory
|
|
693
692
|
allCustomModules.push(...customContentItems);
|
|
694
693
|
|
|
695
|
-
// Add custom modules from
|
|
696
|
-
for (const mod of
|
|
694
|
+
// Add custom modules from cache
|
|
695
|
+
for (const mod of customModulesFromCache) {
|
|
697
696
|
// Skip if this module is already in customContentItems (by path)
|
|
698
697
|
const isDuplicate = allCustomModules.some((item) => item.path && mod.path && path.resolve(item.path) === path.resolve(mod.path));
|
|
699
698
|
|
|
700
699
|
if (!isDuplicate) {
|
|
701
700
|
allCustomModules.push({
|
|
702
|
-
name: `${chalk.cyan('✓')} ${mod.name} ${chalk.gray(`(
|
|
701
|
+
name: `${chalk.cyan('✓')} ${mod.name} ${chalk.gray(`(cached)`)}`,
|
|
703
702
|
value: mod.id,
|
|
704
703
|
checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
|
|
705
704
|
});
|
|
@@ -735,19 +734,20 @@ class UI {
|
|
|
735
734
|
* @param {Array} moduleChoices - Available module choices
|
|
736
735
|
* @returns {Array} Selected module IDs
|
|
737
736
|
*/
|
|
738
|
-
async selectModules(moduleChoices) {
|
|
739
|
-
CLIUtils.displaySection('Module Selection', 'Choose the BMAD modules to install');
|
|
740
|
-
|
|
737
|
+
async selectModules(moduleChoices, defaultSelections = []) {
|
|
741
738
|
const moduleAnswer = await inquirer.prompt([
|
|
742
739
|
{
|
|
743
740
|
type: 'checkbox',
|
|
744
741
|
name: 'modules',
|
|
745
742
|
message: 'Select modules to install:',
|
|
746
743
|
choices: moduleChoices,
|
|
744
|
+
default: defaultSelections,
|
|
747
745
|
},
|
|
748
746
|
]);
|
|
749
747
|
|
|
750
|
-
|
|
748
|
+
const selected = moduleAnswer.modules || [];
|
|
749
|
+
|
|
750
|
+
return selected;
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
/**
|
|
@@ -787,15 +787,16 @@ class UI {
|
|
|
787
787
|
if (stats.isDirectory()) {
|
|
788
788
|
const files = await fs.readdir(directory);
|
|
789
789
|
if (files.length > 0) {
|
|
790
|
-
// Check for any bmad installation (any folder with
|
|
790
|
+
// Check for any bmad installation (any folder with _config/manifest.yaml)
|
|
791
791
|
const { Installer } = require('../installers/lib/core/installer');
|
|
792
792
|
const installer = new Installer();
|
|
793
|
-
const
|
|
794
|
-
const hasBmadInstall =
|
|
793
|
+
const bmadResult = await installer.findBmadDir(directory);
|
|
794
|
+
const hasBmadInstall =
|
|
795
|
+
(await fs.pathExists(bmadResult.bmadDir)) && (await fs.pathExists(path.join(bmadResult.bmadDir, '_config', 'manifest.yaml')));
|
|
795
796
|
|
|
796
797
|
console.log(
|
|
797
798
|
chalk.gray(`Directory exists and contains ${files.length} item(s)`) +
|
|
798
|
-
(hasBmadInstall ? chalk.yellow(` including existing BMAD installation (${path.basename(bmadDir)})`) : ''),
|
|
799
|
+
(hasBmadInstall ? chalk.yellow(` including existing BMAD installation (${path.basename(bmadResult.bmadDir)})`) : ''),
|
|
799
800
|
);
|
|
800
801
|
} else {
|
|
801
802
|
console.log(chalk.gray('Directory exists and is empty'));
|
|
@@ -804,120 +805,6 @@ class UI {
|
|
|
804
805
|
}
|
|
805
806
|
}
|
|
806
807
|
|
|
807
|
-
/**
|
|
808
|
-
* Prompt for custom content location
|
|
809
|
-
* @returns {Object} Custom content configuration
|
|
810
|
-
*/
|
|
811
|
-
async promptCustomContentLocation() {
|
|
812
|
-
try {
|
|
813
|
-
// Skip custom content installation - always return false
|
|
814
|
-
return { hasCustomContent: false };
|
|
815
|
-
|
|
816
|
-
// TODO: Custom content installation temporarily disabled
|
|
817
|
-
// CLIUtils.displaySection('Custom Content', 'Optional: Add custom agents, workflows, and modules');
|
|
818
|
-
|
|
819
|
-
// const { hasCustomContent } = await inquirer.prompt([
|
|
820
|
-
// {
|
|
821
|
-
// type: 'list',
|
|
822
|
-
// name: 'hasCustomContent',
|
|
823
|
-
// message: 'Do you have custom content to install?',
|
|
824
|
-
// choices: [
|
|
825
|
-
// { name: 'No (skip custom content)', value: 'none' },
|
|
826
|
-
// { name: 'Enter a directory path', value: 'directory' },
|
|
827
|
-
// { name: 'Enter a URL', value: 'url' },
|
|
828
|
-
// ],
|
|
829
|
-
// default: 'none',
|
|
830
|
-
// },
|
|
831
|
-
// ]);
|
|
832
|
-
|
|
833
|
-
// if (hasCustomContent === 'none') {
|
|
834
|
-
// return { hasCustomContent: false };
|
|
835
|
-
// }
|
|
836
|
-
|
|
837
|
-
// TODO: Custom content installation temporarily disabled
|
|
838
|
-
// if (hasCustomContent === 'url') {
|
|
839
|
-
// console.log(chalk.yellow('\nURL-based custom content installation is coming soon!'));
|
|
840
|
-
// console.log(chalk.cyan('For now, please download your custom content and choose "Enter a directory path".\n'));
|
|
841
|
-
// return { hasCustomContent: false };
|
|
842
|
-
// }
|
|
843
|
-
|
|
844
|
-
// if (hasCustomContent === 'directory') {
|
|
845
|
-
// let customPath;
|
|
846
|
-
// while (!customPath) {
|
|
847
|
-
// let expandedPath;
|
|
848
|
-
// const { directory } = await inquirer.prompt([
|
|
849
|
-
// {
|
|
850
|
-
// type: 'input',
|
|
851
|
-
// name: 'directory',
|
|
852
|
-
// message: 'Enter directory to search for custom content (will scan subfolders):',
|
|
853
|
-
// default: process.cwd(), // Use actual current working directory
|
|
854
|
-
// validate: async (input) => {
|
|
855
|
-
// if (!input || input.trim() === '') {
|
|
856
|
-
// return 'Please enter a directory path';
|
|
857
|
-
// }
|
|
858
|
-
|
|
859
|
-
// try {
|
|
860
|
-
// expandedPath = this.expandUserPath(input.trim());
|
|
861
|
-
// } catch (error) {
|
|
862
|
-
// return error.message;
|
|
863
|
-
// }
|
|
864
|
-
|
|
865
|
-
// // Check if the path exists
|
|
866
|
-
// const pathExists = await fs.pathExists(expandedPath);
|
|
867
|
-
// if (!pathExists) {
|
|
868
|
-
// return 'Directory does not exist';
|
|
869
|
-
// }
|
|
870
|
-
|
|
871
|
-
// return true;
|
|
872
|
-
// },
|
|
873
|
-
// },
|
|
874
|
-
// ]);
|
|
875
|
-
|
|
876
|
-
// // Now expand the path for use after the prompt
|
|
877
|
-
// expandedPath = this.expandUserPath(directory.trim());
|
|
878
|
-
|
|
879
|
-
// // Check if directory has custom content
|
|
880
|
-
// const customHandler = new CustomHandler();
|
|
881
|
-
// const customFiles = await customHandler.findCustomContent(expandedPath);
|
|
882
|
-
|
|
883
|
-
// if (customFiles.length === 0) {
|
|
884
|
-
// console.log(chalk.yellow(`\nNo custom content found in ${expandedPath}`));
|
|
885
|
-
|
|
886
|
-
// const { tryAgain } = await inquirer.prompt([
|
|
887
|
-
// {
|
|
888
|
-
// type: 'confirm',
|
|
889
|
-
// name: 'tryAgain',
|
|
890
|
-
// message: 'Try a different directory?',
|
|
891
|
-
// default: true,
|
|
892
|
-
// },
|
|
893
|
-
// ]);
|
|
894
|
-
|
|
895
|
-
// if (tryAgain) {
|
|
896
|
-
// continue;
|
|
897
|
-
// } else {
|
|
898
|
-
// return { hasCustomContent: false };
|
|
899
|
-
// }
|
|
900
|
-
// }
|
|
901
|
-
|
|
902
|
-
// customPath = expandedPath;
|
|
903
|
-
// console.log(chalk.green(`\n✓ Found ${customFiles.length} custom content item(s):`));
|
|
904
|
-
// for (const file of customFiles) {
|
|
905
|
-
// const relativePath = path.relative(expandedPath, path.dirname(file));
|
|
906
|
-
// const folderName = path.dirname(file).split(path.sep).pop();
|
|
907
|
-
// console.log(chalk.dim(` • ${folderName} ${chalk.gray(`(${relativePath})`)}`));
|
|
908
|
-
// }
|
|
909
|
-
// }
|
|
910
|
-
|
|
911
|
-
// return { hasCustomContent: true, customPath };
|
|
912
|
-
// }
|
|
913
|
-
|
|
914
|
-
// return { hasCustomContent: false };
|
|
915
|
-
} catch (error) {
|
|
916
|
-
console.error(chalk.red('Error in custom content prompt:'), error);
|
|
917
|
-
return { hasCustomContent: false };
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
|
|
921
808
|
/**
|
|
922
809
|
* Confirm directory selection
|
|
923
810
|
* @param {string} directory - The directory path
|
|
@@ -1205,143 +1092,319 @@ class UI {
|
|
|
1205
1092
|
}
|
|
1206
1093
|
|
|
1207
1094
|
/**
|
|
1208
|
-
*
|
|
1209
|
-
* @
|
|
1095
|
+
* Load existing configurations to use as defaults
|
|
1096
|
+
* @param {string} directory - Installation directory
|
|
1097
|
+
* @returns {Object} Existing configurations
|
|
1210
1098
|
*/
|
|
1211
|
-
async
|
|
1099
|
+
async loadExistingConfigurations(directory) {
|
|
1100
|
+
const configs = {
|
|
1101
|
+
hasCustomContent: false,
|
|
1102
|
+
coreConfig: {},
|
|
1103
|
+
ideConfig: { ides: [], skipIde: false },
|
|
1104
|
+
agentVibesConfig: { enabled: false, alreadyInstalled: false },
|
|
1105
|
+
};
|
|
1106
|
+
|
|
1212
1107
|
try {
|
|
1213
|
-
//
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
//
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
//
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
//
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
//
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1108
|
+
// Load core config
|
|
1109
|
+
configs.coreConfig = await this.collectCoreConfig(directory);
|
|
1110
|
+
|
|
1111
|
+
// Load IDE configuration
|
|
1112
|
+
const configuredIdes = await this.getConfiguredIdes(directory);
|
|
1113
|
+
if (configuredIdes.length > 0) {
|
|
1114
|
+
configs.ideConfig.ides = configuredIdes;
|
|
1115
|
+
configs.ideConfig.skipIde = false;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// Load AgentVibes configuration
|
|
1119
|
+
const agentVibesInstalled = await this.checkAgentVibesInstalled(directory);
|
|
1120
|
+
configs.agentVibesConfig = { enabled: agentVibesInstalled, alreadyInstalled: agentVibesInstalled };
|
|
1121
|
+
|
|
1122
|
+
return configs;
|
|
1123
|
+
} catch {
|
|
1124
|
+
// If loading fails, return empty configs
|
|
1125
|
+
console.warn('Warning: Could not load existing configurations');
|
|
1126
|
+
return configs;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Get configured IDEs from existing installation
|
|
1132
|
+
* @param {string} directory - Installation directory
|
|
1133
|
+
* @returns {Array} List of configured IDEs
|
|
1134
|
+
*/
|
|
1135
|
+
async getConfiguredIdes(directory) {
|
|
1136
|
+
const { Detector } = require('../installers/lib/core/detector');
|
|
1137
|
+
const { Installer } = require('../installers/lib/core/installer');
|
|
1138
|
+
const detector = new Detector();
|
|
1139
|
+
const installer = new Installer();
|
|
1140
|
+
const bmadResult = await installer.findBmadDir(directory);
|
|
1141
|
+
const existingInstall = await detector.detect(bmadResult.bmadDir);
|
|
1142
|
+
return existingInstall.ides || [];
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/**
|
|
1146
|
+
* Prompt user for custom content source location
|
|
1147
|
+
* @returns {Object} Custom content configuration
|
|
1148
|
+
*/
|
|
1149
|
+
async promptCustomContentSource() {
|
|
1150
|
+
const customContentConfig = { hasCustomContent: true, sources: [] };
|
|
1151
|
+
|
|
1152
|
+
// Keep asking for more sources until user is done
|
|
1153
|
+
while (true) {
|
|
1154
|
+
// First ask if user wants to add another module or continue
|
|
1155
|
+
if (customContentConfig.sources.length > 0) {
|
|
1156
|
+
const { action } = await inquirer.prompt([
|
|
1157
|
+
{
|
|
1158
|
+
type: 'list',
|
|
1159
|
+
name: 'action',
|
|
1160
|
+
message: 'Would you like to:',
|
|
1161
|
+
choices: [
|
|
1162
|
+
{ name: 'Add another custom module', value: 'add' },
|
|
1163
|
+
{ name: 'Continue with installation', value: 'continue' },
|
|
1164
|
+
],
|
|
1165
|
+
default: 'continue',
|
|
1166
|
+
},
|
|
1167
|
+
]);
|
|
1168
|
+
|
|
1169
|
+
if (action === 'continue') {
|
|
1170
|
+
break;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
let sourcePath;
|
|
1175
|
+
let isValid = false;
|
|
1176
|
+
|
|
1177
|
+
while (!isValid) {
|
|
1178
|
+
const { path: inputPath } = await inquirer.prompt([
|
|
1179
|
+
{
|
|
1180
|
+
type: 'input',
|
|
1181
|
+
name: 'path',
|
|
1182
|
+
message: 'Enter the path to your custom content folder (or press Enter to cancel):',
|
|
1183
|
+
validate: async (input) => {
|
|
1184
|
+
// Allow empty input to cancel
|
|
1185
|
+
if (!input || input.trim() === '') {
|
|
1186
|
+
return true; // Allow empty to exit
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
try {
|
|
1190
|
+
// Expand the path
|
|
1191
|
+
const expandedPath = this.expandUserPath(input.trim());
|
|
1192
|
+
|
|
1193
|
+
// Check if path exists
|
|
1194
|
+
if (!(await fs.pathExists(expandedPath))) {
|
|
1195
|
+
return 'Path does not exist';
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// Check if it's a directory
|
|
1199
|
+
const stat = await fs.stat(expandedPath);
|
|
1200
|
+
if (!stat.isDirectory()) {
|
|
1201
|
+
return 'Path must be a directory';
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// Check for module.yaml in the root
|
|
1205
|
+
const moduleYamlPath = path.join(expandedPath, 'module.yaml');
|
|
1206
|
+
if (!(await fs.pathExists(moduleYamlPath))) {
|
|
1207
|
+
return 'Directory must contain a module.yaml file in the root';
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Try to parse the module.yaml to get the module ID
|
|
1211
|
+
try {
|
|
1212
|
+
const yaml = require('yaml');
|
|
1213
|
+
const content = await fs.readFile(moduleYamlPath, 'utf8');
|
|
1214
|
+
const moduleData = yaml.parse(content);
|
|
1215
|
+
if (!moduleData.code) {
|
|
1216
|
+
return 'module.yaml must contain a "code" field for the module ID';
|
|
1217
|
+
}
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
return 'Invalid module.yaml file: ' + error.message;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
return true;
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
return 'Error validating path: ' + error.message;
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
},
|
|
1228
|
+
]);
|
|
1229
|
+
|
|
1230
|
+
// If user pressed Enter without typing anything, exit the loop
|
|
1231
|
+
if (!inputPath || inputPath.trim() === '') {
|
|
1232
|
+
// If we have no modules yet, return false for no custom content
|
|
1233
|
+
if (customContentConfig.sources.length === 0) {
|
|
1234
|
+
return { hasCustomContent: false };
|
|
1235
|
+
}
|
|
1236
|
+
return customContentConfig;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
sourcePath = this.expandUserPath(inputPath);
|
|
1240
|
+
isValid = true;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// Read module.yaml to get module info
|
|
1244
|
+
const yaml = require('yaml');
|
|
1245
|
+
const moduleYamlPath = path.join(sourcePath, 'module.yaml');
|
|
1246
|
+
const moduleContent = await fs.readFile(moduleYamlPath, 'utf8');
|
|
1247
|
+
const moduleData = yaml.parse(moduleContent);
|
|
1248
|
+
|
|
1249
|
+
// Add to sources
|
|
1250
|
+
customContentConfig.sources.push({
|
|
1251
|
+
path: sourcePath,
|
|
1252
|
+
id: moduleData.code,
|
|
1253
|
+
name: moduleData.name || moduleData.code,
|
|
1254
|
+
});
|
|
1255
|
+
|
|
1256
|
+
console.log(chalk.green(`✓ Confirmed local custom module: ${moduleData.name || moduleData.code}`));
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// Ask if user wants to add these to the installation
|
|
1260
|
+
const { shouldInstall } = await inquirer.prompt([
|
|
1261
|
+
{
|
|
1262
|
+
type: 'confirm',
|
|
1263
|
+
name: 'shouldInstall',
|
|
1264
|
+
message: `Install ${customContentConfig.sources.length} custom module(s) now?`,
|
|
1265
|
+
default: true,
|
|
1266
|
+
},
|
|
1267
|
+
]);
|
|
1268
|
+
|
|
1269
|
+
if (shouldInstall) {
|
|
1270
|
+
customContentConfig.selected = true;
|
|
1271
|
+
// Store paths to module.yaml files, not directories
|
|
1272
|
+
customContentConfig.selectedFiles = customContentConfig.sources.map((s) => path.join(s.path, 'module.yaml'));
|
|
1273
|
+
// Also include module IDs for installation
|
|
1274
|
+
customContentConfig.selectedModuleIds = customContentConfig.sources.map((s) => s.id);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
return customContentConfig;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
/**
|
|
1281
|
+
* Handle custom modules in the modify flow
|
|
1282
|
+
* @param {string} directory - Installation directory
|
|
1283
|
+
* @param {Array} selectedModules - Currently selected modules
|
|
1284
|
+
* @returns {Object} Result with selected custom modules and custom content config
|
|
1285
|
+
*/
|
|
1286
|
+
async handleCustomModulesInModifyFlow(directory, selectedModules) {
|
|
1287
|
+
// Get existing installation to find custom modules
|
|
1288
|
+
const { existingInstall } = await this.getExistingInstallation(directory);
|
|
1289
|
+
|
|
1290
|
+
// Check if there are any custom modules in cache
|
|
1291
|
+
const { Installer } = require('../installers/lib/core/installer');
|
|
1292
|
+
const installer = new Installer();
|
|
1293
|
+
const { bmadDir } = await installer.findBmadDir(directory);
|
|
1294
|
+
|
|
1295
|
+
const cacheDir = path.join(bmadDir, '_config', 'custom');
|
|
1296
|
+
const cachedCustomModules = [];
|
|
1297
|
+
|
|
1298
|
+
if (await fs.pathExists(cacheDir)) {
|
|
1299
|
+
const entries = await fs.readdir(cacheDir, { withFileTypes: true });
|
|
1300
|
+
for (const entry of entries) {
|
|
1301
|
+
if (entry.isDirectory()) {
|
|
1302
|
+
const moduleYamlPath = path.join(cacheDir, entry.name, 'module.yaml');
|
|
1303
|
+
if (await fs.pathExists(moduleYamlPath)) {
|
|
1304
|
+
const yaml = require('yaml');
|
|
1305
|
+
const content = await fs.readFile(moduleYamlPath, 'utf8');
|
|
1306
|
+
const moduleData = yaml.parse(content);
|
|
1307
|
+
|
|
1308
|
+
cachedCustomModules.push({
|
|
1309
|
+
id: entry.name,
|
|
1310
|
+
name: moduleData.name || entry.name,
|
|
1311
|
+
description: moduleData.description || 'Custom module from cache',
|
|
1312
|
+
checked: selectedModules.includes(entry.name),
|
|
1313
|
+
fromCache: true,
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1344
1318
|
}
|
|
1319
|
+
|
|
1320
|
+
const result = {
|
|
1321
|
+
selectedCustomModules: [],
|
|
1322
|
+
customContentConfig: { hasCustomContent: false },
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
if (cachedCustomModules.length === 0) {
|
|
1326
|
+
return result;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
// Ask user about custom modules
|
|
1330
|
+
console.log(chalk.cyan('\n⚙️ Custom Modules'));
|
|
1331
|
+
console.log(chalk.dim('Found custom modules in your installation:'));
|
|
1332
|
+
|
|
1333
|
+
const { customAction } = await inquirer.prompt([
|
|
1334
|
+
{
|
|
1335
|
+
type: 'list',
|
|
1336
|
+
name: 'customAction',
|
|
1337
|
+
message: 'What would you like to do with custom modules?',
|
|
1338
|
+
choices: [
|
|
1339
|
+
{ name: 'Keep all existing custom modules', value: 'keep' },
|
|
1340
|
+
{ name: 'Select which custom modules to keep', value: 'select' },
|
|
1341
|
+
{ name: 'Add new custom modules', value: 'add' },
|
|
1342
|
+
{ name: 'Remove all custom modules', value: 'remove' },
|
|
1343
|
+
],
|
|
1344
|
+
default: 'keep',
|
|
1345
|
+
},
|
|
1346
|
+
]);
|
|
1347
|
+
|
|
1348
|
+
switch (customAction) {
|
|
1349
|
+
case 'keep': {
|
|
1350
|
+
// Keep all existing custom modules
|
|
1351
|
+
result.selectedCustomModules = cachedCustomModules.map((m) => m.id);
|
|
1352
|
+
console.log(chalk.dim(`Keeping ${result.selectedCustomModules.length} custom module(s)`));
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
case 'select': {
|
|
1357
|
+
// Let user choose which to keep
|
|
1358
|
+
const choices = cachedCustomModules.map((m) => ({
|
|
1359
|
+
name: `${m.name} ${chalk.gray(`(${m.id})`)}`,
|
|
1360
|
+
value: m.id,
|
|
1361
|
+
}));
|
|
1362
|
+
|
|
1363
|
+
const { keepModules } = await inquirer.prompt([
|
|
1364
|
+
{
|
|
1365
|
+
type: 'checkbox',
|
|
1366
|
+
name: 'keepModules',
|
|
1367
|
+
message: 'Select custom modules to keep:',
|
|
1368
|
+
choices: choices,
|
|
1369
|
+
default: cachedCustomModules.filter((m) => m.checked).map((m) => m.id),
|
|
1370
|
+
},
|
|
1371
|
+
]);
|
|
1372
|
+
result.selectedCustomModules = keepModules;
|
|
1373
|
+
break;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
case 'add': {
|
|
1377
|
+
// First ask to keep existing ones
|
|
1378
|
+
const { keepExisting } = await inquirer.prompt([
|
|
1379
|
+
{
|
|
1380
|
+
type: 'confirm',
|
|
1381
|
+
name: 'keepExisting',
|
|
1382
|
+
message: 'Keep existing custom modules?',
|
|
1383
|
+
default: true,
|
|
1384
|
+
},
|
|
1385
|
+
]);
|
|
1386
|
+
|
|
1387
|
+
if (keepExisting) {
|
|
1388
|
+
result.selectedCustomModules = cachedCustomModules.map((m) => m.id);
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// Then prompt for new ones (reuse existing method)
|
|
1392
|
+
const newCustomContent = await this.promptCustomContentSource();
|
|
1393
|
+
if (newCustomContent.hasCustomContent && newCustomContent.selected) {
|
|
1394
|
+
result.selectedCustomModules.push(...newCustomContent.selectedModuleIds);
|
|
1395
|
+
result.customContentConfig = newCustomContent;
|
|
1396
|
+
}
|
|
1397
|
+
break;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
case 'remove': {
|
|
1401
|
+
// Remove all custom modules
|
|
1402
|
+
console.log(chalk.yellow('All custom modules will be removed from the installation'));
|
|
1403
|
+
break;
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
return result;
|
|
1345
1408
|
}
|
|
1346
1409
|
}
|
|
1347
1410
|
|