@lark-apaas/openclaw-scripts-diagnose-cli 0.1.14-alpha.1 → 0.1.14-alpha.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/index.cjs +234 -169
- 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.14-alpha.
|
|
55
|
+
return "0.1.14-alpha.2";
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/rule-engine/base.ts
|
|
@@ -3513,6 +3513,161 @@ function extractScopedNameFromSpec$1(spec) {
|
|
|
3513
3513
|
const at = spec.indexOf("@", 1);
|
|
3514
3514
|
return at === -1 ? spec : spec.slice(0, at);
|
|
3515
3515
|
}
|
|
3516
|
+
/**
|
|
3517
|
+
* Returns true if the installed feishu plugin is version-incompatible with
|
|
3518
|
+
* the current openclaw (or is a legacy plugin that must be replaced).
|
|
3519
|
+
* Used by the upgrade_lark_needed rule and the upgrade-lark pre-check gate.
|
|
3520
|
+
*/
|
|
3521
|
+
function needsLarkUpgrade(ctx) {
|
|
3522
|
+
const cc = resolveCompatContext(ctx);
|
|
3523
|
+
if (!cc) return false;
|
|
3524
|
+
const { ocCur, recommendedOc, installed, isLegacy } = cc;
|
|
3525
|
+
if (isForkPlugin(installed)) return false;
|
|
3526
|
+
if (recommendedOc) return resolveUpgradeDirection(installed, ocCur, recommendedOc, isLegacy) === "lark";
|
|
3527
|
+
return isLegacy || !isVersionCompatible(installed, ocCur);
|
|
3528
|
+
}
|
|
3529
|
+
//#endregion
|
|
3530
|
+
//#region src/channels-probe.ts
|
|
3531
|
+
const CHANNEL_LINE_RE = /^-\s+Feishu\s+([^:]+):\s+(.+)$/;
|
|
3532
|
+
/**
|
|
3533
|
+
* Port of Python `_account_is_working` from the feishu-channel-success-rate skill.
|
|
3534
|
+
*
|
|
3535
|
+
* Strips colon-prefixed key:value bits (dm:, bot:, in:, out:, token:, allow:,
|
|
3536
|
+
* intents:, groups:, health:) and evaluates the canonical health formula.
|
|
3537
|
+
*/
|
|
3538
|
+
function accountIsWorking(bits) {
|
|
3539
|
+
const bitTokens = /* @__PURE__ */ new Set();
|
|
3540
|
+
let hasError = false;
|
|
3541
|
+
let hasProbeFailed = false;
|
|
3542
|
+
for (const raw of bits) {
|
|
3543
|
+
const b = raw.trim();
|
|
3544
|
+
if (!b) continue;
|
|
3545
|
+
if (b.startsWith("error:")) {
|
|
3546
|
+
hasError = true;
|
|
3547
|
+
continue;
|
|
3548
|
+
}
|
|
3549
|
+
if (b === "probe failed") {
|
|
3550
|
+
hasProbeFailed = true;
|
|
3551
|
+
continue;
|
|
3552
|
+
}
|
|
3553
|
+
bitTokens.add(b.split(":")[0]);
|
|
3554
|
+
}
|
|
3555
|
+
if (!bitTokens.has("enabled") || !bitTokens.has("configured")) return false;
|
|
3556
|
+
if (bitTokens.has("works")) return true;
|
|
3557
|
+
if (bitTokens.has("running") && !hasError && !hasProbeFailed) return true;
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3560
|
+
/**
|
|
3561
|
+
* Parse the raw stdout of `openclaw channels status --probe`.
|
|
3562
|
+
* Port of Python `extract_channels_probe` from the feishu-channel-success-rate skill.
|
|
3563
|
+
*/
|
|
3564
|
+
function parseChannelsProbeOutput(text) {
|
|
3565
|
+
const gatewayReachable = text.includes("Gateway reachable");
|
|
3566
|
+
const accounts = [];
|
|
3567
|
+
let anyAccountWorking = false;
|
|
3568
|
+
for (const line of text.split("\n")) {
|
|
3569
|
+
const m = CHANNEL_LINE_RE.exec(line.trim());
|
|
3570
|
+
if (!m) continue;
|
|
3571
|
+
const [, acct, rest] = m;
|
|
3572
|
+
const bits = rest.split(",").map((b) => b.trim());
|
|
3573
|
+
const isWorking = accountIsWorking(bits);
|
|
3574
|
+
if (isWorking) anyAccountWorking = true;
|
|
3575
|
+
accounts.push({
|
|
3576
|
+
id: acct.trim(),
|
|
3577
|
+
bits,
|
|
3578
|
+
isWorking,
|
|
3579
|
+
raw: line.trim()
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
return {
|
|
3583
|
+
gatewayReachable,
|
|
3584
|
+
accounts,
|
|
3585
|
+
anyAccountWorking
|
|
3586
|
+
};
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Run `openclaw channels status --probe` and return a structured result.
|
|
3590
|
+
*
|
|
3591
|
+
* The command may exit non-zero when some bot accounts fail their probe — that
|
|
3592
|
+
* is still useful output. We therefore try to parse stdout even when the
|
|
3593
|
+
* process exits with a non-zero code, falling back to an unavailable result
|
|
3594
|
+
* only when there is genuinely no output to parse.
|
|
3595
|
+
*
|
|
3596
|
+
* @param timeoutMs Maximum wait time. Default is 60 s because v2026.4.x
|
|
3597
|
+
* lacks a per-request HTTP timeout and can block indefinitely.
|
|
3598
|
+
*/
|
|
3599
|
+
function runChannelsProbe(timeoutMs = 6e4) {
|
|
3600
|
+
let stdout = "";
|
|
3601
|
+
let execError;
|
|
3602
|
+
try {
|
|
3603
|
+
stdout = (0, node_child_process.execSync)("openclaw channels status --probe", {
|
|
3604
|
+
encoding: "utf-8",
|
|
3605
|
+
timeout: timeoutMs,
|
|
3606
|
+
stdio: [
|
|
3607
|
+
"ignore",
|
|
3608
|
+
"pipe",
|
|
3609
|
+
"pipe"
|
|
3610
|
+
]
|
|
3611
|
+
});
|
|
3612
|
+
} catch (e) {
|
|
3613
|
+
const err = e;
|
|
3614
|
+
stdout = err.stdout ?? "";
|
|
3615
|
+
execError = err.message;
|
|
3616
|
+
const stderrRaw = err.stderr;
|
|
3617
|
+
const stderr = (typeof stderrRaw === "string" ? stderrRaw : stderrRaw?.toString("utf-8") ?? "").trim();
|
|
3618
|
+
if (stderr) console.error(`channels-probe: stderr from CLI: ${stderr}`);
|
|
3619
|
+
}
|
|
3620
|
+
if (stdout.trim()) return {
|
|
3621
|
+
available: true,
|
|
3622
|
+
...parseChannelsProbeOutput(stdout)
|
|
3623
|
+
};
|
|
3624
|
+
return {
|
|
3625
|
+
available: false,
|
|
3626
|
+
gatewayReachable: false,
|
|
3627
|
+
accounts: [],
|
|
3628
|
+
anyAccountWorking: false,
|
|
3629
|
+
error: execError ?? "no output from openclaw channels status --probe"
|
|
3630
|
+
};
|
|
3631
|
+
}
|
|
3632
|
+
//#endregion
|
|
3633
|
+
//#region src/rules/upgrade-lark-needed.ts
|
|
3634
|
+
/**
|
|
3635
|
+
* Detects the condition that warrants running `upgrade-lark`:
|
|
3636
|
+
* - feishu plugin version incompatible with current openclaw, AND
|
|
3637
|
+
* - channels are not working.
|
|
3638
|
+
*
|
|
3639
|
+
* Both conditions must be true simultaneously. If version is compatible or
|
|
3640
|
+
* channels are working, the rule passes (no action needed).
|
|
3641
|
+
*
|
|
3642
|
+
* profile: experimental — runs only in full sweep mode, not in standard doctor.
|
|
3643
|
+
* level: silent — telemetry/sweep-only, does not trigger page-level repair UI.
|
|
3644
|
+
*/
|
|
3645
|
+
let UpgradeLarkNeededRule = class UpgradeLarkNeededRule extends DiagnoseRule {
|
|
3646
|
+
validate(ctx) {
|
|
3647
|
+
if (!needsLarkUpgrade(ctx)) return { pass: true };
|
|
3648
|
+
let anyAccountWorking = false;
|
|
3649
|
+
try {
|
|
3650
|
+
anyAccountWorking = runChannelsProbe(3e4).anyAccountWorking;
|
|
3651
|
+
} catch {
|
|
3652
|
+
return { pass: true };
|
|
3653
|
+
}
|
|
3654
|
+
if (anyAccountWorking) return { pass: true };
|
|
3655
|
+
return {
|
|
3656
|
+
pass: false,
|
|
3657
|
+
action: "upgrade_lark",
|
|
3658
|
+
message: "飞书插件版本不兼容且 channels 不可用,建议执行 upgrade-lark 命令升级飞书插件"
|
|
3659
|
+
};
|
|
3660
|
+
}
|
|
3661
|
+
};
|
|
3662
|
+
UpgradeLarkNeededRule = __decorate([Rule({
|
|
3663
|
+
key: "upgrade_lark_needed",
|
|
3664
|
+
description: "检测飞书插件版本不兼容且 channels 不可用,判断是否需要执行 upgrade-lark 升级",
|
|
3665
|
+
dependsOn: ["feishu_plugin_version_compat_lark"],
|
|
3666
|
+
repairMode: "check-only",
|
|
3667
|
+
level: "silent",
|
|
3668
|
+
profile: "experimental",
|
|
3669
|
+
usesVars: ["recommendedOpenclawTag"]
|
|
3670
|
+
})], UpgradeLarkNeededRule);
|
|
3516
3671
|
//#endregion
|
|
3517
3672
|
//#region src/rules/cleanup-install-backup-dirs.ts
|
|
3518
3673
|
const DIR_PREFIX = ".openclaw-install-";
|
|
@@ -6236,23 +6391,6 @@ function reportError(params) {
|
|
|
6236
6391
|
} catch {}
|
|
6237
6392
|
}
|
|
6238
6393
|
//#endregion
|
|
6239
|
-
//#region ../../openclaw-slardar/lib/report-log.js
|
|
6240
|
-
function reportLog(params) {
|
|
6241
|
-
try {
|
|
6242
|
-
const extra = mergeLogExtra(buildTelemetryFields(params), {
|
|
6243
|
-
event: params.event,
|
|
6244
|
-
phase: params.phase,
|
|
6245
|
-
status: params.status,
|
|
6246
|
-
...params.extra
|
|
6247
|
-
});
|
|
6248
|
-
Slardar.sendLog?.({
|
|
6249
|
-
content: params.message,
|
|
6250
|
-
level: params.level ?? "info",
|
|
6251
|
-
extra
|
|
6252
|
-
});
|
|
6253
|
-
} catch {}
|
|
6254
|
-
}
|
|
6255
|
-
//#endregion
|
|
6256
6394
|
//#region src/install-cli.ts
|
|
6257
6395
|
const LARK_CLI_NAME = "lark-cli";
|
|
6258
6396
|
const AGENT_SKILLS_NAME = "agent-skills";
|
|
@@ -10149,109 +10287,6 @@ function finalize(results, aborted) {
|
|
|
10149
10287
|
};
|
|
10150
10288
|
}
|
|
10151
10289
|
//#endregion
|
|
10152
|
-
//#region src/channels-probe.ts
|
|
10153
|
-
const CHANNEL_LINE_RE = /^-\s+Feishu\s+([^:]+):\s+(.+)$/;
|
|
10154
|
-
/**
|
|
10155
|
-
* Port of Python `_account_is_working` from the feishu-channel-success-rate skill.
|
|
10156
|
-
*
|
|
10157
|
-
* Strips colon-prefixed key:value bits (dm:, bot:, in:, out:, token:, allow:,
|
|
10158
|
-
* intents:, groups:, health:) and evaluates the canonical health formula.
|
|
10159
|
-
*/
|
|
10160
|
-
function accountIsWorking(bits) {
|
|
10161
|
-
const bitTokens = /* @__PURE__ */ new Set();
|
|
10162
|
-
let hasError = false;
|
|
10163
|
-
let hasProbeFailed = false;
|
|
10164
|
-
for (const raw of bits) {
|
|
10165
|
-
const b = raw.trim();
|
|
10166
|
-
if (!b) continue;
|
|
10167
|
-
if (b.startsWith("error:")) {
|
|
10168
|
-
hasError = true;
|
|
10169
|
-
continue;
|
|
10170
|
-
}
|
|
10171
|
-
if (b === "probe failed") {
|
|
10172
|
-
hasProbeFailed = true;
|
|
10173
|
-
continue;
|
|
10174
|
-
}
|
|
10175
|
-
bitTokens.add(b.split(":")[0]);
|
|
10176
|
-
}
|
|
10177
|
-
if (!bitTokens.has("enabled") || !bitTokens.has("configured")) return false;
|
|
10178
|
-
if (bitTokens.has("works")) return true;
|
|
10179
|
-
if (bitTokens.has("running") && !hasError && !hasProbeFailed) return true;
|
|
10180
|
-
return false;
|
|
10181
|
-
}
|
|
10182
|
-
/**
|
|
10183
|
-
* Parse the raw stdout of `openclaw channels status --probe`.
|
|
10184
|
-
* Port of Python `extract_channels_probe` from the feishu-channel-success-rate skill.
|
|
10185
|
-
*/
|
|
10186
|
-
function parseChannelsProbeOutput(text) {
|
|
10187
|
-
const gatewayReachable = text.includes("Gateway reachable");
|
|
10188
|
-
const accounts = [];
|
|
10189
|
-
let anyAccountWorking = false;
|
|
10190
|
-
for (const line of text.split("\n")) {
|
|
10191
|
-
const m = CHANNEL_LINE_RE.exec(line.trim());
|
|
10192
|
-
if (!m) continue;
|
|
10193
|
-
const [, acct, rest] = m;
|
|
10194
|
-
const bits = rest.split(",").map((b) => b.trim());
|
|
10195
|
-
const isWorking = accountIsWorking(bits);
|
|
10196
|
-
if (isWorking) anyAccountWorking = true;
|
|
10197
|
-
accounts.push({
|
|
10198
|
-
id: acct.trim(),
|
|
10199
|
-
bits,
|
|
10200
|
-
isWorking,
|
|
10201
|
-
raw: line.trim()
|
|
10202
|
-
});
|
|
10203
|
-
}
|
|
10204
|
-
return {
|
|
10205
|
-
gatewayReachable,
|
|
10206
|
-
accounts,
|
|
10207
|
-
anyAccountWorking
|
|
10208
|
-
};
|
|
10209
|
-
}
|
|
10210
|
-
/**
|
|
10211
|
-
* Run `openclaw channels status --probe` and return a structured result.
|
|
10212
|
-
*
|
|
10213
|
-
* The command may exit non-zero when some bot accounts fail their probe — that
|
|
10214
|
-
* is still useful output. We therefore try to parse stdout even when the
|
|
10215
|
-
* process exits with a non-zero code, falling back to an unavailable result
|
|
10216
|
-
* only when there is genuinely no output to parse.
|
|
10217
|
-
*
|
|
10218
|
-
* @param timeoutMs Maximum wait time. Default is 60 s because v2026.4.x
|
|
10219
|
-
* lacks a per-request HTTP timeout and can block indefinitely.
|
|
10220
|
-
*/
|
|
10221
|
-
function runChannelsProbe(timeoutMs = 6e4) {
|
|
10222
|
-
let stdout = "";
|
|
10223
|
-
let execError;
|
|
10224
|
-
try {
|
|
10225
|
-
stdout = (0, node_child_process.execSync)("openclaw channels status --probe", {
|
|
10226
|
-
encoding: "utf-8",
|
|
10227
|
-
timeout: timeoutMs,
|
|
10228
|
-
stdio: [
|
|
10229
|
-
"ignore",
|
|
10230
|
-
"pipe",
|
|
10231
|
-
"pipe"
|
|
10232
|
-
]
|
|
10233
|
-
});
|
|
10234
|
-
} catch (e) {
|
|
10235
|
-
const err = e;
|
|
10236
|
-
stdout = err.stdout ?? "";
|
|
10237
|
-
execError = err.message;
|
|
10238
|
-
const stderrRaw = err.stderr;
|
|
10239
|
-
const stderr = (typeof stderrRaw === "string" ? stderrRaw : stderrRaw?.toString("utf-8") ?? "").trim();
|
|
10240
|
-
if (stderr) console.error(`channels-probe: stderr from CLI: ${stderr}`);
|
|
10241
|
-
}
|
|
10242
|
-
if (stdout.trim()) return {
|
|
10243
|
-
available: true,
|
|
10244
|
-
...parseChannelsProbeOutput(stdout)
|
|
10245
|
-
};
|
|
10246
|
-
return {
|
|
10247
|
-
available: false,
|
|
10248
|
-
gatewayReachable: false,
|
|
10249
|
-
accounts: [],
|
|
10250
|
-
anyAccountWorking: false,
|
|
10251
|
-
error: execError ?? "no output from openclaw channels status --probe"
|
|
10252
|
-
};
|
|
10253
|
-
}
|
|
10254
|
-
//#endregion
|
|
10255
10290
|
//#region src/innerapi/reportCliRun.ts
|
|
10256
10291
|
/**
|
|
10257
10292
|
* CLI-side client for studio_server's `openclaw.report_cli_run` inner
|
|
@@ -10331,7 +10366,7 @@ async function reportCliRun(opts) {
|
|
|
10331
10366
|
//#region src/help.ts
|
|
10332
10367
|
const BIN = "mclaw-diagnose";
|
|
10333
10368
|
function versionBanner() {
|
|
10334
|
-
return `v0.1.14-alpha.
|
|
10369
|
+
return `v0.1.14-alpha.2`;
|
|
10335
10370
|
}
|
|
10336
10371
|
const COMMANDS = [
|
|
10337
10372
|
{
|
|
@@ -10912,18 +10947,16 @@ function reportDoctorRunToSlardar(opts) {
|
|
|
10912
10947
|
}
|
|
10913
10948
|
});
|
|
10914
10949
|
}
|
|
10915
|
-
|
|
10916
|
-
function readFileTail(filePath, maxBytes = 4e3) {
|
|
10950
|
+
function readLogFile(filePath) {
|
|
10917
10951
|
try {
|
|
10918
|
-
|
|
10919
|
-
if (content.length <= maxBytes) return content;
|
|
10920
|
-
return `...(truncated — showing last ${maxBytes} chars)...\n` + content.slice(-maxBytes);
|
|
10952
|
+
return node_fs.default.readFileSync(filePath, "utf-8");
|
|
10921
10953
|
} catch {
|
|
10922
10954
|
return "";
|
|
10923
10955
|
}
|
|
10924
10956
|
}
|
|
10925
10957
|
function reportUpgradeLarkToSlardar(opts) {
|
|
10926
|
-
console.error(`[slardar]
|
|
10958
|
+
console.error(`[slardar] upgrade_lark_run scene=${opts.scene ?? ""} success=${opts.success} exitCode=${opts.exitCode ?? ""} rollbackOk=${opts.rollbackOk ?? ""}`);
|
|
10959
|
+
const logContent = readLogFile(opts.logFile);
|
|
10927
10960
|
reportTask({
|
|
10928
10961
|
eventName: "upgrade_lark_run",
|
|
10929
10962
|
durationMs: opts.durationMs,
|
|
@@ -10932,22 +10965,9 @@ function reportUpgradeLarkToSlardar(opts) {
|
|
|
10932
10965
|
scene: opts.scene ?? "",
|
|
10933
10966
|
exit_code: String(opts.exitCode ?? ""),
|
|
10934
10967
|
rollback_ok: opts.rollbackOk != null ? String(opts.rollbackOk) : "",
|
|
10935
|
-
validation_error:
|
|
10936
|
-
error_msg:
|
|
10937
|
-
|
|
10938
|
-
});
|
|
10939
|
-
const logContent = readFileTail(opts.logFile);
|
|
10940
|
-
console.error(`[slardar] upgrade_lark_detail logFile=${opts.logFile} contentLength=${logContent.length} sendLogAvailable=${typeof Slardar.sendLog}`);
|
|
10941
|
-
reportLog({
|
|
10942
|
-
event: "upgrade_lark_detail",
|
|
10943
|
-
message: logContent || "(no log content)",
|
|
10944
|
-
level: opts.success ? "info" : "error",
|
|
10945
|
-
extra: {
|
|
10946
|
-
log_file: opts.logFile,
|
|
10947
|
-
scene: opts.scene ?? "",
|
|
10948
|
-
success: String(opts.success),
|
|
10949
|
-
exit_code: String(opts.exitCode ?? ""),
|
|
10950
|
-
rollback_ok: opts.rollbackOk != null ? String(opts.rollbackOk) : ""
|
|
10968
|
+
validation_error: opts.validationError ?? "",
|
|
10969
|
+
error_msg: opts.error ?? "",
|
|
10970
|
+
log_content: logContent
|
|
10951
10971
|
}
|
|
10952
10972
|
});
|
|
10953
10973
|
}
|
|
@@ -11117,10 +11137,61 @@ function runUpgradeLark(opts) {
|
|
|
11117
11137
|
log(` configPath : ${configPath}`);
|
|
11118
11138
|
log(`${"=".repeat(60)}`);
|
|
11119
11139
|
log("");
|
|
11120
|
-
log("── [
|
|
11121
|
-
|
|
11140
|
+
log("── [Pre-check A] channels probe(升级前)────────────────");
|
|
11141
|
+
const beforeChannels = probeChannels("before", log, 3e4);
|
|
11122
11142
|
log("");
|
|
11123
|
-
log("── [
|
|
11143
|
+
log("── [Pre-check B] 版本兼容预检 ───────────────────────────");
|
|
11144
|
+
let versionNeedsUpgrade = false;
|
|
11145
|
+
try {
|
|
11146
|
+
const rawConfig = node_fs.default.readFileSync(configPath, "utf-8");
|
|
11147
|
+
versionNeedsUpgrade = needsLarkUpgrade({
|
|
11148
|
+
config: loadJSON5().parse(rawConfig),
|
|
11149
|
+
configPath,
|
|
11150
|
+
vars: {},
|
|
11151
|
+
providerDeps: {
|
|
11152
|
+
usesMiaodaProvider: false,
|
|
11153
|
+
usesMiaodaSecretProvider: false
|
|
11154
|
+
}
|
|
11155
|
+
});
|
|
11156
|
+
log(` version-compat pre-check: ${versionNeedsUpgrade ? "NEEDS_UPGRADE" : "ok"}`);
|
|
11157
|
+
} catch (e) {
|
|
11158
|
+
log(` version-compat pre-check error: ${e.message} — treating as needs-upgrade`);
|
|
11159
|
+
versionNeedsUpgrade = true;
|
|
11160
|
+
}
|
|
11161
|
+
log("");
|
|
11162
|
+
log("── [Gate] 升级前置条件检查 ───────────────────────────────");
|
|
11163
|
+
log(` version needs upgrade : ${versionNeedsUpgrade}`);
|
|
11164
|
+
log(` channels working before: ${beforeChannels.anyAccountWorking}`);
|
|
11165
|
+
if (!versionNeedsUpgrade) {
|
|
11166
|
+
const reason = "version already compatible — upgrade not needed";
|
|
11167
|
+
log(` SKIP: ${reason}`);
|
|
11168
|
+
log(`${"=".repeat(60)}`);
|
|
11169
|
+
log("upgrade-lark skipped (pre-check gate)");
|
|
11170
|
+
log(`${"=".repeat(60)}`);
|
|
11171
|
+
return {
|
|
11172
|
+
ok: true,
|
|
11173
|
+
skipped: true,
|
|
11174
|
+
skipReason: reason,
|
|
11175
|
+
logFile
|
|
11176
|
+
};
|
|
11177
|
+
}
|
|
11178
|
+
if (beforeChannels.anyAccountWorking) {
|
|
11179
|
+
const reason = "channels are working — upgrade not needed (version mismatch but system is functional)";
|
|
11180
|
+
log(` SKIP: ${reason}`);
|
|
11181
|
+
log(`${"=".repeat(60)}`);
|
|
11182
|
+
log("upgrade-lark skipped (pre-check gate)");
|
|
11183
|
+
log(`${"=".repeat(60)}`);
|
|
11184
|
+
return {
|
|
11185
|
+
ok: true,
|
|
11186
|
+
skipped: true,
|
|
11187
|
+
skipReason: reason,
|
|
11188
|
+
logFile
|
|
11189
|
+
};
|
|
11190
|
+
}
|
|
11191
|
+
log(" PROCEED: version incompatible AND channels not working → running upgrade");
|
|
11192
|
+
log("");
|
|
11193
|
+
log("── [1/6] 文件备份 ────────────────────────────────────────");
|
|
11194
|
+
log(`before-state: botCount=${countFeishuBots(configPath)}`);
|
|
11124
11195
|
const backup = backupFiles(fsOpts);
|
|
11125
11196
|
if (!backup.ok) {
|
|
11126
11197
|
log(`ERROR: ${backup.error}`);
|
|
@@ -11133,10 +11204,7 @@ function runUpgradeLark(opts) {
|
|
|
11133
11204
|
log("backup: ok");
|
|
11134
11205
|
logVersionSnapshot("before-versions", snapshotVersions(cwd, log), log);
|
|
11135
11206
|
log("");
|
|
11136
|
-
log("── [
|
|
11137
|
-
const beforeChannels = probeChannels("before", log, 3e4);
|
|
11138
|
-
log("");
|
|
11139
|
-
log("── [4/8] 清理本地 openclaw shim ─────────────────────────");
|
|
11207
|
+
log("── [2/6] 清理本地 openclaw shim ─────────────────────────");
|
|
11140
11208
|
const localOpenclawBin = node_path.default.join(cwd, "node_modules", ".bin", "openclaw");
|
|
11141
11209
|
if (node_fs.default.existsSync(localOpenclawBin)) try {
|
|
11142
11210
|
node_fs.default.rmSync(localOpenclawBin);
|
|
@@ -11146,7 +11214,7 @@ function runUpgradeLark(opts) {
|
|
|
11146
11214
|
}
|
|
11147
11215
|
else log(` skipped: ${localOpenclawBin} (not found)`);
|
|
11148
11216
|
log("");
|
|
11149
|
-
log("── [
|
|
11217
|
+
log("── [3/6] npx install (@larksuite/openclaw-lark-tools update) ──");
|
|
11150
11218
|
const npxResult = (0, node_child_process.spawnSync)("npx", [
|
|
11151
11219
|
"-y",
|
|
11152
11220
|
"@larksuite/openclaw-lark-tools",
|
|
@@ -11189,7 +11257,7 @@ function runUpgradeLark(opts) {
|
|
|
11189
11257
|
};
|
|
11190
11258
|
};
|
|
11191
11259
|
log("");
|
|
11192
|
-
log("── [6
|
|
11260
|
+
log("── [4/6] 插件安装检查 + 版本兼容校验 ───────────────────");
|
|
11193
11261
|
const larkExtDir = node_path.default.join(cwd, "extensions", "openclaw-lark");
|
|
11194
11262
|
const larkVersion = readPkgVersion(node_path.default.join(larkExtDir, "package.json"));
|
|
11195
11263
|
log(` extensions/openclaw-lark: ${node_fs.default.existsSync(larkExtDir) ? "exists" : "missing"}, version=${larkVersion ?? "n/a"}`);
|
|
@@ -11217,25 +11285,22 @@ function runUpgradeLark(opts) {
|
|
|
11217
11285
|
log(" version compat: ok");
|
|
11218
11286
|
logVersionSnapshot("after-versions", snapshotVersions(cwd, log), log);
|
|
11219
11287
|
log("");
|
|
11220
|
-
log("── [
|
|
11288
|
+
log("── [5/6] channels probe(升级后)────────────────────────");
|
|
11221
11289
|
if (!probeChannels("after", log, 3e4).anyAccountWorking) {
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
};
|
|
11233
|
-
}
|
|
11234
|
-
return doRollback("channels probe: no working account after install (was working before)");
|
|
11290
|
+
log(" channels: not working before or after install — pre-existing issue, skipping rollback");
|
|
11291
|
+
return {
|
|
11292
|
+
ok: false,
|
|
11293
|
+
error: "channels probe: no working account (pre-existing issue, not caused by install)",
|
|
11294
|
+
validationError: "channels probe: no working account (pre-existing)",
|
|
11295
|
+
stdout: npxStdout,
|
|
11296
|
+
stderr: npxStderr,
|
|
11297
|
+
exitCode: npxExitCode,
|
|
11298
|
+
logFile
|
|
11299
|
+
};
|
|
11235
11300
|
}
|
|
11236
|
-
log(" channels: ok");
|
|
11301
|
+
log(" channels: ok (recovered after install)");
|
|
11237
11302
|
log("");
|
|
11238
|
-
log("── [
|
|
11303
|
+
log("── [6/6] doctor --fix ────────────────────────────────────");
|
|
11239
11304
|
const fixArgs = ["doctor", "--fix"];
|
|
11240
11305
|
if (opts.scene) fixArgs.push(`--scene=${opts.scene}`);
|
|
11241
11306
|
const fixResult = (0, node_child_process.spawnSync)(process.execPath, [cliScript, ...fixArgs], {
|
package/package.json
CHANGED