browser-opt 1.1.1 → 1.1.2
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/dist/cli/utils/artifact-health.d.ts +21 -0
- package/dist/cli/utils/artifact-health.d.ts.map +1 -0
- package/dist/cli/utils/artifact-health.js +161 -0
- package/dist/cli/utils/artifact-health.js.map +1 -0
- package/dist/cli/utils/output.d.ts.map +1 -1
- package/dist/cli/utils/output.js +13 -0
- package/dist/cli/utils/output.js.map +1 -1
- package/package.json +1 -1
- package/skills/browser-opt/SKILL.md +5 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface BrowserOptArtifactItem {
|
|
2
|
+
path: string;
|
|
3
|
+
sizeBytes: number;
|
|
4
|
+
modifiedAtMs: number;
|
|
5
|
+
}
|
|
6
|
+
export interface BrowserOptArtifactCleanupAdvice {
|
|
7
|
+
artifactCount: number;
|
|
8
|
+
totalSizeBytes: number;
|
|
9
|
+
exceedsCountLimit: boolean;
|
|
10
|
+
exceedsSizeLimit: boolean;
|
|
11
|
+
candidates: BrowserOptArtifactItem[];
|
|
12
|
+
remainingSizeBytes: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 检查项目内临时产物;任何读取异常都按不可安全建议删除处理,不影响原任务结果。
|
|
16
|
+
*/
|
|
17
|
+
export declare function inspectBrowserOptArtifacts(projectDir: string, currentOutputDir?: string, currentHandoffRunId?: string): BrowserOptArtifactCleanupAdvice | null;
|
|
18
|
+
/** 把产物检查结果渲染为简短、可直接操作但不自动执行的删除建议。 */
|
|
19
|
+
export declare function formatBrowserOptArtifactCleanupAdvice(advice: BrowserOptArtifactCleanupAdvice): string[];
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=artifact-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-health.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/artifact-health.ts"],"names":[],"mappings":"AAOA,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,+BAA+B;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAMD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,MAAM,EACzB,mBAAmB,CAAC,EAAE,MAAM,GAC3B,+BAA+B,GAAG,IAAI,CAiDxC;AAwED,qCAAqC;AACrC,wBAAgB,qCAAqC,CAAC,MAAM,EAAE,+BAA+B,GAAG,MAAM,EAAE,CAuBvG"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 检查当前项目 browser-opt 临时产物的数量与容量,并生成只读清理建议。
|
|
3
|
+
* 该模块只处理可重建的运行证据与已结束 handoff,不接触登录态和 Workflow。
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
const ARTIFACT_COUNT_LIMIT = 10;
|
|
8
|
+
const TEMPORARY_SIZE_LIMIT_BYTES = 500 * 1024 * 1024;
|
|
9
|
+
const DEFAULT_DATA_DIR = '.browser-opt';
|
|
10
|
+
/**
|
|
11
|
+
* 检查项目内临时产物;任何读取异常都按不可安全建议删除处理,不影响原任务结果。
|
|
12
|
+
*/
|
|
13
|
+
export function inspectBrowserOptArtifacts(projectDir, currentOutputDir, currentHandoffRunId) {
|
|
14
|
+
try {
|
|
15
|
+
const dataDir = path.resolve(projectDir, DEFAULT_DATA_DIR);
|
|
16
|
+
const artifacts = collectArtifactItems(path.join(dataDir, 'artifacts'));
|
|
17
|
+
const handoffs = collectCompletedHandoffItems(path.join(dataDir, 'handoffs'), currentHandoffRunId);
|
|
18
|
+
const totalSizeBytes = [...artifacts, ...handoffs].reduce((total, item) => total + item.sizeBytes, 0);
|
|
19
|
+
const exceedsCountLimit = artifacts.length > ARTIFACT_COUNT_LIMIT;
|
|
20
|
+
const exceedsSizeLimit = totalSizeBytes > TEMPORARY_SIZE_LIMIT_BYTES;
|
|
21
|
+
if (!exceedsCountLimit && !exceedsSizeLimit) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const protectedOutputDir = currentOutputDir ? path.resolve(currentOutputDir) : undefined;
|
|
25
|
+
const removableArtifacts = artifacts.filter((item) => item.path !== protectedOutputDir);
|
|
26
|
+
const candidates = [];
|
|
27
|
+
const selectedPaths = new Set();
|
|
28
|
+
let remainingSizeBytes = totalSizeBytes;
|
|
29
|
+
const requiredArtifactDeletions = Math.max(0, artifacts.length - ARTIFACT_COUNT_LIMIT);
|
|
30
|
+
for (const item of removableArtifacts.slice(0, requiredArtifactDeletions)) {
|
|
31
|
+
candidates.push(item);
|
|
32
|
+
selectedPaths.add(item.path);
|
|
33
|
+
remainingSizeBytes -= item.sizeBytes;
|
|
34
|
+
}
|
|
35
|
+
if (remainingSizeBytes > TEMPORARY_SIZE_LIMIT_BYTES) {
|
|
36
|
+
const remainingItems = [...removableArtifacts, ...handoffs]
|
|
37
|
+
.filter((item) => !selectedPaths.has(item.path))
|
|
38
|
+
.sort(compareArtifactItems);
|
|
39
|
+
for (const item of remainingItems) {
|
|
40
|
+
candidates.push(item);
|
|
41
|
+
remainingSizeBytes -= item.sizeBytes;
|
|
42
|
+
if (remainingSizeBytes <= TEMPORARY_SIZE_LIMIT_BYTES) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
artifactCount: artifacts.length,
|
|
49
|
+
totalSizeBytes,
|
|
50
|
+
exceedsCountLimit,
|
|
51
|
+
exceedsSizeLimit,
|
|
52
|
+
candidates: candidates.sort(compareArtifactItems),
|
|
53
|
+
remainingSizeBytes: Math.max(0, remainingSizeBytes),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** 按一级目录收集每次运行的证据,目录时间相同时使用绝对路径稳定排序。 */
|
|
61
|
+
function collectArtifactItems(artifactsDir) {
|
|
62
|
+
return collectChildDirectories(artifactsDir)
|
|
63
|
+
.map(createArtifactItem)
|
|
64
|
+
.filter((item) => Boolean(item))
|
|
65
|
+
.sort(compareArtifactItems);
|
|
66
|
+
}
|
|
67
|
+
/** 只收集输出中已经出现 PASS 或 FAIL 终态的 handoff 目录。 */
|
|
68
|
+
function collectCompletedHandoffItems(handoffsDir, currentRunId) {
|
|
69
|
+
return collectChildDirectories(handoffsDir)
|
|
70
|
+
.filter((entryPath) => path.basename(entryPath) !== currentRunId)
|
|
71
|
+
.filter((entryPath) => hasTerminalHandoffOutput(path.join(entryPath, 'output.log')))
|
|
72
|
+
.map(createArtifactItem)
|
|
73
|
+
.filter((item) => Boolean(item))
|
|
74
|
+
.sort(compareArtifactItems);
|
|
75
|
+
}
|
|
76
|
+
function collectChildDirectories(parentDir) {
|
|
77
|
+
try {
|
|
78
|
+
return fs.readdirSync(parentDir, { withFileTypes: true })
|
|
79
|
+
.filter((entry) => entry.isDirectory() && !entry.isSymbolicLink())
|
|
80
|
+
.map((entry) => path.resolve(parentDir, entry.name));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function createArtifactItem(entryPath) {
|
|
87
|
+
try {
|
|
88
|
+
const stat = fs.lstatSync(entryPath);
|
|
89
|
+
return {
|
|
90
|
+
path: entryPath,
|
|
91
|
+
sizeBytes: directorySize(entryPath),
|
|
92
|
+
modifiedAtMs: stat.mtimeMs,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** 递归统计普通文件大小;符号链接只计算链接本身且绝不继续遍历目标。 */
|
|
100
|
+
function directorySize(entryPath) {
|
|
101
|
+
try {
|
|
102
|
+
const stat = fs.lstatSync(entryPath);
|
|
103
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
104
|
+
return stat.size;
|
|
105
|
+
}
|
|
106
|
+
return fs.readdirSync(entryPath).reduce((total, name) => total + directorySize(path.join(entryPath, name)), 0);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function hasTerminalHandoffOutput(outputPath) {
|
|
113
|
+
try {
|
|
114
|
+
const output = fs.readFileSync(outputPath, 'utf-8');
|
|
115
|
+
return /(?:^|\n)执行成功(?:\n|$)/.test(output) || /(?:^|\n)Status: (?:PASS|FAIL)(?:\n|$)/.test(output);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function compareArtifactItems(left, right) {
|
|
122
|
+
return left.modifiedAtMs - right.modifiedAtMs || left.path.localeCompare(right.path);
|
|
123
|
+
}
|
|
124
|
+
/** 把产物检查结果渲染为简短、可直接操作但不自动执行的删除建议。 */
|
|
125
|
+
export function formatBrowserOptArtifactCleanupAdvice(advice) {
|
|
126
|
+
const reasons = [
|
|
127
|
+
...(advice.exceedsCountLimit ? [`运行产物 ${advice.artifactCount} 份,超过 10 份`] : []),
|
|
128
|
+
...(advice.exceedsSizeLimit ? [`临时产物总量 ${formatBytes(advice.totalSizeBytes)},超过 500 MB`] : []),
|
|
129
|
+
];
|
|
130
|
+
const shownCandidates = advice.candidates.slice(0, 5);
|
|
131
|
+
const reclaimableBytes = advice.candidates.reduce((total, item) => total + item.sizeBytes, 0);
|
|
132
|
+
const lines = [
|
|
133
|
+
`产物清理建议:${reasons.join(';')}。以下仅为建议,尚未删除任何文件。`,
|
|
134
|
+
...(shownCandidates.length > 0
|
|
135
|
+
? [
|
|
136
|
+
`建议从最旧产物开始删除,预计可释放 ${formatBytes(reclaimableBytes)}:`,
|
|
137
|
+
...shownCandidates.map((item) => ` - ${item.path}(${formatBytes(item.sizeBytes)})`),
|
|
138
|
+
]
|
|
139
|
+
: ['没有可安全建议删除的旧产物。']),
|
|
140
|
+
];
|
|
141
|
+
if (advice.candidates.length > shownCandidates.length) {
|
|
142
|
+
lines.push(` - 另有 ${advice.candidates.length - shownCandidates.length} 个较新候选未展开`);
|
|
143
|
+
}
|
|
144
|
+
if (advice.remainingSizeBytes > TEMPORARY_SIZE_LIMIT_BYTES) {
|
|
145
|
+
lines.push('删除上述旧产物后仍可能超过 500 MB,请审阅本次运行证据后再决定是否手动删除。');
|
|
146
|
+
}
|
|
147
|
+
return lines;
|
|
148
|
+
}
|
|
149
|
+
function formatBytes(sizeBytes) {
|
|
150
|
+
if (sizeBytes >= 1024 * 1024 * 1024) {
|
|
151
|
+
return `${(sizeBytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
|
|
152
|
+
}
|
|
153
|
+
if (sizeBytes >= 1024 * 1024) {
|
|
154
|
+
return `${(sizeBytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
155
|
+
}
|
|
156
|
+
if (sizeBytes >= 1024) {
|
|
157
|
+
return `${(sizeBytes / 1024).toFixed(2)} KB`;
|
|
158
|
+
}
|
|
159
|
+
return `${sizeBytes} B`;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=artifact-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-health.js","sourceRoot":"","sources":["../../../src/cli/utils/artifact-health.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAOrE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CA4DvE"}
|
package/dist/cli/utils/output.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { collectFailedBrowserOptSteps, formatBrowserOptStepStatus } from '../../browser-opt/utils.js';
|
|
2
|
+
import { formatBrowserOptArtifactCleanupAdvice, inspectBrowserOptArtifacts, } from './artifact-health.js';
|
|
2
3
|
export function printBrowserOptResult(result) {
|
|
3
4
|
if (result.passed) {
|
|
4
5
|
console.log('执行成功');
|
|
6
|
+
printArtifactCleanupAdvice(result);
|
|
5
7
|
return;
|
|
6
8
|
}
|
|
7
9
|
const { report } = result;
|
|
@@ -52,5 +54,16 @@ export function printBrowserOptResult(result) {
|
|
|
52
54
|
console.log(` Error: ${step.error}`);
|
|
53
55
|
}
|
|
54
56
|
}
|
|
57
|
+
printArtifactCleanupAdvice(result);
|
|
58
|
+
}
|
|
59
|
+
/** 任务结果输出完成后检查项目临时产物,检查失败不得覆盖原始 PASS/FAIL。 */
|
|
60
|
+
function printArtifactCleanupAdvice(result) {
|
|
61
|
+
const advice = inspectBrowserOptArtifacts(process.cwd(), result.report.outputDir, process.env.BROWSER_OPT_HANDOFF_RUN_ID);
|
|
62
|
+
if (!advice) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const line of formatBrowserOptArtifactCleanupAdvice(advice)) {
|
|
66
|
+
console.log(line);
|
|
67
|
+
}
|
|
55
68
|
}
|
|
56
69
|
//# sourceMappingURL=output.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -337,5 +337,9 @@ Expected artifacts:
|
|
|
337
337
|
|
|
338
338
|
The assistant response must be concise:
|
|
339
339
|
|
|
340
|
-
- If the run succeeds, reply only with `执行成功`.
|
|
340
|
+
- If the run succeeds and no cleanup advice is printed, reply only with `执行成功`.
|
|
341
|
+
- If the CLI prints cleanup advice because the current project's `.browser-opt/artifacts/`
|
|
342
|
+
has more than 10 run directories or temporary artifacts exceed 500 MB, include that
|
|
343
|
+
advice after the result. It lists the oldest safe deletion candidates first and does not
|
|
344
|
+
mean any files were deleted. Never delete them unless the user explicitly asks.
|
|
341
345
|
- If the run fails, summarize the failure status, report paths, screenshot paths, and failing step.
|