@zeyue0329/xiaoma-cli 1.0.37 → 1.0.39

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 (89) hide show
  1. package/.idea/workspace.xml +27 -26
  2. package/JAVA-BACKEND-COMMANDS-REFERENCE.md +62 -52
  3. package/JAVA-BACKEND-ITERATION-GUIDE.md +125 -18
  4. package/README.md +1 -1
  5. package/common/utils/bmad-doc-template.md +5 -5
  6. package/dist/agents/analyst.txt +35 -5
  7. package/dist/agents/architect.txt +217 -31
  8. package/dist/agents/automation-orchestrator.txt +4 -4
  9. package/dist/agents/dev.txt +3 -3
  10. package/dist/agents/full-requirement-orchestrator.txt +11 -11
  11. package/dist/agents/qa.txt +102 -102
  12. package/dist/agents/sm.txt +6 -6
  13. package/dist/agents/ux-expert.txt +6 -1
  14. package/dist/agents/workflow-executor.txt +879 -0
  15. package/dist/agents/xiaoma-master.txt +258 -37
  16. package/dist/teams/team-all.txt +1223 -445
  17. package/dist/teams/team-fullstack-with-database.txt +384 -446
  18. package/dist/teams/team-fullstack.txt +258 -37
  19. package/dist/teams/team-ide-minimal.txt +111 -111
  20. package/dist/teams/team-no-ui.txt +252 -36
  21. package/docs/architecture-sharding-modification.md +623 -0
  22. package/docs/automated-requirements-analysis-outputs.md +896 -0
  23. package/package.json +1 -1
  24. package/tools/builders/web-builder.js +292 -142
  25. package/tools/bump-all-versions.js +50 -32
  26. package/tools/cli.js +52 -47
  27. package/tools/flattener/aggregate.js +30 -12
  28. package/tools/flattener/binary.js +46 -43
  29. package/tools/flattener/discovery.js +23 -15
  30. package/tools/flattener/files.js +6 -6
  31. package/tools/flattener/ignoreRules.js +122 -121
  32. package/tools/flattener/main.js +249 -144
  33. package/tools/flattener/projectRoot.js +74 -69
  34. package/tools/flattener/prompts.js +12 -10
  35. package/tools/flattener/stats.helpers.js +90 -61
  36. package/tools/flattener/stats.js +1 -1
  37. package/tools/flattener/test-matrix.js +225 -170
  38. package/tools/flattener/xml.js +31 -23
  39. package/tools/installer/bin/xiaoma.js +199 -153
  40. package/tools/installer/lib/config-loader.js +76 -47
  41. package/tools/installer/lib/file-manager.js +101 -44
  42. package/tools/installer/lib/ide-base-setup.js +49 -39
  43. package/tools/installer/lib/ide-setup.js +694 -380
  44. package/tools/installer/lib/installer.js +802 -469
  45. package/tools/installer/lib/memory-profiler.js +22 -12
  46. package/tools/installer/lib/module-manager.js +16 -14
  47. package/tools/installer/lib/resource-locator.js +61 -35
  48. package/tools/lib/dependency-resolver.js +34 -23
  49. package/tools/lib/yaml-utils.js +7 -2
  50. package/tools/preview-release-notes.js +33 -25
  51. package/tools/shared/bannerArt.js +3 -3
  52. package/tools/sync-installer-version.js +16 -7
  53. package/tools/upgraders/v3-to-v4-upgrader.js +244 -163
  54. package/tools/version-bump.js +24 -18
  55. package/tools/xiaoma-npx-wrapper.js +15 -10
  56. package/tools/yaml-format.js +60 -36
  57. package/xiaoma-core/agent-teams/team-fullstack-with-database.yaml +0 -1
  58. package/xiaoma-core/agents/automated-fix-validator.yaml +2 -1
  59. package/xiaoma-core/agents/automated-quality-validator.yaml +10 -5
  60. package/xiaoma-core/agents/automation-orchestrator.md +4 -4
  61. package/xiaoma-core/agents/dev.md +4 -4
  62. package/xiaoma-core/agents/enhanced-workflow-orchestrator.yaml +2 -1
  63. package/xiaoma-core/agents/full-requirement-orchestrator.md +11 -11
  64. package/xiaoma-core/agents/global-requirements-auditor.yaml +11 -3
  65. package/xiaoma-core/agents/intelligent-template-adapter.yaml +19 -5
  66. package/xiaoma-core/agents/master-execution-engine.yaml +19 -5
  67. package/xiaoma-core/agents/workflow-executor.md +8 -4
  68. package/xiaoma-core/agents/xiaoma-master.md +1 -1
  69. package/xiaoma-core/data/test-levels-framework.md +12 -12
  70. package/xiaoma-core/tasks/analyze-existing-database.md +1 -1
  71. package/xiaoma-core/tasks/apply-qa-fixes.md +3 -3
  72. package/xiaoma-core/tasks/batch-story-generation.md +22 -22
  73. package/xiaoma-core/tasks/create-enhanced-story-with-database.md +6 -6
  74. package/xiaoma-core/tasks/nfr-assess.md +6 -6
  75. package/xiaoma-core/tasks/project-integration-testing.md +42 -42
  76. package/xiaoma-core/tasks/qa-gate.md +23 -23
  77. package/xiaoma-core/tasks/review-story.md +18 -18
  78. package/xiaoma-core/tasks/risk-profile.md +25 -25
  79. package/xiaoma-core/tasks/serial-development-orchestration.md +51 -51
  80. package/xiaoma-core/tasks/test-design.md +9 -9
  81. package/xiaoma-core/tasks/trace-requirements.md +21 -21
  82. package/xiaoma-core/templates/competitor-analysis-tmpl.yaml +35 -5
  83. package/xiaoma-core/templates/front-end-architecture-tmpl.yaml +77 -11
  84. package/xiaoma-core/templates/front-end-spec-tmpl.yaml +6 -1
  85. package/xiaoma-core/templates/fullstack-architecture-tmpl.yaml +140 -20
  86. package/xiaoma-core/templates/global-qa-monitoring-tmpl.yaml +2 -1
  87. package/xiaoma-core/templates/requirements-coverage-audit.yaml +2 -1
  88. package/xiaoma-core/workflows/automated-requirements-analysis.yaml +283 -6
  89. package/dist/agents/database-architect.txt +0 -322
@@ -1,39 +1,39 @@
1
- const fs = require('node:fs').promises;
2
- const path = require('node:path');
3
- const DependencyResolver = require('../lib/dependency-resolver');
4
- const yamlUtilities = require('../lib/yaml-utils');
1
+ const fs = require("node:fs").promises;
2
+ const path = require("node:path");
3
+ const DependencyResolver = require("../lib/dependency-resolver");
4
+ const yamlUtilities = require("../lib/yaml-utils");
5
5
 
6
6
  class WebBuilder {
7
7
  constructor(options = {}) {
8
8
  this.rootDir = options.rootDir || process.cwd();
9
- this.outputDirs = options.outputDirs || [path.join(this.rootDir, 'dist')];
9
+ this.outputDirs = options.outputDirs || [path.join(this.rootDir, "dist")];
10
10
  this.resolver = new DependencyResolver(this.rootDir);
11
11
  this.templatePath = path.join(
12
12
  this.rootDir,
13
- 'tools',
14
- 'md-assets',
15
- 'web-agent-startup-instructions.md',
13
+ "tools",
14
+ "md-assets",
15
+ "web-agent-startup-instructions.md",
16
16
  );
17
17
  }
18
18
 
19
19
  parseYaml(content) {
20
- const yaml = require('js-yaml');
20
+ const yaml = require("js-yaml");
21
21
  return yaml.load(content);
22
22
  }
23
23
 
24
- convertToWebPath(filePath, bundleRoot = 'xiaoma-core') {
24
+ convertToWebPath(filePath, bundleRoot = "xiaoma-core") {
25
25
  // Convert absolute paths to web bundle paths with dot prefix
26
26
  // All resources get installed under the bundle root, so use that path
27
27
  const relativePath = path.relative(this.rootDir, filePath);
28
28
  const pathParts = relativePath.split(path.sep);
29
29
 
30
30
  let resourcePath;
31
- if (pathParts[0] === 'expansion-packs') {
31
+ if (pathParts[0] === "expansion-packs") {
32
32
  // For expansion packs, remove 'expansion-packs/packname' and use the rest
33
- resourcePath = pathParts.slice(2).join('/');
33
+ resourcePath = pathParts.slice(2).join("/");
34
34
  } else {
35
35
  // For xiaoma-core, common, etc., remove the first part
36
- resourcePath = pathParts.slice(1).join('/');
36
+ resourcePath = pathParts.slice(1).join("/");
37
37
  }
38
38
 
39
39
  return `.${bundleRoot}/${resourcePath}`;
@@ -41,22 +41,22 @@ class WebBuilder {
41
41
 
42
42
  generateWebInstructions(bundleType, packName = null) {
43
43
  // Generate dynamic web instructions based on bundle type
44
- const rootExample = packName ? `.${packName}` : '.xiaoma-core';
44
+ const rootExample = packName ? `.${packName}` : ".xiaoma-core";
45
45
  const examplePath = packName
46
46
  ? `.${packName}/folder/filename.md`
47
- : '.xiaoma-core/folder/filename.md';
47
+ : ".xiaoma-core/folder/filename.md";
48
48
  const personasExample = packName
49
49
  ? `.${packName}/personas/analyst.md`
50
- : '.xiaoma-core/personas/analyst.md';
50
+ : ".xiaoma-core/personas/analyst.md";
51
51
  const tasksExample = packName
52
52
  ? `.${packName}/tasks/create-story.md`
53
- : '.xiaoma-core/tasks/create-story.md';
53
+ : ".xiaoma-core/tasks/create-story.md";
54
54
  const utilitiesExample = packName
55
55
  ? `.${packName}/utils/template-format.md`
56
- : '.xiaoma-core/utils/template-format.md';
56
+ : ".xiaoma-core/utils/template-format.md";
57
57
  const tasksReference = packName
58
58
  ? `.${packName}/tasks/create-story.md`
59
- : '.xiaoma-core/tasks/create-story.md';
59
+ : ".xiaoma-core/tasks/create-story.md";
60
60
 
61
61
  return `# Web Agent Bundle Instructions
62
62
 
@@ -122,14 +122,16 @@ These references map directly to bundle sections:
122
122
 
123
123
  // Write to all output directories
124
124
  for (const outputDir of this.outputDirs) {
125
- const outputPath = path.join(outputDir, 'agents');
125
+ const outputPath = path.join(outputDir, "agents");
126
126
  await fs.mkdir(outputPath, { recursive: true });
127
127
  const outputFile = path.join(outputPath, `${agentId}.txt`);
128
- await fs.writeFile(outputFile, bundle, 'utf8');
128
+ await fs.writeFile(outputFile, bundle, "utf8");
129
129
  }
130
130
  }
131
131
 
132
- console.log(`Built ${agents.length} agent bundles in ${this.outputDirs.length} locations`);
132
+ console.log(
133
+ `Built ${agents.length} agent bundles in ${this.outputDirs.length} locations`,
134
+ );
133
135
  }
134
136
 
135
137
  async buildTeams() {
@@ -141,58 +143,76 @@ These references map directly to bundle sections:
141
143
 
142
144
  // Write to all output directories
143
145
  for (const outputDir of this.outputDirs) {
144
- const outputPath = path.join(outputDir, 'teams');
146
+ const outputPath = path.join(outputDir, "teams");
145
147
  await fs.mkdir(outputPath, { recursive: true });
146
148
  const outputFile = path.join(outputPath, `${teamId}.txt`);
147
- await fs.writeFile(outputFile, bundle, 'utf8');
149
+ await fs.writeFile(outputFile, bundle, "utf8");
148
150
  }
149
151
  }
150
152
 
151
- console.log(`Built ${teams.length} team bundles in ${this.outputDirs.length} locations`);
153
+ console.log(
154
+ `Built ${teams.length} team bundles in ${this.outputDirs.length} locations`,
155
+ );
152
156
  }
153
157
 
154
158
  async buildAgentBundle(agentId) {
155
159
  const dependencies = await this.resolver.resolveAgentDependencies(agentId);
156
- const template = this.generateWebInstructions('agent');
160
+ const template = this.generateWebInstructions("agent");
157
161
 
158
162
  const sections = [template];
159
163
 
160
164
  // Add agent configuration
161
- const agentPath = this.convertToWebPath(dependencies.agent.path, 'xiaoma-core');
162
- sections.push(this.formatSection(agentPath, dependencies.agent.content, 'xiaoma-core'));
165
+ const agentPath = this.convertToWebPath(
166
+ dependencies.agent.path,
167
+ "xiaoma-core",
168
+ );
169
+ sections.push(
170
+ this.formatSection(agentPath, dependencies.agent.content, "xiaoma-core"),
171
+ );
163
172
 
164
173
  // Add all dependencies
165
174
  for (const resource of dependencies.resources) {
166
- const resourcePath = this.convertToWebPath(resource.path, 'xiaoma-core');
167
- sections.push(this.formatSection(resourcePath, resource.content, 'xiaoma-core'));
175
+ const resourcePath = this.convertToWebPath(resource.path, "xiaoma-core");
176
+ sections.push(
177
+ this.formatSection(resourcePath, resource.content, "xiaoma-core"),
178
+ );
168
179
  }
169
180
 
170
- return sections.join('\n');
181
+ return sections.join("\n");
171
182
  }
172
183
 
173
184
  async buildTeamBundle(teamId) {
174
185
  const dependencies = await this.resolver.resolveTeamDependencies(teamId);
175
- const template = this.generateWebInstructions('team');
186
+ const template = this.generateWebInstructions("team");
176
187
 
177
188
  const sections = [template];
178
189
 
179
190
  // Add team configuration
180
- const teamPath = this.convertToWebPath(dependencies.team.path, 'xiaoma-core');
181
- sections.push(this.formatSection(teamPath, dependencies.team.content, 'xiaoma-core'));
191
+ const teamPath = this.convertToWebPath(
192
+ dependencies.team.path,
193
+ "xiaoma-core",
194
+ );
195
+ sections.push(
196
+ this.formatSection(teamPath, dependencies.team.content, "xiaoma-core"),
197
+ );
182
198
 
183
199
  // Add all agents
184
200
  for (const agent of dependencies.agents) {
185
- const agentPath = this.convertToWebPath(agent.path, 'xiaoma-core');
186
- sections.push(this.formatSection(agentPath, agent.content, 'xiaoma-core'));
201
+ const agentPath = this.convertToWebPath(agent.path, "xiaoma-core");
202
+ sections.push(
203
+ this.formatSection(agentPath, agent.content, "xiaoma-core"),
204
+ );
187
205
  }
188
206
 
189
207
  // Add all deduplicated resources
190
208
  for (const resource of dependencies.resources) {
191
- const resourcePath = this.convertToWebPath(resource.path, 'xiaoma-core');
192
- sections.push(this.formatSection(resourcePath, resource.content, 'xiaoma-core'));
209
+ const resourcePath = this.convertToWebPath(resource.path, "xiaoma-core");
210
+ sections.push(
211
+ this.formatSection(resourcePath, resource.content, "xiaoma-core"),
212
+ );
193
213
  }
194
214
 
195
- return sections.join('\n');
215
+ return sections.join("\n");
196
216
  }
197
217
 
198
218
  processAgentContent(content) {
@@ -208,50 +228,53 @@ These references map directly to bundle sections:
208
228
 
209
229
  // Parse YAML and remove root and IDE-FILE-RESOLUTION properties
210
230
  try {
211
- const yaml = require('js-yaml');
231
+ const yaml = require("js-yaml");
212
232
  const parsed = yaml.load(yamlContent);
213
233
 
214
234
  // Remove the properties if they exist at root level
215
235
  delete parsed.root;
216
- delete parsed['IDE-FILE-RESOLUTION'];
217
- delete parsed['REQUEST-RESOLUTION'];
236
+ delete parsed["IDE-FILE-RESOLUTION"];
237
+ delete parsed["REQUEST-RESOLUTION"];
218
238
 
219
239
  // Also remove from activation-instructions if they exist
220
- if (parsed['activation-instructions'] && Array.isArray(parsed['activation-instructions'])) {
221
- parsed['activation-instructions'] = parsed['activation-instructions'].filter(
222
- (instruction) => {
223
- return (
224
- typeof instruction === 'string' &&
225
- !instruction.startsWith('IDE-FILE-RESOLUTION:') &&
226
- !instruction.startsWith('REQUEST-RESOLUTION:')
227
- );
228
- },
229
- );
240
+ if (
241
+ parsed["activation-instructions"] &&
242
+ Array.isArray(parsed["activation-instructions"])
243
+ ) {
244
+ parsed["activation-instructions"] = parsed[
245
+ "activation-instructions"
246
+ ].filter((instruction) => {
247
+ return (
248
+ typeof instruction === "string" &&
249
+ !instruction.startsWith("IDE-FILE-RESOLUTION:") &&
250
+ !instruction.startsWith("REQUEST-RESOLUTION:")
251
+ );
252
+ });
230
253
  }
231
254
 
232
255
  // Reconstruct the YAML
233
256
  const cleanedYaml = yaml.dump(parsed, { lineWidth: -1 });
234
257
 
235
258
  // Get the agent name from the YAML for the header
236
- const agentName = parsed.agent?.id || 'agent';
259
+ const agentName = parsed.agent?.id || "agent";
237
260
 
238
261
  // Build the new content with just the agent header and YAML
239
262
  const newHeader = `# ${agentName}\n\nCRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n`;
240
263
  const afterYaml = content.slice(Math.max(0, yamlEndIndex));
241
264
 
242
- return newHeader + '```yaml\n' + cleanedYaml.trim() + '\n```' + afterYaml;
265
+ return newHeader + "```yaml\n" + cleanedYaml.trim() + "\n```" + afterYaml;
243
266
  } catch (error) {
244
- console.warn('Failed to process agent YAML:', error.message);
267
+ console.warn("Failed to process agent YAML:", error.message);
245
268
  // If parsing fails, return original content
246
269
  return content;
247
270
  }
248
271
  }
249
272
 
250
- formatSection(path, content, bundleRoot = 'xiaoma-core') {
251
- const separator = '====================';
273
+ formatSection(path, content, bundleRoot = "xiaoma-core") {
274
+ const separator = "====================";
252
275
 
253
276
  // Process agent content if this is an agent file
254
- if (path.includes('/agents/')) {
277
+ if (path.includes("/agents/")) {
255
278
  content = this.processAgentContent(content);
256
279
  }
257
280
 
@@ -262,17 +285,17 @@ These references map directly to bundle sections:
262
285
  `${separator} START: ${path} ${separator}`,
263
286
  content.trim(),
264
287
  `${separator} END: ${path} ${separator}`,
265
- '',
266
- ].join('\n');
288
+ "",
289
+ ].join("\n");
267
290
  }
268
291
 
269
292
  replaceRootReferences(content, bundleRoot) {
270
293
  // Replace {root} with the appropriate bundle root path
271
- return content.replaceAll('{root}', `.${bundleRoot}`);
294
+ return content.replaceAll("{root}", `.${bundleRoot}`);
272
295
  }
273
296
 
274
297
  async validate() {
275
- console.log('Validating agent configurations...');
298
+ console.log("Validating agent configurations...");
276
299
  const agents = await this.resolver.listAgents();
277
300
  for (const agentId of agents) {
278
301
  try {
@@ -284,7 +307,7 @@ These references map directly to bundle sections:
284
307
  }
285
308
  }
286
309
 
287
- console.log('\nValidating team configurations...');
310
+ console.log("\nValidating team configurations...");
288
311
  const teams = await this.resolver.listTeams();
289
312
  for (const teamId of teams) {
290
313
  try {
@@ -309,8 +332,10 @@ These references map directly to bundle sections:
309
332
  }
310
333
 
311
334
  async buildExpansionPack(packName, options = {}) {
312
- const packDir = path.join(this.rootDir, 'expansion-packs', packName);
313
- const outputDirectories = [path.join(this.rootDir, 'dist', 'expansion-packs', packName)];
335
+ const packDir = path.join(this.rootDir, "expansion-packs", packName);
336
+ const outputDirectories = [
337
+ path.join(this.rootDir, "dist", "expansion-packs", packName),
338
+ ];
314
339
 
315
340
  // Clean output directories if requested
316
341
  if (options.clean !== false) {
@@ -324,27 +349,31 @@ These references map directly to bundle sections:
324
349
  }
325
350
 
326
351
  // Build individual agents first
327
- const agentsDir = path.join(packDir, 'agents');
352
+ const agentsDir = path.join(packDir, "agents");
328
353
  try {
329
354
  const agentFiles = await fs.readdir(agentsDir);
330
- const agentMarkdownFiles = agentFiles.filter((f) => f.endsWith('.md'));
355
+ const agentMarkdownFiles = agentFiles.filter((f) => f.endsWith(".md"));
331
356
 
332
357
  if (agentMarkdownFiles.length > 0) {
333
358
  console.log(` Building individual agents for ${packName}:`);
334
359
 
335
360
  for (const agentFile of agentMarkdownFiles) {
336
- const agentName = agentFile.replace('.md', '');
361
+ const agentName = agentFile.replace(".md", "");
337
362
  console.log(` - ${agentName}`);
338
363
 
339
364
  // Build individual agent bundle
340
- const bundle = await this.buildExpansionAgentBundle(packName, packDir, agentName);
365
+ const bundle = await this.buildExpansionAgentBundle(
366
+ packName,
367
+ packDir,
368
+ agentName,
369
+ );
341
370
 
342
371
  // Write to all output directories
343
372
  for (const outputDir of outputDirectories) {
344
- const agentsOutputDir = path.join(outputDir, 'agents');
373
+ const agentsOutputDir = path.join(outputDir, "agents");
345
374
  await fs.mkdir(agentsOutputDir, { recursive: true });
346
375
  const outputFile = path.join(agentsOutputDir, `${agentName}.txt`);
347
- await fs.writeFile(outputFile, bundle, 'utf8');
376
+ await fs.writeFile(outputFile, bundle, "utf8");
348
377
  }
349
378
  }
350
379
  }
@@ -353,28 +382,39 @@ These references map directly to bundle sections:
353
382
  }
354
383
 
355
384
  // Build team bundle
356
- const agentTeamsDir = path.join(packDir, 'agent-teams');
385
+ const agentTeamsDir = path.join(packDir, "agent-teams");
357
386
  try {
358
387
  const teamFiles = await fs.readdir(agentTeamsDir);
359
- const teamFile = teamFiles.find((f) => f.endsWith('.yaml'));
388
+ const teamFile = teamFiles.find((f) => f.endsWith(".yaml"));
360
389
 
361
390
  if (teamFile) {
362
391
  console.log(` Building team bundle for ${packName}`);
363
392
  const teamConfigPath = path.join(agentTeamsDir, teamFile);
364
393
 
365
394
  // Build expansion pack as a team bundle
366
- const bundle = await this.buildExpansionTeamBundle(packName, packDir, teamConfigPath);
395
+ const bundle = await this.buildExpansionTeamBundle(
396
+ packName,
397
+ packDir,
398
+ teamConfigPath,
399
+ );
367
400
 
368
401
  // Write to all output directories
369
402
  for (const outputDir of outputDirectories) {
370
- const teamsOutputDir = path.join(outputDir, 'teams');
403
+ const teamsOutputDir = path.join(outputDir, "teams");
371
404
  await fs.mkdir(teamsOutputDir, { recursive: true });
372
- const outputFile = path.join(teamsOutputDir, teamFile.replace('.yaml', '.txt'));
373
- await fs.writeFile(outputFile, bundle, 'utf8');
374
- console.log(` ✓ Created bundle: ${path.relative(this.rootDir, outputFile)}`);
405
+ const outputFile = path.join(
406
+ teamsOutputDir,
407
+ teamFile.replace(".yaml", ".txt"),
408
+ );
409
+ await fs.writeFile(outputFile, bundle, "utf8");
410
+ console.log(
411
+ ` ✓ Created bundle: ${path.relative(this.rootDir, outputFile)}`,
412
+ );
375
413
  }
376
414
  } else {
377
- console.warn(` ⚠ No team configuration found in ${packName}/agent-teams/`);
415
+ console.warn(
416
+ ` ⚠ No team configuration found in ${packName}/agent-teams/`,
417
+ );
378
418
  }
379
419
  } catch {
380
420
  console.warn(` ⚠ No agent-teams directory found for ${packName}`);
@@ -382,12 +422,12 @@ These references map directly to bundle sections:
382
422
  }
383
423
 
384
424
  async buildExpansionAgentBundle(packName, packDir, agentName) {
385
- const template = this.generateWebInstructions('expansion-agent', packName);
425
+ const template = this.generateWebInstructions("expansion-agent", packName);
386
426
  const sections = [template];
387
427
 
388
428
  // Add agent configuration
389
- const agentPath = path.join(packDir, 'agents', `${agentName}.md`);
390
- const agentContent = await fs.readFile(agentPath, 'utf8');
429
+ const agentPath = path.join(packDir, "agents", `${agentName}.md`);
430
+ const agentContent = await fs.readFile(agentPath, "utf8");
391
431
  const agentWebPath = this.convertToWebPath(agentPath, packName);
392
432
  sections.push(this.formatSection(agentWebPath, agentContent, packName));
393
433
 
@@ -395,22 +435,40 @@ These references map directly to bundle sections:
395
435
  const yamlContent = yamlUtilities.extractYamlFromAgent(agentContent);
396
436
  if (yamlContent) {
397
437
  try {
398
- const yaml = require('js-yaml');
438
+ const yaml = require("js-yaml");
399
439
  const agentConfig = yaml.load(yamlContent);
400
440
 
401
441
  if (agentConfig.dependencies) {
402
442
  // Add resources, first try expansion pack, then core
403
- for (const [resourceType, resources] of Object.entries(agentConfig.dependencies)) {
443
+ for (const [resourceType, resources] of Object.entries(
444
+ agentConfig.dependencies,
445
+ )) {
404
446
  if (Array.isArray(resources)) {
405
447
  for (const resourceName of resources) {
406
448
  let found = false;
407
449
 
408
450
  // Try expansion pack first
409
- const resourcePath = path.join(packDir, resourceType, resourceName);
451
+ const resourcePath = path.join(
452
+ packDir,
453
+ resourceType,
454
+ resourceName,
455
+ );
410
456
  try {
411
- const resourceContent = await fs.readFile(resourcePath, 'utf8');
412
- const resourceWebPath = this.convertToWebPath(resourcePath, packName);
413
- sections.push(this.formatSection(resourceWebPath, resourceContent, packName));
457
+ const resourceContent = await fs.readFile(
458
+ resourcePath,
459
+ "utf8",
460
+ );
461
+ const resourceWebPath = this.convertToWebPath(
462
+ resourcePath,
463
+ packName,
464
+ );
465
+ sections.push(
466
+ this.formatSection(
467
+ resourceWebPath,
468
+ resourceContent,
469
+ packName,
470
+ ),
471
+ );
414
472
  found = true;
415
473
  } catch {
416
474
  // Not in expansion pack, continue
@@ -420,14 +478,19 @@ These references map directly to bundle sections:
420
478
  if (!found) {
421
479
  const corePath = path.join(
422
480
  this.rootDir,
423
- 'xiaoma-core',
481
+ "xiaoma-core",
424
482
  resourceType,
425
483
  resourceName,
426
484
  );
427
485
  try {
428
- const coreContent = await fs.readFile(corePath, 'utf8');
429
- const coreWebPath = this.convertToWebPath(corePath, packName);
430
- sections.push(this.formatSection(coreWebPath, coreContent, packName));
486
+ const coreContent = await fs.readFile(corePath, "utf8");
487
+ const coreWebPath = this.convertToWebPath(
488
+ corePath,
489
+ packName,
490
+ );
491
+ sections.push(
492
+ this.formatSection(coreWebPath, coreContent, packName),
493
+ );
431
494
  found = true;
432
495
  } catch {
433
496
  // Not in core either, continue
@@ -436,11 +499,25 @@ These references map directly to bundle sections:
436
499
 
437
500
  // If not found in core, try common folder
438
501
  if (!found) {
439
- const commonPath = path.join(this.rootDir, 'common', resourceType, resourceName);
502
+ const commonPath = path.join(
503
+ this.rootDir,
504
+ "common",
505
+ resourceType,
506
+ resourceName,
507
+ );
440
508
  try {
441
- const commonContent = await fs.readFile(commonPath, 'utf8');
442
- const commonWebPath = this.convertToWebPath(commonPath, packName);
443
- sections.push(this.formatSection(commonWebPath, commonContent, packName));
509
+ const commonContent = await fs.readFile(commonPath, "utf8");
510
+ const commonWebPath = this.convertToWebPath(
511
+ commonPath,
512
+ packName,
513
+ );
514
+ sections.push(
515
+ this.formatSection(
516
+ commonWebPath,
517
+ commonContent,
518
+ packName,
519
+ ),
520
+ );
444
521
  found = true;
445
522
  } catch {
446
523
  // Not in common either, continue
@@ -457,32 +534,35 @@ These references map directly to bundle sections:
457
534
  }
458
535
  }
459
536
  } catch (error) {
460
- console.debug(`Failed to parse agent YAML for ${agentName}:`, error.message);
537
+ console.debug(
538
+ `Failed to parse agent YAML for ${agentName}:`,
539
+ error.message,
540
+ );
461
541
  }
462
542
  }
463
543
 
464
- return sections.join('\n');
544
+ return sections.join("\n");
465
545
  }
466
546
 
467
547
  async buildExpansionTeamBundle(packName, packDir, teamConfigPath) {
468
- const template = this.generateWebInstructions('expansion-team', packName);
548
+ const template = this.generateWebInstructions("expansion-team", packName);
469
549
 
470
550
  const sections = [template];
471
551
 
472
552
  // Add team configuration and parse to get agent list
473
- const teamContent = await fs.readFile(teamConfigPath, 'utf8');
474
- const teamFileName = path.basename(teamConfigPath, '.yaml');
553
+ const teamContent = await fs.readFile(teamConfigPath, "utf8");
554
+ const teamFileName = path.basename(teamConfigPath, ".yaml");
475
555
  const teamConfig = this.parseYaml(teamContent);
476
556
  const teamWebPath = this.convertToWebPath(teamConfigPath, packName);
477
557
  sections.push(this.formatSection(teamWebPath, teamContent, packName));
478
558
 
479
559
  // Get list of expansion pack agents
480
560
  const expansionAgents = new Set();
481
- const agentsDir = path.join(packDir, 'agents');
561
+ const agentsDir = path.join(packDir, "agents");
482
562
  try {
483
563
  const agentFiles = await fs.readdir(agentsDir);
484
- for (const agentFile of agentFiles.filter((f) => f.endsWith('.md'))) {
485
- const agentName = agentFile.replace('.md', '');
564
+ for (const agentFile of agentFiles.filter((f) => f.endsWith(".md"))) {
565
+ const agentName = agentFile.replace(".md", "");
486
566
  expansionAgents.add(agentName);
487
567
  }
488
568
  } catch {
@@ -491,13 +571,19 @@ These references map directly to bundle sections:
491
571
 
492
572
  // Build a map of all available expansion pack resources for override checking
493
573
  const expansionResources = new Map();
494
- const resourceDirectories = ['templates', 'tasks', 'checklists', 'workflows', 'data'];
574
+ const resourceDirectories = [
575
+ "templates",
576
+ "tasks",
577
+ "checklists",
578
+ "workflows",
579
+ "data",
580
+ ];
495
581
  for (const resourceDir of resourceDirectories) {
496
582
  const resourcePath = path.join(packDir, resourceDir);
497
583
  try {
498
584
  const resourceFiles = await fs.readdir(resourcePath);
499
585
  for (const resourceFile of resourceFiles.filter(
500
- (f) => f.endsWith('.md') || f.endsWith('.yaml'),
586
+ (f) => f.endsWith(".md") || f.endsWith(".yaml"),
501
587
  )) {
502
588
  expansionResources.set(`${resourceDir}#${resourceFile}`, true);
503
589
  }
@@ -510,9 +596,11 @@ These references map directly to bundle sections:
510
596
  const agentsToProcess = teamConfig.agents || [];
511
597
 
512
598
  // Ensure xiaoma-orchestrator is always included for teams
513
- if (!agentsToProcess.includes('xiaoma-orchestrator')) {
514
- console.warn(` ⚠ Team ${teamFileName} missing xiaoma-orchestrator, adding automatically`);
515
- agentsToProcess.unshift('xiaoma-orchestrator');
599
+ if (!agentsToProcess.includes("xiaoma-orchestrator")) {
600
+ console.warn(
601
+ ` ⚠ Team ${teamFileName} missing xiaoma-orchestrator, adding automatically`,
602
+ );
603
+ agentsToProcess.unshift("xiaoma-orchestrator");
516
604
  }
517
605
 
518
606
  // Track all dependencies from all agents (deduplicated)
@@ -522,9 +610,14 @@ These references map directly to bundle sections:
522
610
  if (expansionAgents.has(agentId)) {
523
611
  // Use expansion pack version (override)
524
612
  const agentPath = path.join(agentsDir, `${agentId}.md`);
525
- const agentContent = await fs.readFile(agentPath, 'utf8');
526
- const expansionAgentWebPath = this.convertToWebPath(agentPath, packName);
527
- sections.push(this.formatSection(expansionAgentWebPath, agentContent, packName));
613
+ const agentContent = await fs.readFile(agentPath, "utf8");
614
+ const expansionAgentWebPath = this.convertToWebPath(
615
+ agentPath,
616
+ packName,
617
+ );
618
+ sections.push(
619
+ this.formatSection(expansionAgentWebPath, agentContent, packName),
620
+ );
528
621
 
529
622
  // Parse and collect dependencies from expansion agent
530
623
  const agentYaml = agentContent.match(/```yaml\n([\s\S]*?)\n```/);
@@ -532,52 +625,83 @@ These references map directly to bundle sections:
532
625
  try {
533
626
  const agentConfig = this.parseYaml(agentYaml[1]);
534
627
  if (agentConfig.dependencies) {
535
- for (const [resourceType, resources] of Object.entries(agentConfig.dependencies)) {
628
+ for (const [resourceType, resources] of Object.entries(
629
+ agentConfig.dependencies,
630
+ )) {
536
631
  if (Array.isArray(resources)) {
537
632
  for (const resourceName of resources) {
538
633
  const key = `${resourceType}#${resourceName}`;
539
634
  if (!allDependencies.has(key)) {
540
- allDependencies.set(key, { type: resourceType, name: resourceName });
635
+ allDependencies.set(key, {
636
+ type: resourceType,
637
+ name: resourceName,
638
+ });
541
639
  }
542
640
  }
543
641
  }
544
642
  }
545
643
  }
546
644
  } catch (error) {
547
- console.debug(`Failed to parse agent YAML for ${agentId}:`, error.message);
645
+ console.debug(
646
+ `Failed to parse agent YAML for ${agentId}:`,
647
+ error.message,
648
+ );
548
649
  }
549
650
  }
550
651
  } else {
551
652
  // Use core BMad version
552
653
  try {
553
- const coreAgentPath = path.join(this.rootDir, 'xiaoma-core', 'agents', `${agentId}.md`);
554
- const coreAgentContent = await fs.readFile(coreAgentPath, 'utf8');
555
- const coreAgentWebPath = this.convertToWebPath(coreAgentPath, packName);
556
- sections.push(this.formatSection(coreAgentWebPath, coreAgentContent, packName));
654
+ const coreAgentPath = path.join(
655
+ this.rootDir,
656
+ "xiaoma-core",
657
+ "agents",
658
+ `${agentId}.md`,
659
+ );
660
+ const coreAgentContent = await fs.readFile(coreAgentPath, "utf8");
661
+ const coreAgentWebPath = this.convertToWebPath(
662
+ coreAgentPath,
663
+ packName,
664
+ );
665
+ sections.push(
666
+ this.formatSection(coreAgentWebPath, coreAgentContent, packName),
667
+ );
557
668
 
558
669
  // Parse and collect dependencies from core agent
559
- const yamlContent = yamlUtilities.extractYamlFromAgent(coreAgentContent, true);
670
+ const yamlContent = yamlUtilities.extractYamlFromAgent(
671
+ coreAgentContent,
672
+ true,
673
+ );
560
674
  if (yamlContent) {
561
675
  try {
562
676
  const agentConfig = this.parseYaml(yamlContent);
563
677
  if (agentConfig.dependencies) {
564
- for (const [resourceType, resources] of Object.entries(agentConfig.dependencies)) {
678
+ for (const [resourceType, resources] of Object.entries(
679
+ agentConfig.dependencies,
680
+ )) {
565
681
  if (Array.isArray(resources)) {
566
682
  for (const resourceName of resources) {
567
683
  const key = `${resourceType}#${resourceName}`;
568
684
  if (!allDependencies.has(key)) {
569
- allDependencies.set(key, { type: resourceType, name: resourceName });
685
+ allDependencies.set(key, {
686
+ type: resourceType,
687
+ name: resourceName,
688
+ });
570
689
  }
571
690
  }
572
691
  }
573
692
  }
574
693
  }
575
694
  } catch (error) {
576
- console.debug(`Failed to parse agent YAML for ${agentId}:`, error.message);
695
+ console.debug(
696
+ `Failed to parse agent YAML for ${agentId}:`,
697
+ error.message,
698
+ );
577
699
  }
578
700
  }
579
701
  } catch {
580
- console.warn(` ⚠ Agent ${agentId} not found in core or expansion pack`);
702
+ console.warn(
703
+ ` ⚠ Agent ${agentId} not found in core or expansion pack`,
704
+ );
581
705
  }
582
706
  }
583
707
  }
@@ -592,9 +716,14 @@ These references map directly to bundle sections:
592
716
  // We know it exists in expansion pack, find and load it
593
717
  const expansionPath = path.join(packDir, dep.type, dep.name);
594
718
  try {
595
- const content = await fs.readFile(expansionPath, 'utf8');
596
- const expansionWebPath = this.convertToWebPath(expansionPath, packName);
597
- sections.push(this.formatSection(expansionWebPath, content, packName));
719
+ const content = await fs.readFile(expansionPath, "utf8");
720
+ const expansionWebPath = this.convertToWebPath(
721
+ expansionPath,
722
+ packName,
723
+ );
724
+ sections.push(
725
+ this.formatSection(expansionWebPath, content, packName),
726
+ );
598
727
  console.log(` ✓ Using expansion override for ${key}`);
599
728
  found = true;
600
729
  } catch {
@@ -604,9 +733,14 @@ These references map directly to bundle sections:
604
733
 
605
734
  // If not found in expansion pack (or doesn't exist there), try core
606
735
  if (!found) {
607
- const corePath = path.join(this.rootDir, 'xiaoma-core', dep.type, dep.name);
736
+ const corePath = path.join(
737
+ this.rootDir,
738
+ "xiaoma-core",
739
+ dep.type,
740
+ dep.name,
741
+ );
608
742
  try {
609
- const content = await fs.readFile(corePath, 'utf8');
743
+ const content = await fs.readFile(corePath, "utf8");
610
744
  const coreWebPath = this.convertToWebPath(corePath, packName);
611
745
  sections.push(this.formatSection(coreWebPath, content, packName));
612
746
  found = true;
@@ -617,9 +751,14 @@ These references map directly to bundle sections:
617
751
 
618
752
  // If not found in core, try common folder
619
753
  if (!found) {
620
- const commonPath = path.join(this.rootDir, 'common', dep.type, dep.name);
754
+ const commonPath = path.join(
755
+ this.rootDir,
756
+ "common",
757
+ dep.type,
758
+ dep.name,
759
+ );
621
760
  try {
622
- const content = await fs.readFile(commonPath, 'utf8');
761
+ const content = await fs.readFile(commonPath, "utf8");
623
762
  const commonWebPath = this.convertToWebPath(commonPath, packName);
624
763
  sections.push(this.formatSection(commonWebPath, content, packName));
625
764
  found = true;
@@ -629,7 +768,9 @@ These references map directly to bundle sections:
629
768
  }
630
769
 
631
770
  if (!found) {
632
- console.warn(` ⚠ Dependency ${key} not found in expansion pack or core`);
771
+ console.warn(
772
+ ` ⚠ Dependency ${key} not found in expansion pack or core`,
773
+ );
633
774
  }
634
775
  }
635
776
 
@@ -639,18 +780,23 @@ These references map directly to bundle sections:
639
780
  try {
640
781
  const resourceFiles = await fs.readdir(resourcePath);
641
782
  for (const resourceFile of resourceFiles.filter(
642
- (f) => f.endsWith('.md') || f.endsWith('.yaml'),
783
+ (f) => f.endsWith(".md") || f.endsWith(".yaml"),
643
784
  )) {
644
785
  const filePath = path.join(resourcePath, resourceFile);
645
- const fileContent = await fs.readFile(filePath, 'utf8');
646
- const fileName = resourceFile.replace(/\.(md|yaml)$/, '');
786
+ const fileContent = await fs.readFile(filePath, "utf8");
787
+ const fileName = resourceFile.replace(/\.(md|yaml)$/, "");
647
788
 
648
789
  // Only add if not already included as a dependency
649
790
  const resourceKey = `${resourceDir}#${fileName}`;
650
791
  if (!allDependencies.has(resourceKey)) {
651
792
  const fullResourcePath = path.join(resourcePath, resourceFile);
652
- const resourceWebPath = this.convertToWebPath(fullResourcePath, packName);
653
- sections.push(this.formatSection(resourceWebPath, fileContent, packName));
793
+ const resourceWebPath = this.convertToWebPath(
794
+ fullResourcePath,
795
+ packName,
796
+ );
797
+ sections.push(
798
+ this.formatSection(resourceWebPath, fileContent, packName),
799
+ );
654
800
  }
655
801
  }
656
802
  } catch {
@@ -658,16 +804,20 @@ These references map directly to bundle sections:
658
804
  }
659
805
  }
660
806
 
661
- return sections.join('\n');
807
+ return sections.join("\n");
662
808
  }
663
809
 
664
810
  async listExpansionPacks() {
665
- const expansionPacksDir = path.join(this.rootDir, 'expansion-packs');
811
+ const expansionPacksDir = path.join(this.rootDir, "expansion-packs");
666
812
  try {
667
- const entries = await fs.readdir(expansionPacksDir, { withFileTypes: true });
668
- return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
813
+ const entries = await fs.readdir(expansionPacksDir, {
814
+ withFileTypes: true,
815
+ });
816
+ return entries
817
+ .filter((entry) => entry.isDirectory())
818
+ .map((entry) => entry.name);
669
819
  } catch {
670
- console.warn('No expansion-packs directory found');
820
+ console.warn("No expansion-packs directory found");
671
821
  return [];
672
822
  }
673
823
  }