@lark-apaas/openclaw-scripts-diagnose-cli 0.1.5-alpha.7 → 0.1.5-alpha.8
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 +84 -42
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -53,7 +53,7 @@ let json_diff = require("json-diff");
|
|
|
53
53
|
* it terse and parseable.
|
|
54
54
|
*/
|
|
55
55
|
function getVersion() {
|
|
56
|
-
return "0.1.5-alpha.
|
|
56
|
+
return "0.1.5-alpha.8";
|
|
57
57
|
}
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/rule-engine/base.ts
|
|
@@ -781,12 +781,10 @@ FeishuChannelRule = __decorate([Rule({
|
|
|
781
781
|
//#endregion
|
|
782
782
|
//#region src/rules/feishu-default-account.ts
|
|
783
783
|
/**
|
|
784
|
-
*
|
|
784
|
+
* Owner of the multi-agent feishu channel shape: migrates legacy v1/v2
|
|
785
785
|
* (top-level appId + defaultAccount/default) into v3 (`bot-<appId>` account),
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
* Single-agent configs (no `accounts`) are out of scope — handled by
|
|
789
|
-
* `feishu_channel`.
|
|
786
|
+
* detects + fixes drift on the main bot's appId/appSecret. Single-agent
|
|
787
|
+
* configs (no `accounts`) are out of scope — handled by `feishu_channel`.
|
|
790
788
|
*/
|
|
791
789
|
/** Top-level `channels.feishu.*` account-policy fields migrated into the main bot. */
|
|
792
790
|
const TOP_FIELDS_TO_MIGRATE = [
|
|
@@ -799,11 +797,25 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
799
797
|
validate(ctx) {
|
|
800
798
|
const feishu = getNestedMap(ctx.config, "channels", "feishu");
|
|
801
799
|
if (!feishu) return { pass: true };
|
|
802
|
-
|
|
803
|
-
if (
|
|
800
|
+
const accounts = asRecord(feishu.accounts);
|
|
801
|
+
if (!accounts) return { pass: true };
|
|
802
|
+
const topAppId = feishu.appId;
|
|
803
|
+
if (typeof topAppId === "string" && topAppId !== "") return {
|
|
804
804
|
pass: false,
|
|
805
805
|
message: "channels.feishu has legacy shape; needs migration to accounts.bot-<appId>"
|
|
806
806
|
};
|
|
807
|
+
const mainBot = findMainBotAccount(ctx.config, accounts);
|
|
808
|
+
if (mainBot) {
|
|
809
|
+
const expectedAppId = ctx.vars?.feishuAppID;
|
|
810
|
+
if (typeof expectedAppId === "string" && expectedAppId !== "" && mainBot.acc.appId !== expectedAppId) return {
|
|
811
|
+
pass: false,
|
|
812
|
+
message: `accounts.${mainBot.accountId}.appId mismatch: got ${mainBot.acc.appId}, expected ${expectedAppId}`
|
|
813
|
+
};
|
|
814
|
+
if (!secretMatchesCanonical(mainBot.acc.appSecret)) return {
|
|
815
|
+
pass: false,
|
|
816
|
+
message: `accounts.${mainBot.accountId}.appSecret drift`
|
|
817
|
+
};
|
|
818
|
+
}
|
|
807
819
|
return { pass: true };
|
|
808
820
|
}
|
|
809
821
|
repair(ctx) {
|
|
@@ -811,10 +823,16 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
811
823
|
if (!feishu) return;
|
|
812
824
|
const accounts = asRecord(feishu.accounts);
|
|
813
825
|
if (!accounts) return;
|
|
814
|
-
|
|
826
|
+
const topAppId = feishu.appId;
|
|
827
|
+
if (typeof topAppId === "string" && topAppId !== "") {
|
|
828
|
+
this.migrate(ctx, feishu, accounts, topAppId);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
this.enforceMainBotValues(ctx, accounts);
|
|
815
832
|
}
|
|
816
|
-
migrate(ctx, feishu, accounts, topAppId
|
|
817
|
-
const
|
|
833
|
+
migrate(ctx, feishu, accounts, topAppId) {
|
|
834
|
+
const effectiveAppId = nonEmpty(ctx.vars?.feishuAppID) ?? topAppId;
|
|
835
|
+
const expectedKey = `bot-${effectiveAppId}`;
|
|
818
836
|
const existingBot = asRecord(accounts[expectedKey]) ?? {};
|
|
819
837
|
const defaultAccount = asRecord(accounts.defaultAccount) ?? {};
|
|
820
838
|
const defaultAcc = asRecord(accounts.default) ?? {};
|
|
@@ -831,8 +849,8 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
831
849
|
...topGroups
|
|
832
850
|
};
|
|
833
851
|
if (Object.keys(fusedGroups).length > 0) merged.groups = fusedGroups;
|
|
834
|
-
merged.appId =
|
|
835
|
-
merged.appSecret =
|
|
852
|
+
merged.appId = effectiveAppId;
|
|
853
|
+
merged.appSecret = DEFAULT_FEISHU_APP_SECRET;
|
|
836
854
|
const chatID = ctx.vars?.teamChatID;
|
|
837
855
|
if (typeof chatID === "string" && chatID !== "") {
|
|
838
856
|
const existingGroups = asRecord(merged.groups) ?? {};
|
|
@@ -849,6 +867,14 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
849
867
|
for (const k of TOP_FIELDS_TO_MIGRATE) delete feishu[k];
|
|
850
868
|
this.rewireBindings(ctx.config, expectedKey);
|
|
851
869
|
}
|
|
870
|
+
enforceMainBotValues(ctx, accounts) {
|
|
871
|
+
const mainBot = findMainBotAccount(ctx.config, accounts);
|
|
872
|
+
if (!mainBot) return;
|
|
873
|
+
const acc = accounts[mainBot.accountId];
|
|
874
|
+
const expectedAppId = nonEmpty(ctx.vars?.feishuAppID);
|
|
875
|
+
if (expectedAppId !== void 0 && acc.appId !== expectedAppId) acc.appId = expectedAppId;
|
|
876
|
+
if (!secretMatchesCanonical(acc.appSecret)) acc.appSecret = DEFAULT_FEISHU_APP_SECRET;
|
|
877
|
+
}
|
|
852
878
|
rewireBindings(config, expectedKey) {
|
|
853
879
|
if (!Array.isArray(config.bindings)) return;
|
|
854
880
|
const bindings = config.bindings;
|
|
@@ -894,18 +920,32 @@ FeishuDefaultAccountRule = __decorate([Rule({
|
|
|
894
920
|
repairMode: "standard",
|
|
895
921
|
usesVars: ["feishuAppID", "teamChatID"]
|
|
896
922
|
})], FeishuDefaultAccountRule);
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
923
|
+
function nonEmpty(v) {
|
|
924
|
+
return typeof v === "string" && v !== "" ? v : void 0;
|
|
925
|
+
}
|
|
926
|
+
function findMainBotAccount(config, accounts) {
|
|
927
|
+
const mainId = findMainAgent(config)?.id;
|
|
928
|
+
if (typeof mainId !== "string" || mainId === "") return void 0;
|
|
929
|
+
const bindings = Array.isArray(config.bindings) ? config.bindings : [];
|
|
930
|
+
for (const b of bindings) {
|
|
931
|
+
const rec = asRecord(b);
|
|
932
|
+
const match = asRecord(rec?.match);
|
|
933
|
+
if (rec && match && rec.agentId === mainId && match.channel === "feishu") {
|
|
934
|
+
const accountId = match.accountId;
|
|
935
|
+
if (typeof accountId === "string") {
|
|
936
|
+
const acc = asRecord(accounts[accountId]);
|
|
937
|
+
if (acc) return {
|
|
938
|
+
accountId,
|
|
939
|
+
acc
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
/** Bot accounts must carry the canonical provider-ref `appSecret`. */
|
|
946
|
+
function secretMatchesCanonical(secret) {
|
|
947
|
+
if (typeof secret !== "object" || secret === null || Array.isArray(secret)) return false;
|
|
948
|
+
return matchMap(secret, DEFAULT_FEISHU_APP_SECRET);
|
|
909
949
|
}
|
|
910
950
|
//#endregion
|
|
911
951
|
//#region src/rules/gateway.ts
|
|
@@ -1907,6 +1947,10 @@ function findEntry(pluginVersion) {
|
|
|
1907
1947
|
const PLUGIN_NAME = "openclaw-lark";
|
|
1908
1948
|
const LEGACY_SHORT_NAMES = ["feishu-openclaw-plugin"];
|
|
1909
1949
|
const FORK_SCOPES = ["@lark-apaas"];
|
|
1950
|
+
/** 特化 fork 版全名:虽免于 VERSION_COMPAT_MAP 检查,仍需 openclaw ≥ 此版本 */
|
|
1951
|
+
const FORK_LARK_PLUGIN_FULL_NAME = "@lark-apaas/openclaw-lark";
|
|
1952
|
+
/** 来自 VERSION_COMPAT_MAP openclawLarkVersion=2026.4.1 对应的 minOpenclawVersion */
|
|
1953
|
+
const FORK_LARK_PLUGIN_MIN_OC_VERSION = "2026.3.28";
|
|
1910
1954
|
/**
|
|
1911
1955
|
* 飞书插件 ↔ openclaw 版本兼容检测。
|
|
1912
1956
|
*
|
|
@@ -1931,7 +1975,7 @@ let FeishuPluginVersionCompatRule = class FeishuPluginVersionCompatRule extends
|
|
|
1931
1975
|
if (!ocCur) return { pass: true };
|
|
1932
1976
|
const installed = detectInstalledPlugin(ctx);
|
|
1933
1977
|
if (installed == null) return { pass: true };
|
|
1934
|
-
if (isForkPlugin(installed)) return
|
|
1978
|
+
if (isForkPlugin(installed)) return validateForkPlugin(installed, ocCur, recommendedOc);
|
|
1935
1979
|
const isLegacy = isLegacyPlugin(installed);
|
|
1936
1980
|
if (!isLegacy && isVersionCompatible(installed, ocCur)) return { pass: true };
|
|
1937
1981
|
return decideUpgrade({
|
|
@@ -1975,6 +2019,19 @@ function decideUpgrade(args) {
|
|
|
1975
2019
|
message: `${prefix};当前 openclaw@${ocCur} 已达推荐版本,可直接升级飞书插件`
|
|
1976
2020
|
};
|
|
1977
2021
|
}
|
|
2022
|
+
/**
|
|
2023
|
+
* @lark-apaas/openclaw-lark 豁免 VERSION_COMPAT_MAP,但仍要求 openclaw ≥ FORK_LARK_PLUGIN_MIN_OC_VERSION。
|
|
2024
|
+
* 其他 @lark-apaas scope 的 fork 插件继续无条件 pass。
|
|
2025
|
+
*/
|
|
2026
|
+
function validateForkPlugin(installed, ocCur, recommendedOc) {
|
|
2027
|
+
if (installed.fullName !== FORK_LARK_PLUGIN_FULL_NAME) return { pass: true };
|
|
2028
|
+
if (compareCalVer(ocCur, FORK_LARK_PLUGIN_MIN_OC_VERSION) >= 0) return { pass: true };
|
|
2029
|
+
return {
|
|
2030
|
+
pass: false,
|
|
2031
|
+
action: "upgrade_openclaw",
|
|
2032
|
+
message: `安装了 ${describePlugin(installed)}(fork 版),当前 openclaw@${ocCur} 低于最低要求 ${FORK_LARK_PLUGIN_MIN_OC_VERSION};将 openclaw 升级到 ${recommendedOc} 即可满足`
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
1978
2035
|
function describePlugin(p) {
|
|
1979
2036
|
return (p.fullName ?? p.allowName) + (p.version ? `@${p.version}` : "");
|
|
1980
2037
|
}
|
|
@@ -2955,7 +3012,6 @@ async function installExtension(tag, ossFileMap, opts = {}) {
|
|
|
2955
3012
|
else console.error(`[install-extension] skipConfigUpdate=true — not touching openclaw.json`);
|
|
2956
3013
|
console.error(`[install-extension] done ${targets.length}/${targets.length} in ${Date.now() - t0}ms`);
|
|
2957
3014
|
}
|
|
2958
|
-
const MEM0_PLUGIN_NAME = "openclaw-mem0-plugin";
|
|
2959
3015
|
/**
|
|
2960
3016
|
* Merge each installed extension's installMetadata into openclaw.json's
|
|
2961
3017
|
* plugins.installs[<pkg.name>]. Atomic write via tmp + rename.
|
|
@@ -2963,11 +3019,6 @@ const MEM0_PLUGIN_NAME = "openclaw-mem0-plugin";
|
|
|
2963
3019
|
* - No openclaw.json → log + return (not an error; some install contexts don't have it yet)
|
|
2964
3020
|
* - Extension without installMetadata in manifest → skip that entry (log)
|
|
2965
3021
|
* - Existing plugins.installs entries for other extensions left untouched
|
|
2966
|
-
*
|
|
2967
|
-
* Special-case for mem0: when openclaw-mem0-plugin is among the installed
|
|
2968
|
-
* targets, also append it to plugins.allow (idempotent) and seed
|
|
2969
|
-
* plugins.entries.openclaw-mem0-plugin = { enabled: false } when the key
|
|
2970
|
-
* is absent. Existing values are preserved (user toggles survive).
|
|
2971
3022
|
*/
|
|
2972
3023
|
function updatePluginInstalls(configPath, installedPkgs) {
|
|
2973
3024
|
if (!node_fs.default.existsSync(configPath)) {
|
|
@@ -2987,15 +3038,6 @@ function updatePluginInstalls(configPath, installedPkgs) {
|
|
|
2987
3038
|
installs[pkg.name] = pkg.installMetadata;
|
|
2988
3039
|
updated++;
|
|
2989
3040
|
} else skipped++;
|
|
2990
|
-
if (installedPkgs.some((p) => p.name === MEM0_PLUGIN_NAME)) {
|
|
2991
|
-
const allowRaw = plugins.allow;
|
|
2992
|
-
const allow = Array.isArray(allowRaw) ? allowRaw : [];
|
|
2993
|
-
if (!allow.filter((e) => typeof e === "string").includes(MEM0_PLUGIN_NAME)) allow.push(MEM0_PLUGIN_NAME);
|
|
2994
|
-
plugins.allow = allow;
|
|
2995
|
-
if (!plugins.entries || typeof plugins.entries !== "object" || Array.isArray(plugins.entries)) plugins.entries = {};
|
|
2996
|
-
const entries = plugins.entries;
|
|
2997
|
-
if (!(MEM0_PLUGIN_NAME in entries)) entries[MEM0_PLUGIN_NAME] = { enabled: false };
|
|
2998
|
-
}
|
|
2999
3041
|
const tmpPath = configPath + ".installs-tmp";
|
|
3000
3042
|
node_fs.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2), "utf-8");
|
|
3001
3043
|
moveSafe(tmpPath, configPath);
|
|
@@ -4272,7 +4314,7 @@ async function reportCliRun(opts) {
|
|
|
4272
4314
|
//#region src/help.ts
|
|
4273
4315
|
const BIN = "mclaw-diagnose";
|
|
4274
4316
|
function versionBanner() {
|
|
4275
|
-
return `v0.1.5-alpha.
|
|
4317
|
+
return `v0.1.5-alpha.8`;
|
|
4276
4318
|
}
|
|
4277
4319
|
const COMMANDS = [
|
|
4278
4320
|
{
|