@windsland52/maafw-live 0.0.0-stage → 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 +278 -2
- package/bin/maafw-live.mjs +25 -0
- package/docs/daemon-protocol.md +116 -0
- package/docs/keyframe-evidence-contract-v0.md +61 -0
- package/docs/keyframe-retention-contract-v0.md +236 -0
- package/lib/client/daemon.js +234 -0
- package/lib/client/daemon.js.map +1 -0
- package/lib/commands/annotate.js +172 -0
- package/lib/commands/annotate.js.map +1 -0
- package/lib/commands/calibrate.js +61 -0
- package/lib/commands/calibrate.js.map +1 -0
- package/lib/commands/color.js +73 -0
- package/lib/commands/color.js.map +1 -0
- package/lib/commands/crop.js +228 -0
- package/lib/commands/crop.js.map +1 -0
- package/lib/commands/env.js +215 -0
- package/lib/commands/env.js.map +1 -0
- package/lib/commands/index.js +64 -0
- package/lib/commands/index.js.map +1 -0
- package/lib/commands/input.js +219 -0
- package/lib/commands/input.js.map +1 -0
- package/lib/commands/kf.js +131 -0
- package/lib/commands/kf.js.map +1 -0
- package/lib/commands/reco.js +211 -0
- package/lib/commands/reco.js.map +1 -0
- package/lib/commands/repl.js +698 -0
- package/lib/commands/repl.js.map +1 -0
- package/lib/commands/runtime.js +514 -0
- package/lib/commands/runtime.js.map +1 -0
- package/lib/commands/skill.js +169 -0
- package/lib/commands/skill.js.map +1 -0
- package/lib/commands/timing.js +229 -0
- package/lib/commands/timing.js.map +1 -0
- package/lib/commands/version.js +66 -0
- package/lib/commands/version.js.map +1 -0
- package/lib/daemon/framed.mjs +2850 -0
- package/lib/daemon/reco_child.mjs +146 -0
- package/lib/exec.js +96 -0
- package/lib/exec.js.map +1 -0
- package/lib/flags.js +42 -0
- package/lib/flags.js.map +1 -0
- package/lib/image.js +90 -0
- package/lib/image.js.map +1 -0
- package/lib/index.js +139 -0
- package/lib/index.js.map +1 -0
- package/lib/interface/index.js +12 -0
- package/lib/interface/index.js.map +1 -0
- package/lib/interface/jsonc.js +95 -0
- package/lib/interface/jsonc.js.map +1 -0
- package/lib/interface/load.js +307 -0
- package/lib/interface/load.js.map +1 -0
- package/lib/interface/override.js +103 -0
- package/lib/interface/override.js.map +1 -0
- package/lib/interface/plan.js +188 -0
- package/lib/interface/plan.js.map +1 -0
- package/lib/pkg.js +18 -0
- package/lib/pkg.js.map +1 -0
- package/lib/protocol.js +90 -0
- package/lib/protocol.js.map +1 -0
- package/lib/runtime/actions.js +110 -0
- package/lib/runtime/actions.js.map +1 -0
- package/lib/runtime/keyframes.js +73 -0
- package/lib/runtime/keyframes.js.map +1 -0
- package/lib/runtime/session.js +86 -0
- package/lib/runtime/session.js.map +1 -0
- package/lib/types/client/daemon.d.ts +86 -0
- package/lib/types/commands/annotate.d.ts +3 -0
- package/lib/types/commands/calibrate.d.ts +7 -0
- package/lib/types/commands/color.d.ts +9 -0
- package/lib/types/commands/crop.d.ts +3 -0
- package/lib/types/commands/env.d.ts +2 -0
- package/lib/types/commands/index.d.ts +13 -0
- package/lib/types/commands/input.d.ts +17 -0
- package/lib/types/commands/kf.d.ts +10 -0
- package/lib/types/commands/reco.d.ts +23 -0
- package/lib/types/commands/repl.d.ts +2 -0
- package/lib/types/commands/runtime.d.ts +48 -0
- package/lib/types/commands/skill.d.ts +17 -0
- package/lib/types/commands/timing.d.ts +64 -0
- package/lib/types/commands/version.d.ts +3 -0
- package/lib/types/exec.d.ts +31 -0
- package/lib/types/flags.d.ts +58 -0
- package/lib/types/image.d.ts +27 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/interface/index.d.ts +11 -0
- package/lib/types/interface/jsonc.d.ts +9 -0
- package/lib/types/interface/load.d.ts +113 -0
- package/lib/types/interface/override.d.ts +33 -0
- package/lib/types/interface/plan.d.ts +47 -0
- package/lib/types/pkg.d.ts +6 -0
- package/lib/types/protocol.d.ts +108 -0
- package/lib/types/runtime/actions.d.ts +166 -0
- package/lib/types/runtime/keyframes.d.ts +43 -0
- package/lib/types/runtime/session.d.ts +53 -0
- package/lib/types/update-check.d.ts +20 -0
- package/lib/types/usage.d.ts +3 -0
- package/lib/update-check.js +97 -0
- package/lib/update-check.js.map +1 -0
- package/lib/usage.js +50 -0
- package/lib/usage.js.map +1 -0
- package/package.json +81 -4
- package/skills/README.md +51 -0
- package/skills/maafw-live/SKILL.md +263 -0
- package/skills/maafw-live/references/examples.md +238 -0
- package/skills/maafw-live/references/pitfalls.md +118 -0
- package/skills/maafw-live/references/workflows.md +159 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 关键帧命令:kf status / kf promote / kf list / kf resolve。
|
|
3
|
+
*
|
|
4
|
+
* 升格(promote)是 daemon 内存操作——从 L0 缓存取原图落盘并登记,必须在捕获它的那个
|
|
5
|
+
* daemon 会话里做( REPL 里 stream/输入/run 之后立刻升格,"看到即升格,不攒到最后")。
|
|
6
|
+
* list / resolve 是纯离线文件操作,不依赖 daemon 存活(契约 §4.1)。
|
|
7
|
+
*/
|
|
8
|
+
import { EXIT, fail } from '../protocol.js';
|
|
9
|
+
import { defaultFramesDir, describeRecord, loadManifest, resolveFrame } from '../runtime/keyframes.js';
|
|
10
|
+
import { kfPromote, l0Status, withDaemon } from '../runtime/actions.js';
|
|
11
|
+
import { ensureSession } from '../runtime/session.js';
|
|
12
|
+
import { CONNECT_OPTIONS, daemonFail, sessionOptions } from './runtime.js';
|
|
13
|
+
const DIR_HINT = '库根默认 ~/.maafw-live/frames(与 daemon 的 runDir 一致)';
|
|
14
|
+
export const kfCommand = {
|
|
15
|
+
name: 'kf',
|
|
16
|
+
summary: '关键帧:status 看 L0 缓存,promote 升格原图进本地库,list/resolve 离线解析',
|
|
17
|
+
usage: 'maafw-live kf status [--project <dir>|--kind ...]\n' +
|
|
18
|
+
' maafw-live kf promote <seq>|latest [--note <s>] [--project <dir>|--kind ...]\n' +
|
|
19
|
+
' maafw-live kf list [--dir <frames>] (离线,不需要设备)\n' +
|
|
20
|
+
' maafw-live kf resolve <kf:...> [--dir <frames>] (离线)',
|
|
21
|
+
options: { ...CONNECT_OPTIONS, note: { type: 'string' }, dir: { type: 'string' }, latest: { type: 'boolean' } },
|
|
22
|
+
async run(ctx) {
|
|
23
|
+
const sub = ctx.positionals[0] ?? 'status';
|
|
24
|
+
if (sub === 'list' || sub === 'resolve') {
|
|
25
|
+
const dir = typeof ctx.values.dir === 'string' ? ctx.values.dir : defaultFramesDir();
|
|
26
|
+
if (sub === 'list') {
|
|
27
|
+
const { manifest, error } = loadManifest(dir);
|
|
28
|
+
if (error)
|
|
29
|
+
return fail('KF_MANIFEST', error, DIR_HINT, EXIT.FINDINGS);
|
|
30
|
+
if (!manifest) {
|
|
31
|
+
return {
|
|
32
|
+
exitCode: EXIT.OK,
|
|
33
|
+
human: ['关键帧库 ' + dir + ':尚无留存(manifest 未创建;升格后会自动生成)'],
|
|
34
|
+
data: { dir, count: 0, frames: [] },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
exitCode: EXIT.OK,
|
|
39
|
+
human: [
|
|
40
|
+
'关键帧库 ' + dir + ':' + manifest.frames.length + ' 条(libraryId ' + manifest.libraryId + ')',
|
|
41
|
+
...manifest.frames.map(describeRecord),
|
|
42
|
+
],
|
|
43
|
+
data: { dir, count: manifest.frames.length, frames: manifest.frames },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const id = ctx.positionals[1];
|
|
47
|
+
if (!id)
|
|
48
|
+
return fail('BAD_ARGUMENTS', '用法:maafw-live kf resolve <kf:库UUID:序号>', undefined, EXIT.USAGE);
|
|
49
|
+
const r = resolveFrame(dir, id);
|
|
50
|
+
const human = ['解析 ' + id + ':' + r.status + (r.reason ? '(' + r.reason + ')' : '')];
|
|
51
|
+
if (r.record)
|
|
52
|
+
human.push(' ' + describeRecord(r.record));
|
|
53
|
+
if (r.path)
|
|
54
|
+
human.push(' path: ' + r.path);
|
|
55
|
+
if (r.record)
|
|
56
|
+
human.push(' sha256: ' + r.record.sha256);
|
|
57
|
+
return { exitCode: EXIT.OK, human, data: r };
|
|
58
|
+
}
|
|
59
|
+
if (sub === 'status') {
|
|
60
|
+
try {
|
|
61
|
+
return await withDaemon(async (client) => {
|
|
62
|
+
const st = await l0Status(client);
|
|
63
|
+
const roll = st.roll;
|
|
64
|
+
const anchor = st.anchor;
|
|
65
|
+
return {
|
|
66
|
+
exitCode: EXIT.OK,
|
|
67
|
+
human: [
|
|
68
|
+
'L0 原图缓存:滚动区 ' + String(roll?.count) + '/' + String(roll?.cap) +
|
|
69
|
+
'(' + String(roll?.bytes) + ' bytes),锚区 ' + String(anchor?.count) + '/' + String(anchor?.cap) +
|
|
70
|
+
'(' + String(anchor?.bytes) + ' bytes),seq=' + String(st.seq),
|
|
71
|
+
'关键帧库:' + String(st.framesDir),
|
|
72
|
+
'锚区条目(seq, source):',
|
|
73
|
+
...(anchor?.entries ?? [])
|
|
74
|
+
.map((e) => ' seq=' + e.seq + ' ' + String(e.source)),
|
|
75
|
+
],
|
|
76
|
+
data: st,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
return daemonFail(e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (sub === 'promote') {
|
|
85
|
+
const o = sessionOptions(ctx.values);
|
|
86
|
+
const seqRaw = ctx.positionals[1];
|
|
87
|
+
let args;
|
|
88
|
+
if (seqRaw !== undefined && /^\d+$/.test(seqRaw))
|
|
89
|
+
args = { seq: Number(seqRaw) };
|
|
90
|
+
else if (seqRaw === 'latest' || ctx.values.latest === true)
|
|
91
|
+
args = { latest: true };
|
|
92
|
+
else
|
|
93
|
+
args = {};
|
|
94
|
+
if (typeof ctx.values.note === 'string')
|
|
95
|
+
args.note = ctx.values.note;
|
|
96
|
+
if (!args.seq && !args.latest) {
|
|
97
|
+
return fail('BAD_ARGUMENTS', '给序号(kf promote 42)或 kf promote latest;身份在接受请求时固定,已淘汰则失败', '升格要在捕获它的 daemon 会话里做(repl:stream/输入/run 后立刻升格);一次性命令的 L0 通常只有边界帧', EXIT.USAGE);
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return await withDaemon(async (client) => {
|
|
101
|
+
if (o.project || o.kind) {
|
|
102
|
+
/* 设备会话存在才值得连:L0 缓存是进程态,连一次至少能把输入/截图边界帧留下 */
|
|
103
|
+
await ensureSession(client, o);
|
|
104
|
+
}
|
|
105
|
+
const r = await kfPromote(client, args);
|
|
106
|
+
if (r.ok === false) {
|
|
107
|
+
return fail('KF_PROMOTE', String(r.error ?? '升格失败'), 'L0 淘汰是诚实失败:换 frame_get 导 L1 参考帧,或重采', EXIT.FINDINGS);
|
|
108
|
+
}
|
|
109
|
+
const rec = r.record;
|
|
110
|
+
return {
|
|
111
|
+
exitCode: EXIT.OK,
|
|
112
|
+
human: [
|
|
113
|
+
'已升格:' + String(r.id) + (r.idempotent ? '(幂等重试,返回原对象)' : ''),
|
|
114
|
+
...(rec ? [' 捕获 seq=' + rec.captureSeq + ',控制器尺寸 ' + rec.ctrlW + 'x' + rec.ctrlH + ',source=' + rec.source] : []),
|
|
115
|
+
' path: ' + String(r.path),
|
|
116
|
+
' sha256: ' + String(r.sha256),
|
|
117
|
+
],
|
|
118
|
+
data: r,
|
|
119
|
+
written: [String(r.path)],
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
return daemonFail(e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return fail('BAD_ARGUMENTS', '用法:kf status | kf promote [seq|latest] | kf list | kf resolve <id>', undefined, EXIT.USAGE);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export const KF_COMMANDS = [kfCommand];
|
|
131
|
+
//# sourceMappingURL=kf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kf.js","sourceRoot":"","sources":["../../src/commands/kf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 识别单测:maafw-live reco。
|
|
3
|
+
*
|
|
4
|
+
* 走 daemon 的 reco_test —— 它把识别放进一次性子进程执行(beta 绑定在无效模板上会原生崩溃,
|
|
5
|
+
* 子进程炸掉只损失一次测试,不带走调用方)。支持阈值扫描:一次调用给出阈值-命中曲线。
|
|
6
|
+
* 项目模式下资源目录从 interface.json 解析,避免手写路径与项目声明不一致。
|
|
7
|
+
*/
|
|
8
|
+
import { EXIT, fail } from '../protocol.js';
|
|
9
|
+
import { recoTest, withDaemon } from '../runtime/actions.js';
|
|
10
|
+
import { defaultFramesDir, resolveFrame } from '../runtime/keyframes.js';
|
|
11
|
+
import { describeSession, ensureSession, offlineResource } from '../runtime/session.js';
|
|
12
|
+
import { CONNECT_OPTIONS, daemonFail, sessionOptions } from './runtime.js';
|
|
13
|
+
function parseJson(raw, what) {
|
|
14
|
+
if (raw === undefined)
|
|
15
|
+
return {};
|
|
16
|
+
if (typeof raw !== 'string')
|
|
17
|
+
return {};
|
|
18
|
+
try {
|
|
19
|
+
return { value: JSON.parse(raw) };
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return { error: what + ' 不是合法 JSON:' + String(e.message) };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function suggestThreshold(results) {
|
|
26
|
+
let best = -1;
|
|
27
|
+
for (const r of results) {
|
|
28
|
+
const inner = r.detail?.detail;
|
|
29
|
+
const candidates = [Number(inner?.best?.score), ...(inner?.all ?? []).map((x) => Number(x.score))];
|
|
30
|
+
for (const s of candidates)
|
|
31
|
+
if (Number.isFinite(s) && s > best)
|
|
32
|
+
best = s;
|
|
33
|
+
}
|
|
34
|
+
if (best < 0)
|
|
35
|
+
return null;
|
|
36
|
+
const bestScore = Math.round(best * 1000) / 1000;
|
|
37
|
+
const lowMatch = best < 0.5;
|
|
38
|
+
return {
|
|
39
|
+
bestScore,
|
|
40
|
+
suggest: lowMatch ? null : Math.max(0, Math.round((best - 0.1) * 1000) / 1000),
|
|
41
|
+
lowMatch,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export const recoCommand = {
|
|
45
|
+
name: 'reco',
|
|
46
|
+
summary: '识别单测(子进程隔离):--param/--sweep 阈值扫描,或 --node 整节点 JSON 透传;--act 真机执行动作半',
|
|
47
|
+
usage: 'maafw-live reco --type TemplateMatch --resource-dir <dir> --image <png|kf:ID> [--param <json>] [--sweep <json>] [--project <dir>]\n' +
|
|
48
|
+
' maafw-live reco --node <json> --resource-dir <dir> --image <png|kf:ID> (V1 扁平 / V2 嵌套节点均原样透传)\n' +
|
|
49
|
+
' maafw-live reco --node <json> --resource-dir <dir> --from-kf <kf:库UUID:序号> (库内留存帧:离线、不需要设备)\n' +
|
|
50
|
+
' maafw-live reco --node <json> --act --project <dir> (识别拿框 → 用框 run_action 真机执行)',
|
|
51
|
+
options: {
|
|
52
|
+
...CONNECT_OPTIONS,
|
|
53
|
+
type: { type: 'string' },
|
|
54
|
+
'resource-dir': { type: 'string' },
|
|
55
|
+
image: { type: 'string' },
|
|
56
|
+
seq: { type: 'string' },
|
|
57
|
+
param: { type: 'string' },
|
|
58
|
+
sweep: { type: 'string' },
|
|
59
|
+
node: { type: 'string' },
|
|
60
|
+
act: { type: 'boolean' },
|
|
61
|
+
'from-kf': { type: 'string' },
|
|
62
|
+
'frames-dir': { type: 'string' },
|
|
63
|
+
},
|
|
64
|
+
async run(ctx) {
|
|
65
|
+
const o = sessionOptions(ctx.values);
|
|
66
|
+
const type = typeof ctx.values.type === 'string' ? ctx.values.type : 'TemplateMatch';
|
|
67
|
+
const imageRaw = typeof ctx.values.image === 'string' && ctx.values.image !== '' ? ctx.values.image : undefined;
|
|
68
|
+
/* `--image kf:…:0011` 是 SKILL / roadmap 里记过的写法:以 kf: 开头就按**库帧 ID**解释,
|
|
69
|
+
* 而不是文件路径(否则一路走到 ENOENT,实测踩过)。规范入口仍是 --from-kf。 */
|
|
70
|
+
const kfFromImage = imageRaw?.startsWith('kf:') === true ? imageRaw : undefined;
|
|
71
|
+
const image = kfFromImage ? undefined : imageRaw;
|
|
72
|
+
const seq = typeof ctx.values.seq === 'string' ? Number(ctx.values.seq) : undefined;
|
|
73
|
+
const nodeRaw = typeof ctx.values.node === 'string' ? ctx.values.node : undefined;
|
|
74
|
+
let node;
|
|
75
|
+
if (nodeRaw !== undefined) {
|
|
76
|
+
const parsed = parseJson(nodeRaw, '--node');
|
|
77
|
+
if (parsed.error)
|
|
78
|
+
return fail('BAD_ARGUMENTS', parsed.error, undefined, EXIT.USAGE);
|
|
79
|
+
if (!parsed.value || typeof parsed.value !== 'object' || Array.isArray(parsed.value)) {
|
|
80
|
+
return fail('BAD_ARGUMENTS', '--node 必须是 JSON 对象(pipeline 节点)', undefined, EXIT.USAGE);
|
|
81
|
+
}
|
|
82
|
+
node = parsed.value;
|
|
83
|
+
}
|
|
84
|
+
const param = parseJson(ctx.values.param, '--param');
|
|
85
|
+
if (param.error)
|
|
86
|
+
return fail('BAD_ARGUMENTS', param.error, undefined, EXIT.USAGE);
|
|
87
|
+
const sweep = parseJson(ctx.values.sweep, '--sweep');
|
|
88
|
+
if (sweep.error)
|
|
89
|
+
return fail('BAD_ARGUMENTS', sweep.error, undefined, EXIT.USAGE);
|
|
90
|
+
const act = ctx.values.act === true;
|
|
91
|
+
/* 库帧来源(离线,镜像 crop / annotate 的 --from-kf):先走离线读侧解析,daemon 只接身份与路径 */
|
|
92
|
+
const fromKf = typeof ctx.values['from-kf'] === 'string' && ctx.values['from-kf'] !== ''
|
|
93
|
+
? ctx.values['from-kf']
|
|
94
|
+
: kfFromImage;
|
|
95
|
+
if (fromKf !== undefined && seq !== undefined) {
|
|
96
|
+
return fail('BAD_ARGUMENTS', '--from-kf 与 --seq 互斥:前者在库内留存帧上跑,后者在本会话缓冲帧上跑', '取库里有哪些帧:maafw-live kf list', EXIT.USAGE);
|
|
97
|
+
}
|
|
98
|
+
let kfSource;
|
|
99
|
+
if (fromKf !== undefined) {
|
|
100
|
+
const dir = typeof ctx.values['frames-dir'] === 'string' ? ctx.values['frames-dir'] : defaultFramesDir();
|
|
101
|
+
const rf = resolveFrame(dir, fromKf);
|
|
102
|
+
if (rf.status !== 'available' || !rf.path || !rf.record) {
|
|
103
|
+
const code = rf.status === 'corrupt' ? 'KF_CORRUPT' : (rf.status === 'unsupported' ? 'KF_UNSUPPORTED' : 'KF_MISSING');
|
|
104
|
+
return fail(code, '库帧不可用(' + rf.status + '):' + String(rf.reason ?? '') + '(库 ' + dir + ')', 'kf list 看库内有哪些帧;missing 表示本机不可复核,不代表历史从未观测', EXIT.FINDINGS);
|
|
105
|
+
}
|
|
106
|
+
const rec = rf.record;
|
|
107
|
+
kfSource = {
|
|
108
|
+
id: rec.id, path: rf.path, sha256: rec.sha256, ctrlW: rec.ctrlW, ctrlH: rec.ctrlH,
|
|
109
|
+
captureSeq: rec.captureSeq, capturedAt: rec.capturedAt,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const offline = kfSource !== undefined;
|
|
113
|
+
if (act && offline) {
|
|
114
|
+
return fail('BAD_ARGUMENTS', '--act 要在真机上执行动作、图像取自当前画面:不能与 --from-kf 同用', '离线只做识别判据;要连真机就把 --from-kf 换成 --project 跑 --act', EXIT.USAGE);
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
return await withDaemon(async (client) => {
|
|
118
|
+
const s = offline ? { connected: false } : await ensureSession(client, o);
|
|
119
|
+
let resourceDir = (typeof ctx.values['resource-dir'] === 'string' ? ctx.values['resource-dir'] : undefined)
|
|
120
|
+
?? s.plan?.resource?.paths[0];
|
|
121
|
+
if (!resourceDir && offline && o.project) {
|
|
122
|
+
/* 离线:项目只作资源来源(模板与 OCR 模型),不扫设备不连接 */
|
|
123
|
+
const off = offlineResource(o.project, o.controller, o.resource);
|
|
124
|
+
if (off.error) {
|
|
125
|
+
return fail('PLAN_FAILED', '离线解析项目资源失败:' + off.error, '也可以直接给 --resource-dir <dir>', EXIT.FINDINGS);
|
|
126
|
+
}
|
|
127
|
+
resourceDir = off.paths[0];
|
|
128
|
+
}
|
|
129
|
+
if (!resourceDir) {
|
|
130
|
+
return fail('BAD_ARGUMENTS', '缺少资源目录:给 --resource-dir <dir>,或用 --project <dir> 让 interface.json 决定', undefined, EXIT.USAGE);
|
|
131
|
+
}
|
|
132
|
+
if (act) {
|
|
133
|
+
/* --act:识别拿框 → 真机 run_action。图像来自当前画面(daemon 抓帧),不吃 --image/--seq */
|
|
134
|
+
if (!node) {
|
|
135
|
+
return fail('BAD_ARGUMENTS', '--act 需要同时给 --node <json>(整节点,含 action)', undefined, EXIT.USAGE);
|
|
136
|
+
}
|
|
137
|
+
if (!o.project && !o.kind) {
|
|
138
|
+
return fail('BAD_ARGUMENTS', '--act 要真机执行动作:给 --project <dir> 或 --kind 连接设备', '多步操作用 maafw-live repl', EXIT.USAGE);
|
|
139
|
+
}
|
|
140
|
+
const r = await recoTest(client, { resourceDir, act: true, node });
|
|
141
|
+
if (r.ok === false) {
|
|
142
|
+
return fail('RECO_ACT', String(r.error ?? '动作单测失败'), r.stage === 'recognition' ? '识别未命中/报错——动作半未执行' : undefined, EXIT.FINDINGS);
|
|
143
|
+
}
|
|
144
|
+
const reco = r.reco;
|
|
145
|
+
const retention = r.retention;
|
|
146
|
+
return {
|
|
147
|
+
exitCode: EXIT.OK,
|
|
148
|
+
human: [
|
|
149
|
+
...describeSession(s),
|
|
150
|
+
'节点单测(识别→动作,真机执行):',
|
|
151
|
+
' 识别框 ' + JSON.stringify(reco?.box ?? null),
|
|
152
|
+
' 动作回执 ' + JSON.stringify(r.action ?? null),
|
|
153
|
+
' 边界帧 seq ' + String(retention?.before?.seq) + ' → ' + String(retention?.after?.seq) +
|
|
154
|
+
'(frame_get / kf promote 可复核动作效果)',
|
|
155
|
+
],
|
|
156
|
+
data: r,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (!image && seq === undefined && !offline) {
|
|
160
|
+
return fail('BAD_ARGUMENTS', '缺少图像:一次性命令给 --image <png>;用缓冲帧(--seq)需要在 maafw-live repl 里先 stream start', '库里留存帧用 --from-kf <kf:…>(离线、不需要设备)', EXIT.USAGE);
|
|
161
|
+
}
|
|
162
|
+
const r = await recoTest(client, {
|
|
163
|
+
resourceDir, type,
|
|
164
|
+
...(image ? { image } : {}),
|
|
165
|
+
...(seq !== undefined ? { seq } : {}),
|
|
166
|
+
...(kfSource ? { kfSource } : {}),
|
|
167
|
+
...(node ? { node } : {}),
|
|
168
|
+
...(!node && param.value ? { param: param.value } : {}),
|
|
169
|
+
...(!node && sweep.value ? { sweep: sweep.value } : {}),
|
|
170
|
+
});
|
|
171
|
+
const results = r.results ?? [];
|
|
172
|
+
const human = [
|
|
173
|
+
...describeSession(s),
|
|
174
|
+
'识别 ' + String(r.type ?? type) + ':' + results.length + ' 例' + (node ? '(整节点透传)' : ''),
|
|
175
|
+
...results.map((x) => ' ' + (x.ok ? '[命中]' : '[未中]') + ' ' + JSON.stringify(x.param) + ' ' + x.ms + 'ms'),
|
|
176
|
+
];
|
|
177
|
+
const th = suggestThreshold(r.results ?? []);
|
|
178
|
+
if (th && th.suggest !== null) {
|
|
179
|
+
human.push(' 实测最高置信度 ' + th.bestScore + ' → threshold 起点建议 ' + th.suggest +
|
|
180
|
+
'(实测 − 0.1 留余量,换场景会掉;ROI 收紧可再提)');
|
|
181
|
+
}
|
|
182
|
+
else if (th && th.lowMatch) {
|
|
183
|
+
human.push(' 实测最高置信度 ' + th.bestScore + ':模板与该画面不匹配——threshold 建议不适用,' +
|
|
184
|
+
'先核对模板来源画面与当前画面(识别未命中不是调低阈值的理由)');
|
|
185
|
+
}
|
|
186
|
+
else if (results.length > 0) {
|
|
187
|
+
/* 第三形态:识别跑了,但一个置信度都没带回来(实测:模板文件读不到时就是这个签名——
|
|
188
|
+
* ~230ms、`[未中]`、detail.best 空、all 为空)。它和"分数低的未命中"必须分得开:
|
|
189
|
+
* 后者是画面不匹配(有分数),前者是**输入当时读不到**,处置方向完全不同。 */
|
|
190
|
+
human.push(' 识别未返回任何置信度(' + results.length + ' 例):这与"分数低的未命中"不同——' +
|
|
191
|
+
'多半是模板/资源当时没读到(资源包未加载、模板文件缺失或不可读、临时文件正被杀软扫描)。' +
|
|
192
|
+
'先核对 --resource-dir 与模板是否存在,再重跑一次看是否复现;别当成"画面不匹配"去调阈值');
|
|
193
|
+
}
|
|
194
|
+
if (r.ok === false)
|
|
195
|
+
human.push('error: ' + String(r.error));
|
|
196
|
+
/* 机器侧也要能一眼认出第三形态(阈值建议缺席 ≠ 没跑) */
|
|
197
|
+
const noConfidence = th === null && results.length > 0;
|
|
198
|
+
return {
|
|
199
|
+
exitCode: r.ok === false ? EXIT.FINDINGS : EXIT.OK,
|
|
200
|
+
human,
|
|
201
|
+
data: { ...r, ...(th ? { thresholdSuggestion: th } : {}), ...(noConfidence ? { noConfidence: true } : {}) },
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
return daemonFail(e);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
export const RECO_COMMANDS = [recoCommand];
|
|
211
|
+
//# sourceMappingURL=reco.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reco.js","sourceRoot":"","sources":["../../src/commands/reco.ts"],"names":[],"mappings":"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"}
|