@lark-apaas/openclaw-scripts-diagnose-cli 0.1.5-alpha.8 → 0.1.5
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 +41 -66
- 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
|
|
56
|
+
return "0.1.5";
|
|
57
57
|
}
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/rule-engine/base.ts
|
|
@@ -781,10 +781,12 @@ FeishuChannelRule = __decorate([Rule({
|
|
|
781
781
|
//#endregion
|
|
782
782
|
//#region src/rules/feishu-default-account.ts
|
|
783
783
|
/**
|
|
784
|
-
*
|
|
784
|
+
* Owns the multi-agent feishu-channel migration: turns legacy v1/v2
|
|
785
785
|
* (top-level appId + defaultAccount/default) into v3 (`bot-<appId>` account),
|
|
786
|
-
*
|
|
787
|
-
*
|
|
786
|
+
* preserving the user's top-level `appId` / `appSecret` verbatim. Once on
|
|
787
|
+
* v3 this rule does not touch account values — the user owns them.
|
|
788
|
+
* Single-agent configs (no `accounts`) are out of scope — handled by
|
|
789
|
+
* `feishu_channel`.
|
|
788
790
|
*/
|
|
789
791
|
/** Top-level `channels.feishu.*` account-policy fields migrated into the main bot. */
|
|
790
792
|
const TOP_FIELDS_TO_MIGRATE = [
|
|
@@ -797,25 +799,11 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
797
799
|
validate(ctx) {
|
|
798
800
|
const feishu = getNestedMap(ctx.config, "channels", "feishu");
|
|
799
801
|
if (!feishu) return { pass: true };
|
|
800
|
-
|
|
801
|
-
if (
|
|
802
|
-
const topAppId = feishu.appId;
|
|
803
|
-
if (typeof topAppId === "string" && topAppId !== "") return {
|
|
802
|
+
if (!asRecord(feishu.accounts)) return { pass: true };
|
|
803
|
+
if (hasLegacyTopLevel(feishu)) 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
|
-
}
|
|
819
807
|
return { pass: true };
|
|
820
808
|
}
|
|
821
809
|
repair(ctx) {
|
|
@@ -823,16 +811,10 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
823
811
|
if (!feishu) return;
|
|
824
812
|
const accounts = asRecord(feishu.accounts);
|
|
825
813
|
if (!accounts) return;
|
|
826
|
-
|
|
827
|
-
if (typeof topAppId === "string" && topAppId !== "") {
|
|
828
|
-
this.migrate(ctx, feishu, accounts, topAppId);
|
|
829
|
-
return;
|
|
830
|
-
}
|
|
831
|
-
this.enforceMainBotValues(ctx, accounts);
|
|
814
|
+
if (hasLegacyTopLevel(feishu)) this.migrate(ctx, feishu, accounts, feishu.appId, feishu.appSecret);
|
|
832
815
|
}
|
|
833
|
-
migrate(ctx, feishu, accounts, topAppId) {
|
|
834
|
-
const
|
|
835
|
-
const expectedKey = `bot-${effectiveAppId}`;
|
|
816
|
+
migrate(ctx, feishu, accounts, topAppId, topAppSecret) {
|
|
817
|
+
const expectedKey = `bot-${topAppId}`;
|
|
836
818
|
const existingBot = asRecord(accounts[expectedKey]) ?? {};
|
|
837
819
|
const defaultAccount = asRecord(accounts.defaultAccount) ?? {};
|
|
838
820
|
const defaultAcc = asRecord(accounts.default) ?? {};
|
|
@@ -849,8 +831,8 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
849
831
|
...topGroups
|
|
850
832
|
};
|
|
851
833
|
if (Object.keys(fusedGroups).length > 0) merged.groups = fusedGroups;
|
|
852
|
-
merged.appId =
|
|
853
|
-
merged.appSecret =
|
|
834
|
+
merged.appId = topAppId;
|
|
835
|
+
merged.appSecret = topAppSecret;
|
|
854
836
|
const chatID = ctx.vars?.teamChatID;
|
|
855
837
|
if (typeof chatID === "string" && chatID !== "") {
|
|
856
838
|
const existingGroups = asRecord(merged.groups) ?? {};
|
|
@@ -867,14 +849,6 @@ let FeishuDefaultAccountRule = class FeishuDefaultAccountRule extends DiagnoseRu
|
|
|
867
849
|
for (const k of TOP_FIELDS_TO_MIGRATE) delete feishu[k];
|
|
868
850
|
this.rewireBindings(ctx.config, expectedKey);
|
|
869
851
|
}
|
|
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
|
-
}
|
|
878
852
|
rewireBindings(config, expectedKey) {
|
|
879
853
|
if (!Array.isArray(config.bindings)) return;
|
|
880
854
|
const bindings = config.bindings;
|
|
@@ -920,32 +894,18 @@ FeishuDefaultAccountRule = __decorate([Rule({
|
|
|
920
894
|
repairMode: "standard",
|
|
921
895
|
usesVars: ["feishuAppID", "teamChatID"]
|
|
922
896
|
})], FeishuDefaultAccountRule);
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
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);
|
|
897
|
+
/**
|
|
898
|
+
* Legacy top-level shape only counts as "needs migration" when BOTH appId and
|
|
899
|
+
* appSecret are present. Either one alone is treated as a partial config the
|
|
900
|
+
* user owns; doctor leaves it untouched and won't synthesize the missing half
|
|
901
|
+
* from defaults. `appId` must be a non-empty string (used as bot key);
|
|
902
|
+
* `appSecret` may be a string OR a provider-ref object, so we only require
|
|
903
|
+
* `!== undefined`.
|
|
904
|
+
*/
|
|
905
|
+
function hasLegacyTopLevel(feishu) {
|
|
906
|
+
const appId = feishu.appId;
|
|
907
|
+
if (typeof appId !== "string" || appId === "") return false;
|
|
908
|
+
return feishu.appSecret !== void 0;
|
|
949
909
|
}
|
|
950
910
|
//#endregion
|
|
951
911
|
//#region src/rules/gateway.ts
|
|
@@ -3012,6 +2972,7 @@ async function installExtension(tag, ossFileMap, opts = {}) {
|
|
|
3012
2972
|
else console.error(`[install-extension] skipConfigUpdate=true — not touching openclaw.json`);
|
|
3013
2973
|
console.error(`[install-extension] done ${targets.length}/${targets.length} in ${Date.now() - t0}ms`);
|
|
3014
2974
|
}
|
|
2975
|
+
const MEM0_PLUGIN_NAME = "openclaw-mem0-plugin";
|
|
3015
2976
|
/**
|
|
3016
2977
|
* Merge each installed extension's installMetadata into openclaw.json's
|
|
3017
2978
|
* plugins.installs[<pkg.name>]. Atomic write via tmp + rename.
|
|
@@ -3019,6 +2980,11 @@ async function installExtension(tag, ossFileMap, opts = {}) {
|
|
|
3019
2980
|
* - No openclaw.json → log + return (not an error; some install contexts don't have it yet)
|
|
3020
2981
|
* - Extension without installMetadata in manifest → skip that entry (log)
|
|
3021
2982
|
* - Existing plugins.installs entries for other extensions left untouched
|
|
2983
|
+
*
|
|
2984
|
+
* Special-case for mem0: when openclaw-mem0-plugin is among the installed
|
|
2985
|
+
* targets, also append it to plugins.allow (idempotent) and seed
|
|
2986
|
+
* plugins.entries.openclaw-mem0-plugin = { enabled: false } when the key
|
|
2987
|
+
* is absent. Existing values are preserved (user toggles survive).
|
|
3022
2988
|
*/
|
|
3023
2989
|
function updatePluginInstalls(configPath, installedPkgs) {
|
|
3024
2990
|
if (!node_fs.default.existsSync(configPath)) {
|
|
@@ -3038,6 +3004,15 @@ function updatePluginInstalls(configPath, installedPkgs) {
|
|
|
3038
3004
|
installs[pkg.name] = pkg.installMetadata;
|
|
3039
3005
|
updated++;
|
|
3040
3006
|
} else skipped++;
|
|
3007
|
+
if (installedPkgs.some((p) => p.name === MEM0_PLUGIN_NAME)) {
|
|
3008
|
+
const allowRaw = plugins.allow;
|
|
3009
|
+
const allow = Array.isArray(allowRaw) ? allowRaw : [];
|
|
3010
|
+
if (!allow.filter((e) => typeof e === "string").includes(MEM0_PLUGIN_NAME)) allow.push(MEM0_PLUGIN_NAME);
|
|
3011
|
+
plugins.allow = allow;
|
|
3012
|
+
if (!plugins.entries || typeof plugins.entries !== "object" || Array.isArray(plugins.entries)) plugins.entries = {};
|
|
3013
|
+
const entries = plugins.entries;
|
|
3014
|
+
if (!(MEM0_PLUGIN_NAME in entries)) entries[MEM0_PLUGIN_NAME] = { enabled: false };
|
|
3015
|
+
}
|
|
3041
3016
|
const tmpPath = configPath + ".installs-tmp";
|
|
3042
3017
|
node_fs.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2), "utf-8");
|
|
3043
3018
|
moveSafe(tmpPath, configPath);
|
|
@@ -4314,7 +4289,7 @@ async function reportCliRun(opts) {
|
|
|
4314
4289
|
//#region src/help.ts
|
|
4315
4290
|
const BIN = "mclaw-diagnose";
|
|
4316
4291
|
function versionBanner() {
|
|
4317
|
-
return `v0.1.5
|
|
4292
|
+
return `v0.1.5`;
|
|
4318
4293
|
}
|
|
4319
4294
|
const COMMANDS = [
|
|
4320
4295
|
{
|