From 5e2e78a75a9ef99cd428522f4cdae56eb8eaf5f6 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 30 May 2026 03:33:22 +0200 Subject: [PATCH] perf(wizard): cache setup migration imports --- src/wizard/setup.migration-import.ts | 34 ++++++++++++++++++---- src/wizard/setup.post-install-migration.ts | 22 +++++++++++--- src/wizard/setup.ts | 11 +++++-- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/wizard/setup.migration-import.ts b/src/wizard/setup.migration-import.ts index 376a91a1799..2639e32b2d2 100644 --- a/src/wizard/setup.migration-import.ts +++ b/src/wizard/setup.migration-import.ts @@ -27,6 +27,28 @@ const MEANINGFUL_WORKSPACE_ENTRIES = [ ] as const; const MEANINGFUL_STATE_ENTRIES = ["credentials", "sessions", "agents"] as const; +let migrationProviderRuntimeModulePromise: Promise< + typeof import("../plugins/migration-provider-runtime.js") +> | null = null; +let migrationContextModulePromise: Promise | null = + null; +let configPathsModulePromise: Promise | null = null; + +const loadMigrationProviderRuntimeModule = async () => { + migrationProviderRuntimeModulePromise ??= import("../plugins/migration-provider-runtime.js"); + return await migrationProviderRuntimeModulePromise; +}; + +const loadMigrationContextModule = async () => { + migrationContextModulePromise ??= import("../commands/migrate/context.js"); + return await migrationContextModulePromise; +}; + +const loadConfigPathsModule = async () => { + configPathsModulePromise ??= import("../config/paths.js"); + return await configPathsModulePromise; +}; + async function exists(candidate: string): Promise { try { await fs.access(candidate); @@ -99,9 +121,9 @@ export async function detectSetupMigrationSources(params: { { createMigrationLogger }, { resolveStateDir }, ] = await Promise.all([ - import("../plugins/migration-provider-runtime.js"), - import("../commands/migrate/context.js"), - import("../config/paths.js"), + loadMigrationProviderRuntimeModule(), + loadMigrationContextModule(), + loadConfigPathsModule(), ]); ensureStandaloneMigrationProviderRegistryLoaded({ cfg: params.config }); const stateDir = resolveStateDir(); @@ -160,7 +182,7 @@ async function selectSetupMigrationProvider(params: { ensureStandaloneMigrationProviderRegistryLoaded, resolvePluginMigrationProvider, resolvePluginMigrationProviders, - } = await import("../plugins/migration-provider-runtime.js"); + } = await loadMigrationProviderRuntimeModule(); ensureStandaloneMigrationProviderRegistryLoaded({ cfg: params.baseConfig }); const providers = resolvePluginMigrationProviders({ cfg: params.baseConfig }); if (providers.length === 0) { @@ -218,10 +240,10 @@ export async function runSetupMigrationImport(params: { onboardHelpers, ] = await Promise.all([ import("../commands/onboard-config.js"), - import("../commands/migrate/context.js"), + loadMigrationContextModule(), import("../commands/migrate/apply.js"), import("../commands/migrate/output.js"), - import("../config/paths.js"), + loadConfigPathsModule(), import("../commands/onboard-helpers.js"), ]); const { provider, providerId } = await selectSetupMigrationProvider({ diff --git a/src/wizard/setup.post-install-migration.ts b/src/wizard/setup.post-install-migration.ts index d63775f37dc..1c4fda4106d 100644 --- a/src/wizard/setup.post-install-migration.ts +++ b/src/wizard/setup.post-install-migration.ts @@ -33,6 +33,20 @@ type ResolvedProviderCandidate = { source?: string; }; +let migrationContextModulePromise: Promise | null = + null; +let configPathsModulePromise: Promise | null = null; + +const loadMigrationContextModule = async () => { + migrationContextModulePromise ??= import("../commands/migrate/context.js"); + return await migrationContextModulePromise; +}; + +const loadConfigPathsModule = async () => { + configPathsModulePromise ??= import("../config/paths.js"); + return await configPathsModulePromise; +}; + async function resolveCandidates(params: { config: OpenClawConfig; runtime: RuntimeEnv; @@ -49,8 +63,8 @@ async function resolveCandidates(params: { ] = await Promise.all([ import("../plugins/migration-provider-runtime.js"), import("../plugins/manifest-contract-runtime.js"), - import("../commands/migrate/context.js"), - import("../config/paths.js"), + loadMigrationContextModule(), + loadConfigPathsModule(), ]); ensureStandaloneMigrationProviderRegistryLoaded({ cfg: params.config }); const installedIds = new Set(params.installedPluginIds); @@ -194,8 +208,8 @@ export async function offerPostInstallMigrations( const [{ migrateDefaultCommand }, { createMigrationLogger }, { resolveStateDir }] = await Promise.all([ import("../commands/migrate.js"), - import("../commands/migrate/context.js"), - import("../config/paths.js"), + loadMigrationContextModule(), + loadConfigPathsModule(), ]); preparation = await candidate.provider.prepareApply?.({ config: nextConfig, diff --git a/src/wizard/setup.ts b/src/wizard/setup.ts index fdf4aa6e33d..0e0d490f4c5 100644 --- a/src/wizard/setup.ts +++ b/src/wizard/setup.ts @@ -40,10 +40,12 @@ type SetupFlowChoice = WizardFlow | "import"; type AuthChoiceModule = typeof import("../commands/auth-choice.js"); type ConfigLoggingModule = typeof import("../config/logging.js"); type ModelPickerModule = typeof import("../commands/model-picker.js"); +type OnboardConfigModule = typeof import("../commands/onboard-config.js"); let authChoiceModulePromise: Promise | undefined; let configLoggingModulePromise: Promise | undefined; let modelPickerModulePromise: Promise | undefined; +let onboardConfigModulePromise: Promise | undefined; function loadAuthChoiceModule(): Promise { authChoiceModulePromise ??= import("../commands/auth-choice.js"); @@ -60,6 +62,11 @@ function loadModelPickerModule(): Promise { return modelPickerModulePromise; } +function loadOnboardConfigModule(): Promise { + onboardConfigModulePromise ??= import("../commands/onboard-config.js"); + return onboardConfigModulePromise; +} + async function writeWizardConfigFile( config: OpenClawConfig, opts: { @@ -605,7 +612,7 @@ export async function runSetupWizard( if (mode === "remote") { const { promptRemoteGatewayConfig } = await import("../commands/onboard-remote.js"); - const { applySkipBootstrapConfig } = await import("../commands/onboard-config.js"); + const { applySkipBootstrapConfig } = await loadOnboardConfigModule(); const { logConfigUpdated } = await loadConfigLoggingModule(); let nextConfig = await promptRemoteGatewayConfig(baseConfig, prompter, { secretInputMode: opts.secretInputMode, @@ -634,7 +641,7 @@ export async function runSetupWizard( const workspaceDir = resolveUserPath(workspaceInput.trim() || onboardHelpers.DEFAULT_WORKSPACE); const { applyLocalSetupWorkspaceConfig, applySkipBootstrapConfig } = - await import("../commands/onboard-config.js"); + await loadOnboardConfigModule(); let nextConfig: OpenClawConfig = applyLocalSetupWorkspaceConfig(baseConfig, workspaceDir); if (opts.skipBootstrap) { nextConfig = applySkipBootstrapConfig(nextConfig);