openmatrix 0.2.14 → 0.2.16
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/dist/agents/agent-runner.d.ts +4 -0
- package/dist/agents/agent-runner.js +86 -0
- package/dist/orchestrator/executor.d.ts +32 -2
- package/dist/orchestrator/executor.js +119 -1
- package/dist/orchestrator/meeting-manager.d.ts +16 -1
- package/dist/orchestrator/meeting-manager.js +113 -0
- package/dist/types/index.d.ts +66 -1
- package/package.json +2 -1
- package/skills/auto.md +64 -3
- package/skills/debug.md +1 -1
- package/skills/feature.md +229 -64
- package/skills/resume-feature.md +227 -0
- package/skills/start.md +66 -3
|
@@ -136,8 +136,11 @@ class AgentRunner {
|
|
|
136
136
|
const agentPrompt = this.buildAgentPrompt(task);
|
|
137
137
|
const phaseContext = this.buildPhaseContext(task);
|
|
138
138
|
const accumulatedContext = await this.buildAccumulatedContext(task);
|
|
139
|
+
const ambiguityInstruction = this.buildAmbiguityDetectionInstruction(task);
|
|
139
140
|
return `# 任务执行
|
|
140
141
|
|
|
142
|
+
${ambiguityInstruction}
|
|
143
|
+
|
|
141
144
|
## 任务信息
|
|
142
145
|
- ID: ${task.id}
|
|
143
146
|
- 标题: ${task.title}
|
|
@@ -172,6 +175,89 @@ ${agentPrompt.instructions}
|
|
|
172
175
|
注意: 任务完成后,由 Skill 调用 \`openmatrix complete\` 并传入 --summary 参数,
|
|
173
176
|
该摘要会自动追加到全局 \`.openmatrix/context.md\` 供后续 Agent 参考。
|
|
174
177
|
`;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 构建歧义检测指令
|
|
181
|
+
*/
|
|
182
|
+
buildAmbiguityDetectionInstruction(task) {
|
|
183
|
+
return `## 🚨 歧义检测指令(必须在执行前完成)
|
|
184
|
+
|
|
185
|
+
在开始执行任务之前,你必须完成歧义检测。检测以下 5 种歧义类型:
|
|
186
|
+
|
|
187
|
+
### 检测清单
|
|
188
|
+
|
|
189
|
+
1. **需求歧义** (requirement)
|
|
190
|
+
- 任务描述是否清晰可理解?
|
|
191
|
+
- 是否有缺少的关键信息?
|
|
192
|
+
- 验收标准是否明确?
|
|
193
|
+
|
|
194
|
+
2. **技术歧义** (technical)
|
|
195
|
+
- 技术选型是否明确?
|
|
196
|
+
- 实现方案是否有多种选择?
|
|
197
|
+
- 是否需要特定的技术决策?
|
|
198
|
+
|
|
199
|
+
3. **依赖歧义** (dependency)
|
|
200
|
+
- 依赖任务是否已完成?
|
|
201
|
+
- 依赖代码是否可找到?
|
|
202
|
+
- 是否有缺失的依赖项?
|
|
203
|
+
|
|
204
|
+
4. **验收歧义** (acceptance)
|
|
205
|
+
- 验收标准是否明确?
|
|
206
|
+
- 成功定义是否清晰?
|
|
207
|
+
- 是否有模糊的边界条件?
|
|
208
|
+
|
|
209
|
+
5. **测试结果歧义** (test_result)
|
|
210
|
+
- 测试失败原因是否明确?
|
|
211
|
+
- 测试通过是否可信?
|
|
212
|
+
- 是否需要额外的验证?
|
|
213
|
+
|
|
214
|
+
### 严重程度定义
|
|
215
|
+
|
|
216
|
+
| 级别 | 说明 | 处理方式 |
|
|
217
|
+
|-----|------|---------|
|
|
218
|
+
| **Critical** | 无法继续执行,必须澄清 | 立即报告,等待澄清 |
|
|
219
|
+
| **High** | 可能导致错误结果 | 报告并建议处理方案 |
|
|
220
|
+
| **Medium** | 影响执行效率 | 记录并尝试解决 |
|
|
221
|
+
| **Low** | 轻微不确定性 | 继续执行,备注说明 |
|
|
222
|
+
|
|
223
|
+
### 输出格式
|
|
224
|
+
|
|
225
|
+
如果检测到歧义,在任务执行前输出:
|
|
226
|
+
\`\`\`xml
|
|
227
|
+
<ambiguity_report>
|
|
228
|
+
{
|
|
229
|
+
"hasAmbiguity": true,
|
|
230
|
+
"taskId": "${task.id}",
|
|
231
|
+
"detectionPhase": "pre_execution",
|
|
232
|
+
"ambiguities": [
|
|
233
|
+
{
|
|
234
|
+
"type": "requirement|technical|dependency|acceptance|test_result",
|
|
235
|
+
"severity": "Critical|High|Medium|Low",
|
|
236
|
+
"description": "歧义描述",
|
|
237
|
+
"suggestedResolution": "建议的处理方案"
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
"maxSeverity": "Critical|High|Medium|Low",
|
|
241
|
+
"suggestedStrategy": "ask_immediate|write_meeting|continue",
|
|
242
|
+
"detectedAt": "<ISO timestamp>"
|
|
243
|
+
}
|
|
244
|
+
</ambiguity_report>
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
如果没有歧义,输出:
|
|
248
|
+
\`\`\`xml
|
|
249
|
+
<ambiguity_report>
|
|
250
|
+
{ "hasAmbiguity": false }
|
|
251
|
+
</ambiguity_report>
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
### 处理策略
|
|
255
|
+
|
|
256
|
+
- **Critical/High**: 输出报告后暂停,等待用户决策
|
|
257
|
+
- **Medium**: 输出报告后继续执行,采用合理假设
|
|
258
|
+
- **Low**: 记录并继续执行
|
|
259
|
+
|
|
260
|
+
**重要**: 如果无法解析歧义检测结果,视为无歧义继续执行。`;
|
|
175
261
|
}
|
|
176
262
|
/**
|
|
177
263
|
* 构建累积上下文 - 从全局 context.md 读取前序 Agent 的决策和知识
|
|
@@ -4,6 +4,7 @@ import type { SubagentTask } from '../types/index.js';
|
|
|
4
4
|
import { StateManager } from '../storage/state-manager.js';
|
|
5
5
|
import { ApprovalManager } from './approval-manager.js';
|
|
6
6
|
import { PhaseExecutor } from './phase-executor.js';
|
|
7
|
+
import type { AmbiguityReport } from '../types/index.js';
|
|
7
8
|
export interface ExecutorConfig {
|
|
8
9
|
maxConcurrent: number;
|
|
9
10
|
taskTimeout: number;
|
|
@@ -16,7 +17,7 @@ export interface ExecutorStatus {
|
|
|
16
17
|
waitingApprovals: number;
|
|
17
18
|
}
|
|
18
19
|
export interface ExecutionResult {
|
|
19
|
-
status: 'continue' | 'waiting_approval' | 'completed' | 'failed';
|
|
20
|
+
status: 'continue' | 'waiting_approval' | 'completed' | 'failed' | 'ambiguity_ask_user';
|
|
20
21
|
subagentTasks: SubagentTask[];
|
|
21
22
|
message: string;
|
|
22
23
|
statistics: {
|
|
@@ -26,6 +27,8 @@ export interface ExecutionResult {
|
|
|
26
27
|
pending: number;
|
|
27
28
|
failed: number;
|
|
28
29
|
};
|
|
30
|
+
/** 歧义报告 (仅 status 为 'ambiguity_ask_user' 时存在) */
|
|
31
|
+
ambiguityReport?: AmbiguityReport;
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* OrchestratorExecutor - 执行循环核心
|
|
@@ -41,6 +44,7 @@ export declare class OrchestratorExecutor {
|
|
|
41
44
|
private phaseExecutor;
|
|
42
45
|
private retryManager;
|
|
43
46
|
private aiReviewer;
|
|
47
|
+
private meetingManager;
|
|
44
48
|
private config;
|
|
45
49
|
private taskTimers;
|
|
46
50
|
constructor(stateManager: StateManager, approvalManager: ApprovalManager, config?: Partial<ExecutorConfig>);
|
|
@@ -94,7 +98,9 @@ export declare class OrchestratorExecutor {
|
|
|
94
98
|
/**
|
|
95
99
|
* 标记任务完成
|
|
96
100
|
*
|
|
97
|
-
*
|
|
101
|
+
* 增强:
|
|
102
|
+
* 1. 对于 reviewer 任务,自动解析 Review 报告并生成修复任务
|
|
103
|
+
* 2. 解析歧义报告并根据执行模式处理
|
|
98
104
|
*/
|
|
99
105
|
completeTask(taskId: string, result: {
|
|
100
106
|
success: boolean;
|
|
@@ -102,6 +108,10 @@ export declare class OrchestratorExecutor {
|
|
|
102
108
|
error?: string;
|
|
103
109
|
}): Promise<{
|
|
104
110
|
createdFixTasks?: string[];
|
|
111
|
+
ambiguityResult?: {
|
|
112
|
+
status: 'ambiguity_ask_user' | 'ambiguity_handled';
|
|
113
|
+
report: AmbiguityReport;
|
|
114
|
+
};
|
|
105
115
|
}>;
|
|
106
116
|
/**
|
|
107
117
|
* 处理 Review 结果:解析报告,如有 critical/major 问题则自动创建修复任务
|
|
@@ -111,6 +121,26 @@ export declare class OrchestratorExecutor {
|
|
|
111
121
|
* 获取当前阶段
|
|
112
122
|
*/
|
|
113
123
|
private getCurrentPhase;
|
|
124
|
+
/**
|
|
125
|
+
* 解析歧义报告
|
|
126
|
+
*
|
|
127
|
+
* 从 Agent 输出中提取歧义报告 JSON
|
|
128
|
+
* 支持多种标记格式:
|
|
129
|
+
* - <ambiguity_report>...</ambiguity_report>
|
|
130
|
+
* - AMBIGUITY_REPORT: {...}
|
|
131
|
+
* - 直接 JSON 块
|
|
132
|
+
*/
|
|
133
|
+
private parseAmbiguityReport;
|
|
134
|
+
/**
|
|
135
|
+
* 处理歧义
|
|
136
|
+
*
|
|
137
|
+
* 根据执行模式和严重程度选择处理策略:
|
|
138
|
+
* - auto 模式:所有歧义写入 Meeting,继续执行
|
|
139
|
+
* - 其他模式:
|
|
140
|
+
* - Critical/High:返回 ambiguity_ask_user 状态,让 Skill 层用 AskUserQuestion 处理
|
|
141
|
+
* - Medium/Low:写入 Meeting,继续执行
|
|
142
|
+
*/
|
|
143
|
+
private handleAmbiguity;
|
|
114
144
|
/**
|
|
115
145
|
* 获取执行器状态
|
|
116
146
|
*/
|
|
@@ -8,6 +8,7 @@ const state_machine_js_1 = require("./state-machine.js");
|
|
|
8
8
|
const phase_executor_js_1 = require("./phase-executor.js");
|
|
9
9
|
const retry_manager_js_1 = require("./retry-manager.js");
|
|
10
10
|
const ai_reviewer_js_1 = require("./ai-reviewer.js");
|
|
11
|
+
const meeting_manager_js_1 = require("./meeting-manager.js");
|
|
11
12
|
const logger_js_1 = require("../utils/logger.js");
|
|
12
13
|
/**
|
|
13
14
|
* OrchestratorExecutor - 执行循环核心
|
|
@@ -23,11 +24,13 @@ class OrchestratorExecutor {
|
|
|
23
24
|
phaseExecutor;
|
|
24
25
|
retryManager;
|
|
25
26
|
aiReviewer;
|
|
27
|
+
meetingManager;
|
|
26
28
|
config;
|
|
27
29
|
taskTimers = new Map();
|
|
28
30
|
constructor(stateManager, approvalManager, config) {
|
|
29
31
|
this.stateManager = stateManager;
|
|
30
32
|
this.approvalManager = approvalManager;
|
|
33
|
+
this.meetingManager = new meeting_manager_js_1.MeetingManager(stateManager, approvalManager);
|
|
31
34
|
// 从 state.config 读取 taskTimeout,如果未定义则使用默认值
|
|
32
35
|
const stateConfig = stateManager.getState().then(s => s.config).catch(() => null);
|
|
33
36
|
const defaultTaskTimeout = 600000; // 10 分钟(毫秒)
|
|
@@ -265,13 +268,25 @@ class OrchestratorExecutor {
|
|
|
265
268
|
/**
|
|
266
269
|
* 标记任务完成
|
|
267
270
|
*
|
|
268
|
-
*
|
|
271
|
+
* 增强:
|
|
272
|
+
* 1. 对于 reviewer 任务,自动解析 Review 报告并生成修复任务
|
|
273
|
+
* 2. 解析歧义报告并根据执行模式处理
|
|
269
274
|
*/
|
|
270
275
|
async completeTask(taskId, result) {
|
|
271
276
|
const task = await this.stateManager.getTask(taskId);
|
|
272
277
|
if (!task) {
|
|
273
278
|
throw new Error(`Task ${taskId} not found`);
|
|
274
279
|
}
|
|
280
|
+
// 检查输出中是否包含歧义报告(仅匹配 XML 标签作为唯一触发标记)
|
|
281
|
+
if (result.output?.includes('<ambiguity_report>')) {
|
|
282
|
+
const ambiguityReport = this.parseAmbiguityReport(taskId, result.output);
|
|
283
|
+
if (ambiguityReport?.hasAmbiguity) {
|
|
284
|
+
const ambiguityResult = await this.handleAmbiguity(task, ambiguityReport);
|
|
285
|
+
if (ambiguityResult) {
|
|
286
|
+
return { ambiguityResult };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
275
290
|
if (result.success) {
|
|
276
291
|
// 清除超时计时器
|
|
277
292
|
this.clearTaskTimeout(taskId);
|
|
@@ -370,6 +385,109 @@ class OrchestratorExecutor {
|
|
|
370
385
|
return 'verify';
|
|
371
386
|
return 'accept';
|
|
372
387
|
}
|
|
388
|
+
// ============ Ambiguity Management ============
|
|
389
|
+
/**
|
|
390
|
+
* 解析歧义报告
|
|
391
|
+
*
|
|
392
|
+
* 从 Agent 输出中提取歧义报告 JSON
|
|
393
|
+
* 支持多种标记格式:
|
|
394
|
+
* - <ambiguity_report>...</ambiguity_report>
|
|
395
|
+
* - AMBIGUITY_REPORT: {...}
|
|
396
|
+
* - 直接 JSON 块
|
|
397
|
+
*/
|
|
398
|
+
parseAmbiguityReport(taskId, output) {
|
|
399
|
+
try {
|
|
400
|
+
// 尝试提取 XML 标记格式
|
|
401
|
+
const xmlMatch = output.match(/<ambiguity_report>([\s\S]*?)<\/ambiguity_report>/);
|
|
402
|
+
if (xmlMatch) {
|
|
403
|
+
const jsonStr = xmlMatch[1].trim();
|
|
404
|
+
const report = JSON.parse(jsonStr);
|
|
405
|
+
return { ...report, taskId };
|
|
406
|
+
}
|
|
407
|
+
// 尝试提取 AMBIGUITY_REPORT: 格式
|
|
408
|
+
const prefixMatch = output.match(/AMBIGUITY_REPORT:\s*([\s\S]*?)(?:\n\n|\n---|$)/);
|
|
409
|
+
if (prefixMatch) {
|
|
410
|
+
const jsonStr = prefixMatch[1].trim();
|
|
411
|
+
const report = JSON.parse(jsonStr);
|
|
412
|
+
return { ...report, taskId };
|
|
413
|
+
}
|
|
414
|
+
// 尝试查找包含 hasAmbiguity 的 JSON 块(平衡括号匹配,作为最后兜底)
|
|
415
|
+
const hasAmbiguityIdx = output.indexOf('"hasAmbiguity"');
|
|
416
|
+
if (hasAmbiguityIdx !== -1) {
|
|
417
|
+
// 向前扫描找到深度为 1 的最外层 {
|
|
418
|
+
let start = -1;
|
|
419
|
+
let depth = 0;
|
|
420
|
+
for (let i = hasAmbiguityIdx; i >= 0; i--) {
|
|
421
|
+
if (output[i] === '}')
|
|
422
|
+
depth++;
|
|
423
|
+
else if (output[i] === '{') {
|
|
424
|
+
depth--;
|
|
425
|
+
if (depth < 0) {
|
|
426
|
+
start = i;
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (start !== -1) {
|
|
432
|
+
let d = 0;
|
|
433
|
+
let end = -1;
|
|
434
|
+
for (let i = start; i < output.length; i++) {
|
|
435
|
+
if (output[i] === '{')
|
|
436
|
+
d++;
|
|
437
|
+
else if (output[i] === '}') {
|
|
438
|
+
d--;
|
|
439
|
+
if (d === 0) {
|
|
440
|
+
end = i;
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (end !== -1) {
|
|
446
|
+
const report = JSON.parse(output.slice(start, end + 1));
|
|
447
|
+
return { ...report, taskId };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
console.warn(`⚠️ 解析歧义报告失败: ${taskId}`, error);
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* 处理歧义
|
|
460
|
+
*
|
|
461
|
+
* 根据执行模式和严重程度选择处理策略:
|
|
462
|
+
* - auto 模式:所有歧义写入 Meeting,继续执行
|
|
463
|
+
* - 其他模式:
|
|
464
|
+
* - Critical/High:返回 ambiguity_ask_user 状态,让 Skill 层用 AskUserQuestion 处理
|
|
465
|
+
* - Medium/Low:写入 Meeting,继续执行
|
|
466
|
+
*/
|
|
467
|
+
async handleAmbiguity(task, report) {
|
|
468
|
+
const state = await this.stateManager.getState();
|
|
469
|
+
const mode = state.config.approvalPoints.length === 0 ? 'auto' : 'interactive';
|
|
470
|
+
console.log(`🔍 检测到歧义: ${task.id} - 最高严重程度: ${report.maxSeverity || 'unknown'}`);
|
|
471
|
+
// auto 模式:所有歧义写入 Meeting,继续执行
|
|
472
|
+
if (mode === 'auto') {
|
|
473
|
+
await this.meetingManager.createAmbiguityMeeting(task.id, report);
|
|
474
|
+
console.log(`📝 [auto模式] 歧义已写入 Meeting,继续执行`);
|
|
475
|
+
return { status: 'ambiguity_handled', report };
|
|
476
|
+
}
|
|
477
|
+
// 其他模式:根据严重程度处理
|
|
478
|
+
const severity = report.maxSeverity;
|
|
479
|
+
if (severity === 'critical' || severity === 'high') {
|
|
480
|
+
// Critical/High: 返回特殊状态让 Skill 层用 AskUserQuestion 处理
|
|
481
|
+
console.log(`⚠️ [interactive模式] Critical/High 歧义,需用户确认`);
|
|
482
|
+
return { status: 'ambiguity_ask_user', report };
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
// Medium/Low: 写入 Meeting,继续执行
|
|
486
|
+
await this.meetingManager.createAmbiguityMeeting(task.id, report);
|
|
487
|
+
console.log(`📝 [interactive模式] Medium/Low 歧义已写入 Meeting,继续执行`);
|
|
488
|
+
return { status: 'ambiguity_handled', report };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
373
491
|
/**
|
|
374
492
|
* 获取执行器状态
|
|
375
493
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StateManager } from '../storage/state-manager.js';
|
|
2
2
|
import { ApprovalManager } from './approval-manager.js';
|
|
3
|
-
import type { Approval, Meeting } from '../types/index.js';
|
|
3
|
+
import type { Approval, Meeting, AmbiguityReport } from '../types/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* MeetingManager - Meeting 管理器
|
|
6
6
|
*
|
|
@@ -28,6 +28,21 @@ export declare class MeetingManager {
|
|
|
28
28
|
meeting: Meeting;
|
|
29
29
|
approval: Approval;
|
|
30
30
|
}>;
|
|
31
|
+
/**
|
|
32
|
+
* 获取严重程度对应的图标和标题前缀
|
|
33
|
+
*/
|
|
34
|
+
private getSeverityPrefix;
|
|
35
|
+
/**
|
|
36
|
+
* 格式化歧义报告为 Markdown 描述
|
|
37
|
+
*/
|
|
38
|
+
private formatAmbiguityReport;
|
|
39
|
+
/**
|
|
40
|
+
* 创建歧义 Meeting
|
|
41
|
+
*/
|
|
42
|
+
createAmbiguityMeeting(taskId: string, ambiguityReport: AmbiguityReport): Promise<{
|
|
43
|
+
meeting: Meeting;
|
|
44
|
+
approval: Approval;
|
|
45
|
+
}>;
|
|
31
46
|
/**
|
|
32
47
|
* 开始 Meeting
|
|
33
48
|
*/
|
|
@@ -104,6 +104,119 @@ ${options.map((opt, i) => `${i + 1}. ${opt}`).join('\n')}
|
|
|
104
104
|
});
|
|
105
105
|
return { meeting, approval };
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* 获取严重程度对应的图标和标题前缀
|
|
109
|
+
*/
|
|
110
|
+
getSeverityPrefix(severity) {
|
|
111
|
+
const prefixes = {
|
|
112
|
+
critical: '🔴 Critical',
|
|
113
|
+
high: '🟠 High',
|
|
114
|
+
medium: '🟡 Medium',
|
|
115
|
+
low: '🟢 Low'
|
|
116
|
+
};
|
|
117
|
+
return prefixes[severity];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 格式化歧义报告为 Markdown 描述
|
|
121
|
+
*/
|
|
122
|
+
formatAmbiguityReport(report) {
|
|
123
|
+
const lines = [];
|
|
124
|
+
lines.push('## 歧义检测结果');
|
|
125
|
+
lines.push('');
|
|
126
|
+
lines.push(`**检测阶段**: ${report.detectionPhase === 'pre_execution' ? '执行前' : '执行中'}`);
|
|
127
|
+
lines.push(`**检测时间**: ${report.detectedAt}`);
|
|
128
|
+
lines.push(`**歧义数量**: ${report.ambiguities.length}`);
|
|
129
|
+
if (report.maxSeverity) {
|
|
130
|
+
lines.push(`**最高严重程度**: ${this.getSeverityPrefix(report.maxSeverity)}`);
|
|
131
|
+
}
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push('## 歧义详情');
|
|
134
|
+
lines.push('');
|
|
135
|
+
for (const ambiguity of report.ambiguities) {
|
|
136
|
+
const severityIcon = this.getSeverityPrefix(ambiguity.severity);
|
|
137
|
+
lines.push(`### ${severityIcon} ${ambiguity.type}`);
|
|
138
|
+
lines.push('');
|
|
139
|
+
lines.push(`**描述**: ${ambiguity.description}`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
if (ambiguity.impactScope.length > 0) {
|
|
142
|
+
lines.push('**影响范围**:');
|
|
143
|
+
for (const scope of ambiguity.impactScope) {
|
|
144
|
+
lines.push(`- ${scope}`);
|
|
145
|
+
}
|
|
146
|
+
lines.push('');
|
|
147
|
+
}
|
|
148
|
+
if (ambiguity.possibleSolutions && ambiguity.possibleSolutions.length > 0) {
|
|
149
|
+
lines.push('**可能的解决方案**:');
|
|
150
|
+
for (let i = 0; i < ambiguity.possibleSolutions.length; i++) {
|
|
151
|
+
lines.push(`${i + 1}. ${ambiguity.possibleSolutions[i]}`);
|
|
152
|
+
}
|
|
153
|
+
lines.push('');
|
|
154
|
+
}
|
|
155
|
+
if (ambiguity.relatedFiles && ambiguity.relatedFiles.length > 0) {
|
|
156
|
+
lines.push(`**相关文件**: ${ambiguity.relatedFiles.join(', ')}`);
|
|
157
|
+
lines.push('');
|
|
158
|
+
}
|
|
159
|
+
if (ambiguity.relatedTaskIds && ambiguity.relatedTaskIds.length > 0) {
|
|
160
|
+
lines.push(`**相关任务**: ${ambiguity.relatedTaskIds.join(', ')}`);
|
|
161
|
+
lines.push('');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (report.suggestedStrategy) {
|
|
165
|
+
lines.push('## 建议处理策略');
|
|
166
|
+
lines.push('');
|
|
167
|
+
const strategyMap = {
|
|
168
|
+
ask_immediate: '立即提问 (ask_immediate)',
|
|
169
|
+
write_meeting: '写入 Meeting (write_meeting)',
|
|
170
|
+
continue: '继续执行 (continue)'
|
|
171
|
+
};
|
|
172
|
+
lines.push(strategyMap[report.suggestedStrategy] || report.suggestedStrategy);
|
|
173
|
+
lines.push('');
|
|
174
|
+
}
|
|
175
|
+
if (report.suggestedQuestions && report.suggestedQuestions.length > 0) {
|
|
176
|
+
lines.push('## 建议的问题');
|
|
177
|
+
lines.push('');
|
|
178
|
+
for (let i = 0; i < report.suggestedQuestions.length; i++) {
|
|
179
|
+
lines.push(`${i + 1}. ${report.suggestedQuestions[i]}`);
|
|
180
|
+
}
|
|
181
|
+
lines.push('');
|
|
182
|
+
}
|
|
183
|
+
return lines.join('\n');
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* 创建歧义 Meeting
|
|
187
|
+
*/
|
|
188
|
+
async createAmbiguityMeeting(taskId, ambiguityReport) {
|
|
189
|
+
const meetingId = `meeting-${Date.now().toString(36)}`;
|
|
190
|
+
const now = new Date().toISOString();
|
|
191
|
+
// 根据最高严重程度生成标题
|
|
192
|
+
const severity = ambiguityReport.maxSeverity || 'medium';
|
|
193
|
+
const severityPrefix = this.getSeverityPrefix(severity);
|
|
194
|
+
const titleSummary = ambiguityReport.ambiguities[0]?.description.slice(0, 50) || '歧义检测';
|
|
195
|
+
const meeting = {
|
|
196
|
+
id: meetingId,
|
|
197
|
+
type: 'ambiguity',
|
|
198
|
+
status: 'pending',
|
|
199
|
+
taskId,
|
|
200
|
+
title: `${severityPrefix}: ${titleSummary}...`,
|
|
201
|
+
description: `任务 ${taskId} 检测到歧义,需要用户确认处理方式`,
|
|
202
|
+
impactScope: ambiguityReport.ambiguities.flatMap(a => a.impactScope),
|
|
203
|
+
participants: ['user'],
|
|
204
|
+
createdAt: now,
|
|
205
|
+
ambiguityReport,
|
|
206
|
+
suggestedQuestions: ambiguityReport.suggestedQuestions
|
|
207
|
+
};
|
|
208
|
+
// 保存 Meeting
|
|
209
|
+
await this.stateManager.saveMeeting(meeting);
|
|
210
|
+
// 创建审批
|
|
211
|
+
const approval = await this.approvalManager.createApproval({
|
|
212
|
+
type: 'meeting',
|
|
213
|
+
taskId,
|
|
214
|
+
title: meeting.title,
|
|
215
|
+
description: this.formatAmbiguityReport(ambiguityReport),
|
|
216
|
+
content: JSON.stringify({ meetingId, ambiguityReport })
|
|
217
|
+
});
|
|
218
|
+
return { meeting, approval };
|
|
219
|
+
}
|
|
107
220
|
/**
|
|
108
221
|
* 开始 Meeting
|
|
109
222
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -204,7 +204,7 @@ export interface ApprovalOption {
|
|
|
204
204
|
label: string;
|
|
205
205
|
}
|
|
206
206
|
export type MeetingStatus = 'pending' | 'in_progress' | 'resolved' | 'cancelled';
|
|
207
|
-
export type MeetingType = 'blocking' | 'decision' | 'review' | 'planning';
|
|
207
|
+
export type MeetingType = 'blocking' | 'decision' | 'review' | 'planning' | 'ambiguity';
|
|
208
208
|
export interface Meeting {
|
|
209
209
|
id: string;
|
|
210
210
|
type: MeetingType;
|
|
@@ -219,6 +219,10 @@ export interface Meeting {
|
|
|
219
219
|
createdAt: string;
|
|
220
220
|
startedAt?: string;
|
|
221
221
|
resolvedAt?: string;
|
|
222
|
+
/** 歧义报告 (仅 type 为 'ambiguity' 时使用) */
|
|
223
|
+
ambiguityReport?: AmbiguityReport;
|
|
224
|
+
/** 建议的问题列表 (用于歧义处理) */
|
|
225
|
+
suggestedQuestions?: string[];
|
|
222
226
|
}
|
|
223
227
|
export interface ParsedTask {
|
|
224
228
|
title: string;
|
|
@@ -311,3 +315,64 @@ export interface DebugSession {
|
|
|
311
315
|
updatedAt: string;
|
|
312
316
|
completedAt?: string;
|
|
313
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* 歧义类型
|
|
320
|
+
* - requirement: 需求歧义 (需求描述不清晰、存在多种解读)
|
|
321
|
+
* - technical: 技术歧义 (技术方案选择、实现方式不明确)
|
|
322
|
+
* - dependency: 依赖歧义 (依赖项版本、接口契约不明确)
|
|
323
|
+
* - acceptance: 验收歧义 (验收标准不清晰、无法验证)
|
|
324
|
+
* - test_result: 测试结果歧义 (测试结果不一致、无法判断)
|
|
325
|
+
*/
|
|
326
|
+
export type AmbiguityType = 'requirement' | 'technical' | 'dependency' | 'acceptance' | 'test_result';
|
|
327
|
+
/**
|
|
328
|
+
* 歧义严重程度
|
|
329
|
+
* - critical: 严重歧义,必须立即解决,否则任务无法继续
|
|
330
|
+
* - high: 高优先级歧义,影响核心功能,应尽快解决
|
|
331
|
+
* - medium: 中等优先级歧义,影响非核心功能,可稍后解决
|
|
332
|
+
* - low: 低优先级歧义,影响较小,可在后续处理
|
|
333
|
+
*/
|
|
334
|
+
export type AmbiguitySeverity = 'critical' | 'high' | 'medium' | 'low';
|
|
335
|
+
/**
|
|
336
|
+
* 歧义项 - 描述单个歧义点
|
|
337
|
+
*/
|
|
338
|
+
export interface AmbiguityItem {
|
|
339
|
+
/** 歧义唯一标识 */
|
|
340
|
+
id: string;
|
|
341
|
+
/** 歧义类型 */
|
|
342
|
+
type: AmbiguityType;
|
|
343
|
+
/** 严重程度 */
|
|
344
|
+
severity: AmbiguitySeverity;
|
|
345
|
+
/** 歧义描述 */
|
|
346
|
+
description: string;
|
|
347
|
+
/** 影响范围 */
|
|
348
|
+
impactScope: string[];
|
|
349
|
+
/** 可能的解决方案 */
|
|
350
|
+
possibleSolutions?: string[];
|
|
351
|
+
/** 相关文件 */
|
|
352
|
+
relatedFiles?: string[];
|
|
353
|
+
/** 相关任务 ID */
|
|
354
|
+
relatedTaskIds?: string[];
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* 歧义报告 - Agent 输出的歧义检测结果
|
|
358
|
+
*/
|
|
359
|
+
export interface AmbiguityReport {
|
|
360
|
+
/** 报告唯一标识 */
|
|
361
|
+
id: string;
|
|
362
|
+
/** 关联的任务 ID */
|
|
363
|
+
taskId: string;
|
|
364
|
+
/** 检测阶段: 'pre_execution' 执行前 | 'during_execution' 执行中 */
|
|
365
|
+
detectionPhase: 'pre_execution' | 'during_execution';
|
|
366
|
+
/** 检测到的歧义列表 */
|
|
367
|
+
ambiguities: AmbiguityItem[];
|
|
368
|
+
/** 是否存在歧义 */
|
|
369
|
+
hasAmbiguity: boolean;
|
|
370
|
+
/** 最高严重程度 (用于快速判断) */
|
|
371
|
+
maxSeverity?: AmbiguitySeverity;
|
|
372
|
+
/** 检测时间 */
|
|
373
|
+
detectedAt: string;
|
|
374
|
+
/** 建议的处理策略 */
|
|
375
|
+
suggestedStrategy?: 'ask_immediate' | 'write_meeting' | 'continue';
|
|
376
|
+
/** 建议的问题列表 (用于 AskUserQuestion) */
|
|
377
|
+
suggestedQuestions?: string[];
|
|
378
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openmatrix",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"description": "AI Agent task orchestration system with Claude Code Skills integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@typescript-eslint/eslint-plugin": "^8.58.1",
|
|
53
53
|
"@typescript-eslint/parser": "^8.58.1",
|
|
54
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
54
55
|
"eslint": "^10.2.0",
|
|
55
56
|
"vitest": "^1.6.0"
|
|
56
57
|
},
|