@lark-apaas/openclaw-scripts-diagnose-cli 0.1.9-alpha.1 → 0.1.10-alpha.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/dist/index.cjs +129 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ node_assert = __toESM(node_assert);
|
|
|
52
52
|
* it terse and parseable.
|
|
53
53
|
*/
|
|
54
54
|
function getVersion() {
|
|
55
|
-
return "0.1.
|
|
55
|
+
return "0.1.10-alpha.0";
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/rule-engine/base.ts
|
|
@@ -1523,6 +1523,133 @@ function applyVars(str, entries) {
|
|
|
1523
1523
|
return out;
|
|
1524
1524
|
}
|
|
1525
1525
|
//#endregion
|
|
1526
|
+
//#region src/rules/agents-md-paths.ts
|
|
1527
|
+
function collectExistingAgentsMdPaths(ctx) {
|
|
1528
|
+
const paths = /* @__PURE__ */ new Set();
|
|
1529
|
+
if (ctx.configPath) paths.add(node_path.default.join(node_path.default.dirname(ctx.configPath), "workspace", "AGENTS.md"));
|
|
1530
|
+
const agents = asRecord(ctx.config.agents);
|
|
1531
|
+
const list = Array.isArray(agents?.list) ? agents.list : [];
|
|
1532
|
+
for (const item of list) {
|
|
1533
|
+
const agent = asRecord(item);
|
|
1534
|
+
if (typeof agent?.workspace === "string" && agent.workspace) paths.add(node_path.default.join(agent.workspace, "AGENTS.md"));
|
|
1535
|
+
}
|
|
1536
|
+
return [...paths].filter((filePath) => node_fs.default.existsSync(filePath));
|
|
1537
|
+
}
|
|
1538
|
+
//#endregion
|
|
1539
|
+
//#region src/rules/agents-md-service-commands.ts
|
|
1540
|
+
const SERVICE_COMMAND_REPLACEMENTS = [
|
|
1541
|
+
["`sh scripts/start.sh`", "`sh /opt/force/bin/openclaw_scripts/start.sh`"],
|
|
1542
|
+
["`sh scripts/restart.sh`", "`sh /opt/force/bin/openclaw_scripts/restart.sh`"],
|
|
1543
|
+
["`sh scripts/stop.sh`", "`sh /opt/force/bin/openclaw_scripts/stop.sh`"]
|
|
1544
|
+
];
|
|
1545
|
+
let AgentsMdServiceCommandsRule = class AgentsMdServiceCommandsRule extends DiagnoseRule {
|
|
1546
|
+
validate(ctx) {
|
|
1547
|
+
const agentsMdPath = collectExistingAgentsMdPaths(ctx).find((filePath) => {
|
|
1548
|
+
return hasOldServiceCommands(node_fs.default.readFileSync(filePath, "utf-8"));
|
|
1549
|
+
});
|
|
1550
|
+
if (!agentsMdPath) return { pass: true };
|
|
1551
|
+
return {
|
|
1552
|
+
pass: false,
|
|
1553
|
+
message: `${agentsMdPath} 中存在旧版服务命令,需要改为 /opt/force/bin/openclaw_scripts 路径`
|
|
1554
|
+
};
|
|
1555
|
+
}
|
|
1556
|
+
repair(ctx) {
|
|
1557
|
+
for (const agentsMdPath of collectExistingAgentsMdPaths(ctx)) {
|
|
1558
|
+
const content = node_fs.default.readFileSync(agentsMdPath, "utf-8");
|
|
1559
|
+
const next = replaceOldServiceCommands(content);
|
|
1560
|
+
if (next !== content) node_fs.default.writeFileSync(agentsMdPath, next, "utf-8");
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
AgentsMdServiceCommandsRule = __decorate([Rule({
|
|
1565
|
+
key: "agents_md_service_commands",
|
|
1566
|
+
description: "检测各智能体 AGENTS.md 中旧版 OpenClaw 服务命令,并替换为 /opt/force/bin/openclaw_scripts 路径",
|
|
1567
|
+
dependsOn: ["config_syntax_check"],
|
|
1568
|
+
repairMode: "standard"
|
|
1569
|
+
})], AgentsMdServiceCommandsRule);
|
|
1570
|
+
function hasOldServiceCommands(content) {
|
|
1571
|
+
return SERVICE_COMMAND_REPLACEMENTS.some(([oldCmd]) => content.includes(oldCmd));
|
|
1572
|
+
}
|
|
1573
|
+
function replaceOldServiceCommands(content) {
|
|
1574
|
+
let next = content;
|
|
1575
|
+
for (const [oldCmd, newCmd] of SERVICE_COMMAND_REPLACEMENTS) next = next.split(oldCmd).join(newCmd);
|
|
1576
|
+
return next;
|
|
1577
|
+
}
|
|
1578
|
+
//#endregion
|
|
1579
|
+
//#region src/rules/agents-md-resource-constrained-tools.ts
|
|
1580
|
+
const RESOURCE_CONSTRAINED_TOOLS_TAG = "resource_constrained_tools";
|
|
1581
|
+
const RESOURCE_CONSTRAINED_TOOLS_BLOCK = [
|
|
1582
|
+
"<resource_constrained_tools>",
|
|
1583
|
+
"### Browser tab 管理",
|
|
1584
|
+
"Chrome tab 是沙箱里的**头号资源杀手**:在线上 OpenClaw 集群的 Mem Top10 里占 42%、CPU Top10 里占 70%。下面规则**全部**指 `browser` 工具自身的 action(不是别的 MCP),按\"调用前 / 调用后 / 自查 / 兜底\"四阶段顺序遵守,不要跳。",
|
|
1585
|
+
"#### 调用 `browser action: \"open\"` 之前——必答两问",
|
|
1586
|
+
"1. 我上一次 `open` 的 tab 是否还活着?活着 → 用 `action: \"navigate\"` + 它的 `targetId` 换 URL,**不要新开**。",
|
|
1587
|
+
"2. 完成这次访问后,我下一步能不能立刻 `close`?不能 → 拆小任务,先不开。",
|
|
1588
|
+
"#### 调用 `browser action: \"open\"` 之后——下一个 `browser` 工具调用必须是以下之一",
|
|
1589
|
+
"- `action: \"navigate\"`(带 open 返回的 `targetId`):复用此 tab 换 URL。",
|
|
1590
|
+
"- `action: \"close\"`(带 open 返回的 `targetId`):关闭此 tab,任务结束。",
|
|
1591
|
+
"- `action: \"snapshot\"` / `\"click\"` / `\"type\"` 等:仅当**当前任务仍在这个 tab 上推进**时可用;任务做完仍必须显式 `close` 并传 `targetId`。",
|
|
1592
|
+
"**严禁**下面这种序列(线上实测到的 chrome 内存 Top1 故障模式):",
|
|
1593
|
+
" BAD:",
|
|
1594
|
+
" browser(open, url=A) → snapshot",
|
|
1595
|
+
" → browser(open, url=B) → snapshot",
|
|
1596
|
+
" → browser(open, url=C) → snapshot",
|
|
1597
|
+
" → …(任务结束未关)",
|
|
1598
|
+
" # 每次 open 都新建一个 tab;snapshot 不会关;chrome 堆栈式泄漏。",
|
|
1599
|
+
"应该写成:",
|
|
1600
|
+
" GOOD:",
|
|
1601
|
+
" browser(open, url=A) → snapshot",
|
|
1602
|
+
" → browser(navigate, targetId=t1, url=B) → snapshot",
|
|
1603
|
+
" → … → browser(close, targetId=t1)",
|
|
1604
|
+
" # 始终复用同一个 tab;任务结束显式 close。",
|
|
1605
|
+
"#### 异常时止损",
|
|
1606
|
+
"发现 Chrome 卡顿、心跳延迟、沙箱负载升高:先 `close` 所有非活跃 tab;仍不行就让 shell 杀掉 chrome 进程(`pkill -INT chromium-browser` 或等价命令)让它按需重启,**不要**继续开新 tab。",
|
|
1607
|
+
"### FFmpeg / 媒体编码使用限制",
|
|
1608
|
+
"ffmpeg 默认吃满所有 CPU 核心,沙箱只有 1–2 vCPU,一次无约束转码就能拖垮心跳和 Browser。下面的规则**只针对 shell 直接调用的 `ffmpeg` / `ffprobe`**:",
|
|
1609
|
+
"- **优先用 skill:** `skills/video-frames` 等媒体 skill 是已审查过的窄用例,跟着它们的写法走比自己手撸 ffmpeg 安全;只在 skill 不覆盖时才直接 shell `ffmpeg`。注意 `video-frames` 抽中后段帧用 `--time`(demuxer seek,几乎零 CPU)而非 `--index N`(会从头解码 N 帧)。",
|
|
1610
|
+
"- **先 probe 再 encode:** 转码前先 `ffprobe -v error -threads 1 -show_streams -show_format -of json <input>` 拿到时长、码率、编码;能用 `-c copy` 流拷贝就绝不重编码;时长超 1200s 先 `-t` 截断或拒绝任务。",
|
|
1611
|
+
"- **强制限线程:** 必须显式带 `-threads 1`(最多 `-threads 2`),滤镜链追加 `-filter_threads 1 -filter_complex_threads 1`。",
|
|
1612
|
+
"- **软件编码必须 ultrafast:** x264/x265 统一 `-preset ultrafast`,禁止 `medium` 及以上预设;质量不够时降分辨率(`-vf scale=-2:720`)或降帧率(`-r 24`),不要靠提高 preset。",
|
|
1613
|
+
"- **禁止并发 ffmpeg:** 同一沙箱内同时只允许一个 ffmpeg 进程,开下一个前用 `pgrep -x ffmpeg` 确认无残留;禁止 `xargs -P`、禁止循环里并行批处理。",
|
|
1614
|
+
"- **必须前台 + 超时兜底:** 用 `timeout 45 ffmpeg -nostdin -hide_banner -loglevel error ...` 包一层(与上游 `MEDIA_FFMPEG_TIMEOUT_MS` 对齐,最多放宽到 `timeout 90`),ffprobe 用 `timeout 10`;禁止 `&` 后台、禁止 `nohup`,跑飞时必须能 Ctrl-C 打断。",
|
|
1615
|
+
"- **中间产物即用即删:** 临时切片、调色板、`-pass 1` log 等,任务结束或失败时立即 `rm -f`,不要把 `/tmp/*.mp4`、`ffmpeg2pass-*.log` 留到下一个任务。",
|
|
1616
|
+
"- **异常时硬停:** 沙箱变慢、心跳丢失、或 `frame=` 长时间不前进,立即 `pkill -INT ffmpeg`(不行就 `-KILL`);**不要**重试相同命令,先降分辨率/preset 或改用流拷贝。",
|
|
1617
|
+
"</resource_constrained_tools>"
|
|
1618
|
+
].join("\n");
|
|
1619
|
+
let AgentsMdResourceConstrainedToolsRule = class AgentsMdResourceConstrainedToolsRule extends DiagnoseRule {
|
|
1620
|
+
validate(ctx) {
|
|
1621
|
+
const stalePath = collectExistingAgentsMdPaths(ctx).find((filePath) => {
|
|
1622
|
+
return !hasCurrentResourceConstrainedToolsBlock(node_fs.default.readFileSync(filePath, "utf-8"));
|
|
1623
|
+
});
|
|
1624
|
+
if (!stalePath) return { pass: true };
|
|
1625
|
+
return {
|
|
1626
|
+
pass: false,
|
|
1627
|
+
message: `${stalePath} 中缺少或存在旧版 resource_constrained_tools,需要更新`
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
repair(ctx) {
|
|
1631
|
+
for (const filePath of collectExistingAgentsMdPaths(ctx)) {
|
|
1632
|
+
const content = node_fs.default.readFileSync(filePath, "utf-8");
|
|
1633
|
+
const next = upsertResourceConstrainedToolsBlock(content);
|
|
1634
|
+
if (next !== content) node_fs.default.writeFileSync(filePath, next, "utf-8");
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
AgentsMdResourceConstrainedToolsRule = __decorate([Rule({
|
|
1639
|
+
key: "agents_md_resource_constrained_tools",
|
|
1640
|
+
description: "检测各智能体 AGENTS.md 中 resource_constrained_tools 规则块,缺失时追加,存在时替换为当前内容",
|
|
1641
|
+
dependsOn: ["config_syntax_check"],
|
|
1642
|
+
repairMode: "standard"
|
|
1643
|
+
})], AgentsMdResourceConstrainedToolsRule);
|
|
1644
|
+
function hasCurrentResourceConstrainedToolsBlock(content) {
|
|
1645
|
+
return content.includes(RESOURCE_CONSTRAINED_TOOLS_BLOCK);
|
|
1646
|
+
}
|
|
1647
|
+
function upsertResourceConstrainedToolsBlock(content) {
|
|
1648
|
+
const tagRe = new RegExp(`<${RESOURCE_CONSTRAINED_TOOLS_TAG}>[\\s\\S]*?</${RESOURCE_CONSTRAINED_TOOLS_TAG}>`);
|
|
1649
|
+
if (tagRe.test(content)) return content.replace(tagRe, RESOURCE_CONSTRAINED_TOOLS_BLOCK);
|
|
1650
|
+
return `${content}${content.length > 0 && !content.endsWith("\n") ? "\n\n" : "\n"}${RESOURCE_CONSTRAINED_TOOLS_BLOCK}\n`;
|
|
1651
|
+
}
|
|
1652
|
+
//#endregion
|
|
1526
1653
|
//#region src/rules/model-provider.ts
|
|
1527
1654
|
const DEFAULT_API_KEY = {
|
|
1528
1655
|
source: "file",
|
|
@@ -9875,7 +10002,7 @@ async function reportCliRun(opts) {
|
|
|
9875
10002
|
//#region src/help.ts
|
|
9876
10003
|
const BIN = "mclaw-diagnose";
|
|
9877
10004
|
function versionBanner() {
|
|
9878
|
-
return `v0.1.
|
|
10005
|
+
return `v0.1.10-alpha.0`;
|
|
9879
10006
|
}
|
|
9880
10007
|
const COMMANDS = [
|
|
9881
10008
|
{
|
package/package.json
CHANGED