@lark-apaas/openclaw-scripts-diagnose-cli 0.1.15-alpha.15 → 0.1.15-alpha.17
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 +144 -48
- 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.17";
|
|
56
56
|
}
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/rule-engine/base.ts
|
|
@@ -4180,9 +4180,10 @@ let FeishuBotChannelConfigRule = class FeishuBotChannelConfigRule extends Diagno
|
|
|
4180
4180
|
};
|
|
4181
4181
|
}
|
|
4182
4182
|
/** Check a single bot entry (either an account object or the feishu channel itself).
|
|
4183
|
-
* appSecret is validated based on its current type:
|
|
4184
4183
|
* - object → must match canonical provider-ref
|
|
4185
4184
|
* - string → must match larkApps plaintext
|
|
4185
|
+
* - undefined/null → missing
|
|
4186
|
+
* - other → unexpected type
|
|
4186
4187
|
*/
|
|
4187
4188
|
checkBot(label, bot, larkApp, issues) {
|
|
4188
4189
|
const creatorOpenID = larkApp.creatorOpenID;
|
|
@@ -4195,7 +4196,8 @@ let FeishuBotChannelConfigRule = class FeishuBotChannelConfigRule extends Diagno
|
|
|
4195
4196
|
if (!matchMap(secret, DEFAULT_FEISHU_APP_SECRET)) issues.push(`${label} appSecret is a provider-ref but not the canonical one`);
|
|
4196
4197
|
} else if (typeof secret === "string") {
|
|
4197
4198
|
if (secret !== larkApp.appSecret) issues.push(`${label} appSecret plaintext mismatch`);
|
|
4198
|
-
} else issues.push(`${label} appSecret
|
|
4199
|
+
} else if (secret === void 0 || secret === null) issues.push(`${label} appSecret is missing`);
|
|
4200
|
+
else issues.push(`${label} appSecret has unexpected type ${typeof secret}`);
|
|
4199
4201
|
}
|
|
4200
4202
|
repair(ctx) {
|
|
4201
4203
|
const larkApps = ctx.vars.larkApps;
|
|
@@ -4219,9 +4221,8 @@ let FeishuBotChannelConfigRule = class FeishuBotChannelConfigRule extends Diagno
|
|
|
4219
4221
|
}
|
|
4220
4222
|
}
|
|
4221
4223
|
/** Fix a single bot entry in-place.
|
|
4222
|
-
*
|
|
4223
|
-
* -
|
|
4224
|
-
* - string → fix to larkApps plaintext
|
|
4224
|
+
* - object (provider-ref) → fix to canonical
|
|
4225
|
+
* - otherwise → fix to larkApps plaintext
|
|
4225
4226
|
*/
|
|
4226
4227
|
fixBot(bot, larkApp) {
|
|
4227
4228
|
const creatorOpenID = larkApp.creatorOpenID;
|
|
@@ -4235,9 +4236,7 @@ let FeishuBotChannelConfigRule = class FeishuBotChannelConfigRule extends Diagno
|
|
|
4235
4236
|
const secret = bot.appSecret;
|
|
4236
4237
|
if (typeof secret === "object" && secret !== null && !Array.isArray(secret)) {
|
|
4237
4238
|
if (!matchMap(secret, DEFAULT_FEISHU_APP_SECRET)) bot.appSecret = { ...DEFAULT_FEISHU_APP_SECRET };
|
|
4238
|
-
} else if (
|
|
4239
|
-
if (secret !== larkApp.appSecret) bot.appSecret = larkApp.appSecret;
|
|
4240
|
-
}
|
|
4239
|
+
} else if (secret !== larkApp.appSecret) bot.appSecret = larkApp.appSecret;
|
|
4241
4240
|
}
|
|
4242
4241
|
};
|
|
4243
4242
|
FeishuBotChannelConfigRule = __decorate([Rule({
|
|
@@ -7123,45 +7122,56 @@ function fixBotChannelConfig(configPath, larkApps, log) {
|
|
|
7123
7122
|
return;
|
|
7124
7123
|
}
|
|
7125
7124
|
const config = loadJSON5().parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
7126
|
-
const
|
|
7127
|
-
if (!
|
|
7128
|
-
log("no feishu
|
|
7125
|
+
const feishu = asRecord(getNestedMap(config, "channels", "feishu"));
|
|
7126
|
+
if (!feishu) {
|
|
7127
|
+
log("no feishu channel in config, skip bot channel config fix");
|
|
7129
7128
|
return;
|
|
7130
7129
|
}
|
|
7131
7130
|
let fixCount = 0;
|
|
7132
|
-
|
|
7131
|
+
const accounts = asRecord(feishu.accounts);
|
|
7132
|
+
if (accounts) for (const [, account] of Object.entries(accounts)) {
|
|
7133
7133
|
const bot = asRecord(account);
|
|
7134
7134
|
if (!bot) continue;
|
|
7135
7135
|
const appId = bot.appId;
|
|
7136
7136
|
if (typeof appId !== "string" || !appId.startsWith("cli_")) continue;
|
|
7137
7137
|
const larkApp = larkApps.find((e) => e.larkAppID === appId);
|
|
7138
7138
|
if (!larkApp) continue;
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
fixCount++;
|
|
7146
|
-
}
|
|
7147
|
-
}
|
|
7148
|
-
const secret = bot.appSecret;
|
|
7149
|
-
let needsFix = false;
|
|
7150
|
-
if (typeof secret === "object" && secret !== null && !Array.isArray(secret)) {
|
|
7151
|
-
if (!matchMap(secret, DEFAULT_FEISHU_APP_SECRET)) needsFix = true;
|
|
7152
|
-
} else if (typeof secret === "string") {
|
|
7153
|
-
if (secret !== larkApp.appSecret) needsFix = true;
|
|
7154
|
-
} else needsFix = true;
|
|
7155
|
-
if (needsFix) {
|
|
7156
|
-
bot.appSecret = { ...DEFAULT_FEISHU_APP_SECRET };
|
|
7157
|
-
fixCount++;
|
|
7158
|
-
}
|
|
7139
|
+
fixCount += fixBot(bot, larkApp);
|
|
7140
|
+
}
|
|
7141
|
+
const singleAppId = feishu.appId;
|
|
7142
|
+
if (typeof singleAppId === "string" && singleAppId.startsWith("cli_") && !accounts) {
|
|
7143
|
+
const larkApp = larkApps.find((e) => e.larkAppID === singleAppId);
|
|
7144
|
+
if (larkApp) fixCount += fixBot(feishu, larkApp);
|
|
7159
7145
|
}
|
|
7160
7146
|
if (fixCount > 0) {
|
|
7161
7147
|
node_fs.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
7162
7148
|
log(`fixed ${fixCount} bot channel config issue(s) (allowFrom/appSecret)`);
|
|
7163
7149
|
} else log("bot channel config ok, no fixes needed");
|
|
7164
7150
|
}
|
|
7151
|
+
/** Fix a single bot entry in-place. Returns number of fixes applied. */
|
|
7152
|
+
function fixBot(bot, larkApp) {
|
|
7153
|
+
let fixCount = 0;
|
|
7154
|
+
const creatorOpenID = larkApp.creatorOpenID;
|
|
7155
|
+
if (typeof creatorOpenID === "string" && creatorOpenID !== "") {
|
|
7156
|
+
const allowFrom = Array.isArray(bot.allowFrom) ? [...bot.allowFrom] : [];
|
|
7157
|
+
if (!allowFrom.includes(creatorOpenID)) {
|
|
7158
|
+
allowFrom.push(creatorOpenID);
|
|
7159
|
+
bot.allowFrom = allowFrom;
|
|
7160
|
+
fixCount++;
|
|
7161
|
+
}
|
|
7162
|
+
}
|
|
7163
|
+
const secret = bot.appSecret;
|
|
7164
|
+
if (typeof secret === "object" && secret !== null && !Array.isArray(secret)) {
|
|
7165
|
+
if (!matchMap(secret, DEFAULT_FEISHU_APP_SECRET)) {
|
|
7166
|
+
bot.appSecret = { ...DEFAULT_FEISHU_APP_SECRET };
|
|
7167
|
+
fixCount++;
|
|
7168
|
+
}
|
|
7169
|
+
} else if (secret !== larkApp.appSecret) {
|
|
7170
|
+
bot.appSecret = larkApp.appSecret;
|
|
7171
|
+
fixCount++;
|
|
7172
|
+
}
|
|
7173
|
+
return fixCount;
|
|
7174
|
+
}
|
|
7165
7175
|
/**
|
|
7166
7176
|
* Step 7: Verify startup scripts landed in configDir/scripts/.
|
|
7167
7177
|
*
|
|
@@ -10704,7 +10714,7 @@ async function reportCliRun(opts) {
|
|
|
10704
10714
|
//#region src/help.ts
|
|
10705
10715
|
const BIN = "mclaw-diagnose";
|
|
10706
10716
|
function versionBanner() {
|
|
10707
|
-
return `v0.1.15-alpha.
|
|
10717
|
+
return `v0.1.15-alpha.17`;
|
|
10708
10718
|
}
|
|
10709
10719
|
const COMMANDS = [
|
|
10710
10720
|
{
|
|
@@ -11893,15 +11903,15 @@ function isPidAlive(pid) {
|
|
|
11893
11903
|
}
|
|
11894
11904
|
}
|
|
11895
11905
|
/**
|
|
11896
|
-
*
|
|
11906
|
+
* 尝试获取安装操作互斥锁。
|
|
11897
11907
|
*
|
|
11898
11908
|
* 利用 open(O_CREAT | O_EXCL) 的 POSIX 原子性确保同一时刻只有一个安装指令运行。
|
|
11899
11909
|
* 覆盖的安装指令:upgrade-lark / install-openclaw / install-extension / install-cli / reset --worker。
|
|
11900
11910
|
*
|
|
11901
|
-
*
|
|
11902
|
-
*
|
|
11911
|
+
* 返回 null 表示成功获取锁;返回错误信息字符串表示锁被其他进程持有。
|
|
11912
|
+
* 与抛异常相比,返回值让调用方可以输出符合各自格式的 result,而不依赖 catch handler 统一处理。
|
|
11903
11913
|
*
|
|
11904
|
-
* 成功获取后自动注册 process.
|
|
11914
|
+
* 成功获取后自动注册 process.once('exit') 释放锁,无需调用方手动清理。
|
|
11905
11915
|
*/
|
|
11906
11916
|
function acquireInstallLock(command) {
|
|
11907
11917
|
node_fs.default.mkdirSync(DIAGNOSE_DIR, { recursive: true });
|
|
@@ -11917,7 +11927,7 @@ function acquireInstallLock(command) {
|
|
|
11917
11927
|
node_fs.default.closeSync(fd);
|
|
11918
11928
|
process.once("exit", releaseInstallLock);
|
|
11919
11929
|
console.error(`[install-lock] acquired command=${command} pid=${process.pid}`);
|
|
11920
|
-
return;
|
|
11930
|
+
return null;
|
|
11921
11931
|
} catch (e) {
|
|
11922
11932
|
if (e.code !== "EEXIST") throw e;
|
|
11923
11933
|
let existing = null;
|
|
@@ -11936,13 +11946,13 @@ function acquireInstallLock(command) {
|
|
|
11936
11946
|
} catch {}
|
|
11937
11947
|
continue;
|
|
11938
11948
|
}
|
|
11939
|
-
|
|
11949
|
+
return `另一个安装指令正在运行,请等待其完成后重试。\n 占用指令: ${existing.command}\n 进程 PID : ${existing.pid}\n 开始时间: ${existing.startedAt}\n 锁文件 : ${INSTALL_LOCK_FILE}`;
|
|
11940
11950
|
}
|
|
11941
11951
|
}
|
|
11942
11952
|
/**
|
|
11943
11953
|
* 释放安装操作互斥锁。
|
|
11944
11954
|
* 仅删除由本进程创建的锁文件,避免误删其他进程的锁。
|
|
11945
|
-
* 通常由 process.
|
|
11955
|
+
* 通常由 process.once('exit') 自动调用,不需要手动调用。
|
|
11946
11956
|
*/
|
|
11947
11957
|
function releaseInstallLock() {
|
|
11948
11958
|
try {
|
|
@@ -11956,8 +11966,18 @@ function releaseInstallLock() {
|
|
|
11956
11966
|
}
|
|
11957
11967
|
//#endregion
|
|
11958
11968
|
//#region src/index.ts
|
|
11969
|
+
/** 锁冲突时各 install 命令的统一处理:输出 { ok: false } 并退出 */
|
|
11970
|
+
function handleInstallLockConflict(lockErr) {
|
|
11971
|
+
console.log(JSON.stringify({
|
|
11972
|
+
ok: false,
|
|
11973
|
+
error: lockErr
|
|
11974
|
+
}));
|
|
11975
|
+
node_process.default.exit(1);
|
|
11976
|
+
}
|
|
11959
11977
|
const args = node_process.default.argv.slice(2);
|
|
11960
11978
|
const mode = args.find((a) => !a.startsWith("-"));
|
|
11979
|
+
const t0 = Date.now();
|
|
11980
|
+
const scene = getFlag(args, "scene");
|
|
11961
11981
|
/**
|
|
11962
11982
|
* Pull the first non-flag positional after the mode name.
|
|
11963
11983
|
* (The mode itself is args[0] in the filtered set, so we skip index 0.)
|
|
@@ -12041,13 +12061,11 @@ async function main() {
|
|
|
12041
12061
|
}
|
|
12042
12062
|
const caller = getFlag(args, "caller");
|
|
12043
12063
|
const traceId = getFlag(args, "trace-id");
|
|
12044
|
-
const scene = getFlag(args, "scene");
|
|
12045
12064
|
const profile = getFlag(args, "profile") === "experimental" ? "experimental" : "standard";
|
|
12046
12065
|
const rc = setRunContext({
|
|
12047
12066
|
caller,
|
|
12048
12067
|
traceId
|
|
12049
12068
|
});
|
|
12050
|
-
const t0 = Date.now();
|
|
12051
12069
|
console.error(`${mode}: begin argv=[${args.join(" ")}] version=${getVersion()} traceId=${traceId ?? "-"} caller=${caller ?? "-"} runIdGenerated=${rc.generated}`);
|
|
12052
12070
|
switch (mode) {
|
|
12053
12071
|
case "check": {
|
|
@@ -12154,8 +12172,18 @@ async function main() {
|
|
|
12154
12172
|
console.error("Error: --task-id=<id> is required for worker");
|
|
12155
12173
|
node_process.default.exit(1);
|
|
12156
12174
|
}
|
|
12157
|
-
acquireInstallLock("reset");
|
|
12158
12175
|
const resultFile = resetResultFile(taskId);
|
|
12176
|
+
const resetLockErr = acquireInstallLock("reset");
|
|
12177
|
+
if (resetLockErr) {
|
|
12178
|
+
try {
|
|
12179
|
+
node_fs.default.writeFileSync(resultFile, JSON.stringify({
|
|
12180
|
+
status: "failed",
|
|
12181
|
+
error: resetLockErr
|
|
12182
|
+
}));
|
|
12183
|
+
} catch {}
|
|
12184
|
+
node_process.default.exitCode = 1;
|
|
12185
|
+
return;
|
|
12186
|
+
}
|
|
12159
12187
|
const raw = await fetchCtxViaInnerApi({
|
|
12160
12188
|
populate: planCtxPopulate({ command: "reset" }),
|
|
12161
12189
|
caller,
|
|
@@ -12199,7 +12227,8 @@ async function main() {
|
|
|
12199
12227
|
console.error("Usage: install-openclaw <tag> [--oss_file_map=<base64>]");
|
|
12200
12228
|
node_process.default.exit(1);
|
|
12201
12229
|
}
|
|
12202
|
-
acquireInstallLock("install-openclaw");
|
|
12230
|
+
const installOcLockErr = acquireInstallLock("install-openclaw");
|
|
12231
|
+
if (installOcLockErr) handleInstallLockConflict(installOcLockErr);
|
|
12203
12232
|
const ossFileMapFlag = getFlag(args, "oss_file_map");
|
|
12204
12233
|
let installOssFileMap;
|
|
12205
12234
|
let rawForTelemetry;
|
|
@@ -12242,7 +12271,8 @@ async function main() {
|
|
|
12242
12271
|
console.error("Usage: install-extension <tag> (--all | --extension=<name>...) [--home_base=<dir>] [--config_path=<path>] [--skip-config-update] [--oss_file_map=<base64>]");
|
|
12243
12272
|
node_process.default.exit(1);
|
|
12244
12273
|
}
|
|
12245
|
-
acquireInstallLock("install-extension");
|
|
12274
|
+
const installExtLockErr = acquireInstallLock("install-extension");
|
|
12275
|
+
if (installExtLockErr) handleInstallLockConflict(installExtLockErr);
|
|
12246
12276
|
const all = args.includes("--all");
|
|
12247
12277
|
const names = getMultiFlag(args, "extension");
|
|
12248
12278
|
const homeBase = getFlag(args, "home_base");
|
|
@@ -12306,7 +12336,8 @@ async function main() {
|
|
|
12306
12336
|
console.error("Usage: install-cli <tag> --cli=<name>... [--home_base=<dir>] [--oss_file_map=<base64>]");
|
|
12307
12337
|
node_process.default.exit(1);
|
|
12308
12338
|
}
|
|
12309
|
-
acquireInstallLock("install-cli");
|
|
12339
|
+
const installCliLockErr = acquireInstallLock("install-cli");
|
|
12340
|
+
if (installCliLockErr) handleInstallLockConflict(installCliLockErr);
|
|
12310
12341
|
const homeBase = getFlag(args, "home_base");
|
|
12311
12342
|
const ossFileMapFlag = getFlag(args, "oss_file_map");
|
|
12312
12343
|
let installOssFileMap;
|
|
@@ -12450,7 +12481,31 @@ async function main() {
|
|
|
12450
12481
|
}
|
|
12451
12482
|
case "upgrade-lark": {
|
|
12452
12483
|
const checkOnly = args.includes("--check");
|
|
12453
|
-
if (!checkOnly)
|
|
12484
|
+
if (!checkOnly) {
|
|
12485
|
+
const upgradeLockErr = acquireInstallLock("upgrade-lark");
|
|
12486
|
+
if (upgradeLockErr) {
|
|
12487
|
+
const fixStatus = computeFixStatus(scene, "failed");
|
|
12488
|
+
const failResult = {
|
|
12489
|
+
status: "failed",
|
|
12490
|
+
error: upgradeLockErr,
|
|
12491
|
+
logFile: "",
|
|
12492
|
+
fixStatus
|
|
12493
|
+
};
|
|
12494
|
+
if (fixStatus !== void 0) writeFixStatusEvent(fixStatus, failResult, console.error);
|
|
12495
|
+
console.log(JSON.stringify(failResult));
|
|
12496
|
+
reportUpgradeLarkToSlardar({
|
|
12497
|
+
scene,
|
|
12498
|
+
checkOnly,
|
|
12499
|
+
durationMs: Date.now() - t0,
|
|
12500
|
+
resultStatus: "failed",
|
|
12501
|
+
error: upgradeLockErr,
|
|
12502
|
+
logFile: "",
|
|
12503
|
+
resultSummary: buildUpgradeLarkResultSummary(failResult, checkOnly)
|
|
12504
|
+
});
|
|
12505
|
+
node_process.default.exitCode = 1;
|
|
12506
|
+
return;
|
|
12507
|
+
}
|
|
12508
|
+
}
|
|
12454
12509
|
const skipRestart = args.includes("--skip-restart");
|
|
12455
12510
|
const result = runUpgradeLark({
|
|
12456
12511
|
runId: rc.runId,
|
|
@@ -12516,6 +12571,47 @@ main().catch((err) => {
|
|
|
12516
12571
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12517
12572
|
console.error(`${mode ?? "<no-mode>"}: error message=${msg}`);
|
|
12518
12573
|
node_process.default.stderr.write(`Error: ${msg}\n`);
|
|
12574
|
+
if (mode) {
|
|
12575
|
+
const durationMs = Date.now() - t0;
|
|
12576
|
+
if (mode === "upgrade-lark") {
|
|
12577
|
+
const checkOnly = args.includes("--check");
|
|
12578
|
+
const fixStatus = computeFixStatus(scene, "failed");
|
|
12579
|
+
const failResult = {
|
|
12580
|
+
status: "failed",
|
|
12581
|
+
error: msg,
|
|
12582
|
+
logFile: "",
|
|
12583
|
+
fixStatus
|
|
12584
|
+
};
|
|
12585
|
+
if (fixStatus !== void 0) writeFixStatusEvent(fixStatus, failResult, console.error);
|
|
12586
|
+
console.log(JSON.stringify(failResult));
|
|
12587
|
+
reportUpgradeLarkToSlardar({
|
|
12588
|
+
scene,
|
|
12589
|
+
checkOnly,
|
|
12590
|
+
durationMs,
|
|
12591
|
+
resultStatus: "failed",
|
|
12592
|
+
error: msg,
|
|
12593
|
+
logFile: "",
|
|
12594
|
+
resultSummary: buildUpgradeLarkResultSummary(failResult, checkOnly)
|
|
12595
|
+
});
|
|
12596
|
+
} else if ([
|
|
12597
|
+
"doctor",
|
|
12598
|
+
"check",
|
|
12599
|
+
"repair",
|
|
12600
|
+
"install-openclaw",
|
|
12601
|
+
"install-extension",
|
|
12602
|
+
"install-cli",
|
|
12603
|
+
"download-resource",
|
|
12604
|
+
"reset",
|
|
12605
|
+
"lark-cli-init"
|
|
12606
|
+
].includes(mode)) reportDoctorRunToSlardar({
|
|
12607
|
+
command: mode,
|
|
12608
|
+
scene,
|
|
12609
|
+
profile: getFlag(args, "profile") === "experimental" ? "experimental" : "standard",
|
|
12610
|
+
fix: args.includes("--fix"),
|
|
12611
|
+
durationMs,
|
|
12612
|
+
success: false
|
|
12613
|
+
});
|
|
12614
|
+
}
|
|
12519
12615
|
node_process.default.exitCode = 1;
|
|
12520
12616
|
});
|
|
12521
12617
|
//#endregion
|
package/package.json
CHANGED