





















@@ -18,6 +18,10 @@ import {
1818collectRelevantDoctorPluginIds,
1919listPluginDoctorLegacyConfigRules,
2020} from "../plugins/doctor-contract-registry.js";
21+import {
22+loadInstalledPluginIndexInstallRecordsSync,
23+writePersistedInstalledPluginIndexInstallRecordsSync,
24+} from "../plugins/installed-plugin-index-records.js";
2125import { sanitizeTerminalText } from "../terminal/safe-text.js";
2226import { isRecord } from "../utils.js";
2327import { VERSION } from "../version.js";
@@ -60,6 +64,7 @@ import {
6064projectSourceOntoRuntimeShape,
6165restoreEnvRefsFromMap,
6266resolvePersistCandidateForWrite,
67+resolveManagedUnsetPathsForWrite,
6368resolveWriteEnvSnapshotForPath,
6469} from "./io.write-prepare.js";
6570import { findLegacyConfigIssues } from "./legacy.js";
@@ -70,6 +75,10 @@ import {
7075} from "./materialize.js";
7176import { applyMergePatch } from "./merge-patch.js";
7277import { resolveConfigPath, resolveStateDir } from "./paths.js";
78+import {
79+extractShippedPluginInstallConfigRecords,
80+stripShippedPluginInstallConfigRecords,
81+} from "./plugin-install-config-migration.js";
7382import { applyConfigOverrides } from "./runtime-overrides.js";
7483import {
7584clearRuntimeConfigSnapshot as clearRuntimeConfigSnapshotState,
@@ -1009,9 +1018,12 @@ async function recoverConfigFromJsonRootSuffixWithDeps(params: {
10091018readResolution.resolvedConfigRaw,
10101019suffixRecovery.parsed,
10111020);
1012-const validated = validateConfigObjectWithPlugins(legacyResolution.effectiveConfigRaw, {
1013-env: params.deps.env,
1014-});
1021+const validated = validateConfigObjectWithPlugins(
1022+stripShippedPluginInstallConfigRecords(legacyResolution.effectiveConfigRaw),
1023+{
1024+env: params.deps.env,
1025+},
1026+);
10151027if (!validated.ok) {
10161028return false;
10171029}
@@ -1198,6 +1210,41 @@ export function createConfigIO(
11981210return applyConfigOverrides(cfgWithOwnerDisplaySecret);
11991211}
120012121213+function migrateAndStripShippedPluginInstallConfigRecords(configRaw: unknown): unknown {
1214+const installRecords = extractShippedPluginInstallConfigRecords(configRaw);
1215+const stripped = stripShippedPluginInstallConfigRecords(configRaw);
1216+if (Object.keys(installRecords).length === 0) {
1217+return stripped;
1218+}
1219+1220+try {
1221+const stateDir = resolveStateDir(deps.env, deps.homedir);
1222+const existingRecords = loadInstalledPluginIndexInstallRecordsSync({
1223+env: deps.env,
1224+ stateDir,
1225+});
1226+const nextRecords = {
1227+ ...installRecords,
1228+ ...existingRecords,
1229+};
1230+if (Object.keys(installRecords).some((pluginId) => !(pluginId in existingRecords))) {
1231+writePersistedInstalledPluginIndexInstallRecordsSync(nextRecords, {
1232+config: coerceConfig(stripped),
1233+env: deps.env,
1234+ stateDir,
1235+});
1236+}
1237+} catch (err) {
1238+deps.logger.warn(
1239+`Config (${configPath}): could not migrate shipped plugins.installs records into the plugin index: ${formatErrorMessage(
1240+ err,
1241+ )}`,
1242+);
1243+}
1244+1245+return stripped;
1246+}
1247+12011248function loadConfig(): OpenClawConfig {
12021249try {
12031250maybeLoadDotEnvForConfig(deps.env);
@@ -1230,7 +1277,9 @@ export function createConfigIO(
12301277);
12311278const resolvedConfig = readResolution.resolvedConfigRaw;
12321279const legacyResolution = resolveLegacyConfigForRead(resolvedConfig, effectiveParsed);
1233-const effectiveConfigRaw = legacyResolution.effectiveConfigRaw;
1280+const effectiveConfigRaw = migrateAndStripShippedPluginInstallConfigRecords(
1281+legacyResolution.effectiveConfigRaw,
1282+);
12341283for (const w of readResolution.envWarnings) {
12351284deps.logger.warn(
12361285`Config (${configPath}): missing env var "${w.varName}" at ${w.configPath} - feature using this value will be unavailable`,
@@ -1439,7 +1488,9 @@ export function createConfigIO(
1439148814401489const resolvedConfigRaw = readResolution.resolvedConfigRaw;
14411490const legacyResolution = resolveLegacyConfigForRead(resolvedConfigRaw, effectiveParsed);
1442-const effectiveConfigRaw = legacyResolution.effectiveConfigRaw;
1491+const effectiveConfigRaw = migrateAndStripShippedPluginInstallConfigRecords(
1492+legacyResolution.effectiveConfigRaw,
1493+);
14431494fallbackSourceConfig = coerceConfig(effectiveConfigRaw);
14441495const validated = validateConfigObjectWithPlugins(effectiveConfigRaw, {
14451496env: deps.env,
@@ -1562,6 +1613,7 @@ export function createConfigIO(
15621613writeOptions: {
15631614envSnapshotForRestore: result.envSnapshotForRestore,
15641615expectedConfigPath: configPath,
1616+unsetPaths: resolveManagedUnsetPathsForWrite(undefined),
15651617},
15661618};
15671619}
@@ -1609,7 +1661,9 @@ export function createConfigIO(
16091661readResolution.resolvedConfigRaw,
16101662recovered.parsed,
16111663);
1612-return coerceConfig(legacyResolution.effectiveConfigRaw);
1664+return coerceConfig(
1665+stripShippedPluginInstallConfigRecords(legacyResolution.effectiveConfigRaw),
1666+);
16131667} catch {
16141668return {};
16151669}
@@ -1620,6 +1674,7 @@ export function createConfigIO(
16201674options: ConfigWriteOptions = {},
16211675): Promise<{ persistedHash: string; persistedConfig: OpenClawConfig }> {
16221676clearConfigCache();
1677+const unsetPaths = resolveManagedUnsetPathsForWrite(options.unsetPaths);
16231678let persistCandidate: unknown = cfg;
16241679const snapshot = options.baseSnapshot ?? (await readConfigFileSnapshotInternal()).snapshot;
16251680let envRefMap: Map<string, string> | null = null;
@@ -1655,10 +1710,7 @@ export function createConfigIO(
16551710}
16561711}
165717121658-persistCandidate = applyUnsetPathsForWrite(
1659-persistCandidate as OpenClawConfig,
1660-options.unsetPaths,
1661-);
1713+persistCandidate = applyUnsetPathsForWrite(persistCandidate as OpenClawConfig, unsetPaths);
1662171416631715const validated = validateConfigObjectRawWithPlugins(persistCandidate, { env: deps.env });
16641716if (!validated.ok) {
@@ -1720,7 +1772,7 @@ export function createConfigIO(
17201772envRefMap && changedPaths
17211773 ? (restoreEnvRefsFromMap(cfgToWrite, "", envRefMap, changedPaths) as OpenClawConfig)
17221774 : cfgToWrite;
1723-const outputConfig = applyUnsetPathsForWrite(outputConfigBase, options.unsetPaths);
1775+const outputConfig = applyUnsetPathsForWrite(outputConfigBase, unsetPaths);
17241776// Do NOT apply runtime defaults when writing - user config should only contain
17251777// explicitly set values. Runtime defaults are applied when loading (issue #6070).
17261778const stampedOutputConfig = stampConfigVersion(outputConfig);
@@ -2054,7 +2106,7 @@ export async function writeConfigFile(
20542106expectedConfigPath: options.expectedConfigPath,
20552107envSnapshotForRestore: options.envSnapshotForRestore,
20562108}),
2057-unsetPaths: options.unsetPaths,
2109+unsetPaths: resolveManagedUnsetPathsForWrite(options.unsetPaths),
20582110allowDestructiveWrite: options.allowDestructiveWrite,
20592111skipRuntimeSnapshotRefresh: options.skipRuntimeSnapshotRefresh,
20602112skipOutputLogs: options.skipOutputLogs,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。