bmad-method 6.2.3-next.0 → 6.2.3-next.10

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.
Files changed (143) hide show
  1. package/.claude-plugin/marketplace.json +0 -1
  2. package/package.json +9 -8
  3. package/src/bmm-skills/1-analysis/bmad-agent-analyst/SKILL.md +7 -4
  4. package/src/bmm-skills/1-analysis/bmad-agent-tech-writer/SKILL.md +6 -4
  5. package/src/bmm-skills/1-analysis/bmad-document-project/workflow.md +8 -10
  6. package/src/bmm-skills/1-analysis/bmad-prfaq/SKILL.md +96 -0
  7. package/src/bmm-skills/1-analysis/bmad-prfaq/agents/artifact-analyzer.md +60 -0
  8. package/src/bmm-skills/1-analysis/bmad-prfaq/agents/web-researcher.md +49 -0
  9. package/src/bmm-skills/1-analysis/bmad-prfaq/assets/prfaq-template.md +62 -0
  10. package/src/bmm-skills/1-analysis/bmad-prfaq/bmad-manifest.json +16 -0
  11. package/src/bmm-skills/1-analysis/bmad-prfaq/references/customer-faq.md +55 -0
  12. package/src/bmm-skills/1-analysis/bmad-prfaq/references/internal-faq.md +51 -0
  13. package/src/bmm-skills/1-analysis/bmad-prfaq/references/press-release.md +60 -0
  14. package/src/bmm-skills/1-analysis/bmad-prfaq/references/verdict.md +79 -0
  15. package/src/bmm-skills/1-analysis/bmad-product-brief/SKILL.md +1 -6
  16. package/src/bmm-skills/1-analysis/bmad-product-brief/bmad-manifest.json +1 -1
  17. package/src/bmm-skills/1-analysis/research/bmad-domain-research/workflow.md +8 -6
  18. package/src/bmm-skills/1-analysis/research/bmad-market-research/workflow.md +8 -6
  19. package/src/bmm-skills/1-analysis/research/bmad-technical-research/workflow.md +8 -6
  20. package/src/bmm-skills/2-plan-workflows/bmad-agent-pm/SKILL.md +6 -4
  21. package/src/bmm-skills/2-plan-workflows/bmad-agent-ux-designer/SKILL.md +6 -4
  22. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/workflow.md +8 -9
  23. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/workflow.md +8 -9
  24. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01-discovery.md +1 -1
  25. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01b-legacy-conversion.md +1 -1
  26. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-02-review.md +1 -1
  27. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-03-edit.md +1 -1
  28. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +1 -1
  29. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/workflow.md +8 -9
  30. package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/workflow.md +8 -9
  31. package/src/bmm-skills/3-solutioning/bmad-agent-architect/SKILL.md +6 -4
  32. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/workflow.md +8 -10
  33. package/src/bmm-skills/3-solutioning/bmad-create-architecture/workflow.md +8 -14
  34. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/workflow.md +10 -12
  35. package/src/bmm-skills/3-solutioning/bmad-generate-project-context/workflow.md +8 -12
  36. package/src/bmm-skills/4-implementation/bmad-agent-dev/SKILL.md +6 -4
  37. package/src/bmm-skills/4-implementation/bmad-agent-qa/SKILL.md +6 -4
  38. package/src/bmm-skills/4-implementation/bmad-agent-quick-flow-solo-dev/SKILL.md +6 -4
  39. package/src/bmm-skills/4-implementation/bmad-agent-sm/SKILL.md +6 -4
  40. package/src/bmm-skills/module-help.csv +2 -1
  41. package/src/core-skills/bmad-advanced-elicitation/SKILL.md +1 -2
  42. package/src/core-skills/bmad-distillator/SKILL.md +0 -1
  43. package/src/core-skills/bmad-distillator/resources/distillate-format-reference.md +10 -10
  44. package/src/core-skills/bmad-party-mode/SKILL.md +121 -2
  45. package/tools/{cli → installer}/bmad-cli.js +3 -1
  46. package/tools/{cli/lib → installer}/cli-utils.js +3 -4
  47. package/tools/{cli → installer}/commands/install.js +3 -3
  48. package/tools/{cli → installer}/commands/status.js +4 -4
  49. package/tools/{cli → installer}/commands/uninstall.js +5 -5
  50. package/tools/installer/core/config.js +52 -0
  51. package/tools/{cli/installers/lib → installer}/core/custom-module-cache.js +1 -1
  52. package/tools/installer/core/existing-install.js +127 -0
  53. package/tools/installer/core/install-paths.js +129 -0
  54. package/tools/installer/core/installer.js +1790 -0
  55. package/tools/{cli/installers/lib → installer}/core/manifest-generator.js +3 -3
  56. package/tools/{cli/installers/lib → installer}/core/manifest.js +2 -2
  57. package/tools/{cli/installers/lib/custom/handler.js → installer/custom-handler.js} +1 -1
  58. package/tools/{cli/installers/lib → installer}/ide/_config-driven.js +30 -397
  59. package/tools/{cli/installers/lib → installer}/ide/manager.js +1 -53
  60. package/tools/installer/ide/platform-codes.js +37 -0
  61. package/tools/installer/ide/platform-codes.yaml +192 -0
  62. package/tools/{cli/installers/lib → installer}/ide/shared/module-injections.js +1 -1
  63. package/tools/{cli/installers/lib → installer}/message-loader.js +2 -2
  64. package/tools/installer/modules/custom-modules.js +197 -0
  65. package/tools/installer/modules/external-manager.js +354 -0
  66. package/tools/{cli/installers/lib/core/config-collector.js → installer/modules/official-modules.js} +714 -43
  67. package/tools/{cli/lib → installer}/ui.js +65 -299
  68. package/tools/javascript-conventions.md +5 -0
  69. package/tools/platform-codes.yaml +6 -0
  70. package/src/bmm-skills/2-plan-workflows/create-prd/data/domain-complexity.csv +0 -15
  71. package/src/bmm-skills/2-plan-workflows/create-prd/data/prd-purpose.md +0 -197
  72. package/src/bmm-skills/2-plan-workflows/create-prd/data/project-types.csv +0 -11
  73. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +0 -224
  74. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +0 -191
  75. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +0 -209
  76. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +0 -174
  77. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +0 -214
  78. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +0 -228
  79. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +0 -217
  80. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +0 -205
  81. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +0 -243
  82. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +0 -263
  83. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +0 -209
  84. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +0 -264
  85. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +0 -242
  86. package/src/bmm-skills/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +0 -232
  87. package/src/bmm-skills/2-plan-workflows/create-prd/workflow-validate-prd.md +0 -65
  88. package/src/core-skills/bmad-init/SKILL.md +0 -100
  89. package/src/core-skills/bmad-init/resources/core-module.yaml +0 -25
  90. package/src/core-skills/bmad-init/scripts/bmad_init.py +0 -624
  91. package/src/core-skills/bmad-init/scripts/tests/test_bmad_init.py +0 -393
  92. package/src/core-skills/bmad-party-mode/steps/step-01-agent-loading.md +0 -138
  93. package/src/core-skills/bmad-party-mode/steps/step-02-discussion-orchestration.md +0 -187
  94. package/src/core-skills/bmad-party-mode/steps/step-03-graceful-exit.md +0 -167
  95. package/src/core-skills/bmad-party-mode/workflow.md +0 -190
  96. package/tools/bmad-npx-wrapper.js +0 -38
  97. package/tools/cli/installers/lib/core/dependency-resolver.js +0 -743
  98. package/tools/cli/installers/lib/core/detector.js +0 -223
  99. package/tools/cli/installers/lib/core/ide-config-manager.js +0 -157
  100. package/tools/cli/installers/lib/core/installer.js +0 -3002
  101. package/tools/cli/installers/lib/ide/_base-ide.js +0 -657
  102. package/tools/cli/installers/lib/ide/platform-codes.js +0 -100
  103. package/tools/cli/installers/lib/ide/platform-codes.yaml +0 -341
  104. package/tools/cli/installers/lib/modules/external-manager.js +0 -136
  105. package/tools/cli/installers/lib/modules/manager.js +0 -928
  106. package/tools/cli/lib/config.js +0 -213
  107. package/tools/cli/lib/platform-codes.js +0 -116
  108. package/tools/lib/xml-utils.js +0 -13
  109. /package/tools/{cli → installer}/README.md +0 -0
  110. /package/tools/{cli → installer}/external-official-modules.yaml +0 -0
  111. /package/tools/{cli/lib → installer}/file-ops.js +0 -0
  112. /package/tools/{cli/installers/lib → installer}/ide/shared/agent-command-generator.js +0 -0
  113. /package/tools/{cli/installers/lib → installer}/ide/shared/bmad-artifacts.js +0 -0
  114. /package/tools/{cli/installers/lib → installer}/ide/shared/path-utils.js +0 -0
  115. /package/tools/{cli/installers/lib → installer}/ide/shared/skill-manifest.js +0 -0
  116. /package/tools/{cli/installers/lib → installer}/ide/templates/agent-command-template.md +0 -0
  117. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/antigravity.md +0 -0
  118. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-agent.md +0 -0
  119. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-task.md +0 -0
  120. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-tool.md +0 -0
  121. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-workflow.md +0 -0
  122. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-agent.toml +0 -0
  123. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-task.toml +0 -0
  124. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-tool.toml +0 -0
  125. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow-yaml.toml +0 -0
  126. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow.toml +0 -0
  127. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-agent.md +0 -0
  128. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-task.md +0 -0
  129. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-tool.md +0 -0
  130. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-workflow.md +0 -0
  131. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-agent.md +0 -0
  132. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-task.md +0 -0
  133. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-tool.md +0 -0
  134. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow-yaml.md +0 -0
  135. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow.md +0 -0
  136. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/rovodev.md +0 -0
  137. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/trae.md +0 -0
  138. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/windsurf-workflow.md +0 -0
  139. /package/tools/{cli/installers/lib → installer}/ide/templates/split/.gitkeep +0 -0
  140. /package/tools/{cli/installers → installer}/install-messages.yaml +0 -0
  141. /package/tools/{cli/lib → installer}/project-root.js +0 -0
  142. /package/tools/{cli/lib → installer}/prompts.js +0 -0
  143. /package/tools/{cli/lib → installer}/yaml-format.js +0 -0
@@ -0,0 +1,192 @@
1
+ # BMAD Platform Codes Configuration
2
+ #
3
+ # Each platform entry has:
4
+ # name: Display name shown to users
5
+ # preferred: Whether shown as a recommended option on install
6
+ # suspended: (optional) Message explaining why install is blocked
7
+ # installer:
8
+ # target_dir: Directory where skill directories are installed
9
+ # legacy_targets: (optional) Old target dirs to clean up on reinstall
10
+ # ancestor_conflict_check: (optional) Refuse install when ancestor dir has BMAD files
11
+
12
+ platforms:
13
+ antigravity:
14
+ name: "Google Antigravity"
15
+ preferred: false
16
+ installer:
17
+ legacy_targets:
18
+ - .agent/workflows
19
+ target_dir: .agent/skills
20
+
21
+ auggie:
22
+ name: "Auggie"
23
+ preferred: false
24
+ installer:
25
+ legacy_targets:
26
+ - .augment/commands
27
+ target_dir: .augment/skills
28
+
29
+ claude-code:
30
+ name: "Claude Code"
31
+ preferred: true
32
+ installer:
33
+ legacy_targets:
34
+ - .claude/commands
35
+ target_dir: .claude/skills
36
+
37
+ cline:
38
+ name: "Cline"
39
+ preferred: false
40
+ installer:
41
+ legacy_targets:
42
+ - .clinerules/workflows
43
+ target_dir: .cline/skills
44
+
45
+ codex:
46
+ name: "Codex"
47
+ preferred: false
48
+ installer:
49
+ legacy_targets:
50
+ - .codex/prompts
51
+ - ~/.codex/prompts
52
+ target_dir: .agents/skills
53
+
54
+ codebuddy:
55
+ name: "CodeBuddy"
56
+ preferred: false
57
+ installer:
58
+ legacy_targets:
59
+ - .codebuddy/commands
60
+ target_dir: .codebuddy/skills
61
+
62
+ crush:
63
+ name: "Crush"
64
+ preferred: false
65
+ installer:
66
+ legacy_targets:
67
+ - .crush/commands
68
+ target_dir: .crush/skills
69
+
70
+ cursor:
71
+ name: "Cursor"
72
+ preferred: true
73
+ installer:
74
+ legacy_targets:
75
+ - .cursor/commands
76
+ target_dir: .cursor/skills
77
+
78
+ gemini:
79
+ name: "Gemini CLI"
80
+ preferred: false
81
+ installer:
82
+ legacy_targets:
83
+ - .gemini/commands
84
+ target_dir: .gemini/skills
85
+
86
+ github-copilot:
87
+ name: "GitHub Copilot"
88
+ preferred: false
89
+ installer:
90
+ legacy_targets:
91
+ - .github/agents
92
+ - .github/prompts
93
+ target_dir: .github/skills
94
+
95
+ iflow:
96
+ name: "iFlow"
97
+ preferred: false
98
+ installer:
99
+ legacy_targets:
100
+ - .iflow/commands
101
+ target_dir: .iflow/skills
102
+
103
+ junie:
104
+ name: "Junie"
105
+ preferred: false
106
+ installer:
107
+ target_dir: .agents/skills
108
+
109
+ kilo:
110
+ name: "KiloCoder"
111
+ preferred: false
112
+ installer:
113
+ legacy_targets:
114
+ - .kilocode/workflows
115
+ target_dir: .kilocode/skills
116
+
117
+ kiro:
118
+ name: "Kiro"
119
+ preferred: false
120
+ installer:
121
+ legacy_targets:
122
+ - .kiro/steering
123
+ target_dir: .kiro/skills
124
+
125
+ ona:
126
+ name: "Ona"
127
+ preferred: false
128
+ installer:
129
+ target_dir: .ona/skills
130
+
131
+ opencode:
132
+ name: "OpenCode"
133
+ preferred: false
134
+ installer:
135
+ legacy_targets:
136
+ - .opencode/agents
137
+ - .opencode/commands
138
+ - .opencode/agent
139
+ - .opencode/command
140
+ target_dir: .opencode/skills
141
+
142
+ pi:
143
+ name: "Pi"
144
+ preferred: false
145
+ installer:
146
+ target_dir: .pi/skills
147
+
148
+ qoder:
149
+ name: "Qoder"
150
+ preferred: false
151
+ installer:
152
+ target_dir: .qoder/skills
153
+
154
+ qwen:
155
+ name: "QwenCoder"
156
+ preferred: false
157
+ installer:
158
+ legacy_targets:
159
+ - .qwen/commands
160
+ target_dir: .qwen/skills
161
+
162
+ roo:
163
+ name: "Roo Code"
164
+ preferred: false
165
+ installer:
166
+ legacy_targets:
167
+ - .roo/commands
168
+ target_dir: .roo/skills
169
+
170
+ rovo-dev:
171
+ name: "Rovo Dev"
172
+ preferred: false
173
+ installer:
174
+ legacy_targets:
175
+ - .rovodev/workflows
176
+ target_dir: .rovodev/skills
177
+
178
+ trae:
179
+ name: "Trae"
180
+ preferred: false
181
+ installer:
182
+ legacy_targets:
183
+ - .trae/rules
184
+ target_dir: .trae/skills
185
+
186
+ windsurf:
187
+ name: "Windsurf"
188
+ preferred: false
189
+ installer:
190
+ legacy_targets:
191
+ - .windsurf/workflows
192
+ target_dir: .windsurf/skills
@@ -2,7 +2,7 @@ const path = require('node:path');
2
2
  const fs = require('fs-extra');
3
3
  const yaml = require('yaml');
4
4
  const { glob } = require('glob');
5
- const { getSourcePath } = require('../../../../lib/project-root');
5
+ const { getSourcePath } = require('../../project-root');
6
6
 
7
7
  async function loadModuleInjectionConfig(handler, moduleName) {
8
8
  const sourceModulesPath = getSourcePath('modules');
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs-extra');
2
2
  const path = require('node:path');
3
3
  const yaml = require('yaml');
4
- const prompts = require('../../lib/prompts');
4
+ const prompts = require('./prompts');
5
5
 
6
6
  /**
7
7
  * Load and display installer messages from messages.yaml
@@ -18,7 +18,7 @@ class MessageLoader {
18
18
  return this.messages;
19
19
  }
20
20
 
21
- const messagesPath = path.join(__dirname, '..', 'install-messages.yaml');
21
+ const messagesPath = path.join(__dirname, 'install-messages.yaml');
22
22
 
23
23
  try {
24
24
  const content = fs.readFileSync(messagesPath, 'utf8');
@@ -0,0 +1,197 @@
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const yaml = require('yaml');
4
+ const { CustomHandler } = require('../custom-handler');
5
+ const { Manifest } = require('../core/manifest');
6
+ const prompts = require('../prompts');
7
+
8
+ class CustomModules {
9
+ constructor() {
10
+ this.paths = new Map();
11
+ }
12
+
13
+ has(moduleCode) {
14
+ return this.paths.has(moduleCode);
15
+ }
16
+
17
+ get(moduleCode) {
18
+ return this.paths.get(moduleCode);
19
+ }
20
+
21
+ set(moduleId, sourcePath) {
22
+ this.paths.set(moduleId, sourcePath);
23
+ }
24
+
25
+ /**
26
+ * Install a custom module from its source path.
27
+ * @param {string} moduleName - Module identifier
28
+ * @param {string} bmadDir - Target bmad directory
29
+ * @param {Function} fileTrackingCallback - Optional callback to track installed files
30
+ * @param {Object} options - Install options
31
+ * @param {Object} options.moduleConfig - Pre-collected module configuration
32
+ * @returns {Object} Install result
33
+ */
34
+ async install(moduleName, bmadDir, fileTrackingCallback = null, options = {}) {
35
+ const sourcePath = this.paths.get(moduleName);
36
+ if (!sourcePath) {
37
+ throw new Error(`No source path for custom module '${moduleName}'`);
38
+ }
39
+
40
+ if (!(await fs.pathExists(sourcePath))) {
41
+ throw new Error(`Source for custom module '${moduleName}' not found at: ${sourcePath}`);
42
+ }
43
+
44
+ const targetPath = path.join(bmadDir, moduleName);
45
+
46
+ // Read custom.yaml and merge into module config
47
+ let moduleConfig = options.moduleConfig ? { ...options.moduleConfig } : {};
48
+ const customConfigPath = path.join(sourcePath, 'custom.yaml');
49
+ if (await fs.pathExists(customConfigPath)) {
50
+ try {
51
+ const content = await fs.readFile(customConfigPath, 'utf8');
52
+ const customConfig = yaml.parse(content);
53
+ if (customConfig) {
54
+ moduleConfig = { ...moduleConfig, ...customConfig };
55
+ }
56
+ } catch (error) {
57
+ await prompts.log.warn(`Failed to read custom.yaml for ${moduleName}: ${error.message}`);
58
+ }
59
+ }
60
+
61
+ // Remove existing installation
62
+ if (await fs.pathExists(targetPath)) {
63
+ await fs.remove(targetPath);
64
+ }
65
+
66
+ // Copy files with filtering
67
+ await this._copyWithFiltering(sourcePath, targetPath, fileTrackingCallback);
68
+
69
+ // Add to manifest
70
+ const manifest = new Manifest();
71
+ const versionInfo = await manifest.getModuleVersionInfo(moduleName, bmadDir, sourcePath);
72
+ await manifest.addModule(bmadDir, moduleName, {
73
+ version: versionInfo.version,
74
+ source: versionInfo.source,
75
+ npmPackage: versionInfo.npmPackage,
76
+ repoUrl: versionInfo.repoUrl,
77
+ });
78
+
79
+ return { success: true, module: moduleName, path: targetPath, moduleConfig };
80
+ }
81
+
82
+ /**
83
+ * Copy module files, filtering out install-time-only artifacts.
84
+ * @param {string} sourcePath - Source module directory
85
+ * @param {string} targetPath - Target module directory
86
+ * @param {Function} fileTrackingCallback - Optional callback to track installed files
87
+ */
88
+ async _copyWithFiltering(sourcePath, targetPath, fileTrackingCallback = null) {
89
+ const files = await this._getFileList(sourcePath);
90
+
91
+ for (const file of files) {
92
+ if (file.startsWith('sub-modules/')) continue;
93
+
94
+ const isInSidecar = path
95
+ .dirname(file)
96
+ .split('/')
97
+ .some((dir) => dir.toLowerCase().endsWith('-sidecar'));
98
+ if (isInSidecar) continue;
99
+
100
+ if (file === 'module.yaml') continue;
101
+ if (file === 'config.yaml') continue;
102
+
103
+ const sourceFile = path.join(sourcePath, file);
104
+ const targetFile = path.join(targetPath, file);
105
+
106
+ // Skip web-only agents
107
+ if (file.startsWith('agents/') && file.endsWith('.md')) {
108
+ const content = await fs.readFile(sourceFile, 'utf8');
109
+ if (/<agent[^>]*\slocalskip="true"[^>]*>/.test(content)) {
110
+ continue;
111
+ }
112
+ }
113
+
114
+ await fs.ensureDir(path.dirname(targetFile));
115
+ await fs.copy(sourceFile, targetFile, { overwrite: true });
116
+
117
+ if (fileTrackingCallback) {
118
+ fileTrackingCallback(targetFile);
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Recursively list all files in a directory.
125
+ * @param {string} dir - Directory to scan
126
+ * @param {string} baseDir - Base directory for relative paths
127
+ * @returns {string[]} Relative file paths
128
+ */
129
+ async _getFileList(dir, baseDir = dir) {
130
+ const files = [];
131
+ const entries = await fs.readdir(dir, { withFileTypes: true });
132
+
133
+ for (const entry of entries) {
134
+ const fullPath = path.join(dir, entry.name);
135
+ if (entry.isDirectory()) {
136
+ files.push(...(await this._getFileList(fullPath, baseDir)));
137
+ } else {
138
+ files.push(path.relative(baseDir, fullPath));
139
+ }
140
+ }
141
+
142
+ return files;
143
+ }
144
+
145
+ /**
146
+ * Discover custom module source paths from all available sources.
147
+ * @param {Object} config - Installation configuration
148
+ * @param {Object} paths - InstallPaths instance
149
+ * @returns {Map<string, string>} Map of module ID to source path
150
+ */
151
+ async discoverPaths(config, paths) {
152
+ this.paths = new Map();
153
+
154
+ if (config._quickUpdate) {
155
+ if (config._customModuleSources) {
156
+ for (const [moduleId, customInfo] of config._customModuleSources) {
157
+ this.paths.set(moduleId, customInfo.sourcePath);
158
+ }
159
+ }
160
+ return this.paths;
161
+ }
162
+
163
+ // From UI: selectedFiles
164
+ if (config.customContent && config.customContent.selected && config.customContent.selectedFiles) {
165
+ const customHandler = new CustomHandler();
166
+ for (const customFile of config.customContent.selectedFiles) {
167
+ const customInfo = await customHandler.getCustomInfo(customFile, paths.projectRoot);
168
+ if (customInfo && customInfo.id) {
169
+ this.paths.set(customInfo.id, customInfo.path);
170
+ }
171
+ }
172
+ }
173
+
174
+ // From UI: sources
175
+ if (config.customContent && config.customContent.sources) {
176
+ for (const source of config.customContent.sources) {
177
+ this.paths.set(source.id, source.path);
178
+ }
179
+ }
180
+
181
+ // From UI: cachedModules
182
+ if (config.customContent && config.customContent.cachedModules) {
183
+ const selectedCachedIds = config.customContent.selectedCachedModules || [];
184
+ const shouldIncludeAll = selectedCachedIds.length === 0 && config.customContent.selected;
185
+
186
+ for (const cachedModule of config.customContent.cachedModules) {
187
+ if (cachedModule.id && cachedModule.cachePath && (shouldIncludeAll || selectedCachedIds.includes(cachedModule.id))) {
188
+ this.paths.set(cachedModule.id, cachedModule.cachePath);
189
+ }
190
+ }
191
+ }
192
+
193
+ return this.paths;
194
+ }
195
+ }
196
+
197
+ module.exports = { CustomModules };