openmatrix 0.1.63 → 0.1.64

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.
@@ -12,7 +12,7 @@ class Scheduler {
12
12
  this.stateMachine = new state_machine_js_1.StateMachine();
13
13
  this.config = {
14
14
  maxConcurrentTasks: 3,
15
- taskTimeout: 120000,
15
+ taskTimeout: 600000, // 10 分钟
16
16
  ...config
17
17
  };
18
18
  }
@@ -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
- return null;
36
+ catch (error) {
37
+ // 只隐藏"文件不存在"错误,其他错误(权限、磁盘等)抛出以便调用者处理
38
+ if (error.code === 'ENOENT' || error.code === 'EISDIR') {
39
+ return null;
40
+ }
41
+ throw error;
29
42
  }
30
43
  }
31
- async writeMarkdown(path, content) {
32
- const fullPath = (0, path_1.join)(this.basePath, path);
33
- await (0, promises_1.mkdir)((0, path_1.dirname)(fullPath), { recursive: true });
34
- await (0, promises_1.writeFile)(fullPath, content, 'utf-8');
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
- return null;
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
  }
@@ -196,24 +216,61 @@ class StateManager {
196
216
  // 直接写入状态,不经过 updateState(避免重入锁死锁)
197
217
  const state = await this.getState();
198
218
  const stats = { ...state.statistics };
219
+ // 扩展统计字段(如果不存在则初始化)
220
+ if (!('scheduled' in stats))
221
+ stats.scheduled = 0;
222
+ if (!('blocked' in stats))
223
+ stats.blocked = 0;
224
+ if (!('waiting' in stats))
225
+ stats.waiting = 0;
226
+ if (!('verify' in stats))
227
+ stats.verify = 0;
228
+ if (!('accept' in stats))
229
+ stats.accept = 0;
230
+ if (!('retry_queue' in stats))
231
+ stats.retry_queue = 0;
199
232
  // Decrement old status count
200
233
  if (oldStatus === 'pending')
201
234
  stats.pending--;
235
+ else if (oldStatus === 'scheduled')
236
+ stats.scheduled--;
202
237
  else if (oldStatus === 'in_progress')
203
238
  stats.inProgress--;
239
+ else if (oldStatus === 'blocked')
240
+ stats.blocked--;
241
+ else if (oldStatus === 'waiting')
242
+ stats.waiting--;
243
+ else if (oldStatus === 'verify')
244
+ stats.verify--;
245
+ else if (oldStatus === 'accept')
246
+ stats.accept--;
204
247
  else if (oldStatus === 'completed')
205
248
  stats.completed--;
206
249
  else if (oldStatus === 'failed')
207
250
  stats.failed--;
251
+ else if (oldStatus === 'retry_queue')
252
+ stats.retry_queue--;
208
253
  // Increment new status count
209
254
  if (newStatus === 'pending')
210
255
  stats.pending++;
256
+ else if (newStatus === 'scheduled')
257
+ stats.scheduled++;
211
258
  else if (newStatus === 'in_progress')
212
259
  stats.inProgress++;
260
+ else if (newStatus === 'blocked')
261
+ stats.blocked++;
262
+ else if (newStatus === 'waiting')
263
+ stats.waiting++;
264
+ else if (newStatus === 'verify')
265
+ stats.verify++;
266
+ else if (newStatus === 'accept')
267
+ stats.accept++;
213
268
  else if (newStatus === 'completed')
214
269
  stats.completed++;
215
270
  else if (newStatus === 'failed')
216
271
  stats.failed++;
272
+ else if (newStatus === 'retry_queue')
273
+ stats.retry_queue++;
217
274
  const newState = { ...state, statistics: stats };
218
275
  await this.store.writeJson('state.json', newState);
219
276
  this.stateCache = newState;
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmatrix",
3
- "version": "0.1.63",
3
+ "version": "0.1.64",
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",
package/skills/auto.md CHANGED
@@ -1,8 +1,17 @@
1
1
  ---
2
2
  name: om:auto
3
- description: 全自动执行任务 - AI 拆分,无阻塞,bypass permissions
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
- 4. Git 自动提交(**必须使用 HEREDOC 格式**):
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 格式**):