@zeyue0329/xiaoma-cli 1.0.36 β 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.
- package/.idea/workspace.xml +27 -26
- package/JAVA-BACKEND-COMMANDS-REFERENCE.md +62 -52
- package/JAVA-BACKEND-ITERATION-GUIDE.md +125 -18
- package/README.md +1 -1
- package/common/utils/bmad-doc-template.md +5 -5
- package/dist/agents/analyst.txt +35 -5
- package/dist/agents/architect.txt +217 -31
- package/dist/agents/automation-orchestrator.txt +4 -4
- package/dist/agents/dev.txt +3 -3
- package/dist/agents/full-requirement-orchestrator.txt +11 -11
- package/dist/agents/qa.txt +102 -102
- package/dist/agents/sm.txt +6 -6
- package/dist/agents/ux-expert.txt +6 -1
- package/dist/agents/workflow-executor.txt +879 -0
- package/dist/agents/xiaoma-master.txt +258 -37
- package/dist/teams/team-all.txt +1223 -445
- package/dist/teams/team-fullstack-with-database.txt +384 -446
- package/dist/teams/team-fullstack.txt +258 -37
- package/dist/teams/team-ide-minimal.txt +111 -111
- package/dist/teams/team-no-ui.txt +252 -36
- package/docs/architecture-sharding-modification.md +623 -0
- package/docs/automated-requirements-analysis-outputs.md +896 -0
- package/package.json +1 -1
- package/tools/builders/web-builder.js +292 -142
- package/tools/bump-all-versions.js +50 -32
- package/tools/cli.js +52 -47
- package/tools/flattener/aggregate.js +30 -12
- package/tools/flattener/binary.js +46 -43
- package/tools/flattener/discovery.js +23 -15
- package/tools/flattener/files.js +6 -6
- package/tools/flattener/ignoreRules.js +122 -121
- package/tools/flattener/main.js +249 -144
- package/tools/flattener/projectRoot.js +74 -69
- package/tools/flattener/prompts.js +12 -10
- package/tools/flattener/stats.helpers.js +90 -61
- package/tools/flattener/stats.js +1 -1
- package/tools/flattener/test-matrix.js +225 -170
- package/tools/flattener/xml.js +31 -23
- package/tools/installer/bin/xiaoma.js +199 -153
- package/tools/installer/lib/config-loader.js +76 -47
- package/tools/installer/lib/file-manager.js +101 -44
- package/tools/installer/lib/ide-base-setup.js +49 -39
- package/tools/installer/lib/ide-setup.js +694 -380
- package/tools/installer/lib/installer.js +802 -469
- package/tools/installer/lib/memory-profiler.js +22 -12
- package/tools/installer/lib/module-manager.js +16 -14
- package/tools/installer/lib/resource-locator.js +61 -35
- package/tools/lib/dependency-resolver.js +34 -23
- package/tools/lib/yaml-utils.js +7 -2
- package/tools/preview-release-notes.js +33 -25
- package/tools/shared/bannerArt.js +3 -3
- package/tools/sync-installer-version.js +16 -7
- package/tools/upgraders/v3-to-v4-upgrader.js +244 -163
- package/tools/version-bump.js +24 -18
- package/tools/xiaoma-npx-wrapper.js +15 -10
- package/tools/yaml-format.js +60 -36
- package/xiaoma-core/agent-teams/team-fullstack-with-database.yaml +0 -1
- package/xiaoma-core/agents/automated-fix-validator.yaml +2 -1
- package/xiaoma-core/agents/automated-quality-validator.yaml +10 -5
- package/xiaoma-core/agents/automation-orchestrator.md +4 -4
- package/xiaoma-core/agents/dev.md +4 -4
- package/xiaoma-core/agents/enhanced-workflow-orchestrator.yaml +2 -1
- package/xiaoma-core/agents/full-requirement-orchestrator.md +11 -11
- package/xiaoma-core/agents/global-requirements-auditor.yaml +11 -3
- package/xiaoma-core/agents/intelligent-template-adapter.yaml +19 -5
- package/xiaoma-core/agents/master-execution-engine.yaml +19 -5
- package/xiaoma-core/agents/workflow-executor.md +126 -18
- package/xiaoma-core/agents/xiaoma-master.md +1 -1
- package/xiaoma-core/data/test-levels-framework.md +12 -12
- package/xiaoma-core/tasks/analyze-existing-database.md +1 -1
- package/xiaoma-core/tasks/apply-qa-fixes.md +3 -3
- package/xiaoma-core/tasks/batch-story-generation.md +22 -22
- package/xiaoma-core/tasks/create-enhanced-story-with-database.md +6 -6
- package/xiaoma-core/tasks/nfr-assess.md +6 -6
- package/xiaoma-core/tasks/project-integration-testing.md +42 -42
- package/xiaoma-core/tasks/qa-gate.md +23 -23
- package/xiaoma-core/tasks/review-story.md +18 -18
- package/xiaoma-core/tasks/risk-profile.md +25 -25
- package/xiaoma-core/tasks/serial-development-orchestration.md +51 -51
- package/xiaoma-core/tasks/test-design.md +9 -9
- package/xiaoma-core/tasks/trace-requirements.md +21 -21
- package/xiaoma-core/templates/competitor-analysis-tmpl.yaml +35 -5
- package/xiaoma-core/templates/front-end-architecture-tmpl.yaml +77 -11
- package/xiaoma-core/templates/front-end-spec-tmpl.yaml +6 -1
- package/xiaoma-core/templates/fullstack-architecture-tmpl.yaml +140 -20
- package/xiaoma-core/templates/global-qa-monitoring-tmpl.yaml +2 -1
- package/xiaoma-core/templates/requirements-coverage-audit.yaml +2 -1
- package/xiaoma-core/workflows/automated-requirements-analysis.yaml +4 -4
- package/dist/agents/database-architect.txt +0 -322
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Helps identify memory leaks and optimize resource usage
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const v8 = require(
|
|
6
|
+
const v8 = require("node:v8");
|
|
7
7
|
|
|
8
8
|
class MemoryProfiler {
|
|
9
9
|
constructor() {
|
|
@@ -134,9 +134,11 @@ class MemoryProfiler {
|
|
|
134
134
|
|
|
135
135
|
if (largeGrowths.length > 0) {
|
|
136
136
|
recommendations.push({
|
|
137
|
-
type:
|
|
137
|
+
type: "warning",
|
|
138
138
|
message: `Large memory growth detected in ${largeGrowths.length} operations`,
|
|
139
|
-
details: largeGrowths.map(
|
|
139
|
+
details: largeGrowths.map(
|
|
140
|
+
(g) => `${g.from} β ${g.to}: ${g.heapGrowth}`,
|
|
141
|
+
),
|
|
140
142
|
});
|
|
141
143
|
}
|
|
142
144
|
|
|
@@ -144,9 +146,9 @@ class MemoryProfiler {
|
|
|
144
146
|
if (this.peakMemory > 500 * 1024 * 1024) {
|
|
145
147
|
// 500MB
|
|
146
148
|
recommendations.push({
|
|
147
|
-
type:
|
|
149
|
+
type: "warning",
|
|
148
150
|
message: `High peak memory usage: ${this.formatBytes(this.peakMemory)}`,
|
|
149
|
-
suggestion:
|
|
151
|
+
suggestion: "Consider processing files in smaller batches",
|
|
150
152
|
});
|
|
151
153
|
}
|
|
152
154
|
|
|
@@ -154,9 +156,10 @@ class MemoryProfiler {
|
|
|
154
156
|
const continuousGrowth = this.checkContinuousGrowth();
|
|
155
157
|
if (continuousGrowth) {
|
|
156
158
|
recommendations.push({
|
|
157
|
-
type:
|
|
158
|
-
message:
|
|
159
|
-
details:
|
|
159
|
+
type: "error",
|
|
160
|
+
message: "Potential memory leak detected",
|
|
161
|
+
details:
|
|
162
|
+
"Memory usage continuously increases without significant decreases",
|
|
160
163
|
});
|
|
161
164
|
}
|
|
162
165
|
|
|
@@ -171,7 +174,10 @@ class MemoryProfiler {
|
|
|
171
174
|
|
|
172
175
|
let increasingCount = 0;
|
|
173
176
|
for (let index = 1; index < this.checkpoints.length; index++) {
|
|
174
|
-
if (
|
|
177
|
+
if (
|
|
178
|
+
this.checkpoints[index].raw.heapUsed >
|
|
179
|
+
this.checkpoints[index - 1].raw.heapUsed
|
|
180
|
+
) {
|
|
175
181
|
increasingCount++;
|
|
176
182
|
}
|
|
177
183
|
}
|
|
@@ -184,13 +190,17 @@ class MemoryProfiler {
|
|
|
184
190
|
* Format bytes to human-readable string
|
|
185
191
|
*/
|
|
186
192
|
formatBytes(bytes) {
|
|
187
|
-
if (bytes === 0) return
|
|
193
|
+
if (bytes === 0) return "0 B";
|
|
188
194
|
|
|
189
195
|
const k = 1024;
|
|
190
|
-
const sizes = [
|
|
196
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
191
197
|
const index = Math.floor(Math.log(bytes) / Math.log(k));
|
|
192
198
|
|
|
193
|
-
return
|
|
199
|
+
return (
|
|
200
|
+
Number.parseFloat((bytes / Math.pow(k, index)).toFixed(2)) +
|
|
201
|
+
" " +
|
|
202
|
+
sizes[index]
|
|
203
|
+
);
|
|
194
204
|
}
|
|
195
205
|
|
|
196
206
|
/**
|
|
@@ -15,9 +15,9 @@ class ModuleManager {
|
|
|
15
15
|
*/
|
|
16
16
|
async initializeCommonModules() {
|
|
17
17
|
const modules = await Promise.all([
|
|
18
|
-
this.getModule(
|
|
19
|
-
this.getModule(
|
|
20
|
-
this.getModule(
|
|
18
|
+
this.getModule("chalk"),
|
|
19
|
+
this.getModule("ora"),
|
|
20
|
+
this.getModule("inquirer"),
|
|
21
21
|
]);
|
|
22
22
|
|
|
23
23
|
return {
|
|
@@ -64,20 +64,20 @@ class ModuleManager {
|
|
|
64
64
|
*/
|
|
65
65
|
async _loadModule(moduleName) {
|
|
66
66
|
switch (moduleName) {
|
|
67
|
-
case
|
|
68
|
-
return (await import(
|
|
67
|
+
case "chalk": {
|
|
68
|
+
return (await import("chalk")).default;
|
|
69
69
|
}
|
|
70
|
-
case
|
|
71
|
-
return (await import(
|
|
70
|
+
case "ora": {
|
|
71
|
+
return (await import("ora")).default;
|
|
72
72
|
}
|
|
73
|
-
case
|
|
74
|
-
return (await import(
|
|
73
|
+
case "inquirer": {
|
|
74
|
+
return (await import("inquirer")).default;
|
|
75
75
|
}
|
|
76
|
-
case
|
|
77
|
-
return (await import(
|
|
76
|
+
case "glob": {
|
|
77
|
+
return (await import("glob")).glob;
|
|
78
78
|
}
|
|
79
|
-
case
|
|
80
|
-
return (await import(
|
|
79
|
+
case "globSync": {
|
|
80
|
+
return (await import("glob")).globSync;
|
|
81
81
|
}
|
|
82
82
|
default: {
|
|
83
83
|
throw new Error(`Unknown module: ${moduleName}`);
|
|
@@ -99,7 +99,9 @@ class ModuleManager {
|
|
|
99
99
|
* @returns {Promise<Object>} Object with module names as keys
|
|
100
100
|
*/
|
|
101
101
|
async getModules(moduleNames) {
|
|
102
|
-
const modules = await Promise.all(
|
|
102
|
+
const modules = await Promise.all(
|
|
103
|
+
moduleNames.map((name) => this.getModule(name)),
|
|
104
|
+
);
|
|
103
105
|
|
|
104
106
|
return moduleNames.reduce((accumulator, name, index) => {
|
|
105
107
|
accumulator[name] = modules[index];
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Reduces duplicate file system operations and memory usage
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const path = require(
|
|
7
|
-
const fs = require(
|
|
8
|
-
const moduleManager = require(
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const fs = require("fs-extra");
|
|
8
|
+
const moduleManager = require("./module-manager");
|
|
9
9
|
|
|
10
10
|
class ResourceLocator {
|
|
11
11
|
constructor() {
|
|
@@ -20,7 +20,7 @@ class ResourceLocator {
|
|
|
20
20
|
*/
|
|
21
21
|
getBmadCorePath() {
|
|
22
22
|
if (!this._bmadCorePath) {
|
|
23
|
-
this._bmadCorePath = path.join(__dirname,
|
|
23
|
+
this._bmadCorePath = path.join(__dirname, "../../../xiaoma-core");
|
|
24
24
|
}
|
|
25
25
|
return this._bmadCorePath;
|
|
26
26
|
}
|
|
@@ -30,7 +30,10 @@ class ResourceLocator {
|
|
|
30
30
|
*/
|
|
31
31
|
getExpansionPacksPath() {
|
|
32
32
|
if (!this._expansionPacksPath) {
|
|
33
|
-
this._expansionPacksPath = path.join(
|
|
33
|
+
this._expansionPacksPath = path.join(
|
|
34
|
+
__dirname,
|
|
35
|
+
"../../../expansion-packs",
|
|
36
|
+
);
|
|
34
37
|
}
|
|
35
38
|
return this._expansionPacksPath;
|
|
36
39
|
}
|
|
@@ -48,7 +51,7 @@ class ResourceLocator {
|
|
|
48
51
|
return this._globCache.get(cacheKey);
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
const { glob } = await moduleManager.getModules([
|
|
54
|
+
const { glob } = await moduleManager.getModules(["glob"]);
|
|
52
55
|
const files = await glob(pattern, options);
|
|
53
56
|
|
|
54
57
|
// Cache for 5 minutes
|
|
@@ -71,7 +74,11 @@ class ResourceLocator {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
// Check in xiaoma-core
|
|
74
|
-
let agentPath = path.join(
|
|
77
|
+
let agentPath = path.join(
|
|
78
|
+
this.getBmadCorePath(),
|
|
79
|
+
"agents",
|
|
80
|
+
`${agentId}.md`,
|
|
81
|
+
);
|
|
75
82
|
if (await fs.pathExists(agentPath)) {
|
|
76
83
|
this._pathCache.set(cacheKey, agentPath);
|
|
77
84
|
return agentPath;
|
|
@@ -80,7 +87,7 @@ class ResourceLocator {
|
|
|
80
87
|
// Check in expansion packs
|
|
81
88
|
const expansionPacks = await this.getExpansionPacks();
|
|
82
89
|
for (const pack of expansionPacks) {
|
|
83
|
-
agentPath = path.join(pack.path,
|
|
90
|
+
agentPath = path.join(pack.path, "agents", `${agentId}.md`);
|
|
84
91
|
if (await fs.pathExists(agentPath)) {
|
|
85
92
|
this._pathCache.set(cacheKey, agentPath);
|
|
86
93
|
return agentPath;
|
|
@@ -95,32 +102,35 @@ class ResourceLocator {
|
|
|
95
102
|
* @returns {Promise<Array>} Array of agent objects
|
|
96
103
|
*/
|
|
97
104
|
async getAvailableAgents() {
|
|
98
|
-
const cacheKey =
|
|
105
|
+
const cacheKey = "all-agents";
|
|
99
106
|
|
|
100
107
|
if (this._pathCache.has(cacheKey)) {
|
|
101
108
|
return this._pathCache.get(cacheKey);
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
const agents = [];
|
|
105
|
-
const yaml = require(
|
|
106
|
-
const { extractYamlFromAgent } = require(
|
|
112
|
+
const yaml = require("js-yaml");
|
|
113
|
+
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
|
107
114
|
|
|
108
115
|
// Get agents from xiaoma-core
|
|
109
|
-
const coreAgents = await this.findFiles(
|
|
116
|
+
const coreAgents = await this.findFiles("agents/*.md", {
|
|
110
117
|
cwd: this.getBmadCorePath(),
|
|
111
118
|
});
|
|
112
119
|
|
|
113
120
|
for (const agentFile of coreAgents) {
|
|
114
|
-
const content = await fs.readFile(
|
|
121
|
+
const content = await fs.readFile(
|
|
122
|
+
path.join(this.getBmadCorePath(), agentFile),
|
|
123
|
+
"utf8",
|
|
124
|
+
);
|
|
115
125
|
const yamlContent = extractYamlFromAgent(content);
|
|
116
126
|
if (yamlContent) {
|
|
117
127
|
try {
|
|
118
128
|
const metadata = yaml.load(yamlContent);
|
|
119
129
|
agents.push({
|
|
120
|
-
id: path.basename(agentFile,
|
|
121
|
-
name: metadata.agent_name || path.basename(agentFile,
|
|
122
|
-
description: metadata.description ||
|
|
123
|
-
source:
|
|
130
|
+
id: path.basename(agentFile, ".md"),
|
|
131
|
+
name: metadata.agent_name || path.basename(agentFile, ".md"),
|
|
132
|
+
description: metadata.description || "No description available",
|
|
133
|
+
source: "core",
|
|
124
134
|
});
|
|
125
135
|
} catch {
|
|
126
136
|
// Skip invalid agents
|
|
@@ -140,7 +150,7 @@ class ResourceLocator {
|
|
|
140
150
|
* @returns {Promise<Array>} Array of expansion pack objects
|
|
141
151
|
*/
|
|
142
152
|
async getExpansionPacks() {
|
|
143
|
-
const cacheKey =
|
|
153
|
+
const cacheKey = "expansion-packs";
|
|
144
154
|
|
|
145
155
|
if (this._pathCache.has(cacheKey)) {
|
|
146
156
|
return this._pathCache.get(cacheKey);
|
|
@@ -150,23 +160,31 @@ class ResourceLocator {
|
|
|
150
160
|
const expansionPacksPath = this.getExpansionPacksPath();
|
|
151
161
|
|
|
152
162
|
if (await fs.pathExists(expansionPacksPath)) {
|
|
153
|
-
const entries = await fs.readdir(expansionPacksPath, {
|
|
163
|
+
const entries = await fs.readdir(expansionPacksPath, {
|
|
164
|
+
withFileTypes: true,
|
|
165
|
+
});
|
|
154
166
|
|
|
155
167
|
for (const entry of entries) {
|
|
156
168
|
if (entry.isDirectory()) {
|
|
157
|
-
const configPath = path.join(
|
|
169
|
+
const configPath = path.join(
|
|
170
|
+
expansionPacksPath,
|
|
171
|
+
entry.name,
|
|
172
|
+
"config.yaml",
|
|
173
|
+
);
|
|
158
174
|
if (await fs.pathExists(configPath)) {
|
|
159
175
|
try {
|
|
160
|
-
const yaml = require(
|
|
161
|
-
const config = yaml.load(await fs.readFile(configPath,
|
|
176
|
+
const yaml = require("js-yaml");
|
|
177
|
+
const config = yaml.load(await fs.readFile(configPath, "utf8"));
|
|
162
178
|
packs.push({
|
|
163
179
|
id: entry.name,
|
|
164
180
|
name: config.name || entry.name,
|
|
165
|
-
version: config.version ||
|
|
166
|
-
description: config.description ||
|
|
181
|
+
version: config.version || "1.0.0",
|
|
182
|
+
description: config.description || "No description available",
|
|
167
183
|
shortTitle:
|
|
168
|
-
config[
|
|
169
|
-
|
|
184
|
+
config["short-title"] ||
|
|
185
|
+
config.description ||
|
|
186
|
+
"No description available",
|
|
187
|
+
author: config.author || "Unknown",
|
|
170
188
|
path: path.join(expansionPacksPath, entry.name),
|
|
171
189
|
});
|
|
172
190
|
} catch {
|
|
@@ -196,12 +214,16 @@ class ResourceLocator {
|
|
|
196
214
|
return this._pathCache.get(cacheKey);
|
|
197
215
|
}
|
|
198
216
|
|
|
199
|
-
const teamPath = path.join(
|
|
217
|
+
const teamPath = path.join(
|
|
218
|
+
this.getBmadCorePath(),
|
|
219
|
+
"agent-teams",
|
|
220
|
+
`${teamId}.yaml`,
|
|
221
|
+
);
|
|
200
222
|
|
|
201
223
|
if (await fs.pathExists(teamPath)) {
|
|
202
224
|
try {
|
|
203
|
-
const yaml = require(
|
|
204
|
-
const content = await fs.readFile(teamPath,
|
|
225
|
+
const yaml = require("js-yaml");
|
|
226
|
+
const content = await fs.readFile(teamPath, "utf8");
|
|
205
227
|
const config = yaml.load(content);
|
|
206
228
|
this._pathCache.set(cacheKey, config);
|
|
207
229
|
return config;
|
|
@@ -230,8 +252,8 @@ class ResourceLocator {
|
|
|
230
252
|
return { all: [], byType: {} };
|
|
231
253
|
}
|
|
232
254
|
|
|
233
|
-
const content = await fs.readFile(agentPath,
|
|
234
|
-
const { extractYamlFromAgent } = require(
|
|
255
|
+
const content = await fs.readFile(agentPath, "utf8");
|
|
256
|
+
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
|
235
257
|
const yamlContent = extractYamlFromAgent(content);
|
|
236
258
|
|
|
237
259
|
if (!yamlContent) {
|
|
@@ -239,7 +261,7 @@ class ResourceLocator {
|
|
|
239
261
|
}
|
|
240
262
|
|
|
241
263
|
try {
|
|
242
|
-
const yaml = require(
|
|
264
|
+
const yaml = require("js-yaml");
|
|
243
265
|
const metadata = yaml.load(yamlContent);
|
|
244
266
|
const dependencies = metadata.dependencies || {};
|
|
245
267
|
|
|
@@ -284,12 +306,16 @@ class ResourceLocator {
|
|
|
284
306
|
return this._pathCache.get(cacheKey);
|
|
285
307
|
}
|
|
286
308
|
|
|
287
|
-
const idePath = path.join(
|
|
309
|
+
const idePath = path.join(
|
|
310
|
+
this.getBmadCorePath(),
|
|
311
|
+
"ide-rules",
|
|
312
|
+
`${ideId}.yaml`,
|
|
313
|
+
);
|
|
288
314
|
|
|
289
315
|
if (await fs.pathExists(idePath)) {
|
|
290
316
|
try {
|
|
291
|
-
const yaml = require(
|
|
292
|
-
const content = await fs.readFile(idePath,
|
|
317
|
+
const yaml = require("js-yaml");
|
|
318
|
+
const content = await fs.readFile(idePath, "utf8");
|
|
293
319
|
const config = yaml.load(content);
|
|
294
320
|
this._pathCache.set(cacheKey, config);
|
|
295
321
|
return config;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const yaml = require(
|
|
4
|
-
const { extractYamlFromAgent } = require(
|
|
1
|
+
const fs = require("node:fs").promises;
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const yaml = require("js-yaml");
|
|
4
|
+
const { extractYamlFromAgent } = require("./yaml-utils");
|
|
5
5
|
|
|
6
6
|
class DependencyResolver {
|
|
7
7
|
constructor(rootDir) {
|
|
8
8
|
this.rootDir = rootDir;
|
|
9
|
-
this.xiaomaCore = path.join(rootDir,
|
|
10
|
-
this.common = path.join(rootDir,
|
|
9
|
+
this.xiaomaCore = path.join(rootDir, "xiaoma-core");
|
|
10
|
+
this.common = path.join(rootDir, "common");
|
|
11
11
|
this.cache = new Map();
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
async resolveAgentDependencies(agentId) {
|
|
15
|
-
const agentPath = path.join(this.xiaomaCore,
|
|
16
|
-
const agentContent = await fs.readFile(agentPath,
|
|
15
|
+
const agentPath = path.join(this.xiaomaCore, "agents", `${agentId}.md`);
|
|
16
|
+
const agentContent = await fs.readFile(agentPath, "utf8");
|
|
17
17
|
|
|
18
18
|
// Extract YAML from markdown content with command cleaning
|
|
19
19
|
const yamlContent = extractYamlFromAgent(agentContent, true);
|
|
@@ -36,7 +36,7 @@ class DependencyResolver {
|
|
|
36
36
|
// Personas are now embedded in agent configs, no need to resolve separately
|
|
37
37
|
|
|
38
38
|
// Resolve other dependencies
|
|
39
|
-
const depTypes = [
|
|
39
|
+
const depTypes = ["tasks", "templates", "checklists", "data", "utils"];
|
|
40
40
|
for (const depType of depTypes) {
|
|
41
41
|
const deps = agentConfig.dependencies?.[depType] || [];
|
|
42
42
|
for (const depId of deps) {
|
|
@@ -49,8 +49,12 @@ class DependencyResolver {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async resolveTeamDependencies(teamId) {
|
|
52
|
-
const teamPath = path.join(
|
|
53
|
-
|
|
52
|
+
const teamPath = path.join(
|
|
53
|
+
this.xiaomaCore,
|
|
54
|
+
"agent-teams",
|
|
55
|
+
`${teamId}.yaml`,
|
|
56
|
+
);
|
|
57
|
+
const teamContent = await fs.readFile(teamPath, "utf8");
|
|
54
58
|
const teamConfig = yaml.load(teamContent);
|
|
55
59
|
|
|
56
60
|
const dependencies = {
|
|
@@ -65,7 +69,9 @@ class DependencyResolver {
|
|
|
65
69
|
};
|
|
66
70
|
|
|
67
71
|
// Always add xiaoma-orchestrator agent first if it's a team
|
|
68
|
-
const bmadAgent = await this.resolveAgentDependencies(
|
|
72
|
+
const bmadAgent = await this.resolveAgentDependencies(
|
|
73
|
+
"xiaoma-orchestrator",
|
|
74
|
+
);
|
|
69
75
|
dependencies.agents.push(bmadAgent.agent);
|
|
70
76
|
for (const res of bmadAgent.resources) {
|
|
71
77
|
dependencies.resources.set(res.path, res);
|
|
@@ -75,19 +81,20 @@ class DependencyResolver {
|
|
|
75
81
|
let agentsToResolve = teamConfig.agents || [];
|
|
76
82
|
|
|
77
83
|
// Handle wildcard "*" - include all agents except xiaoma-master
|
|
78
|
-
if (agentsToResolve.includes(
|
|
84
|
+
if (agentsToResolve.includes("*")) {
|
|
79
85
|
const allAgents = await this.listAgents();
|
|
80
86
|
// Remove wildcard and add all agents except those already in the list and xiaoma-master
|
|
81
|
-
agentsToResolve = agentsToResolve.filter((a) => a !==
|
|
87
|
+
agentsToResolve = agentsToResolve.filter((a) => a !== "*");
|
|
82
88
|
for (const agent of allAgents) {
|
|
83
|
-
if (!agentsToResolve.includes(agent) && agent !==
|
|
89
|
+
if (!agentsToResolve.includes(agent) && agent !== "xiaoma-master") {
|
|
84
90
|
agentsToResolve.push(agent);
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
for (const agentId of agentsToResolve) {
|
|
90
|
-
if (agentId ===
|
|
96
|
+
if (agentId === "xiaoma-orchestrator" || agentId === "xiaoma-master")
|
|
97
|
+
continue; // Already added or excluded
|
|
91
98
|
const agentDeps = await this.resolveAgentDependencies(agentId);
|
|
92
99
|
dependencies.agents.push(agentDeps.agent);
|
|
93
100
|
|
|
@@ -99,7 +106,7 @@ class DependencyResolver {
|
|
|
99
106
|
|
|
100
107
|
// Resolve workflows
|
|
101
108
|
for (const workflowId of teamConfig.workflows || []) {
|
|
102
|
-
const resource = await this.loadResource(
|
|
109
|
+
const resource = await this.loadResource("workflows", workflowId);
|
|
103
110
|
if (resource) dependencies.resources.set(resource.path, resource);
|
|
104
111
|
}
|
|
105
112
|
|
|
@@ -122,12 +129,12 @@ class DependencyResolver {
|
|
|
122
129
|
// First try xiaoma-core
|
|
123
130
|
try {
|
|
124
131
|
filePath = path.join(this.xiaomaCore, type, id);
|
|
125
|
-
content = await fs.readFile(filePath,
|
|
132
|
+
content = await fs.readFile(filePath, "utf8");
|
|
126
133
|
} catch {
|
|
127
134
|
// If not found in xiaoma-core, try common folder
|
|
128
135
|
try {
|
|
129
136
|
filePath = path.join(this.common, type, id);
|
|
130
|
-
content = await fs.readFile(filePath,
|
|
137
|
+
content = await fs.readFile(filePath, "utf8");
|
|
131
138
|
} catch {
|
|
132
139
|
// File not found in either location
|
|
133
140
|
}
|
|
@@ -155,8 +162,10 @@ class DependencyResolver {
|
|
|
155
162
|
|
|
156
163
|
async listAgents() {
|
|
157
164
|
try {
|
|
158
|
-
const files = await fs.readdir(path.join(this.xiaomaCore,
|
|
159
|
-
return files
|
|
165
|
+
const files = await fs.readdir(path.join(this.xiaomaCore, "agents"));
|
|
166
|
+
return files
|
|
167
|
+
.filter((f) => f.endsWith(".md"))
|
|
168
|
+
.map((f) => f.replace(".md", ""));
|
|
160
169
|
} catch {
|
|
161
170
|
return [];
|
|
162
171
|
}
|
|
@@ -164,8 +173,10 @@ class DependencyResolver {
|
|
|
164
173
|
|
|
165
174
|
async listTeams() {
|
|
166
175
|
try {
|
|
167
|
-
const files = await fs.readdir(path.join(this.xiaomaCore,
|
|
168
|
-
return files
|
|
176
|
+
const files = await fs.readdir(path.join(this.xiaomaCore, "agent-teams"));
|
|
177
|
+
return files
|
|
178
|
+
.filter((f) => f.endsWith(".yaml"))
|
|
179
|
+
.map((f) => f.replace(".yaml", ""));
|
|
169
180
|
} catch {
|
|
170
181
|
return [];
|
|
171
182
|
}
|
package/tools/lib/yaml-utils.js
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
function extractYamlFromAgent(agentContent, cleanCommands = false) {
|
|
12
12
|
// Remove carriage returns and match YAML block
|
|
13
|
-
const yamlMatch = agentContent
|
|
13
|
+
const yamlMatch = agentContent
|
|
14
|
+
.replaceAll("\r", "")
|
|
15
|
+
.match(/```ya?ml\n([\s\S]*?)\n```/);
|
|
14
16
|
if (!yamlMatch) return null;
|
|
15
17
|
|
|
16
18
|
let yamlContent = yamlMatch[1].trim();
|
|
@@ -18,7 +20,10 @@ function extractYamlFromAgent(agentContent, cleanCommands = false) {
|
|
|
18
20
|
// Clean up command descriptions if requested
|
|
19
21
|
// Converts "- command - description" to just "- command"
|
|
20
22
|
if (cleanCommands) {
|
|
21
|
-
yamlContent = yamlContent.replaceAll(
|
|
23
|
+
yamlContent = yamlContent.replaceAll(
|
|
24
|
+
/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm,
|
|
25
|
+
"$1$2",
|
|
26
|
+
);
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
return yamlContent;
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
const { execSync } = require(
|
|
2
|
-
const fs = require(
|
|
1
|
+
const { execSync } = require("node:child_process");
|
|
2
|
+
const fs = require("node:fs");
|
|
3
3
|
|
|
4
4
|
// Get the latest stable tag (exclude beta tags)
|
|
5
|
-
const allTags = execSync(
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const allTags = execSync("git tag -l | sort -V", { encoding: "utf8" })
|
|
6
|
+
.split("\n")
|
|
7
|
+
.filter(Boolean);
|
|
8
|
+
const stableTags = allTags.filter((tag) => !tag.includes("beta"));
|
|
9
|
+
const latestTag = stableTags.at(-1) || "v5.0.0";
|
|
8
10
|
|
|
9
11
|
// Get commits since last tag
|
|
10
|
-
const commits = execSync(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const commits = execSync(
|
|
13
|
+
`git log ${latestTag}..HEAD --pretty=format:"- %s" --reverse`,
|
|
14
|
+
{
|
|
15
|
+
encoding: "utf8",
|
|
16
|
+
},
|
|
17
|
+
)
|
|
18
|
+
.split("\n")
|
|
14
19
|
.filter(Boolean);
|
|
15
20
|
|
|
16
21
|
// Categorize commits
|
|
@@ -18,49 +23,52 @@ const features = commits.filter((commit) => /^- (feat|Feature)/.test(commit));
|
|
|
18
23
|
const fixes = commits.filter((commit) => /^- (fix|Fix)/.test(commit));
|
|
19
24
|
const chores = commits.filter((commit) => /^- (chore|Chore)/.test(commit));
|
|
20
25
|
const others = commits.filter(
|
|
21
|
-
(commit) =>
|
|
26
|
+
(commit) =>
|
|
27
|
+
!/^- (feat|Feature|fix|Fix|chore|Chore|release:|Release:)/.test(commit),
|
|
22
28
|
);
|
|
23
29
|
|
|
24
30
|
// Get next version (you can modify this logic)
|
|
25
|
-
const currentVersion = require(
|
|
26
|
-
const versionParts = currentVersion.split(
|
|
31
|
+
const currentVersion = require("../package.json").version;
|
|
32
|
+
const versionParts = currentVersion.split(".").map(Number);
|
|
27
33
|
const nextVersion = `${versionParts[0]}.${versionParts[1] + 1}.0`; // Default to minor bump
|
|
28
34
|
|
|
29
35
|
console.log(`## π What's New in v${nextVersion}\n`);
|
|
30
36
|
|
|
31
37
|
if (features.length > 0) {
|
|
32
|
-
console.log(
|
|
38
|
+
console.log("### β¨ New Features");
|
|
33
39
|
for (const feature of features) console.log(feature);
|
|
34
|
-
console.log(
|
|
40
|
+
console.log("");
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
if (fixes.length > 0) {
|
|
38
|
-
console.log(
|
|
44
|
+
console.log("### π Bug Fixes");
|
|
39
45
|
for (const fix of fixes) console.log(fix);
|
|
40
|
-
console.log(
|
|
46
|
+
console.log("");
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
if (others.length > 0) {
|
|
44
|
-
console.log(
|
|
50
|
+
console.log("### π¦ Other Changes");
|
|
45
51
|
for (const other of others) console.log(other);
|
|
46
|
-
console.log(
|
|
52
|
+
console.log("");
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
if (chores.length > 0) {
|
|
50
|
-
console.log(
|
|
56
|
+
console.log("### π§ Maintenance");
|
|
51
57
|
for (const chore of chores) console.log(chore);
|
|
52
|
-
console.log(
|
|
58
|
+
console.log("");
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
console.log(
|
|
56
|
-
console.log(
|
|
57
|
-
console.log(
|
|
58
|
-
console.log(
|
|
61
|
+
console.log("\n## π¦ Installation\n");
|
|
62
|
+
console.log("```bash");
|
|
63
|
+
console.log("npx xiaoma-cli install");
|
|
64
|
+
console.log("```");
|
|
59
65
|
|
|
60
66
|
console.log(
|
|
61
67
|
`\n**Full Changelog**: https://github.com/zqyl-xiaoma/xiaoma-cli-release/compare/${latestTag}...v${nextVersion}`,
|
|
62
68
|
);
|
|
63
69
|
|
|
64
|
-
console.log(
|
|
70
|
+
console.log(
|
|
71
|
+
`\n---\nπ **Summary**: ${commits.length} commits since ${latestTag}`,
|
|
72
|
+
);
|
|
65
73
|
console.log(`π·οΈ **Previous tag**: ${latestTag}`);
|
|
66
74
|
console.log(`π **Next version**: v${nextVersion} (estimated)`);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// ASCII banner art definitions extracted from banners.js to separate art from logic
|
|
2
2
|
|
|
3
|
-
const XIAOMA_TITLE =
|
|
4
|
-
const FLATTENER_TITLE =
|
|
5
|
-
const INSTALLER_TITLE =
|
|
3
|
+
const XIAOMA_TITLE = "XIAOMA-CLIβ’";
|
|
4
|
+
const FLATTENER_TITLE = "FLATTENER";
|
|
5
|
+
const INSTALLER_TITLE = "INSTALLER";
|
|
6
6
|
|
|
7
7
|
// Large ASCII blocks (block-style fonts)
|
|
8
8
|
const XIAOMA_LARGE = `
|
|
@@ -3,23 +3,32 @@
|
|
|
3
3
|
* Used by semantic-release to keep versions in sync
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require(
|
|
7
|
-
const path = require(
|
|
6
|
+
const fs = require("node:fs");
|
|
7
|
+
const path = require("node:path");
|
|
8
8
|
|
|
9
9
|
function syncInstallerVersion() {
|
|
10
10
|
// Read main package.json
|
|
11
|
-
const mainPackagePath = path.join(__dirname,
|
|
12
|
-
const mainPackage = JSON.parse(fs.readFileSync(mainPackagePath,
|
|
11
|
+
const mainPackagePath = path.join(__dirname, "..", "package.json");
|
|
12
|
+
const mainPackage = JSON.parse(fs.readFileSync(mainPackagePath, "utf8"));
|
|
13
13
|
|
|
14
14
|
// Read installer package.json
|
|
15
|
-
const installerPackagePath = path.join(
|
|
16
|
-
|
|
15
|
+
const installerPackagePath = path.join(
|
|
16
|
+
__dirname,
|
|
17
|
+
"installer",
|
|
18
|
+
"package.json",
|
|
19
|
+
);
|
|
20
|
+
const installerPackage = JSON.parse(
|
|
21
|
+
fs.readFileSync(installerPackagePath, "utf8"),
|
|
22
|
+
);
|
|
17
23
|
|
|
18
24
|
// Update installer version to match main version
|
|
19
25
|
installerPackage.version = mainPackage.version;
|
|
20
26
|
|
|
21
27
|
// Write back installer package.json
|
|
22
|
-
fs.writeFileSync(
|
|
28
|
+
fs.writeFileSync(
|
|
29
|
+
installerPackagePath,
|
|
30
|
+
JSON.stringify(installerPackage, null, 2) + "\n",
|
|
31
|
+
);
|
|
23
32
|
|
|
24
33
|
console.log(`Synced installer version to ${mainPackage.version}`);
|
|
25
34
|
}
|