@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,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `maafw-live skill` —— 随包发布的 agent skill 与"装在 agent 里的那一份"如何对齐。
|
|
3
|
+
*
|
|
4
|
+
* 为什么不写版本号:skill 讲的是本工具的命令与判据,跟包走才不会各说各话;但写进文件的版本号
|
|
5
|
+
* 每次发版都要改,而且从仓库装的副本仍然对不上。所以对齐用**比字节**:逐文件 same / different /
|
|
6
|
+
* missing / extra(extra 是目标目录多出来的文件,例如 skills CLI 放进来的 agent 元数据,不算漂移)。
|
|
7
|
+
*
|
|
8
|
+
* 与本仓 docs/ 的分工:docs/ 是字段与协议的唯一出处,skill 只写动线与判据——两者都随包发布,
|
|
9
|
+
* 区别在消费者(人读 docs,agent 装 skill),因此这里只做"是不是同一份字节",不解释内容。
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { EXIT, fail } from '../protocol.js';
|
|
16
|
+
const SKILL_NAME = 'maafw-live';
|
|
17
|
+
/** 包内 skill 目录:lib/commands/ → <包根>/skills/maafw-live(本地 checkout 同构) */
|
|
18
|
+
export function skillPayloadDir() {
|
|
19
|
+
return join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'skills', SKILL_NAME);
|
|
20
|
+
}
|
|
21
|
+
const sha256 = (buf) => createHash('sha256').update(buf).digest('hex');
|
|
22
|
+
/** 目录内全部文件的相对路径('/' 分隔、排序稳定),供比对与安装共用。 */
|
|
23
|
+
function listFiles(dir) {
|
|
24
|
+
const out = [];
|
|
25
|
+
const walk = (cur) => {
|
|
26
|
+
for (const e of readdirSync(cur, { withFileTypes: true })) {
|
|
27
|
+
const abs = join(cur, e.name);
|
|
28
|
+
if (e.isDirectory())
|
|
29
|
+
walk(abs);
|
|
30
|
+
else if (e.isFile())
|
|
31
|
+
out.push(relative(dir, abs).split(sep).join('/'));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
walk(dir);
|
|
35
|
+
return out.sort();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 逐文件比对(纯函数,单测直接喂两个目录)。只比字节:任何不同都是 different,
|
|
39
|
+
* 但在**仅行尾不同**(CRLF ↔ LF)时补一条 note——那不是内容分叉,是工具改写。
|
|
40
|
+
*/
|
|
41
|
+
export function compareSkillTrees(payload, target) {
|
|
42
|
+
const files = listFiles(payload);
|
|
43
|
+
const rows = [];
|
|
44
|
+
for (const rel of files) {
|
|
45
|
+
const pb = readFileSync(join(payload, ...rel.split('/')));
|
|
46
|
+
const ta = join(target, ...rel.split('/'));
|
|
47
|
+
const base = { path: rel, bytes: pb.length, sha256: sha256(pb) };
|
|
48
|
+
if (!existsSync(ta)) {
|
|
49
|
+
rows.push({ ...base, status: 'missing' });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const tb = readFileSync(ta);
|
|
53
|
+
if (pb.equals(tb)) {
|
|
54
|
+
rows.push({ ...base, status: 'same' });
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const eolOnly = pb.toString('utf8').replace(/\r\n/g, '\n') === tb.toString('utf8').replace(/\r\n/g, '\n');
|
|
58
|
+
rows.push({ ...base, status: 'different', ...(eolOnly ? { note: '仅行尾不同(CRLF/LF)' } : {}) });
|
|
59
|
+
}
|
|
60
|
+
for (const rel of listFiles(target)) {
|
|
61
|
+
if (!files.includes(rel))
|
|
62
|
+
rows.push({ path: rel, status: 'extra' });
|
|
63
|
+
}
|
|
64
|
+
return rows;
|
|
65
|
+
}
|
|
66
|
+
const driftOf = (rows) => rows.some((r) => r.status !== 'same' && r.status !== 'extra');
|
|
67
|
+
function readPayload(dir) {
|
|
68
|
+
return listFiles(dir).map((rel) => {
|
|
69
|
+
const buf = readFileSync(join(dir, ...rel.split('/')));
|
|
70
|
+
return { path: rel, bytes: buf.length, sha256: sha256(buf), text: buf.toString('utf8') };
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export const skillCommand = {
|
|
74
|
+
name: 'skill',
|
|
75
|
+
summary: '随包 skill:看包内副本与文件指纹、比对已装副本(same/different/missing/extra)、字节精确安装',
|
|
76
|
+
usage: 'maafw-live skill 包内 skill 位置与文件指纹\n' +
|
|
77
|
+
' maafw-live skill --check <dir> 比对 <dir>/maafw-live 与包内副本(有漂移退出 3)\n' +
|
|
78
|
+
' maafw-live skill --install <dir> 把包内副本逐字节写到 <dir>/maafw-live\n' +
|
|
79
|
+
' maafw-live skill --print [--format json] 输出包内副本内容(harness 自取)',
|
|
80
|
+
options: {
|
|
81
|
+
check: { type: 'string' },
|
|
82
|
+
install: { type: 'string' },
|
|
83
|
+
print: { type: 'boolean' },
|
|
84
|
+
format: { type: 'string' },
|
|
85
|
+
},
|
|
86
|
+
async run(ctx) {
|
|
87
|
+
const payload = skillPayloadDir();
|
|
88
|
+
if (!existsSync(payload)) {
|
|
89
|
+
return fail('SKILL_NOT_FOUND', '包内未找到 skill 目录:' + payload, '本版本应随包发布 skills/maafw-live;从仓库运行时确认 skills/ 没有被删', EXIT.ENV);
|
|
90
|
+
}
|
|
91
|
+
const files = listFiles(payload);
|
|
92
|
+
const checkDir = typeof ctx.values.check === 'string' ? ctx.values.check : undefined;
|
|
93
|
+
if (checkDir !== undefined) {
|
|
94
|
+
const target = join(checkDir, SKILL_NAME);
|
|
95
|
+
if (!existsSync(target)) {
|
|
96
|
+
return fail('SKILL_DIR_NOT_FOUND', '目标目录下没有 ' + SKILL_NAME + ' skill:' + target, '给的是**安装根目录**(里面应当有 ' + SKILL_NAME + '/SKILL.md),例如 --global 装的 ~/.claude/skills', EXIT.ENV);
|
|
97
|
+
}
|
|
98
|
+
const rows = compareSkillTrees(payload, target);
|
|
99
|
+
const drifted = driftOf(rows);
|
|
100
|
+
const extra = rows.filter((r) => r.status === 'extra');
|
|
101
|
+
const mark = (s) => s === 'same' ? 'same ' : (s === 'different' ? 'different' : (s === 'missing' ? 'missing ' : 'extra '));
|
|
102
|
+
const human = [
|
|
103
|
+
'包内副本 ' + payload,
|
|
104
|
+
'已装副本 ' + target,
|
|
105
|
+
...rows.map((r) => ' ' + mark(r.status) + ' ' + r.path + (r.note ? '(' + r.note + ')' : '')),
|
|
106
|
+
drifted
|
|
107
|
+
? '结论:有漂移——用 --install <dir> 覆盖,或用 skills CLI 重新安装'
|
|
108
|
+
: '结论:逐字节一致' + (extra.length ? '(' + extra.length + ' 个多余文件不计漂移)' : ''),
|
|
109
|
+
];
|
|
110
|
+
return {
|
|
111
|
+
exitCode: drifted ? EXIT.FINDINGS : EXIT.OK,
|
|
112
|
+
human,
|
|
113
|
+
data: { payload, target, drift: drifted, files: rows },
|
|
114
|
+
...(drifted ? { warnings: ['skill 与包内副本不一致:已装副本可能对应旧版本 CLI'] } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const installDir = typeof ctx.values.install === 'string' ? ctx.values.install : undefined;
|
|
118
|
+
if (installDir !== undefined) {
|
|
119
|
+
const target = join(installDir, SKILL_NAME);
|
|
120
|
+
const written = [];
|
|
121
|
+
for (const rel of files) {
|
|
122
|
+
const dst = join(target, ...rel.split('/'));
|
|
123
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
124
|
+
writeFileSync(dst, readFileSync(join(payload, ...rel.split('/'))));
|
|
125
|
+
written.push(dst);
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
exitCode: EXIT.OK,
|
|
129
|
+
human: [
|
|
130
|
+
'已写出 ' + files.length + ' 个文件 → ' + target,
|
|
131
|
+
...written.map((w) => ' ' + w),
|
|
132
|
+
'注:本命令只做逐字节复制;要 agent 自动更新请用 skills CLI(npx skills add …)',
|
|
133
|
+
],
|
|
134
|
+
data: { payload, target, files: written },
|
|
135
|
+
written,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (ctx.values.print === true) {
|
|
139
|
+
const rows = readPayload(payload);
|
|
140
|
+
const asJson = ctx.values.format === 'json';
|
|
141
|
+
if (asJson) {
|
|
142
|
+
return {
|
|
143
|
+
exitCode: EXIT.OK,
|
|
144
|
+
data: { payload, files: rows },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const human = [];
|
|
148
|
+
for (const f of rows) {
|
|
149
|
+
human.push('===== ' + f.path + ' =====');
|
|
150
|
+
human.push(...f.text.replace(/\r\n/g, '\n').replace(/\n$/, '').split('\n'));
|
|
151
|
+
human.push('');
|
|
152
|
+
}
|
|
153
|
+
return { exitCode: EXIT.OK, human, data: { payload, files: rows.map(({ text, ...rest }) => rest) } };
|
|
154
|
+
}
|
|
155
|
+
const rows = readPayload(payload);
|
|
156
|
+
const total = rows.reduce((a, f) => a + f.bytes, 0);
|
|
157
|
+
return {
|
|
158
|
+
exitCode: EXIT.OK,
|
|
159
|
+
human: [
|
|
160
|
+
'包内 skill:' + payload,
|
|
161
|
+
'文件 ' + rows.length + ' 个,共 ' + total + ' 字节(skill 不写自己的版本号——对齐用比字节)',
|
|
162
|
+
...rows.map((f) => ' ' + f.sha256.slice(0, 12) + ' ' + String(f.bytes).padStart(6) + ' ' + f.path),
|
|
163
|
+
'下一步:maafw-live skill --check <安装根目录> 比对已装副本;--install <目录> 逐字节写出',
|
|
164
|
+
],
|
|
165
|
+
data: { payload, files: rows.map(({ text, ...rest }) => rest) },
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* timing:从帧流与节点事件反推 pipeline 的 delay / timeout 建议值。
|
|
3
|
+
*
|
|
4
|
+
* 做法:自动开流 → 跑任务(--runs n 次采样)→ 对齐两类时间线——
|
|
5
|
+
* - 节点时长(record.nodes)→ 节点级 timeout 建议(P95 × 1.5 余量)
|
|
6
|
+
* - 节点完成后的画面稳定时间(完成事件到下一个 stable 事件的时距)→ post-delay /
|
|
7
|
+
* wait_freezes 建议;下一节点先于 stable 开始则标"未稳定"(连续动画/识别窗口过紧)。
|
|
8
|
+
* 分布口径:建议值只取成功 run(失败 run 的时长是提前终止的,对 timeout 建议是误导);
|
|
9
|
+
* 单次采样退化为 P50=P95=该值,与历史单次行为逐字段一致。
|
|
10
|
+
*/
|
|
11
|
+
import { EXIT, fail } from '../protocol.js';
|
|
12
|
+
import { computePipelineOverride, mergeOverride } from '../interface/index.js';
|
|
13
|
+
import * as act from '../runtime/actions.js';
|
|
14
|
+
import { withDaemon } from '../runtime/actions.js';
|
|
15
|
+
import { describeSession, ensureSession } from '../runtime/session.js';
|
|
16
|
+
import { CONNECT_OPTIONS, daemonFail, sessionOptions } from './runtime.js';
|
|
17
|
+
/** 最近邻秩百分位:sorted 升序;n=1 时任意 p 返回该值,n 小时偏保守端(P95 取最大) */
|
|
18
|
+
export function percentile(values, p) {
|
|
19
|
+
if (!values.length)
|
|
20
|
+
return 0;
|
|
21
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
22
|
+
const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));
|
|
23
|
+
return sorted[idx];
|
|
24
|
+
}
|
|
25
|
+
/** 跨 run 聚合(纯函数,单测直断言):节点统计与建议值都只算成功样本 */
|
|
26
|
+
export function aggregateTiming(samples) {
|
|
27
|
+
const ok = samples.filter((s) => s.ok);
|
|
28
|
+
const failed = samples.length - ok.length;
|
|
29
|
+
const durations = ok.map((s) => s.durationMs);
|
|
30
|
+
const maxNodeP95 = ok.length ? percentile(ok.map((s) => Math.max(0, ...s.nodes.map((n) => n.ms))), 95) : 0;
|
|
31
|
+
const settleSamples = ok.map((s) => {
|
|
32
|
+
const ss = s.nodes.filter((n) => n.settle !== null).map((n) => n.settle);
|
|
33
|
+
return ss.length ? Math.max(...ss) : null;
|
|
34
|
+
});
|
|
35
|
+
const settles = settleSamples.filter((v) => v !== null);
|
|
36
|
+
const names = [...new Set(ok.flatMap((s) => s.nodes.map((n) => n.name)))];
|
|
37
|
+
const nodeStats = names.map((name) => {
|
|
38
|
+
/* 全部出现都算:同名节点 run 内重复执行时,慢的往往是第二次(首跑等动画) */
|
|
39
|
+
const per = ok.flatMap((s) => s.nodes.filter((n) => n.name === name));
|
|
40
|
+
const ms = per.map((n) => n.ms);
|
|
41
|
+
const st = per.filter((n) => n.settle !== null).map((n) => n.settle);
|
|
42
|
+
return {
|
|
43
|
+
name,
|
|
44
|
+
status: per.at(-1)?.status ?? 'unknown',
|
|
45
|
+
runs: ok.filter((s) => s.nodes.some((n) => n.name === name)).length,
|
|
46
|
+
occurrences: per.length,
|
|
47
|
+
msP50: percentile(ms, 50),
|
|
48
|
+
msP95: percentile(ms, 95),
|
|
49
|
+
settleP50: st.length ? percentile(st, 50) : null,
|
|
50
|
+
settleP95: st.length ? percentile(st, 95) : null,
|
|
51
|
+
settleSamples: st.length,
|
|
52
|
+
nextBeforeStable: per.some((n) => n.nextBeforeStable),
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
successful: ok.length, failed,
|
|
57
|
+
durationP50: percentile(durations, 50),
|
|
58
|
+
durationP95: percentile(durations, 95),
|
|
59
|
+
maxNodeP95,
|
|
60
|
+
maxSettleP95: settles.length ? percentile(settles, 95) : null,
|
|
61
|
+
nodeStats,
|
|
62
|
+
suggest: {
|
|
63
|
+
nodeTimeoutMs: Math.ceil((maxNodeP95 * 1.5) / 100) * 100,
|
|
64
|
+
taskTimeoutMs: Math.ceil((percentile(durations, 95) * 2) / 1000) * 1000,
|
|
65
|
+
postDelayMs: settles.length ? Math.ceil((percentile(settles, 95) * 1.2) / 50) * 50 : null,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export const timingCommand = {
|
|
70
|
+
name: 'timing',
|
|
71
|
+
summary: '跑任务并反推 timing 建议:节点时长 → timeout,动作后稳定时间 → wait_freezes 兜底参考;--runs n 取 P50/P95 分布',
|
|
72
|
+
usage: 'maafw-live timing --entry <task> --project <dir> [--timeout <ms>] [--runs <n>] [--preset <name>] [--override <json>]\n' +
|
|
73
|
+
' 自动开流(帧流与节点事件对齐是分析前提);单次采样是下界,--runs 3-5 取分布再定稿',
|
|
74
|
+
options: {
|
|
75
|
+
...CONNECT_OPTIONS,
|
|
76
|
+
entry: { type: 'string' },
|
|
77
|
+
'resource-dir': { type: 'string' },
|
|
78
|
+
timeout: { type: 'string' },
|
|
79
|
+
runs: { type: 'string' },
|
|
80
|
+
override: { type: 'string' },
|
|
81
|
+
preset: { type: 'string' },
|
|
82
|
+
},
|
|
83
|
+
async run(ctx) {
|
|
84
|
+
const o = sessionOptions(ctx.values);
|
|
85
|
+
const entry = (typeof ctx.values.entry === 'string' ? ctx.values.entry : ctx.positionals[0]) ?? undefined;
|
|
86
|
+
const resourceDir = typeof ctx.values['resource-dir'] === 'string' ? ctx.values['resource-dir'] : undefined;
|
|
87
|
+
if (!entry)
|
|
88
|
+
return fail('BAD_ARGUMENTS', '缺少入口任务名:--entry <task>', undefined, EXIT.USAGE);
|
|
89
|
+
if (!o.project && !resourceDir) {
|
|
90
|
+
return fail('BAD_ARGUMENTS', '要么给 --project <dir>,要么给 --resource-dir <dir>', undefined, EXIT.USAGE);
|
|
91
|
+
}
|
|
92
|
+
const timeoutMs = typeof ctx.values.timeout === 'string' ? Number(ctx.values.timeout) : 120000;
|
|
93
|
+
if (!Number.isFinite(timeoutMs))
|
|
94
|
+
return fail('BAD_ARGUMENTS', '--timeout 必须是毫秒数', undefined, EXIT.USAGE);
|
|
95
|
+
const runs = typeof ctx.values.runs === 'string' ? Number(ctx.values.runs) : 1;
|
|
96
|
+
if (!Number.isInteger(runs) || runs < 1 || runs > 10) {
|
|
97
|
+
return fail('BAD_ARGUMENTS', '--runs 需为 1-10 的整数(真机动作采样,别当压测跑)', undefined, EXIT.USAGE);
|
|
98
|
+
}
|
|
99
|
+
let override = {};
|
|
100
|
+
if (typeof ctx.values.override === 'string') {
|
|
101
|
+
try {
|
|
102
|
+
override = JSON.parse(ctx.values.override);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
return fail('BAD_ARGUMENTS', '--override 不是合法 JSON', undefined, EXIT.USAGE);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
return await withDaemon(async (client) => {
|
|
110
|
+
const s = await ensureSession(client, o);
|
|
111
|
+
let args;
|
|
112
|
+
if (o.project) {
|
|
113
|
+
const paths = s.plan?.resource?.paths ?? [];
|
|
114
|
+
if (!paths.length) {
|
|
115
|
+
return fail('RESOURCE_NOT_FOUND', '项目里没有解析出资源路径:检查 interface.json 的 resource[] 声明', undefined, EXIT.FINDINGS);
|
|
116
|
+
}
|
|
117
|
+
const task = s.plan?.loaded.tasks.find((t) => t.name === entry || t.entry === entry);
|
|
118
|
+
const chain = computePipelineOverride({
|
|
119
|
+
loaded: s.plan.loaded,
|
|
120
|
+
controllerName: s.plan?.controllerName ?? null,
|
|
121
|
+
resourceName: s.plan?.resource?.selected ?? null,
|
|
122
|
+
taskName: task?.name ?? null,
|
|
123
|
+
presetName: typeof ctx.values.preset === 'string' ? ctx.values.preset : null,
|
|
124
|
+
});
|
|
125
|
+
/* 用户 --override 最后覆盖合成结果:**与 run 共用同一份合并实现**。
|
|
126
|
+
* 这里曾经自己展开 fields——字符串会被摊成 {0:'a',1:'b'}、null / 数字静默变空对象,
|
|
127
|
+
* 于是同一个 --override 在 timing 与 run 下结果不同。 */
|
|
128
|
+
mergeOverride(chain.override, override);
|
|
129
|
+
args = {
|
|
130
|
+
resourceDirs: paths, entry: task?.entry ?? entry,
|
|
131
|
+
override: chain.override, timeoutMs,
|
|
132
|
+
agents: s.plan.loaded.agents.map((a) => ({ exec: a.exec, args: a.args })),
|
|
133
|
+
agentCwd: s.plan.loaded.dir ?? undefined,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
args = { resourceDir, entry, override, timeoutMs };
|
|
138
|
+
}
|
|
139
|
+
/* 帧流是分析前提:开流 → 跑 n 次 → 停流;每 run 切自己的事件区间对齐。
|
|
140
|
+
* 末节点可能把下一 run 开头的 stable 算作自己的稳定点——语义上仍是
|
|
141
|
+
* "该节点之后画面何时静默",可接受。 */
|
|
142
|
+
await act.streamStart(client, { fps: 8 }).catch(() => null);
|
|
143
|
+
const samples = [];
|
|
144
|
+
try {
|
|
145
|
+
for (let i = 1; i <= runs; i++) {
|
|
146
|
+
const eventsBefore = client.events.events.length;
|
|
147
|
+
const r = await act.run(client, args, timeoutMs);
|
|
148
|
+
const evs = client.events.events.slice(eventsBefore);
|
|
149
|
+
if (r.ok === false || !r.record) {
|
|
150
|
+
return fail('TIMING_RUN', '任务没跑起来:' + String(r.error ?? '?'), undefined, EXIT.FINDINGS);
|
|
151
|
+
}
|
|
152
|
+
const rec = r.record;
|
|
153
|
+
/* 时间线对齐:run 类事件带节点名与消息;stable 是画面静默点 */
|
|
154
|
+
const runEvs = evs.filter((e) => e.type === 'run' && e.node);
|
|
155
|
+
const stables = evs.filter((e) => e.type === 'stable').map((e) => Number(e.t));
|
|
156
|
+
const nodes = rec.nodes.map((n) => {
|
|
157
|
+
const done = runEvs.filter((e) => e.node === n.name && /Succeeded$/.test(e.msg)).at(-1)
|
|
158
|
+
?? runEvs.filter((e) => e.node === n.name && /Failed$/.test(e.msg)).at(-1);
|
|
159
|
+
if (!done)
|
|
160
|
+
return { name: n.name, ms: n.ms, status: n.status, settle: null, nextBeforeStable: false };
|
|
161
|
+
const nextNode = runEvs.find((e) => e.t > done.t && e.node !== n.name);
|
|
162
|
+
const stable = stables.find((t) => t > done.t);
|
|
163
|
+
const settle = stable !== undefined ? stable - done.t : null;
|
|
164
|
+
return {
|
|
165
|
+
name: n.name, ms: n.ms, status: n.status,
|
|
166
|
+
settle,
|
|
167
|
+
nextBeforeStable: nextNode !== undefined && (stable === undefined || nextNode.t < stable),
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
samples.push({ index: i, ok: rec.ok, durationMs: rec.durationMs, nodes, events: evs.length });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
await act.streamStop(client).catch(() => null);
|
|
175
|
+
}
|
|
176
|
+
const agg = aggregateTiming(samples);
|
|
177
|
+
if (!agg.successful) {
|
|
178
|
+
return fail('TIMING_RUN', runs + ' 次采样全部未成功——没有可用于建议的成功样本', undefined, EXIT.FINDINGS);
|
|
179
|
+
}
|
|
180
|
+
const unsettled = agg.nodeStats.filter((n) => n.nextBeforeStable);
|
|
181
|
+
const last = samples.at(-1);
|
|
182
|
+
const human = [
|
|
183
|
+
...describeSession(s),
|
|
184
|
+
'timing 采样 x' + runs + '(' + agg.successful + ' 成功' + (agg.failed ? ' / ' + agg.failed + ' 失败' : '') + '):',
|
|
185
|
+
...samples.map((smp) => ' #' + smp.index + ' ' + (smp.ok ? '成功' : '失败(不计入建议)') + ' ' + smp.durationMs + 'ms ' + smp.nodes.length + ' 节点'),
|
|
186
|
+
'节点时长分布(成功样本,P50 / P95):',
|
|
187
|
+
...agg.nodeStats.map((n) => ' [' + n.status + '] ' + n.name + ' ' + n.msP50 + ' / ' + n.msP95 + 'ms' +
|
|
188
|
+
(n.settleP50 !== null ? ' 稳定 +' + n.settleP50 + ' / +' + n.settleP95 + 'ms' : '') +
|
|
189
|
+
(n.occurrences > n.runs ? ' (重复执行 ' + n.occurrences + ' 次 / ' + n.runs + ' run——重试或 Next 环)' : '') +
|
|
190
|
+
(n.runs < agg.successful ? ' (' + n.runs + '/' + agg.successful + ' run 出现——分支或跳过)' : '') +
|
|
191
|
+
(n.nextBeforeStable ? ' (下一节点先于画面稳定开始——识别窗口紧或连续动画)' : '')),
|
|
192
|
+
'建议(P95 × 余量,n=' + agg.successful + ' 成功采样;界面切换优先用 next 等待节点表达,delay 尽量保持缺省):',
|
|
193
|
+
' 节点 timeout ≥ ' + agg.suggest.nodeTimeoutMs + 'ms(各 run 最长节点 P95 ' + agg.maxNodeP95 + 'ms × 1.5)',
|
|
194
|
+
' 任务 timeout ≥ ' + agg.suggest.taskTimeoutMs + 'ms(任务时长 P95 ' + agg.durationP95 + 'ms × 2)',
|
|
195
|
+
agg.suggest.postDelayMs !== null
|
|
196
|
+
? ' 动作后稳定参考 ' + agg.suggest.postDelayMs + 'ms(各 run 最长稳定 P95 ' + agg.maxSettleP95 + 'ms × 1.2)——优先由 next 等待节点的 timeout 覆盖该时长;确需兜底用 post_wait_freezes,post_delay 是最后手段'
|
|
197
|
+
: ' 动作后稳定时间:无 stable 事件可参考(画面持续变化或流太短)',
|
|
198
|
+
];
|
|
199
|
+
if (agg.failed)
|
|
200
|
+
human.push(' 注意:' + agg.failed + ' 个失败 run 未计入建议;失败原因与时长见 data.runs');
|
|
201
|
+
if (unsettled.length) {
|
|
202
|
+
human.push(' 注意:' + unsettled.map((n) => n.name).join(' , ') + ' 未等画面稳定就进入下一节点');
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
exitCode: EXIT.OK,
|
|
206
|
+
human,
|
|
207
|
+
data: {
|
|
208
|
+
runs: samples, distribution: agg, suggest: agg.suggest,
|
|
209
|
+
/* 兼容字段:单次消费方读 record / nodes 的形状不变 */
|
|
210
|
+
record: { ok: last.ok, durationMs: last.durationMs, nodes: last.nodes },
|
|
211
|
+
nodes: last.nodes,
|
|
212
|
+
sampledEvents: samples.reduce((a, smp) => a + smp.events, 0),
|
|
213
|
+
},
|
|
214
|
+
warnings: [
|
|
215
|
+
...(agg.failed ? [agg.failed + ' 个失败 run 未计入建议'] : []),
|
|
216
|
+
...samples.filter((smp) => !smp.ok).map((smp) => 'run #' + smp.index + ' 未成功——该样本已排除'),
|
|
217
|
+
...(unsettled.length ? [unsettled.length + ' 个节点未等画面稳定即进入下一节点:' + unsettled.map((n) => n.name).join(' , ')] : []),
|
|
218
|
+
...(runs === 1 ? ['单次采样=下界:加 --runs 3-5 取分布再定稿'] : []),
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
return daemonFail(e);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
export const TIMING_COMMANDS = [timingCommand];
|
|
229
|
+
//# sourceMappingURL=timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/commands/timing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** `maafw-live version` —— CLI 与运行环境版本。技能用它做版本对齐;`--check` 对 registry 查有没有新版。 */
|
|
2
|
+
import { EXIT, fail } from '../protocol.js';
|
|
3
|
+
import { cliPackage } from '../pkg.js';
|
|
4
|
+
import { compareVersions, fetchLatest, readState, shouldCheck, updateCheckDisabled, writeState, } from '../update-check.js';
|
|
5
|
+
export const versionCommand = {
|
|
6
|
+
name: 'version',
|
|
7
|
+
summary: '打印 maafw-live CLI 及依赖的版本;--check 顺带对 registry 查有没有新版',
|
|
8
|
+
usage: 'maafw-live version [--check]',
|
|
9
|
+
options: { check: { type: 'boolean' } },
|
|
10
|
+
async run(ctx) {
|
|
11
|
+
const pkg = cliPackage();
|
|
12
|
+
const human = [
|
|
13
|
+
`${pkg.name} ${pkg.version}`,
|
|
14
|
+
// 装的是带 scope 的包名,敲的是裸名——同一个词的两种形态,这里显式给出敲的那个
|
|
15
|
+
` command maafw-live`,
|
|
16
|
+
` node ${process.version}`,
|
|
17
|
+
` platform ${process.platform} ${process.arch}`,
|
|
18
|
+
];
|
|
19
|
+
const data = {
|
|
20
|
+
name: pkg.name,
|
|
21
|
+
version: pkg.version,
|
|
22
|
+
node: process.version,
|
|
23
|
+
platform: process.platform,
|
|
24
|
+
arch: process.arch,
|
|
25
|
+
};
|
|
26
|
+
const explicit = ctx.values.check === true;
|
|
27
|
+
/* 显式请求:不受 TTY/限频约束,查不到要如实说。自动路径:只在交互终端、限频、失败静默。 */
|
|
28
|
+
const auto = !explicit && !updateCheckDisabled() && process.stdout.isTTY === true;
|
|
29
|
+
if (explicit || auto) {
|
|
30
|
+
let latest = auto ? readState()?.latest ?? null : null;
|
|
31
|
+
let fresh = false;
|
|
32
|
+
const cached = readState();
|
|
33
|
+
if (explicit || shouldCheck(cached, Date.now())) {
|
|
34
|
+
const fetched = await fetchLatest(pkg.name);
|
|
35
|
+
if (fetched) {
|
|
36
|
+
latest = fetched;
|
|
37
|
+
writeState({ checkedAt: Date.now(), latest: fetched });
|
|
38
|
+
fresh = true;
|
|
39
|
+
}
|
|
40
|
+
else if (explicit) {
|
|
41
|
+
return fail('UPDATE_CHECK_FAILED', '查询 registry 失败(离线 / 代理 / registry 抖动)', '加 --check 才需要联网;不带它 version 完全离线可用', EXIT.ENV);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (cached) {
|
|
45
|
+
latest = cached.latest;
|
|
46
|
+
}
|
|
47
|
+
if (latest) {
|
|
48
|
+
const cmp = compareVersions(latest, pkg.version);
|
|
49
|
+
data.latest = latest;
|
|
50
|
+
data.updateAvailable = cmp > 0;
|
|
51
|
+
data.source = fresh ? 'registry' : 'cache';
|
|
52
|
+
if (cmp > 0) {
|
|
53
|
+
human.push(` 新版 ${latest}(当前 ${pkg.version})`, ` 升级 npm install --global ${pkg.name}@latest`);
|
|
54
|
+
/* 自动提示不改退出码:版本旧不是"这次调用发现的问题" */
|
|
55
|
+
return { exitCode: explicit ? EXIT.FINDINGS : EXIT.OK, human, data };
|
|
56
|
+
}
|
|
57
|
+
human.push(` 最新 ${latest}(已是最新)`);
|
|
58
|
+
}
|
|
59
|
+
else if (explicit) {
|
|
60
|
+
human.push(' 最新 查询不到(registry 不可达)');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { exitCode: EXIT.OK, human, data };
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"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"}
|