@mickorz/opencode-agentic-workflow 0.3.2 → 0.5.0

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.
Files changed (133) hide show
  1. package/README.md +306 -5
  2. package/dist/cli/config.d.ts +121 -0
  3. package/dist/cli/config.js +331 -0
  4. package/dist/cli/config.js.map +1 -0
  5. package/dist/cli/doctor.d.ts +5 -0
  6. package/dist/cli/doctor.js +141 -0
  7. package/dist/cli/doctor.js.map +1 -0
  8. package/dist/cli/index.d.ts +18 -0
  9. package/dist/cli/index.js +120 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/install.d.ts +19 -0
  12. package/dist/cli/install.js +135 -0
  13. package/dist/cli/install.js.map +1 -0
  14. package/dist/cli/uninstall.d.ts +16 -0
  15. package/dist/cli/uninstall.js +110 -0
  16. package/dist/cli/uninstall.js.map +1 -0
  17. package/dist/cli/update.d.ts +15 -0
  18. package/dist/cli/update.js +86 -0
  19. package/dist/cli/update.js.map +1 -0
  20. package/dist/core/index.d.ts +39 -0
  21. package/dist/core/index.js +38 -0
  22. package/dist/core/index.js.map +1 -0
  23. package/dist/observability/events.d.ts +43 -0
  24. package/dist/observability/events.js.map +1 -1
  25. package/dist/plugin/checkpoint-override.d.ts +26 -0
  26. package/dist/plugin/checkpoint-override.js +43 -0
  27. package/dist/plugin/checkpoint-override.js.map +1 -0
  28. package/dist/plugin/define-workflow.d.ts +33 -0
  29. package/dist/plugin/define-workflow.js +103 -0
  30. package/dist/plugin/define-workflow.js.map +1 -0
  31. package/dist/plugin/index.js +426 -23
  32. package/dist/plugin/index.js.map +1 -1
  33. package/dist/plugin/opencode-v2-executor.js +58 -46
  34. package/dist/plugin/opencode-v2-executor.js.map +1 -1
  35. package/dist/plugin/progress-board.d.ts +64 -0
  36. package/dist/plugin/progress-board.js +150 -0
  37. package/dist/plugin/progress-board.js.map +1 -0
  38. package/dist/plugin/progress-rpc.d.ts +390 -0
  39. package/dist/plugin/progress-rpc.js +318 -0
  40. package/dist/plugin/progress-rpc.js.map +1 -0
  41. package/dist/plugin/progress-view.d.ts +82 -0
  42. package/dist/plugin/progress-view.js +244 -0
  43. package/dist/plugin/progress-view.js.map +1 -0
  44. package/dist/plugin/run-sessions.d.ts +28 -0
  45. package/dist/plugin/run-sessions.js +46 -0
  46. package/dist/plugin/run-sessions.js.map +1 -0
  47. package/dist/plugin/tool-args.d.ts +15 -0
  48. package/dist/plugin/tool-args.js +28 -0
  49. package/dist/plugin/tool-args.js.map +1 -0
  50. package/dist/plugin/tui.d.ts +11 -4
  51. package/dist/plugin/tui.js +149 -5
  52. package/dist/plugin/tui.js.map +1 -1
  53. package/dist/plugin/workflow-control.d.ts +16 -0
  54. package/dist/plugin/workflow-control.js +85 -0
  55. package/dist/plugin/workflow-control.js.map +1 -0
  56. package/dist/plugin/workflow-schedule.d.ts +24 -0
  57. package/dist/plugin/workflow-schedule.js +97 -0
  58. package/dist/plugin/workflow-schedule.js.map +1 -0
  59. package/dist/quality/checkpoint.d.ts +7 -2
  60. package/dist/quality/checkpoint.js +13 -4
  61. package/dist/quality/checkpoint.js.map +1 -1
  62. package/dist/quality/verify.d.ts +21 -2
  63. package/dist/quality/verify.js +36 -14
  64. package/dist/quality/verify.js.map +1 -1
  65. package/dist/registry/definition.d.ts +12 -0
  66. package/dist/registry/definition.js.map +1 -1
  67. package/dist/registry/registry.d.ts +4 -0
  68. package/dist/registry/registry.js +20 -1
  69. package/dist/registry/registry.js.map +1 -1
  70. package/dist/registry/run-control.d.ts +27 -0
  71. package/dist/registry/run-control.js +51 -0
  72. package/dist/registry/run-control.js.map +1 -0
  73. package/dist/registry/runner.d.ts +29 -6
  74. package/dist/registry/runner.js +153 -35
  75. package/dist/registry/runner.js.map +1 -1
  76. package/dist/runtime/errors.d.ts +26 -0
  77. package/dist/runtime/errors.js +30 -0
  78. package/dist/runtime/errors.js.map +1 -1
  79. package/dist/runtime/executor.d.ts +22 -0
  80. package/dist/runtime/executor.js.map +1 -1
  81. package/dist/runtime/run-context.d.ts +44 -0
  82. package/dist/runtime/run-context.js +32 -0
  83. package/dist/runtime/run-context.js.map +1 -0
  84. package/dist/scheduler/cron.d.ts +29 -0
  85. package/dist/scheduler/cron.js +171 -0
  86. package/dist/scheduler/cron.js.map +1 -0
  87. package/dist/scheduler/service.d.ts +78 -0
  88. package/dist/scheduler/service.js +210 -0
  89. package/dist/scheduler/service.js.map +1 -0
  90. package/dist/scheduler/store.d.ts +26 -0
  91. package/dist/scheduler/store.js +94 -0
  92. package/dist/scheduler/store.js.map +1 -0
  93. package/dist/scheduler/types.d.ts +53 -0
  94. package/dist/scheduler/types.js +12 -0
  95. package/dist/scheduler/types.js.map +1 -0
  96. package/dist/state/journal.d.ts +23 -0
  97. package/dist/state/journal.js +2 -0
  98. package/dist/state/journal.js.map +1 -1
  99. package/dist/state/recorder.d.ts +67 -0
  100. package/dist/state/recorder.js +148 -2
  101. package/dist/state/recorder.js.map +1 -1
  102. package/dist/workflow/agent.d.ts +42 -1
  103. package/dist/workflow/agent.js +116 -6
  104. package/dist/workflow/agent.js.map +1 -1
  105. package/dist/workflow/judge-panel.d.ts +37 -0
  106. package/dist/workflow/judge-panel.js +66 -0
  107. package/dist/workflow/judge-panel.js.map +1 -0
  108. package/dist/workflow/pipeline.d.ts +21 -0
  109. package/dist/workflow/pipeline.js +71 -0
  110. package/dist/workflow/pipeline.js.map +1 -0
  111. package/dist/workflow/race.d.ts +16 -0
  112. package/dist/workflow/race.js +46 -0
  113. package/dist/workflow/race.js.map +1 -0
  114. package/dist/workflow/sequence.js +6 -0
  115. package/dist/workflow/sequence.js.map +1 -1
  116. package/dist/workflows/loader.d.ts +124 -0
  117. package/dist/workflows/loader.js +500 -0
  118. package/dist/workflows/loader.js.map +1 -0
  119. package/dist/workspace/ambient.d.ts +6 -4
  120. package/dist/workspace/ambient.js +10 -4
  121. package/dist/workspace/ambient.js.map +1 -1
  122. package/dist/workspace/in-place.d.ts +26 -0
  123. package/dist/workspace/in-place.js +48 -0
  124. package/dist/workspace/in-place.js.map +1 -0
  125. package/dist/workspace/index.d.ts +1 -0
  126. package/dist/workspace/index.js +1 -0
  127. package/dist/workspace/index.js.map +1 -1
  128. package/package.json +16 -6
  129. package/skills/workflow-authoring/SKILL.md +111 -0
  130. package/skills/workflow-optimize/SKILL.md +70 -0
  131. package/dist/workflows/index.d.ts +0 -19
  132. package/dist/workflows/index.js +0 -40
  133. package/dist/workflows/index.js.map +0 -1
@@ -0,0 +1,171 @@
1
+ // cron 子集校验与 slot 计算(P2-7,v1-parity;零依赖实现)
2
+ //
3
+ // 支持的四模式(与 v1 同子集——覆盖定时场景的第一版全部需求):
4
+ // 每分钟 / 每 n 分钟 `* * * * *` / 分钟字段 星杠n(n 1-59)
5
+ // 每小时 m 分 `m * * * *`
6
+ // 每天 h 点 m 分 `m h * * *`
7
+ // 每周 W 的 h 点 m 分 `m h * * W`(W = 0-6 单值或逗号列表,0=周日)
8
+ //
9
+ // slot 计算:本地时区闭式数学(v1 用 cron-parser;v2 零依赖手写)。
10
+ // DST 切换日的 slot 可能与墙钟偏差 1 小时(诚实边界,对分钟级/小时级
11
+ // 场景无实质影响)。同一表达式各次计算确定一致。
12
+ //
13
+ // 纪律:Core 侧模块,禁止 import OpenCode API(架构不变量)。
14
+ const EVERY_MINUTES = /^(\*\/(\d{1,2})|\*) \* \* \* \*$/;
15
+ const HOURLY = /^(\d{1,2}) \* \* \* \*$/;
16
+ const DAILY = /^(\d{1,2}) (\d{1,2}) \* \* \*$/;
17
+ const WEEKLY = /^(\d{1,2}) (\d{1,2}) \* \* (\d(?:,\d)*)$/;
18
+ const FORMAT_HELP = [
19
+ '不支持的 cron 表达式 "${expr}"。仅支持四种模式:',
20
+ " * * * * * 每分钟;*/n * * * * 每 n 分钟(n 1-59,如 */5 每 5 分钟)",
21
+ " m * * * * 每小时 m 分(如 30 * * * * 每小时半点)",
22
+ " m h * * * 每天 h 点 m 分(如 0 9 * * * 每天 9 点)",
23
+ " m h * * W 每周 W 的 h 点 m 分(W 0-6,0=周日;如 0 10 * * 1 每周一 10 点)",
24
+ ].join("\n");
25
+ /**
26
+ * 校验并解析 cron 表达式。
27
+ * 合法返回 CronSpec;非法返回错误信息(含格式说明,可直接展示)。
28
+ */
29
+ export function parseCron(expr) {
30
+ const text = expr.trim();
31
+ if (text.length === 0) {
32
+ return 'cron 表达式为空(支持格式见下)\n' + FORMAT_HELP.replace("${expr}", expr);
33
+ }
34
+ let m = EVERY_MINUTES.exec(text);
35
+ if (m) {
36
+ const step = m[2] === undefined ? 1 : Number(m[2]); // 裸 "*" 等价 */1
37
+ if (step < 1 || step > 59)
38
+ return `每分钟模式的步长需在 1-59 之间,收到 ${step}`;
39
+ return { kind: "minutes", step };
40
+ }
41
+ m = HOURLY.exec(text);
42
+ if (m) {
43
+ const minute = Number(m[1]);
44
+ if (minute > 59)
45
+ return `分钟需在 0-59 之间,收到 ${minute}`;
46
+ return { kind: "hourly", minute };
47
+ }
48
+ m = DAILY.exec(text);
49
+ if (m) {
50
+ const minute = Number(m[1]);
51
+ const hour = Number(m[2]);
52
+ if (minute > 59)
53
+ return `分钟需在 0-59 之间,收到 ${minute}`;
54
+ if (hour > 23)
55
+ return `小时需在 0-23 之间,收到 ${hour}`;
56
+ return { kind: "daily", minute, hour };
57
+ }
58
+ m = WEEKLY.exec(text);
59
+ if (m) {
60
+ const minute = Number(m[1]);
61
+ const hour = Number(m[2]);
62
+ if (minute > 59)
63
+ return `分钟需在 0-59 之间,收到 ${minute}`;
64
+ if (hour > 23)
65
+ return `小时需在 0-23 之间,收到 ${hour}`;
66
+ const days = m[3].split(",").map(Number);
67
+ for (const day of days) {
68
+ if (day > 6)
69
+ return `星期需在 0-6 之间(0=周日),收到 ${day}`;
70
+ }
71
+ return { kind: "weekly", minute, hour, days };
72
+ }
73
+ return FORMAT_HELP.replace("${expr}", expr);
74
+ }
75
+ export function validateCron(expr) {
76
+ const parsed = parseCron(expr);
77
+ return typeof parsed === "string" ? parsed : null;
78
+ }
79
+ /** 把时间截到分钟(秒/毫秒归零) */
80
+ function zeroToMinute(date) {
81
+ const d = new Date(date.getTime());
82
+ d.setSeconds(0, 0);
83
+ return d;
84
+ }
85
+ /** 严格晚于 after 的第一个候选(分钟对齐);先保证 > after 再按谓词推进 */
86
+ function firstCandidate(after) {
87
+ let t = zeroToMinute(new Date(after.getTime() + 1));
88
+ while (t.getTime() <= after.getTime()) {
89
+ t = new Date(t.getTime() + 60_000);
90
+ }
91
+ return t;
92
+ }
93
+ /**
94
+ * after 之后的下一个未来 slot(严格晚于 after)。
95
+ * 已通过校验的 spec 才可调用(parseCron 返回 CronSpec)。
96
+ */
97
+ export function nextRun(spec, after) {
98
+ let t = firstCandidate(after);
99
+ switch (spec.kind) {
100
+ case "minutes": {
101
+ // 分钟 0 恒满足(0 % n === 0),60 分钟内必命中
102
+ for (let i = 0; i < 60 && t.getMinutes() % spec.step !== 0; i++) {
103
+ t = new Date(t.getTime() + 60_000);
104
+ }
105
+ return t;
106
+ }
107
+ case "hourly": {
108
+ t.setMinutes(spec.minute);
109
+ if (t.getTime() <= after.getTime())
110
+ t = new Date(t.getTime() + 3_600_000);
111
+ t.setMinutes(spec.minute); // 跨小时后再对齐分钟(+1h 保持分钟不变,此行防御 DST 偏移)
112
+ return t;
113
+ }
114
+ case "daily": {
115
+ t.setHours(spec.hour, spec.minute, 0, 0);
116
+ if (t.getTime() <= after.getTime())
117
+ t = new Date(t.getTime() + 86_400_000);
118
+ t.setHours(spec.hour, spec.minute, 0, 0);
119
+ return t;
120
+ }
121
+ case "weekly": {
122
+ t.setHours(spec.hour, spec.minute, 0, 0);
123
+ if (t.getTime() <= after.getTime())
124
+ t = new Date(t.getTime() + 86_400_000);
125
+ t.setHours(spec.hour, spec.minute, 0, 0);
126
+ for (let i = 0; i < 7 && !spec.days.includes(t.getDay()); i++) {
127
+ t = new Date(t.getTime() + 86_400_000);
128
+ t.setHours(spec.hour, spec.minute, 0, 0);
129
+ }
130
+ return t;
131
+ }
132
+ }
133
+ }
134
+ /** now 之前(含恰好等于)最近的一个过去 slot */
135
+ export function latestSlot(spec, now) {
136
+ let t = zeroToMinute(now);
137
+ switch (spec.kind) {
138
+ case "minutes": {
139
+ for (let i = 0; i < 60 && t.getMinutes() % spec.step !== 0; i++) {
140
+ t = new Date(t.getTime() - 60_000);
141
+ }
142
+ return t;
143
+ }
144
+ case "hourly": {
145
+ t.setMinutes(spec.minute);
146
+ if (t.getTime() > now.getTime())
147
+ t = new Date(t.getTime() - 3_600_000);
148
+ t.setMinutes(spec.minute);
149
+ return t;
150
+ }
151
+ case "daily": {
152
+ t.setHours(spec.hour, spec.minute, 0, 0);
153
+ if (t.getTime() > now.getTime())
154
+ t = new Date(t.getTime() - 86_400_000);
155
+ t.setHours(spec.hour, spec.minute, 0, 0);
156
+ return t;
157
+ }
158
+ case "weekly": {
159
+ t.setHours(spec.hour, spec.minute, 0, 0);
160
+ if (t.getTime() > now.getTime())
161
+ t = new Date(t.getTime() - 86_400_000);
162
+ t.setHours(spec.hour, spec.minute, 0, 0);
163
+ for (let i = 0; i < 7 && !spec.days.includes(t.getDay()); i++) {
164
+ t = new Date(t.getTime() - 86_400_000);
165
+ t.setHours(spec.hour, spec.minute, 0, 0);
166
+ }
167
+ return t;
168
+ }
169
+ }
170
+ }
171
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/scheduler/cron.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * SchedulerService(P2-7):定时任务的核心编排(宿主无关)
3
+ *
4
+ * 职责:何时触发(cron slot + 游标去重)与记录生命周期;
5
+ * 怎么执行(workflow 启动方式)经 TriggerFn 注入(插件侧接线
6
+ * startWorkflowDetached + 单飞检查)。
7
+ *
8
+ * 触发语义(如实告知,全部写进工具描述):
9
+ * - 游标基线 = 创建时刻的最近过去 slot:创建前的 slot 不补跑
10
+ * (要立刻跑用 runNow)
11
+ * - 宿主停机错过的 slot,重启后**合并为最近一个** slot 补跑一次
12
+ * (绝不按停机时长逐个补)
13
+ * - 单飞冲突(本进程已有 live run):该 slot 记录 skipped 并消费——
14
+ * 是跳过不是延迟
15
+ * - 调度器随宿主进程存活(timer unref,不阻止退出)
16
+ *
17
+ * 纪律:Core 侧模块,禁止 import OpenCode API(架构不变量)。
18
+ */
19
+ import type { Schedule, ScheduleRun, ScheduleView } from "./types.js";
20
+ /** 触发器以此异常表示「本次跳过」(如单飞冲突);其他异常 = failed */
21
+ export declare class ScheduleSkipError extends Error {
22
+ constructor(reason: string);
23
+ }
24
+ export interface TriggerResult {
25
+ runId: string;
26
+ /** workflow 终态映射(completed→success / failed→failed / aborted→aborted) */
27
+ completion: Promise<"success" | "failed" | "aborted">;
28
+ }
29
+ /** 执行器注入:如何启动一次 workflow run(返回 runId + 终态 promise) */
30
+ export type TriggerFn = (schedule: Schedule, trigger: "scheduled" | "manual") => Promise<TriggerResult>;
31
+ export interface SchedulerDeps {
32
+ /** schedulesDir(绝对路径) */
33
+ dir: string;
34
+ /** 时钟注入(测试用);缺省真实时间 */
35
+ now?: () => Date;
36
+ /** create 时校验 flow 存在(registry 查询) */
37
+ flowExists: (flow: string) => boolean;
38
+ /** 已知 flow 清单(报错提示用) */
39
+ knownFlows?: () => string[];
40
+ /** 执行注入(插件侧接线 startWorkflowDetached) */
41
+ trigger: TriggerFn;
42
+ /** tick 间隔 ms,默认 15000 */
43
+ tickMs?: number;
44
+ }
45
+ export interface CreateScheduleInput {
46
+ id: string;
47
+ flow: string;
48
+ cron: string;
49
+ name?: string;
50
+ args?: Record<string, unknown>;
51
+ /** 缺省 true */
52
+ enabled?: boolean;
53
+ }
54
+ export declare class SchedulerService {
55
+ private readonly deps;
56
+ private timer;
57
+ constructor(deps: SchedulerDeps);
58
+ private now;
59
+ start(): void;
60
+ stop(): void;
61
+ create(input: CreateScheduleInput): Promise<ScheduleView>;
62
+ setEnabled(id: string, enabled: boolean): Promise<ScheduleView>;
63
+ remove(id: string): Promise<void>;
64
+ list(): Promise<ScheduleView[]>;
65
+ /** 详情:视图 + 最近触发记录(默认 10 条) */
66
+ detail(id: string, runLimit?: number): Promise<{
67
+ view: ScheduleView;
68
+ runs: ScheduleRun[];
69
+ }>;
70
+ private require;
71
+ private view;
72
+ /** 手动立即触发(manual;不消费 cron 游标;单飞冲突照常 skip) */
73
+ runNow(id: string): Promise<ScheduleRun>;
74
+ /** 一个 tick:消费到点 slot。返回本轮触发的 schedule id(可测/日志) */
75
+ tick(): Promise<string[]>;
76
+ /** 触发一次:记录 running → 执行注入 → 终态回写。fire 不抛(异常进记录) */
77
+ private fire;
78
+ }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * SchedulerService(P2-7):定时任务的核心编排(宿主无关)
3
+ *
4
+ * 职责:何时触发(cron slot + 游标去重)与记录生命周期;
5
+ * 怎么执行(workflow 启动方式)经 TriggerFn 注入(插件侧接线
6
+ * startWorkflowDetached + 单飞检查)。
7
+ *
8
+ * 触发语义(如实告知,全部写进工具描述):
9
+ * - 游标基线 = 创建时刻的最近过去 slot:创建前的 slot 不补跑
10
+ * (要立刻跑用 runNow)
11
+ * - 宿主停机错过的 slot,重启后**合并为最近一个** slot 补跑一次
12
+ * (绝不按停机时长逐个补)
13
+ * - 单飞冲突(本进程已有 live run):该 slot 记录 skipped 并消费——
14
+ * 是跳过不是延迟
15
+ * - 调度器随宿主进程存活(timer unref,不阻止退出)
16
+ *
17
+ * 纪律:Core 侧模块,禁止 import OpenCode API(架构不变量)。
18
+ */
19
+ import { latestSlot, nextRun, parseCron } from "./cron.js";
20
+ import { appendRun, deleteSchedule as deleteScheduleFiles, getSchedule, listRuns, listSchedules, readCursor, saveSchedule, updateRun, writeCursor, } from "./store.js";
21
+ const ID_PATTERN = /^[a-z][a-z0-9-]*$/;
22
+ /** 触发器以此异常表示「本次跳过」(如单飞冲突);其他异常 = failed */
23
+ export class ScheduleSkipError extends Error {
24
+ constructor(reason) {
25
+ super(reason);
26
+ this.name = "ScheduleSkipError";
27
+ }
28
+ }
29
+ export class SchedulerService {
30
+ deps;
31
+ timer;
32
+ constructor(deps) {
33
+ this.deps = deps;
34
+ }
35
+ now() {
36
+ return this.deps.now ? this.deps.now() : new Date();
37
+ }
38
+ // ── 生命周期 ─────────────────────────────────────────────────────────
39
+ start() {
40
+ if (this.timer)
41
+ return;
42
+ const tickMs = this.deps.tickMs ?? 15_000;
43
+ this.timer = setInterval(() => {
44
+ void this.tick();
45
+ }, tickMs);
46
+ // 不阻止宿主进程退出(调度器随宿主存活,进程退出即停)
47
+ if (typeof this.timer.unref === "function")
48
+ this.timer.unref();
49
+ console.log(`[agentic-workflow] scheduler started (tick ${tickMs}ms, dir ${this.deps.dir})`);
50
+ }
51
+ stop() {
52
+ if (!this.timer)
53
+ return;
54
+ clearInterval(this.timer);
55
+ this.timer = undefined;
56
+ }
57
+ // ── CRUD ─────────────────────────────────────────────────────────────
58
+ async create(input) {
59
+ const { id, flow, cron } = input;
60
+ if (!ID_PATTERN.test(id)) {
61
+ throw new Error(`schedule id 必须是 kebab-case(小写字母开头,含小写字母/数字/-),收到 "${id}"`);
62
+ }
63
+ const cronError = ((spec) => (typeof spec === "string" ? spec : null))(parseCron(cron));
64
+ if (cronError)
65
+ throw new Error(`INVALID_CRON:${cronError}`);
66
+ if (!this.deps.flowExists(flow)) {
67
+ const known = this.deps.knownFlows?.().join(", ") ?? "(无)";
68
+ throw new Error(`FLOW_NOT_FOUND:未找到 flow "${flow}"(已知:${known})`);
69
+ }
70
+ if (await getSchedule(this.deps.dir, id)) {
71
+ throw new Error(`DUPLICATE:schedule "${id}" 已存在(改配置请先 delete 再 create,或用 enable/disable)`);
72
+ }
73
+ const nowIso = this.now().toISOString();
74
+ const schedule = {
75
+ id,
76
+ name: input.name,
77
+ flow,
78
+ cron,
79
+ enabled: input.enabled ?? true,
80
+ ...(input.args !== undefined ? { args: input.args } : {}),
81
+ createdAt: nowIso,
82
+ updatedAt: nowIso,
83
+ };
84
+ await saveSchedule(this.deps.dir, schedule);
85
+ // 游标基线 = 创建时刻的最近过去 slot:创建前的 slot 不补跑
86
+ const spec = parseCron(cron);
87
+ const cursor = await readCursor(this.deps.dir);
88
+ cursor[id] = latestSlot(spec, this.now()).getTime();
89
+ await writeCursor(this.deps.dir, cursor);
90
+ return this.view(schedule);
91
+ }
92
+ async setEnabled(id, enabled) {
93
+ const schedule = await this.require(id);
94
+ schedule.enabled = enabled;
95
+ schedule.updatedAt = this.now().toISOString();
96
+ await saveSchedule(this.deps.dir, schedule);
97
+ return this.view(schedule);
98
+ }
99
+ async remove(id) {
100
+ await this.require(id);
101
+ await deleteScheduleFiles(this.deps.dir, id);
102
+ }
103
+ async list() {
104
+ const schedules = await listSchedules(this.deps.dir);
105
+ return Promise.all(schedules.map((s) => this.view(s)));
106
+ }
107
+ /** 详情:视图 + 最近触发记录(默认 10 条) */
108
+ async detail(id, runLimit = 10) {
109
+ const schedule = await this.require(id);
110
+ const runs = (await listRuns(this.deps.dir, id)).slice(0, runLimit);
111
+ return { view: await this.view(schedule), runs };
112
+ }
113
+ async require(id) {
114
+ const schedule = await getSchedule(this.deps.dir, id);
115
+ if (!schedule)
116
+ throw new Error(`NOT_FOUND:未找到 schedule "${id}"`);
117
+ return schedule;
118
+ }
119
+ async view(schedule) {
120
+ const spec = parseCron(schedule.cron);
121
+ const runs = await listRuns(this.deps.dir, schedule.id);
122
+ const last = runs[0];
123
+ return {
124
+ ...schedule,
125
+ ...(last ? { lastRunAt: last.startedAt, lastRunStatus: last.status } : {}),
126
+ ...(schedule.enabled && typeof spec === "object"
127
+ ? { nextRunAt: nextRun(spec, this.now()).toISOString() }
128
+ : {}),
129
+ };
130
+ }
131
+ // ── 触发 ─────────────────────────────────────────────────────────────
132
+ /** 手动立即触发(manual;不消费 cron 游标;单飞冲突照常 skip) */
133
+ async runNow(id) {
134
+ const schedule = await this.require(id);
135
+ const now = this.now();
136
+ return this.fire(schedule, "manual", now.getTime());
137
+ }
138
+ /** 一个 tick:消费到点 slot。返回本轮触发的 schedule id(可测/日志) */
139
+ async tick() {
140
+ const now = this.now();
141
+ const schedules = await listSchedules(this.deps.dir);
142
+ const cursor = await readCursor(this.deps.dir);
143
+ const fired = [];
144
+ for (const schedule of schedules) {
145
+ if (!schedule.enabled)
146
+ continue;
147
+ const spec = parseCron(schedule.cron);
148
+ if (typeof spec === "string") {
149
+ console.log(`[agentic-workflow] scheduler: schedule ${schedule.id} cron invalid, skipped: ${spec.split("\n")[0]}`);
150
+ continue;
151
+ }
152
+ const slot = latestSlot(spec, now).getTime();
153
+ const consumed = cursor[schedule.id] ?? 0;
154
+ if (slot <= consumed)
155
+ continue; // 已消费(或基线之内)
156
+ // 消费游标(含停机补跑合并:直接跳到最近 slot)后触发
157
+ cursor[schedule.id] = slot;
158
+ await writeCursor(this.deps.dir, cursor);
159
+ console.log(`[agentic-workflow] scheduler: ${schedule.id} due (slot ${new Date(slot).toISOString()})`);
160
+ await this.fire(schedule, "scheduled", slot);
161
+ fired.push(schedule.id);
162
+ }
163
+ return fired;
164
+ }
165
+ /** 触发一次:记录 running → 执行注入 → 终态回写。fire 不抛(异常进记录) */
166
+ async fire(schedule, trigger, slotEpoch) {
167
+ const startedAt = new Date().toISOString();
168
+ const record = {
169
+ scheduleId: schedule.id,
170
+ flow: schedule.flow,
171
+ trigger,
172
+ slot: new Date(slotEpoch).toISOString(),
173
+ slotEpoch,
174
+ status: "running",
175
+ startedAt,
176
+ };
177
+ await appendRun(this.deps.dir, schedule.id, record);
178
+ try {
179
+ const started = await this.deps.trigger(schedule, trigger);
180
+ record.workflowRunId = started.runId;
181
+ await updateRun(this.deps.dir, schedule.id, slotEpoch, trigger, { workflowRunId: started.runId });
182
+ // 终态回写(detached completion;fire 自身不等待终态)
183
+ void started.completion.then((status) => {
184
+ void updateRun(this.deps.dir, schedule.id, slotEpoch, trigger, {
185
+ status,
186
+ finishedAt: new Date().toISOString(),
187
+ });
188
+ }, (error) => {
189
+ void updateRun(this.deps.dir, schedule.id, slotEpoch, trigger, {
190
+ status: "failed",
191
+ finishedAt: new Date().toISOString(),
192
+ note: error instanceof Error ? error.message : String(error),
193
+ });
194
+ });
195
+ return record;
196
+ }
197
+ catch (error) {
198
+ const skipped = error instanceof ScheduleSkipError;
199
+ const status = skipped ? "skipped" : "failed";
200
+ const patch = {
201
+ status,
202
+ finishedAt: new Date().toISOString(),
203
+ note: error instanceof Error ? error.message : String(error),
204
+ };
205
+ await updateRun(this.deps.dir, schedule.id, slotEpoch, trigger, patch);
206
+ return { ...record, ...patch };
207
+ }
208
+ }
209
+ }
210
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/scheduler/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Schedule 文件存储(P2-7)
3
+ *
4
+ * schedulesDir 布局:
5
+ * <id>.json Schedule 配置(工具管理;点开头文件被忽略)
6
+ * .cursor.json 触发游标 { [id]: lastSlotEpochMs }(原子写)
7
+ * runs/<id>.json 该 id 的触发记录(新的在前,上限 50 条,原子写)
8
+ *
9
+ * 纪律:Core 侧模块,禁止 import OpenCode API(架构不变量)。
10
+ */
11
+ import type { Schedule, ScheduleRun } from "./types.js";
12
+ /** 全部 Schedule(按 id 排序;点开头与 runs/ 不算配置) */
13
+ export declare function listSchedules(dir: string): Promise<Schedule[]>;
14
+ export declare function getSchedule(dir: string, id: string): Promise<Schedule | undefined>;
15
+ export declare function saveSchedule(dir: string, schedule: Schedule): Promise<void>;
16
+ /** 删除配置 + 该 id 的游标与记录 */
17
+ export declare function deleteSchedule(dir: string, id: string): Promise<void>;
18
+ /** 触发游标:id -> 已消费的 slot epoch ms */
19
+ export declare function readCursor(dir: string): Promise<Record<string, number>>;
20
+ export declare function writeCursor(dir: string, cursor: Record<string, number>): Promise<void>;
21
+ /** 某 id 的触发记录(新的在前) */
22
+ export declare function listRuns(dir: string, id: string): Promise<ScheduleRun[]>;
23
+ /** 追加一条记录(新的在前,上限 50 条截断) */
24
+ export declare function appendRun(dir: string, id: string, run: ScheduleRun): Promise<void>;
25
+ /** 按 slotEpoch + trigger 定位记录并更新(服务在 run 收口时改状态) */
26
+ export declare function updateRun(dir: string, id: string, slotEpoch: number, trigger: "scheduled" | "manual", patch: Partial<ScheduleRun>): Promise<ScheduleRun | undefined>;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Schedule 文件存储(P2-7)
3
+ *
4
+ * schedulesDir 布局:
5
+ * <id>.json Schedule 配置(工具管理;点开头文件被忽略)
6
+ * .cursor.json 触发游标 { [id]: lastSlotEpochMs }(原子写)
7
+ * runs/<id>.json 该 id 的触发记录(新的在前,上限 50 条,原子写)
8
+ *
9
+ * 纪律:Core 侧模块,禁止 import OpenCode API(架构不变量)。
10
+ */
11
+ import { mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
12
+ import path from "node:path";
13
+ const RUNS_KEEP = 50;
14
+ /** 原子写(tmp + rename;与 journal 同纪律——绝不写半截文件) */
15
+ async function atomicWrite(file, content) {
16
+ await mkdir(path.dirname(file), { recursive: true });
17
+ const tmp = `${file}.tmp-${process.pid}-${Date.now().toString(36)}`;
18
+ await writeFile(tmp, content, "utf8");
19
+ await rename(tmp, file);
20
+ }
21
+ async function readJson(file) {
22
+ try {
23
+ return JSON.parse(await readFile(file, "utf8"));
24
+ }
25
+ catch {
26
+ return undefined; // 不存在或坏 JSON:视为无(工具层对配置文件报错,游标自愈)
27
+ }
28
+ }
29
+ /** 全部 Schedule(按 id 排序;点开头与 runs/ 不算配置) */
30
+ export async function listSchedules(dir) {
31
+ let entries;
32
+ try {
33
+ entries = await readdir(dir);
34
+ }
35
+ catch {
36
+ return []; // 目录不存在 = 无定时任务
37
+ }
38
+ const schedules = [];
39
+ for (const entry of entries) {
40
+ if (!entry.endsWith(".json") || entry.startsWith("."))
41
+ continue;
42
+ const parsed = (await readJson(path.join(dir, entry)));
43
+ if (parsed && typeof parsed.id === "string" && typeof parsed.flow === "string") {
44
+ schedules.push(parsed);
45
+ }
46
+ }
47
+ return schedules.sort((a, b) => a.id.localeCompare(b.id));
48
+ }
49
+ export async function getSchedule(dir, id) {
50
+ const parsed = (await readJson(path.join(dir, `${id}.json`)));
51
+ return parsed && parsed.id === id ? parsed : undefined;
52
+ }
53
+ export async function saveSchedule(dir, schedule) {
54
+ await atomicWrite(path.join(dir, `${schedule.id}.json`), JSON.stringify(schedule, null, 2) + "\n");
55
+ }
56
+ /** 删除配置 + 该 id 的游标与记录 */
57
+ export async function deleteSchedule(dir, id) {
58
+ await rm(path.join(dir, `${id}.json`), { force: true });
59
+ await rm(path.join(dir, "runs", `${id}.json`), { force: true });
60
+ const cursor = (await readJson(path.join(dir, ".cursor.json")));
61
+ if (cursor && id in cursor) {
62
+ delete cursor[id];
63
+ await atomicWrite(path.join(dir, ".cursor.json"), JSON.stringify(cursor, null, 2) + "\n");
64
+ }
65
+ }
66
+ /** 触发游标:id -> 已消费的 slot epoch ms */
67
+ export async function readCursor(dir) {
68
+ return (await readJson(path.join(dir, ".cursor.json"))) ?? {};
69
+ }
70
+ export async function writeCursor(dir, cursor) {
71
+ await atomicWrite(path.join(dir, ".cursor.json"), JSON.stringify(cursor, null, 2) + "\n");
72
+ }
73
+ /** 某 id 的触发记录(新的在前) */
74
+ export async function listRuns(dir, id) {
75
+ return (await readJson(path.join(dir, "runs", `${id}.json`))) ?? [];
76
+ }
77
+ /** 追加一条记录(新的在前,上限 50 条截断) */
78
+ export async function appendRun(dir, id, run) {
79
+ const existing = await listRuns(dir, id);
80
+ const next = [run, ...existing].slice(0, RUNS_KEEP);
81
+ await atomicWrite(path.join(dir, "runs", `${id}.json`), JSON.stringify(next, null, 2) + "\n");
82
+ }
83
+ /** 按 slotEpoch + trigger 定位记录并更新(服务在 run 收口时改状态) */
84
+ export async function updateRun(dir, id, slotEpoch, trigger, patch) {
85
+ const runs = await listRuns(dir, id);
86
+ const index = runs.findIndex((r) => r.slotEpoch === slotEpoch && r.trigger === trigger);
87
+ if (index === -1)
88
+ return undefined;
89
+ const updated = { ...runs[index], ...patch };
90
+ runs[index] = updated;
91
+ await atomicWrite(path.join(dir, "runs", `${id}.json`), JSON.stringify(runs, null, 2) + "\n");
92
+ return updated;
93
+ }
94
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/scheduler/store.ts"],"names":[],"mappings":"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"}