openmatrix 0.1.0
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/README.md +512 -0
- package/dist/agents/agent-runner.d.ts +152 -0
- package/dist/agents/agent-runner.js +656 -0
- package/dist/agents/base-agent.d.ts +46 -0
- package/dist/agents/base-agent.js +17 -0
- package/dist/agents/impl/coder-agent.d.ts +17 -0
- package/dist/agents/impl/coder-agent.js +96 -0
- package/dist/agents/impl/executor-agent.d.ts +32 -0
- package/dist/agents/impl/executor-agent.js +168 -0
- package/dist/agents/impl/index.d.ts +6 -0
- package/dist/agents/impl/index.js +17 -0
- package/dist/agents/impl/planner-agent.d.ts +24 -0
- package/dist/agents/impl/planner-agent.js +126 -0
- package/dist/agents/impl/researcher-agent.d.ts +17 -0
- package/dist/agents/impl/researcher-agent.js +133 -0
- package/dist/agents/impl/reviewer-agent.d.ts +17 -0
- package/dist/agents/impl/reviewer-agent.js +120 -0
- package/dist/agents/impl/tester-agent.d.ts +17 -0
- package/dist/agents/impl/tester-agent.js +110 -0
- package/dist/cli/commands/approve.d.ts +2 -0
- package/dist/cli/commands/approve.js +87 -0
- package/dist/cli/commands/meeting.d.ts +2 -0
- package/dist/cli/commands/meeting.js +245 -0
- package/dist/cli/commands/report.d.ts +2 -0
- package/dist/cli/commands/report.js +202 -0
- package/dist/cli/commands/resume.d.ts +2 -0
- package/dist/cli/commands/resume.js +104 -0
- package/dist/cli/commands/retry.d.ts +2 -0
- package/dist/cli/commands/retry.js +79 -0
- package/dist/cli/commands/start.d.ts +2 -0
- package/dist/cli/commands/start.js +252 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +226 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +26 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -0
- package/dist/orchestrator/ai-reviewer.d.ts +50 -0
- package/dist/orchestrator/ai-reviewer.js +326 -0
- package/dist/orchestrator/approval-manager.d.ts +62 -0
- package/dist/orchestrator/approval-manager.js +160 -0
- package/dist/orchestrator/executor.d.ts +114 -0
- package/dist/orchestrator/executor.js +325 -0
- package/dist/orchestrator/full-test-runner.d.ts +122 -0
- package/dist/orchestrator/full-test-runner.js +335 -0
- package/dist/orchestrator/git-commit-manager.d.ts +75 -0
- package/dist/orchestrator/git-commit-manager.js +248 -0
- package/dist/orchestrator/interactive-question-generator.d.ts +90 -0
- package/dist/orchestrator/interactive-question-generator.js +312 -0
- package/dist/orchestrator/meeting-manager.d.ts +85 -0
- package/dist/orchestrator/meeting-manager.js +222 -0
- package/dist/orchestrator/phase-executor.d.ts +198 -0
- package/dist/orchestrator/phase-executor.js +796 -0
- package/dist/orchestrator/question-generator.d.ts +22 -0
- package/dist/orchestrator/question-generator.js +102 -0
- package/dist/orchestrator/retry-manager.d.ts +41 -0
- package/dist/orchestrator/retry-manager.js +83 -0
- package/dist/orchestrator/scheduler.d.ts +62 -0
- package/dist/orchestrator/scheduler.js +148 -0
- package/dist/orchestrator/state-machine.d.ts +53 -0
- package/dist/orchestrator/state-machine.js +124 -0
- package/dist/orchestrator/task-parser.d.ts +7 -0
- package/dist/orchestrator/task-parser.js +63 -0
- package/dist/orchestrator/task-planner.d.ts +71 -0
- package/dist/orchestrator/task-planner.js +316 -0
- package/dist/storage/file-store.d.ts +12 -0
- package/dist/storage/file-store.js +80 -0
- package/dist/storage/state-manager.d.ts +31 -0
- package/dist/storage/state-manager.js +202 -0
- package/dist/types/index.d.ts +193 -0
- package/dist/types/index.js +30 -0
- package/dist/utils/logger.d.ts +41 -0
- package/dist/utils/logger.js +166 -0
- package/dist/utils/progress-reporter.d.ts +116 -0
- package/dist/utils/progress-reporter.js +287 -0
- package/package.json +50 -0
- package/scripts/build-check.js +19 -0
- package/scripts/install-skills.js +51 -0
- package/skills/approve.md +253 -0
- package/skills/meeting.md +346 -0
- package/skills/report.md +100 -0
- package/skills/resume.md +68 -0
- package/skills/retry.md +61 -0
- package/skills/start.md +449 -0
- package/skills/status.md +46 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.statusCommand = void 0;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const state_manager_js_1 = require("../../storage/state-manager.js");
|
|
42
|
+
const progress_reporter_js_1 = require("../../utils/progress-reporter.js");
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const chokidar = __importStar(require("chokidar"));
|
|
45
|
+
const readline = __importStar(require("readline"));
|
|
46
|
+
exports.statusCommand = new commander_1.Command('status')
|
|
47
|
+
.description('Show current execution status')
|
|
48
|
+
.option('--json', 'Output as JSON')
|
|
49
|
+
.option('--graph', 'Show dependency graph')
|
|
50
|
+
.option('--detailed', 'Show detailed task info')
|
|
51
|
+
.option('--watch', 'Watch for status changes in real-time')
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
const manager = new state_manager_js_1.StateManager('.openmatrix');
|
|
54
|
+
const reporter = new progress_reporter_js_1.ProgressReporter({ width: 30 });
|
|
55
|
+
if (options.watch) {
|
|
56
|
+
await runWatchMode(manager, reporter, options);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
await showStatus(manager, reporter, options);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* 显示当前状态
|
|
64
|
+
*/
|
|
65
|
+
async function showStatus(manager, reporter, options) {
|
|
66
|
+
try {
|
|
67
|
+
await manager.initialize();
|
|
68
|
+
const state = await manager.getState();
|
|
69
|
+
const tasks = await manager.listTasks();
|
|
70
|
+
if (options.json) {
|
|
71
|
+
console.log(JSON.stringify({ state, tasks }, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Header
|
|
75
|
+
console.log(chalk_1.default.bold('\n📊 OpenMatrix Status'));
|
|
76
|
+
console.log('━'.repeat(42));
|
|
77
|
+
console.log(`\n Run ID: ${chalk_1.default.cyan(state.runId)}`);
|
|
78
|
+
console.log(` Status: ${formatStatus(state.status)}`);
|
|
79
|
+
console.log(` Phase: ${chalk_1.default.yellow(state.currentPhase)}`);
|
|
80
|
+
console.log(` Started: ${state.startedAt}\n`);
|
|
81
|
+
// Progress visualization
|
|
82
|
+
if (state.statistics.totalTasks > 0) {
|
|
83
|
+
console.log(reporter.renderStatistics({
|
|
84
|
+
total: state.statistics.totalTasks,
|
|
85
|
+
completed: state.statistics.completed,
|
|
86
|
+
inProgress: state.statistics.inProgress,
|
|
87
|
+
pending: state.statistics.pending,
|
|
88
|
+
failed: state.statistics.failed
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
// Dependency graph
|
|
92
|
+
if (options.graph && tasks.length > 0) {
|
|
93
|
+
console.log('\n📊 Task Dependency Graph');
|
|
94
|
+
console.log('━'.repeat(42));
|
|
95
|
+
console.log(reporter.renderDependencyGraph(tasks));
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
// Detailed task list
|
|
99
|
+
if (options.detailed && tasks.length > 0) {
|
|
100
|
+
console.log('\n📋 Task Details');
|
|
101
|
+
console.log('━'.repeat(42));
|
|
102
|
+
for (const task of tasks) {
|
|
103
|
+
console.log(reporter.renderTaskCard(task));
|
|
104
|
+
console.log();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else if (tasks.length > 0) {
|
|
108
|
+
// Simple task list
|
|
109
|
+
console.log(chalk_1.default.bold('\n📋 Tasks'));
|
|
110
|
+
for (const task of tasks) {
|
|
111
|
+
const icon = reporter.getStatusIcon(task.status);
|
|
112
|
+
console.log(` ${icon} ${task.id}: ${task.title}`);
|
|
113
|
+
}
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
// Quick tips
|
|
117
|
+
console.log(chalk_1.default.gray('💡 Tips:'));
|
|
118
|
+
console.log(chalk_1.default.gray(' --watch Real-time status updates'));
|
|
119
|
+
console.log(chalk_1.default.gray(' --graph Show dependency graph'));
|
|
120
|
+
console.log(chalk_1.default.gray(' --detailed Show detailed task info'));
|
|
121
|
+
console.log(chalk_1.default.gray(' --json Output as JSON'));
|
|
122
|
+
console.log();
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error(chalk_1.default.red('Error:'), error);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Watch 模式 - 实时更新状态
|
|
131
|
+
*/
|
|
132
|
+
async function runWatchMode(manager, reporter, options) {
|
|
133
|
+
await manager.initialize();
|
|
134
|
+
// 清屏函数
|
|
135
|
+
const clearScreen = () => {
|
|
136
|
+
console.clear();
|
|
137
|
+
};
|
|
138
|
+
// 渲染状态
|
|
139
|
+
const renderStatus = async () => {
|
|
140
|
+
clearScreen();
|
|
141
|
+
console.log(chalk_1.default.bold.cyan('📊 OpenMatrix Watch Mode'));
|
|
142
|
+
console.log(chalk_1.default.gray('━'.repeat(42)));
|
|
143
|
+
console.log(chalk_1.default.gray('Press Ctrl+C to exit\n'));
|
|
144
|
+
try {
|
|
145
|
+
const state = await manager.getState();
|
|
146
|
+
const tasks = await manager.listTasks();
|
|
147
|
+
// 状态概览
|
|
148
|
+
console.log(`Run ID: ${chalk_1.default.cyan(state.runId)}`);
|
|
149
|
+
console.log(`Status: ${formatStatus(state.status)}`);
|
|
150
|
+
console.log(`Phase: ${chalk_1.default.yellow(state.currentPhase)}`);
|
|
151
|
+
console.log(`Updated: ${chalk_1.default.gray(new Date().toLocaleTimeString())}\n`);
|
|
152
|
+
// 进度条
|
|
153
|
+
if (state.statistics.totalTasks > 0) {
|
|
154
|
+
console.log(reporter.renderProgressBar(state.statistics.completed, state.statistics.totalTasks, 'Overall Progress'));
|
|
155
|
+
}
|
|
156
|
+
// 任务列表 (带动画图标)
|
|
157
|
+
if (tasks.length > 0) {
|
|
158
|
+
console.log(chalk_1.default.bold('\n📋 Tasks:'));
|
|
159
|
+
for (const task of tasks) {
|
|
160
|
+
const icon = reporter.getStatusIcon(task.status);
|
|
161
|
+
const statusColor = getStatusColor(task.status);
|
|
162
|
+
console.log(` ${icon} ${statusColor(task.id)}: ${task.title}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// 底部提示
|
|
166
|
+
console.log(chalk_1.default.gray('\n━'.repeat(42)));
|
|
167
|
+
console.log(chalk_1.default.gray('Watching for changes...'));
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error(chalk_1.default.red('Error:'), error);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
// 初始渲染
|
|
174
|
+
await renderStatus();
|
|
175
|
+
// 监听文件变化
|
|
176
|
+
const watcher = chokidar.watch('.openmatrix', {
|
|
177
|
+
ignored: /(^|[\/\\])\../,
|
|
178
|
+
persistent: true,
|
|
179
|
+
ignoreInitial: true
|
|
180
|
+
});
|
|
181
|
+
watcher.on('all', async (event, path) => {
|
|
182
|
+
await renderStatus();
|
|
183
|
+
});
|
|
184
|
+
// 处理退出
|
|
185
|
+
const rl = readline.createInterface({
|
|
186
|
+
input: process.stdin,
|
|
187
|
+
output: process.stdout
|
|
188
|
+
});
|
|
189
|
+
rl.on('close', () => {
|
|
190
|
+
watcher.close();
|
|
191
|
+
console.log(chalk_1.default.gray('\n👋 Watch mode ended'));
|
|
192
|
+
process.exit(0);
|
|
193
|
+
});
|
|
194
|
+
// 保持进程运行
|
|
195
|
+
await new Promise(() => { });
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 格式化状态显示
|
|
199
|
+
*/
|
|
200
|
+
function formatStatus(status) {
|
|
201
|
+
const colors = {
|
|
202
|
+
initialized: 'gray',
|
|
203
|
+
running: 'green',
|
|
204
|
+
paused: 'yellow',
|
|
205
|
+
completed: 'green',
|
|
206
|
+
failed: 'red'
|
|
207
|
+
};
|
|
208
|
+
const color = colors[status] || 'white';
|
|
209
|
+
return chalk_1.default[color](status);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* 获取状态颜色函数
|
|
213
|
+
*/
|
|
214
|
+
function getStatusColor(status) {
|
|
215
|
+
const colors = {
|
|
216
|
+
completed: 'green',
|
|
217
|
+
in_progress: 'blue',
|
|
218
|
+
failed: 'red',
|
|
219
|
+
blocked: 'red',
|
|
220
|
+
pending: 'gray',
|
|
221
|
+
verify: 'yellow',
|
|
222
|
+
accept: 'cyan'
|
|
223
|
+
};
|
|
224
|
+
const color = colors[status] || 'white';
|
|
225
|
+
return chalk_1.default[color];
|
|
226
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const status_js_1 = require("./commands/status.js");
|
|
6
|
+
const start_js_1 = require("./commands/start.js");
|
|
7
|
+
const approve_js_1 = require("./commands/approve.js");
|
|
8
|
+
const resume_js_1 = require("./commands/resume.js");
|
|
9
|
+
const retry_js_1 = require("./commands/retry.js");
|
|
10
|
+
const report_js_1 = require("./commands/report.js");
|
|
11
|
+
const meeting_js_1 = require("./commands/meeting.js");
|
|
12
|
+
const program = new commander_1.Command();
|
|
13
|
+
program
|
|
14
|
+
.name('openmatrix')
|
|
15
|
+
.description('AI Agent Task Orchestration System - 多 Agent 任务编排系统')
|
|
16
|
+
.version('0.1.0');
|
|
17
|
+
// 添加命令
|
|
18
|
+
program.addCommand(status_js_1.statusCommand);
|
|
19
|
+
program.addCommand(start_js_1.startCommand);
|
|
20
|
+
program.addCommand(approve_js_1.approveCommand);
|
|
21
|
+
program.addCommand(resume_js_1.resumeCommand);
|
|
22
|
+
program.addCommand(retry_js_1.retryCommand);
|
|
23
|
+
program.addCommand(report_js_1.reportCommand);
|
|
24
|
+
program.addCommand(meeting_js_1.meetingCommand);
|
|
25
|
+
// 默认帮助
|
|
26
|
+
program.parse();
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StateManager = exports.FileStore = void 0;
|
|
4
|
+
// src/index.ts
|
|
5
|
+
// export { Orchestrator } from './orchestrator/index.js';
|
|
6
|
+
var file_store_js_1 = require("./storage/file-store.js");
|
|
7
|
+
Object.defineProperty(exports, "FileStore", { enumerable: true, get: function () { return file_store_js_1.FileStore; } });
|
|
8
|
+
var state_manager_js_1 = require("./storage/state-manager.js");
|
|
9
|
+
Object.defineProperty(exports, "StateManager", { enumerable: true, get: function () { return state_manager_js_1.StateManager; } });
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Task } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* AI Reviewer 验收报告
|
|
4
|
+
*/
|
|
5
|
+
export interface ReviewReport {
|
|
6
|
+
taskId: string;
|
|
7
|
+
overallStatus: 'approved' | 'needs_changes' | 'rejected';
|
|
8
|
+
categories: ReviewCategory[];
|
|
9
|
+
issues: ReviewIssue[];
|
|
10
|
+
suggestions: string[];
|
|
11
|
+
summary: string;
|
|
12
|
+
reviewedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ReviewCategory {
|
|
15
|
+
name: string;
|
|
16
|
+
status: 'pass' | 'warning' | 'fail';
|
|
17
|
+
score: number;
|
|
18
|
+
details: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ReviewIssue {
|
|
21
|
+
severity: 'critical' | 'major' | 'minor' | 'suggestion';
|
|
22
|
+
file?: string;
|
|
23
|
+
line?: number;
|
|
24
|
+
description: string;
|
|
25
|
+
suggestion?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* AIReviewer - AI 代码审查器
|
|
29
|
+
*
|
|
30
|
+
* 在 Accept Phase 执行完整的代码审查:
|
|
31
|
+
* 1. 代码质量评估
|
|
32
|
+
* 2. 安全性检查
|
|
33
|
+
* 3. 性能评估
|
|
34
|
+
* 4. 最佳实践验证
|
|
35
|
+
* 5. 测试覆盖检查
|
|
36
|
+
*/
|
|
37
|
+
export declare class AIReviewer {
|
|
38
|
+
/**
|
|
39
|
+
* 生成 AI Review 提示词
|
|
40
|
+
*/
|
|
41
|
+
buildReviewPrompt(task: Task): string;
|
|
42
|
+
/**
|
|
43
|
+
* 解析 AI Review 结果
|
|
44
|
+
*/
|
|
45
|
+
parseReviewResult(output: string): ReviewReport;
|
|
46
|
+
/**
|
|
47
|
+
* 生成验收阶段提示词 (包含 AI Review)
|
|
48
|
+
*/
|
|
49
|
+
buildAcceptPrompt(task: Task): string;
|
|
50
|
+
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AIReviewer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* AIReviewer - AI 代码审查器
|
|
6
|
+
*
|
|
7
|
+
* 在 Accept Phase 执行完整的代码审查:
|
|
8
|
+
* 1. 代码质量评估
|
|
9
|
+
* 2. 安全性检查
|
|
10
|
+
* 3. 性能评估
|
|
11
|
+
* 4. 最佳实践验证
|
|
12
|
+
* 5. 测试覆盖检查
|
|
13
|
+
*/
|
|
14
|
+
class AIReviewer {
|
|
15
|
+
/**
|
|
16
|
+
* 生成 AI Review 提示词
|
|
17
|
+
*/
|
|
18
|
+
buildReviewPrompt(task) {
|
|
19
|
+
return `# AI Code Review - 验收阶段
|
|
20
|
+
|
|
21
|
+
## 任务信息
|
|
22
|
+
- Task ID: ${task.id}
|
|
23
|
+
- 标题: ${task.title}
|
|
24
|
+
- 描述: ${task.description}
|
|
25
|
+
|
|
26
|
+
## 审查范围
|
|
27
|
+
|
|
28
|
+
请对本次任务的所有代码变更进行完整审查。
|
|
29
|
+
|
|
30
|
+
## 审查清单
|
|
31
|
+
|
|
32
|
+
### 1. 代码质量 (Code Quality)
|
|
33
|
+
- [ ] 代码可读性: 命名清晰、结构合理
|
|
34
|
+
- [ ] 函数复杂度: 单一职责、适当长度
|
|
35
|
+
- [ ] 代码复用: 避免重复、抽取公共逻辑
|
|
36
|
+
- [ ] 注释质量: 关键逻辑有注释、复杂代码有说明
|
|
37
|
+
- [ ] 错误处理: 异常情况有处理、错误信息清晰
|
|
38
|
+
|
|
39
|
+
### 2. 安全性 (Security)
|
|
40
|
+
- [ ] 输入验证: 用户输入有校验
|
|
41
|
+
- [ ] SQL 注入: 数据库查询使用参数化
|
|
42
|
+
- [ ] XSS 攻击: 输出有转义
|
|
43
|
+
- [ ] 敏感数据: 密码/密钥不明文存储
|
|
44
|
+
- [ ] 权限控制: 敏感操作有权限检查
|
|
45
|
+
|
|
46
|
+
### 3. 性能 (Performance)
|
|
47
|
+
- [ ] 算法效率: 时间复杂度合理
|
|
48
|
+
- [ ] 数据库查询: 避免 N+1、使用索引
|
|
49
|
+
- [ ] 内存使用: 无内存泄漏、大对象及时释放
|
|
50
|
+
- [ ] 缓存策略: 适当使用缓存
|
|
51
|
+
- [ ] 异步处理: 耗时操作使用异步
|
|
52
|
+
|
|
53
|
+
### 4. 最佳实践 (Best Practices)
|
|
54
|
+
- [ ] 设计模式: 合理使用设计模式
|
|
55
|
+
- [ ] 依赖注入: 避免硬编码依赖
|
|
56
|
+
- [ ] 配置管理: 配置与代码分离
|
|
57
|
+
- [ ] 日志记录: 关键操作有日志
|
|
58
|
+
- [ ] 测试友好: 代码易于测试
|
|
59
|
+
|
|
60
|
+
### 5. 测试覆盖 (Test Coverage)
|
|
61
|
+
- [ ] 单元测试: 核心逻辑有测试
|
|
62
|
+
- [ ] 边界情况: 边界值有测试
|
|
63
|
+
- [ ] 异常路径: 错误情况有测试
|
|
64
|
+
- [ ] 测试质量: 测试有意义、不是为测试而测试
|
|
65
|
+
|
|
66
|
+
## 输出格式
|
|
67
|
+
|
|
68
|
+
在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
69
|
+
|
|
70
|
+
### ai-review-report.md
|
|
71
|
+
|
|
72
|
+
\`\`\`markdown
|
|
73
|
+
# AI Review 报告
|
|
74
|
+
|
|
75
|
+
## 任务信息
|
|
76
|
+
- Task ID: ${task.id}
|
|
77
|
+
- 审查时间: [当前时间]
|
|
78
|
+
|
|
79
|
+
## 总体评价
|
|
80
|
+
[✅ 通过 / ⚠️ 需要修改 / ❌ 拒绝]
|
|
81
|
+
|
|
82
|
+
## 分类评估
|
|
83
|
+
|
|
84
|
+
### 1. 代码质量
|
|
85
|
+
- 评分: [0-100]
|
|
86
|
+
- 状态: ✅ / ⚠️ / ❌
|
|
87
|
+
- 详情:
|
|
88
|
+
- [具体评价1]
|
|
89
|
+
- [具体评价2]
|
|
90
|
+
|
|
91
|
+
### 2. 安全性
|
|
92
|
+
- 评分: [0-100]
|
|
93
|
+
- 状态: ✅ / ⚠️ / ❌
|
|
94
|
+
- 详情:
|
|
95
|
+
- [具体评价1]
|
|
96
|
+
- [具体评价2]
|
|
97
|
+
|
|
98
|
+
### 3. 性能
|
|
99
|
+
- 评分: [0-100]
|
|
100
|
+
- 状态: ✅ / ⚠️ / ❌
|
|
101
|
+
- 详情:
|
|
102
|
+
- [具体评价1]
|
|
103
|
+
- [具体评价2]
|
|
104
|
+
|
|
105
|
+
### 4. 最佳实践
|
|
106
|
+
- 评分: [0-100]
|
|
107
|
+
- 状态: ✅ / ⚠️ / ❌
|
|
108
|
+
- 详情:
|
|
109
|
+
- [具体评价1]
|
|
110
|
+
- [具体评价2]
|
|
111
|
+
|
|
112
|
+
### 5. 测试覆盖
|
|
113
|
+
- 评分: [0-100]
|
|
114
|
+
- 状态: ✅ / ⚠️ / ❌
|
|
115
|
+
- 详情:
|
|
116
|
+
- [具体评价1]
|
|
117
|
+
- [具体评价2]
|
|
118
|
+
|
|
119
|
+
## 问题列表
|
|
120
|
+
|
|
121
|
+
### 严重 (Critical) - 必须修复
|
|
122
|
+
1. [文件:行号] 问题描述
|
|
123
|
+
- 建议: 修复建议
|
|
124
|
+
|
|
125
|
+
### 重要 (Major) - 强烈建议修复
|
|
126
|
+
1. [文件:行号] 问题描述
|
|
127
|
+
- 建议: 修复建议
|
|
128
|
+
|
|
129
|
+
### 次要 (Minor) - 可选优化
|
|
130
|
+
1. [文件:行号] 问题描述
|
|
131
|
+
|
|
132
|
+
### 建议 (Suggestion) - 改进建议
|
|
133
|
+
1. [改进建议]
|
|
134
|
+
|
|
135
|
+
## 总结
|
|
136
|
+
[审查总结和最终建议]
|
|
137
|
+
\`\`\`
|
|
138
|
+
|
|
139
|
+
## 最终输出
|
|
140
|
+
|
|
141
|
+
根据审查结果,输出以下之一:
|
|
142
|
+
|
|
143
|
+
**通过:**
|
|
144
|
+
\`\`\`
|
|
145
|
+
AI_REVIEW_APPROVED
|
|
146
|
+
\`\`\`
|
|
147
|
+
|
|
148
|
+
**需要修改:**
|
|
149
|
+
\`\`\`
|
|
150
|
+
AI_REVIEW_NEEDS_CHANGES
|
|
151
|
+
需要修复的问题:
|
|
152
|
+
1. [Critical/Major 问题描述]
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
**拒绝:**
|
|
156
|
+
\`\`\`
|
|
157
|
+
AI_REVIEW_REJECTED
|
|
158
|
+
拒绝原因:
|
|
159
|
+
1. [严重问题描述]
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
## 审查原则
|
|
163
|
+
|
|
164
|
+
1. **平衡** - 不要过于严苛,也不要过于宽松
|
|
165
|
+
2. **实用** - 关注真正重要的问题
|
|
166
|
+
3. **建设性** - 提供具体的改进建议
|
|
167
|
+
4. **上下文** - 考虑项目的实际情况和约束
|
|
168
|
+
5. **渐进** - 允许代码渐进式改进,不要求完美
|
|
169
|
+
`;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 解析 AI Review 结果
|
|
173
|
+
*/
|
|
174
|
+
parseReviewResult(output) {
|
|
175
|
+
const lines = output.split('\n');
|
|
176
|
+
const issues = [];
|
|
177
|
+
const categories = [];
|
|
178
|
+
const suggestions = [];
|
|
179
|
+
let overallStatus = 'approved';
|
|
180
|
+
// 检查最终状态
|
|
181
|
+
if (output.includes('AI_REVIEW_APPROVED')) {
|
|
182
|
+
overallStatus = 'approved';
|
|
183
|
+
}
|
|
184
|
+
else if (output.includes('AI_REVIEW_REJECTED')) {
|
|
185
|
+
overallStatus = 'rejected';
|
|
186
|
+
}
|
|
187
|
+
else if (output.includes('AI_REVIEW_NEEDS_CHANGES')) {
|
|
188
|
+
overallStatus = 'needs_changes';
|
|
189
|
+
}
|
|
190
|
+
// 解析问题
|
|
191
|
+
const criticalSection = output.match(/### 严重[\s\S]*?(?=###|$)/);
|
|
192
|
+
const majorSection = output.match(/### 重要[\s\S]*?(?=###|$)/);
|
|
193
|
+
const minorSection = output.match(/### 次要[\s\S]*?(?=###|$)/);
|
|
194
|
+
const suggestionSection = output.match(/### 建议[\s\S]*?(?=##|$)/);
|
|
195
|
+
if (criticalSection) {
|
|
196
|
+
const items = criticalSection[0].match(/^\d+\..*$/gm) || [];
|
|
197
|
+
items.forEach(item => {
|
|
198
|
+
issues.push({
|
|
199
|
+
severity: 'critical',
|
|
200
|
+
description: item.replace(/^\d+\.\s*/, '').trim()
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (majorSection) {
|
|
205
|
+
const items = majorSection[0].match(/^\d+\..*$/gm) || [];
|
|
206
|
+
items.forEach(item => {
|
|
207
|
+
issues.push({
|
|
208
|
+
severity: 'major',
|
|
209
|
+
description: item.replace(/^\d+\.\s*/, '').trim()
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (minorSection) {
|
|
214
|
+
const items = minorSection[0].match(/^\d+\..*$/gm) || [];
|
|
215
|
+
items.forEach(item => {
|
|
216
|
+
issues.push({
|
|
217
|
+
severity: 'minor',
|
|
218
|
+
description: item.replace(/^\d+\.\s*/, '').trim()
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (suggestionSection) {
|
|
223
|
+
const items = suggestionSection[0].match(/^\d+\..*$/gm) || [];
|
|
224
|
+
items.forEach(item => {
|
|
225
|
+
suggestions.push(item.replace(/^\d+\.\s*/, '').trim());
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
// 解析分类评分
|
|
229
|
+
const categoryPatterns = [
|
|
230
|
+
{ name: '代码质量', pattern: /### 1\. 代码质量[\s\S]*?- 评分:\s*(\d+)/ },
|
|
231
|
+
{ name: '安全性', pattern: /### 2\. 安全性[\s\S]*?- 评分:\s*(\d+)/ },
|
|
232
|
+
{ name: '性能', pattern: /### 3\. 性能[\s\S]*?- 评分:\s*(\d+)/ },
|
|
233
|
+
{ name: '最佳实践', pattern: /### 4\. 最佳实践[\s\S]*?- 评分:\s*(\d+)/ },
|
|
234
|
+
{ name: '测试覆盖', pattern: /### 5\. 测试覆盖[\s\S]*?- 评分:\s*(\d+)/ }
|
|
235
|
+
];
|
|
236
|
+
for (const { name, pattern } of categoryPatterns) {
|
|
237
|
+
const match = output.match(pattern);
|
|
238
|
+
if (match) {
|
|
239
|
+
const score = parseInt(match[1], 10);
|
|
240
|
+
categories.push({
|
|
241
|
+
name,
|
|
242
|
+
score,
|
|
243
|
+
status: score >= 80 ? 'pass' : score >= 60 ? 'warning' : 'fail',
|
|
244
|
+
details: []
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// 提取总结
|
|
249
|
+
const summaryMatch = output.match(/## 总结\s*([\s\S]*?)(?=```|$)/);
|
|
250
|
+
const summary = summaryMatch ? summaryMatch[1].trim() : '';
|
|
251
|
+
return {
|
|
252
|
+
taskId: '',
|
|
253
|
+
overallStatus,
|
|
254
|
+
categories,
|
|
255
|
+
issues,
|
|
256
|
+
suggestions,
|
|
257
|
+
summary,
|
|
258
|
+
reviewedAt: new Date().toISOString()
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* 生成验收阶段提示词 (包含 AI Review)
|
|
263
|
+
*/
|
|
264
|
+
buildAcceptPrompt(task) {
|
|
265
|
+
const reviewPrompt = this.buildReviewPrompt(task);
|
|
266
|
+
return `# 验收阶段 (Accept Phase)
|
|
267
|
+
|
|
268
|
+
## 任务信息
|
|
269
|
+
- ID: ${task.id}
|
|
270
|
+
- 标题: ${task.title}
|
|
271
|
+
- 描述: ${task.description}
|
|
272
|
+
|
|
273
|
+
## 验收流程
|
|
274
|
+
|
|
275
|
+
### 1. AI Code Review
|
|
276
|
+
执行完整的代码审查:
|
|
277
|
+
|
|
278
|
+
${reviewPrompt}
|
|
279
|
+
|
|
280
|
+
### 2. 功能验证
|
|
281
|
+
- 确认功能按需求实现
|
|
282
|
+
- 检查边界情况处理
|
|
283
|
+
- 验证错误处理
|
|
284
|
+
|
|
285
|
+
### 3. 文档检查
|
|
286
|
+
- README 是否更新
|
|
287
|
+
- API 文档是否完整
|
|
288
|
+
- 注释是否充分
|
|
289
|
+
|
|
290
|
+
### 4. 最终确认
|
|
291
|
+
- 所有测试通过
|
|
292
|
+
- AI Review 通过
|
|
293
|
+
- 文档已更新
|
|
294
|
+
- 可以合并
|
|
295
|
+
|
|
296
|
+
## 输出要求
|
|
297
|
+
|
|
298
|
+
在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
299
|
+
- \`accept-report.md\` - 验收报告
|
|
300
|
+
- \`ai-review-report.md\` - AI 审查报告
|
|
301
|
+
|
|
302
|
+
## 结果格式
|
|
303
|
+
|
|
304
|
+
如果验收通过,输出:
|
|
305
|
+
\`\`\`
|
|
306
|
+
ACCEPT_PASSED
|
|
307
|
+
\`\`\`
|
|
308
|
+
|
|
309
|
+
如果需要修改,输出:
|
|
310
|
+
\`\`\`
|
|
311
|
+
ACCEPT_NEEDS_MODIFICATION
|
|
312
|
+
修改建议:
|
|
313
|
+
1. [建议]
|
|
314
|
+
2. [建议]
|
|
315
|
+
\`\`\`
|
|
316
|
+
|
|
317
|
+
如果验收失败,输出:
|
|
318
|
+
\`\`\`
|
|
319
|
+
ACCEPT_FAILED
|
|
320
|
+
失败原因:
|
|
321
|
+
1. [原因]
|
|
322
|
+
\`\`\`
|
|
323
|
+
`;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
exports.AIReviewer = AIReviewer;
|