@mickorz/opencode-agentic-workflow 0.3.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.
- package/LICENSE +21 -0
- package/README.md +406 -0
- package/dist/metrics/collector.d.ts +98 -0
- package/dist/metrics/collector.js +246 -0
- package/dist/metrics/collector.js.map +1 -0
- package/dist/observability/events.d.ts +99 -0
- package/dist/observability/events.js +55 -0
- package/dist/observability/events.js.map +1 -0
- package/dist/observability/observe.d.ts +7 -0
- package/dist/observability/observe.js +29 -0
- package/dist/observability/observe.js.map +1 -0
- package/dist/observability/trace.d.ts +26 -0
- package/dist/observability/trace.js +52 -0
- package/dist/observability/trace.js.map +1 -0
- package/dist/plugin/checkpoint-rpc.d.ts +74 -0
- package/dist/plugin/checkpoint-rpc.js +73 -0
- package/dist/plugin/checkpoint-rpc.js.map +1 -0
- package/dist/plugin/index.d.ts +24 -0
- package/dist/plugin/index.js +271 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/interactive-checkpoint-gate.d.ts +35 -0
- package/dist/plugin/interactive-checkpoint-gate.js +86 -0
- package/dist/plugin/interactive-checkpoint-gate.js.map +1 -0
- package/dist/plugin/opencode-v2-executor.d.ts +55 -0
- package/dist/plugin/opencode-v2-executor.js +92 -0
- package/dist/plugin/opencode-v2-executor.js.map +1 -0
- package/dist/plugin/policy-checkpoint-gate.d.ts +18 -0
- package/dist/plugin/policy-checkpoint-gate.js +27 -0
- package/dist/plugin/policy-checkpoint-gate.js.map +1 -0
- package/dist/plugin/price-table.d.ts +46 -0
- package/dist/plugin/price-table.js +44 -0
- package/dist/plugin/price-table.js.map +1 -0
- package/dist/plugin/tui.d.ts +12 -0
- package/dist/plugin/tui.js +53 -0
- package/dist/plugin/tui.js.map +1 -0
- package/dist/quality/check.d.ts +30 -0
- package/dist/quality/check.js +51 -0
- package/dist/quality/check.js.map +1 -0
- package/dist/quality/checkpoint.d.ts +44 -0
- package/dist/quality/checkpoint.js +55 -0
- package/dist/quality/checkpoint.js.map +1 -0
- package/dist/quality/json.d.ts +10 -0
- package/dist/quality/json.js +31 -0
- package/dist/quality/json.js.map +1 -0
- package/dist/quality/predicates.d.ts +17 -0
- package/dist/quality/predicates.js +44 -0
- package/dist/quality/predicates.js.map +1 -0
- package/dist/quality/verify.d.ts +50 -0
- package/dist/quality/verify.js +110 -0
- package/dist/quality/verify.js.map +1 -0
- package/dist/registry/definition.d.ts +66 -0
- package/dist/registry/definition.js +19 -0
- package/dist/registry/definition.js.map +1 -0
- package/dist/registry/errors.d.ts +31 -0
- package/dist/registry/errors.js +48 -0
- package/dist/registry/errors.js.map +1 -0
- package/dist/registry/index.d.ts +9 -0
- package/dist/registry/index.js +9 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/registry.d.ts +45 -0
- package/dist/registry/registry.js +117 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/registry/runner.d.ts +56 -0
- package/dist/registry/runner.js +199 -0
- package/dist/registry/runner.js.map +1 -0
- package/dist/registry/schema.d.ts +18 -0
- package/dist/registry/schema.js +73 -0
- package/dist/registry/schema.js.map +1 -0
- package/dist/runtime/command.d.ts +38 -0
- package/dist/runtime/command.js +61 -0
- package/dist/runtime/command.js.map +1 -0
- package/dist/runtime/engine.d.ts +17 -0
- package/dist/runtime/engine.js +31 -0
- package/dist/runtime/engine.js.map +1 -0
- package/dist/runtime/errors.d.ts +56 -0
- package/dist/runtime/errors.js +88 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/executor.d.ts +46 -0
- package/dist/runtime/executor.js +16 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/semaphore.d.ts +24 -0
- package/dist/runtime/semaphore.js +57 -0
- package/dist/runtime/semaphore.js.map +1 -0
- package/dist/state/file-store.d.ts +25 -0
- package/dist/state/file-store.js +138 -0
- package/dist/state/file-store.js.map +1 -0
- package/dist/state/journal.d.ts +83 -0
- package/dist/state/journal.js +59 -0
- package/dist/state/journal.js.map +1 -0
- package/dist/state/recorder.d.ts +63 -0
- package/dist/state/recorder.js +138 -0
- package/dist/state/recorder.js.map +1 -0
- package/dist/state/store.d.ts +23 -0
- package/dist/state/store.js +14 -0
- package/dist/state/store.js.map +1 -0
- package/dist/workflow/agent.d.ts +8 -0
- package/dist/workflow/agent.js +38 -0
- package/dist/workflow/agent.js.map +1 -0
- package/dist/workflow/fallback.d.ts +15 -0
- package/dist/workflow/fallback.js +32 -0
- package/dist/workflow/fallback.js.map +1 -0
- package/dist/workflow/parallel.d.ts +14 -0
- package/dist/workflow/parallel.js +62 -0
- package/dist/workflow/parallel.js.map +1 -0
- package/dist/workflow/phase.d.ts +7 -0
- package/dist/workflow/phase.js +12 -0
- package/dist/workflow/phase.js.map +1 -0
- package/dist/workflow/reliable.d.ts +50 -0
- package/dist/workflow/reliable.js +92 -0
- package/dist/workflow/reliable.js.map +1 -0
- package/dist/workflow/retry.d.ts +28 -0
- package/dist/workflow/retry.js +53 -0
- package/dist/workflow/retry.js.map +1 -0
- package/dist/workflow/sequence.d.ts +40 -0
- package/dist/workflow/sequence.js +100 -0
- package/dist/workflow/sequence.js.map +1 -0
- package/dist/workflow/smoke.d.ts +17 -0
- package/dist/workflow/smoke.js +38 -0
- package/dist/workflow/smoke.js.map +1 -0
- package/dist/workflows/artifact.d.ts +24 -0
- package/dist/workflows/artifact.js +71 -0
- package/dist/workflows/artifact.js.map +1 -0
- package/dist/workflows/index.d.ts +19 -0
- package/dist/workflows/index.js +40 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/reliable.d.ts +18 -0
- package/dist/workflows/reliable.js +32 -0
- package/dist/workflows/reliable.js.map +1 -0
- package/dist/workflows/smoke.d.ts +13 -0
- package/dist/workflows/smoke.js +26 -0
- package/dist/workflows/smoke.js.map +1 -0
- package/dist/workspace/ambient.d.ts +12 -0
- package/dist/workspace/ambient.js +17 -0
- package/dist/workspace/ambient.js.map +1 -0
- package/dist/workspace/git-worktree.d.ts +29 -0
- package/dist/workspace/git-worktree.js +110 -0
- package/dist/workspace/git-worktree.js.map +1 -0
- package/dist/workspace/index.d.ts +6 -0
- package/dist/workspace/index.js +6 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/provider.d.ts +61 -0
- package/dist/workspace/provider.js +15 -0
- package/dist/workspace/provider.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunJournal —— run 生命周期记录器(P2.1)
|
|
3
|
+
*
|
|
4
|
+
* 包装 ExecutionStore:每次状态变更后全量落盘(journal = 一串原子快照)。
|
|
5
|
+
* P2.2 的 sequence resume 将基于这些记录重建执行(attach -> 读已完成步骤 -> 续跑)。
|
|
6
|
+
*
|
|
7
|
+
* 典型生命周期:
|
|
8
|
+
* start() -> run 创建并落盘(全部步骤 pending)
|
|
9
|
+
* stepStarted(i) -> 步骤开始(input 记录)
|
|
10
|
+
* stepCompleted(i) -> 步骤成功(output 记录,resume 时的续跑依据)
|
|
11
|
+
* stepFailed(i, e) -> 步骤失败(error 记录)
|
|
12
|
+
* complete()/fail(e) -> run 收口(fail 时仍为 pending 的步骤标记 skipped)
|
|
13
|
+
*
|
|
14
|
+
* status=aborted 预留给中断场景(交互拒绝/人工打断,P2.3+)。
|
|
15
|
+
*/
|
|
16
|
+
import { createRun, toErrorRecord, } from "./journal.js";
|
|
17
|
+
export class RunJournal {
|
|
18
|
+
store;
|
|
19
|
+
run;
|
|
20
|
+
constructor(store, run) {
|
|
21
|
+
this.store = store;
|
|
22
|
+
this.run = run;
|
|
23
|
+
}
|
|
24
|
+
/** 创建新 run 并持久化初始状态 */
|
|
25
|
+
static async start(store, input) {
|
|
26
|
+
const run = createRun(input);
|
|
27
|
+
await store.createRun(run);
|
|
28
|
+
return new RunJournal(store, run);
|
|
29
|
+
}
|
|
30
|
+
/** 附加到已有 run(resume 场景:读取历史 journal 继续记录);不存在返回 undefined */
|
|
31
|
+
static async attach(store, runId) {
|
|
32
|
+
const run = await store.getRun(runId);
|
|
33
|
+
return run ? new RunJournal(store, run) : undefined;
|
|
34
|
+
}
|
|
35
|
+
assertOpen() {
|
|
36
|
+
if (this.run.status !== "running") {
|
|
37
|
+
throw new Error(`journal closed (status=${this.run.status}): run ${this.run.runId}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
step(index) {
|
|
41
|
+
const step = this.run.steps[index];
|
|
42
|
+
if (!step) {
|
|
43
|
+
throw new Error(`step index out of range: ${index} (run ${this.run.runId})`);
|
|
44
|
+
}
|
|
45
|
+
return step;
|
|
46
|
+
}
|
|
47
|
+
async stepStarted(index, input) {
|
|
48
|
+
this.assertOpen();
|
|
49
|
+
const step = this.step(index);
|
|
50
|
+
step.status = "running";
|
|
51
|
+
step.input = input;
|
|
52
|
+
step.startedAt = Date.now();
|
|
53
|
+
this.run.currentStep = index;
|
|
54
|
+
await this.store.saveRun(this.run);
|
|
55
|
+
}
|
|
56
|
+
async stepCompleted(index, output) {
|
|
57
|
+
this.assertOpen();
|
|
58
|
+
const step = this.step(index);
|
|
59
|
+
step.status = "completed";
|
|
60
|
+
step.output = output;
|
|
61
|
+
step.completedAt = Date.now();
|
|
62
|
+
await this.store.saveRun(this.run);
|
|
63
|
+
}
|
|
64
|
+
async stepFailed(index, error) {
|
|
65
|
+
this.assertOpen();
|
|
66
|
+
const step = this.step(index);
|
|
67
|
+
step.status = "failed";
|
|
68
|
+
step.error = toErrorRecord(error);
|
|
69
|
+
step.completedAt = Date.now();
|
|
70
|
+
await this.store.saveRun(this.run);
|
|
71
|
+
}
|
|
72
|
+
/** run 成功收口 */
|
|
73
|
+
async complete() {
|
|
74
|
+
this.assertOpen();
|
|
75
|
+
this.run.status = "completed";
|
|
76
|
+
this.run.completedAt = Date.now();
|
|
77
|
+
await this.store.saveRun(this.run);
|
|
78
|
+
}
|
|
79
|
+
/** run 失败收口:仍为 pending 的步骤标记 skipped(fail-fast 下它们不会被执行) */
|
|
80
|
+
async fail(error) {
|
|
81
|
+
this.assertOpen();
|
|
82
|
+
this.run.status = "failed";
|
|
83
|
+
this.run.completedAt = Date.now();
|
|
84
|
+
this.run.failure = toErrorRecord(error);
|
|
85
|
+
for (const step of this.run.steps) {
|
|
86
|
+
if (step.status === "pending")
|
|
87
|
+
step.status = "skipped";
|
|
88
|
+
}
|
|
89
|
+
await this.store.saveRun(this.run);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 记录 workspace 身份(P2.7 隔离启用时,resume attach 的依据)。
|
|
93
|
+
* 仅限 run 进行中(收口后不可再写)。
|
|
94
|
+
*/
|
|
95
|
+
async setWorkspace(identity) {
|
|
96
|
+
this.assertOpen();
|
|
97
|
+
this.run.workspace = identity;
|
|
98
|
+
await this.store.saveRun(this.run);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 清除 workspace 身份(清理完成后调用)。
|
|
102
|
+
* 维护性操作:允许在 run 收口后执行——否则已清理的 run
|
|
103
|
+
* 在幂等 resume 时会试图 attach 一个已删除的 worktree。
|
|
104
|
+
*/
|
|
105
|
+
async clearWorkspace() {
|
|
106
|
+
if (this.run.workspace === undefined)
|
|
107
|
+
return;
|
|
108
|
+
this.run.workspace = undefined;
|
|
109
|
+
await this.store.saveRun(this.run);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 重新打开已收口的 run(resume 场景):
|
|
113
|
+
* failed/aborted -> running;未完成步骤重置 pending(连同 input/output/时间戳/错误),
|
|
114
|
+
* completed 步骤原样保留(resume 的续跑依据)。
|
|
115
|
+
*/
|
|
116
|
+
async reopen() {
|
|
117
|
+
if (this.run.status === "running")
|
|
118
|
+
return;
|
|
119
|
+
if (this.run.status === "completed") {
|
|
120
|
+
throw new Error(`cannot reopen completed run: ${this.run.runId}`);
|
|
121
|
+
}
|
|
122
|
+
this.run.status = "running";
|
|
123
|
+
this.run.completedAt = undefined;
|
|
124
|
+
this.run.failure = undefined;
|
|
125
|
+
for (const step of this.run.steps) {
|
|
126
|
+
if (step.status !== "completed") {
|
|
127
|
+
step.status = "pending";
|
|
128
|
+
step.error = undefined;
|
|
129
|
+
step.input = undefined;
|
|
130
|
+
step.output = undefined;
|
|
131
|
+
step.startedAt = undefined;
|
|
132
|
+
step.completedAt = undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
await this.store.saveRun(this.run);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/state/recorder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,SAAS,EACT,aAAa,GAGd,MAAM,cAAc,CAAA;AAerB,MAAM,OAAO,UAAU;IAEF,KAAK;IACb,GAAG;IAFd,YACmB,KAAqB,EAC7B,GAAgB;qBADR,KAAK;mBACb,GAAG;IACX,CAAC;IAEJ,uBAAuB;IACvB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAqB,EAAE,KAAwB;QAChE,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;QAC5B,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAC1B,OAAO,IAAI,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACnC,CAAC;IAED,6DAA6D;IAC7D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAqB,EAAE,KAAa;QACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACrC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACrD,CAAC;IAEO,UAAU;QAChB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,GAAG,CAAC,MAAM,UAAU,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAA;QACtF,CAAC;IACH,CAAC;IAEO,IAAI,CAAC,KAAa;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAA;QAC9E,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,KAAe;QAC9C,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC3B,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,KAAK,CAAA;QAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,MAAgB;QACjD,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,WAAW,CAAA;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAa,EAAE,KAAc;QAC5C,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;QACjC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,eAAe;IACf,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,WAAW,CAAA;QAC7B,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACjC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,IAAI,CAAC,KAAc;QACvB,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAA;QAC1B,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACjC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;QACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;QACxD,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,QAA2B;QAC5C,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;QAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS;YAAE,OAAM;QAC5C,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QAC9B,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,OAAM;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAA;QACnE,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,CAAA;QAC3B,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,SAAS,CAAA;QAChC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,SAAS,CAAA;QAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;gBACvB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;gBACtB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;gBACtB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;gBACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;gBAC1B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;YAC9B,CAAC;QACH,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecutionStore —— 持久化执行记录的存储抽象(P2.1)
|
|
3
|
+
*
|
|
4
|
+
* 依赖倒置(与 AgentExecutor / CheckpointGate 同思路):
|
|
5
|
+
* Workflow Core 只依赖本接口;实现可以是
|
|
6
|
+
* FileExecutionStore(本地 JSON)/ SQLiteExecutionStore /
|
|
7
|
+
* OpenCodeStorageAdapter(P2 后期,经 ctx.storage)。
|
|
8
|
+
*
|
|
9
|
+
* 写入契约:
|
|
10
|
+
* - saveRun 为全量覆写(journal 每次状态变更后整体落盘)
|
|
11
|
+
* - 实现必须保证单个 run 文件的写入原子性(读不到半截 JSON)
|
|
12
|
+
*/
|
|
13
|
+
import type { WorkflowRun } from "./journal.js";
|
|
14
|
+
export interface ExecutionStore {
|
|
15
|
+
/** 新建 run(已存在同 runId 时抛错,防止覆盖历史记录) */
|
|
16
|
+
createRun(run: WorkflowRun): Promise<void>;
|
|
17
|
+
/** 全量覆写保存 run */
|
|
18
|
+
saveRun(run: WorkflowRun): Promise<void>;
|
|
19
|
+
/** 读取 run;不存在返回 undefined */
|
|
20
|
+
getRun(runId: string): Promise<WorkflowRun | undefined>;
|
|
21
|
+
/** 列出 runs;可选按 workflow id 过滤(不区分版本),按 startedAt 倒序 */
|
|
22
|
+
listRuns(workflowId?: string): Promise<WorkflowRun[]>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecutionStore —— 持久化执行记录的存储抽象(P2.1)
|
|
3
|
+
*
|
|
4
|
+
* 依赖倒置(与 AgentExecutor / CheckpointGate 同思路):
|
|
5
|
+
* Workflow Core 只依赖本接口;实现可以是
|
|
6
|
+
* FileExecutionStore(本地 JSON)/ SQLiteExecutionStore /
|
|
7
|
+
* OpenCodeStorageAdapter(P2 后期,经 ctx.storage)。
|
|
8
|
+
*
|
|
9
|
+
* 写入契约:
|
|
10
|
+
* - saveRun 为全量覆写(journal 每次状态变更后整体落盘)
|
|
11
|
+
* - 实现必须保证单个 run 文件的写入原子性(读不到半截 JSON)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/state/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent() —— 提交单个子 agent 任务
|
|
3
|
+
*
|
|
4
|
+
* 不感知 ctx / OpenCode:只经由 requireExecutor() 拿到当前绑定的
|
|
5
|
+
* AgentExecutor 并执行。P2.4 起派发 agent.started / completed / failed 事件。
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentResult } from "../runtime/executor.js";
|
|
8
|
+
export declare function agent(prompt: string): Promise<AgentResult>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent() —— 提交单个子 agent 任务
|
|
3
|
+
*
|
|
4
|
+
* 不感知 ctx / OpenCode:只经由 requireExecutor() 拿到当前绑定的
|
|
5
|
+
* AgentExecutor 并执行。P2.4 起派发 agent.started / completed / failed 事件。
|
|
6
|
+
*/
|
|
7
|
+
import { requireExecutor } from "../runtime/engine.js";
|
|
8
|
+
import { emitEvent, preview } from "../observability/events.js";
|
|
9
|
+
import { currentWorkspace } from "../workspace/ambient.js";
|
|
10
|
+
export async function agent(prompt) {
|
|
11
|
+
const workspace = currentWorkspace();
|
|
12
|
+
emitEvent({ type: "agent.started", promptPreview: preview(prompt) });
|
|
13
|
+
const startedAt = Date.now();
|
|
14
|
+
try {
|
|
15
|
+
const result = await requireExecutor().execute({
|
|
16
|
+
prompt,
|
|
17
|
+
...(workspace ? { cwd: workspace.root } : {}),
|
|
18
|
+
});
|
|
19
|
+
emitEvent({
|
|
20
|
+
type: "agent.completed",
|
|
21
|
+
durationMs: Date.now() - startedAt,
|
|
22
|
+
outputLength: result.output.length,
|
|
23
|
+
usage: result.usage,
|
|
24
|
+
costUSD: result.costUSD,
|
|
25
|
+
model: result.model,
|
|
26
|
+
});
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
emitEvent({
|
|
31
|
+
type: "agent.failed",
|
|
32
|
+
durationMs: Date.now() - startedAt,
|
|
33
|
+
error: error instanceof Error ? error.message : String(error),
|
|
34
|
+
});
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/workflow/agent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAAc;IACxC,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAA;IACpC,SAAS,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACpE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC,OAAO,CAAC;YAC7C,MAAM;YACN,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9C,CAAC,CAAA;QACF,SAAS,CAAC;YACR,IAAI,EAAE,iBAAiB;YACvB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;YAClC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAA;QACF,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,SAAS,CAAC;YACR,IAAI,EAAE,cAAc;YACpB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAA;QACF,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fallback() —— 降级候选组合子(P1.4)
|
|
3
|
+
*
|
|
4
|
+
* 依序尝试候选任务,第一个成功者胜出;全部失败抛 WorkflowFallbackError
|
|
5
|
+
* (errors 按尝试顺序排列,保留每个候选的失败原因)。
|
|
6
|
+
*
|
|
7
|
+
* 与 retry 的组合即用户链路:
|
|
8
|
+
* agent -> check fail -> retry -> still fail -> fallback
|
|
9
|
+
* fallback([() => retry(primary), () => degraded])
|
|
10
|
+
*/
|
|
11
|
+
export interface FallbackOptions {
|
|
12
|
+
/** 日志标签 */
|
|
13
|
+
label?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function fallback<T>(candidates: Array<() => Promise<T>>, options?: FallbackOptions): Promise<T>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fallback() —— 降级候选组合子(P1.4)
|
|
3
|
+
*
|
|
4
|
+
* 依序尝试候选任务,第一个成功者胜出;全部失败抛 WorkflowFallbackError
|
|
5
|
+
* (errors 按尝试顺序排列,保留每个候选的失败原因)。
|
|
6
|
+
*
|
|
7
|
+
* 与 retry 的组合即用户链路:
|
|
8
|
+
* agent -> check fail -> retry -> still fail -> fallback
|
|
9
|
+
* fallback([() => retry(primary), () => degraded])
|
|
10
|
+
*/
|
|
11
|
+
import { WorkflowFallbackError } from "../runtime/errors.js";
|
|
12
|
+
export async function fallback(candidates, options) {
|
|
13
|
+
const label = options?.label ?? "";
|
|
14
|
+
const errors = [];
|
|
15
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
16
|
+
const candidate = candidates[i];
|
|
17
|
+
if (!candidate)
|
|
18
|
+
continue;
|
|
19
|
+
try {
|
|
20
|
+
const value = await candidate();
|
|
21
|
+
console.log(`[agentic-workflow] fallback resolved by candidate #${i}${label ? ` (${label})` : ""}`);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
catch (cause) {
|
|
25
|
+
errors.push(cause);
|
|
26
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
27
|
+
console.log(`[agentic-workflow] fallback candidate #${i} failed${label ? ` (${label})` : ""}: ${message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
throw new WorkflowFallbackError(errors, label);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/workflow/fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAO5D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAmC,EACnC,OAAyB;IAEzB,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAA;IAClC,MAAM,MAAM,GAAc,EAAE,CAAA;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;QAC/B,IAAI,CAAC,SAAS;YAAE,SAAQ;QACxB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;YAC/B,OAAO,CAAC,GAAG,CACT,sDAAsD,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACvF,CAAA;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,OAAO,CAAC,GAAG,CACT,0CAA0C,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,EAAE,CAC9F,CAAA;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAChD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parallel() —— 并行执行多个任务(P1.3 失败语义)
|
|
3
|
+
*
|
|
4
|
+
* onFailure 三种模式:
|
|
5
|
+
* "fail-fast"(默认):第一个失败即抛 WorkflowParallelError;
|
|
6
|
+
* 其余任务不再影响结果(已附加吞错处理,不会产生 unhandled rejection)。
|
|
7
|
+
* "collect" :等全部任务落定;任一失败则抛错,携带全部失败与成功结果(完整可观测)。
|
|
8
|
+
* "partial" :等全部任务落定;返回结果数组,失败槽位为 undefined,不抛错(尽力而为)。
|
|
9
|
+
*/
|
|
10
|
+
export interface ParallelOptions {
|
|
11
|
+
/** 失败模式,默认 "fail-fast" */
|
|
12
|
+
onFailure?: "fail-fast" | "collect" | "partial";
|
|
13
|
+
}
|
|
14
|
+
export declare function parallel<T>(tasks: Array<() => Promise<T>>, options?: ParallelOptions): Promise<T[]>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parallel() —— 并行执行多个任务(P1.3 失败语义)
|
|
3
|
+
*
|
|
4
|
+
* onFailure 三种模式:
|
|
5
|
+
* "fail-fast"(默认):第一个失败即抛 WorkflowParallelError;
|
|
6
|
+
* 其余任务不再影响结果(已附加吞错处理,不会产生 unhandled rejection)。
|
|
7
|
+
* "collect" :等全部任务落定;任一失败则抛错,携带全部失败与成功结果(完整可观测)。
|
|
8
|
+
* "partial" :等全部任务落定;返回结果数组,失败槽位为 undefined,不抛错(尽力而为)。
|
|
9
|
+
*/
|
|
10
|
+
import { WorkflowParallelError } from "../runtime/errors.js";
|
|
11
|
+
export async function parallel(tasks, options) {
|
|
12
|
+
const onFailure = options?.onFailure ?? "fail-fast";
|
|
13
|
+
if (tasks.length === 0)
|
|
14
|
+
return [];
|
|
15
|
+
if (onFailure === "fail-fast") {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const results = new Array(tasks.length).fill(undefined);
|
|
18
|
+
let rejected = false;
|
|
19
|
+
let pending = tasks.length;
|
|
20
|
+
tasks.forEach((task, index) => {
|
|
21
|
+
Promise.resolve()
|
|
22
|
+
.then(task)
|
|
23
|
+
.then((value) => {
|
|
24
|
+
if (rejected)
|
|
25
|
+
return;
|
|
26
|
+
results[index] = value;
|
|
27
|
+
pending -= 1;
|
|
28
|
+
if (pending === 0)
|
|
29
|
+
resolve(results);
|
|
30
|
+
})
|
|
31
|
+
.catch((cause) => {
|
|
32
|
+
if (rejected)
|
|
33
|
+
return; // 已失败:吞掉后续错误,避免 unhandled rejection
|
|
34
|
+
rejected = true;
|
|
35
|
+
reject(new WorkflowParallelError([{ index, error: cause }], results, "fail-fast"));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// collect / partial:等全部落定
|
|
41
|
+
const settled = await Promise.allSettled(tasks.map((task) => task()));
|
|
42
|
+
const results = new Array(tasks.length).fill(undefined);
|
|
43
|
+
const failures = [];
|
|
44
|
+
settled.forEach((outcome, index) => {
|
|
45
|
+
if (outcome.status === "fulfilled") {
|
|
46
|
+
results[index] = outcome.value;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
failures.push({ index, error: outcome.reason });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (onFailure === "collect" && failures.length > 0) {
|
|
53
|
+
throw new WorkflowParallelError(failures, results, "collect");
|
|
54
|
+
}
|
|
55
|
+
// partial:失败槽位保持 undefined,仅记录日志
|
|
56
|
+
for (const failure of failures) {
|
|
57
|
+
const message = failure.error instanceof Error ? failure.error.message : String(failure.error);
|
|
58
|
+
console.log(`[agentic-workflow] parallel task #${failure.index} failed (partial): ${message}`);
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=parallel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/workflow/parallel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* phase() —— 标记当前工作流阶段
|
|
3
|
+
*
|
|
4
|
+
* P0: metadata + log;P2.4 起升级为事件源(phase.started 派发到事件总线),
|
|
5
|
+
* TUI / metrics / trace / journal 均可消费。
|
|
6
|
+
*/
|
|
7
|
+
import { emitEvent } from "../observability/events.js";
|
|
8
|
+
export function phase(name) {
|
|
9
|
+
console.log(`[agentic-workflow] phase: ${name}`);
|
|
10
|
+
emitEvent({ type: "phase.started", name });
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=phase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase.js","sourceRoot":"","sources":["../../src/workflow/phase.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAEtD,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAA;IAChD,SAAS,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAA;AAC5C,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reliable Workflow —— P1 完整可靠执行链(用户验收 Demo 的落地)
|
|
3
|
+
*
|
|
4
|
+
* 链路:执行 -> 确定性检查 -> 语义验证(N reviewer)-> 人工审批
|
|
5
|
+
*
|
|
6
|
+
* agent(分析主题) —— 做事
|
|
7
|
+
* -> check(commandSuccess) —— 确定性验证(环境命令真实执行)
|
|
8
|
+
* -> verify(artifact) —— 语义质量验证(reviewer 子会话并行)
|
|
9
|
+
* -> checkpoint(审批) —— Human-in-the-loop(P1 策略门 / P2.3 交互门)
|
|
10
|
+
*
|
|
11
|
+
* 默认 fail-fast:任一环节失败即中断(WorkflowError 家族)。
|
|
12
|
+
*
|
|
13
|
+
* P2.5 resume 关键设计:步骤状态经 prev 链**累积**(不再闭包捕获)——
|
|
14
|
+
* resume 跳过 completed 步骤时,后续步骤与最终报告仍能从
|
|
15
|
+
* journal 记录的累积状态完整重建。
|
|
16
|
+
*/
|
|
17
|
+
import { type ReviewVerdict } from "../quality/verify.js";
|
|
18
|
+
import { type RunStepsFn } from "./sequence.js";
|
|
19
|
+
export interface ReliableWorkflowOptions {
|
|
20
|
+
/** check 步骤执行的命令,默认 "node --version" */
|
|
21
|
+
checkCommand?: string;
|
|
22
|
+
/** verify 的 reviewer 数,默认 2 */
|
|
23
|
+
reviewers?: number;
|
|
24
|
+
/** checkpoint 节点标签 */
|
|
25
|
+
checkpointLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* 注入的步骤编排入口(registry ctx.runSteps);缺省 sequence 直跑。
|
|
28
|
+
* 传入后 start/resume 由其内部封装(journal 记录 / completed 前缀跳过)。
|
|
29
|
+
*/
|
|
30
|
+
runSteps?: RunStepsFn;
|
|
31
|
+
}
|
|
32
|
+
/** 链路累积状态:每一步返回 {...prev, 新字段},journal 逐步落盘 */
|
|
33
|
+
export interface ReliableState {
|
|
34
|
+
artifact?: string;
|
|
35
|
+
checkLabel?: string;
|
|
36
|
+
checkOk?: boolean;
|
|
37
|
+
verdicts?: ReviewVerdict[];
|
|
38
|
+
checkpointApproved?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface ReliableWorkflowReport {
|
|
41
|
+
topic: string;
|
|
42
|
+
artifact: string;
|
|
43
|
+
checkLabel: string;
|
|
44
|
+
checkOk: boolean;
|
|
45
|
+
verdicts: ReviewVerdict[];
|
|
46
|
+
verified: boolean;
|
|
47
|
+
checkpointApproved: boolean;
|
|
48
|
+
output: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function runReliableWorkflow(topic: string, options?: ReliableWorkflowOptions): Promise<ReliableWorkflowReport>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reliable Workflow —— P1 完整可靠执行链(用户验收 Demo 的落地)
|
|
3
|
+
*
|
|
4
|
+
* 链路:执行 -> 确定性检查 -> 语义验证(N reviewer)-> 人工审批
|
|
5
|
+
*
|
|
6
|
+
* agent(分析主题) —— 做事
|
|
7
|
+
* -> check(commandSuccess) —— 确定性验证(环境命令真实执行)
|
|
8
|
+
* -> verify(artifact) —— 语义质量验证(reviewer 子会话并行)
|
|
9
|
+
* -> checkpoint(审批) —— Human-in-the-loop(P1 策略门 / P2.3 交互门)
|
|
10
|
+
*
|
|
11
|
+
* 默认 fail-fast:任一环节失败即中断(WorkflowError 家族)。
|
|
12
|
+
*
|
|
13
|
+
* P2.5 resume 关键设计:步骤状态经 prev 链**累积**(不再闭包捕获)——
|
|
14
|
+
* resume 跳过 completed 步骤时,后续步骤与最终报告仍能从
|
|
15
|
+
* journal 记录的累积状态完整重建。
|
|
16
|
+
*/
|
|
17
|
+
import { assert } from "../quality/check.js";
|
|
18
|
+
import { checkpoint } from "../quality/checkpoint.js";
|
|
19
|
+
import { commandSuccess } from "../quality/predicates.js";
|
|
20
|
+
import { assertVerify } from "../quality/verify.js";
|
|
21
|
+
import { observeWorkflow } from "../observability/observe.js";
|
|
22
|
+
import { agent } from "./agent.js";
|
|
23
|
+
import { phase } from "./phase.js";
|
|
24
|
+
import { sequence } from "./sequence.js";
|
|
25
|
+
export async function runReliableWorkflow(topic, options) {
|
|
26
|
+
const checkCommand = options?.checkCommand ?? "node --version";
|
|
27
|
+
const reviewers = options?.reviewers ?? 2;
|
|
28
|
+
const runSteps = options?.runSteps ?? ((steps, stepOptions) => sequence(steps, stepOptions));
|
|
29
|
+
return observeWorkflow("reliable", async () => {
|
|
30
|
+
phase("Execute");
|
|
31
|
+
const state = await runSteps([
|
|
32
|
+
// 1. 执行:分析主题
|
|
33
|
+
async () => {
|
|
34
|
+
const result = await agent(`针对主题「${topic}」写一份简明分析(3-5 个要点)。` +
|
|
35
|
+
"直接用你自己的知识回答,禁止调用 workflow 或其他任何工具。");
|
|
36
|
+
return { artifact: result.output };
|
|
37
|
+
},
|
|
38
|
+
// 2. 确定性检查:环境命令真实执行(失败即中断:assert 严格版)
|
|
39
|
+
async (prev) => {
|
|
40
|
+
const label = `check: ${checkCommand} must succeed`;
|
|
41
|
+
const result = await assert(() => commandSuccess(checkCommand), label);
|
|
42
|
+
return { ...prev, checkLabel: label, checkOk: result.ok };
|
|
43
|
+
},
|
|
44
|
+
// 3. 语义验证:N reviewer 并行评审 agent 产物(任一 fail 即中断:assertVerify 严格版)
|
|
45
|
+
async (prev) => {
|
|
46
|
+
const result = await assertVerify(prev?.artifact ?? "", {
|
|
47
|
+
reviewers,
|
|
48
|
+
label: `verify: ${topic}`,
|
|
49
|
+
criteria: "分析切题、要点清晰、无事实性错误",
|
|
50
|
+
});
|
|
51
|
+
return { ...prev, verdicts: result.verdicts };
|
|
52
|
+
},
|
|
53
|
+
// 4. 人工审批(P1 策略门 / P2.3 交互门,经 CheckpointGate 注入)
|
|
54
|
+
async (prev) => {
|
|
55
|
+
await checkpoint("验证完成,是否继续?", {
|
|
56
|
+
label: options?.checkpointLabel ?? "final-review",
|
|
57
|
+
});
|
|
58
|
+
return { ...prev, checkpointApproved: true };
|
|
59
|
+
},
|
|
60
|
+
], { stepNames: ["execute", "check", "verify", "checkpoint"] });
|
|
61
|
+
phase("Done");
|
|
62
|
+
const artifact = state?.artifact ?? "";
|
|
63
|
+
const checkLabel = state?.checkLabel ?? "";
|
|
64
|
+
const checkOk = state?.checkOk ?? false;
|
|
65
|
+
const verdicts = state?.verdicts ?? [];
|
|
66
|
+
const checkpointApproved = state?.checkpointApproved ?? false;
|
|
67
|
+
const passed = verdicts.filter((v) => v.verdict === "pass").length;
|
|
68
|
+
const output = [
|
|
69
|
+
`# Reliable Workflow 报告:${topic}`,
|
|
70
|
+
"",
|
|
71
|
+
`1. 执行:agent 已产出分析(${artifact.length} 字符)`,
|
|
72
|
+
`2. 确定性检查 ${checkOk ? "通过" : "失败"}:${checkLabel}`,
|
|
73
|
+
`3. 语义验证 ${passed}/${verdicts.length} reviewer 通过`,
|
|
74
|
+
`4. 审批:${checkpointApproved ? "已批准" : "未批准"}`,
|
|
75
|
+
"",
|
|
76
|
+
"## 分析产物",
|
|
77
|
+
"",
|
|
78
|
+
artifact,
|
|
79
|
+
].join("\n");
|
|
80
|
+
return {
|
|
81
|
+
topic,
|
|
82
|
+
artifact,
|
|
83
|
+
checkLabel,
|
|
84
|
+
checkOk,
|
|
85
|
+
verdicts,
|
|
86
|
+
verified: passed === verdicts.length,
|
|
87
|
+
checkpointApproved,
|
|
88
|
+
output,
|
|
89
|
+
};
|
|
90
|
+
}, { topic, reviewers, checkCommand });
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=reliable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reliable.js","sourceRoot":"","sources":["../../src/workflow/reliable.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* retry() —— 失败重试组合子(P1.4)
|
|
3
|
+
*
|
|
4
|
+
* 基于统一失败模型(WorkflowError 家族):默认重试一切失败,
|
|
5
|
+
* 可用 retryOn 过滤(例如对配额类错误不重试,防重试风暴——见经验沉淀)。
|
|
6
|
+
*
|
|
7
|
+
* 防锤击默认值(经验教训 tool-throw-retry-storm-and-concurrency.md):
|
|
8
|
+
* attempts=3 / delayMs=1000 / exponential backoff / maxDelayMs=30s
|
|
9
|
+
*
|
|
10
|
+
* 拒绝契约:
|
|
11
|
+
* - 重试耗尽 -> WorkflowRetryError(attempts + lastError cause 链)
|
|
12
|
+
* - retryOn 判定不可重试 -> 原样抛出原始异常(调用方自行分类)
|
|
13
|
+
*/
|
|
14
|
+
export interface RetryOptions {
|
|
15
|
+
/** 总尝试次数(含首次),默认 3 */
|
|
16
|
+
attempts?: number;
|
|
17
|
+
/** 首次重试前等待毫秒,默认 1000;0 表示立即重试 */
|
|
18
|
+
delayMs?: number;
|
|
19
|
+
/** 退避策略:fixed 固定间隔 / exponential 指数退避(默认) */
|
|
20
|
+
backoff?: "fixed" | "exponential";
|
|
21
|
+
/** exponential 模式下的单次等待上限,默认 30000 */
|
|
22
|
+
maxDelayMs?: number;
|
|
23
|
+
/** 重试过滤器:返回 false 的异常不重试、原样抛出 */
|
|
24
|
+
retryOn?: (error: unknown) => boolean;
|
|
25
|
+
/** 日志标签 */
|
|
26
|
+
label?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function retry<T>(task: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* retry() —— 失败重试组合子(P1.4)
|
|
3
|
+
*
|
|
4
|
+
* 基于统一失败模型(WorkflowError 家族):默认重试一切失败,
|
|
5
|
+
* 可用 retryOn 过滤(例如对配额类错误不重试,防重试风暴——见经验沉淀)。
|
|
6
|
+
*
|
|
7
|
+
* 防锤击默认值(经验教训 tool-throw-retry-storm-and-concurrency.md):
|
|
8
|
+
* attempts=3 / delayMs=1000 / exponential backoff / maxDelayMs=30s
|
|
9
|
+
*
|
|
10
|
+
* 拒绝契约:
|
|
11
|
+
* - 重试耗尽 -> WorkflowRetryError(attempts + lastError cause 链)
|
|
12
|
+
* - retryOn 判定不可重试 -> 原样抛出原始异常(调用方自行分类)
|
|
13
|
+
*/
|
|
14
|
+
import { WorkflowRetryError } from "../runtime/errors.js";
|
|
15
|
+
function sleep(ms) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
export async function retry(task, options) {
|
|
19
|
+
const attempts = Math.max(1, Math.floor(options?.attempts ?? 3));
|
|
20
|
+
const delayMs = options?.delayMs ?? 1000;
|
|
21
|
+
const backoff = options?.backoff ?? "exponential";
|
|
22
|
+
const maxDelayMs = options?.maxDelayMs ?? 30_000;
|
|
23
|
+
const retryOn = options?.retryOn ?? (() => true);
|
|
24
|
+
const label = options?.label ?? "";
|
|
25
|
+
let lastError;
|
|
26
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
27
|
+
try {
|
|
28
|
+
return await task();
|
|
29
|
+
}
|
|
30
|
+
catch (cause) {
|
|
31
|
+
lastError = cause;
|
|
32
|
+
if (attempt === attempts) {
|
|
33
|
+
throw new WorkflowRetryError(attempts, lastError, label);
|
|
34
|
+
}
|
|
35
|
+
if (!retryOn(cause)) {
|
|
36
|
+
// 不可重试:原样抛出,让调用方的失败策略接手
|
|
37
|
+
throw cause;
|
|
38
|
+
}
|
|
39
|
+
const wait = backoff === "exponential"
|
|
40
|
+
? Math.min(delayMs * 2 ** (attempt - 1), maxDelayMs)
|
|
41
|
+
: delayMs;
|
|
42
|
+
if (wait > 0) {
|
|
43
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
44
|
+
console.log(`[agentic-workflow] retry ${attempt}/${attempts - 1}${label ? ` (${label})` : ""} ` +
|
|
45
|
+
`in ${wait}ms after: ${message}`);
|
|
46
|
+
await sleep(wait);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/* istanbul ignore next -- 循环必然 return/throw,不可达 */
|
|
51
|
+
throw new WorkflowRetryError(attempts, lastError, label);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/workflow/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAiBzD,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,IAAsB,EACtB,OAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,IAAI,CAAA;IACxC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,aAAa,CAAA;IACjD,MAAM,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,MAAM,CAAA;IAChD,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAChD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAA;IAElC,IAAI,SAAkB,CAAA;IAEtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;QACrD,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAA;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAA;YAEjB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,MAAM,IAAI,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;YAC1D,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpB,wBAAwB;gBACxB,MAAM,KAAK,CAAA;YACb,CAAC;YAED,MAAM,IAAI,GACR,OAAO,KAAK,aAAa;gBACvB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC;gBACpD,CAAC,CAAC,OAAO,CAAA;YACb,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACtE,OAAO,CAAC,GAAG,CACT,4BAA4B,OAAO,IAAI,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG;oBACjF,MAAM,IAAI,aAAa,OAAO,EAAE,CACnC,CAAA;gBACD,MAAM,KAAK,CAAC,IAAI,CAAC,CAAA;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,IAAI,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;AAC1D,CAAC"}
|