From c3e629cbf40565e24b316bc648e89bcc2f9986f4 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 29 May 2026 03:36:56 +0200 Subject: [PATCH] refactor: share non-interactive onboard config writes --- .../onboard-non-interactive/config-write.ts | 51 +++++++++++++++++++ src/commands/onboard-non-interactive/local.ts | 45 +++------------- .../onboard-non-interactive/remote.ts | 43 ++-------------- 3 files changed, 62 insertions(+), 77 deletions(-) create mode 100644 src/commands/onboard-non-interactive/config-write.ts diff --git a/src/commands/onboard-non-interactive/config-write.ts b/src/commands/onboard-non-interactive/config-write.ts new file mode 100644 index 00000000000..152980c03b9 --- /dev/null +++ b/src/commands/onboard-non-interactive/config-write.ts @@ -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 { + // 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; +} diff --git a/src/commands/onboard-non-interactive/local.ts b/src/commands/onboard-non-interactive/local.ts index 2f406af3008..a3d11d1e96f 100644 --- a/src/commands/onboard-non-interactive/local.ts +++ b/src/commands/onboard-non-interactive/local.ts @@ -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, { diff --git a/src/commands/onboard-non-interactive/remote.ts b/src/commands/onboard-non-interactive/remote.ts index 001d39f2f66..51f32c03d8f 100644 --- a/src/commands/onboard-non-interactive/remote.ts +++ b/src/commands/onboard-non-interactive/remote.ts @@ -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);