openmatrix 0.1.49 → 0.1.50

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.
@@ -58,11 +58,9 @@ class SmartQuestionAnalyzer {
58
58
  async analyze(taskDescription, parsedTask) {
59
59
  // 1. 获取项目上下文
60
60
  const projectContext = await this.getProjectContext();
61
- // 2. 分析任务理解
62
- const understanding = this.analyzeTaskUnderstanding(taskDescription, projectContext);
63
- // 3. 执行推断
61
+ // 2. 执行推断
64
62
  const inferences = this.inferAnswers(taskDescription, projectContext);
65
- // 4. 筛选需要提问的问题
63
+ // 3. 筛选需要提问的问题
66
64
  const questionsToAsk = inferences
67
65
  .filter(i => i.confidence === 'low' || !i.inferredAnswer)
68
66
  .map(i => i.questionId);
@@ -70,7 +68,6 @@ class SmartQuestionAnalyzer {
70
68
  .filter(i => i.confidence !== 'low' && i.inferredAnswer)
71
69
  .map(i => i.questionId);
72
70
  return {
73
- understanding,
74
71
  inferences,
75
72
  questionsToAsk,
76
73
  skippedQuestions,
@@ -163,199 +160,6 @@ class SmartQuestionAnalyzer {
163
160
  this.cachedContext = context;
164
161
  return context;
165
162
  }
166
- /**
167
- * 分析任务理解
168
- */
169
- analyzeTaskUnderstanding(taskDescription, context) {
170
- const desc = taskDescription.toLowerCase();
171
- // 1. 判断任务类型
172
- const taskType = this.detectTaskType(desc);
173
- // 2. 判断影响范围
174
- const scope = this.detectScope(desc, context);
175
- // 3. 判断复杂度
176
- const complexity = this.detectComplexity(desc, taskType, scope);
177
- // 4. 生成建议
178
- const suggestions = this.generateSuggestions(taskType, complexity, desc);
179
- return {
180
- taskType: taskType.type,
181
- taskTypeLabel: taskType.label,
182
- scope: scope.areas,
183
- scopeLabel: scope.label,
184
- complexity: complexity.level,
185
- complexityLabel: complexity.label,
186
- estimatedCommits: complexity.estimatedCommits,
187
- suggestions
188
- };
189
- }
190
- /**
191
- * 检测任务类型
192
- */
193
- detectTaskType(desc) {
194
- // Bug 修复
195
- if (/(fix|bug|修复|hotfix|patch|问题|报错|错误|异常)/i.test(desc)) {
196
- return { type: 'bugfix', label: 'Bug 修复' };
197
- }
198
- // 重构
199
- if (/(refactor|重构|优化|improve|改进)/i.test(desc)) {
200
- return { type: 'refactor', label: '重构优化' };
201
- }
202
- // 文档
203
- if (/(doc|文档|readme|文档|注释)/i.test(desc)) {
204
- return { type: 'docs', label: '文档编写' };
205
- }
206
- // 测试
207
- if (/(test|测试|单元|unit|coverage|覆盖率)/i.test(desc)) {
208
- return { type: 'test', label: '测试编写' };
209
- }
210
- // 配置
211
- if (/(config|配置|设置|setup|初始化)/i.test(desc)) {
212
- return { type: 'config', label: '配置修改' };
213
- }
214
- // 新功能 (默认)
215
- if (/(implement|add|新功能|实现|开发|feature|添加|创建)/i.test(desc)) {
216
- return { type: 'feature', label: '新功能开发' };
217
- }
218
- return { type: 'unknown', label: '待确认' };
219
- }
220
- /**
221
- * 检测影响范围
222
- */
223
- detectScope(desc, context) {
224
- const areas = [];
225
- // 从描述中检测
226
- if (/(前端|页面|ui|样式|css|html|react|vue|component)/i.test(desc)) {
227
- areas.push('前端');
228
- }
229
- if (/(后端|api|服务|server|接口|数据库|database)/i.test(desc)) {
230
- areas.push('后端');
231
- }
232
- if (/(cli|命令行|终端|terminal)/i.test(desc)) {
233
- areas.push('CLI');
234
- }
235
- if (/(测试|test|spec)/i.test(desc)) {
236
- areas.push('测试');
237
- }
238
- if (/(文档|doc|readme)/i.test(desc)) {
239
- areas.push('文档');
240
- }
241
- if (/(配置|config)/i.test(desc)) {
242
- areas.push('配置');
243
- }
244
- // 从项目上下文补充
245
- if (areas.length === 0) {
246
- if (context.hasFrontend)
247
- areas.push('前端');
248
- if (context.hasBackend)
249
- areas.push('后端');
250
- }
251
- // 默认
252
- if (areas.length === 0) {
253
- areas.push('代码');
254
- }
255
- const label = areas.join('、');
256
- return { areas, label };
257
- }
258
- /**
259
- * 检测复杂度
260
- */
261
- detectComplexity(desc, taskType, scope) {
262
- // 简单任务关键词
263
- const simpleKeywords = /(fix|bug|修复|改|调整|样式|变量名|文案|按钮|颜色|字体)/i;
264
- // 复杂任务关键词 - 需要更精确
265
- const complexKeywords = /(系统|架构|集成|完整|从零|优化整体|多模块|全栈)/i;
266
- const multiScope = scope.areas.length >= 3;
267
- // Bug 修复
268
- if (taskType.type === 'bugfix') {
269
- if (simpleKeywords.test(desc) || desc.length < 50) {
270
- return { level: 'simple', label: '简单', estimatedCommits: '预计 1 个 commit' };
271
- }
272
- return { level: 'medium', label: '中等', estimatedCommits: '预计 1-2 个 commit' };
273
- }
274
- // 文档、配置
275
- if (taskType.type === 'docs' || taskType.type === 'config') {
276
- return { level: 'simple', label: '简单', estimatedCommits: '预计 1 个 commit' };
277
- }
278
- // 测试
279
- if (taskType.type === 'test') {
280
- if (multiScope) {
281
- return { level: 'medium', label: '中等', estimatedCommits: '预计 2-3 个 commit' };
282
- }
283
- return { level: 'simple', label: '简单', estimatedCommits: '预计 1 个 commit' };
284
- }
285
- // 复杂关键词检测
286
- if (complexKeywords.test(desc) || multiScope) {
287
- return { level: 'complex', label: '复杂', estimatedCommits: '预计 3+ 个 commit' };
288
- }
289
- // 新功能 - 默认 medium
290
- if (taskType.type === 'feature') {
291
- // 只有非常简单的单文件修改才判断为 simple
292
- if (desc.length < 20 && scope.areas.length === 1 && /(按钮|链接|文案|颜色)/.test(desc)) {
293
- return { level: 'simple', label: '简单', estimatedCommits: '预计 1 个 commit' };
294
- }
295
- if (desc.length > 100 || scope.areas.length >= 2) {
296
- return { level: 'medium', label: '中等', estimatedCommits: '预计 2-3 个 commit' };
297
- }
298
- return { level: 'medium', label: '中等', estimatedCommits: '预计 2-3 个 commit' };
299
- }
300
- // 重构 - 默认 medium
301
- if (taskType.type === 'refactor') {
302
- if (multiScope || /(整体|全部|系统)/.test(desc)) {
303
- return { level: 'complex', label: '复杂', estimatedCommits: '预计 3+ 个 commit' };
304
- }
305
- return { level: 'medium', label: '中等', estimatedCommits: '预计 2-3 个 commit' };
306
- }
307
- // 默认中等
308
- return { level: 'medium', label: '中等', estimatedCommits: '预计 1-2 个 commit' };
309
- }
310
- /**
311
- * 生成建议
312
- */
313
- generateSuggestions(taskType, complexity, desc) {
314
- const suggestions = [];
315
- // 复杂任务优先建议头脑风暴
316
- if (complexity.level === 'complex') {
317
- suggestions.push('建议先头脑风暴,明确需求');
318
- }
319
- // 根据任务类型建议
320
- switch (taskType.type) {
321
- case 'bugfix':
322
- suggestions.push('直接修复,无需 TDD');
323
- suggestions.push('使用 fast 模式');
324
- break;
325
- case 'feature':
326
- if (complexity.level === 'complex') {
327
- suggestions.push('使用 strict 模式保证质量');
328
- }
329
- else {
330
- suggestions.push('使用 balanced 模式');
331
- }
332
- break;
333
- case 'refactor':
334
- suggestions.push('确保测试覆盖');
335
- suggestions.push('使用 balanced 模式');
336
- break;
337
- case 'test':
338
- suggestions.push('使用 fast 或 balanced 模式');
339
- break;
340
- case 'docs':
341
- suggestions.push('无需测试');
342
- suggestions.push('使用 fast 模式');
343
- break;
344
- case 'config':
345
- suggestions.push('注意配置安全');
346
- suggestions.push('使用 fast 模式');
347
- break;
348
- default:
349
- if (complexity.level !== 'complex') {
350
- suggestions.push('根据实际情况选择模式');
351
- }
352
- }
353
- // 确保至少有一个建议
354
- if (suggestions.length === 0) {
355
- suggestions.push('建议先确认任务需求');
356
- }
357
- return suggestions;
358
- }
359
163
  /**
360
164
  * 推断问题答案
361
165
  */
@@ -584,21 +388,7 @@ class SmartQuestionAnalyzer {
584
388
  * 生成推断摘要
585
389
  */
586
390
  generateSummary(result) {
587
- const lines = [];
588
- // 任务理解
589
- lines.push('🔍 我理解的任务:\n');
590
- lines.push(`📋 类型: ${result.understanding.taskTypeLabel}`);
591
- lines.push(`📁 范围: ${result.understanding.scopeLabel}`);
592
- lines.push(`⚡ 复杂度: ${result.understanding.complexityLabel} (${result.understanding.estimatedCommits})`);
593
- // 建议
594
- if (result.understanding.suggestions.length > 0) {
595
- lines.push('\n💡 建议执行方式:');
596
- for (const suggestion of result.understanding.suggestions) {
597
- lines.push(` • ${suggestion}`);
598
- }
599
- }
600
- // 推断结果
601
- lines.push('\n📊 配置推断:');
391
+ const lines = ['📊 AI 推断结果:\n'];
602
392
  for (const inference of result.inferences) {
603
393
  const icon = inference.confidence === 'high' ? '✅' :
604
394
  inference.confidence === 'medium' ? '🤔' : '❓';
@@ -606,55 +396,15 @@ class SmartQuestionAnalyzer {
606
396
  ? inference.inferredAnswer.join(', ')
607
397
  : inference.inferredAnswer || '待确认';
608
398
  lines.push(`${icon} ${inference.questionId}: ${answer}`);
609
- }
610
- if (result.questionsToAsk.length > 0) {
611
- lines.push(`\n❓ 需要确认: ${result.questionsToAsk.join(', ')}`);
612
- }
613
- else {
614
- lines.push('\n✅ 配置已推断,可直接执行');
615
- }
616
- return lines.join('\n');
617
- }
618
- /**
619
- * 生成 Markdown 格式输出
620
- */
621
- generateMarkdown(result) {
622
- const lines = [];
623
- lines.push('## 🔍 我理解的任务\n');
624
- lines.push(`| 属性 | 值 |`);
625
- lines.push(`|------|-----|`);
626
- lines.push(`| 📋 类型 | ${result.understanding.taskTypeLabel} |`);
627
- lines.push(`| 📁 范围 | ${result.understanding.scopeLabel} |`);
628
- lines.push(`| ⚡ 复杂度 | ${result.understanding.complexityLabel} |`);
629
- lines.push(`| ⏱️ 预计 | ${result.understanding.estimatedCommits} |`);
630
- // 建议
631
- if (result.understanding.suggestions.length > 0) {
632
- lines.push('\n## 💡 建议执行方式\n');
633
- for (const suggestion of result.understanding.suggestions) {
634
- lines.push(`- ${suggestion}`);
399
+ if (inference.reason) {
400
+ lines.push(` └─ ${inference.reason}`);
635
401
  }
636
402
  }
637
- // 推断的配置
638
- lines.push('\n## 📊 推荐配置\n');
639
- lines.push(`| 配置项 | 推荐值 | 置信度 |`);
640
- lines.push(`|--------|--------|--------|`);
641
- for (const inference of result.inferences) {
642
- const answer = Array.isArray(inference.inferredAnswer)
643
- ? inference.inferredAnswer.join(', ')
644
- : inference.inferredAnswer || '待确认';
645
- const confidenceIcon = inference.confidence === 'high' ? '✅' :
646
- inference.confidence === 'medium' ? '🤔' : '❓';
647
- lines.push(`| ${inference.questionId} | ${answer} | ${confidenceIcon} |`);
648
- }
649
- // 需要确认的问题
650
403
  if (result.questionsToAsk.length > 0) {
651
- lines.push('\n## 需要确认\n');
652
- for (const q of result.questionsToAsk) {
653
- lines.push(`- ${q}`);
654
- }
404
+ lines.push(`\n❓ 需要确认的问题: ${result.questionsToAsk.join(', ')}`);
655
405
  }
656
406
  else {
657
- lines.push('\n✅ **所有配置已推断,可直接执行**');
407
+ lines.push('\n✅ 所有问题已推断,无需额外确认');
658
408
  }
659
409
  return lines.join('\n');
660
410
  }
@@ -1,12 +1,4 @@
1
1
  import type { ParsedTask } from '../types/index.js';
2
- /**
3
- * TaskParser - 任务解析器
4
- *
5
- * 职责:解析用户输入的任务描述,提取结构化信息
6
- *
7
- * 注意:TaskParser 只负责格式解析,不做业务逻辑判断
8
- * 任务拆解的智能逻辑应该由 TaskPlanner (调用 AI) 来完成
9
- */
10
2
  export declare class TaskParser {
11
3
  parse(content: string): ParsedTask;
12
4
  private extractTitle;
@@ -1,14 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TaskParser = void 0;
4
- /**
5
- * TaskParser - 任务解析器
6
- *
7
- * 职责:解析用户输入的任务描述,提取结构化信息
8
- *
9
- * 注意:TaskParser 只负责格式解析,不做业务逻辑判断
10
- * 任务拆解的智能逻辑应该由 TaskPlanner (调用 AI) 来完成
11
- */
12
4
  class TaskParser {
13
5
  parse(content) {
14
6
  const title = this.extractTitle(content);
@@ -26,43 +18,38 @@ class TaskParser {
26
18
  };
27
19
  }
28
20
  extractTitle(content) {
29
- // 1. 从第一个 # 标题提取
30
- const headerMatch = content.match(/^#\s+(.+)$/m);
31
- if (headerMatch) {
32
- return headerMatch[1].trim();
33
- }
34
- // 2. 没有标题,取第一行非空内容(截断到 50 字符)
35
- const firstLine = content.split('\n').find(l => l.trim());
36
- return firstLine ? firstLine.trim().slice(0, 50) : 'Untitled Task';
21
+ const match = content.match(/^#\s+(.+)$/m);
22
+ return match ? match[1].trim() : 'Untitled Task';
37
23
  }
38
24
  extractDescription(content) {
39
- // 移除标题和 sections,获取第一段
25
+ // Remove title and sections, get first paragraph
40
26
  let desc = content
41
27
  .replace(/^#\s+.+$/m, '')
42
28
  .replace(/^##\s+.+$/gm, '')
43
29
  .replace(/^- .+$/gm, '')
44
30
  .trim();
45
- // 获取第一个非空行
31
+ // Get first non-empty line
46
32
  const lines = desc.split('\n').filter(l => l.trim());
47
33
  return lines.length > 0 ? lines[0].trim() : '';
48
34
  }
49
35
  extractSection(content, sectionName) {
36
+ // Split content into lines and find the section
50
37
  const lines = content.split('\n');
51
38
  const items = [];
52
39
  let inSection = false;
53
40
  for (const line of lines) {
54
- // 检查是否进入目标 section
41
+ // Check if we're entering the target section
55
42
  if (line.match(new RegExp(`^##\\s+${sectionName}\\s*$`))) {
56
43
  inSection = true;
57
44
  continue;
58
45
  }
59
- // 检查是否进入其他 section
46
+ // Check if we've hit another section
60
47
  if (line.match(/^##\s+/)) {
61
48
  if (inSection)
62
- break;
49
+ break; // Exit if we were in the target section
63
50
  continue;
64
51
  }
65
- // 提取列表项
52
+ // Extract list items if we're in the target section
66
53
  if (inSection) {
67
54
  const itemMatch = line.match(/^-\s+(.+)$/);
68
55
  if (itemMatch) {
@@ -17,34 +17,69 @@ export interface UserAnswers {
17
17
  testCoverage?: string;
18
18
  documentationLevel?: string;
19
19
  additionalContext?: Record<string, string>;
20
+ /** 是否启用 E2E 测试 */
21
+ e2eTests?: boolean;
22
+ /** E2E 测试类型 (web/mobile/gui) */
23
+ e2eType?: 'web' | 'mobile' | 'gui';
20
24
  }
21
25
  /**
22
26
  * TaskPlanner - 任务拆解器
23
27
  *
24
- * 1. 按 goals 拆分为多个 coder + tester 任务对
25
- * 2. goals 为空时退化为 3 任务模式 (planner → coder → tester)
26
- * 3. 自动注入用户上下文和验收标准
28
+ * 增强版特性:
29
+ * 1. 更细粒度的任务拆分 (每个目标拆分为设计+实现+测试)
30
+ * 2. 测试任务配对 (每个开发任务自动生成对应测试任务)
31
+ * 3. 验收标准注入 (从用户回答中提取)
32
+ * 4. 用户上下文注入 (将用户回答注入任务描述)
33
+ * 5. 依赖关系分析 (自动分析任务间依赖)
27
34
  */
28
35
  export declare class TaskPlanner {
36
+ private userAnswers;
37
+ constructor(userAnswers?: UserAnswers);
38
+ /**
39
+ * 设置用户回答
40
+ */
41
+ setUserAnswers(answers: UserAnswers): void;
29
42
  /**
30
43
  * Break down a parsed task into sub-tasks
44
+ *
45
+ * 增强版: 生成更细粒度的任务,包含设计、开发、测试配对
31
46
  */
32
47
  breakdown(parsedTask: ParsedTask, answers: Record<string, string>): TaskBreakdown[];
33
48
  /**
34
- * 按 goals 拆分: 每个 goal 一个 coder + 一个 tester
49
+ * 提取用户上下文
35
50
  */
36
- private breakdownByGoals;
51
+ private extractUserContext;
37
52
  /**
38
- * 无 goals 时的退化模式: planner → coder → tester
39
- * 把 rawContent 整体交给 planner 分析,生成 PLAN.md
40
- * coder 基于 PLAN.md 实现
53
+ * 解析数组类型的回答
41
54
  */
42
- private breakdownFallback;
43
- private extractUserContext;
44
55
  private parseArrayAnswer;
56
+ /**
57
+ * 构建任务描述 (注入用户上下文)
58
+ */
45
59
  private buildTaskDescription;
60
+ /**
61
+ * 构建测试任务描述
62
+ */
46
63
  private buildTestDescription;
64
+ /**
65
+ * 构建 E2E 测试任务描述
66
+ */
67
+ private buildE2ETestDescription;
68
+ /**
69
+ * 获取 E2E 测试类型配置
70
+ */
71
+ private getE2ETypeConfig;
72
+ /**
73
+ * 生成用户流程测试用例
74
+ */
75
+ private generateUserFlows;
76
+ /**
77
+ * 解析覆盖率数值
78
+ */
47
79
  private parseCoverage;
80
+ /**
81
+ * 生成验收标准
82
+ */
48
83
  private generateAcceptanceCriteria;
49
84
  private generateTaskId;
50
85
  private determinePriority;