@qing3a/flow-rpa-app 0.5.12 → 0.7.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/README.md +16 -13
- package/dist/cli.d.ts +52 -19
- package/dist/cli.js +257 -93
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +4 -20
- package/dist/config.js +23 -45
- package/dist/config.js.map +1 -1
- package/dist/gate-key.d.ts +65 -0
- package/dist/gate-key.js +93 -0
- package/dist/gate-key.js.map +1 -0
- package/dist/gate-runtime.d.ts +27 -0
- package/dist/gate-runtime.js +44 -0
- package/dist/gate-runtime.js.map +1 -0
- package/dist/http.js +1 -2
- package/dist/http.js.map +1 -1
- package/dist/main.js +12 -12
- package/dist/main.js.map +1 -1
- package/dist/registry.d.ts +33 -2
- package/dist/registry.js +94 -10
- package/dist/registry.js.map +1 -1
- package/dist/runner.d.ts +59 -14
- package/dist/runner.js +158 -76
- package/dist/runner.js.map +1 -1
- package/dist/server.d.ts +11 -21
- package/dist/server.js +36 -132
- package/dist/server.js.map +1 -1
- package/dist/session-rotation.d.ts +58 -0
- package/dist/session-rotation.js +61 -0
- package/dist/session-rotation.js.map +1 -0
- package/dist/status.d.ts +55 -15
- package/dist/status.js +116 -65
- package/dist/status.js.map +1 -1
- package/package.json +2 -2
- package/skill/flow-rpa-engine.md +159 -50
- package/starter/baseline.json +18 -0
- package/starter/liepin_search_resumes/flow.json +34 -10
package/dist/registry.js
CHANGED
|
@@ -1,17 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { parseFlow } from '@qing3a/flow-rpa-engine/src/validate.js';
|
|
4
5
|
import { FlowPatchSchema } from '@qing3a/flow-rpa-engine/src/schema.js';
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/** 基线文件名(与流程目录同级,即 flows/ 下) */
|
|
7
|
+
export const BASELINE_FILE = 'baseline.json';
|
|
8
|
+
/** 解析基线清单(缺失/损坏/格式不符 → undefined = 无校验;**绝不抛错**) */
|
|
9
|
+
export function loadBaseline(flowsDir) {
|
|
8
10
|
let raw;
|
|
9
11
|
try {
|
|
10
|
-
raw = readFileSync(
|
|
12
|
+
raw = readFileSync(join(flowsDir, BASELINE_FILE), 'utf8');
|
|
11
13
|
}
|
|
12
14
|
catch {
|
|
13
|
-
return undefined; //
|
|
15
|
+
return undefined; // 无基线文件(老版本流程目录 / 用户自建目录)
|
|
14
16
|
}
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (!parsed || typeof parsed !== 'object' || typeof parsed.flows !== 'object' || parsed.flows === null)
|
|
20
|
+
return undefined;
|
|
21
|
+
return {
|
|
22
|
+
version: typeof parsed.version === 'number' ? parsed.version : 0,
|
|
23
|
+
generatedAt: typeof parsed.generatedAt === 'string' ? parsed.generatedAt : '',
|
|
24
|
+
flows: parsed.flows,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return undefined; // 基线损坏 → 退化为无校验(fail-soft:它只是「来源可见性」,不是执行前置)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** sha256(十六进制小写) */
|
|
32
|
+
function sha256(bytes) {
|
|
33
|
+
return createHash('sha256').update(bytes).digest('hex');
|
|
34
|
+
}
|
|
35
|
+
/** 流程目录下的文件名(小写排序;目录/子目录不进清单——starter 包只有平铺文件) */
|
|
36
|
+
function listFlowFiles(flowDir) {
|
|
37
|
+
try {
|
|
38
|
+
return readdirSync(flowDir)
|
|
39
|
+
.filter((f) => {
|
|
40
|
+
try {
|
|
41
|
+
return statSync(join(flowDir, f)).isFile();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
.sort();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** 读取用户覆盖层(`flow.patch.json` 的**原始字节**;不存在 → undefined) */
|
|
54
|
+
function readPatchRaw(flowDir) {
|
|
55
|
+
try {
|
|
56
|
+
return readFileSync(join(flowDir, 'flow.patch.json'), 'utf8');
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** 解析覆盖层原始字节(语法/结构错误 → 警告 + undefined;原流程生效) */
|
|
63
|
+
function parsePatch(raw, name, warnings) {
|
|
15
64
|
try {
|
|
16
65
|
return FlowPatchSchema.parse(JSON.parse(raw));
|
|
17
66
|
}
|
|
@@ -41,7 +90,7 @@ export class FlowRegistry {
|
|
|
41
90
|
flowsDir;
|
|
42
91
|
/** flow_id → 已解析的流程定义(缓存;flow 为 patch 合并后的最终形态) */
|
|
43
92
|
cache = new Map();
|
|
44
|
-
/** 最近一次扫描的流程加载警告(坏 flow.json / 坏 patch
|
|
93
|
+
/** 最近一次扫描的流程加载警告(坏 flow.json / 坏 patch / 偏离内置基线等;fail-loud 警告态,get_status 呈现) */
|
|
45
94
|
_warnings = [];
|
|
46
95
|
constructor(flowsDir) {
|
|
47
96
|
this.flowsDir = flowsDir;
|
|
@@ -50,9 +99,10 @@ export class FlowRegistry {
|
|
|
50
99
|
warnings() {
|
|
51
100
|
return this._warnings;
|
|
52
101
|
}
|
|
53
|
-
/** 扫描 flows/ 下各子目录的 flow.json(含 D5 patch
|
|
102
|
+
/** 扫描 flows/ 下各子目录的 flow.json(含 D5 patch 合并 + T035-2 基线比对) */
|
|
54
103
|
list() {
|
|
55
104
|
this._warnings = [];
|
|
105
|
+
this.cache.clear(); // 每次扫描重建缓存:来源标注不做陈旧缓存(文件可能刚被改)
|
|
56
106
|
const out = [];
|
|
57
107
|
let entries;
|
|
58
108
|
try {
|
|
@@ -63,6 +113,9 @@ export class FlowRegistry {
|
|
|
63
113
|
catch {
|
|
64
114
|
return [];
|
|
65
115
|
}
|
|
116
|
+
// T035-2:基线只读一次(每目录都读会浪费;缺失 → 无校验降级)
|
|
117
|
+
const baseline = loadBaseline(this.flowsDir);
|
|
118
|
+
let modifiedCount = 0;
|
|
66
119
|
for (const name of entries) {
|
|
67
120
|
const flowDir = join(this.flowsDir, name);
|
|
68
121
|
const flowPath = join(flowDir, 'flow.json');
|
|
@@ -74,7 +127,27 @@ export class FlowRegistry {
|
|
|
74
127
|
continue;
|
|
75
128
|
}
|
|
76
129
|
try {
|
|
77
|
-
const
|
|
130
|
+
const patchRaw = readPatchRaw(flowDir);
|
|
131
|
+
const flow = applyPatch(parseFlow(raw), patchRaw !== undefined ? parsePatch(patchRaw, name, this._warnings) : undefined);
|
|
132
|
+
// T035-2(S6):来源判定——基线声称认得这个 id 吗?逐文件哈希一致吗?
|
|
133
|
+
// 目录名与 flow.id 都可作为基线键(starter 同步后两者一致;用户改名后仍能认出来)
|
|
134
|
+
const base = baseline?.flows?.[name] ?? baseline?.flows?.[flow.id];
|
|
135
|
+
let origin = 'local';
|
|
136
|
+
if (base && base.files && typeof base.files === 'object') {
|
|
137
|
+
const actual = new Map();
|
|
138
|
+
for (const f of listFlowFiles(flowDir))
|
|
139
|
+
actual.set(f, sha256(readFileSync(join(flowDir, f))));
|
|
140
|
+
const expected = base.files;
|
|
141
|
+
const expectedNames = Object.keys(expected);
|
|
142
|
+
const sameFileSet = expectedNames.length === actual.size && expectedNames.every((f) => actual.has(f));
|
|
143
|
+
const sameContent = sameFileSet && expectedNames.every((f) => actual.get(f) === expected[f]);
|
|
144
|
+
origin = sameContent ? 'builtin' : 'builtin-modified';
|
|
145
|
+
if (origin === 'builtin-modified') {
|
|
146
|
+
modifiedCount++;
|
|
147
|
+
// 不阻断执行(用户有权改自己的流程);只在 doctor / get_status / 启动日志呈现
|
|
148
|
+
this._warnings.push(`流程 ${flow.id} 与内置基线不一致(本地已改动)`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
78
151
|
out.push({
|
|
79
152
|
id: flow.id,
|
|
80
153
|
name: flow.name,
|
|
@@ -84,9 +157,12 @@ export class FlowRegistry {
|
|
|
84
157
|
name: i.name,
|
|
85
158
|
required: i.required === true,
|
|
86
159
|
...(i.description ? { description: i.description } : {}),
|
|
160
|
+
// T031C-1:default 一并透传(Agent 不必靠猜缺省值;executor 侧同源注入)
|
|
161
|
+
...(i.default !== undefined ? { default: String(i.default) } : {}),
|
|
87
162
|
})),
|
|
163
|
+
origin,
|
|
88
164
|
});
|
|
89
|
-
this.cache.set(flow.id, { version: flow.version, raw, flow });
|
|
165
|
+
this.cache.set(flow.id, { version: flow.version, raw, flow, origin });
|
|
90
166
|
}
|
|
91
167
|
catch (e) {
|
|
92
168
|
// D1:解析失败不静默跳过——收集警告(启动/状态页呈现),等 run_flow 才暴露太晚
|
|
@@ -94,6 +170,14 @@ export class FlowRegistry {
|
|
|
94
170
|
continue;
|
|
95
171
|
}
|
|
96
172
|
}
|
|
173
|
+
// T035-2:无基线(或基线里一个流程都不认得)→ **一行降级日志**(可校验性本身要可见,
|
|
174
|
+
// 但「包内 baseline.json 缺失」不是用户的问题,故用日志而不用警告——见 brief「不报错」)
|
|
175
|
+
if (baseline === undefined && out.length > 0) {
|
|
176
|
+
console.log(`[flow-rpa] 无内置流程基线(${BASELINE_FILE} 缺失或损坏),跳过来源校验(不阻断执行)`);
|
|
177
|
+
}
|
|
178
|
+
else if (baseline !== undefined && modifiedCount > 0) {
|
|
179
|
+
console.log(`[flow-rpa] ${modifiedCount} 个内置流程与基线不一致(本地已改动,仅告警不阻断)`);
|
|
180
|
+
}
|
|
97
181
|
out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
98
182
|
return out;
|
|
99
183
|
}
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAa,MAAM,yCAAyC,CAAA;AAC9E,OAAO,EAAE,eAAe,EAAkB,MAAM,uCAAuC,CAAA;AAoDvF,gCAAgC;AAChC,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAA;AAE5C,oDAAoD;AACpD,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA,CAAC,0BAA0B;IAC7C,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAA;QACvD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;YAAE,OAAO,SAAS,CAAA;QACxH,OAAO;YACL,OAAO,EAAE,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAChE,WAAW,EAAE,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YAC7E,KAAK,EAAE,MAAM,CAAC,KAA8B;SAC7C,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA,CAAC,6CAA6C;IAChE,CAAC;AACH,CAAC;AAED,qBAAqB;AACrB,SAAS,MAAM,CAAC,KAAsB;IACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACzD,CAAC;AAED,kDAAkD;AAClD,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,OAAO,CAAC;aACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACZ,IAAI,CAAC;gBACH,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAA;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC,CAAC;aACD,IAAI,EAAE,CAAA;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,2DAA2D;AAC3D,SAAS,YAAY,CAAC,OAAe;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAA;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,SAAS,UAAU,CAAC,GAAW,EAAE,IAAY,EAAE,QAAkB;IAC/D,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAc,CAAA;IAC5D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uCAAuC;QACvC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,oCAAoC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACtG,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,KAA4B;IACjE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACjC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAC3B,IAAI,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;QAChB,OAAO;YACL,GAAG,CAAC;YACJ,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxD,CAAA;IACH,CAAC,CAAC,CAAA;IACF,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAA;AAC3B,CAAC;AAED,MAAM,OAAO,YAAY;IACN,QAAQ,CAAQ;IACjC,mDAAmD;IAC3C,KAAK,GAAG,IAAI,GAAG,EAA4E,CAAA;IACnG,iFAAiF;IACzE,SAAS,GAAa,EAAE,CAAA;IAEhC,YAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED,6CAA6C;IAC7C,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,8DAA8D;IAC9D,IAAI;QACF,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA,CAAC,+BAA+B;QAClD,MAAM,GAAG,GAAkB,EAAE,CAAA;QAC7B,IAAI,OAAiB,CAAA;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC1D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAA;QACX,CAAC;QACD,qCAAqC;QACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5C,IAAI,aAAa,GAAG,CAAC,CAAA;QACrB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;YAC3C,IAAI,GAAW,CAAA;YACf,IAAI,CAAC;gBACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,SAAQ;YACV,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;gBACtC,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;gBACxH,2CAA2C;gBAC3C,mDAAmD;gBACnD,MAAM,IAAI,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAClE,IAAI,MAAM,GAAe,OAAO,CAAA;gBAChC,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;oBACxC,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC;wBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;oBAC7F,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAA;oBAC3B,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;oBAC3C,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;oBACrG,MAAM,WAAW,GAAG,WAAW,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;oBAC5F,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAA;oBACrD,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;wBAClC,aAAa,EAAE,CAAA;wBACf,oDAAoD;wBACpD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAA;oBACtD,CAAC;gBACH,CAAC;gBACD,GAAG,CAAC,IAAI,CAAC;oBACP,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACtC,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI;wBAC7B,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACxD,qDAAqD;wBACrD,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACnE,CAAC,CAAC;oBACH,MAAM;iBACP,CAAC,CAAA;gBACF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YACvE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,gDAAgD;gBAChD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,oBAAoB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;gBAC5F,SAAQ;YACV,CAAC;QACH,CAAC;QACD,kDAAkD;QAClD,yDAAyD;QACzD,IAAI,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,sBAAsB,aAAa,uBAAuB,CAAC,CAAA;QACzE,CAAC;aAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,cAAc,aAAa,4BAA4B,CAAC,CAAA;QACtE,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5D,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,CAAA;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B,CAAC;IAED,2BAA2B;IAC3B,UAAU;QACR,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;CACF"}
|
package/dist/runner.d.ts
CHANGED
|
@@ -3,12 +3,13 @@ import type { EnvCheck } from '@qing3a/flow-rpa-engine/src/schema.js';
|
|
|
3
3
|
import { type DomSnapshot } from '@qing3a/flow-rpa-engine/src/export.js';
|
|
4
4
|
import { SuggestionStore, type FlowPatchApplier } from '@qing3a/flow-rpa-engine/src/learning.js';
|
|
5
5
|
import { RunStore } from '@qing3a/flow-rpa-engine/src/storage.js';
|
|
6
|
-
import {
|
|
6
|
+
import { ObservationExporter } from '@qing3a/flow-rpa-engine/src/export.js';
|
|
7
7
|
import { PerfGate } from '@qing3a/flow-rpa-engine/src/bench.js';
|
|
8
8
|
import { CooldownGate, SiteGate } from '@qing3a/flow-rpa-engine/src/gate.js';
|
|
9
9
|
import { BehaviorArchive } from '@qing3a/flow-rpa-engine/src/behavior.js';
|
|
10
|
-
import { FlowRegistry } from './registry.js';
|
|
10
|
+
import { FlowRegistry, type FlowOrigin } from './registry.js';
|
|
11
11
|
import type { RunConfig } from './config.js';
|
|
12
|
+
import { type GateKeyResolution, type GateKeySource } from './gate-key.js';
|
|
12
13
|
/**
|
|
13
14
|
* run_flow 异步执行层(移植 Rust `server.rs` 的 execute_run/spawn_run + M9 D-R1/D-R2)。
|
|
14
15
|
*
|
|
@@ -30,7 +31,21 @@ export interface RunFlowResult {
|
|
|
30
31
|
pausedAt?: string;
|
|
31
32
|
/** T015 P0-1:暂停原因(login / env_check / paused) */
|
|
32
33
|
pauseReason?: 'login' | 'env_check' | 'paused';
|
|
34
|
+
/** T027/B2:结构化下一步指引(暂停/预检拒绝时;只进工具返回与 CLI 输出,不落 run.json——data/ 格式冻结) */
|
|
35
|
+
pauseGuidance?: string;
|
|
36
|
+
/** T027/B2:登录态预检拒绝(run 保持 paused 未执行;CLI 据此退出码 1,与「resume 后再次 paused」区分) */
|
|
37
|
+
precheckRejected?: boolean;
|
|
38
|
+
/** T035-2(S6):流程来源(builtin / builtin-modified / local)——**只进工具面/CLI 输出,不落 run.json** */
|
|
39
|
+
origin?: FlowOrigin;
|
|
40
|
+
/** T035-1(S2):本次 run 实际使用的同站闸门 key(`site:<host>` / `flow:<id>`)与维度——只进工具面 */
|
|
41
|
+
gateKey?: string;
|
|
42
|
+
gateKeySource?: GateKeySource;
|
|
33
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* T027/B2:pauseReason → 结构化下一步指引(人工接管交接,bsk human-in-the-loop 借鉴)。
|
|
46
|
+
* 只进工具返回 message / CLI 输出,绝不落 run.json(data/ 格式冻结);绝不自动 resume(无人值守边界)。
|
|
47
|
+
*/
|
|
48
|
+
export declare function pauseGuidance(reason: 'login' | 'env_check' | 'paused' | undefined, runId: string): string;
|
|
34
49
|
export interface RunFlowArgs {
|
|
35
50
|
flowId: string;
|
|
36
51
|
vars: Record<string, string>;
|
|
@@ -45,6 +60,12 @@ export interface RunFlowArgs {
|
|
|
45
60
|
loopIter?: number;
|
|
46
61
|
loopSub?: number;
|
|
47
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* T035-1(S2):调用方**已解析过**的闸门 key(server/CLI 的 run 前 acquire 用过的那一个)。
|
|
65
|
+
* 传入 = 同一 run 的 acquire 与 penalize 记同一个 key(不重复探测页面、不产生二次口径漂移);
|
|
66
|
+
* 不传(如 resume_run)= run 内按「运行时 host → 流程声明 host → flow 维度」现解析。
|
|
67
|
+
*/
|
|
68
|
+
gateKeyResolved?: GateKeyResolution;
|
|
48
69
|
}
|
|
49
70
|
/** 执行上下文(runner 持有全部共享状态) */
|
|
50
71
|
export interface ExecCtx {
|
|
@@ -52,7 +73,7 @@ export interface ExecCtx {
|
|
|
52
73
|
store: RunStore;
|
|
53
74
|
runs: Map<string, RunFlowResult>;
|
|
54
75
|
suggestions: SuggestionStore;
|
|
55
|
-
platform:
|
|
76
|
+
platform: ObservationExporter;
|
|
56
77
|
siteGate: SiteGate;
|
|
57
78
|
coolGate: CooldownGate;
|
|
58
79
|
perf: PerfGate;
|
|
@@ -106,7 +127,17 @@ export declare class MockPage implements PageOps {
|
|
|
106
127
|
private extracted;
|
|
107
128
|
/** 测试用:waitMs 真实阻塞时长(默认 0 = no-op;设 >0 可让 run 慢下来验证队列忙) */
|
|
108
129
|
slowWaitMs: number;
|
|
130
|
+
/** 测试用:注入的非拟人兜底事件(takeFallbacks 取走并清空;默认空 = 纯拟人路径) */
|
|
131
|
+
fallbackEvents: Array<{
|
|
132
|
+
kind: string;
|
|
133
|
+
selector?: string;
|
|
134
|
+
}>;
|
|
109
135
|
setEnvCheck(config: EnvCheck | undefined): void;
|
|
136
|
+
/** 兜底计量(PageOps.takeFallbacks):取走并清空 */
|
|
137
|
+
takeFallbacks(): Array<{
|
|
138
|
+
kind: string;
|
|
139
|
+
selector?: string;
|
|
140
|
+
}>;
|
|
110
141
|
navigate(url: string): Promise<void>;
|
|
111
142
|
click(sel: string, index: number): Promise<void>;
|
|
112
143
|
input(_sel: string, v: string): Promise<void>;
|
|
@@ -123,29 +154,45 @@ export declare class MockPage implements PageOps {
|
|
|
123
154
|
/** mock 的 snapshotDom(D-S1 验收:mock 模式不采集 → 返回 undefined 语义由 executeRun 跳过处理) */
|
|
124
155
|
snapshotDom(): Promise<DomSnapshot>;
|
|
125
156
|
}
|
|
126
|
-
/**
|
|
127
|
-
* 自动上报(自动注册闭环):平台已配置时,run 结束后自动 deliver + 上传观察包到 md-forge。
|
|
128
|
-
* 失败记台账 Failed(sync_pending_uploads / 启动 bootstrap 可重试);平台未配置 → 零开销 no-op。
|
|
129
|
-
*/
|
|
130
|
-
export declare function autoUploadRun(ctx: ExecCtx, runId: string): Promise<void>;
|
|
131
157
|
/**
|
|
132
158
|
* T020 P0-2:run 完成后顺带清理——超窗 runs 归档到 data/archive、snapshots/extracted 删除、
|
|
133
|
-
* 残留 *.tmp
|
|
159
|
+
* 残留 *.tmp 清扫;失败仅日志(不阻断 run 收尾)。
|
|
160
|
+
* T029:观察包自动上传已随 md-forge 退役移除(export_observation 仍可本地导出)。
|
|
134
161
|
*/
|
|
135
162
|
export declare function housekeepingAfterRun(ctx: ExecCtx): Promise<void>;
|
|
136
163
|
/** 同步执行一个 run(构造驱动 → 解释执行 → 落盘 → 自动上报 → 更新运行状态) */
|
|
137
|
-
export declare function executeRun(ctx: ExecCtx, args: RunFlowArgs, runId: string
|
|
164
|
+
export declare function executeRun(ctx: ExecCtx, args: RunFlowArgs, runId: string,
|
|
165
|
+
/**
|
|
166
|
+
* 测试注入的页面驱动(**仅 mock 模式生效**;缺省 new MockPage())。
|
|
167
|
+
* 真实模式恒用 CdpPage —— 注入值被忽略,测试缝隙不会漏进真实执行路径。
|
|
168
|
+
*/
|
|
169
|
+
pageOverride?: PageOps): Promise<RunFlowResult>;
|
|
170
|
+
/**
|
|
171
|
+
* T027/B2:登录态探测器(真实模式缺省实现)——连 9222 现有标签页,
|
|
172
|
+
* 用 engine region.ts 登录区双重特征(isLoginSignal:路由特征 + 页面文本强标记,与 executor 每步复查同源)判定是否已登录。
|
|
173
|
+
* 标签页选择:优先与暂停流程同 host(用户在该站登录的页);无同 host → 首个 page 标签。
|
|
174
|
+
* 返回 true = 已登录(预检通过);false = 仍在登录区。
|
|
175
|
+
* 任何失败(浏览器不可达/无标签页/evaluate 失败)→ 抛错(调用方视为「预检不可判定」放行——评审定案 Q2)。
|
|
176
|
+
*/
|
|
177
|
+
export declare function probeLoginState(ctx: ExecCtx, flowId: string): Promise<boolean>;
|
|
178
|
+
/** T027/B2:resume 预检配置(detectLogin 注入式——mock/测试替换;缺省真实模式用 probeLoginState) */
|
|
179
|
+
export interface ResumePrecheck {
|
|
180
|
+
detectLogin?: () => Promise<boolean>;
|
|
181
|
+
}
|
|
138
182
|
/**
|
|
139
183
|
* T015 P0-2:resume_run——从暂停点继续执行(人工接管后调用)。
|
|
140
184
|
* 语义:
|
|
141
185
|
* - 仅接受 status=paused 的 run(执行中/非 paused → 明确拒绝;不重跑已完成步骤);
|
|
142
186
|
* - 先校验暂停超时(缺省 5 分钟可配置)→ 超时转 failed(防无限挂起);
|
|
187
|
+
* - T027/B2 登录态预检:pauseReason=login 时先探测引擎浏览器登录态——仍在登录区 → 拒绝本次 resume
|
|
188
|
+
* (返回 precheckRejected,run 保持 paused,不消耗真实执行轮次——防封视角:真实站点的无谓失败本身就是风险信号);
|
|
189
|
+
* 预检不可判定(浏览器不可达等)→ 放行走原路径(executor 每步登录复查兜底);mock 模式不预检;
|
|
143
190
|
* - 复用 vars(暂停时已持久化)与 resumeStepIndex/resumeLoop* 上下文,从暂停点继续;
|
|
144
191
|
* executor 每步前自动重新校验登录区/验证码(仍异常 → 再次 paused 并提示,不自动重试——防封不变);
|
|
145
192
|
* - 完成后正常走 done/failed 落盘 + L2 学习 + 自动上报(与普通 run 一致)。
|
|
146
193
|
* 返回 RunFlowResult(status: running / done / failed / paused)。
|
|
147
194
|
*/
|
|
148
|
-
export declare function resumeRun(ctx: ExecCtx, runId: string): Promise<RunFlowResult>;
|
|
195
|
+
export declare function resumeRun(ctx: ExecCtx, runId: string, precheck?: ResumePrecheck): Promise<RunFlowResult>;
|
|
149
196
|
/**
|
|
150
197
|
* T009 P0-1:会话轮换——重启引擎浏览器进程(同 profile data/edge-profile,登录态持久保留)。
|
|
151
198
|
* 语义:kill 当前 9222 Edge 调试实例 → 用同一 user-data-dir 重新拉起新会话(新进程/新 CDP 连接)。
|
|
@@ -153,9 +200,7 @@ export declare function resumeRun(ctx: ExecCtx, runId: string): Promise<RunFlowR
|
|
|
153
200
|
* 不破坏 open-browser/懒加载登录:登录态在 profile(重启保留);下次 open-browser/run 重新拉起。
|
|
154
201
|
*/
|
|
155
202
|
export declare function rotateBrowserSession(port: number, edgePath: string, userDataDir: string): Promise<void>;
|
|
156
|
-
/**
|
|
157
|
-
export declare function autoUploadSuggestions(ctx: ExecCtx, flowId: string, suggestionIds: string[]): Promise<void>;
|
|
158
|
-
/** 流程的目标站点 host(取首个 navigate 步骤的 url;无 navigate 返回 undefined —— 不节流 mock) */
|
|
203
|
+
/** 流程声明的目标站点 host(T035-1 起 = **全部** navigate 步骤里最后一个;无 navigate → undefined) */
|
|
159
204
|
export declare function flowHost(ctx: ExecCtx, flowId: string): string | undefined;
|
|
160
205
|
/** 队列当前状态(自描述聚合用 D-S1;只读) */
|
|
161
206
|
export declare function queueState(): {
|