openmatrix 0.1.63 → 0.1.65
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 +1 -1
- package/dist/agents/agent-runner.js +22 -13
- package/dist/cli/commands/brainstorm.js +14 -18
- package/dist/cli/commands/complete.js +35 -2
- package/dist/cli/commands/start.js +6 -3
- package/dist/cli/commands/step.js +7 -1
- package/dist/orchestrator/executor.js +1 -1
- package/dist/orchestrator/git-commit-manager.js +12 -2
- package/dist/orchestrator/phase-executor.d.ts +3 -0
- package/dist/orchestrator/phase-executor.js +445 -349
- package/dist/orchestrator/scheduler.js +1 -1
- package/dist/storage/file-store.d.ts +9 -1
- package/dist/storage/file-store.js +24 -9
- package/dist/storage/state-manager.js +80 -2
- package/dist/types/index.d.ts +6 -0
- package/package.json +1 -1
- package/skills/auto.md +14 -2
- package/skills/meeting.md +15 -0
- package/skills/start.md +10 -1
|
@@ -3,8 +3,16 @@ export declare class FileStore {
|
|
|
3
3
|
constructor(basePath: string);
|
|
4
4
|
ensureDir(path: string): Promise<void>;
|
|
5
5
|
writeJson<T>(path: string, data: T): Promise<void>;
|
|
6
|
-
readJson<T>(path: string): Promise<T | null>;
|
|
7
6
|
writeMarkdown(path: string, content: string): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* 读取 JSON 文件
|
|
9
|
+
* @returns 文件内容,如果文件不存在则返回 null;其他错误会抛出异常
|
|
10
|
+
*/
|
|
11
|
+
readJson<T>(path: string): Promise<T | null>;
|
|
12
|
+
/**
|
|
13
|
+
* 读取 Markdown 文件
|
|
14
|
+
* @returns 文件内容,如果文件不存在则返回 null;其他错误会抛出异常
|
|
15
|
+
*/
|
|
8
16
|
readMarkdown(path: string): Promise<string | null>;
|
|
9
17
|
exists(path: string): Promise<boolean>;
|
|
10
18
|
listFiles(dir: string): Promise<string[]>;
|
|
@@ -18,28 +18,43 @@ class FileStore {
|
|
|
18
18
|
await (0, promises_1.mkdir)((0, path_1.dirname)(fullPath), { recursive: true });
|
|
19
19
|
await (0, promises_1.writeFile)(fullPath, JSON.stringify(data, null, 2), 'utf-8');
|
|
20
20
|
}
|
|
21
|
+
async writeMarkdown(path, content) {
|
|
22
|
+
const fullPath = (0, path_1.join)(this.basePath, path);
|
|
23
|
+
await (0, promises_1.mkdir)((0, path_1.dirname)(fullPath), { recursive: true });
|
|
24
|
+
await (0, promises_1.writeFile)(fullPath, content, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 读取 JSON 文件
|
|
28
|
+
* @returns 文件内容,如果文件不存在则返回 null;其他错误会抛出异常
|
|
29
|
+
*/
|
|
21
30
|
async readJson(path) {
|
|
22
31
|
const fullPath = (0, path_1.join)(this.basePath, path);
|
|
23
32
|
try {
|
|
24
33
|
const content = await (0, promises_1.readFile)(fullPath, 'utf-8');
|
|
25
34
|
return JSON.parse(content);
|
|
26
35
|
}
|
|
27
|
-
catch {
|
|
28
|
-
|
|
36
|
+
catch (error) {
|
|
37
|
+
// 只隐藏"文件不存在"错误,其他错误(权限、磁盘等)抛出以便调用者处理
|
|
38
|
+
if (error.code === 'ENOENT' || error.code === 'EISDIR') {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
29
42
|
}
|
|
30
43
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
44
|
+
/**
|
|
45
|
+
* 读取 Markdown 文件
|
|
46
|
+
* @returns 文件内容,如果文件不存在则返回 null;其他错误会抛出异常
|
|
47
|
+
*/
|
|
36
48
|
async readMarkdown(path) {
|
|
37
49
|
const fullPath = (0, path_1.join)(this.basePath, path);
|
|
38
50
|
try {
|
|
39
51
|
return await (0, promises_1.readFile)(fullPath, 'utf-8');
|
|
40
52
|
}
|
|
41
|
-
catch {
|
|
42
|
-
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error.code === 'ENOENT' || error.code === 'EISDIR') {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
43
58
|
}
|
|
44
59
|
}
|
|
45
60
|
async exists(path) {
|
|
@@ -46,13 +46,33 @@ class StateManager {
|
|
|
46
46
|
completed: 0,
|
|
47
47
|
inProgress: 0,
|
|
48
48
|
failed: 0,
|
|
49
|
-
pending: 0
|
|
49
|
+
pending: 0,
|
|
50
|
+
scheduled: 0,
|
|
51
|
+
blocked: 0,
|
|
52
|
+
waiting: 0,
|
|
53
|
+
verify: 0,
|
|
54
|
+
accept: 0,
|
|
55
|
+
retry_queue: 0
|
|
50
56
|
}
|
|
51
57
|
};
|
|
52
58
|
await this.store.writeJson('state.json', initialState);
|
|
53
59
|
this.stateCache = initialState;
|
|
54
60
|
}
|
|
55
61
|
else {
|
|
62
|
+
// 合并旧状态的统计字段(兼容旧版本)
|
|
63
|
+
existing.statistics = {
|
|
64
|
+
totalTasks: existing.statistics.totalTasks ?? 0,
|
|
65
|
+
completed: existing.statistics.completed ?? 0,
|
|
66
|
+
inProgress: existing.statistics.inProgress ?? 0,
|
|
67
|
+
failed: existing.statistics.failed ?? 0,
|
|
68
|
+
pending: existing.statistics.pending ?? 0,
|
|
69
|
+
scheduled: existing.statistics.scheduled ?? 0,
|
|
70
|
+
blocked: existing.statistics.blocked ?? 0,
|
|
71
|
+
waiting: existing.statistics.waiting ?? 0,
|
|
72
|
+
verify: existing.statistics.verify ?? 0,
|
|
73
|
+
accept: existing.statistics.accept ?? 0,
|
|
74
|
+
retry_queue: existing.statistics.retry_queue ?? 0
|
|
75
|
+
};
|
|
56
76
|
this.stateCache = existing;
|
|
57
77
|
}
|
|
58
78
|
}
|
|
@@ -65,7 +85,28 @@ class StateManager {
|
|
|
65
85
|
async updateState(updates) {
|
|
66
86
|
await this.withLock(async () => {
|
|
67
87
|
const state = await this.getState();
|
|
68
|
-
|
|
88
|
+
// 确保 statistics 存在(兼容旧版本)
|
|
89
|
+
if (!state.statistics) {
|
|
90
|
+
state.statistics = {
|
|
91
|
+
totalTasks: 0,
|
|
92
|
+
completed: 0,
|
|
93
|
+
inProgress: 0,
|
|
94
|
+
failed: 0,
|
|
95
|
+
pending: 0,
|
|
96
|
+
scheduled: 0,
|
|
97
|
+
blocked: 0,
|
|
98
|
+
waiting: 0,
|
|
99
|
+
verify: 0,
|
|
100
|
+
accept: 0,
|
|
101
|
+
retry_queue: 0
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// 合并 updates,statistics 需要单独处理
|
|
105
|
+
const newState = {
|
|
106
|
+
...state,
|
|
107
|
+
...updates,
|
|
108
|
+
statistics: updates.statistics ? { ...state.statistics, ...updates.statistics } : state.statistics
|
|
109
|
+
};
|
|
69
110
|
await this.store.writeJson('state.json', newState);
|
|
70
111
|
this.stateCache = newState;
|
|
71
112
|
});
|
|
@@ -196,24 +237,61 @@ class StateManager {
|
|
|
196
237
|
// 直接写入状态,不经过 updateState(避免重入锁死锁)
|
|
197
238
|
const state = await this.getState();
|
|
198
239
|
const stats = { ...state.statistics };
|
|
240
|
+
// 扩展统计字段(如果不存在则初始化)
|
|
241
|
+
if (!('scheduled' in stats))
|
|
242
|
+
stats.scheduled = 0;
|
|
243
|
+
if (!('blocked' in stats))
|
|
244
|
+
stats.blocked = 0;
|
|
245
|
+
if (!('waiting' in stats))
|
|
246
|
+
stats.waiting = 0;
|
|
247
|
+
if (!('verify' in stats))
|
|
248
|
+
stats.verify = 0;
|
|
249
|
+
if (!('accept' in stats))
|
|
250
|
+
stats.accept = 0;
|
|
251
|
+
if (!('retry_queue' in stats))
|
|
252
|
+
stats.retry_queue = 0;
|
|
199
253
|
// Decrement old status count
|
|
200
254
|
if (oldStatus === 'pending')
|
|
201
255
|
stats.pending--;
|
|
256
|
+
else if (oldStatus === 'scheduled')
|
|
257
|
+
stats.scheduled--;
|
|
202
258
|
else if (oldStatus === 'in_progress')
|
|
203
259
|
stats.inProgress--;
|
|
260
|
+
else if (oldStatus === 'blocked')
|
|
261
|
+
stats.blocked--;
|
|
262
|
+
else if (oldStatus === 'waiting')
|
|
263
|
+
stats.waiting--;
|
|
264
|
+
else if (oldStatus === 'verify')
|
|
265
|
+
stats.verify--;
|
|
266
|
+
else if (oldStatus === 'accept')
|
|
267
|
+
stats.accept--;
|
|
204
268
|
else if (oldStatus === 'completed')
|
|
205
269
|
stats.completed--;
|
|
206
270
|
else if (oldStatus === 'failed')
|
|
207
271
|
stats.failed--;
|
|
272
|
+
else if (oldStatus === 'retry_queue')
|
|
273
|
+
stats.retry_queue--;
|
|
208
274
|
// Increment new status count
|
|
209
275
|
if (newStatus === 'pending')
|
|
210
276
|
stats.pending++;
|
|
277
|
+
else if (newStatus === 'scheduled')
|
|
278
|
+
stats.scheduled++;
|
|
211
279
|
else if (newStatus === 'in_progress')
|
|
212
280
|
stats.inProgress++;
|
|
281
|
+
else if (newStatus === 'blocked')
|
|
282
|
+
stats.blocked++;
|
|
283
|
+
else if (newStatus === 'waiting')
|
|
284
|
+
stats.waiting++;
|
|
285
|
+
else if (newStatus === 'verify')
|
|
286
|
+
stats.verify++;
|
|
287
|
+
else if (newStatus === 'accept')
|
|
288
|
+
stats.accept++;
|
|
213
289
|
else if (newStatus === 'completed')
|
|
214
290
|
stats.completed++;
|
|
215
291
|
else if (newStatus === 'failed')
|
|
216
292
|
stats.failed++;
|
|
293
|
+
else if (newStatus === 'retry_queue')
|
|
294
|
+
stats.retry_queue++;
|
|
217
295
|
const newState = { ...state, statistics: stats };
|
|
218
296
|
await this.store.writeJson('state.json', newState);
|
|
219
297
|
this.stateCache = newState;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -85,6 +85,12 @@ export interface GlobalState {
|
|
|
85
85
|
inProgress: number;
|
|
86
86
|
failed: number;
|
|
87
87
|
pending: number;
|
|
88
|
+
scheduled: number;
|
|
89
|
+
blocked: number;
|
|
90
|
+
waiting: number;
|
|
91
|
+
verify: number;
|
|
92
|
+
accept: number;
|
|
93
|
+
retry_queue: number;
|
|
88
94
|
};
|
|
89
95
|
}
|
|
90
96
|
export interface AppConfig {
|
package/package.json
CHANGED
package/skills/auto.md
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: om:auto
|
|
3
|
-
description:
|
|
3
|
+
description: 全自动执行任务指令 - AI 拆分,无阻塞,bypass permissions
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
<NOTE>
|
|
7
|
+
## 注意:区分 `/om:auto` 指令与「全自动执行」模式
|
|
8
|
+
|
|
9
|
+
- **`/om:auto`** 是一个 **Skill 指令**,为 Agent 无障碍执行准备
|
|
10
|
+
- **「全自动执行」**是 `/om:start` 中用户选择的 **执行模式选项**
|
|
11
|
+
|
|
12
|
+
**关键区别**:`/om/auto` 不创建 Meeting 记录,直接跳过阻塞任务。
|
|
13
|
+
</NOTE>
|
|
14
|
+
|
|
6
15
|
<NO-OTHER-SKILLS>
|
|
7
16
|
执行此技能时,不得调用 superpowers、gsd 或其他任务编排相关的技能。OpenMatrix 独立运行,不依赖外部任务编排系统。
|
|
8
17
|
</NO-OTHER-SKILLS>
|
|
@@ -191,7 +200,10 @@ openmatrix step --json
|
|
|
191
200
|
如果返回 `status: "next"` → 继续执行返回的 task
|
|
192
201
|
如果返回 `status: "done"` → 所有任务完成,进入最终提交
|
|
193
202
|
如果返回 `status: "blocked"` → 有阻塞任务,处理 Meeting
|
|
194
|
-
|
|
203
|
+
|
|
204
|
+
**Meeting 处理机制:**
|
|
205
|
+
`/om:auto` 不创建 Meeting 记录,直接跳过阻塞任务,无障碍执行。
|
|
206
|
+
|
|
195
207
|
|
|
196
208
|
**Agent 上下文共享机制 (Agent Memory):**
|
|
197
209
|
|
package/skills/meeting.md
CHANGED
|
@@ -345,4 +345,19 @@ openmatrix meeting --skip-all --message "批量跳过"
|
|
|
345
345
|
↓
|
|
346
346
|
恢复执行或标记完成
|
|
347
347
|
```
|
|
348
|
+
|
|
349
|
+
## 与 start 的集成
|
|
350
|
+
|
|
351
|
+
执行 `/om:start` 时:
|
|
352
|
+
1. 阻塞任务自动跳过,创建 Meeting 记录
|
|
353
|
+
2. 非阻塞任务继续执行,最大化并行度
|
|
354
|
+
3. 所有非阻塞任务完成后,自动提示有待处理的 Meeting
|
|
355
|
+
4. 用户使用 `/om:meeting` 统一处理阻塞问题
|
|
356
|
+
|
|
357
|
+
**全自动执行模式下的 Meeting 流程:**
|
|
358
|
+
```
|
|
359
|
+
/om:start → 执行任务 → 遇到阻塞 → 创建 Meeting → 跳过阻塞 → 继续执行其他任务
|
|
360
|
+
↓
|
|
361
|
+
所有非阻塞任务完成 → 提示 Meeting → /om:meeting → 用户处理 → 完成
|
|
362
|
+
```
|
|
348
363
|
</notes>
|
package/skills/start.md
CHANGED
|
@@ -131,7 +131,7 @@ AskUserQuestion({
|
|
|
131
131
|
question: "请选择执行模式:",
|
|
132
132
|
header: "执行模式",
|
|
133
133
|
options: [
|
|
134
|
-
{ label: "全自动执行 (推荐)", description: "
|
|
134
|
+
{ label: "全自动执行 (推荐)", description: "无需确认,自动完成,阻塞任务 (Meeting) 留到最后统一处理" },
|
|
135
135
|
{ label: "关键节点确认", description: "plan/merge 时暂停确认" },
|
|
136
136
|
{ label: "每阶段确认", description: "每个阶段完成后暂停" }
|
|
137
137
|
],
|
|
@@ -277,9 +277,18 @@ Agent-1 完成 → 写入 context.md → Agent-2 读取 Agent-1 的上下文 →
|
|
|
277
277
|
**Meeting 处理(auto 模式):** 记录并跳过,执行完成后统一展示。
|
|
278
278
|
|
|
279
279
|
**执行完成后:**
|
|
280
|
+
|
|
281
|
+
### Meeting 机制
|
|
282
|
+
|
|
283
|
+
在「全自动执行」模式下:
|
|
284
|
+
- 遇到阻塞任务时,创建 Meeting 记录并跳过该任务
|
|
285
|
+
- 继续执行其他独立任务,最大化并行度
|
|
286
|
+
- 所有非阻塞任务完成后,提示用户使用 `/om:meeting` 统一处理阻塞问题
|
|
287
|
+
|
|
280
288
|
```bash
|
|
281
289
|
openmatrix meeting --list
|
|
282
290
|
```
|
|
291
|
+
|
|
283
292
|
如有 pending Meeting,交互式处理。
|
|
284
293
|
|
|
285
294
|
所有任务完成后,执行最终 Git 提交(**必须使用 HEREDOC 格式**):
|