@zeyue0329/xiaoma-cli 1.0.37 → 1.0.38

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 +4 -4
  89. package/dist/agents/database-architect.txt +0 -322
@@ -1,27 +1,27 @@
1
- const fs = require('node:fs');
2
- const path = require('node:path');
3
- const yaml = require('js-yaml');
1
+ const fs = require("node:fs");
2
+ const path = require("node:path");
3
+ const yaml = require("js-yaml");
4
4
 
5
5
  const arguments_ = process.argv.slice(2);
6
- const bumpType = arguments_[0] || 'minor'; // default to minor
6
+ const bumpType = arguments_[0] || "minor"; // default to minor
7
7
 
8
- if (!['major', 'minor', 'patch'].includes(bumpType)) {
9
- console.log('Usage: node bump-all-versions.js [major|minor|patch]');
10
- console.log('Default: minor');
8
+ if (!["major", "minor", "patch"].includes(bumpType)) {
9
+ console.log("Usage: node bump-all-versions.js [major|minor|patch]");
10
+ console.log("Default: minor");
11
11
  process.exit(1);
12
12
  }
13
13
 
14
14
  function bumpVersion(currentVersion, type) {
15
- const [major, minor, patch] = currentVersion.split('.').map(Number);
15
+ const [major, minor, patch] = currentVersion.split(".").map(Number);
16
16
 
17
17
  switch (type) {
18
- case 'major': {
18
+ case "major": {
19
19
  return `${major + 1}.0.0`;
20
20
  }
21
- case 'minor': {
21
+ case "minor": {
22
22
  return `${major}.${minor + 1}.0`;
23
23
  }
24
- case 'patch': {
24
+ case "patch": {
25
25
  return `${major}.${minor}.${patch + 1}`;
26
26
  }
27
27
  default: {
@@ -34,44 +34,50 @@ async function bumpAllVersions() {
34
34
  const updatedItems = [];
35
35
 
36
36
  // First, bump the core version (package.json)
37
- const packagePath = path.join(__dirname, '..', 'package.json');
37
+ const packagePath = path.join(__dirname, "..", "package.json");
38
38
  try {
39
- const packageContent = fs.readFileSync(packagePath, 'utf8');
39
+ const packageContent = fs.readFileSync(packagePath, "utf8");
40
40
  const packageJson = JSON.parse(packageContent);
41
- const oldCoreVersion = packageJson.version || '1.0.0';
41
+ const oldCoreVersion = packageJson.version || "1.0.0";
42
42
  const newCoreVersion = bumpVersion(oldCoreVersion, bumpType);
43
43
 
44
44
  packageJson.version = newCoreVersion;
45
45
 
46
- fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n');
46
+ fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + "\n");
47
47
 
48
48
  updatedItems.push({
49
- type: 'core',
50
- name: 'BMad Core',
49
+ type: "core",
50
+ name: "BMad Core",
51
51
  oldVersion: oldCoreVersion,
52
52
  newVersion: newCoreVersion,
53
53
  });
54
- console.log(`✓ BMad Core (package.json): ${oldCoreVersion} → ${newCoreVersion}`);
54
+ console.log(
55
+ `✓ BMad Core (package.json): ${oldCoreVersion} → ${newCoreVersion}`,
56
+ );
55
57
  } catch (error) {
56
58
  console.error(`✗ Failed to update BMad Core: ${error.message}`);
57
59
  }
58
60
 
59
61
  // Then, bump all expansion packs
60
- const expansionPacksDir = path.join(__dirname, '..', 'expansion-packs');
62
+ const expansionPacksDir = path.join(__dirname, "..", "expansion-packs");
61
63
 
62
64
  try {
63
65
  const entries = fs.readdirSync(expansionPacksDir, { withFileTypes: true });
64
66
 
65
67
  for (const entry of entries) {
66
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'README.md') {
68
+ if (
69
+ entry.isDirectory() &&
70
+ !entry.name.startsWith(".") &&
71
+ entry.name !== "README.md"
72
+ ) {
67
73
  const packId = entry.name;
68
- const configPath = path.join(expansionPacksDir, packId, 'config.yaml');
74
+ const configPath = path.join(expansionPacksDir, packId, "config.yaml");
69
75
 
70
76
  if (fs.existsSync(configPath)) {
71
77
  try {
72
- const configContent = fs.readFileSync(configPath, 'utf8');
78
+ const configContent = fs.readFileSync(configPath, "utf8");
73
79
  const config = yaml.load(configContent);
74
- const oldVersion = config.version || '1.0.0';
80
+ const oldVersion = config.version || "1.0.0";
75
81
  const newVersion = bumpVersion(oldVersion, bumpType);
76
82
 
77
83
  config.version = newVersion;
@@ -79,7 +85,12 @@ async function bumpAllVersions() {
79
85
  const updatedYaml = yaml.dump(config, { indent: 2 });
80
86
  fs.writeFileSync(configPath, updatedYaml);
81
87
 
82
- updatedItems.push({ type: 'expansion', name: packId, oldVersion, newVersion });
88
+ updatedItems.push({
89
+ type: "expansion",
90
+ name: packId,
91
+ oldVersion,
92
+ newVersion,
93
+ });
83
94
  console.log(`✓ ${packId}: ${oldVersion} → ${newVersion}`);
84
95
  } catch (error) {
85
96
  console.error(`✗ Failed to update ${packId}: ${error.message}`);
@@ -89,25 +100,32 @@ async function bumpAllVersions() {
89
100
  }
90
101
 
91
102
  if (updatedItems.length > 0) {
92
- const coreCount = updatedItems.filter((index) => index.type === 'core').length;
93
- const expansionCount = updatedItems.filter((index) => index.type === 'expansion').length;
103
+ const coreCount = updatedItems.filter(
104
+ (index) => index.type === "core",
105
+ ).length;
106
+ const expansionCount = updatedItems.filter(
107
+ (index) => index.type === "expansion",
108
+ ).length;
94
109
 
95
110
  console.log(
96
111
  `\n✓ Successfully bumped ${updatedItems.length} item(s) with ${bumpType} version bump`,
97
112
  );
98
113
  if (coreCount > 0) console.log(` - ${coreCount} core`);
99
- if (expansionCount > 0) console.log(` - ${expansionCount} expansion pack(s)`);
114
+ if (expansionCount > 0)
115
+ console.log(` - ${expansionCount} expansion pack(s)`);
100
116
 
101
- console.log('\nNext steps:');
102
- console.log('1. Test the changes');
117
+ console.log("\nNext steps:");
118
+ console.log("1. Test the changes");
103
119
  console.log(
104
- '2. Commit: git add -A && git commit -m "chore: bump all versions (' + bumpType + ')"',
120
+ '2. Commit: git add -A && git commit -m "chore: bump all versions (' +
121
+ bumpType +
122
+ ')"',
105
123
  );
106
124
  } else {
107
- console.log('No items found to update');
125
+ console.log("No items found to update");
108
126
  }
109
127
  } catch (error) {
110
- console.error('Error reading expansion packs directory:', error.message);
128
+ console.error("Error reading expansion packs directory:", error.message);
111
129
  process.exit(1);
112
130
  }
113
131
  }
package/tools/cli.js CHANGED
@@ -1,24 +1,24 @@
1
- const { Command } = require('commander');
2
- const WebBuilder = require('./builders/web-builder');
3
- const V3ToV4Upgrader = require('./upgraders/v3-to-v4-upgrader');
4
- const IdeSetup = require('./installer/lib/ide-setup');
5
- const path = require('node:path');
1
+ const { Command } = require("commander");
2
+ const WebBuilder = require("./builders/web-builder");
3
+ const V3ToV4Upgrader = require("./upgraders/v3-to-v4-upgrader");
4
+ const IdeSetup = require("./installer/lib/ide-setup");
5
+ const path = require("node:path");
6
6
 
7
7
  const program = new Command();
8
8
 
9
9
  program
10
- .name('bmad-build')
11
- .description('XIAOMA-CLI™ build tool for creating web bundles')
12
- .version('4.0.0');
10
+ .name("bmad-build")
11
+ .description("XIAOMA-CLI™ build tool for creating web bundles")
12
+ .version("4.0.0");
13
13
 
14
14
  program
15
- .command('build')
16
- .description('Build web bundles for agents and teams')
17
- .option('-a, --agents-only', 'Build only agent bundles')
18
- .option('-t, --teams-only', 'Build only team bundles')
19
- .option('-e, --expansions-only', 'Build only expansion pack bundles')
20
- .option('--no-expansions', 'Skip building expansion packs')
21
- .option('--no-clean', 'Skip cleaning output directories')
15
+ .command("build")
16
+ .description("Build web bundles for agents and teams")
17
+ .option("-a, --agents-only", "Build only agent bundles")
18
+ .option("-t, --teams-only", "Build only team bundles")
19
+ .option("-e, --expansions-only", "Build only expansion pack bundles")
20
+ .option("--no-expansions", "Skip building expansion packs")
21
+ .option("--no-clean", "Skip cleaning output directories")
22
22
  .action(async (options) => {
23
23
  const builder = new WebBuilder({
24
24
  rootDir: process.cwd(),
@@ -26,42 +26,42 @@ program
26
26
 
27
27
  try {
28
28
  if (options.clean) {
29
- console.log('Cleaning output directories...');
29
+ console.log("Cleaning output directories...");
30
30
  await builder.cleanOutputDirs();
31
31
  }
32
32
 
33
33
  if (options.expansionsOnly) {
34
- console.log('Building expansion pack bundles...');
34
+ console.log("Building expansion pack bundles...");
35
35
  await builder.buildAllExpansionPacks({ clean: false });
36
36
  } else {
37
37
  if (!options.teamsOnly) {
38
- console.log('Building agent bundles...');
38
+ console.log("Building agent bundles...");
39
39
  await builder.buildAgents();
40
40
  }
41
41
 
42
42
  if (!options.agentsOnly) {
43
- console.log('Building team bundles...');
43
+ console.log("Building team bundles...");
44
44
  await builder.buildTeams();
45
45
  }
46
46
 
47
47
  if (!options.noExpansions) {
48
- console.log('Building expansion pack bundles...');
48
+ console.log("Building expansion pack bundles...");
49
49
  await builder.buildAllExpansionPacks({ clean: false });
50
50
  }
51
51
  }
52
52
 
53
- console.log('Build completed successfully!');
53
+ console.log("Build completed successfully!");
54
54
  } catch (error) {
55
- console.error('Build failed:', error.message);
55
+ console.error("Build failed:", error.message);
56
56
  process.exit(1);
57
57
  }
58
58
  });
59
59
 
60
60
  program
61
- .command('build:expansions')
62
- .description('Build web bundles for all expansion packs')
63
- .option('--expansion <name>', 'Build specific expansion pack only')
64
- .option('--no-clean', 'Skip cleaning output directories')
61
+ .command("build:expansions")
62
+ .description("Build web bundles for all expansion packs")
63
+ .option("--expansion <name>", "Build specific expansion pack only")
64
+ .option("--no-clean", "Skip cleaning output directories")
65
65
  .action(async (options) => {
66
66
  const builder = new WebBuilder({
67
67
  rootDir: process.cwd(),
@@ -70,44 +70,46 @@ program
70
70
  try {
71
71
  if (options.expansion) {
72
72
  console.log(`Building expansion pack: ${options.expansion}`);
73
- await builder.buildExpansionPack(options.expansion, { clean: options.clean });
73
+ await builder.buildExpansionPack(options.expansion, {
74
+ clean: options.clean,
75
+ });
74
76
  } else {
75
- console.log('Building all expansion packs...');
77
+ console.log("Building all expansion packs...");
76
78
  await builder.buildAllExpansionPacks({ clean: options.clean });
77
79
  }
78
80
 
79
- console.log('Expansion pack build completed successfully!');
81
+ console.log("Expansion pack build completed successfully!");
80
82
  } catch (error) {
81
- console.error('Expansion pack build failed:', error.message);
83
+ console.error("Expansion pack build failed:", error.message);
82
84
  process.exit(1);
83
85
  }
84
86
  });
85
87
 
86
88
  program
87
- .command('list:agents')
88
- .description('List all available agents')
89
+ .command("list:agents")
90
+ .description("List all available agents")
89
91
  .action(async () => {
90
92
  const builder = new WebBuilder({ rootDir: process.cwd() });
91
93
  const agents = await builder.resolver.listAgents();
92
- console.log('Available agents:');
94
+ console.log("Available agents:");
93
95
  for (const agent of agents) console.log(` - ${agent}`);
94
96
  process.exit(0);
95
97
  });
96
98
 
97
99
  program
98
- .command('list:expansions')
99
- .description('List all available expansion packs')
100
+ .command("list:expansions")
101
+ .description("List all available expansion packs")
100
102
  .action(async () => {
101
103
  const builder = new WebBuilder({ rootDir: process.cwd() });
102
104
  const expansions = await builder.listExpansionPacks();
103
- console.log('Available expansion packs:');
105
+ console.log("Available expansion packs:");
104
106
  for (const expansion of expansions) console.log(` - ${expansion}`);
105
107
  process.exit(0);
106
108
  });
107
109
 
108
110
  program
109
- .command('validate')
110
- .description('Validate agent and team configurations')
111
+ .command("validate")
112
+ .description("Validate agent and team configurations")
111
113
  .action(async () => {
112
114
  const builder = new WebBuilder({ rootDir: process.cwd() });
113
115
  try {
@@ -115,31 +117,34 @@ program
115
117
  const agents = await builder.resolver.listAgents();
116
118
  const teams = await builder.resolver.listTeams();
117
119
 
118
- console.log('Validating agents...');
120
+ console.log("Validating agents...");
119
121
  for (const agent of agents) {
120
122
  await builder.resolver.resolveAgentDependencies(agent);
121
123
  console.log(` ✓ ${agent}`);
122
124
  }
123
125
 
124
- console.log('\nValidating teams...');
126
+ console.log("\nValidating teams...");
125
127
  for (const team of teams) {
126
128
  await builder.resolver.resolveTeamDependencies(team);
127
129
  console.log(` ✓ ${team}`);
128
130
  }
129
131
 
130
- console.log('\nAll configurations are valid!');
132
+ console.log("\nAll configurations are valid!");
131
133
  } catch (error) {
132
- console.error('Validation failed:', error.message);
134
+ console.error("Validation failed:", error.message);
133
135
  process.exit(1);
134
136
  }
135
137
  });
136
138
 
137
139
  program
138
- .command('upgrade')
139
- .description('Upgrade a XIAOMA-CLI™ V3 project to V4')
140
- .option('-p, --project <path>', 'Path to V3 project (defaults to current directory)')
141
- .option('--dry-run', 'Show what would be changed without making changes')
142
- .option('--no-backup', 'Skip creating backup (not recommended)')
140
+ .command("upgrade")
141
+ .description("Upgrade a XIAOMA-CLI™ V3 project to V4")
142
+ .option(
143
+ "-p, --project <path>",
144
+ "Path to V3 project (defaults to current directory)",
145
+ )
146
+ .option("--dry-run", "Show what would be changed without making changes")
147
+ .option("--no-backup", "Skip creating backup (not recommended)")
143
148
  .action(async (options) => {
144
149
  const upgrader = new V3ToV4Upgrader();
145
150
  await upgrader.upgrade({
@@ -1,7 +1,7 @@
1
- const fs = require('fs-extra');
2
- const path = require('node:path');
3
- const os = require('node:os');
4
- const { isBinaryFile } = require('./binary.js');
1
+ const fs = require("fs-extra");
2
+ const path = require("node:path");
3
+ const os = require("node:os");
4
+ const { isBinaryFile } = require("./binary.js");
5
5
 
6
6
  /**
7
7
  * Aggregate file contents with bounded concurrency.
@@ -22,10 +22,16 @@ async function aggregateFileContents(files, rootDir, spinner = null) {
22
22
  // Automatic concurrency selection based on CPU count and workload size.
23
23
  // - Base on 2x logical CPUs, clamped to [2, 64]
24
24
  // - For very small workloads, avoid excessive parallelism
25
- const cpuCount = os.cpus && Array.isArray(os.cpus()) ? os.cpus().length : os.cpus?.length || 4;
25
+ const cpuCount =
26
+ os.cpus && Array.isArray(os.cpus())
27
+ ? os.cpus().length
28
+ : os.cpus?.length || 4;
26
29
  let concurrency = Math.min(64, Math.max(2, (Number(cpuCount) || 4) * 2));
27
30
  if (files.length > 0 && files.length < concurrency) {
28
- concurrency = Math.max(1, Math.min(concurrency, Math.ceil(files.length / 2)));
31
+ concurrency = Math.max(
32
+ 1,
33
+ Math.min(concurrency, Math.ceil(files.length / 2)),
34
+ );
29
35
  }
30
36
 
31
37
  async function processOne(filePath) {
@@ -38,25 +44,37 @@ async function aggregateFileContents(files, rootDir, spinner = null) {
38
44
  const binary = await isBinaryFile(filePath);
39
45
  if (binary) {
40
46
  const { size } = await fs.stat(filePath);
41
- results.binaryFiles.push({ path: relativePath, absolutePath: filePath, size });
47
+ results.binaryFiles.push({
48
+ path: relativePath,
49
+ absolutePath: filePath,
50
+ size,
51
+ });
42
52
  } else {
43
- const content = await fs.readFile(filePath, 'utf8');
53
+ const content = await fs.readFile(filePath, "utf8");
44
54
  results.textFiles.push({
45
55
  path: relativePath,
46
56
  absolutePath: filePath,
47
57
  content,
48
58
  size: content.length,
49
- lines: content.split('\n').length,
59
+ lines: content.split("\n").length,
50
60
  });
51
61
  }
52
62
  } catch (error) {
53
63
  const relativePath = path.relative(rootDir, filePath);
54
- const errorInfo = { path: relativePath, absolutePath: filePath, error: error.message };
64
+ const errorInfo = {
65
+ path: relativePath,
66
+ absolutePath: filePath,
67
+ error: error.message,
68
+ };
55
69
  results.errors.push(errorInfo);
56
70
  if (spinner) {
57
- spinner.warn(`Warning: Could not read file ${relativePath}: ${error.message}`);
71
+ spinner.warn(
72
+ `Warning: Could not read file ${relativePath}: ${error.message}`,
73
+ );
58
74
  } else {
59
- console.warn(`Warning: Could not read file ${relativePath}: ${error.message}`);
75
+ console.warn(
76
+ `Warning: Could not read file ${relativePath}: ${error.message}`,
77
+ );
60
78
  }
61
79
  } finally {
62
80
  results.processedFiles++;
@@ -1,6 +1,6 @@
1
- const fsp = require('node:fs/promises');
2
- const path = require('node:path');
3
- const { Buffer } = require('node:buffer');
1
+ const fsp = require("node:fs/promises");
2
+ const path = require("node:path");
3
+ const { Buffer } = require("node:buffer");
4
4
 
5
5
  /**
6
6
  * Efficiently determine if a file is binary without reading the whole file.
@@ -13,46 +13,46 @@ async function isBinaryFile(filePath) {
13
13
  try {
14
14
  const stats = await fsp.stat(filePath);
15
15
  if (stats.isDirectory()) {
16
- throw new Error('EISDIR: illegal operation on a directory');
16
+ throw new Error("EISDIR: illegal operation on a directory");
17
17
  }
18
18
 
19
19
  const binaryExtensions = new Set([
20
- '.jpg',
21
- '.jpeg',
22
- '.png',
23
- '.gif',
24
- '.bmp',
25
- '.ico',
26
- '.svg',
27
- '.pdf',
28
- '.doc',
29
- '.docx',
30
- '.xls',
31
- '.xlsx',
32
- '.ppt',
33
- '.pptx',
34
- '.zip',
35
- '.tar',
36
- '.gz',
37
- '.rar',
38
- '.7z',
39
- '.exe',
40
- '.dll',
41
- '.so',
42
- '.dylib',
43
- '.mp3',
44
- '.mp4',
45
- '.avi',
46
- '.mov',
47
- '.wav',
48
- '.ttf',
49
- '.otf',
50
- '.woff',
51
- '.woff2',
52
- '.bin',
53
- '.dat',
54
- '.db',
55
- '.sqlite',
20
+ ".jpg",
21
+ ".jpeg",
22
+ ".png",
23
+ ".gif",
24
+ ".bmp",
25
+ ".ico",
26
+ ".svg",
27
+ ".pdf",
28
+ ".doc",
29
+ ".docx",
30
+ ".xls",
31
+ ".xlsx",
32
+ ".ppt",
33
+ ".pptx",
34
+ ".zip",
35
+ ".tar",
36
+ ".gz",
37
+ ".rar",
38
+ ".7z",
39
+ ".exe",
40
+ ".dll",
41
+ ".so",
42
+ ".dylib",
43
+ ".mp3",
44
+ ".mp4",
45
+ ".avi",
46
+ ".mov",
47
+ ".wav",
48
+ ".ttf",
49
+ ".otf",
50
+ ".woff",
51
+ ".woff2",
52
+ ".bin",
53
+ ".dat",
54
+ ".db",
55
+ ".sqlite",
56
56
  ]);
57
57
 
58
58
  const extension = path.extname(filePath).toLowerCase();
@@ -60,17 +60,20 @@ async function isBinaryFile(filePath) {
60
60
  if (stats.size === 0) return false;
61
61
 
62
62
  const sampleSize = Math.min(4096, stats.size);
63
- const fd = await fsp.open(filePath, 'r');
63
+ const fd = await fsp.open(filePath, "r");
64
64
  try {
65
65
  const buffer = Buffer.allocUnsafe(sampleSize);
66
66
  const { bytesRead } = await fd.read(buffer, 0, sampleSize, 0);
67
- const slice = bytesRead === sampleSize ? buffer : buffer.subarray(0, bytesRead);
67
+ const slice =
68
+ bytesRead === sampleSize ? buffer : buffer.subarray(0, bytesRead);
68
69
  return slice.includes(0);
69
70
  } finally {
70
71
  await fd.close();
71
72
  }
72
73
  } catch (error) {
73
- console.warn(`Warning: Could not determine if file is binary: ${filePath} - ${error.message}`);
74
+ console.warn(
75
+ `Warning: Could not determine if file is binary: ${filePath} - ${error.message}`,
76
+ );
74
77
  return false;
75
78
  }
76
79
  }
@@ -1,20 +1,24 @@
1
- const path = require('node:path');
2
- const { execFile } = require('node:child_process');
3
- const { promisify } = require('node:util');
4
- const { glob } = require('glob');
5
- const { loadIgnore } = require('./ignoreRules.js');
1
+ const path = require("node:path");
2
+ const { execFile } = require("node:child_process");
3
+ const { promisify } = require("node:util");
4
+ const { glob } = require("glob");
5
+ const { loadIgnore } = require("./ignoreRules.js");
6
6
 
7
7
  const pExecFile = promisify(execFile);
8
8
 
9
9
  async function isGitRepo(rootDir) {
10
10
  try {
11
- const { stdout } = await pExecFile('git', ['rev-parse', '--is-inside-work-tree'], {
12
- cwd: rootDir,
13
- });
11
+ const { stdout } = await pExecFile(
12
+ "git",
13
+ ["rev-parse", "--is-inside-work-tree"],
14
+ {
15
+ cwd: rootDir,
16
+ },
17
+ );
14
18
  return (
15
- String(stdout || '')
19
+ String(stdout || "")
16
20
  .toString()
17
- .trim() === 'true'
21
+ .trim() === "true"
18
22
  );
19
23
  } catch {
20
24
  return false;
@@ -23,10 +27,14 @@ async function isGitRepo(rootDir) {
23
27
 
24
28
  async function gitListFiles(rootDir) {
25
29
  try {
26
- const { stdout } = await pExecFile('git', ['ls-files', '-co', '--exclude-standard'], {
27
- cwd: rootDir,
28
- });
29
- return String(stdout || '')
30
+ const { stdout } = await pExecFile(
31
+ "git",
32
+ ["ls-files", "-co", "--exclude-standard"],
33
+ {
34
+ cwd: rootDir,
35
+ },
36
+ );
37
+ return String(stdout || "")
30
38
  .split(/\r?\n/)
31
39
  .map((s) => s.trim())
32
40
  .filter(Boolean);
@@ -56,7 +64,7 @@ async function discoverFiles(rootDir, options = {}) {
56
64
  }
57
65
 
58
66
  // Glob fallback
59
- const globbed = await glob('**/*', {
67
+ const globbed = await glob("**/*", {
60
68
  cwd: rootDir,
61
69
  nodir: true,
62
70
  dot: true,
@@ -1,8 +1,8 @@
1
- const path = require('node:path');
2
- const discovery = require('./discovery.js');
3
- const ignoreRules = require('./ignoreRules.js');
4
- const { isBinaryFile } = require('./binary.js');
5
- const { aggregateFileContents } = require('./aggregate.js');
1
+ const path = require("node:path");
2
+ const discovery = require("./discovery.js");
3
+ const ignoreRules = require("./ignoreRules.js");
4
+ const { isBinaryFile } = require("./binary.js");
5
+ const { aggregateFileContents } = require("./aggregate.js");
6
6
 
7
7
  // Backward-compatible signature; delegate to central loader
8
8
  async function parseGitignore(gitignorePath) {
@@ -14,7 +14,7 @@ async function discoverFiles(rootDir) {
14
14
  // Delegate to discovery module which respects .gitignore and defaults
15
15
  return await discovery.discoverFiles(rootDir, { preferGit: true });
16
16
  } catch (error) {
17
- console.error('Error discovering files:', error.message);
17
+ console.error("Error discovering files:", error.message);
18
18
  return [];
19
19
  }
20
20
  }