@zeyue0329/xiaoma-cli 1.0.39 → 1.0.41

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 (27) hide show
  1. package/.idea/workspace.xml +1 -0
  2. package/.xiaoma-core/.coordinator-state.json +19 -0
  3. package/dist/agents/architect.txt +192 -0
  4. package/dist/agents/workflow-helper.txt +93 -0
  5. package/dist/teams/team-all.txt +245 -190
  6. package/dist/teams/team-fullstack-with-database.txt +2 -0
  7. package/dist/teams/team-fullstack.txt +2 -0
  8. package/dist/teams/team-no-ui.txt +2 -0
  9. package/docs/architecture/workflow-coordinator-implementation.md +1188 -0
  10. package/docs/prd/workflow-coordinator-prd.md +1214 -0
  11. package/package.json +1 -1
  12. package/tools/installer/package.json +1 -1
  13. package/tools/workflow-coordinator/README.md +38 -0
  14. package/tools/workflow-coordinator/USAGE.md +548 -0
  15. package/tools/workflow-coordinator/package-lock.json +4868 -0
  16. package/tools/workflow-coordinator/package.json +35 -0
  17. package/tools/workflow-coordinator/src/api/server.js +207 -0
  18. package/tools/workflow-coordinator/src/controller/workflow-controller.js +263 -0
  19. package/tools/workflow-coordinator/src/index.js +113 -0
  20. package/tools/workflow-coordinator/src/parser/workflow-parser.js +144 -0
  21. package/tools/workflow-coordinator/src/utils/state-manager.js +59 -0
  22. package/tools/workflow-coordinator/src/utils/validator.js +86 -0
  23. package/tools/workflow-coordinator/test/integration-test.js +266 -0
  24. package/tools/workflow-coordinator/test/quick-test.js +127 -0
  25. package/xiaoma-core/agents/architect.md +2 -0
  26. package/xiaoma-core/agents/workflow-helper.md +481 -0
  27. package/xiaoma-core/workflows/automated-requirements-analysis.yaml +11 -8
@@ -0,0 +1,1188 @@
1
+ # 工作流协调器 - 完整实现指南
2
+
3
+ > **版本**: 2.0.0
4
+ > **日期**: 2025-11-13
5
+ > **相关文档**: [PRD文档](../prd/workflow-coordinator-prd.md)
6
+
7
+ ---
8
+
9
+ ## 目录
10
+
11
+ 1. [快速开始](#1-快速开始)
12
+ 2. [协调器端实现](#2-协调器端实现)
13
+ 3. [Claude Code端实现](#3-claude-code端实现)
14
+ 4. [完整示例](#4-完整示例)
15
+ 5. [测试和调试](#5-测试和调试)
16
+
17
+ ---
18
+
19
+ ## 1. 快速开始
20
+
21
+ ### 1.1 项目初始化
22
+
23
+ ```bash
24
+ # 1. 创建协调器项目
25
+ cd tools/
26
+ mkdir workflow-coordinator
27
+ cd workflow-coordinator
28
+
29
+ # 2. 初始化npm项目
30
+ npm init -y
31
+
32
+ # 3. 安装依赖
33
+ npm install express js-yaml fs-extra chalk cors dotenv
34
+
35
+ # 4. 安装开发依赖
36
+ npm install --save-dev nodemon jest
37
+
38
+ # 5. 创建目录结构
39
+ mkdir -p src/{api,parser,controller,utils}
40
+ mkdir -p test
41
+ ```
42
+
43
+ ### 1.2 项目结构
44
+
45
+ ```
46
+ tools/workflow-coordinator/
47
+ ├── src/
48
+ │ ├── index.js # 主入口
49
+ │ ├── api/
50
+ │ │ └── server.js # HTTP服务器
51
+ │ ├── parser/
52
+ │ │ └── workflow-parser.js # 工作流解析器
53
+ │ ├── controller/
54
+ │ │ └── workflow-controller.js # 工作流控制器
55
+ │ └── utils/
56
+ │ ├── state-manager.js # 状态管理
57
+ │ └── validator.js # 验证器
58
+ ├── test/
59
+ ├── package.json
60
+ └── README.md
61
+
62
+ xiaoma-core/agents/
63
+ └── workflow-helper.md # 新增智能体
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 2. 协调器端实现
69
+
70
+ ### 2.1 主入口 (src/index.js)
71
+
72
+ ```javascript
73
+ #!/usr/bin/env node
74
+
75
+ const path = require('path');
76
+ const chalk = require('chalk');
77
+ const WorkflowParser = require('./parser/workflow-parser');
78
+ const WorkflowController = require('./controller/workflow-controller');
79
+ const CoordinatorServer = require('./api/server');
80
+
81
+ async function main() {
82
+ const args = process.argv.slice(2);
83
+ const command = args[0];
84
+ const workflowName = args[1];
85
+
86
+ if (command === 'start' && workflowName) {
87
+ console.log(chalk.blue(`\n🚀 启动工作流协调器\n`));
88
+
89
+ try {
90
+ // 1. 解析工作流
91
+ console.log(chalk.cyan(`📋 解析工作流: ${workflowName}`));
92
+ const parser = new WorkflowParser();
93
+ const executionPlan = await parser.parse(workflowName);
94
+
95
+ console.log(chalk.green(`✅ 工作流解析完成: ${executionPlan.metadata.name}`));
96
+ console.log(chalk.gray(` 步骤数: ${executionPlan.steps.length}`));
97
+
98
+ // 2. 创建控制器
99
+ const controller = new WorkflowController(executionPlan);
100
+
101
+ // 3. 启动HTTP服务
102
+ console.log(chalk.cyan(`\n🌐 启动HTTP服务...`));
103
+ const server = new CoordinatorServer(controller);
104
+ const port = process.env.COORDINATOR_PORT || 3001;
105
+
106
+ await server.start(port);
107
+
108
+ console.log(chalk.green(`✅ HTTP服务已启动: http://localhost:${port}`));
109
+ console.log(chalk.yellow(`\n⏳ 等待Claude Code连接...\n`));
110
+ console.log(chalk.gray(` 提示: 在Claude Code中执行以下命令启动工作流:`));
111
+ console.log(chalk.gray(` /workflow-helper`));
112
+ console.log(chalk.gray(` *start-workflow ${workflowName}\n`));
113
+
114
+ } catch (error) {
115
+ console.error(chalk.red(`\n❌ 启动失败: ${error.message}\n`));
116
+ console.error(error.stack);
117
+ process.exit(1);
118
+ }
119
+
120
+ } else {
121
+ // 显示帮助
122
+ console.log(chalk.blue(`\n工作流协调器\n`));
123
+ console.log(`用法:`);
124
+ console.log(` xiaoma-coordinator start <workflow-name> 启动工作流协调器`);
125
+ console.log(``);
126
+ console.log(`示例:`);
127
+ console.log(` xiaoma-coordinator start requirements-analysis`);
128
+ console.log(``);
129
+ }
130
+ }
131
+
132
+ main();
133
+ ```
134
+
135
+ ---
136
+
137
+ ### 2.2 HTTP服务器 (src/api/server.js)
138
+
139
+ ```javascript
140
+ const express = require('express');
141
+ const cors = require('cors');
142
+ const chalk = require('chalk');
143
+
144
+ class CoordinatorServer {
145
+ constructor(controller) {
146
+ this.app = express();
147
+ this.controller = controller;
148
+ this.setupMiddleware();
149
+ this.setupRoutes();
150
+ }
151
+
152
+ setupMiddleware() {
153
+ this.app.use(express.json({ limit: '50mb' }));
154
+ this.app.use(cors());
155
+
156
+ // 请求日志
157
+ this.app.use((req, res, next) => {
158
+ console.log(chalk.gray(`[${new Date().toISOString()}] ${req.method} ${req.path}`));
159
+ next();
160
+ });
161
+ }
162
+
163
+ setupRoutes() {
164
+ // API: 启动工作流
165
+ this.app.post('/workflow/start', async (req, res) => {
166
+ try {
167
+ const { workflowId, context } = req.body;
168
+
169
+ console.log(chalk.cyan(`\n📥 收到启动请求: ${workflowId}`));
170
+
171
+ const result = await this.controller.startWorkflow(workflowId, context);
172
+
173
+ console.log(chalk.green(`✅ 返回第一步指令: ${result.firstStep.stepId}`));
174
+
175
+ res.json(result);
176
+ } catch (error) {
177
+ console.error(chalk.red(`❌ 启动失败: ${error.message}`));
178
+ res.status(500).json({
179
+ success: false,
180
+ error: error.message
181
+ });
182
+ }
183
+ });
184
+
185
+ // API: 步骤完成回调
186
+ this.app.post('/workflow/step-complete', async (req, res) => {
187
+ try {
188
+ const { workflowId, stepId, status, outputs, duration } = req.body;
189
+
190
+ console.log(chalk.cyan(`\n📥 步骤完成: ${stepId}`));
191
+ console.log(chalk.gray(` 耗时: ${Math.round(duration / 1000)}秒`));
192
+ console.log(chalk.gray(` 输出: ${outputs.length}个文件`));
193
+
194
+ const result = await this.controller.onStepComplete({
195
+ workflowId,
196
+ stepId,
197
+ status,
198
+ outputs,
199
+ duration
200
+ });
201
+
202
+ if (result.hasNextStep) {
203
+ console.log(chalk.green(`✅ 返回下一步指令: ${result.nextStep.stepId}`));
204
+ console.log(chalk.yellow(` 进度: ${result.progress.percentComplete}% (${result.progress.currentStepIndex}/${result.progress.totalSteps})`));
205
+ } else {
206
+ console.log(chalk.green.bold(`\n🎉 工作流执行完成!\n`));
207
+ }
208
+
209
+ res.json(result);
210
+ } catch (error) {
211
+ console.error(chalk.red(`❌ 处理失败: ${error.message}`));
212
+ res.status(500).json({
213
+ success: false,
214
+ error: error.message
215
+ });
216
+ }
217
+ });
218
+
219
+ // API: 步骤失败回调
220
+ this.app.post('/workflow/step-failed', async (req, res) => {
221
+ try {
222
+ const { workflowId, stepId, error, errorDetails } = req.body;
223
+
224
+ console.log(chalk.red(`\n❌ 步骤失败: ${stepId}`));
225
+ console.log(chalk.red(` 错误: ${error}`));
226
+
227
+ const result = await this.controller.onStepFailed({
228
+ workflowId,
229
+ stepId,
230
+ error,
231
+ errorDetails
232
+ });
233
+
234
+ res.json(result);
235
+ } catch (error) {
236
+ console.error(chalk.red(`❌ 处理失败: ${error.message}`));
237
+ res.status(500).json({
238
+ success: false,
239
+ error: error.message
240
+ });
241
+ }
242
+ });
243
+
244
+ // API: 查询状态
245
+ this.app.get('/workflow/status', (req, res) => {
246
+ const status = this.controller.getStatus();
247
+ res.json(status);
248
+ });
249
+
250
+ // API: 中止工作流
251
+ this.app.post('/workflow/abort', async (req, res) => {
252
+ try {
253
+ const { workflowId, reason } = req.body;
254
+
255
+ console.log(chalk.yellow(`\n⏸️ 中止工作流: ${reason}`));
256
+
257
+ await this.controller.abort(workflowId, reason);
258
+
259
+ res.json({
260
+ success: true,
261
+ message: '工作流已中止'
262
+ });
263
+ } catch (error) {
264
+ res.status(500).json({
265
+ success: false,
266
+ error: error.message
267
+ });
268
+ }
269
+ });
270
+
271
+ // 健康检查
272
+ this.app.get('/health', (req, res) => {
273
+ res.json({ status: 'ok' });
274
+ });
275
+ }
276
+
277
+ async start(port) {
278
+ return new Promise((resolve) => {
279
+ this.server = this.app.listen(port, () => {
280
+ resolve();
281
+ });
282
+ });
283
+ }
284
+
285
+ async stop() {
286
+ if (this.server) {
287
+ await this.server.close();
288
+ }
289
+ }
290
+ }
291
+
292
+ module.exports = CoordinatorServer;
293
+ ```
294
+
295
+ ---
296
+
297
+ ### 2.3 工作流控制器 (src/controller/workflow-controller.js)
298
+
299
+ ```javascript
300
+ const fs = require('fs-extra');
301
+ const path = require('path');
302
+ const StateManager = require('../utils/state-manager');
303
+ const Validator = require('../utils/validator');
304
+
305
+ class WorkflowController {
306
+ constructor(executionPlan) {
307
+ this.executionPlan = executionPlan;
308
+ this.stateManager = new StateManager();
309
+ this.validator = new Validator();
310
+ this.state = null;
311
+ }
312
+
313
+ /**
314
+ * 启动工作流
315
+ */
316
+ async startWorkflow(workflowId, context = {}) {
317
+ // 初始化状态
318
+ this.state = {
319
+ workflowId: workflowId,
320
+ workflowName: this.executionPlan.metadata.name,
321
+ status: 'in_progress',
322
+ startTime: new Date().toISOString(),
323
+ currentStepIndex: 0,
324
+ completedSteps: [],
325
+ context: context,
326
+ errors: [],
327
+ retries: {}
328
+ };
329
+
330
+ // 保存状态
331
+ await this.stateManager.save(this.state);
332
+
333
+ // 获取第一步
334
+ const firstStepDef = this.executionPlan.steps[0];
335
+ const firstStep = this.buildStepInstruction(firstStepDef);
336
+
337
+ return {
338
+ success: true,
339
+ workflowId: workflowId,
340
+ workflowName: this.executionPlan.metadata.name,
341
+ totalSteps: this.executionPlan.steps.length,
342
+ firstStep: firstStep
343
+ };
344
+ }
345
+
346
+ /**
347
+ * 步骤完成回调
348
+ */
349
+ async onStepComplete({ workflowId, stepId, status, outputs, duration }) {
350
+ // 1. 验证步骤输出
351
+ const stepDef = this.executionPlan.steps[this.state.currentStepIndex];
352
+ const validationResult = await this.validator.validateOutputs(stepDef, outputs);
353
+
354
+ if (!validationResult.passed) {
355
+ return {
356
+ success: false,
357
+ action: 'fix_quality',
358
+ issues: validationResult.issues,
359
+ message: '步骤输出质量验证失败,请修复问题后重试'
360
+ };
361
+ }
362
+
363
+ // 2. 记录完成步骤
364
+ this.state.completedSteps.push({
365
+ stepId: stepId,
366
+ agent: stepDef.agent,
367
+ status: status,
368
+ outputs: outputs,
369
+ duration: duration,
370
+ completedAt: new Date().toISOString()
371
+ });
372
+
373
+ // 3. 移动到下一步
374
+ this.state.currentStepIndex++;
375
+
376
+ // 4. 保存状态
377
+ await this.stateManager.save(this.state);
378
+
379
+ // 5. 检查是否还有下一步
380
+ if (this.state.currentStepIndex >= this.executionPlan.steps.length) {
381
+ // 工作流完成
382
+ this.state.status = 'completed';
383
+ this.state.endTime = new Date().toISOString();
384
+ await this.stateManager.save(this.state);
385
+
386
+ return {
387
+ success: true,
388
+ hasNextStep: false,
389
+ message: '🎉 工作流执行完成!',
390
+ summary: this.generateSummary()
391
+ };
392
+ }
393
+
394
+ // 6. 获取下一步指令
395
+ const nextStepDef = this.executionPlan.steps[this.state.currentStepIndex];
396
+ const nextStep = this.buildStepInstruction(nextStepDef);
397
+
398
+ return {
399
+ success: true,
400
+ hasNextStep: true,
401
+ nextStep: nextStep,
402
+ progress: {
403
+ currentStepIndex: this.state.currentStepIndex + 1,
404
+ totalSteps: this.executionPlan.steps.length,
405
+ percentComplete: Math.round(((this.state.currentStepIndex + 1) / this.executionPlan.steps.length) * 100)
406
+ }
407
+ };
408
+ }
409
+
410
+ /**
411
+ * 步骤失败回调
412
+ */
413
+ async onStepFailed({ workflowId, stepId, error, errorDetails }) {
414
+ const stepDef = this.executionPlan.steps[this.state.currentStepIndex];
415
+
416
+ // 记录错误
417
+ this.state.errors.push({
418
+ stepId: stepId,
419
+ error: error,
420
+ errorDetails: errorDetails,
421
+ timestamp: new Date().toISOString()
422
+ });
423
+
424
+ // 检查是否可以重试
425
+ const maxRetries = stepDef.onFailure?.max_retries || 3;
426
+ const currentRetries = this.state.retries[stepId] || 0;
427
+
428
+ if (currentRetries < maxRetries) {
429
+ // 可以重试
430
+ this.state.retries[stepId] = currentRetries + 1;
431
+ await this.stateManager.save(this.state);
432
+
433
+ const retryStep = this.buildStepInstruction(stepDef);
434
+
435
+ return {
436
+ success: true,
437
+ action: 'retry',
438
+ retryCount: currentRetries + 1,
439
+ maxRetries: maxRetries,
440
+ retryStep: retryStep,
441
+ message: `将进行第 ${currentRetries + 1} 次重试`
442
+ };
443
+ } else {
444
+ // 达到最大重试次数,中止工作流
445
+ this.state.status = 'failed';
446
+ this.state.endTime = new Date().toISOString();
447
+ await this.stateManager.save(this.state);
448
+
449
+ return {
450
+ success: false,
451
+ action: 'abort',
452
+ message: `步骤 "${stepId}" 执行失败,已达最大重试次数`,
453
+ escalation: stepDef.onFailure?.escalation || '需要人工介入'
454
+ };
455
+ }
456
+ }
457
+
458
+ /**
459
+ * 构建步骤执行指令
460
+ */
461
+ buildStepInstruction(stepDef) {
462
+ // 从 detailed_steps 中提取命令和提示词
463
+ const detailedSteps = stepDef.detailedSteps || [];
464
+
465
+ // 找到第一个命令步骤(非智能体切换)
466
+ const commandStep = detailedSteps.find(ds =>
467
+ ds.command && ds.command.startsWith('*')
468
+ );
469
+
470
+ // 找到智能体切换步骤
471
+ const agentSwitchStep = detailedSteps.find(ds =>
472
+ ds.command && ds.command.startsWith('/')
473
+ );
474
+
475
+ return {
476
+ stepId: stepDef.id,
477
+ stepDescription: stepDef.description,
478
+ agent: stepDef.agent,
479
+ switchCommand: agentSwitchStep?.command || `/agent ${stepDef.agent}`,
480
+ executeCommand: commandStep?.command || '',
481
+ prompt: commandStep?.prompt_template || '',
482
+ inputFiles: stepDef.requires || [],
483
+ expectedOutputs: stepDef.outputs || [],
484
+ detailedSteps: detailedSteps,
485
+ estimatedDuration: stepDef.duration
486
+ };
487
+ }
488
+
489
+ /**
490
+ * 生成完成摘要
491
+ */
492
+ generateSummary() {
493
+ const totalDuration = this.state.completedSteps.reduce((sum, step) => sum + step.duration, 0);
494
+ const allOutputs = this.state.completedSteps.flatMap(step => step.outputs);
495
+
496
+ return {
497
+ workflowId: this.state.workflowId,
498
+ workflowName: this.state.workflowName,
499
+ status: this.state.status,
500
+ startTime: this.state.startTime,
501
+ endTime: this.state.endTime,
502
+ totalDuration: totalDuration,
503
+ totalSteps: this.state.completedSteps.length,
504
+ outputs: allOutputs.map(o => o.file),
505
+ errors: this.state.errors.length
506
+ };
507
+ }
508
+
509
+ /**
510
+ * 获取当前状态
511
+ */
512
+ getStatus() {
513
+ return {
514
+ workflowId: this.state?.workflowId,
515
+ status: this.state?.status || 'not_started',
516
+ currentStepIndex: this.state?.currentStepIndex,
517
+ totalSteps: this.executionPlan.steps.length,
518
+ completedSteps: this.state?.completedSteps.map(s => s.stepId) || [],
519
+ errors: this.state?.errors.length || 0
520
+ };
521
+ }
522
+
523
+ /**
524
+ * 中止工作流
525
+ */
526
+ async abort(workflowId, reason) {
527
+ if (this.state) {
528
+ this.state.status = 'aborted';
529
+ this.state.abortReason = reason;
530
+ this.state.endTime = new Date().toISOString();
531
+ await this.stateManager.save(this.state);
532
+ }
533
+ }
534
+ }
535
+
536
+ module.exports = WorkflowController;
537
+ ```
538
+
539
+ ---
540
+
541
+ ### 2.4 工作流解析器 (src/parser/workflow-parser.js)
542
+
543
+ ```javascript
544
+ const fs = require('fs-extra');
545
+ const yaml = require('js-yaml');
546
+ const path = require('path');
547
+
548
+ class WorkflowParser {
549
+ constructor() {
550
+ this.workflowsDir = path.join(process.cwd(), '../../xiaoma-core/workflows');
551
+ }
552
+
553
+ async parse(workflowName) {
554
+ // 1. 查找工作流文件
555
+ const workflowFile = this.findWorkflowFile(workflowName);
556
+
557
+ if (!workflowFile) {
558
+ throw new Error(`工作流文件未找到: ${workflowName}`);
559
+ }
560
+
561
+ // 2. 读取并解析YAML
562
+ const yamlContent = await fs.readFile(workflowFile, 'utf-8');
563
+ const workflowDef = yaml.load(yamlContent);
564
+
565
+ // 3. 验证工作流定义
566
+ this.validate(workflowDef);
567
+
568
+ // 4. 构建执行计划
569
+ const executionPlan = {
570
+ metadata: {
571
+ id: workflowDef.workflow.id,
572
+ name: workflowDef.workflow.name,
573
+ description: workflowDef.workflow.description,
574
+ type: workflowDef.workflow.type
575
+ },
576
+ steps: workflowDef.workflow.sequence.map(step => this.parseStep(step)),
577
+ qualityGates: workflowDef.workflow.quality_gates || {},
578
+ errorHandling: workflowDef.workflow.error_handling || {}
579
+ };
580
+
581
+ return executionPlan;
582
+ }
583
+
584
+ parseStep(stepYaml) {
585
+ return {
586
+ id: stepYaml.step,
587
+ description: stepYaml.action || stepYaml.step,
588
+ agent: stepYaml.agent,
589
+ duration: stepYaml.duration,
590
+ requires: stepYaml.requires || [],
591
+ detailedSteps: stepYaml.detailed_steps || [],
592
+ validationCriteria: stepYaml.validation_criteria || [],
593
+ outputs: this.extractOutputs(stepYaml),
594
+ onFailure: stepYaml.on_failure
595
+ };
596
+ }
597
+
598
+ extractOutputs(stepYaml) {
599
+ const outputs = [];
600
+
601
+ // 从validation_criteria提取
602
+ if (stepYaml.validation_criteria) {
603
+ stepYaml.validation_criteria.forEach(criterion => {
604
+ if (typeof criterion === 'string' && criterion.includes('file_created:')) {
605
+ const filePath = criterion.split('file_created:')[1].trim().replace(/["']/g, '');
606
+ outputs.push({ file: filePath });
607
+ }
608
+ });
609
+ }
610
+
611
+ // 从detailed_steps提取
612
+ if (stepYaml.detailed_steps) {
613
+ stepYaml.detailed_steps.forEach(detailStep => {
614
+ if (detailStep.output && detailStep.output.file) {
615
+ outputs.push({ file: detailStep.output.file });
616
+ }
617
+ });
618
+ }
619
+
620
+ return outputs;
621
+ }
622
+
623
+ findWorkflowFile(workflowName) {
624
+ const possibleNames = [
625
+ `${workflowName}.yaml`,
626
+ `${workflowName}.yml`,
627
+ `automated-${workflowName}.yaml`,
628
+ `automated-${workflowName}.yml`
629
+ ];
630
+
631
+ for (const name of possibleNames) {
632
+ const filePath = path.join(this.workflowsDir, name);
633
+ if (fs.existsSync(filePath)) {
634
+ return filePath;
635
+ }
636
+ }
637
+
638
+ return null;
639
+ }
640
+
641
+ validate(workflowDef) {
642
+ if (!workflowDef.workflow) {
643
+ throw new Error('无效的工作流定义: 缺少 workflow 字段');
644
+ }
645
+
646
+ if (!workflowDef.workflow.sequence || !Array.isArray(workflowDef.workflow.sequence)) {
647
+ throw new Error('无效的工作流定义: 缺少 sequence 字段');
648
+ }
649
+
650
+ if (workflowDef.workflow.sequence.length === 0) {
651
+ throw new Error('无效的工作流定义: sequence 为空');
652
+ }
653
+ }
654
+ }
655
+
656
+ module.exports = WorkflowParser;
657
+ ```
658
+
659
+ ---
660
+
661
+ ### 2.5 状态管理器 (src/utils/state-manager.js)
662
+
663
+ ```javascript
664
+ const fs = require('fs-extra');
665
+ const path = require('path');
666
+
667
+ class StateManager {
668
+ constructor() {
669
+ this.stateDir = path.join(process.cwd(), '../../.xiaoma-core');
670
+ this.stateFile = path.join(this.stateDir, '.coordinator-state.json');
671
+ }
672
+
673
+ async save(state) {
674
+ await fs.ensureDir(this.stateDir);
675
+ await fs.writeFile(this.stateFile, JSON.stringify(state, null, 2), 'utf-8');
676
+ }
677
+
678
+ async load() {
679
+ if (!fs.existsSync(this.stateFile)) {
680
+ return null;
681
+ }
682
+
683
+ const content = await fs.readFile(this.stateFile, 'utf-8');
684
+ return JSON.parse(content);
685
+ }
686
+
687
+ async clear() {
688
+ if (fs.existsSync(this.stateFile)) {
689
+ await fs.remove(this.stateFile);
690
+ }
691
+ }
692
+ }
693
+
694
+ module.exports = StateManager;
695
+ ```
696
+
697
+ ---
698
+
699
+ ### 2.6 验证器 (src/utils/validator.js)
700
+
701
+ ```javascript
702
+ const fs = require('fs-extra');
703
+
704
+ class Validator {
705
+ async validateOutputs(stepDef, actualOutputs) {
706
+ const issues = [];
707
+
708
+ // 验证所有预期输出文件
709
+ for (const expectedOutput of stepDef.outputs || []) {
710
+ const filePath = expectedOutput.file;
711
+ const actualOutput = actualOutputs.find(o => o.file === filePath);
712
+
713
+ if (!actualOutput) {
714
+ issues.push({
715
+ level: 'error',
716
+ message: `输出文件未报告: ${filePath}`
717
+ });
718
+ continue;
719
+ }
720
+
721
+ if (!actualOutput.exists) {
722
+ issues.push({
723
+ level: 'error',
724
+ message: `输出文件不存在: ${filePath}`
725
+ });
726
+ continue;
727
+ }
728
+
729
+ if (actualOutput.size === 0) {
730
+ issues.push({
731
+ level: 'warning',
732
+ message: `输出文件为空: ${filePath}`
733
+ });
734
+ }
735
+ }
736
+
737
+ return {
738
+ passed: issues.filter(i => i.level === 'error').length === 0,
739
+ issues: issues
740
+ };
741
+ }
742
+ }
743
+
744
+ module.exports = Validator;
745
+ ```
746
+
747
+ ---
748
+
749
+ ## 3. Claude Code端实现
750
+
751
+ ### 3.1 workflow-helper智能体定义
752
+
753
+ **文件**: `xiaoma-core/agents/workflow-helper.md`
754
+
755
+ ```markdown
756
+ # Workflow Helper - 工作流助手 🤖
757
+
758
+ > **核心使命: 与工作流协调器通信,自动执行工作流步骤**
759
+
760
+ ---
761
+
762
+ 激活通知: 此文件包含您完整的智能体操作指南。
763
+
764
+ 关键提示: 请阅读此文件中的完整YAML块以理解您的操作参数,并严格遵循您的激活指令:
765
+
766
+ ## 完整的智能体定义
767
+
768
+ \`\`\`yaml
769
+ activation-instructions:
770
+ - 步骤1: 阅读整个文件
771
+ - 步骤2: 采用下面'agent'和'persona'部分中定义的角色
772
+ - 步骤3: 向用户打招呼,显示可用命令
773
+ - 步骤4: 等待用户执行命令
774
+
775
+ agent:
776
+ name: workflow-helper
777
+ id: workflow-helper
778
+ title: Workflow Helper
779
+ icon: 🤖
780
+ role: 工作流自动化助手,负责与工作流协调器通信
781
+ expertise: 工作流执行、智能体协调、HTTP通信
782
+
783
+ persona:
784
+ role: 工作流自动化助手
785
+ style: 自动化、高效、精确、无需确认
786
+ identity: 专注于执行工作流协调器下发的指令,自动完成所有步骤
787
+ focus: 与协调器通信、智能体切换、状态报告
788
+ core_principles:
789
+ - 严格按照协调器指令执行
790
+ - 自动切换智能体
791
+ - 自动报告步骤完成状态
792
+ - 绝不询问用户是否继续
793
+ - 完全自动化执行
794
+
795
+ commands:
796
+ - help: 显示可用命令
797
+ - start-workflow {workflow-name}: 启动工作流
798
+ - status: 查询当前工作流状态
799
+ - abort: 中止当前工作流
800
+
801
+ configuration:
802
+ coordinator_url: "http://localhost:3001"
803
+ \`\`\`
804
+
805
+ ---
806
+
807
+ ## 工作原理
808
+
809
+ 1. **用户启动**: 用户执行 `*start-workflow requirements-analysis`
810
+ 2. **调用协调器**: 通过HTTP API请求第一步指令
811
+ 3. **执行步骤**: 切换智能体,执行命令,生成文档
812
+ 4. **报告完成**: 调用协调器API报告步骤完成
813
+ 5. **获取下一步**: 协调器返回下一步指令
814
+ 6. **自动循环**: 重复步骤3-5直到工作流完成
815
+
816
+ ---
817
+
818
+ ## 命令说明
819
+
820
+ ### *start-workflow {workflow-name}
821
+
822
+ 启动指定的工作流
823
+
824
+ **示例**:
825
+ \`\`\`
826
+ *start-workflow requirements-analysis
827
+ \`\`\`
828
+
829
+ **执行流程**:
830
+ 1. 调用 POST http://localhost:3001/workflow/start
831
+ 2. 获取第一步指令
832
+ 3. 自动执行第一步
833
+ 4. 报告完成并获取下一步
834
+ 5. 循环执行直到完成
835
+
836
+ ---
837
+
838
+ ### *status
839
+
840
+ 查询当前工作流执行状态
841
+
842
+ **示例**:
843
+ \`\`\`
844
+ *status
845
+ \`\`\`
846
+
847
+ ---
848
+
849
+ ### *abort
850
+
851
+ 中止当前工作流
852
+
853
+ **示例**:
854
+ \`\`\`
855
+ *abort
856
+ \`\`\`
857
+
858
+ ---
859
+
860
+ ## 实现细节
861
+
862
+ ### 命令: *start-workflow
863
+
864
+ 当用户执行此命令时,你需要:
865
+
866
+ \`\`\`javascript
867
+ // 1. 调用协调器API启动工作流
868
+ const response = await fetch('http://localhost:3001/workflow/start', {
869
+ method: 'POST',
870
+ headers: { 'Content-Type': 'application/json' },
871
+ body: JSON.stringify({
872
+ workflowId: workflowName,
873
+ context: { projectRoot: process.cwd() }
874
+ })
875
+ });
876
+
877
+ const result = await response.json();
878
+
879
+ // 2. 获取第一步指令
880
+ const firstStep = result.firstStep;
881
+
882
+ // 3. 执行第一步
883
+ await executeStep(firstStep);
884
+ \`\`\`
885
+
886
+ ### 执行步骤逻辑
887
+
888
+ \`\`\`javascript
889
+ async function executeStep(stepInstruction) {
890
+ console.log(\`\\n执行步骤: \${stepInstruction.stepId}\`);
891
+ console.log(\`智能体: \${stepInstruction.agent}\`);
892
+
893
+ const startTime = Date.now();
894
+
895
+ // 1. 切换智能体(如果需要)
896
+ if (stepInstruction.switchCommand) {
897
+ console.log(\`切换到: \${stepInstruction.agent}\`);
898
+ // 这里需要实际的智能体切换
899
+ // 比如: /analyst, /architect, /pm等
900
+ }
901
+
902
+ // 2. 执行命令
903
+ console.log(\`执行命令: \${stepInstruction.executeCommand}\`);
904
+ console.log(\`\\n提示词:\\n\${stepInstruction.prompt}\\n\`);
905
+
906
+ // 3. 等待智能体执行完成并生成文档
907
+ // (这部分由实际的智能体执行,比如Analyst生成需求分析文档)
908
+
909
+ // 4. 收集输出文件信息
910
+ const outputs = stepInstruction.expectedOutputs.map(output => ({
911
+ file: output.file || output,
912
+ exists: fs.existsSync(output.file || output),
913
+ size: fs.existsSync(output.file || output) ? fs.statSync(output.file || output).size : 0
914
+ }));
915
+
916
+ // 5. 报告步骤完成
917
+ const completeResponse = await fetch('http://localhost:3001/workflow/step-complete', {
918
+ method: 'POST',
919
+ headers: { 'Content-Type': 'application/json' },
920
+ body: JSON.stringify({
921
+ workflowId: 'current',
922
+ stepId: stepInstruction.stepId,
923
+ status: 'success',
924
+ outputs: outputs,
925
+ duration: Date.now() - startTime
926
+ })
927
+ });
928
+
929
+ const nextStepResult = await completeResponse.json();
930
+
931
+ // 6. 检查是否有下一步
932
+ if (nextStepResult.hasNextStep) {
933
+ console.log(\`\\n进度: \${nextStepResult.progress.percentComplete}%\`);
934
+ console.log(\`→ 自动进入下一步骤...\\n\`);
935
+
936
+ // 7. 自动执行下一步(关键:不询问用户!)
937
+ await executeStep(nextStepResult.nextStep);
938
+ } else {
939
+ console.log(\`\\n🎉 工作流执行完成!\`);
940
+ console.log(nextStepResult.message);
941
+ }
942
+ }
943
+ \`\`\`
944
+
945
+ ---
946
+
947
+ ## 重要提示
948
+
949
+ 1. **完全自动化**: 步骤间绝不询问用户"是否继续"
950
+ 2. **自动切换智能体**: 根据协调器指令自动切换
951
+ 3. **自动报告状态**: 每个步骤完成后立即报告
952
+ 4. **错误处理**: 如果步骤失败,报告给协调器处理
953
+
954
+ ---
955
+
956
+ 祝你工作愉快! 🤖
957
+ ```
958
+
959
+ ---
960
+
961
+ ## 4. 完整示例
962
+
963
+ ### 4.1 启动协调器
964
+
965
+ **终端1: 启动协调器**
966
+
967
+ ```bash
968
+ cd tools/workflow-coordinator
969
+
970
+ # 安装依赖(首次)
971
+ npm install
972
+
973
+ # 启动协调器
974
+ node src/index.js start requirements-analysis
975
+
976
+ # 输出:
977
+ # 🚀 启动工作流协调器
978
+ #
979
+ # 📋 解析工作流: requirements-analysis
980
+ # ✅ 工作流解析完成: 自动化需求分析和架构设计流程
981
+ # 步骤数: 6
982
+ #
983
+ # 🌐 启动HTTP服务...
984
+ # ✅ HTTP服务已启动: http://localhost:3001
985
+ #
986
+ # ⏳ 等待Claude Code连接...
987
+ #
988
+ # 提示: 在Claude Code中执行以下命令启动工作流:
989
+ # /workflow-helper
990
+ # *start-workflow requirements-analysis
991
+ ```
992
+
993
+ ### 4.2 在Claude Code中执行
994
+
995
+ **终端2: Claude Code**
996
+
997
+ ```bash
998
+ # 1. 切换到workflow-helper智能体
999
+ /workflow-helper
1000
+
1001
+ # 2. 启动工作流
1002
+ *start-workflow requirements-analysis
1003
+ ```
1004
+
1005
+ **预期输出**:
1006
+
1007
+ ```
1008
+ 工作流助手已激活 🤖
1009
+
1010
+ 启动工作流: requirements-analysis
1011
+
1012
+ 📡 调用协调器API...
1013
+ ✅ 连接成功: 自动化需求分析和架构设计流程
1014
+ 总步骤数: 6
1015
+
1016
+ 执行步骤: requirements_analysis_and_elicitation
1017
+ 智能体: analyst
1018
+ 切换到: analyst
1019
+
1020
+ 提示词:
1021
+ 我需要对产品经理提供的需求文档进行深度分析和澄清。
1022
+
1023
+ (Analyst智能体执行需求分析,生成文档...)
1024
+
1025
+ ✅ 步骤完成: requirements_analysis_and_elicitation
1026
+ 输出: docs/requirements/requirements-analysis.md (25.6 KB)
1027
+
1028
+ 📡 报告步骤完成...
1029
+ ✅ 协调器响应成功
1030
+
1031
+ 进度: 16% (1/6)
1032
+ → 自动进入下一步骤...
1033
+
1034
+ 执行步骤: analyze_existing_architecture
1035
+ 智能体: architect
1036
+ 切换到: architect
1037
+
1038
+ 提示词:
1039
+ 请分析当前项目的后端架构。
1040
+
1041
+ (Architect智能体执行架构分析...)
1042
+
1043
+ ✅ 步骤完成: analyze_existing_architecture
1044
+ 输出: docs/architecture/current-architecture-analysis.md (18.4 KB)
1045
+
1046
+ 进度: 33% (2/6)
1047
+ → 自动进入下一步骤...
1048
+
1049
+ (继续执行剩余步骤...)
1050
+
1051
+ 🎉 工作流执行完成!
1052
+
1053
+ 总耗时: 1小时48分钟
1054
+ 完成步骤: 6
1055
+ 生成文档: 10个
1056
+ ```
1057
+
1058
+ **协调器端同步输出**:
1059
+
1060
+ ```
1061
+ 📥 收到启动请求: requirements-analysis
1062
+ ✅ 返回第一步指令: requirements_analysis_and_elicitation
1063
+
1064
+ 📥 步骤完成: requirements_analysis_and_elicitation
1065
+ 耗时: 1140秒
1066
+ 输出: 1个文件
1067
+ ✅ 返回下一步指令: analyze_existing_architecture
1068
+ 进度: 16% (1/6)
1069
+
1070
+ 📥 步骤完成: analyze_existing_architecture
1071
+ 耗时: 900秒
1072
+ 输出: 1个文件
1073
+ ✅ 返回下一步指令: create_brownfield_prd
1074
+ 进度: 33% (2/6)
1075
+
1076
+ (...)
1077
+
1078
+ 🎉 工作流执行完成!
1079
+ ```
1080
+
1081
+ ---
1082
+
1083
+ ## 5. 测试和调试
1084
+
1085
+ ### 5.1 测试协调器API
1086
+
1087
+ ```bash
1088
+ # 测试启动工作流
1089
+ curl -X POST http://localhost:3001/workflow/start \
1090
+ -H "Content-Type: application/json" \
1091
+ -d '{"workflowId":"requirements-analysis","context":{}}'
1092
+
1093
+ # 测试步骤完成
1094
+ curl -X POST http://localhost:3001/workflow/step-complete \
1095
+ -H "Content-Type: application/json" \
1096
+ -d '{
1097
+ "workflowId":"requirements-analysis",
1098
+ "stepId":"requirements_analysis_and_elicitation",
1099
+ "status":"success",
1100
+ "outputs":[{"file":"docs/requirements/requirements-analysis.md","exists":true,"size":25600}],
1101
+ "duration":1140000
1102
+ }'
1103
+
1104
+ # 测试查询状态
1105
+ curl http://localhost:3001/workflow/status
1106
+
1107
+ # 测试健康检查
1108
+ curl http://localhost:3001/health
1109
+ ```
1110
+
1111
+ ### 5.2 调试技巧
1112
+
1113
+ 1. **启用详细日志**:
1114
+ ```javascript
1115
+ // 在coordinator中添加
1116
+ console.log(JSON.stringify(stepInstruction, null, 2));
1117
+ ```
1118
+
1119
+ 2. **查看状态文件**:
1120
+ ```bash
1121
+ cat .xiaoma-core/.coordinator-state.json | jq
1122
+ ```
1123
+
1124
+ 3. **模拟步骤执行**:
1125
+ 创建测试脚本模拟Claude Code的请求
1126
+
1127
+ ---
1128
+
1129
+ ## 6. package.json配置
1130
+
1131
+ ```json
1132
+ {
1133
+ "name": "xiaoma-workflow-coordinator",
1134
+ "version": "1.0.0",
1135
+ "description": "工作流协调器 - 驱动XiaoMa-CLI工作流自动执行",
1136
+ "main": "src/index.js",
1137
+ "bin": {
1138
+ "xiaoma-coordinator": "src/index.js"
1139
+ },
1140
+ "scripts": {
1141
+ "start": "node src/index.js",
1142
+ "dev": "nodemon src/index.js",
1143
+ "test": "jest"
1144
+ },
1145
+ "keywords": ["workflow", "automation", "coordinator"],
1146
+ "author": "XiaoMa Team",
1147
+ "license": "MIT",
1148
+ "dependencies": {
1149
+ "express": "^4.18.2",
1150
+ "js-yaml": "^4.1.0",
1151
+ "fs-extra": "^11.1.1",
1152
+ "chalk": "^5.3.0",
1153
+ "cors": "^2.8.5",
1154
+ "dotenv": "^16.3.1"
1155
+ },
1156
+ "devDependencies": {
1157
+ "nodemon": "^3.0.1",
1158
+ "jest": "^29.7.0"
1159
+ }
1160
+ }
1161
+ ```
1162
+
1163
+ ---
1164
+
1165
+ ## 附录
1166
+
1167
+ ### A. 常见问题
1168
+
1169
+ **Q: 协调器无法连接?**
1170
+ A: 检查端口3001是否被占用,可以修改环境变量`COORDINATOR_PORT`
1171
+
1172
+ **Q: workflow-helper无法调用协调器API?**
1173
+ A: 确认协调器已启动,检查URL是否正确: http://localhost:3001
1174
+
1175
+ **Q: 步骤执行后无法获取输出文件?**
1176
+ A: 确认智能体已正确生成文档,检查文件路径是否正确
1177
+
1178
+ **Q: 如何添加新的工作流?**
1179
+ A: 在`xiaoma-core/workflows/`目录下创建新的YAML文件即可
1180
+
1181
+ ---
1182
+
1183
+ **文档完成!** 🎉
1184
+
1185
+ 现在你可以:
1186
+ 1. 按照此指南实现协调器
1187
+ 2. 创建workflow-helper智能体
1188
+ 3. 测试完整的工作流自动执行