UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

139 lines (138 loc) 5.81 kB
import { i as formatErrorMessage } from "./errors-BXgSefBE.js"; import { t as formatCliCommand } from "./command-format-CKGmlpAQ.js"; import { p as readMigrationConfigPatchDetails, y as writeMigrationConfigPath } from "./migration-CRXv-K-p.js"; //#region src/wizard/setup.post-install-migration.ts let migrationContextModulePromise = null; let configPathsModulePromise = null; const loadMigrationContextModule = async () => { migrationContextModulePromise ??= import("./context-lWhWMFgy.js"); return await migrationContextModulePromise; }; const loadConfigPathsModule = async () => { configPathsModulePromise ??= import("./paths-BiLl1Sm1.js"); return await configPathsModulePromise; }; async function resolveCandidates(params) { if (params.installedPluginIds.length === 0) return []; const [{ ensureStandaloneMigrationProviderRegistryLoaded, resolvePluginMigrationProviders }, { resolveManifestContractRuntimePluginResolution }, { createMigrationLogger }, { resolveStateDir }] = await Promise.all([ import("./migration-provider-runtime-DRWJd65t.js"), import("./manifest-contract-runtime-B9JZ2iHx.js"), loadMigrationContextModule(), loadConfigPathsModule() ]); ensureStandaloneMigrationProviderRegistryLoaded({ cfg: params.config }); const installedIds = new Set(params.installedPluginIds); const providers = resolvePluginMigrationProviders({ cfg: params.config }); const stateDir = resolveStateDir(); const logger = createMigrationLogger(params.runtime); const candidates = []; for (const provider of providers) { if (!provider.detect) continue; if (!resolveManifestContractRuntimePluginResolution({ cfg: params.config, contract: "migrationProviders", value: provider.id }).pluginIds.some((pluginId) => installedIds.has(pluginId))) continue; try { const detection = await provider.detect({ config: params.config, stateDir, logger }); if (!detection.found || detection.confidence === "low") continue; candidates.push({ provider, ...detection.source ? { source: detection.source } : {} }); } catch (error) { logger.debug?.(`Post-install migration detect for ${provider.id} failed: ${formatErrorMessage(error)}`); } } return candidates; } function describeCandidate(candidate) { const parts = [candidate.provider.label]; if (candidate.source) parts.push(`at ${candidate.source}`); return parts.join(" "); } function logMigrationHint(runtime, candidate) { const command = formatCliCommand(`openclaw migrate ${candidate.provider.id} --dry-run`); runtime.log(`Detected ${describeCandidate(candidate)}. Preview migration with ${command}.`); } function applyMigrationConfigPatches(config, result) { const patches = (result?.items ?? []).filter((item) => Boolean(item && typeof item === "object" && "kind" in item && item.kind === "config" && "action" in item && item.action === "merge" && "status" in item && item.status === "migrated")).map(readMigrationConfigPatchDetails).filter((patch) => patch !== void 0); if (patches.length === 0) return config; const nextConfig = structuredClone(config); for (const patch of patches) writeMigrationConfigPath(nextConfig, patch.path, patch.value); return nextConfig; } /** * Offer interactive migration for any migration provider owned by a plugin * that was just installed during onboarding. In non-interactive mode this is * a no-op apart from a hint line so scripted setups never mutate state * unexpectedly. The actual migration UI (skill/plugin checkboxes, confirm * prompt) is owned by `openclaw migrate <provider>`; this helper only owns * the gate prompt. */ async function offerPostInstallMigrations(params) { const candidates = await resolveCandidates({ config: params.config, runtime: params.runtime, installedPluginIds: params.installedPluginIds }); if (candidates.length === 0) return { config: params.config }; let nextConfig = params.config; const prompter = params.prompter; const interactive = params.nonInteractive !== true && process.stdin.isTTY && prompter !== void 0; for (const candidate of candidates) { if (!interactive || !prompter) { logMigrationHint(params.runtime, candidate); continue; } const description = describeCandidate(candidate); let accepted; try { accepted = await prompter.confirm({ message: `Migrate ${description} into this agent now?`, initialValue: false }); } catch (error) { params.runtime.log(`Skipping ${candidate.provider.label} migration prompt: ${formatErrorMessage(error)}`); logMigrationHint(params.runtime, candidate); continue; } if (!accepted) { logMigrationHint(params.runtime, candidate); continue; } let preparation = void 0; try { const [{ migrateDefaultCommand }, { createMigrationLogger }, { resolveStateDir }] = await Promise.all([ import("./migrate-CzOhVYZh.js"), loadMigrationContextModule(), loadConfigPathsModule() ]); preparation = await candidate.provider.prepareApply?.({ config: nextConfig, stateDir: resolveStateDir(), logger: createMigrationLogger(params.runtime), ...candidate.source ? { source: candidate.source } : {}, providerOptions: { configPatchMode: "return" } }); const result = await migrateDefaultCommand(params.runtime, { provider: candidate.provider.id, configOverride: nextConfig, configPatchMode: "return", suppressPlanLog: true }); nextConfig = applyMigrationConfigPatches(nextConfig, result); } catch (error) { params.runtime.log(`${candidate.provider.label} migration failed: ${formatErrorMessage(error)}. Re-run with ${formatCliCommand(`openclaw migrate ${candidate.provider.id} --dry-run`)} to inspect.`); } finally { await preparation?.dispose?.(); } } return { config: nextConfig }; } //#endregion export { offerPostInstallMigrations };