openmatrix 0.2.30 → 0.2.33
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 +154 -154
- package/dist/cli/commands/approve.js +35 -1
- package/dist/cli/commands/auto.js +2 -2
- package/dist/cli/commands/check-gitignore.js +34 -30
- package/dist/cli/commands/check.js +1 -1
- package/dist/cli/commands/complete.js +35 -7
- package/dist/cli/commands/debug.js +2 -1
- package/dist/cli/commands/deploy.js +1 -1
- package/dist/cli/commands/install-skills.js +3 -0
- package/dist/cli/commands/meeting.js +37 -1
- package/dist/cli/commands/report.js +1 -1
- package/dist/cli/commands/resume.js +35 -1
- package/dist/cli/commands/retry.js +130 -56
- package/dist/cli/commands/start.js +14 -3
- package/dist/cli/commands/status.js +32 -29
- package/dist/cli/commands/step.js +4 -1
- package/dist/orchestrator/ai-reviewer.d.ts +5 -0
- package/dist/orchestrator/ai-reviewer.js +9 -2
- package/dist/orchestrator/context-collector.js +17 -5
- package/dist/orchestrator/executor.d.ts +8 -0
- package/dist/orchestrator/executor.js +38 -8
- package/dist/orchestrator/phase-executor.d.ts +4 -0
- package/dist/orchestrator/phase-executor.js +21 -4
- package/dist/storage/file-store.js +8 -0
- package/dist/storage/state-manager.js +52 -19
- package/dist/test/generator.js +113 -113
- package/dist/types/index.d.ts +2 -0
- package/dist/utils/error-handler.d.ts +18 -0
- package/dist/utils/error-handler.js +32 -0
- package/dist/utils/worktree-sync.js +24 -3
- package/package.json +61 -61
- package/skills/SKILL.md +53 -53
- package/skills/auto.md +410 -413
- package/skills/brainstorm.md +19 -12
- package/skills/debug.md +694 -691
- package/skills/deploy.md +658 -658
- package/skills/feature.md +713 -686
- package/skills/plan.md +298 -296
- package/skills/report.md +9 -5
- package/skills/resume.md +292 -287
- package/skills/start.md +117 -27
- package/skills/status.md +5 -4
- package/skills/test.md +875 -875
- package/dist/agents/base-agent.d.ts +0 -46
- package/dist/agents/base-agent.js +0 -17
- package/dist/cli/commands/analyze.d.ts +0 -2
- package/dist/cli/commands/analyze.js +0 -50
- package/dist/orchestrator/smart-question-analyzer.d.ts +0 -90
- package/dist/orchestrator/smart-question-analyzer.js +0 -512
|
@@ -53,6 +53,10 @@ export declare class OrchestratorExecutor {
|
|
|
53
53
|
* 获取 PhaseExecutor 实例
|
|
54
54
|
*/
|
|
55
55
|
getPhaseExecutor(): PhaseExecutor;
|
|
56
|
+
/**
|
|
57
|
+
* 设置运行 ID(同时更新 PhaseExecutor 和 AIReviewer)
|
|
58
|
+
*/
|
|
59
|
+
setRunId(runId: string): void;
|
|
56
60
|
private loadConfigFromState;
|
|
57
61
|
/**
|
|
58
62
|
* 执行一步 - 返回待执行的 Subagent 任务
|
|
@@ -145,10 +149,14 @@ export declare class OrchestratorExecutor {
|
|
|
145
149
|
getStatus(): Promise<ExecutorStatus>;
|
|
146
150
|
/**
|
|
147
151
|
* 获取 AgentRunner 实例
|
|
152
|
+
*
|
|
153
|
+
* 注意:此方法假设 executor 已完成初始化(通过 step() 或其他方法触发)
|
|
148
154
|
*/
|
|
149
155
|
getAgentRunner(): AgentRunner;
|
|
150
156
|
/**
|
|
151
157
|
* 获取 Scheduler 实例
|
|
158
|
+
*
|
|
159
|
+
* 注意:此方法假设 executor 已完成初始化(通过 step() 或其他方法触发)
|
|
152
160
|
*/
|
|
153
161
|
getScheduler(): Scheduler;
|
|
154
162
|
/**
|
|
@@ -39,14 +39,7 @@ class OrchestratorExecutor {
|
|
|
39
39
|
...config
|
|
40
40
|
};
|
|
41
41
|
this._configReady = this.loadConfigFromState(stateManager);
|
|
42
|
-
|
|
43
|
-
maxConcurrentTasks: this.config.maxConcurrent,
|
|
44
|
-
taskTimeout: this.config.taskTimeout
|
|
45
|
-
});
|
|
46
|
-
this.agentRunner = new agent_runner_js_1.AgentRunner(stateManager, approvalManager, {
|
|
47
|
-
maxConcurrent: this.config.maxConcurrent,
|
|
48
|
-
taskTimeout: this.config.taskTimeout
|
|
49
|
-
});
|
|
42
|
+
// scheduler 和 agentRunner 在 loadConfigFromState 中根据 state.config 初始化
|
|
50
43
|
this.stateMachine = new state_machine_js_1.StateMachine();
|
|
51
44
|
this.phaseExecutor = new phase_executor_js_1.PhaseExecutor(stateManager, approvalManager);
|
|
52
45
|
this.retryManager = new retry_manager_js_1.RetryManager();
|
|
@@ -58,16 +51,43 @@ class OrchestratorExecutor {
|
|
|
58
51
|
getPhaseExecutor() {
|
|
59
52
|
return this.phaseExecutor;
|
|
60
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* 设置运行 ID(同时更新 PhaseExecutor 和 AIReviewer)
|
|
56
|
+
*/
|
|
57
|
+
setRunId(runId) {
|
|
58
|
+
this.phaseExecutor.setRunId(runId);
|
|
59
|
+
this.aiReviewer.setRunId(runId);
|
|
60
|
+
}
|
|
61
61
|
async loadConfigFromState(stateManager) {
|
|
62
62
|
try {
|
|
63
63
|
const state = await stateManager.getState();
|
|
64
64
|
if (state.config?.taskTimeout) {
|
|
65
65
|
this.config.taskTimeout = state.config.taskTimeout;
|
|
66
66
|
}
|
|
67
|
+
// agentMode 的优先级最高,明确指定时直接设置并发数
|
|
68
|
+
if (state.config?.agentMode === 'single') {
|
|
69
|
+
this.config.maxConcurrent = 1;
|
|
70
|
+
}
|
|
71
|
+
else if (state.config?.agentMode === 'parallel') {
|
|
72
|
+
this.config.maxConcurrent = 3;
|
|
73
|
+
}
|
|
74
|
+
// 注意:不再从 maxConcurrentAgents 覆盖,因为:
|
|
75
|
+
// 1. agentMode 已经明确了意图(single=1, parallel=3)
|
|
76
|
+
// 2. 构造函数传入的 maxConcurrent 用于测试等场景
|
|
77
|
+
// 3. CLI 通过 agentMode 而不是 maxConcurrentAgents 控制并发
|
|
67
78
|
}
|
|
68
79
|
catch {
|
|
69
80
|
// use default config
|
|
70
81
|
}
|
|
82
|
+
// 初始化 scheduler 和 agentRunner(使用最终配置)
|
|
83
|
+
this.scheduler = new scheduler_js_1.Scheduler(this.stateManager, {
|
|
84
|
+
maxConcurrentTasks: this.config.maxConcurrent,
|
|
85
|
+
taskTimeout: this.config.taskTimeout
|
|
86
|
+
});
|
|
87
|
+
this.agentRunner = new agent_runner_js_1.AgentRunner(this.stateManager, this.approvalManager, {
|
|
88
|
+
maxConcurrent: this.config.maxConcurrent,
|
|
89
|
+
taskTimeout: this.config.taskTimeout
|
|
90
|
+
});
|
|
71
91
|
}
|
|
72
92
|
/**
|
|
73
93
|
* 执行一步 - 返回待执行的 Subagent 任务
|
|
@@ -505,14 +525,24 @@ class OrchestratorExecutor {
|
|
|
505
525
|
}
|
|
506
526
|
/**
|
|
507
527
|
* 获取 AgentRunner 实例
|
|
528
|
+
*
|
|
529
|
+
* 注意:此方法假设 executor 已完成初始化(通过 step() 或其他方法触发)
|
|
508
530
|
*/
|
|
509
531
|
getAgentRunner() {
|
|
532
|
+
if (!this.agentRunner) {
|
|
533
|
+
throw new Error('Executor not initialized. Call step() first or wait for initialization.');
|
|
534
|
+
}
|
|
510
535
|
return this.agentRunner;
|
|
511
536
|
}
|
|
512
537
|
/**
|
|
513
538
|
* 获取 Scheduler 实例
|
|
539
|
+
*
|
|
540
|
+
* 注意:此方法假设 executor 已完成初始化(通过 step() 或其他方法触发)
|
|
514
541
|
*/
|
|
515
542
|
getScheduler() {
|
|
543
|
+
if (!this.scheduler) {
|
|
544
|
+
throw new Error('Executor not initialized. Call step() first or wait for initialization.');
|
|
545
|
+
}
|
|
516
546
|
return this.scheduler;
|
|
517
547
|
}
|
|
518
548
|
// ============ Timeout Management ============
|
|
@@ -70,6 +70,21 @@ class PhaseExecutor {
|
|
|
70
70
|
setRunId(runId) {
|
|
71
71
|
this.runId = runId;
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* 获取当前 runId — 优先使用手动设置的值,否则从 stateManager 读取
|
|
75
|
+
*/
|
|
76
|
+
async getRunId() {
|
|
77
|
+
if (this.runId)
|
|
78
|
+
return this.runId;
|
|
79
|
+
try {
|
|
80
|
+
const state = await this.stateManager.getState();
|
|
81
|
+
this.runId = state.runId;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// fallback
|
|
85
|
+
}
|
|
86
|
+
return this.runId;
|
|
87
|
+
}
|
|
73
88
|
/**
|
|
74
89
|
* 设置质量配置
|
|
75
90
|
*/
|
|
@@ -154,6 +169,8 @@ class PhaseExecutor {
|
|
|
154
169
|
* 准备阶段执行的 Subagent 任务
|
|
155
170
|
*/
|
|
156
171
|
async preparePhaseExecution(task) {
|
|
172
|
+
// 确保 runId 已初始化(避免生成 .openmatrix//tasks/ 错误路径)
|
|
173
|
+
await this.getRunId();
|
|
157
174
|
const currentPhase = this.getCurrentPhase(task);
|
|
158
175
|
switch (currentPhase) {
|
|
159
176
|
case 'tdd':
|
|
@@ -386,7 +403,7 @@ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
|
|
|
386
403
|
- 圈复杂度: < 10
|
|
387
404
|
|
|
388
405
|
## 输出要求
|
|
389
|
-
完成后,在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
406
|
+
完成后,在 \`.openmatrix/${this.runId}/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
390
407
|
- \`result.md\` - 实现说明
|
|
391
408
|
- \`changes.txt\` - 变更文件列表
|
|
392
409
|
|
|
@@ -621,7 +638,7 @@ fi
|
|
|
621
638
|
|
|
622
639
|
## 📊 质量报告格式
|
|
623
640
|
|
|
624
|
-
在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建 \`quality-report.json\`:
|
|
641
|
+
在 \`.openmatrix/${this.runId}/tasks/${task.id}/artifacts/\` 目录下创建 \`quality-report.json\`:
|
|
625
642
|
|
|
626
643
|
\`\`\`json
|
|
627
644
|
{
|
|
@@ -762,7 +779,7 @@ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
|
|
|
762
779
|
## 验收流程
|
|
763
780
|
|
|
764
781
|
### 1. 检查验证阶段结果
|
|
765
|
-
读取 \`.openmatrix/tasks/${task.id}/artifacts/verify-report.md\`
|
|
782
|
+
读取 \`.openmatrix/${this.runId}/tasks/${task.id}/artifacts/verify-report.md\`
|
|
766
783
|
确认所有检查项已通过
|
|
767
784
|
|
|
768
785
|
### 2. 验证验收标准
|
|
@@ -821,7 +838,7 @@ fi
|
|
|
821
838
|
- **确认代码能实际运行**(不是只编译通过)
|
|
822
839
|
|
|
823
840
|
## 输出要求
|
|
824
|
-
在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
841
|
+
在 \`.openmatrix/${this.runId}/tasks/${task.id}/artifacts/\` 目录下创建:
|
|
825
842
|
- \`accept-report.md\` - 验收报告
|
|
826
843
|
|
|
827
844
|
## 结果格式
|
|
@@ -91,6 +91,10 @@ class FileStore {
|
|
|
91
91
|
.map((f) => f.name);
|
|
92
92
|
}
|
|
93
93
|
catch (error) {
|
|
94
|
+
const nodeError = error;
|
|
95
|
+
if (nodeError.code === 'ENOENT' || nodeError.code === 'EISDIR') {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
94
98
|
(0, error_handler_js_1.logError)(error, { operation: 'listFiles', file: fullPath });
|
|
95
99
|
return [];
|
|
96
100
|
}
|
|
@@ -104,6 +108,10 @@ class FileStore {
|
|
|
104
108
|
.map((f) => f.name);
|
|
105
109
|
}
|
|
106
110
|
catch (error) {
|
|
111
|
+
const nodeError = error;
|
|
112
|
+
if (nodeError.code === 'ENOENT' || nodeError.code === 'EISDIR') {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
107
115
|
(0, error_handler_js_1.logError)(error, { operation: 'listDirs', file: fullPath });
|
|
108
116
|
return [];
|
|
109
117
|
}
|
|
@@ -4,6 +4,7 @@ exports.StateManager = void 0;
|
|
|
4
4
|
const file_store_js_1 = require("./file-store.js");
|
|
5
5
|
const promises_1 = require("fs/promises");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
+
const error_handler_js_1 = require("../utils/error-handler.js");
|
|
7
8
|
const DEFAULT_CONFIG = {
|
|
8
9
|
timeout: 120,
|
|
9
10
|
taskTimeout: 600000, // 10 分钟(毫秒)
|
|
@@ -271,6 +272,10 @@ class StateManager {
|
|
|
271
272
|
});
|
|
272
273
|
}
|
|
273
274
|
async getTask(taskId) {
|
|
275
|
+
// 验证 taskId 格式防止路径遍历
|
|
276
|
+
if (!(0, error_handler_js_1.validateId)(taskId, 'taskId')) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
274
279
|
let task = await this.store.readJson(`tasks/${taskId}/task.json`);
|
|
275
280
|
if (!task) {
|
|
276
281
|
task = await this.store.readJson(`tasks/${taskId}.json`);
|
|
@@ -324,11 +329,13 @@ class StateManager {
|
|
|
324
329
|
* 保存 Phase 结果到任务子目录
|
|
325
330
|
*/
|
|
326
331
|
async savePhaseResult(taskId, phase, result) {
|
|
327
|
-
await this.
|
|
328
|
-
taskId
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
await this.withFileLock(async () => {
|
|
333
|
+
await this.store.writeJson(`tasks/${taskId}/${phase}.json`, {
|
|
334
|
+
taskId,
|
|
335
|
+
phase,
|
|
336
|
+
timestamp: new Date().toISOString(),
|
|
337
|
+
...result
|
|
338
|
+
});
|
|
332
339
|
});
|
|
333
340
|
}
|
|
334
341
|
/**
|
|
@@ -341,7 +348,9 @@ class StateManager {
|
|
|
341
348
|
* 保存 Agent 上下文到 context.md
|
|
342
349
|
*/
|
|
343
350
|
async saveTaskContext(taskId, content) {
|
|
344
|
-
await this.
|
|
351
|
+
await this.withFileLock(async () => {
|
|
352
|
+
await this.store.writeMarkdown(`tasks/${taskId}/context.md`, content);
|
|
353
|
+
});
|
|
345
354
|
}
|
|
346
355
|
/**
|
|
347
356
|
* 读取 Agent 上下文
|
|
@@ -420,13 +429,21 @@ class StateManager {
|
|
|
420
429
|
}
|
|
421
430
|
// ============ Approval Methods ============
|
|
422
431
|
async saveApproval(approval) {
|
|
423
|
-
await this.
|
|
432
|
+
await this.withFileLock(async () => {
|
|
433
|
+
await this.store.writeJson(`approvals/${approval.id}.json`, approval);
|
|
434
|
+
});
|
|
424
435
|
}
|
|
425
436
|
async getApproval(approvalId) {
|
|
437
|
+
// 验证 approvalId 格式防止路径遍历
|
|
438
|
+
if (!(0, error_handler_js_1.validateId)(approvalId, 'approvalId')) {
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
426
441
|
return await this.store.readJson(`approvals/${approvalId}.json`);
|
|
427
442
|
}
|
|
428
443
|
async updateApproval(approval) {
|
|
429
|
-
await this.
|
|
444
|
+
await this.withFileLock(async () => {
|
|
445
|
+
await this.store.writeJson(`approvals/${approval.id}.json`, approval);
|
|
446
|
+
});
|
|
430
447
|
}
|
|
431
448
|
async getApprovalsByStatus(status) {
|
|
432
449
|
const files = await this.store.listFiles('approvals');
|
|
@@ -498,8 +515,10 @@ class StateManager {
|
|
|
498
515
|
* 路径: .openmatrix/{runId}/research/session.json
|
|
499
516
|
*/
|
|
500
517
|
async saveResearchSession(session) {
|
|
501
|
-
await this.
|
|
502
|
-
|
|
518
|
+
await this.withFileLock(async () => {
|
|
519
|
+
await this.store.ensureDir('research');
|
|
520
|
+
await this.store.writeJson('research/session.json', session);
|
|
521
|
+
});
|
|
503
522
|
}
|
|
504
523
|
/**
|
|
505
524
|
* 读取研究会话
|
|
@@ -511,8 +530,10 @@ class StateManager {
|
|
|
511
530
|
* 保存研究报告
|
|
512
531
|
*/
|
|
513
532
|
async saveResearchReport(content) {
|
|
514
|
-
await this.
|
|
515
|
-
|
|
533
|
+
await this.withFileLock(async () => {
|
|
534
|
+
await this.store.ensureDir('research');
|
|
535
|
+
await this.store.writeMarkdown('research/RESEARCH.md', content);
|
|
536
|
+
});
|
|
516
537
|
}
|
|
517
538
|
/**
|
|
518
539
|
* 读取研究报告
|
|
@@ -524,8 +545,10 @@ class StateManager {
|
|
|
524
545
|
* 保存研究上下文 (供 start 使用)
|
|
525
546
|
*/
|
|
526
547
|
async saveResearchContext(context) {
|
|
527
|
-
await this.
|
|
528
|
-
|
|
548
|
+
await this.withFileLock(async () => {
|
|
549
|
+
await this.store.ensureDir('research');
|
|
550
|
+
await this.store.writeJson('research/context.json', context);
|
|
551
|
+
});
|
|
529
552
|
}
|
|
530
553
|
/**
|
|
531
554
|
* 读取研究上下文
|
|
@@ -543,16 +566,20 @@ class StateManager {
|
|
|
543
566
|
* 保存知识条目
|
|
544
567
|
*/
|
|
545
568
|
async saveKnowledgeFinding(index, content) {
|
|
546
|
-
await this.
|
|
547
|
-
|
|
569
|
+
await this.withFileLock(async () => {
|
|
570
|
+
await this.store.ensureDir('research/knowledge');
|
|
571
|
+
await this.store.writeMarkdown(`research/knowledge/finding-${index}.md`, content);
|
|
572
|
+
});
|
|
548
573
|
}
|
|
549
574
|
// ============ Brainstorm Methods ============
|
|
550
575
|
/**
|
|
551
576
|
* 保存头脑风暴会话
|
|
552
577
|
*/
|
|
553
578
|
async saveBrainstormSession(session) {
|
|
554
|
-
await this.
|
|
555
|
-
|
|
579
|
+
await this.withFileLock(async () => {
|
|
580
|
+
await this.store.ensureDir('brainstorm');
|
|
581
|
+
await this.store.writeJson('brainstorm/session.json', session);
|
|
582
|
+
});
|
|
556
583
|
}
|
|
557
584
|
/**
|
|
558
585
|
* 读取头脑风暴会话
|
|
@@ -613,9 +640,15 @@ class StateManager {
|
|
|
613
640
|
}
|
|
614
641
|
// ============ Meeting Methods ============
|
|
615
642
|
async saveMeeting(meeting) {
|
|
616
|
-
await this.
|
|
643
|
+
await this.withFileLock(async () => {
|
|
644
|
+
await this.store.writeJson(`meetings/${meeting.id}.json`, meeting);
|
|
645
|
+
});
|
|
617
646
|
}
|
|
618
647
|
async getMeeting(meetingId) {
|
|
648
|
+
// 验证 meetingId 格式防止路径遍历
|
|
649
|
+
if (!(0, error_handler_js_1.validateId)(meetingId, 'meetingId')) {
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
619
652
|
return await this.store.readJson(`meetings/${meetingId}.json`);
|
|
620
653
|
}
|
|
621
654
|
async getMeetingsByStatus(status) {
|