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.
Files changed (85) hide show
  1. package/README.md +512 -0
  2. package/dist/agents/agent-runner.d.ts +152 -0
  3. package/dist/agents/agent-runner.js +656 -0
  4. package/dist/agents/base-agent.d.ts +46 -0
  5. package/dist/agents/base-agent.js +17 -0
  6. package/dist/agents/impl/coder-agent.d.ts +17 -0
  7. package/dist/agents/impl/coder-agent.js +96 -0
  8. package/dist/agents/impl/executor-agent.d.ts +32 -0
  9. package/dist/agents/impl/executor-agent.js +168 -0
  10. package/dist/agents/impl/index.d.ts +6 -0
  11. package/dist/agents/impl/index.js +17 -0
  12. package/dist/agents/impl/planner-agent.d.ts +24 -0
  13. package/dist/agents/impl/planner-agent.js +126 -0
  14. package/dist/agents/impl/researcher-agent.d.ts +17 -0
  15. package/dist/agents/impl/researcher-agent.js +133 -0
  16. package/dist/agents/impl/reviewer-agent.d.ts +17 -0
  17. package/dist/agents/impl/reviewer-agent.js +120 -0
  18. package/dist/agents/impl/tester-agent.d.ts +17 -0
  19. package/dist/agents/impl/tester-agent.js +110 -0
  20. package/dist/cli/commands/approve.d.ts +2 -0
  21. package/dist/cli/commands/approve.js +87 -0
  22. package/dist/cli/commands/meeting.d.ts +2 -0
  23. package/dist/cli/commands/meeting.js +245 -0
  24. package/dist/cli/commands/report.d.ts +2 -0
  25. package/dist/cli/commands/report.js +202 -0
  26. package/dist/cli/commands/resume.d.ts +2 -0
  27. package/dist/cli/commands/resume.js +104 -0
  28. package/dist/cli/commands/retry.d.ts +2 -0
  29. package/dist/cli/commands/retry.js +79 -0
  30. package/dist/cli/commands/start.d.ts +2 -0
  31. package/dist/cli/commands/start.js +252 -0
  32. package/dist/cli/commands/status.d.ts +2 -0
  33. package/dist/cli/commands/status.js +226 -0
  34. package/dist/cli/index.d.ts +2 -0
  35. package/dist/cli/index.js +26 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +9 -0
  38. package/dist/orchestrator/ai-reviewer.d.ts +50 -0
  39. package/dist/orchestrator/ai-reviewer.js +326 -0
  40. package/dist/orchestrator/approval-manager.d.ts +62 -0
  41. package/dist/orchestrator/approval-manager.js +160 -0
  42. package/dist/orchestrator/executor.d.ts +114 -0
  43. package/dist/orchestrator/executor.js +325 -0
  44. package/dist/orchestrator/full-test-runner.d.ts +122 -0
  45. package/dist/orchestrator/full-test-runner.js +335 -0
  46. package/dist/orchestrator/git-commit-manager.d.ts +75 -0
  47. package/dist/orchestrator/git-commit-manager.js +248 -0
  48. package/dist/orchestrator/interactive-question-generator.d.ts +90 -0
  49. package/dist/orchestrator/interactive-question-generator.js +312 -0
  50. package/dist/orchestrator/meeting-manager.d.ts +85 -0
  51. package/dist/orchestrator/meeting-manager.js +222 -0
  52. package/dist/orchestrator/phase-executor.d.ts +198 -0
  53. package/dist/orchestrator/phase-executor.js +796 -0
  54. package/dist/orchestrator/question-generator.d.ts +22 -0
  55. package/dist/orchestrator/question-generator.js +102 -0
  56. package/dist/orchestrator/retry-manager.d.ts +41 -0
  57. package/dist/orchestrator/retry-manager.js +83 -0
  58. package/dist/orchestrator/scheduler.d.ts +62 -0
  59. package/dist/orchestrator/scheduler.js +148 -0
  60. package/dist/orchestrator/state-machine.d.ts +53 -0
  61. package/dist/orchestrator/state-machine.js +124 -0
  62. package/dist/orchestrator/task-parser.d.ts +7 -0
  63. package/dist/orchestrator/task-parser.js +63 -0
  64. package/dist/orchestrator/task-planner.d.ts +71 -0
  65. package/dist/orchestrator/task-planner.js +316 -0
  66. package/dist/storage/file-store.d.ts +12 -0
  67. package/dist/storage/file-store.js +80 -0
  68. package/dist/storage/state-manager.d.ts +31 -0
  69. package/dist/storage/state-manager.js +202 -0
  70. package/dist/types/index.d.ts +193 -0
  71. package/dist/types/index.js +30 -0
  72. package/dist/utils/logger.d.ts +41 -0
  73. package/dist/utils/logger.js +166 -0
  74. package/dist/utils/progress-reporter.d.ts +116 -0
  75. package/dist/utils/progress-reporter.js +287 -0
  76. package/package.json +50 -0
  77. package/scripts/build-check.js +19 -0
  78. package/scripts/install-skills.js +51 -0
  79. package/skills/approve.md +253 -0
  80. package/skills/meeting.md +346 -0
  81. package/skills/report.md +100 -0
  82. package/skills/resume.md +68 -0
  83. package/skills/retry.md +61 -0
  84. package/skills/start.md +449 -0
  85. package/skills/status.md +46 -0
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitCommitManager = void 0;
4
+ // src/orchestrator/git-commit-manager.ts
5
+ const child_process_1 = require("child_process");
6
+ const util_1 = require("util");
7
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
8
+ /**
9
+ * GitCommitManager - Git 自动提交管理器
10
+ *
11
+ * 功能:
12
+ * 1. 自动生成详细提交信息
13
+ * 2. 包含任务名、修改内容、影响范围
14
+ * 3. 支持每个子任务完成后自动提交
15
+ */
16
+ class GitCommitManager {
17
+ repoPath;
18
+ enabled = true;
19
+ constructor(repoPath = process.cwd()) {
20
+ this.repoPath = repoPath;
21
+ }
22
+ /**
23
+ * 设置是否启用自动提交
24
+ */
25
+ setEnabled(enabled) {
26
+ this.enabled = enabled;
27
+ }
28
+ /**
29
+ * 检查是否在 Git 仓库中
30
+ */
31
+ async isGitRepo() {
32
+ try {
33
+ await execAsync('git rev-parse --is-inside-work-tree', { cwd: this.repoPath });
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ /**
41
+ * 获取当前分支名
42
+ */
43
+ async getCurrentBranch() {
44
+ const { stdout } = await execAsync('git rev-parse --abbrev-ref HEAD', { cwd: this.repoPath });
45
+ return stdout.trim();
46
+ }
47
+ /**
48
+ * 获取未提交的文件列表
49
+ */
50
+ async getUncommittedFiles() {
51
+ try {
52
+ const { stdout } = await execAsync('git status --porcelain', { cwd: this.repoPath });
53
+ return stdout
54
+ .split('\n')
55
+ .filter(line => line.trim())
56
+ .map(line => line.slice(3).trim());
57
+ }
58
+ catch {
59
+ return [];
60
+ }
61
+ }
62
+ /**
63
+ * 获取已修改的文件差异统计
64
+ */
65
+ async getDiffStats() {
66
+ const stats = new Map();
67
+ try {
68
+ const { stdout } = await execAsync('git diff --stat', { cwd: this.repoPath });
69
+ const lines = stdout.split('\n').filter(l => l.trim());
70
+ for (const line of lines) {
71
+ const match = line.match(/^(.+?)\s+\|\s+(\d+)\s+([+-]+)/);
72
+ if (match) {
73
+ const file = match[1].trim();
74
+ const changes = match[3] || '';
75
+ stats.set(file, {
76
+ additions: (changes.match(/\+/g) || []).length,
77
+ deletions: (changes.match(/-/g) || []).length
78
+ });
79
+ }
80
+ }
81
+ }
82
+ catch {
83
+ // ignore
84
+ }
85
+ return stats;
86
+ }
87
+ /**
88
+ * 分析影响范围
89
+ */
90
+ async analyzeImpactScope(files) {
91
+ const scopes = new Set();
92
+ for (const file of files) {
93
+ // 根据文件路径分析影响范围
94
+ if (file.includes('src/cli/'))
95
+ scopes.add('CLI');
96
+ if (file.includes('src/orchestrator/'))
97
+ scopes.add('Orchestrator');
98
+ if (file.includes('src/agents/'))
99
+ scopes.add('Agents');
100
+ if (file.includes('src/storage/'))
101
+ scopes.add('Storage');
102
+ if (file.includes('src/types/'))
103
+ scopes.add('Types');
104
+ if (file.includes('skills/'))
105
+ scopes.add('Skills');
106
+ if (file.includes('docs/'))
107
+ scopes.add('Documentation');
108
+ if (file.includes('tests/'))
109
+ scopes.add('Tests');
110
+ if (file.endsWith('.md'))
111
+ scopes.add('Documentation');
112
+ if (file.endsWith('package.json'))
113
+ scopes.add('Dependencies');
114
+ if (file.endsWith('tsconfig.json'))
115
+ scopes.add('TypeScript Config');
116
+ }
117
+ return Array.from(scopes);
118
+ }
119
+ /**
120
+ * 生成提交信息
121
+ */
122
+ generateCommitMessage(info) {
123
+ const lines = [];
124
+ // 标题行 - 包含任务 ID 和标题
125
+ const phaseEmoji = {
126
+ tdd: '🧪',
127
+ develop: '✨',
128
+ verify: '✅',
129
+ accept: '🎉'
130
+ };
131
+ const title = info.taskTitle.length > 50
132
+ ? info.taskTitle.slice(0, 47) + '...'
133
+ : info.taskTitle;
134
+ lines.push(`${phaseEmoji[info.phase]} (${info.taskId}): ${title}`);
135
+ lines.push('');
136
+ // 修改内容
137
+ if (info.changes.length > 0) {
138
+ lines.push('## 修改内容');
139
+ for (const change of info.changes.slice(0, 10)) {
140
+ lines.push(`- ${change}`);
141
+ }
142
+ if (info.changes.length > 10) {
143
+ lines.push(`- ... 及其他 ${info.changes.length - 10} 项修改`);
144
+ }
145
+ lines.push('');
146
+ }
147
+ // 影响范围
148
+ if (info.impactScope.length > 0) {
149
+ lines.push('## 影响范围');
150
+ lines.push(`模块: ${info.impactScope.join(', ')}`);
151
+ lines.push('');
152
+ }
153
+ // 元数据
154
+ lines.push('---');
155
+ lines.push(`Task-ID: ${info.taskId}`);
156
+ lines.push(`Run-ID: ${info.runId}`);
157
+ lines.push(`Phase: ${info.phase}`);
158
+ lines.push(`Co-Authored-By: OpenMatrix Agent <agent@openmatrix.dev>`);
159
+ return lines.join('\n');
160
+ }
161
+ /**
162
+ * 执行提交
163
+ */
164
+ async commit(info) {
165
+ if (!this.enabled) {
166
+ return { success: false, message: 'Auto-commit is disabled' };
167
+ }
168
+ try {
169
+ // 检查是否在 Git 仓库中
170
+ if (!await this.isGitRepo()) {
171
+ return { success: false, error: 'Not a git repository' };
172
+ }
173
+ // 获取未提交的文件
174
+ const files = await this.getUncommittedFiles();
175
+ if (files.length === 0) {
176
+ return { success: false, message: 'No changes to commit' };
177
+ }
178
+ // 分析影响范围
179
+ const impactScope = await this.analyzeImpactScope(files);
180
+ // 更新 commit info
181
+ const fullInfo = {
182
+ ...info,
183
+ changes: files,
184
+ impactScope: info.impactScope.length > 0 ? info.impactScope : impactScope
185
+ };
186
+ // 生成提交信息
187
+ const commitMessage = this.generateCommitMessage(fullInfo);
188
+ // 添加所有文件
189
+ await execAsync('git add -A', { cwd: this.repoPath });
190
+ // 执行提交
191
+ const { stdout } = await execAsync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { cwd: this.repoPath });
192
+ // 提取 commit hash
193
+ const hashMatch = stdout.match(/\[.+?\s+([a-f0-9]+)\]/);
194
+ const commitHash = hashMatch ? hashMatch[1] : undefined;
195
+ return {
196
+ success: true,
197
+ commitHash,
198
+ message: `Committed ${files.length} files`
199
+ };
200
+ }
201
+ catch (error) {
202
+ return {
203
+ success: false,
204
+ error: error instanceof Error ? error.message : String(error)
205
+ };
206
+ }
207
+ }
208
+ /**
209
+ * 提交任务完成
210
+ */
211
+ async commitTaskCompletion(task, runId) {
212
+ return this.commit({
213
+ taskId: task.id,
214
+ taskTitle: task.title,
215
+ runId,
216
+ phase: 'develop',
217
+ changes: [],
218
+ impactScope: []
219
+ });
220
+ }
221
+ /**
222
+ * 提交验证阶段完成
223
+ */
224
+ async commitVerifyComplete(task, runId, testResults) {
225
+ return this.commit({
226
+ taskId: task.id,
227
+ taskTitle: task.title,
228
+ runId,
229
+ phase: 'verify',
230
+ changes: testResults,
231
+ impactScope: ['Tests']
232
+ });
233
+ }
234
+ /**
235
+ * 提交验收阶段完成
236
+ */
237
+ async commitAcceptComplete(task, runId) {
238
+ return this.commit({
239
+ taskId: task.id,
240
+ taskTitle: task.title,
241
+ runId,
242
+ phase: 'accept',
243
+ changes: [],
244
+ impactScope: []
245
+ });
246
+ }
247
+ }
248
+ exports.GitCommitManager = GitCommitManager;
@@ -0,0 +1,90 @@
1
+ import type { ParsedTask } from '../types/index.js';
2
+ /**
3
+ * 交互式问题 - 支持多轮追问
4
+ */
5
+ export interface InteractiveQuestion {
6
+ id: string;
7
+ question: string;
8
+ type: 'single' | 'multiple' | 'text' | 'confirm';
9
+ options?: QuestionOption[];
10
+ required: boolean;
11
+ /** 追问条件 - 根据回答触发 */
12
+ followUpCondition?: {
13
+ /** 触发追问的选项 key */
14
+ triggerKeys: string[];
15
+ /** 追问问题 */
16
+ followUpQuestions: InteractiveQuestion[];
17
+ };
18
+ /** 问题分类 */
19
+ category: 'objective' | 'technical' | 'scope' | 'quality' | 'constraint' | 'risk';
20
+ /** 优先级 (1-7, 1 最高) */
21
+ priority: number;
22
+ }
23
+ export interface QuestionOption {
24
+ key: string;
25
+ label: string;
26
+ description?: string;
27
+ }
28
+ export interface QuestionAnswer {
29
+ questionId: string;
30
+ selectedKeys: string[];
31
+ textValue?: string;
32
+ }
33
+ export interface QuestionSession {
34
+ sessionId: string;
35
+ taskId: string;
36
+ questions: InteractiveQuestion[];
37
+ answers: QuestionAnswer[];
38
+ currentQuestionIndex: number;
39
+ status: 'pending' | 'in_progress' | 'completed';
40
+ createdAt: string;
41
+ completedAt?: string;
42
+ }
43
+ /**
44
+ * InteractiveQuestionGenerator - 交互式问题生成器
45
+ *
46
+ * 特性:
47
+ * 1. 多轮追问 - 根据回答动态生成新问题
48
+ * 2. 优先级排序 - 按重要性顺序提问
49
+ * 3. 条件分支 - 不同回答触发不同追问
50
+ * 4. 交互友好 - 支持单步/批量回答
51
+ */
52
+ export declare class InteractiveQuestionGenerator {
53
+ private session;
54
+ /**
55
+ * 开始新的问答会话
56
+ */
57
+ startSession(parsedTask: ParsedTask): QuestionSession;
58
+ /**
59
+ * 获取当前问题
60
+ */
61
+ getCurrentQuestion(): InteractiveQuestion | null;
62
+ /**
63
+ * 获取下一个问题 (支持交互式逐个提问)
64
+ */
65
+ getNextQuestion(): InteractiveQuestion | null;
66
+ /**
67
+ * 回答当前问题
68
+ */
69
+ answerCurrentQuestion(answer: QuestionAnswer): InteractiveQuestion | null;
70
+ /**
71
+ * 批量回答问题
72
+ */
73
+ answerMultiple(answers: QuestionAnswer[]): QuestionSession;
74
+ /**
75
+ * 获取会话状态
76
+ */
77
+ getSession(): QuestionSession | null;
78
+ /**
79
+ * 获取所有问题和答案的摘要
80
+ */
81
+ getSummary(): string;
82
+ /**
83
+ * 生成基础问题集
84
+ */
85
+ private generateBaseQuestions;
86
+ /**
87
+ * 根据任务内容动态添加问题
88
+ */
89
+ addContextualQuestions(task: ParsedTask, questions: InteractiveQuestion[]): InteractiveQuestion[];
90
+ }
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InteractiveQuestionGenerator = void 0;
4
+ /**
5
+ * InteractiveQuestionGenerator - 交互式问题生成器
6
+ *
7
+ * 特性:
8
+ * 1. 多轮追问 - 根据回答动态生成新问题
9
+ * 2. 优先级排序 - 按重要性顺序提问
10
+ * 3. 条件分支 - 不同回答触发不同追问
11
+ * 4. 交互友好 - 支持单步/批量回答
12
+ */
13
+ class InteractiveQuestionGenerator {
14
+ session = null;
15
+ /**
16
+ * 开始新的问答会话
17
+ */
18
+ startSession(parsedTask) {
19
+ const baseQuestions = this.generateBaseQuestions(parsedTask);
20
+ this.session = {
21
+ sessionId: `qs-${Date.now().toString(36)}`,
22
+ taskId: parsedTask.title,
23
+ questions: baseQuestions.sort((a, b) => a.priority - b.priority),
24
+ answers: [],
25
+ currentQuestionIndex: 0,
26
+ status: 'in_progress',
27
+ createdAt: new Date().toISOString()
28
+ };
29
+ return this.session;
30
+ }
31
+ /**
32
+ * 获取当前问题
33
+ */
34
+ getCurrentQuestion() {
35
+ if (!this.session || this.session.status !== 'in_progress') {
36
+ return null;
37
+ }
38
+ return this.session.questions[this.session.currentQuestionIndex] || null;
39
+ }
40
+ /**
41
+ * 获取下一个问题 (支持交互式逐个提问)
42
+ */
43
+ getNextQuestion() {
44
+ if (!this.session || this.session.status !== 'in_progress') {
45
+ return null;
46
+ }
47
+ // 检查是否有追问
48
+ const lastAnswer = this.session.answers[this.session.answers.length - 1];
49
+ if (lastAnswer) {
50
+ const lastQuestion = this.session.questions.find(q => q.id === lastAnswer.questionId);
51
+ if (lastQuestion?.followUpCondition) {
52
+ const shouldFollowUp = lastQuestion.followUpCondition.triggerKeys.some(key => lastAnswer.selectedKeys.includes(key));
53
+ if (shouldFollowUp) {
54
+ // 插入追问到队列
55
+ const followUps = lastQuestion.followUpCondition.followUpQuestions;
56
+ const insertIndex = this.session.currentQuestionIndex + 1;
57
+ this.session.questions.splice(insertIndex, 0, ...followUps);
58
+ }
59
+ }
60
+ }
61
+ this.session.currentQuestionIndex++;
62
+ if (this.session.currentQuestionIndex >= this.session.questions.length) {
63
+ this.session.status = 'completed';
64
+ this.session.completedAt = new Date().toISOString();
65
+ return null;
66
+ }
67
+ return this.session.questions[this.session.currentQuestionIndex];
68
+ }
69
+ /**
70
+ * 回答当前问题
71
+ */
72
+ answerCurrentQuestion(answer) {
73
+ if (!this.session) {
74
+ throw new Error('No active session');
75
+ }
76
+ // 记录答案
77
+ this.session.answers.push(answer);
78
+ // 获取下一个问题
79
+ return this.getNextQuestion();
80
+ }
81
+ /**
82
+ * 批量回答问题
83
+ */
84
+ answerMultiple(answers) {
85
+ if (!this.session) {
86
+ throw new Error('No active session');
87
+ }
88
+ for (const answer of answers) {
89
+ this.session.answers.push(answer);
90
+ }
91
+ // 处理追问
92
+ for (const answer of answers) {
93
+ const question = this.session.questions.find(q => q.id === answer.questionId);
94
+ if (question?.followUpCondition) {
95
+ const shouldFollowUp = question.followUpCondition.triggerKeys.some(key => answer.selectedKeys.includes(key));
96
+ if (shouldFollowUp) {
97
+ this.session.questions.push(...question.followUpCondition.followUpQuestions);
98
+ }
99
+ }
100
+ }
101
+ this.session.status = 'completed';
102
+ this.session.completedAt = new Date().toISOString();
103
+ return this.session;
104
+ }
105
+ /**
106
+ * 获取会话状态
107
+ */
108
+ getSession() {
109
+ return this.session;
110
+ }
111
+ /**
112
+ * 获取所有问题和答案的摘要
113
+ */
114
+ getSummary() {
115
+ if (!this.session) {
116
+ return 'No active session';
117
+ }
118
+ const lines = ['## 问题回答摘要\n'];
119
+ for (const answer of this.session.answers) {
120
+ const question = this.session.questions.find(q => q.id === answer.questionId);
121
+ if (question) {
122
+ const answerText = answer.textValue ||
123
+ answer.selectedKeys.map(k => {
124
+ const opt = question.options?.find(o => o.key === k);
125
+ return opt?.label || k;
126
+ }).join(', ');
127
+ lines.push(`**${question.question}**`);
128
+ lines.push(`> ${answerText}\n`);
129
+ }
130
+ }
131
+ return lines.join('\n');
132
+ }
133
+ /**
134
+ * 生成基础问题集
135
+ */
136
+ generateBaseQuestions(task) {
137
+ const questions = [];
138
+ // 1. 核心目标
139
+ questions.push({
140
+ id: 'objective',
141
+ question: '这个任务的主要目标是什么?',
142
+ type: 'single',
143
+ required: true,
144
+ category: 'objective',
145
+ priority: 1,
146
+ options: [
147
+ { key: 'new_feature', label: '实现新功能', description: '添加新的功能特性' },
148
+ { key: 'bug_fix', label: '修复 Bug', description: '修复已知问题' },
149
+ { key: 'refactor', label: '重构优化', description: '改进代码结构或性能' },
150
+ { key: 'other', label: '其他', description: '其他类型任务' }
151
+ ],
152
+ followUpCondition: {
153
+ triggerKeys: ['other'],
154
+ followUpQuestions: [
155
+ {
156
+ id: 'objective_other_detail',
157
+ question: '请详细描述任务目标:',
158
+ type: 'text',
159
+ required: true,
160
+ category: 'objective',
161
+ priority: 1.5
162
+ }
163
+ ]
164
+ }
165
+ });
166
+ // 2. 技术栈
167
+ questions.push({
168
+ id: 'tech_stack',
169
+ question: '使用什么技术栈?',
170
+ type: 'multiple',
171
+ required: true,
172
+ category: 'technical',
173
+ priority: 2,
174
+ options: [
175
+ { key: 'typescript', label: 'TypeScript', description: '类型安全的 JavaScript' },
176
+ { key: 'javascript', label: 'JavaScript', description: '标准 JavaScript' },
177
+ { key: 'react', label: 'React', description: 'React 前端框架' },
178
+ { key: 'vue', label: 'Vue', description: 'Vue 前端框架' },
179
+ { key: 'node', label: 'Node.js', description: 'Node.js 后端' },
180
+ { key: 'python', label: 'Python', description: 'Python 语言' },
181
+ { key: 'other', label: '其他', description: '其他技术栈' }
182
+ ],
183
+ followUpCondition: {
184
+ triggerKeys: ['other'],
185
+ followUpQuestions: [
186
+ {
187
+ id: 'tech_stack_other_detail',
188
+ question: '请描述使用的技术栈:',
189
+ type: 'text',
190
+ required: true,
191
+ category: 'technical',
192
+ priority: 2.5
193
+ }
194
+ ]
195
+ }
196
+ });
197
+ // 3. 数据存储
198
+ questions.push({
199
+ id: 'data_storage',
200
+ question: '需要什么类型的存储?',
201
+ type: 'single',
202
+ required: true,
203
+ category: 'technical',
204
+ priority: 3,
205
+ options: [
206
+ { key: 'postgresql', label: 'PostgreSQL', description: '关系型数据库' },
207
+ { key: 'mongodb', label: 'MongoDB', description: '文档数据库' },
208
+ { key: 'sqlite', label: 'SQLite', description: '本地数据库' },
209
+ { key: 'none', label: '无需存储', description: '不需要数据持久化' }
210
+ ]
211
+ });
212
+ // 4. 认证方式
213
+ questions.push({
214
+ id: 'auth_method',
215
+ question: '需要用户认证吗?',
216
+ type: 'single',
217
+ required: true,
218
+ category: 'technical',
219
+ priority: 4,
220
+ options: [
221
+ { key: 'jwt', label: 'JWT Token', description: '无状态认证' },
222
+ { key: 'oauth', label: 'OAuth 2.0', description: '第三方授权' },
223
+ { key: 'session', label: 'Session Cookie', description: '传统会话' },
224
+ { key: 'none', label: '无需认证', description: '无用户系统' }
225
+ ]
226
+ });
227
+ // 5. API 风格
228
+ questions.push({
229
+ id: 'api_style',
230
+ question: 'API 采用什么风格?',
231
+ type: 'single',
232
+ required: true,
233
+ category: 'technical',
234
+ priority: 5,
235
+ options: [
236
+ { key: 'rest', label: 'RESTful', description: 'REST API' },
237
+ { key: 'graphql', label: 'GraphQL', description: 'GraphQL API' },
238
+ { key: 'grpc', label: 'gRPC', description: '高性能 RPC' },
239
+ { key: 'mixed', label: '混合', description: '多种风格混合' }
240
+ ]
241
+ });
242
+ // 6. 测试要求
243
+ questions.push({
244
+ id: 'test_coverage',
245
+ question: '测试覆盖率要求?',
246
+ type: 'single',
247
+ required: true,
248
+ category: 'quality',
249
+ priority: 6,
250
+ options: [
251
+ { key: 'high', label: '>80% (严格)', description: '完整单元测试和集成测试' },
252
+ { key: 'medium', label: '>60% (标准)', description: '核心功能测试' },
253
+ { key: 'low', label: '>40% (基础)', description: '关键路径测试' },
254
+ { key: 'none', label: '无要求', description: '不需要测试' }
255
+ ]
256
+ });
257
+ // 7. 文档要求
258
+ questions.push({
259
+ id: 'doc_level',
260
+ question: '需要什么级别的文档?',
261
+ type: 'single',
262
+ required: true,
263
+ category: 'quality',
264
+ priority: 7,
265
+ options: [
266
+ { key: 'full', label: '完整文档', description: 'API + 使用指南 + 架构' },
267
+ { key: 'basic', label: '基础文档', description: 'README + API' },
268
+ { key: 'minimal', label: '最小文档', description: '仅 README' },
269
+ { key: 'none', label: '无需文档', description: '不生成文档' }
270
+ ]
271
+ });
272
+ return questions;
273
+ }
274
+ /**
275
+ * 根据任务内容动态添加问题
276
+ */
277
+ addContextualQuestions(task, questions) {
278
+ // 如果有多个目标,询问优先级
279
+ if (task.goals.length > 1) {
280
+ questions.push({
281
+ id: 'goal_priority',
282
+ question: '以下目标中,哪些是核心必须完成的?(可多选)',
283
+ type: 'multiple',
284
+ required: true,
285
+ category: 'scope',
286
+ priority: 1.5,
287
+ options: task.goals.map((goal, index) => ({
288
+ key: `goal_${index}`,
289
+ label: goal.slice(0, 50) + (goal.length > 50 ? '...' : '')
290
+ }))
291
+ });
292
+ }
293
+ // 如果有约束条件,确认是否遵循
294
+ if (task.constraints.length > 0) {
295
+ questions.push({
296
+ id: 'constraints_confirm',
297
+ question: '请确认约束条件:',
298
+ type: 'confirm',
299
+ required: true,
300
+ category: 'constraint',
301
+ priority: 3.5,
302
+ options: [
303
+ { key: 'confirm', label: '确认遵循所有约束', description: '按照约束条件执行' },
304
+ { key: 'modify', label: '需要调整约束', description: '部分约束需要修改' },
305
+ { key: 'ignore', label: '忽略约束', description: '不遵循约束条件' }
306
+ ]
307
+ });
308
+ }
309
+ return questions;
310
+ }
311
+ }
312
+ exports.InteractiveQuestionGenerator = InteractiveQuestionGenerator;