@lark-apaas/openclaw-scripts-diagnose-cli 0.1.11-alpha.1 → 0.1.11-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.
Files changed (2) hide show
  1. package/dist/index.cjs +63 -23
  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.11-alpha.1";
55
+ return "0.1.11-alpha.2";
56
56
  }
57
57
  //#endregion
58
58
  //#region src/rule-engine/base.ts
@@ -86,11 +86,16 @@ function getRuleMetas(keys) {
86
86
  description: r.meta.description ?? "(no description)",
87
87
  repairMode: r.meta.repairMode,
88
88
  profile: r.meta.profile ?? "standard",
89
+ level: getRuleImpactLevel(r.meta),
89
90
  dependsOn: r.meta.dependsOn ?? [],
90
91
  hasSkipWhen: r.meta.skipWhen !== void 0,
91
92
  hasRepair: r.repair !== DiagnoseRule.prototype.repair
92
93
  }));
93
94
  }
95
+ /** Default to critical for compatibility with tests/callers that build fake rules. */
96
+ function getRuleImpactLevel(meta) {
97
+ return meta.level ?? "critical";
98
+ }
94
99
  /**
95
100
  * 判断规则在当前 profile 下是否应执行。
96
101
  * experimental profile 运行所有规则;standard 只运行 standard(或未标注)规则。
@@ -1314,7 +1319,8 @@ let OpenclawRuntimeMissingRule = class OpenclawRuntimeMissingRule extends Diagno
1314
1319
  OpenclawRuntimeMissingRule = __decorate([Rule({
1315
1320
  key: "openclaw_runtime_missing",
1316
1321
  description: "检查 openclaw 二进制是否在 PATH 中可用;缺失时提示重新安装",
1317
- repairMode: "user-confirm"
1322
+ repairMode: "user-confirm",
1323
+ level: "critical"
1318
1324
  })], OpenclawRuntimeMissingRule);
1319
1325
  //#endregion
1320
1326
  //#region src/rules/multi-process-detect.ts
@@ -1338,7 +1344,8 @@ let ProcessStatusRule = class ProcessStatusRule extends DiagnoseRule {
1338
1344
  ProcessStatusRule = __decorate([Rule({
1339
1345
  key: "multi_process_detect",
1340
1346
  description: "通过 pgrep 检测是否存在多个并发的 openclaw-gateway 进程;多进程通常表明上次会话未正常退出",
1341
- repairMode: "standard"
1347
+ repairMode: "standard",
1348
+ level: "critical"
1342
1349
  })], ProcessStatusRule);
1343
1350
  //#endregion
1344
1351
  //#region src/rules/config-file-recover.ts
@@ -1404,7 +1411,8 @@ let ConfigFileBackupRule = class ConfigFileBackupRule extends DiagnoseRule {
1404
1411
  ConfigFileBackupRule = __decorate([Rule({
1405
1412
  key: "config_file_recover",
1406
1413
  description: "扫描 .bak* 配置备份,当主配置 openclaw.json 缺失时恢复编号最高的备份",
1407
- repairMode: "standard"
1414
+ repairMode: "standard",
1415
+ level: "critical"
1408
1416
  })], ConfigFileBackupRule);
1409
1417
  //#endregion
1410
1418
  //#region src/rules/config-file-missing.ts
@@ -1439,7 +1447,8 @@ ConfigFileMissingRule = __decorate([Rule({
1439
1447
  key: "config_file_missing",
1440
1448
  description: "在执行恢复后检查 openclaw.json 是否存在;若仍缺失则触发全量重置",
1441
1449
  dependsOn: ["config_file_recover"],
1442
- repairMode: "reset"
1450
+ repairMode: "reset",
1451
+ level: "critical"
1443
1452
  })], ConfigFileMissingRule);
1444
1453
  //#endregion
1445
1454
  //#region src/rules/config-syntax.ts
@@ -1462,7 +1471,8 @@ ConfigSyntaxRule = __decorate([Rule({
1462
1471
  key: "config_syntax_check",
1463
1472
  description: "验证 openclaw.json 的 JSON5 语法;schema 校验失败或解析错误时需要 AI 辅助修复",
1464
1473
  dependsOn: ["config_file_recover", "config_file_missing"],
1465
- repairMode: "ai"
1474
+ repairMode: "ai",
1475
+ level: "critical"
1466
1476
  })], ConfigSyntaxRule);
1467
1477
  //#endregion
1468
1478
  //#region src/rules/template-vars-unreplaced.ts
@@ -1493,6 +1503,7 @@ TemplateVarsUnreplacedRule = __decorate([Rule({
1493
1503
  description: "检测 openclaw.json 中未替换的 $__XXX__ 占位符,并从注入的环境变量中填充",
1494
1504
  dependsOn: ["config_syntax_check"],
1495
1505
  repairMode: "standard",
1506
+ level: "critical",
1496
1507
  usesVars: ["templateVars"]
1497
1508
  })], TemplateVarsUnreplacedRule);
1498
1509
  function collectPlaceholders(value, found) {
@@ -1648,6 +1659,7 @@ GatewayRule = __decorate([Rule({
1648
1659
  description: "验证 gateway 必填字段(port、mode、bind、auth、trustedProxies)是否存在且有效;修复缺失或非法值",
1649
1660
  dependsOn: ["config_syntax_check"],
1650
1661
  repairMode: "standard",
1662
+ level: "critical",
1651
1663
  usesVars: ["gatewayToken"]
1652
1664
  })], GatewayRule);
1653
1665
  //#endregion
@@ -1694,6 +1706,7 @@ AllowedOriginsRule = __decorate([Rule({
1694
1706
  description: "确保所有 expectedOrigins 条目都存在于 gateway.auth.allowedOrigins 中;自动追加缺失的条目",
1695
1707
  dependsOn: ["config_syntax_check"],
1696
1708
  repairMode: "standard",
1709
+ level: "critical",
1697
1710
  usesVars: ["expectedOrigins"]
1698
1711
  })], AllowedOriginsRule);
1699
1712
  function getExpectedOrigins(vars) {
@@ -1753,7 +1766,8 @@ SessionPersistenceRule = __decorate([Rule({
1753
1766
  key: "session_persistence",
1754
1767
  description: "补齐 session.resetByChannel 与 session.maintenance 持久化配置",
1755
1768
  dependsOn: ["config_syntax_check"],
1756
- repairMode: "standard"
1769
+ repairMode: "standard",
1770
+ level: "silent"
1757
1771
  })], SessionPersistenceRule);
1758
1772
  //#endregion
1759
1773
  //#region src/rules/feishu-default-account.ts
@@ -1870,6 +1884,7 @@ FeishuDefaultAccountRule = __decorate([Rule({
1870
1884
  description: "将旧版 v1/v2 飞书 channel 配置迁移为规范的 v3 bot-<appId> 账号结构",
1871
1885
  dependsOn: ["config_syntax_check"],
1872
1886
  repairMode: "standard",
1887
+ level: "critical",
1873
1888
  usesVars: ["feishuAppID", "teamChatID"]
1874
1889
  })], FeishuDefaultAccountRule);
1875
1890
  /**
@@ -1948,6 +1963,7 @@ FeishuChannelRule = __decorate([Rule({
1948
1963
  description: "确保 channels.feishu 已启用,且包含单 agent 所需的 appId 和 appSecret 字段",
1949
1964
  dependsOn: ["config_syntax_check", "feishu_default_account"],
1950
1965
  repairMode: "standard",
1966
+ level: "critical",
1951
1967
  usesVars: ["feishuAppID", "feishuAppSecret"]
1952
1968
  })], FeishuChannelRule);
1953
1969
  //#endregion
@@ -1978,7 +1994,8 @@ FeishuBotIdRule = __decorate([Rule({
1978
1994
  key: "feishu_bot_id",
1979
1995
  description: "确保多账号飞书配置中每个 bot-<appId> 账号 key 与 appId 一致",
1980
1996
  dependsOn: ["config_syntax_check", "feishu_default_account"],
1981
- repairMode: "standard"
1997
+ repairMode: "standard",
1998
+ level: "critical"
1982
1999
  })], FeishuBotIdRule);
1983
2000
  function getMismatchedAccounts(accounts) {
1984
2001
  const mismatched = [];
@@ -2062,6 +2079,7 @@ FeishuAccountsConsistencyRule = __decorate([Rule({
2062
2079
  description: "检测多 agent 配置中 channels.feishu.accounts、agents.list 与 feishu bindings 之间的数量/ID 不一致(实验性)",
2063
2080
  dependsOn: ["config_syntax_check"],
2064
2081
  repairMode: "check-only",
2082
+ level: "silent",
2065
2083
  usesVars: ["feishuAppID"],
2066
2084
  profile: "experimental"
2067
2085
  })], FeishuAccountsConsistencyRule);
@@ -2183,6 +2201,7 @@ ModelProviderRule = __decorate([Rule({
2183
2201
  description: "检查妙搭 model provider 配置项(baseUrl、apiKey、必要 headers)是否存在且格式正确;非妙搭沙箱时跳过",
2184
2202
  dependsOn: ["config_syntax_check"],
2185
2203
  repairMode: "standard",
2204
+ level: "critical",
2186
2205
  usesVars: ["innerAPIKey", "baseURL"],
2187
2206
  skipWhen: ({ hasMiaoda }) => !hasMiaoda
2188
2207
  })], ModelProviderRule);
@@ -2251,6 +2270,7 @@ SecretProviderRule = _SecretProviderRule = __decorate([Rule({
2251
2270
  description: "验证 miaoda-provider / miaoda-secret-provider 配置块是否存在且完整;未检测到妙搭 provider 时跳过",
2252
2271
  dependsOn: ["config_syntax_check"],
2253
2272
  repairMode: "standard",
2273
+ level: "critical",
2254
2274
  skipWhen: ({ hasMiaoda, deps }) => !hasMiaoda || !deps.usesMiaodaProvider && !deps.usesMiaodaSecretProvider
2255
2275
  })], SecretProviderRule);
2256
2276
  //#endregion
@@ -2313,6 +2333,7 @@ JwtTokenRule = __decorate([Rule({
2313
2333
  description: "验证 miaoda provider 引用的 JWT token 文件存在且未过期;非妙搭沙箱时跳过",
2314
2334
  dependsOn: ["config_syntax_check"],
2315
2335
  repairMode: "standard",
2336
+ level: "critical",
2316
2337
  usesVars: ["providerFilePath"],
2317
2338
  skipWhen: ({ hasMiaoda, deps }) => !hasMiaoda || !deps.usesMiaodaProvider
2318
2339
  })], JwtTokenRule);
@@ -2370,6 +2391,7 @@ SecretsFileRule = __decorate([Rule({
2370
2391
  description: "验证 miaoda secret-provider 引用的 secrets.json 文件存在且可解析;非妙搭或非 secret-provider 沙箱时跳过",
2371
2392
  dependsOn: ["config_syntax_check"],
2372
2393
  repairMode: "standard",
2394
+ level: "critical",
2373
2395
  usesVars: [
2374
2396
  "secretsFilePath",
2375
2397
  "feishuAppSecret",
@@ -2408,7 +2430,8 @@ AgentsMdServiceCommandsRule = __decorate([Rule({
2408
2430
  key: "agents_md_service_commands",
2409
2431
  description: "检测各智能体 AGENTS.md 中旧版 OpenClaw 服务命令,并替换为 /opt/force/bin/openclaw_scripts 路径",
2410
2432
  dependsOn: ["config_syntax_check"],
2411
- repairMode: "standard"
2433
+ repairMode: "standard",
2434
+ level: "silent"
2412
2435
  })], AgentsMdServiceCommandsRule);
2413
2436
  function hasOldServiceCommands(content) {
2414
2437
  return SERVICE_COMMAND_REPLACEMENTS.some(([oldCmd]) => content.includes(oldCmd));
@@ -2482,10 +2505,14 @@ AgentsMdResourceConstrainedToolsRule = __decorate([Rule({
2482
2505
  key: "agents_md_resource_constrained_tools",
2483
2506
  description: "检测各智能体 AGENTS.md 中 resource_constrained_tools 规则块,缺失时追加,存在时替换为当前内容",
2484
2507
  dependsOn: ["config_syntax_check"],
2485
- repairMode: "standard"
2508
+ repairMode: "standard",
2509
+ level: "silent"
2486
2510
  })], AgentsMdResourceConstrainedToolsRule);
2487
2511
  function hasCurrentResourceConstrainedToolsBlock(content) {
2488
- return content.includes(RESOURCE_CONSTRAINED_TOOLS_BLOCK);
2512
+ return normalizeForTemplateMatch(content).includes(normalizeForTemplateMatch(RESOURCE_CONSTRAINED_TOOLS_BLOCK));
2513
+ }
2514
+ function normalizeForTemplateMatch(content) {
2515
+ return content.replace(/\r\n?/g, "\n").split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0).join("\n");
2489
2516
  }
2490
2517
  function upsertResourceConstrainedToolsBlock(content) {
2491
2518
  const tagRe = new RegExp(`<${RESOURCE_CONSTRAINED_TOOLS_TAG}>[\\s\\S]*?</${RESOURCE_CONSTRAINED_TOOLS_TAG}>`);
@@ -2547,7 +2574,8 @@ MiaodaOfficialPluginsInstallSpecUnlockRule = __decorate([Rule({
2547
2574
  key: "miaoda_official_plugins_install_spec_unlock",
2548
2575
  description: "移除官方妙搭插件安装条目中的锁版本 npm spec,使其跟随最新 manifest 版本",
2549
2576
  dependsOn: ["config_syntax_check"],
2550
- repairMode: "standard"
2577
+ repairMode: "standard",
2578
+ level: "silent"
2551
2579
  })], MiaodaOfficialPluginsInstallSpecUnlockRule);
2552
2580
  //#endregion
2553
2581
  //#region src/rules/miaoda-plugin-allow.ts
@@ -2581,6 +2609,7 @@ MiaodaPluginAllowRule = __decorate([Rule({
2581
2609
  description: "当 openclaw-extension-miaoda 已在磁盘安装但未在 allow 列表中时,将其添加到 plugins.allow(实验性)",
2582
2610
  dependsOn: ["config_syntax_check"],
2583
2611
  repairMode: "standard",
2612
+ level: "critical",
2584
2613
  profile: "standard"
2585
2614
  })], MiaodaPluginAllowRule);
2586
2615
  function getAllow$1(config) {
@@ -2626,7 +2655,8 @@ LarkPluginAllowRule = __decorate([Rule({
2626
2655
  key: "lark_plugin_allow",
2627
2656
  description: "当飞书插件(openclaw-lark 或旧版名)已在磁盘安装但未加入 plugins.allow 时,自动添加",
2628
2657
  dependsOn: ["config_syntax_check"],
2629
- repairMode: "standard"
2658
+ repairMode: "standard",
2659
+ level: "critical"
2630
2660
  })], LarkPluginAllowRule);
2631
2661
  function getAllow(config) {
2632
2662
  const plugins = config.plugins;
@@ -2716,7 +2746,8 @@ OldMiaodaPluginsCleanupRule = __decorate([Rule({
2716
2746
  key: "old_miaoda_plugins_cleanup",
2717
2747
  description: "当新版 openclaw-extension-miaoda 已存在时,清理过时插件引用(openclaw-feishu-greeting、openclaw-miaoda-keepalive 等)",
2718
2748
  dependsOn: ["config_syntax_check"],
2719
- repairMode: "standard"
2749
+ repairMode: "standard",
2750
+ level: "silent"
2720
2751
  })], OldMiaodaPluginsCleanupRule);
2721
2752
  //#endregion
2722
2753
  //#region src/rules/builtin-plugin-missing.ts
@@ -2751,6 +2782,7 @@ BuiltinPluginMissingRule = __decorate([Rule({
2751
2782
  description: "检查所有内置扩展插件(openclaw-lark、openclaw-extension-miaoda 等)是否已在磁盘安装;缺失时提示重新安装(实验性)",
2752
2783
  dependsOn: ["config_syntax_check"],
2753
2784
  repairMode: "user-confirm",
2785
+ level: "critical",
2754
2786
  profile: "experimental"
2755
2787
  })], BuiltinPluginMissingRule);
2756
2788
  //#endregion
@@ -2794,6 +2826,7 @@ BuiltinPluginInstallsCleanupRule = __decorate([Rule({
2794
2826
  description: "在 builtin_plugin_missing 通过后,清除 plugins.installs 中磁盘目录已不存在的条目(实验性)",
2795
2827
  dependsOn: ["builtin_plugin_missing"],
2796
2828
  repairMode: "standard",
2829
+ level: "silent",
2797
2830
  profile: "experimental"
2798
2831
  })], BuiltinPluginInstallsCleanupRule);
2799
2832
  //#endregion
@@ -3076,7 +3109,8 @@ FeishuPluginStateNormalizeRule = __decorate([Rule({
3076
3109
  key: "feishu_plugin_state_normalize",
3077
3110
  description: "规范化磁盘上的飞书插件状态:删除旧版插件目录、清理内置 feishu 目录,并将 openclaw.json 条目对齐到 openclaw-lark 插件",
3078
3111
  dependsOn: ["config_syntax_check"],
3079
- repairMode: "standard"
3112
+ repairMode: "standard",
3113
+ level: "critical"
3080
3114
  })], FeishuPluginStateNormalizeRule);
3081
3115
  function isPluginInstalled(ctx) {
3082
3116
  return node_fs.default.existsSync(node_path.default.join(getExtensionsDir(ctx.configPath), PLUGIN_NAME$1));
@@ -3349,6 +3383,7 @@ FeishuPluginOpenclawUpgradeRule = __decorate([Rule({
3349
3383
  description: "检查飞书插件是否要求更高版本的 openclaw;是则提示升级 openclaw",
3350
3384
  dependsOn: ["config_syntax_check"],
3351
3385
  repairMode: "user-confirm",
3386
+ level: "critical",
3352
3387
  usesVars: ["recommendedOpenclawTag"]
3353
3388
  })], FeishuPluginOpenclawUpgradeRule);
3354
3389
  /**
@@ -3375,6 +3410,7 @@ FeishuPluginLarkUpgradeRule = __decorate([Rule({
3375
3410
  description: "检查飞书插件版本是否落后于当前 openclaw;是则提示升级飞书插件",
3376
3411
  dependsOn: ["config_syntax_check", "feishu_plugin_version_compat_openclaw"],
3377
3412
  repairMode: "user-confirm",
3413
+ level: "critical",
3378
3414
  usesVars: ["recommendedOpenclawTag"]
3379
3415
  })], FeishuPluginLarkUpgradeRule);
3380
3416
  function isForkPlugin(p) {
@@ -3515,7 +3551,8 @@ let CleanupInstallBackupDirsRule = class CleanupInstallBackupDirsRule extends Di
3515
3551
  CleanupInstallBackupDirsRule = __decorate([Rule({
3516
3552
  key: "cleanup_install_backup_dirs",
3517
3553
  description: "清理 extensions/ 目录中升级中断遗留的 .openclaw-install-stage-* 和 .openclaw-install-backups/ 脏目录",
3518
- repairMode: "standard"
3554
+ repairMode: "standard",
3555
+ level: "critical"
3519
3556
  })], CleanupInstallBackupDirsRule);
3520
3557
  //#endregion
3521
3558
  //#region src/check.ts
@@ -3637,7 +3674,7 @@ function runCheckImpl(input) {
3637
3674
  action: r.action
3638
3675
  });
3639
3676
  failedKeys.add(meta.key);
3640
- pushFailedRule(result, meta.repairMode, meta.key, r.message || "", r.action);
3677
+ if (getRuleImpactLevel(meta) === "critical") pushFailedRule(result, meta.repairMode, meta.key, r.message || "", r.action);
3641
3678
  }
3642
3679
  }
3643
3680
  console.error(`runCheck: end totalMs=${Date.now() - tStart} failed={standard:${result.failedRules.standard.length},ai:${result.failedRules.ai.length},reset:${result.failedRules.reset.length}}`);
@@ -6561,7 +6598,12 @@ function mergeCoreBackupAndOrigins(configPath, vars, resetData, log) {
6561
6598
  const config = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
6562
6599
  const merged = [];
6563
6600
  const backupAccounts = backup.channels?.feishu?.accounts;
6564
- if ((backup.agents?.length ?? 0) > 0 || backupAccounts != null && Object.keys(backupAccounts).length > 0) {
6601
+ const isMultiAgent = (backup.agents?.length ?? 0) > 0 || backupAccounts != null && Object.keys(backupAccounts).length > 0;
6602
+ if (backup.bindings && backup.bindings.length > 0) {
6603
+ config.bindings = backup.bindings;
6604
+ merged.push("bindings");
6605
+ }
6606
+ if (isMultiAgent) {
6565
6607
  if (backup.agents && backup.agents.length > 0) {
6566
6608
  if (!config.agents) config.agents = {};
6567
6609
  const agents = config.agents;
@@ -6584,10 +6626,6 @@ function mergeCoreBackupAndOrigins(configPath, vars, resetData, log) {
6584
6626
  list[mainIdx].default = true;
6585
6627
  merged.push("main-team-mode");
6586
6628
  }
6587
- if (backup.bindings && backup.bindings.length > 0) {
6588
- config.bindings = backup.bindings;
6589
- merged.push("bindings");
6590
- }
6591
6629
  if (!config.channels) config.channels = {};
6592
6630
  const ch = config.channels;
6593
6631
  if (!ch.feishu) ch.feishu = {};
@@ -10052,7 +10090,7 @@ async function reportCliRun(opts) {
10052
10090
  //#region src/help.ts
10053
10091
  const BIN = "mclaw-diagnose";
10054
10092
  function versionBanner() {
10055
- return `v0.1.11-alpha.1`;
10093
+ return `v0.1.11-alpha.2`;
10056
10094
  }
10057
10095
  const COMMANDS = [
10058
10096
  {
@@ -10526,6 +10564,7 @@ function flushDiagnoseSlardar() {
10526
10564
  }
10527
10565
  function reportDoctorRunToSlardar(opts) {
10528
10566
  const outcomes = opts.ruleOutcomes ?? [];
10567
+ const ruleLevels = new Map(getAllRules().map((rule) => [rule.meta.key, getRuleImpactLevel(rule.meta)]));
10529
10568
  console.error(`[slardar] reportTask command=${opts.command} scene=${opts.scene ?? ""} profile=${opts.profile} fix=${opts.fix} events=${1 + outcomes.length}`);
10530
10569
  reportTask({
10531
10570
  eventName: "diagnose_cli_run",
@@ -10552,6 +10591,7 @@ function reportDoctorRunToSlardar(opts) {
10552
10591
  fix: String(opts.fix),
10553
10592
  rule_key: o.rule,
10554
10593
  rule_status: o.status,
10594
+ rule_level: ruleLevels.get(o.rule) ?? "",
10555
10595
  rule_message: o.message ?? ""
10556
10596
  }
10557
10597
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/openclaw-scripts-diagnose-cli",
3
- "version": "0.1.11-alpha.1",
3
+ "version": "0.1.11-alpha.2",
4
4
  "description": "CLI for OpenClaw config diagnose and repair with JSON5 support",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {