refactor: share non-interactive onboard config writes

This commit is contained in:
Vincent Koc
2026-05-29 03:36:56 +02:00
parent edda0608ac
commit c3e629cbf4
3 changed files with 62 additions and 77 deletions

View File

@@ -0,0 +1,51 @@
import {
commitConfigWriteWithPendingPluginInstalls,
hasPendingPluginInstallRecords,
stripPendingPluginInstallRecords,
unchangedPendingPluginInstallRecordIds,
} from "../../cli/plugins-install-record-commit.js";
import { replaceConfigFile } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
export async function commitNonInteractiveOnboardConfig(params: {
nextConfig: OpenClawConfig;
baseConfig: OpenClawConfig;
baseHash?: string;
reset?: boolean;
}): Promise<OpenClawConfig> {
// Ordinary onboard reruns must preserve existing agents.list / bindings.
// Only explicit --reset may allow a config size drop; see openclaw#84692.
const allowConfigSizeDrop = params.reset === true;
let writeBaseHash = params.baseHash;
let nextConfig = params.nextConfig;
if (!allowConfigSizeDrop && hasPendingPluginInstallRecords(params.baseConfig)) {
const migrated = await commitConfigWriteWithPendingPluginInstalls({
nextConfig: params.baseConfig,
writeOptions: { allowConfigSizeDrop: true },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
});
writeBaseHash = migrated.persistedHash ?? undefined;
nextConfig = stripPendingPluginInstallRecords(
nextConfig,
unchangedPendingPluginInstallRecordIds(nextConfig, params.baseConfig),
);
}
const committed = await commitConfigWriteWithPendingPluginInstalls({
nextConfig,
writeOptions: { allowConfigSizeDrop },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
});
return committed.config;
}

View File

@@ -1,11 +1,5 @@
import { formatCliCommand } from "../../cli/command-format.js";
import {
commitConfigWriteWithPendingPluginInstalls,
hasPendingPluginInstallRecords,
stripPendingPluginInstallRecords,
unchangedPendingPluginInstallRecordIds,
} from "../../cli/plugins-install-record-commit.js";
import { replaceConfigFile, resolveGatewayPort } from "../../config/config.js";
import { resolveGatewayPort } from "../../config/config.js";
import { logConfigUpdated } from "../../config/logging.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolveGatewayAuthToken } from "../../gateway/auth-token-resolution.js";
@@ -21,6 +15,7 @@ import {
waitForGatewayReachable,
} from "../onboard-helpers.js";
import type { OnboardOptions } from "../onboard-types.js";
import { commitNonInteractiveOnboardConfig } from "./config-write.js";
import { applyNonInteractiveGatewayConfig } from "./local/gateway-config.js";
import {
type GatewayHealthFailureDiagnostics,
@@ -210,40 +205,12 @@ export async function runNonInteractiveLocalSetup(params: {
nextConfig = applyNonInteractiveSkillsConfig({ nextConfig, opts, runtime });
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
// Ordinary onboard reruns must preserve existing agents.list / bindings.
// Only explicit --reset is allowed to shrink the config — see openclaw#84692.
const allowConfigSizeDrop = opts.reset === true;
let writeBaseHash = baseHash;
if (!allowConfigSizeDrop && hasPendingPluginInstallRecords(baseConfig)) {
const migrated = await commitConfigWriteWithPendingPluginInstalls({
nextConfig: baseConfig,
writeOptions: { allowConfigSizeDrop: true },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
});
writeBaseHash = migrated.persistedHash ?? undefined;
nextConfig = stripPendingPluginInstallRecords(
nextConfig,
unchangedPendingPluginInstallRecordIds(nextConfig, baseConfig),
);
}
const committed = await commitConfigWriteWithPendingPluginInstalls({
nextConfig = await commitNonInteractiveOnboardConfig({
nextConfig,
writeOptions: { allowConfigSizeDrop },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
baseConfig,
baseHash,
reset: opts.reset,
});
nextConfig = committed.config;
logConfigUpdated(runtime);
await ensureWorkspaceAndSessions(workspaceDir, runtime, {

View File

@@ -1,11 +1,4 @@
import { formatCliCommand } from "../../cli/command-format.js";
import {
commitConfigWriteWithPendingPluginInstalls,
hasPendingPluginInstallRecords,
stripPendingPluginInstallRecords,
unchangedPendingPluginInstallRecordIds,
} from "../../cli/plugins-install-record-commit.js";
import { replaceConfigFile } from "../../config/config.js";
import { logConfigUpdated } from "../../config/logging.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { type RuntimeEnv, writeRuntimeJson } from "../../runtime.js";
@@ -13,6 +6,7 @@ import { normalizeOptionalString } from "../../shared/string-coerce.js";
import { applySkipBootstrapConfig } from "../onboard-config.js";
import { applyWizardMetadata } from "../onboard-helpers.js";
import type { OnboardOptions } from "../onboard-types.js";
import { commitNonInteractiveOnboardConfig } from "./config-write.js";
export async function runNonInteractiveRemoteSetup(params: {
opts: OnboardOptions;
@@ -47,38 +41,11 @@ export async function runNonInteractiveRemoteSetup(params: {
nextConfig = applySkipBootstrapConfig(nextConfig);
}
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
// Ordinary remote onboard reruns must preserve existing agents.list /
// bindings the same way the local writer does — see openclaw#84692.
const allowConfigSizeDrop = opts.reset === true;
let writeBaseHash = baseHash;
if (!allowConfigSizeDrop && hasPendingPluginInstallRecords(baseConfig)) {
const migrated = await commitConfigWriteWithPendingPluginInstalls({
nextConfig: baseConfig,
writeOptions: { allowConfigSizeDrop: true },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
});
writeBaseHash = migrated.persistedHash ?? undefined;
nextConfig = stripPendingPluginInstallRecords(
nextConfig,
unchangedPendingPluginInstallRecordIds(nextConfig, baseConfig),
);
}
await commitConfigWriteWithPendingPluginInstalls({
await commitNonInteractiveOnboardConfig({
nextConfig,
writeOptions: { allowConfigSizeDrop },
commit: async (config, writeOptions) => {
return await replaceConfigFile({
nextConfig: config,
...(writeBaseHash !== undefined ? { baseHash: writeBaseHash } : {}),
...(writeOptions ? { writeOptions } : {}),
});
},
baseConfig,
baseHash,
reset: opts.reset,
});
logConfigUpdated(runtime);