

























@@ -0,0 +1,158 @@
1+import { formatCliCommand } from "../cli/command-format.js";
2+import type { OpenClawConfig } from "../config/types.openclaw.js";
3+import type { PluginInstallRecord } from "../config/types.plugins.js";
4+import {
5+readPersistedPluginInstallLedger,
6+resolvePluginInstallLedgerStorePath,
7+withoutPluginInstallRecords,
8+writePersistedPluginInstallLedger,
9+type PluginInstallLedgerStoreOptions,
10+} from "../plugins/install-ledger-store.js";
11+import { refreshPluginRegistry } from "../plugins/plugin-registry.js";
12+import { note } from "../terminal/note.js";
13+import { shortenHomePath } from "../utils.js";
14+import type { DoctorPrompter } from "./doctor-prompter.js";
15+import {
16+DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV,
17+migratePluginRegistryForInstall,
18+preflightPluginRegistryInstallMigration,
19+type PluginRegistryInstallMigrationParams,
20+} from "./doctor/shared/plugin-registry-migration.js";
21+22+type PluginRegistryDoctorRepairParams = Omit<PluginRegistryInstallMigrationParams, "config"> &
23+PluginInstallLedgerStoreOptions & {
24+config: OpenClawConfig;
25+prompter: Pick<DoctorPrompter, "shouldRepair">;
26+};
27+28+type LegacyInstallLedgerMigrationResult = {
29+config: OpenClawConfig;
30+migrated: boolean;
31+recordCount: number;
32+};
33+34+function countRecords(records: Record<string, unknown> | undefined): number {
35+return Object.keys(records ?? {}).length;
36+}
37+38+function mergeInstallRecords(
39+legacyRecords: Record<string, PluginInstallRecord>,
40+ledgerRecords: Record<string, PluginInstallRecord> | undefined,
41+): Record<string, PluginInstallRecord> {
42+return {
43+ ...legacyRecords,
44+ ...(ledgerRecords ?? {}),
45+};
46+}
47+48+async function maybeMigrateLegacyInstallLedger(
49+params: PluginRegistryDoctorRepairParams,
50+): Promise<LegacyInstallLedgerMigrationResult> {
51+const legacyRecords = params.config.plugins?.installs;
52+const legacyCount = countRecords(legacyRecords);
53+if (!legacyRecords || legacyCount === 0) {
54+return {
55+config: params.config,
56+migrated: false,
57+recordCount: 0,
58+};
59+}
60+61+const ledgerPath = resolvePluginInstallLedgerStorePath(params);
62+if (!params.prompter.shouldRepair) {
63+note(
64+[
65+`Legacy plugin install records still live in config at \`plugins.installs\`.`,
66+`Repair with ${formatCliCommand("openclaw doctor --fix")} to move them to ${shortenHomePath(ledgerPath)} and remove the config copy.`,
67+].join("\n"),
68+"Plugin registry",
69+);
70+return {
71+config: params.config,
72+migrated: false,
73+recordCount: legacyCount,
74+};
75+}
76+77+const existingLedger = await readPersistedPluginInstallLedger(params);
78+const nextRecords = mergeInstallRecords(legacyRecords, existingLedger?.records);
79+await writePersistedPluginInstallLedger(nextRecords, params);
80+const nextConfig = withoutPluginInstallRecords(params.config);
81+note(
82+[
83+`Moved ${legacyCount} legacy plugin install record${legacyCount === 1 ? "" : "s"} from config to ${shortenHomePath(ledgerPath)}.`,
84+"Removed the legacy `plugins.installs` config copy.",
85+].join("\n"),
86+"Plugin registry",
87+);
88+return {
89+config: nextConfig,
90+migrated: true,
91+recordCount: legacyCount,
92+};
93+}
94+95+export async function maybeRepairPluginRegistryState(
96+params: PluginRegistryDoctorRepairParams,
97+): Promise<OpenClawConfig> {
98+let nextConfig = params.config;
99+const ledgerMigration = await maybeMigrateLegacyInstallLedger(params);
100+nextConfig = ledgerMigration.config;
101+102+const migrationParams = {
103+ ...params,
104+config: nextConfig,
105+};
106+const preflight = preflightPluginRegistryInstallMigration(migrationParams);
107+for (const warning of preflight.deprecationWarnings) {
108+note(warning, "Plugin registry");
109+}
110+if (preflight.action === "disabled") {
111+note(
112+`${DISABLE_PLUGIN_REGISTRY_MIGRATION_ENV} is set; skipping plugin registry repair.`,
113+"Plugin registry",
114+);
115+return nextConfig;
116+}
117+118+if (!params.prompter.shouldRepair) {
119+if (preflight.action === "migrate") {
120+note(
121+[
122+"Persisted plugin registry is missing or stale.",
123+`Repair with ${formatCliCommand("openclaw doctor --fix")} to rebuild ${shortenHomePath(preflight.filePath)} from enabled plugins.`,
124+].join("\n"),
125+"Plugin registry",
126+);
127+}
128+return nextConfig;
129+}
130+131+if (preflight.action === "migrate") {
132+const result = await migratePluginRegistryForInstall(migrationParams);
133+if (result.migrated) {
134+const total = result.current.plugins.length;
135+const enabled = result.current.plugins.filter((plugin) => plugin.enabled).length;
136+note(
137+`Plugin registry rebuilt: ${enabled}/${total} enabled plugins indexed.`,
138+"Plugin registry",
139+);
140+}
141+return nextConfig;
142+}
143+144+if (ledgerMigration.migrated) {
145+const index = await refreshPluginRegistry({
146+ ...migrationParams,
147+reason: "migration",
148+});
149+const total = index.plugins.length;
150+const enabled = index.plugins.filter((plugin) => plugin.enabled).length;
151+note(
152+`Plugin registry refreshed: ${enabled}/${total} enabled plugins indexed.`,
153+"Plugin registry",
154+);
155+}
156+157+return nextConfig;
158+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。