@lark-apaas/openclaw-scripts-diagnose-cli 0.1.15-alpha.12 → 0.1.15-alpha.14
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 +160 -30
- 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.15-alpha.
|
|
55
|
+
return "0.1.15-alpha.14";
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/rule-engine/base.ts
|
|
@@ -2634,6 +2634,12 @@ const SECRETS_FILE_PATH = "/home/gem/workspace/.force/openclaw/miaoda-openclaw-s
|
|
|
2634
2634
|
/** Absolute path to the openclaw config JSON. */
|
|
2635
2635
|
const CONFIG_PATH = `${WORKSPACE_DIR}/openclaw.json`;
|
|
2636
2636
|
/**
|
|
2637
|
+
* upgrade-lark 场景专属修复状态的信号文件目录。
|
|
2638
|
+
* fixStatus 有值时在此目录下创建同名文件(如 /tmp/event/PORT_FIX_READY),
|
|
2639
|
+
* 文件内容为完整的 UpgradeLarkResult JSON,供外部进程轮询感知升级结果。
|
|
2640
|
+
*/
|
|
2641
|
+
const FIX_EVENT_DIR = "/tmp/event";
|
|
2642
|
+
/**
|
|
2637
2643
|
* upgrade-lark 每次运行的日志文件路径,含时间戳便于按时间排序定位。
|
|
2638
2644
|
* checkOnly=true 时文件名含 "-check" 后缀,便于与正式安装日志区分。
|
|
2639
2645
|
*/
|
|
@@ -3313,6 +3319,13 @@ function execCaptureErr(cmd) {
|
|
|
3313
3319
|
throw new Error(stderrStr ? `${base}\nstderr: ${stderrStr}` : base);
|
|
3314
3320
|
}
|
|
3315
3321
|
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Synchronous sleep using Atomics.wait on a shared buffer.
|
|
3324
|
+
* Works on the main thread (unlike setTimeout which requires an event loop tick).
|
|
3325
|
+
*/
|
|
3326
|
+
function sleepSync(ms) {
|
|
3327
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
3328
|
+
}
|
|
3316
3329
|
/** POSIX single-quote shell escape. Paths with embedded quotes are rare but
|
|
3317
3330
|
* the token-file path conventions in sandboxes don't guarantee cleanliness. */
|
|
3318
3331
|
function shellQuote(s) {
|
|
@@ -7365,14 +7378,6 @@ function getResetTask(taskId) {
|
|
|
7365
7378
|
progress: "等待中..."
|
|
7366
7379
|
};
|
|
7367
7380
|
}
|
|
7368
|
-
/**
|
|
7369
|
-
* Synchronous sleep using Atomics.wait on a shared buffer.
|
|
7370
|
-
*/
|
|
7371
|
-
function sleepSync(ms) {
|
|
7372
|
-
const buf = new SharedArrayBuffer(4);
|
|
7373
|
-
const arr = new Int32Array(buf);
|
|
7374
|
-
Atomics.wait(arr, 0, 0, ms);
|
|
7375
|
-
}
|
|
7376
7381
|
//#endregion
|
|
7377
7382
|
//#region src/oss/resolveOssFileMap.ts
|
|
7378
7383
|
/**
|
|
@@ -10692,7 +10697,7 @@ async function reportCliRun(opts) {
|
|
|
10692
10697
|
//#region src/help.ts
|
|
10693
10698
|
const BIN = "mclaw-diagnose";
|
|
10694
10699
|
function versionBanner() {
|
|
10695
|
-
return `v0.1.15-alpha.
|
|
10700
|
+
return `v0.1.15-alpha.14`;
|
|
10696
10701
|
}
|
|
10697
10702
|
const COMMANDS = [
|
|
10698
10703
|
{
|
|
@@ -11295,6 +11300,7 @@ function reportDoctorRunToSlardar(opts) {
|
|
|
11295
11300
|
* - rollback_ok:回滚是否成功(对应 UpgradeLarkResult.rollbackOk,未触发回滚时为空)
|
|
11296
11301
|
* - validation_error:安装后校验失败信息(对应 UpgradeLarkResult.validationError)
|
|
11297
11302
|
* - error:命令级错误信息(对应 UpgradeLarkResult.error)
|
|
11303
|
+
* - port_check_ok:端口存活检测结果(对应 UpgradeLarkResult.portCheckOk,未执行时为空)
|
|
11298
11304
|
* - result:执行结果一行摘要(派生字段,见 buildUpgradeLarkResultSummary)
|
|
11299
11305
|
* - log_file:日志文件绝对路径(对应 UpgradeLarkResult.logFile)
|
|
11300
11306
|
*
|
|
@@ -11325,6 +11331,7 @@ function reportUpgradeLarkToSlardar(opts) {
|
|
|
11325
11331
|
rollback_ok: String(opts.rollbackOk ?? ""),
|
|
11326
11332
|
validation_error: opts.validationError ?? "",
|
|
11327
11333
|
error: opts.error ?? "",
|
|
11334
|
+
port_check_ok: String(opts.portCheckOk ?? ""),
|
|
11328
11335
|
result: opts.resultSummary,
|
|
11329
11336
|
log_file: opts.logFile
|
|
11330
11337
|
},
|
|
@@ -11334,7 +11341,8 @@ function reportUpgradeLarkToSlardar(opts) {
|
|
|
11334
11341
|
backup_ms: t.backupMs ?? -1,
|
|
11335
11342
|
npx_install_ms: t.npxInstallMs ?? -1,
|
|
11336
11343
|
post_probe_ms: t.postProbeMs ?? -1,
|
|
11337
|
-
doctor_fix_ms: t.doctorFixMs ?? -1
|
|
11344
|
+
doctor_fix_ms: t.doctorFixMs ?? -1,
|
|
11345
|
+
port_check_ms: t.portCheckMs ?? -1
|
|
11338
11346
|
}
|
|
11339
11347
|
});
|
|
11340
11348
|
}
|
|
@@ -11493,6 +11501,82 @@ function probeChannels(label, log, timeoutMs) {
|
|
|
11493
11501
|
};
|
|
11494
11502
|
}
|
|
11495
11503
|
}
|
|
11504
|
+
/**
|
|
11505
|
+
* 根据 scene、最终状态和端口检测结果,计算场景专属修复状态。
|
|
11506
|
+
* scene 不在已知场景列表时返回 undefined。
|
|
11507
|
+
*/
|
|
11508
|
+
function computeFixStatus(scene, status, portCheckOk = void 0) {
|
|
11509
|
+
if (scene === "FromPreviewFailed") return status === "success" && portCheckOk !== false ? "PORT_FIX_READY" : "PORT_FIX_FAILED";
|
|
11510
|
+
if (scene === "FromChannelFailed") return status === "success" ? "CHANNEL_FIX_READY" : "CHANNEL_FIX_FAILED";
|
|
11511
|
+
}
|
|
11512
|
+
/**
|
|
11513
|
+
* 轮询端口检测脚本,确认 openclaw-gateway 在重启后监听指定端口。
|
|
11514
|
+
*
|
|
11515
|
+
* 逻辑:
|
|
11516
|
+
* 1. 先等待 initialWaitMs(让服务有时间完成重启)
|
|
11517
|
+
* 2. 循环执行 `bash ${BUILTIN_PATH}/tool/port_check.sh <port>`,至多 maxAttempts 次:
|
|
11518
|
+
* - 输出为空 → 服务尚未就绪,等 intervalMs 后重试
|
|
11519
|
+
* - 输出含端口号 → 端口存活,返回 ok=true
|
|
11520
|
+
* - 输出非空但不含端口号 → 端口异常,立即返回 ok=false
|
|
11521
|
+
* 3. 超过 maxAttempts 仍无响应 → 返回 ok=false
|
|
11522
|
+
*
|
|
11523
|
+
* 注意:${BUILTIN_PATH} 是沙箱 shell 环境变量,通过 `bash -c` 让 shell 自行展开,
|
|
11524
|
+
* Node 侧不读取、不拼接该路径。
|
|
11525
|
+
*/
|
|
11526
|
+
function pollPortCheck(opts) {
|
|
11527
|
+
const { port, initialWaitMs, intervalMs, maxAttempts, log } = opts;
|
|
11528
|
+
const portStr = String(port);
|
|
11529
|
+
const cmd = "bash ${BUILTIN_PATH}/tool/port_check.sh " + portStr;
|
|
11530
|
+
log(` waiting ${initialWaitMs / 1e3}s before first port-check poll...`);
|
|
11531
|
+
if (initialWaitMs > 0) sleepSync(initialWaitMs);
|
|
11532
|
+
for (let i = 1; i <= maxAttempts; i++) {
|
|
11533
|
+
const r = (0, node_child_process.spawnSync)("bash", ["-c", cmd], {
|
|
11534
|
+
encoding: "utf-8",
|
|
11535
|
+
stdio: [
|
|
11536
|
+
"ignore",
|
|
11537
|
+
"pipe",
|
|
11538
|
+
"pipe"
|
|
11539
|
+
],
|
|
11540
|
+
timeout: 1e4
|
|
11541
|
+
});
|
|
11542
|
+
const output = (r.stdout ?? "").trim();
|
|
11543
|
+
const errout = (r.stderr ?? "").trim();
|
|
11544
|
+
log(` port-check [${i}/${maxAttempts}]: exit=${r.status ?? "null"} output=${JSON.stringify(output)}${errout ? ` stderr=${JSON.stringify(errout)}` : ""}`);
|
|
11545
|
+
if (!output) {
|
|
11546
|
+
sleepSync(intervalMs);
|
|
11547
|
+
continue;
|
|
11548
|
+
}
|
|
11549
|
+
if (output.includes(portStr)) {
|
|
11550
|
+
log(` port-check: SUCCESS — port ${port} confirmed in output`);
|
|
11551
|
+
return {
|
|
11552
|
+
ok: true,
|
|
11553
|
+
output
|
|
11554
|
+
};
|
|
11555
|
+
}
|
|
11556
|
+
log(` port-check: FAILED — output non-empty but port ${port} not found`);
|
|
11557
|
+
return {
|
|
11558
|
+
ok: false,
|
|
11559
|
+
output
|
|
11560
|
+
};
|
|
11561
|
+
}
|
|
11562
|
+
log(` port-check: FAILED — no response after ${maxAttempts} attempts`);
|
|
11563
|
+
return { ok: false };
|
|
11564
|
+
}
|
|
11565
|
+
/**
|
|
11566
|
+
* 将 fixStatus 信号文件写入 /tmp/event/<fixStatus>,内容为完整的 UpgradeLarkResult JSON。
|
|
11567
|
+
* 外部进程(如服务端诊断流程)通过轮询此文件感知升级结果。
|
|
11568
|
+
* 写入失败只记录日志,不影响主流程返回值。
|
|
11569
|
+
*/
|
|
11570
|
+
function writeFixStatusEvent(fixStatus, result, log) {
|
|
11571
|
+
const filePath = `${FIX_EVENT_DIR}/${fixStatus}`;
|
|
11572
|
+
try {
|
|
11573
|
+
node_fs.default.mkdirSync(FIX_EVENT_DIR, { recursive: true });
|
|
11574
|
+
node_fs.default.writeFileSync(filePath, JSON.stringify(result, null, 2));
|
|
11575
|
+
log(`[fix-event] written: ${filePath}`);
|
|
11576
|
+
} catch (e) {
|
|
11577
|
+
log(`[fix-event] write failed: ${filePath} — ${e.message}`);
|
|
11578
|
+
}
|
|
11579
|
+
}
|
|
11496
11580
|
function runUpgradeLark(opts) {
|
|
11497
11581
|
const cwd = opts.cwd ?? "/home/gem/workspace/agent";
|
|
11498
11582
|
const configPath = opts.configPath ?? CONFIG_PATH;
|
|
@@ -11512,6 +11596,26 @@ function runUpgradeLark(opts) {
|
|
|
11512
11596
|
log(` configPath : ${configPath}`);
|
|
11513
11597
|
log(`${"=".repeat(60)}`);
|
|
11514
11598
|
const timing = {};
|
|
11599
|
+
for (const s of [
|
|
11600
|
+
"PORT_FIX_READY",
|
|
11601
|
+
"PORT_FIX_FAILED",
|
|
11602
|
+
"CHANNEL_FIX_READY",
|
|
11603
|
+
"CHANNEL_FIX_FAILED"
|
|
11604
|
+
]) {
|
|
11605
|
+
const f = `${FIX_EVENT_DIR}/${s}`;
|
|
11606
|
+
try {
|
|
11607
|
+
if (node_fs.default.existsSync(f)) {
|
|
11608
|
+
node_fs.default.rmSync(f);
|
|
11609
|
+
log(`[fix-event] cleared stale: ${f}`);
|
|
11610
|
+
}
|
|
11611
|
+
} catch (e) {
|
|
11612
|
+
log(`[fix-event] clear failed: ${f} — ${e.message}`);
|
|
11613
|
+
}
|
|
11614
|
+
}
|
|
11615
|
+
const finalReturn = (r) => {
|
|
11616
|
+
if (r.fixStatus !== void 0) writeFixStatusEvent(r.fixStatus, r, log);
|
|
11617
|
+
return r;
|
|
11618
|
+
};
|
|
11515
11619
|
log("");
|
|
11516
11620
|
log("── [Pre-check A] channels probe(升级前)────────────────");
|
|
11517
11621
|
const t_preProbeStart = Date.now();
|
|
@@ -11550,13 +11654,14 @@ function runUpgradeLark(opts) {
|
|
|
11550
11654
|
log(`${"=".repeat(60)}`);
|
|
11551
11655
|
log("upgrade-lark skipped (pre-check gate)");
|
|
11552
11656
|
log(`${"=".repeat(60)}`);
|
|
11553
|
-
return {
|
|
11657
|
+
return finalReturn({
|
|
11554
11658
|
status: "skipped",
|
|
11555
11659
|
skipReason: reason,
|
|
11556
11660
|
upgradeNeeded: false,
|
|
11557
11661
|
timing,
|
|
11558
|
-
logFile
|
|
11559
|
-
|
|
11662
|
+
logFile,
|
|
11663
|
+
fixStatus: computeFixStatus(opts.scene, "skipped")
|
|
11664
|
+
});
|
|
11560
11665
|
}
|
|
11561
11666
|
if (beforeChannels.anyAccountWorking) {
|
|
11562
11667
|
const reason = "channels are working — upgrade not needed (issue detected but system is functional)";
|
|
@@ -11564,13 +11669,14 @@ function runUpgradeLark(opts) {
|
|
|
11564
11669
|
log(`${"=".repeat(60)}`);
|
|
11565
11670
|
log("upgrade-lark skipped (pre-check gate)");
|
|
11566
11671
|
log(`${"=".repeat(60)}`);
|
|
11567
|
-
return {
|
|
11672
|
+
return finalReturn({
|
|
11568
11673
|
status: "skipped",
|
|
11569
11674
|
skipReason: reason,
|
|
11570
11675
|
upgradeNeeded: false,
|
|
11571
11676
|
timing,
|
|
11572
|
-
logFile
|
|
11573
|
-
|
|
11677
|
+
logFile,
|
|
11678
|
+
fixStatus: computeFixStatus(opts.scene, "skipped")
|
|
11679
|
+
});
|
|
11574
11680
|
}
|
|
11575
11681
|
log(` PROCEED: requiresLarkUpgrade=true (version=${versionIncompatible}, feishuConfig=${feishuConfigInvalid}) AND channels not working → running upgrade`);
|
|
11576
11682
|
if (opts.checkOnly) {
|
|
@@ -11578,13 +11684,13 @@ function runUpgradeLark(opts) {
|
|
|
11578
11684
|
log(`${"=".repeat(60)}`);
|
|
11579
11685
|
log("upgrade-lark check complete");
|
|
11580
11686
|
log(`${"=".repeat(60)}`);
|
|
11581
|
-
return {
|
|
11687
|
+
return finalReturn({
|
|
11582
11688
|
status: "skipped",
|
|
11583
11689
|
skipReason: "check",
|
|
11584
11690
|
upgradeNeeded: true,
|
|
11585
11691
|
timing,
|
|
11586
11692
|
logFile
|
|
11587
|
-
};
|
|
11693
|
+
});
|
|
11588
11694
|
}
|
|
11589
11695
|
log("");
|
|
11590
11696
|
log("── [1/6] 文件备份 ────────────────────────────────────────");
|
|
@@ -11594,12 +11700,13 @@ function runUpgradeLark(opts) {
|
|
|
11594
11700
|
timing.backupMs = Date.now() - t_backupStart;
|
|
11595
11701
|
if (!backup.ok) {
|
|
11596
11702
|
log(`ERROR: ${backup.error}`);
|
|
11597
|
-
return {
|
|
11703
|
+
return finalReturn({
|
|
11598
11704
|
status: "failed",
|
|
11599
11705
|
error: backup.error,
|
|
11600
11706
|
timing,
|
|
11601
|
-
logFile
|
|
11602
|
-
|
|
11707
|
+
logFile,
|
|
11708
|
+
fixStatus: computeFixStatus(opts.scene, "failed")
|
|
11709
|
+
});
|
|
11603
11710
|
}
|
|
11604
11711
|
log("backup: ok");
|
|
11605
11712
|
logVersionSnapshot("before-versions", snapshotVersions(cwd, log), log);
|
|
@@ -11640,14 +11747,14 @@ function runUpgradeLark(opts) {
|
|
|
11640
11747
|
if (statusCheckDelayMs > 0) {
|
|
11641
11748
|
log("");
|
|
11642
11749
|
log(`── 等待 ${statusCheckDelayMs / 1e3}s(让 openclaw 服务完成重启) ─────────────`);
|
|
11643
|
-
|
|
11750
|
+
sleepSync(statusCheckDelayMs);
|
|
11644
11751
|
log("wait done");
|
|
11645
11752
|
}
|
|
11646
11753
|
const doRollback = (reason) => {
|
|
11647
11754
|
log(`ERROR: ${reason}`);
|
|
11648
11755
|
const rollbackOk = restoreFiles(fsOpts);
|
|
11649
11756
|
log(`rollback: ${rollbackOk ? "ok" : "FAILED"}`);
|
|
11650
|
-
return {
|
|
11757
|
+
return finalReturn({
|
|
11651
11758
|
status: "failed",
|
|
11652
11759
|
error: reason,
|
|
11653
11760
|
validationError: reason,
|
|
@@ -11656,8 +11763,9 @@ function runUpgradeLark(opts) {
|
|
|
11656
11763
|
exitCode: npxExitCode,
|
|
11657
11764
|
rollbackOk,
|
|
11658
11765
|
timing,
|
|
11659
|
-
logFile
|
|
11660
|
-
|
|
11766
|
+
logFile,
|
|
11767
|
+
fixStatus: computeFixStatus(opts.scene, "failed")
|
|
11768
|
+
});
|
|
11661
11769
|
};
|
|
11662
11770
|
log("");
|
|
11663
11771
|
log("── [4/5] 安装后诊断校验 ─────────────────────────────────");
|
|
@@ -11709,8 +11817,9 @@ function runUpgradeLark(opts) {
|
|
|
11709
11817
|
if (fixResult.stderr?.trim()) log(`doctor(fix) stderr:\n${fixResult.stderr.trim()}`);
|
|
11710
11818
|
log(`doctor(fix) exit: ${fixResult.status ?? "null"}${fixResult.error ? ` error: ${fixResult.error.message}` : ""}`);
|
|
11711
11819
|
log("");
|
|
11712
|
-
log("── [7/
|
|
11820
|
+
log("── [7/8] 重启 openclaw 服务 ──────────────────────────────");
|
|
11713
11821
|
const restartScript = "/opt/force/bin/openclaw_scripts/restart.sh";
|
|
11822
|
+
let restartExecuted = false;
|
|
11714
11823
|
if (opts.skipRestart) log(" skipped: --skip-restart");
|
|
11715
11824
|
else if (node_fs.default.existsSync(restartScript)) {
|
|
11716
11825
|
const t_restart = Date.now();
|
|
@@ -11727,19 +11836,39 @@ function runUpgradeLark(opts) {
|
|
|
11727
11836
|
if (restartResult.stdout?.trim()) log(` restart stdout:\n${restartResult.stdout.trim()}`);
|
|
11728
11837
|
if (restartResult.stderr?.trim()) log(` restart stderr:\n${restartResult.stderr.trim()}`);
|
|
11729
11838
|
log(` restart.sh exit: ${restartResult.status ?? "null"} (${restartMs}ms)${restartResult.error ? ` error: ${restartResult.error.message}` : ""}`);
|
|
11839
|
+
restartExecuted = true;
|
|
11730
11840
|
} else log(` skipped: ${restartScript} not found`);
|
|
11731
11841
|
log("");
|
|
11842
|
+
log("── [8/8] 端口存活检测 ────────────────────────────────────");
|
|
11843
|
+
let portCheckOk;
|
|
11844
|
+
if (!restartExecuted) log(" skipped: restart was not executed");
|
|
11845
|
+
else {
|
|
11846
|
+
const t_portCheck = Date.now();
|
|
11847
|
+
const pcResult = pollPortCheck({
|
|
11848
|
+
port: 18789,
|
|
11849
|
+
initialWaitMs: opts.portCheckInitialWaitMs ?? 3e3,
|
|
11850
|
+
intervalMs: opts.portCheckIntervalMs ?? 1e3,
|
|
11851
|
+
maxAttempts: opts.portCheckMaxAttempts ?? 30,
|
|
11852
|
+
log
|
|
11853
|
+
});
|
|
11854
|
+
timing.portCheckMs = Date.now() - t_portCheck;
|
|
11855
|
+
portCheckOk = pcResult.ok;
|
|
11856
|
+
log(` port-check result: ${portCheckOk ? "ok" : "FAILED"} (${timing.portCheckMs}ms)`);
|
|
11857
|
+
}
|
|
11858
|
+
log("");
|
|
11732
11859
|
log(`${"=".repeat(60)}`);
|
|
11733
11860
|
log("upgrade-lark completed successfully");
|
|
11734
11861
|
log(`${"=".repeat(60)}`);
|
|
11735
|
-
return {
|
|
11862
|
+
return finalReturn({
|
|
11736
11863
|
status: "success",
|
|
11737
11864
|
stdout: npxStdout,
|
|
11738
11865
|
stderr: npxStderr,
|
|
11739
11866
|
exitCode: npxExitCode,
|
|
11867
|
+
portCheckOk,
|
|
11740
11868
|
timing,
|
|
11741
|
-
logFile
|
|
11742
|
-
|
|
11869
|
+
logFile,
|
|
11870
|
+
fixStatus: computeFixStatus(opts.scene, "success", portCheckOk)
|
|
11871
|
+
});
|
|
11743
11872
|
}
|
|
11744
11873
|
//#endregion
|
|
11745
11874
|
//#region src/index.ts
|
|
@@ -12255,6 +12384,7 @@ async function main() {
|
|
|
12255
12384
|
rollbackOk: result.rollbackOk,
|
|
12256
12385
|
validationError: result.validationError,
|
|
12257
12386
|
error: result.error,
|
|
12387
|
+
portCheckOk: result.portCheckOk,
|
|
12258
12388
|
timing: result.timing
|
|
12259
12389
|
});
|
|
12260
12390
|
try {
|
package/package.json
CHANGED