@lark-apaas/openclaw-scripts-diagnose-cli 0.1.1-alpha.23 → 0.1.1-alpha.25
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 +167 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -877,6 +877,121 @@ SecretsRule = __decorate([Rule({
|
|
|
877
877
|
skipWhen: ({ hasMiaoda, deps }) => !hasMiaoda || !deps.usesMiaodaSecretProvider
|
|
878
878
|
})], SecretsRule);
|
|
879
879
|
//#endregion
|
|
880
|
+
//#region src/rules/template-vars-unreplaced.ts
|
|
881
|
+
/**
|
|
882
|
+
* Placeholder format used by miaoda-openclaw-template and Go-side templateVars,
|
|
883
|
+
* e.g. `$$__FEISHU_APP_ID__`. Double underscores on both sides act as a natural
|
|
884
|
+
* boundary so split-join replacement can't accidentally overlap between keys.
|
|
885
|
+
*/
|
|
886
|
+
const PLACEHOLDER_RE = /\$\$__[A-Z0-9_]+__/g;
|
|
887
|
+
let TemplateVarsUnreplacedRule = class TemplateVarsUnreplacedRule extends DiagnoseRule {
|
|
888
|
+
validate(ctx) {
|
|
889
|
+
const found = /* @__PURE__ */ new Set();
|
|
890
|
+
collectPlaceholders(ctx.config, found);
|
|
891
|
+
if (found.size === 0) return { pass: true };
|
|
892
|
+
return {
|
|
893
|
+
pass: false,
|
|
894
|
+
message: "存在未替换的模板占位符: " + [...found].sort().join(", ")
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
repair(ctx) {
|
|
898
|
+
const map = ctx.templateVars;
|
|
899
|
+
if (!map || Object.keys(map).length === 0) return;
|
|
900
|
+
replaceInPlace(ctx.config, Object.entries(map));
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
TemplateVarsUnreplacedRule = __decorate([Rule({
|
|
904
|
+
key: "template_vars_unreplaced",
|
|
905
|
+
dependsOn: ["config_syntax_check"],
|
|
906
|
+
repairMode: "standard"
|
|
907
|
+
})], TemplateVarsUnreplacedRule);
|
|
908
|
+
function collectPlaceholders(value, found) {
|
|
909
|
+
if (typeof value === "string") {
|
|
910
|
+
const matches = value.match(PLACEHOLDER_RE);
|
|
911
|
+
if (matches) for (const m of matches) found.add(m);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
if (Array.isArray(value)) {
|
|
915
|
+
for (const v of value) collectPlaceholders(v, found);
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
if (value && typeof value === "object") for (const v of Object.values(value)) collectPlaceholders(v, found);
|
|
919
|
+
}
|
|
920
|
+
function replaceInPlace(value, entries) {
|
|
921
|
+
if (Array.isArray(value)) {
|
|
922
|
+
for (let i = 0; i < value.length; i++) {
|
|
923
|
+
const el = value[i];
|
|
924
|
+
if (typeof el === "string") value[i] = applyVars(el, entries);
|
|
925
|
+
else replaceInPlace(el, entries);
|
|
926
|
+
}
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
if (value && typeof value === "object") {
|
|
930
|
+
const obj = value;
|
|
931
|
+
for (const key of Object.keys(obj)) {
|
|
932
|
+
const v = obj[key];
|
|
933
|
+
if (typeof v === "string") obj[key] = applyVars(v, entries);
|
|
934
|
+
else replaceInPlace(v, entries);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
/** Split-join replacement — matches the algorithm in reset.ts:120 and avoids regex-escaping `$$`. */
|
|
939
|
+
function applyVars(str, entries) {
|
|
940
|
+
let out = str;
|
|
941
|
+
for (const [placeholder, value] of entries) {
|
|
942
|
+
if (!value) continue;
|
|
943
|
+
if (out.includes(placeholder)) out = out.split(placeholder).join(value);
|
|
944
|
+
}
|
|
945
|
+
return out;
|
|
946
|
+
}
|
|
947
|
+
//#endregion
|
|
948
|
+
//#region src/rules/cleanup-install-backup-dirs.ts
|
|
949
|
+
const DIR_PREFIX = ".openclaw-install-";
|
|
950
|
+
function resolveExtensionsDir(configPath) {
|
|
951
|
+
return node_path.default.join(node_path.default.dirname(configPath), "extensions");
|
|
952
|
+
}
|
|
953
|
+
function findLeftoverDirs(extensionsDir) {
|
|
954
|
+
if (!fileExists(extensionsDir)) return [];
|
|
955
|
+
let entries;
|
|
956
|
+
try {
|
|
957
|
+
entries = node_fs.default.readdirSync(extensionsDir, { withFileTypes: true });
|
|
958
|
+
} catch {
|
|
959
|
+
return [];
|
|
960
|
+
}
|
|
961
|
+
return entries.filter((e) => e.isDirectory() && e.name.startsWith(DIR_PREFIX)).map((e) => node_path.default.join(extensionsDir, e.name));
|
|
962
|
+
}
|
|
963
|
+
let CleanupInstallBackupDirsRule = class CleanupInstallBackupDirsRule extends DiagnoseRule {
|
|
964
|
+
validate(ctx) {
|
|
965
|
+
const configPath = ctx.config.__configPath;
|
|
966
|
+
if (!configPath) return { pass: true };
|
|
967
|
+
const dirs = findLeftoverDirs(resolveExtensionsDir(configPath));
|
|
968
|
+
if (dirs.length === 0) return { pass: true };
|
|
969
|
+
return {
|
|
970
|
+
pass: false,
|
|
971
|
+
message: `extensions 目录下发现 ${dirs.length} 个 ${DIR_PREFIX}* 脏目录需要清理`
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
repair(ctx) {
|
|
975
|
+
const configPath = ctx.config.__configPath;
|
|
976
|
+
if (!configPath) return;
|
|
977
|
+
const dirs = findLeftoverDirs(resolveExtensionsDir(configPath));
|
|
978
|
+
const failures = [];
|
|
979
|
+
for (const dir of dirs) try {
|
|
980
|
+
node_fs.default.rmSync(dir, {
|
|
981
|
+
recursive: true,
|
|
982
|
+
force: true
|
|
983
|
+
});
|
|
984
|
+
} catch (e) {
|
|
985
|
+
failures.push(`${node_path.default.basename(dir)}: ${e.message}`);
|
|
986
|
+
}
|
|
987
|
+
if (dirs.length > 0 && failures.length === dirs.length) throw new Error(`cleanup_install_backup_dirs: 全部清理失败: ${failures.join("; ")}`);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
CleanupInstallBackupDirsRule = __decorate([Rule({
|
|
991
|
+
key: "cleanup_install_backup_dirs",
|
|
992
|
+
repairMode: "standard"
|
|
993
|
+
})], CleanupInstallBackupDirsRule);
|
|
994
|
+
//#endregion
|
|
880
995
|
//#region src/rules/miaoda-official-plugins-install-spec-unlock.ts
|
|
881
996
|
/**
|
|
882
997
|
* Official miaoda-side plugins that must track manifest — version-locked specs
|
|
@@ -942,19 +1057,21 @@ const OLD_PLUGIN_NAMES = Object.freeze([
|
|
|
942
1057
|
"miaoda-keepalive"
|
|
943
1058
|
]);
|
|
944
1059
|
function getPluginMaps(config) {
|
|
1060
|
+
const rawAllow = asRecord(config.plugins)?.allow;
|
|
945
1061
|
return {
|
|
946
1062
|
entries: getNestedMap(config, "plugins", "entries"),
|
|
947
|
-
installs: getNestedMap(config, "plugins", "installs")
|
|
1063
|
+
installs: getNestedMap(config, "plugins", "installs"),
|
|
1064
|
+
allow: Array.isArray(rawAllow) ? rawAllow : void 0
|
|
948
1065
|
};
|
|
949
1066
|
}
|
|
950
1067
|
function getExtensionsDir(configPath) {
|
|
951
1068
|
return node_path.default.join(node_path.default.dirname(configPath), "extensions");
|
|
952
1069
|
}
|
|
953
|
-
function hasNewMiaoda({ entries, installs }) {
|
|
954
|
-
return asRecord(entries?.[NEW_MIAODA]) != null || asRecord(installs?.[NEW_MIAODA]) != null;
|
|
1070
|
+
function hasNewMiaoda({ entries, installs, allow }) {
|
|
1071
|
+
return asRecord(entries?.[NEW_MIAODA]) != null || asRecord(installs?.[NEW_MIAODA]) != null || (allow?.includes(NEW_MIAODA) ?? false);
|
|
955
1072
|
}
|
|
956
|
-
function findResiduals({ entries, installs }, extensionsDir) {
|
|
957
|
-
return OLD_PLUGIN_NAMES.filter((name) => entries?.[name] != null || installs?.[name] != null || node_fs.default.existsSync(node_path.default.join(extensionsDir, name)));
|
|
1073
|
+
function findResiduals({ entries, installs, allow }, extensionsDir) {
|
|
1074
|
+
return OLD_PLUGIN_NAMES.filter((name) => entries?.[name] != null || installs?.[name] != null || (allow?.includes(name) ?? false) || node_fs.default.existsSync(node_path.default.join(extensionsDir, name)));
|
|
958
1075
|
}
|
|
959
1076
|
let OldMiaodaPluginsCleanupRule = class OldMiaodaPluginsCleanupRule extends DiagnoseRule {
|
|
960
1077
|
validate(ctx) {
|
|
@@ -971,7 +1088,12 @@ let OldMiaodaPluginsCleanupRule = class OldMiaodaPluginsCleanupRule extends Diag
|
|
|
971
1088
|
const maps = getPluginMaps(ctx.config);
|
|
972
1089
|
if (!hasNewMiaoda(maps)) return;
|
|
973
1090
|
const extensionsDir = getExtensionsDir(ctx.configPath);
|
|
974
|
-
const { entries, installs } = maps;
|
|
1091
|
+
const { entries, installs, allow } = maps;
|
|
1092
|
+
const oldSet = new Set(OLD_PLUGIN_NAMES);
|
|
1093
|
+
if (allow) for (let i = allow.length - 1; i >= 0; i--) {
|
|
1094
|
+
const v = allow[i];
|
|
1095
|
+
if (typeof v === "string" && oldSet.has(v)) allow.splice(i, 1);
|
|
1096
|
+
}
|
|
975
1097
|
for (const name of OLD_PLUGIN_NAMES) {
|
|
976
1098
|
if (entries && name in entries) delete entries[name];
|
|
977
1099
|
if (installs && name in installs) delete installs[name];
|
|
@@ -995,6 +1117,45 @@ OldMiaodaPluginsCleanupRule = __decorate([Rule({
|
|
|
995
1117
|
repairMode: "standard"
|
|
996
1118
|
})], OldMiaodaPluginsCleanupRule);
|
|
997
1119
|
//#endregion
|
|
1120
|
+
//#region src/rules/lark-plugin-allow.ts
|
|
1121
|
+
const LARK_PLUGIN = "openclaw-lark";
|
|
1122
|
+
const LARK_PLUGIN_NAMES = [LARK_PLUGIN, "feishu-openclaw-plugin"];
|
|
1123
|
+
let LarkPluginAllowRule = class LarkPluginAllowRule extends DiagnoseRule {
|
|
1124
|
+
validate(ctx) {
|
|
1125
|
+
const allow = getAllow(ctx.config);
|
|
1126
|
+
if (LARK_PLUGIN_NAMES.some((name) => allow.includes(name))) return { pass: true };
|
|
1127
|
+
return {
|
|
1128
|
+
pass: false,
|
|
1129
|
+
message: `plugins.allow 缺少飞书插件 (expected one of: ${LARK_PLUGIN_NAMES.join(", ")})`
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
repair(ctx) {
|
|
1133
|
+
if (ctx.config.plugins == null || typeof ctx.config.plugins !== "object" || Array.isArray(ctx.config.plugins)) {
|
|
1134
|
+
ctx.config.plugins = { allow: [LARK_PLUGIN] };
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
const pluginsMap = ctx.config.plugins;
|
|
1138
|
+
const rawAllow = pluginsMap.allow;
|
|
1139
|
+
const original = Array.isArray(rawAllow) ? rawAllow : [];
|
|
1140
|
+
const stringAllow = original.filter((e) => typeof e === "string");
|
|
1141
|
+
if (LARK_PLUGIN_NAMES.some((name) => stringAllow.includes(name))) return;
|
|
1142
|
+
original.push(LARK_PLUGIN);
|
|
1143
|
+
pluginsMap.allow = original;
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
LarkPluginAllowRule = __decorate([Rule({
|
|
1147
|
+
key: "lark_plugin_allow",
|
|
1148
|
+
dependsOn: ["config_syntax_check"],
|
|
1149
|
+
repairMode: "standard"
|
|
1150
|
+
})], LarkPluginAllowRule);
|
|
1151
|
+
function getAllow(config) {
|
|
1152
|
+
const plugins = config.plugins;
|
|
1153
|
+
if (plugins == null || typeof plugins !== "object" || Array.isArray(plugins)) return [];
|
|
1154
|
+
const allow = plugins.allow;
|
|
1155
|
+
if (!Array.isArray(allow)) return [];
|
|
1156
|
+
return allow.filter((e) => typeof e === "string");
|
|
1157
|
+
}
|
|
1158
|
+
//#endregion
|
|
998
1159
|
//#region src/check.ts
|
|
999
1160
|
function runCheck(input) {
|
|
1000
1161
|
const result = { failedRules: {
|
package/package.json
CHANGED