UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

2,303 lines 103 kB
import { f as withPluginCache, i as createPluginCache } from "./plugin-cache-DGWspMEc.js";
import "./src-vebZIeLe.js";
import { t as expectDefined } from "./expect-CyE8FADM.js";
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { c as resolveUserPath } from "./home-dir-BPhrG-aM.js";
import { b as createRuntimeConfigWriteApplication, v as attachRuntimeConfigWriteApplication } from "./io.runtime-B9iJRs3w.js";
import "./utils-P__uGsPB.js";
import { n as ok, t as err } from "./result-BQGgYouL.js";
import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js";
import { g as resolveAmbientOwnerAgentId, i as listAgentEntries, m as resolveAgentWorkspaceDir } from "./agent-scope-config-DcbEhP0R.js";
import "./session-key-BnWWjqNc.js";
import { t as formatErrorMessage } from "./errors-Db3Ymjlb.js";
import { c as normalizePluginTargetConfig } from "./config-state-BkU1frVq.js";
import { c as resolvePluginMetadataSnapshot } from "./plugin-metadata-snapshot-w-4EjxI4.js";
import { a as legacyModelKey, c as normalizeProviderId } from "./model-ref-shared-Dz7QU0Lx.js";
import { t as modelKey } from "./model-key-CMdQNkZf.js";
import { n as createMergePatch, t as applyMergePatch } from "./merge-patch-DCMj2JVh.js";
import { i as buildModelAliasIndex, y as resolveModelRefFromString } from "./model-selection-shared-BlLyx1r2.js";
import { t as splitTrailingAuthProfile } from "./model-ref-profile-BIKs-96s.js";
import { a as resolveAgentModelPrimaryValue, n as normalizeAgentModelRefForConfig } from "./model-input-BuGMCNOz.js";
import { o as resolveAgentEffectiveModelPrimary } from "./agent-scope-DbtJyKUL.js";
import { n as getActivePluginRegistryWorkspaceDirFromState } from "./runtime-state-Ccxn1fO9.js";
import { n as resolveProviderIdForAuth } from "./provider-auth-aliases-DhA9c2am.js";
import { n as enablePluginInConfig, r as enablePluginWithCapabilityConsent } from "./enable-3OwjFbBV.js";
import { _ as getPluginRegistryForContext } from "./runtime-BL4wZfTq.js";
import { i as captureGatewayRootWorkAdmissionContinuationScope } from "./gateway-work-admission-R1IpuDim.js";
import { a as loadPersistedAuthProfileStore } from "./persisted-B_qhhBlh.js";
import { t as readCodexCliActiveApiKey } from "./cli-credentials-CHuqM5pH.js";
import { n as withPluginRuntimeGenerationScope } from "./generation-scope-Cf83d_iq.js";
import { i as getPluginRuntimeLoadContext } from "./load-context-BdeWeJHL.js";
import { n as resolvePluginProvidersCore } from "./providers.runtime-DCovueHC.js";
import { S as updateAuthProfileStoreWithLock, f as loadAuthProfileStoreForRuntime } from "./store-F1B2duCT.js";
import { p as normalizeAuthProfileCredential } from "./profiles-DOTqXcYA.js";
import "./sessions-BdNAJTEP.js";
import { t as SessionManager } from "./session-manager-DO0bDxav.js";
import { a as resolveCliRuntimeCanonicalProvider, i as resolveCliBackendConfig } from "./cli-backends-Bs_a4MW0.js";
import { t as loadAgentRuntimePluginRegistryHandle } from "./runtime-plugins-BDPJ7y4t.js";
import "./model-selection-di2kjKCB.js";
import { n as resolveManifestProviderAuthChoice } from "./provider-auth-choices-DsRM415K.js";
import { a as supportsSetupTextInference, i as supportsSetupManualSecret } from "./setup-inference-auth-options-DDoD9isn.js";
import { c as SetupInferenceCancelledError, d as parseProviderAutoSetupChoiceId, f as redactSetupInferenceError, g as waitForProviderAuth, h as throwIfSetupInferenceCancelled, l as SetupInferenceOwnerDriftError, m as setupInferenceLog, o as SetupInferenceActivationIndeterminateError, p as resolveSetupInferenceWorkspace, r as AUTO_LOCAL_MODEL_LEAN_ANNOUNCEMENT, s as SetupInferenceActivationUnavailableError, u as invalidSetupConfigError } from "./setup-inference-detect-QZ_aVC2Y.js";
import { o as prepareSystemAgentRunAdmission } from "./admitted-run-context-CHY5SdVF.js";
import { i as describeFailoverError } from "./failover-error-BkNxlp8A.js";
import { t as buildAgentRuntimeAuthPlan } from "./auth-D2bx7kf3.js";
import { n as supportsModelTools } from "./model-tool-support-DIQSEumC.js";
import { i as appendSystemAgentAuditEntry } from "./audit-D3_LINzS.js";
import { t as CliExecutionAuthProfileError } from "./cli-execution-auth-BmnnNTfm.js";
import { i as sameDefaultInferenceRoute, n as projectInferenceRoute, r as resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route-fT4JRSHY.js";
import { a as resolveSystemAgentVerifiedInferenceRoute, n as createSystemAgentVerifiedInferenceBinding, r as hasCurrentSystemAgentOwnerPluginArtifacts, t as captureSystemAgentOwnerPluginArtifacts } from "./verified-inference-D8I0G1w6.js";
import { t as applyAutoLocalModelLean } from "./local-model-lean-auto-DgTezp-6.js";
import { t as withPluginLifecycleLease } from "./plugin-lifecycle-lease-BtAFH872.js";
import { t as createPluginCapabilityConsentPrompter } from "./plugin-capability-consent-CaBGom29.js";
import { n as WizardCancelledError, r as WizardNavigationError } from "./prompts-DLsO8MlU.js";
import { n as createQuickstartNotePrompter } from "./setup-apply-BVRZv42c.js";
import { n as createSystemAgentModelSelectionUpdater, t as applySystemAgentModelSelection } from "./setup-model-selection-C6YbZMxz.js";
import { n as prepareProviderAuthProfilesForPersistence } from "./provider-auth-persistence-BgUvISv3.js";
import { a as OPENAI_API_DEFAULT_MODEL_REF, i as GEMINI_CLI_DEFAULT_MODEL_REF, n as CLAUDE_CLI_DEFAULT_MODEL_REF, r as CODEX_APP_SERVER_DEFAULT_MODEL_REF, t as ANTHROPIC_API_DEFAULT_MODEL_REF } from "./onboard-inference-ambient-BvxNJ30C.js";
import "./onboard-inference-BTIb2cEv.js";
import { i as extractAgentRunText, r as extractAgentRunTerminalError } from "./agent-run-result-JlQhspoW.js";
import { a as runProviderPluginAuthMethodUnpersisted, n as applyProviderPluginAuthMethodResultConfig } from "./provider-auth-choice-DsHvi0o6.js";
import { isDeepStrictEqual } from "node:util";
import path from "node:path";
import fs from "node:fs/promises";
import os from "node:os";
import { randomUUID } from "node:crypto";
//#region src/system-agent/revalidate-inference-owner.ts
/** Setup owns fresh package facts without replacing the Gateway's startup generation. */
function loadSetupInferencePluginGeneration(params) {
	const preferBuiltPluginArtifacts = getPluginRuntimeLoadContext(getPluginRegistryForContext() ?? void 0)?.preferBuiltPluginArtifacts;
	return withPluginCache(createPluginCache(), () => {
		const generation = {
			config: params.config,
			metadataSnapshot: (params.resolvePluginMetadataSnapshot ?? resolvePluginMetadataSnapshot)({
				config: params.config,
				env: process.env,
				workspaceDir: params.workspaceDir,
				allowCurrent: false
			})
		};
		const pluginRegistry = withPluginRuntimeGenerationScope(generation, () => loadAgentRuntimePluginRegistryHandle({
			config: params.config,
			workspaceDir: params.workspaceDir,
			metadataSnapshot: generation.metadataSnapshot,
			preferBuiltPluginArtifacts,
			selections: [params.selection]
		}));
		if (!pluginRegistry) throw new Error(`Could not load the ${params.selection.runtime} runtime plugin.`);
		return {
			...generation,
			pluginRegistry
		};
	});
}
async function revalidateSetupInferenceOwner(params) {
	const configuredHarnessId = params.route.runner === "embedded" ? params.route.agentHarnessRuntimeOverride?.trim() : void 0;
	const successfulHarnessId = params.auth.agentHarnessId?.trim() || (configuredHarnessId && configuredHarnessId !== "auto" ? configuredHarnessId : void 0);
	const createBinding = () => (params.deps.createSystemAgentVerifiedInferenceBinding ?? createSystemAgentVerifiedInferenceBinding)({
		configuredRoute: params.route,
		executionRoute: params.route,
		auth: params.auth,
		deps: params.deps
	});
	if (params.route.runner === "embedded" && successfulHarnessId && successfulHarnessId !== "openclaw") {
		const workspaceDir = resolveAgentWorkspaceDir(params.route.runConfig, params.route.agentId, process.env);
		const generation = loadSetupInferencePluginGeneration({
			config: params.route.runConfig,
			workspaceDir,
			selection: {
				provider: params.route.provider,
				modelId: params.route.model,
				runtime: successfulHarnessId,
				agentId: params.route.agentId
			},
			resolvePluginMetadataSnapshot: params.deps.resolvePluginMetadataSnapshot
		});
		return await withPluginRuntimeGenerationScope(generation, createBinding);
	}
	return await createBinding();
}
//#endregion
//#region src/system-agent/setup-inference-persist.ts
async function cleanupSetupInferenceTempDir(params) {
	try {
		(params.deps.disposeOpenClawAgentDatabaseByPath ?? (await import("./openclaw-agent-db-Bfc4Wmxr.js")).disposeOpenClawAgentDatabaseByPath)(path.join(params.tempDir, "agent", "openclaw-agent.sqlite"));
	} catch {
		setupInferenceLog.warn("Could not dispose the temporary inference auth database.");
	}
	try {
		await (params.deps.removeTempDir ?? ((dir) => fs.rm(dir, {
			recursive: true,
			force: true
		})))(params.tempDir);
	} catch (error) {
		params.runtime?.error?.(`Could not remove temporary AI setup files: ${formatErrorMessage(error)}`);
		setupInferenceLog.warn("Could not remove the temporary inference test directory.");
	}
}
async function isCodexInstallRecordPersisted(record, deps) {
	try {
		const currentInstallRecords = await (deps.readPersistedInstalledPluginIndexInstallRecords ?? (await import("./installed-plugin-index-records-DGtSxIvi.js")).readPersistedInstalledPluginIndexInstallRecords)();
		return currentInstallRecords !== null && isDeepStrictEqual(currentInstallRecords.codex, record);
	} catch {
		return false;
	}
}
async function retainUnownedCodexInstall(params) {
	if (params.verifyOwnership && await isCodexInstallRecordPersisted(params.record, params.deps)) return true;
	if (params.record.source !== "npm" || !params.record.installPath?.trim()) return true;
	try {
		const marked = await (params.deps.markRetainedManagedNpmInstall ?? (await import("./managed-npm-retention-D-XbPuXW.js")).markRetainedManagedNpmInstall)({
			packageDir: params.record.installPath,
			pluginId: "codex",
			reason: "openclaw-inference-activation-not-committed"
		});
		if (!marked) setupInferenceLog.warn("Could not retain the uncommitted Codex runtime package generation.");
		return marked;
	} catch {
		setupInferenceLog.warn("Could not retain the uncommitted Codex runtime package generation.");
		return false;
	} finally {
		await clearUnownedCodexInstallCaches(params.deps);
	}
}
async function clearUnownedCodexInstallCaches(deps) {
	try {
		(deps.clearLoadInstalledPluginIndexInstallRecordsCache ?? (await import("./installed-plugin-index-records-DGtSxIvi.js")).clearLoadInstalledPluginIndexInstallRecordsCache)();
	} catch {
		setupInferenceLog.warn("Could not clear the plugin install-record cache after failed Codex activation.");
	}
	try {
		(deps.clearPluginMetadataLifecycleCaches ?? (await import("./plugin-metadata-lifecycle-DHzcnC3d.js")).clearPluginMetadataLifecycleCaches)();
	} catch {
		setupInferenceLog.warn("Could not clear plugin metadata caches after failed Codex activation.");
	}
	try {
		await (deps.invalidatePluginRuntimeDiscoveryAfterConfigMutation ?? (await import("./registry-refresh-x5mIxBEc.js")).invalidatePluginRuntimeDiscoveryAfterConfigMutation)({ logger: setupInferenceLog });
	} catch {
		setupInferenceLog.warn("Could not clear plugin runtime discovery after failed Codex activation.");
	}
}
async function restoreSetupPluginMetadata(params) {
	try {
		const snapshot = await params.readSnapshot();
		const sourceConfig = snapshot.exists && snapshot.valid ? snapshot.sourceConfig ?? snapshot.config : {};
		await (params.deps.refreshPluginRegistryAfterConfigMutation ?? (await import("./registry-refresh-x5mIxBEc.js")).refreshPluginRegistryAfterConfigMutation)({
			config: sourceConfig,
			reason: "source-changed",
			workspaceDir: params.workspaceDir,
			logger: setupInferenceLog
		});
	} catch {
		setupInferenceLog.warn("Could not restore plugin metadata after the inference setup probe.");
	}
}
function isMergePatchObject(value) {
	return isRecord(value);
}
function mergePatchConflicts(base, current, patch) {
	if (!isMergePatchObject(patch)) return !isDeepStrictEqual(base, current);
	const baseIsObject = isMergePatchObject(base);
	const currentIsObject = isMergePatchObject(current);
	if (baseIsObject !== currentIsObject) return true;
	if (!baseIsObject && !currentIsObject && !isDeepStrictEqual(base, current)) return true;
	const baseRecord = baseIsObject ? base : {};
	const currentRecord = currentIsObject ? current : {};
	return Object.entries(patch).some(([key, childPatch]) => mergePatchConflicts(baseRecord[key], currentRecord[key], childPatch));
}
function applyManualAuthConfig(config, manualAuth, configKind, enablePlugin = enablePluginInConfig) {
	let enabledConfig = config;
	if (manualAuth.pluginId) {
		const enableResult = enablePlugin(config, manualAuth.pluginId);
		if (!enableResult.enabled) throw new Error(`Provider plugin ${manualAuth.pluginId} is ${enableResult.reason}.`);
		enabledConfig = enableResult.config;
	}
	if (mergePatchConflicts(configKind === "runtime" ? manualAuth.runtimeConfigBase : manualAuth.sourceConfigBase, enabledConfig, manualAuth.configPatch)) throw new Error("Provider configuration changed during the live inference test, so the verified credential was not saved. Review the current provider settings and retry.");
	return applyMergePatch(enabledConfig, manualAuth.configPatch);
}
function modelSelectionReferencesProfile(value, profileIds) {
	if (typeof value === "string") {
		const profile = splitTrailingAuthProfile(value).profile;
		return profile !== void 0 && profileIds.has(profile);
	}
	if (!isMergePatchObject(value)) return false;
	if (modelSelectionReferencesProfile(value.primary, profileIds)) return true;
	return Array.isArray(value.fallbacks) && value.fallbacks.some((fallback) => modelSelectionReferencesProfile(fallback, profileIds));
}
function configReferencesManualAuthProfiles(config, receipt) {
	const profileIds = new Set(receipt.profiles.map((profile) => profile.profileId));
	if (Object.keys(config.auth?.profiles ?? {}).some((profileId) => profileIds.has(profileId))) return true;
	if (Object.values(config.auth?.order ?? {}).some((order) => order.some((profileId) => profileIds.has(profileId)))) return true;
	if (modelSelectionReferencesProfile(config.agents?.defaults?.model, profileIds)) return true;
	return listAgentEntries(config).some((agent) => modelSelectionReferencesProfile(agent.model, profileIds));
}
function readManualAuthProfiles(receipt, deps) {
	let store;
	try {
		store = (deps.loadPersistedAuthProfileStore ?? loadPersistedAuthProfileStore)(receipt.agentDir);
	} catch {
		return "unknown";
	}
	if (!store) return "unknown";
	if (receipt.profiles.every((profile) => isDeepStrictEqual(store.profiles[profile.profileId], profile.credential))) return "present";
	if (receipt.profiles.every((profile) => store.profiles[profile.profileId] === void 0)) return "absent";
	return "mismatch";
}
function manualAuthProfilesPersisted(receipt, deps) {
	return readManualAuthProfiles(receipt, deps) === "present";
}
async function persistManualAuthProfiles(params) {
	const prepared = params.secretStorage ? prepareProviderAuthProfilesForPersistence({
		profiles: params.profiles,
		config: params.secretStorage.config,
		...params.secretStorage.env ? { env: params.secretStorage.env } : {}
	}) : {
		profiles: [...params.profiles],
		rollback: () => {}
	};
	const profiles = prepared.profiles.map((profile) => ({
		profileId: profile.profileId,
		credential: normalizeAuthProfileCredential(profile.credential)
	}));
	const insertedProfileIds = /* @__PURE__ */ new Set();
	const receipt = {
		agentDir: params.agentDir,
		profiles,
		insertedProfileIds,
		rollbackProtectedSecretStorage: prepared.rollback
	};
	let collision = false;
	const updated = await (params.deps.updateAuthProfileStoreWithLock ?? updateAuthProfileStoreWithLock)({
		agentDir: params.agentDir,
		saveOptions: {
			filterExternalAuthProfiles: false,
			syncExternalCli: false
		},
		updater: (store) => {
			let changed = false;
			for (const profile of profiles) {
				const existing = store.profiles[profile.profileId];
				if (existing && !isDeepStrictEqual(existing, profile.credential)) {
					collision = true;
					return false;
				}
				if (!existing) {
					store.profiles[profile.profileId] = profile.credential;
					insertedProfileIds.add(profile.profileId);
					changed = true;
				}
			}
			return changed;
		}
	});
	if (collision) {
		prepared.rollback();
		return { status: "not-persisted" };
	}
	const readback = readManualAuthProfiles(receipt, params.deps);
	if (updated !== null || readback === "present") return {
		status: "persisted",
		receipt
	};
	if (readback === "absent") {
		prepared.rollback();
		return { status: "not-persisted" };
	}
	return {
		status: "unknown",
		receipt
	};
}
function rollbackManualAuthSecretStorage(receipt) {
	try {
		receipt.rollbackProtectedSecretStorage();
		return true;
	} catch {
		return false;
	}
}
async function rollbackManualAuthProfiles(receipt, deps) {
	if (receipt.insertedProfileIds.size === 0) return rollbackManualAuthSecretStorage(receipt);
	const update = deps.updateAuthProfileStoreWithLock ?? updateAuthProfileStoreWithLock;
	for (let attempt = 0; attempt < 3; attempt += 1) {
		let updated = null;
		try {
			updated = await update({
				agentDir: receipt.agentDir,
				saveOptions: {
					filterExternalAuthProfiles: false,
					syncExternalCli: false
				},
				updater: (store) => {
					let changed = false;
					for (const profile of receipt.profiles) {
						if (!receipt.insertedProfileIds.has(profile.profileId)) continue;
						if (isDeepStrictEqual(store.profiles[profile.profileId], profile.credential)) {
							delete store.profiles[profile.profileId];
							changed = true;
						}
					}
					return changed;
				}
			});
		} catch {}
		if (updated && receipt.profiles.every((profile) => !receipt.insertedProfileIds.has(profile.profileId) || updated.profiles[profile.profileId] === void 0)) return rollbackManualAuthSecretStorage(receipt);
		let persistedStore;
		try {
			persistedStore = (deps.loadPersistedAuthProfileStore ?? loadPersistedAuthProfileStore)(receipt.agentDir);
		} catch {
			persistedStore = null;
		}
		if (persistedStore && receipt.profiles.every((profile) => !receipt.insertedProfileIds.has(profile.profileId) || persistedStore.profiles[profile.profileId] === void 0)) return rollbackManualAuthSecretStorage(receipt);
	}
	return false;
}
//#endregion
//#region src/system-agent/setup-inference-plan-helpers.ts
function configureCodexCliPreparedAuth(cfg, homeScope) {
	const entry = cfg.plugins?.entries?.codex;
	const pluginConfig = entry?.config ?? {};
	const appServer = pluginConfig.appServer && typeof pluginConfig.appServer === "object" ? pluginConfig.appServer : {};
	const transport = "transport" in appServer ? appServer.transport : void 0;
	if (typeof transport === "string" && transport !== "stdio") return err(`Codex setup needs a local stdio app-server for prepared sign-in, but plugins.entries.codex.config.appServer.transport is "${transport}". Remove that transport override to let setup manage a local Codex, or finish Codex sign-in on the remote app-server host and retry.`);
	return ok({
		...cfg,
		plugins: {
			...cfg.plugins,
			entries: {
				...cfg.plugins?.entries,
				codex: {
					...entry,
					config: {
						...pluginConfig,
						appServer: {
							...appServer,
							transport: "stdio",
							homeScope
						}
					}
				}
			}
		}
	});
}
async function extractRunWinnerError(plan, result) {
	const winnerProvider = result.meta?.executionTrace?.winnerProvider?.trim();
	const winnerModel = result.meta?.executionTrace?.winnerModel?.trim();
	if (!winnerProvider || !winnerModel) return "The inference run did not report which provider and model produced its reply.";
	if (winnerProvider === plan.provider) {
		if (winnerModel === plan.model) return;
		const { resolveDirectBundledProviderPolicySurface } = await import("./provider-policy-surface-DyuAVcbb.js");
		if (resolveDirectBundledProviderPolicySurface(plan.provider)?.isResponseModelEquivalent?.({
			provider: plan.provider,
			requestedModelId: plan.model,
			responseModelId: winnerModel
		}) === true) return;
	}
	return `The inference run answered through ${winnerProvider}/${winnerModel} instead of the requested ${plan.provider}/${plan.model}. Disable model-routing overrides or choose the working route directly, then retry.`;
}
function resolveToolFreeCliSetupError(plan) {
	if (plan.runner !== "cli") return;
	const backend = resolveCliBackendConfig(plan.provider, plan.config, plan.agentId ? { agentId: plan.agentId } : {});
	if (backend?.sideQuestionToolMode === "disabled") return;
	const geminiCliProvider = parseRef(GEMINI_CLI_DEFAULT_MODEL_REF).provider;
	if (backend?.nativeToolMode === "none" && plan.provider !== geminiCliProvider) return;
	return plan.provider === geminiCliProvider ? "Gemini CLI cannot be used for inference-gated setup because it has no hard tool-free mode. Choose Claude Code, Codex, or an API-key provider; normal Gemini CLI agent runs remain available after setup." : `CLI backend ${backend?.id ?? plan.provider} cannot be used for inference-gated setup because it has no hard tool-free mode. Choose another inference provider.`;
}
function resolveStrictSetupAuthProfileError(params) {
	const profileId = params.plan.authProfileId?.trim();
	if (!profileId) return;
	const credential = (params.deps.loadAuthProfileStoreForRuntime ?? loadAuthProfileStoreForRuntime)(params.plan.agentDir, {
		readOnly: true,
		allowKeychainPrompt: false,
		config: params.plan.config,
		externalCliProviderIds: [params.plan.provider]
	}).profiles[profileId];
	if (!credential) return `No credentials found for the configured setup profile "${profileId}".`;
	if (params.plan.runner === "embedded") {
		if (buildAgentRuntimeAuthPlan({
			provider: params.plan.provider,
			authProfileProvider: credential.provider,
			authProfileMode: credential.type,
			sessionAuthProfileId: profileId,
			config: params.plan.config,
			workspaceDir: params.workspaceDir,
			harnessId: params.plan.agentHarnessRuntimeOverride,
			harnessRuntime: params.plan.agentHarnessRuntimeOverride,
			allowHarnessAuthProfileForwarding: true
		}).forwardedAuthProfileId === profileId) return;
	} else {
		const aliasContext = {
			config: params.plan.config,
			workspaceDir: params.workspaceDir
		};
		try {
			if (resolveProviderIdForAuth(params.plan.provider, aliasContext) === resolveProviderIdForAuth(credential.provider, aliasContext)) return;
		} catch {
			return `Could not verify that configured setup profile "${profileId}" belongs to the selected ${params.plan.provider} inference route.`;
		}
	}
	return `Configured setup profile "${profileId}" belongs to ${credential.provider}, not the selected ${params.plan.provider} inference route.`;
}
function parseRef(modelRef) {
	const slash = modelRef.indexOf("/");
	return slash === -1 ? {
		provider: modelRef,
		model: ""
	} : {
		provider: modelRef.slice(0, slash),
		model: modelRef.slice(slash + 1)
	};
}
function projectSetupTargetModelMetadata(config, modelRef, agentId) {
	const target = parseRef(modelRef);
	const canonicalKey = modelKey(target.provider, target.model);
	const keys = new Set([
		canonicalKey,
		legacyModelKey(target.provider, target.model),
		`${target.provider}/${canonicalKey}`
	].filter((key) => Boolean(key)));
	const project = (models) => Object.fromEntries([...keys].map((key) => [key, Object.hasOwn(models ?? {}, key) ? {
		exists: true,
		value: structuredClone(models?.[key])
	} : { exists: false }]));
	const defaultAgentId = resolveAmbientOwnerAgentId(config, agentId);
	const agent = listAgentEntries(config).find((entry) => normalizeAgentId(entry.id) === defaultAgentId);
	return {
		defaultAgentId,
		defaults: project(config.agents?.defaults?.models),
		agent: project(agent?.models)
	};
}
function resolveSetupAgentRuntimeId(kind) {
	if (kind === "claude-cli") return "claude-cli";
	if (kind === "codex-cli") return "codex";
	if (kind === "openai-api-key" || kind === "anthropic-api-key" || kind === "api-key" || kind === "provider-auth" || parseProviderAutoSetupChoiceId(kind) !== void 0) return "openclaw";
}
const SETUP_STATUS_BY_FAILOVER_REASON = {
	auth: "auth",
	auth_permanent: "auth",
	format: "format",
	rate_limit: "rate_limit",
	overloaded: "rate_limit",
	billing: "billing",
	server_error: "unknown",
	timeout: "timeout",
	tls_certificate: "unknown",
	context_overflow: "unknown",
	model_not_found: "format",
	session_expired: "unknown",
	empty_response: "unknown",
	no_error_details: "unknown",
	unclassified: "unknown",
	unknown: "unknown"
};
function mapFailoverReasonToSetupStatus(reason) {
	return reason ? SETUP_STATUS_BY_FAILOVER_REASON[reason] ?? "unknown" : "unknown";
}
function prepareManualAuthForActivation(params) {
	const selectedProfile = params.profiles.find((profile) => profile.profileId === params.selectedProfileId);
	if (!selectedProfile) throw new Error("The selected setup credential was not returned by its provider.");
	const selectedProfileId = `${normalizeProviderId(selectedProfile.credential.provider) || "provider"}:setup-${randomUUID()}`;
	const profile = {
		...selectedProfile,
		profileId: selectedProfileId
	};
	return {
		config: projectManualInferenceConfig({
			...params,
			selectedProfile,
			selectedProfileId
		}),
		profiles: [profile],
		selectedProfileId
	};
}
function copySelectedModelMetadata(params) {
	const preparedDefaultModels = params.prepared.agents?.defaults?.models;
	if (preparedDefaultModels && Object.hasOwn(preparedDefaultModels, params.modelRef)) params.target.agents = {
		...params.target.agents,
		defaults: {
			...params.target.agents?.defaults,
			models: {
				...params.target.agents?.defaults?.models,
				[params.modelRef]: structuredClone(expectDefined(preparedDefaultModels[params.modelRef], "prepared default models entry at params.model ref"))
			}
		}
	};
	const defaultAgentId = resolveAmbientOwnerAgentId(params.target, params.agentId);
	const preparedAgent = listAgentEntries(params.prepared).find((agent) => normalizeAgentId(agent.id) === defaultAgentId);
	if (!preparedAgent?.models || !Object.hasOwn(preparedAgent.models, params.modelRef)) return;
	const targetEntryKey = Object.keys(params.target.agents?.entries ?? {}).find((agentId) => normalizeAgentId(agentId) === defaultAgentId);
	if (!targetEntryKey || !params.target.agents?.entries?.[targetEntryKey]) return;
	const nextEntries = structuredClone(params.target.agents.entries);
	const targetAgent = expectDefined(nextEntries[targetEntryKey], "target agent entry");
	targetAgent.models = {
		...targetAgent.models,
		[params.modelRef]: structuredClone(expectDefined(preparedAgent.models[params.modelRef], "models entry at params.model ref"))
	};
	params.target.agents = {
		...params.target.agents,
		entries: nextEntries
	};
}
function findSelectedProviderConfigKey(config, providerId) {
	const providers = config.models?.providers;
	if (!providers) return;
	if (Object.hasOwn(providers, providerId)) return providerId;
	const normalizedProvider = normalizeProviderId(providerId);
	return Object.keys(providers).find((candidate) => normalizeProviderId(candidate) === normalizedProvider);
}
/**
* Provider auth hooks are untrusted setup input. Carry only the selected
* inference route's config into the probe; OpenClaw owns every other setup
* surface after intelligence exists.
*/
function projectManualInferenceConfig(params) {
	const config = structuredClone(params.baseConfig);
	if (params.selectedProfile && params.selectedProfileId) {
		const metadata = params.preparedConfig.auth?.profiles?.[params.selectedProfile.profileId] ?? {
			provider: params.selectedProfile.credential.provider,
			mode: params.selectedProfile.credential.type
		};
		config.auth = {
			...config.auth,
			profiles: {
				...config.auth?.profiles,
				[params.selectedProfileId]: structuredClone(metadata)
			}
		};
	}
	const providerConfigKey = findSelectedProviderConfigKey(params.preparedConfig, params.providerId);
	if (providerConfigKey) {
		const preparedProvider = params.preparedConfig.models?.providers?.[providerConfigKey];
		if (preparedProvider === void 0) throw new Error(`Prepared provider config missing for ${providerConfigKey}`);
		config.models = {
			...config.models,
			providers: {
				...config.models?.providers,
				[providerConfigKey]: structuredClone(preparedProvider)
			}
		};
	}
	if (params.pluginId) {
		const preparedEntry = params.preparedConfig.plugins?.entries?.[params.pluginId];
		if (preparedEntry !== void 0) config.plugins = {
			...config.plugins,
			entries: {
				...config.plugins?.entries,
				[params.pluginId]: structuredClone(preparedEntry)
			}
		};
	}
	copySelectedModelMetadata({
		target: config,
		prepared: params.preparedConfig,
		modelRef: params.modelRef,
		...params.agentId ? { agentId: params.agentId } : {}
	});
	return config;
}
function canonicalizeSetupModelRef(params) {
	const aliasIndex = buildModelAliasIndex({
		cfg: params.cfg,
		defaultProvider: params.defaultProvider
	});
	const resolved = resolveModelRefFromString({
		cfg: params.cfg,
		raw: params.raw,
		defaultProvider: params.defaultProvider,
		aliasIndex
	});
	return resolved ? `${resolved.ref.provider}/${resolved.ref.model}` : params.raw;
}
//#endregion
//#region src/system-agent/setup-inference-probe.ts
const SETUP_INFERENCE_TEST_MAX_TOKENS = 256;
/** Plugin and auto-selected harnesses may not support OpenClaw's request-scoped token cap. */
function resolveSetupInferenceProbeStreamParams(agentHarnessId) {
	return !agentHarnessId || agentHarnessId === "openclaw" ? { streamParams: { maxTokens: SETUP_INFERENCE_TEST_MAX_TOKENS } } : {};
}
//#endregion
//#region src/system-agent/setup-inference-test.ts
async function runSetupInferenceTest(params) {
	const connection = await runSetupInferenceProbe(params);
	const provider = params.plan.config.models?.providers?.[params.plan.provider];
	const model = provider?.models.find((entry) => entry.id === params.plan.model);
	if (!connection.ok || !params.verifyAgentTools || params.prompt !== void 0 || params.plan.runner !== "embedded" || !provider?.localService || !supportsModelTools(model ?? {})) return connection;
	const workspace = await fs.realpath(await fs.mkdtemp(path.join(params.tempDir, "agent-check-")));
	let acceptingResults = true;
	try {
		const nonce = randomUUID();
		const fixture = path.join(workspace, "verification.txt");
		await fs.writeFile(fixture, nonce, { mode: 384 });
		let observedRead = false;
		const verified = await runSetupInferenceProbe({
			...params,
			tempDir: workspace,
			plan: {
				...params.plan,
				...connection.auth.authProfileId ? { authProfileId: connection.auth.authProfileId } : {}
			},
			prompt: `Read ${JSON.stringify(fixture)} using the available tools. Reply with the complete file contents. Do not modify files or perform any other task.`
		}, { onAgentToolResult: ({ toolName, result, isError }) => {
			if (!acceptingResults || toolName !== "read" || isError || !isRecord(result) || !Array.isArray(result.content)) return;
			observedRead ||= result.content.some((item) => isRecord(item) && item.type === "text" && typeof item.text === "string" && item.text.includes(nonce));
		} });
		if (!verified.ok) return verified;
		if (!observedRead || !verified.text.includes(nonce)) return {
			ok: false,
			status: "format",
			error: "The local model answered a simple prompt but could not read and return a file through an OpenClaw tool. Choose another model or review its tool support, then retry setup. No default model was changed."
		};
		if (!isDeepStrictEqual(connection.auth, verified.auth)) return {
			ok: false,
			status: "auth",
			error: "The local model's execution owner changed during tool verification. Retry setup before selecting it as the default."
		};
		return {
			...verified,
			latencyMs: connection.latencyMs + verified.latencyMs
		};
	} finally {
		acceptingResults = false;
		await fs.rm(workspace, {
			recursive: true,
			force: true
		}).catch(() => {
			setupInferenceLog.warn("Could not remove the temporary local model verification file.");
		});
	}
}
async function runSetupInferenceProbe(params, agentProbe) {
	const { plan, tempDir, deps, authProfileStateMode, requireExecutionOwner } = params;
	const runId = `probe-setup-inference-${randomUUID()}`;
	const sessionId = runId;
	const sessionFile = `in-memory:${sessionId}`;
	const sessionManager = SessionManager.inMemory(tempDir);
	const effectiveAgentId = plan.routeAgentId ?? plan.agentId ?? "openclaw";
	const sessionKey = `agent:${effectiveAgentId}:setup-inference:incognito-${runId}`;
	const timeoutMs = deps.timeoutMs ?? 9e4;
	const started = Date.now();
	const phase = agentProbe ? "tool-use" : "response";
	const failed = (status, error) => {
		setupInferenceLog.warn("Inference setup probe failed.", {
			event: "setup_inference_probe_failed",
			provider: plan.provider,
			model: plan.model,
			runner: plan.runner,
			runId,
			phase,
			status,
			timeoutMs,
			durationMs: Date.now() - started
		});
		return {
			ok: false,
			status,
			error: status === "timeout" ? `The setup ${phase} check timed out. Retry setup, or choose another model or runtime. No default model was changed.` : error
		};
	};
	const preparedRunAdmission = prepareSystemAgentRunAdmission(plan.config, runId, effectiveAgentId, "system-agent.setup-inference");
	let successfulAuth;
	try {
		if (plan.runner === "cli") {
			const unsupportedError = resolveToolFreeCliSetupError(plan);
			if (unsupportedError) return failed("unavailable", unsupportedError);
		}
		const strictProfileError = resolveStrictSetupAuthProfileError({
			plan,
			workspaceDir: tempDir,
			deps
		});
		if (strictProfileError) return failed("auth", strictProfileError);
		let result;
		if (plan.runner === "cli") result = await (deps.runCliAgent ?? (await import("./cli-runner-msdgHSKR.js")).runCliAgent)({
			preparedRunAdmission,
			sessionId,
			sessionKey,
			sessionManager,
			agentId: effectiveAgentId,
			trigger: "manual",
			sessionFile,
			workspaceDir: tempDir,
			...plan.agentDir ? { agentDir: plan.agentDir } : {},
			config: plan.executionConfig ?? plan.config,
			prompt: params.prompt ?? "Reply with the single word OK. Do not use tools.",
			provider: plan.provider,
			model: plan.model,
			...plan.authProfileId ? { authProfileId: plan.authProfileId } : {},
			timeoutMs,
			runId,
			messageChannel: "openclaw",
			messageProvider: "openclaw",
			executionMode: "side-question",
			disableTools: true,
			cleanupCliLiveSessionOnRunEnd: true,
			onSuccessfulAuthBinding: (binding) => {
				successfulAuth = binding;
			},
			...params.signal ? { abortSignal: params.signal } : {}
		});
		else {
			const runEmbedded = deps.runEmbeddedAgent ?? (await import("./embedded-agent-CUhbhIMN.js")).runEmbeddedAgent;
			const executionConfig = plan.executionConfig ?? plan.config;
			result = await runEmbedded({
				preparedRunAdmission,
				sessionId,
				sessionKey,
				sessionManager,
				sessionPersistence: "detached",
				agentId: effectiveAgentId,
				trigger: "manual",
				sessionFile,
				workspaceDir: tempDir,
				...plan.agentDir ? { agentDir: plan.agentDir } : {},
				config: agentProbe ? {
					...executionConfig,
					agents: {
						...executionConfig.agents,
						entries: {
							...executionConfig.agents?.entries,
							[effectiveAgentId]: {
								...executionConfig.agents?.entries?.[effectiveAgentId],
								workspace: tempDir,
								contextInjection: "never"
							}
						}
					}
				} : executionConfig,
				prompt: params.prompt ?? "Reply with the single word OK. Do not use tools.",
				provider: plan.provider,
				model: plan.model,
				...plan.authProfileId ? {
					authProfileId: plan.authProfileId,
					authProfileIdSource: "user"
				} : {},
				authProfileStateMode,
				preparedModelRuntimeMode: "isolated-read-only",
				...plan.cleanupBundleMcpOnRunEnd ? { cleanupBundleMcpOnRunEnd: true } : {},
				...plan.agentHarnessRuntimeOverride ? { agentHarnessRuntimeOverride: plan.agentHarnessRuntimeOverride } : {},
				timeoutMs,
				runId,
				lane: `session:probe-setup-inference:${plan.provider}`,
				thinkLevel: "off",
				reasoningLevel: "off",
				verboseLevel: "off",
				disableTrajectory: true,
				...params.prompt === void 0 ? resolveSetupInferenceProbeStreamParams(plan.agentHarnessRuntimeOverride) : {},
				...agentProbe ? {
					permissionMode: "read-only",
					sessionRoot: tempDir,
					toolsAllow: ["read"],
					toolExecutionAllow: ["read"],
					onAgentToolResult: agentProbe.onAgentToolResult
				} : {
					disableTools: true,
					modelRun: true
				},
				messageChannel: "openclaw",
				messageProvider: "openclaw",
				onSuccessfulAuthBinding: (binding) => {
					successfulAuth = binding;
				},
				...params.signal ? { abortSignal: params.signal } : {}
			});
		}
		if (params.signal?.aborted) throw new SetupInferenceCancelledError();
		const terminalError = extractAgentRunTerminalError(result);
		if (terminalError) {
			const described = describeFailoverError(new Error(terminalError));
			return failed(mapFailoverReasonToSetupStatus(described.reason), described.message);
		}
		const text = extractAgentRunText(result)?.trim();
		if (!text) return failed("format", "The model started but did not send a reply. Try again or pick another option.");
		const winnerError = await extractRunWinnerError(plan, result);
		if (winnerError) return failed("unknown", winnerError);
		if (requireExecutionOwner && !successfulAuth) return failed("unknown", "Inference succeeded, but its runtime did not report an owner that OpenClaw can safely reuse.");
		return {
			ok: true,
			latencyMs: Date.now() - started,
			text,
			auth: successfulAuth ?? (!requireExecutionOwner && plan.authProfileId ? { authProfileId: plan.authProfileId } : {})
		};
	} catch (error) {
		const described = describeFailoverError(error);
		return failed(mapFailoverReasonToSetupStatus(described.reason), described.message);
	} finally {
		preparedRunAdmission.close();
	}
}
//#endregion
//#region src/system-agent/setup-inference-activate-persist.ts
async function persistActivatedSetupInference(input) {
	const { params, deps, plan, testPlan, test, codexPluginPatch, pendingCodexInstall, cfg, sourceCfg, verifiedRoute, baselineRoute, stagedRoute, stagedOwnerPluginArtifacts, baselineTargetModelMetadata, sourceTargetModelMetadata, routeDeps, readSnapshot, hasPreparedAuthProfiles, state, revalidateOwner } = input;
	let committedConfig;
	let { codexInstallOwnership } = state;
	const requestedAgentId = params.agentId ? testPlan.routeAgentId : void 0;
	const projectRoute = (config) => projectInferenceRoute(config, requestedAgentId, routeDeps);
	const resolveRoute = (config) => resolveSystemAgentConfiguredRouteFromConfig(config, requestedAgentId, routeDeps);
	const { stripPendingPluginInstallRecords } = await import("./install-record-commit-DVoT_zjZ.js");
	const agentRuntimeId = resolveSetupAgentRuntimeId(params.kind);
	const selectModel = plan.persistModelRef ? await createSystemAgentModelSelectionUpdater({
		model: plan.persistModelRef,
		...params.agentId ? { targetAgentId: testPlan.routeAgentId } : {},
		...agentRuntimeId ? { agentRuntimeId } : {},
		...plan.manualAuth && plan.authProfileId ? { authProfileId: plan.authProfileId } : {}
	}) : void 0;
	const stageCandidate = (current, configKind) => {
		let next = codexPluginPatch === void 0 ? current : stripPendingPluginInstallRecords(current);
		if (plan.manualAuth) next = applyManualAuthConfig(next, plan.manualAuth, configKind, deps.enablePluginInConfig ?? enablePluginInConfig);
		if (codexPluginPatch !== void 0) {
			const patched = applyMergePatch(next, codexPluginPatch);
			const enabledCodex = enablePluginInConfig(normalizePluginTargetConfig(patched, "codex"), "codex");
			if (!enabledCodex.enabled) throw new SetupInferenceActivationUnavailableError(`Could not enable the Codex runtime plugin: ${enabledCodex.reason ?? "plugin disabled"}.`);
			next = enabledCodex.config;
		}
		const autoLocalModelLean = applyAutoLocalModelLean({
			config: next,
			providerId: testPlan.provider,
			modelRef: plan.modelRef,
			previousModelRef: resolveAgentModelPrimaryValue(current.agents?.defaults?.model)
		});
		next = selectModel ? selectModel(autoLocalModelLean.config) : autoLocalModelLean.config;
		return {
			config: pendingCodexInstall ? {
				...next,
				plugins: {
					...next.plugins,
					installs: { codex: pendingCodexInstall }
				}
			} : next,
			autoLocalModelLeanApplied: autoLocalModelLean.enabled
		};
	};
	const persistedRoute = pendingCodexInstall ? await projectRoute(stripPendingPluginInstallRecords(stageCandidate(cfg, "runtime").config)) : verifiedRoute;
	const expectedSourceCandidateRoute = await projectRoute(stageCandidate(sourceCfg, "source").config);
	const transformConfig = deps.transformConfigWithPendingPluginInstalls ?? (await import("./install-record-commit-DVoT_zjZ.js")).transformConfigWithPendingPluginInstalls;
	let manualAuthReceipt;
	if (hasPreparedAuthProfiles && plan.manualAuth) {
		throwIfSetupInferenceCancelled(params);
		await params.beforePersistentEffect?.();
		throwIfSetupInferenceCancelled(params);
		const initialCandidate = stageCandidate(cfg, "runtime").config;
		const initialRoute = await projectRoute(initialCandidate);
		const resolvedRoute = await resolveRoute(initialCandidate);
		if (!sameDefaultInferenceRoute(initialRoute, verifiedRoute) || !resolvedRoute || resolvedRoute.modelLabel !== (plan.persistModelRef ?? plan.modelRef) || resolvedRoute.authProfileId !== plan.authProfileId) throw new Error("The default-agent inference route changed during its live test, so the verified credential was not saved. Review the current model/auth/runtime settings and retry.");
		const persistedManualAuth = await persistManualAuthProfiles({
			profiles: plan.manualAuth.profiles,
			agentDir: resolvedRoute.agentDir,
			deps,
			secretStorage: {
				config: initialCandidate,
				env: process.env
			}
		});
		if (persistedManualAuth.status === "unknown") {
			if (await rollbackManualAuthProfiles(persistedManualAuth.receipt, deps)) return {
				ok: false,
				status: "unknown",
				error: "Could not confirm the credential write, so it was rolled back. Try again in a moment."
			};
			throw new SetupInferenceActivationIndeterminateError("Inference activation could not confirm whether its verified credential was saved or rolled back. No config commit was attempted; run openclaw doctor --fix before retrying.");
		}
		if (persistedManualAuth.status === "not-persisted") return {
			ok: false,
			status: "unknown",
			error: "Could not save the verified credential; try again in a moment."
		};
		manualAuthReceipt = persistedManualAuth.receipt;
	}
	const application = params.onRuntimeApplication ? createRuntimeConfigWriteApplication(captureGatewayRootWorkAdmissionContinuationScope()?.run) : void 0;
	if (application) params.onRuntimeApplication?.(application);
	let commitMayHaveStarted = false;
	try {
		throwIfSetupInferenceCancelled(params);
		const committed = await transformConfig({
			base: "source",
			...application ? { writeOptions: attachRuntimeConfigWriteApplication({}, application) } : {},
			transform: async (current, context) => {
				const latestRuntime = context.snapshot.runtimeConfig ?? context.snapshot.config;
				const stagedRuntime = stageCandidate(latestRuntime, "runtime").config;
				const latestBaseline = await projectRoute(latestRuntime);
				if (!sameDefaultInferenceRoute(latestBaseline, baselineRoute)) throw new Error("The default-agent inference route changed during its live test, so the verified candidate was not saved. Review the current model/auth/runtime settings and retry.");
				if (!isDeepStrictEqual(projectSetupTargetModelMetadata(latestRuntime, stagedRoute.modelLabel, requestedAgentId), baselineTargetModelMetadata)) throw new Error("The target model metadata changed during its live inference test, so the verified candidate was not saved. Review the current model settings and retry.");
				const currentRoute = await projectRoute(stagedRuntime);
				if (!sameDefaultInferenceRoute(currentRoute, verifiedRoute)) throw new Error("The default-agent inference route changed during its live test, so the verified candidate was not saved. Review the current model/auth/runtime settings and retry.");
				const resolvedRoute = await resolveRoute(stagedRuntime);
				if (!resolvedRoute || resolvedRoute.modelLabel !== (plan.persistModelRef ?? plan.modelRef) || plan.authProfileId && resolvedRoute.authProfileId !== plan.authProfileId) throw new Error("The latest default-agent route no longer matches the verified candidate, so it was not saved. Review the current config and retry.");
				if (!isDeepStrictEqual(projectSetupTargetModelMetadata(current, stagedRoute.modelLabel, requestedAgentId), sourceTargetModelMetadata)) throw new Error("The authored target model metadata changed during its live inference test, so the verified candidate was not saved. Review the current model settings and retry.");
				const { config: nextConfig, autoLocalModelLeanApplied } = stageCandidate(current, "source");
				const nextRouteProjection = await projectRoute(nextConfig);
				const nextResolvedRoute = await resolveRoute(nextConfig);
				if (!sameDefaultInferenceRoute(nextRouteProjection, expectedSourceCandidateRoute) || !nextResolvedRoute || nextResolvedRoute.modelLabel !== (plan.persistModelRef ?? plan.modelRef) || plan.authProfileId && nextResolvedRoute.authProfileId !== plan.authProfileId) throw new Error("The source config no longer matches the verified candidate, so it was not saved. Review the current config and retry.");
				await revalidateOwner({
					route: nextResolvedRoute,
					auth: test.auth,
					stagedOwnerPluginArtifacts,
					deps
				});
				throwIfSetupInferenceCancelled(params);
				params.onCommitStarted?.(current);
				commitMayHaveStarted = true;
				state.autoLocalModelLeanApplied = autoLocalModelLeanApplied;
				return { nextConfig };
			}
		});
		committedConfig = committed.nextConfig;
		state.gatewayRestartRequired = committed.followUp.requiresRestart;
		if (pendingCodexInstall) codexInstallOwnership = "owned";
	} catch (error) {
		if (!commitMayHaveStarted) {
			if (manualAuthReceipt) {
				if (!await rollbackManualAuthProfiles(manualAuthReceipt, deps)) throw new SetupInferenceActivationIndeterminateError("Inference activation stopped before its config commit, but could not confirm removal of its staged credential. Run openclaw doctor --fix before retrying.");
			}
			throw error;
		}
		const reconciledSnapshot = await readSnapshot().catch(() => null);
		const reconciledRuntime = reconciledSnapshot?.exists && reconciledSnapshot.valid ? reconciledSnapshot.runtimeConfig ?? reconciledSnapshot.config : void 0;
		const reconciledRoute = reconciledRuntime ? await projectRoute(reconciledRuntime) : void 0;
		const codexInstallPersisted = pendingCodexInstall ? await isCodexInstallRecordPersisted(pendingCodexInstall, deps) : true;
		const committedDespiteError = reconciledRoute !== void 0 && sameDefaultInferenceRoute(reconciledRoute, persistedRoute) && (!manualAuthReceipt || manualAuthProfilesPersisted(manualAuthReceipt, deps)) && codexInstallPersisted;
		if (pendingCodexInstall) codexInstallOwnership = committedDespiteError ? "owned" : "unowned";
		if (!committedDespiteError) {
			if (manualAuthReceipt) {
				if (!reconciledRuntime || configReferencesManualAuthProfiles(reconciledRuntime, manualAuthReceipt)) throw new SetupInferenceActivationIndeterminateError("Inference activation could not confirm its config commit state. The verified credential was retained because the current config may reference it. Run openclaw doctor --fix before retrying.");
				if (!await rollbackManualAuthProfiles(manualAuthReceipt, deps)) throw new SetupInferenceActivationIndeterminateError("Inference activation failed and its staged credential could not be rolled back. Run openclaw doctor --fix before retrying.");
			}
			throw error;
		}
		committedConfig = reconciledSnapshot?.sourceConfig ?? reconciledRuntime;
		state.gatewayRestartRequired = pendingCodexInstall !== void 0;
		setupInferenceLog.warn("Inference activation committed successfully despite a post-write cleanup error.");
	}
	state.committedConfig = committedConfig;
	state.codexInstallOwnership = codexInstallOwnership;
}
//#endregion
//#region src/system-agent/setup-inference-owner.ts
function hasSameOwnerPluginArtifacts(binding, snapshot) {
	return isDeepStrictEqual(binding.ownerPluginIds, snapshot.ownerPluginIds) && isDeepStrictEqual(binding.ownerPluginArtifacts, snapshot.ownerPluginArtifacts);
}
/**
* Revalidate the successful probe's owner against current config. Any drift
* throws SetupInferenceOwnerDriftError, which activation returns as an auth
* failure result — a throw that escapes here would crash the onboarding ladder.
*/
async function revalidateStableSetupInferenceOwner(params) {
	let binding;
	try {
		binding = await revalidateSetupInferenceOwner({
			route: params.route,
			auth: params.auth,
			deps: params.deps
		});
	} catch (error) {
		throw new SetupInferenceOwnerDriftError(`The verified inference owner changed before activation completed. Retry the inference check. (${formatErrorMessage(error)})`, { cause: error });
	}
	if (!params.stagedOwnerPluginArtifacts || !hasSameOwnerPluginArtifacts(binding, params.stagedOwnerPluginArtifacts)) throw new SetupInferenceOwnerDriftError("The verified inference owner changed before activation completed. Retry the inference check. (The owner plugin runtime changed during its live test.)");
	return binding;
}
//#endregion
//#region src/system-agent/setup-inference-plan-provider-auth.ts
async function runProviderManualSecretMethod(params) {
	const optionKey = params.choice.optionKey;
	const runNonInteractive = params.method.runNonInteractive;
	if (!optionKey || !params.choice.cliOption || !runNonInteractive) throw new Error("Provider does not expose app-guided secret setup.");
	let methodError = "";
	const isolatedRuntime = {
		log: () => {},
		error: (...args) => {
			methodError = args.map(String).join(" ");
		},
		exit: (code) => {
			throw new Error(methodError || `Provider setup exited with code ${code}.`);
		}
	};
	const existingPrimary = resolveAgentModelPrimaryValue(params.config.agents?.defaults?.model);
	const existingProvider = existingPrimary ? parseRef(existingPrimary).provider : void 0;
	let providerSetupConfig = params.config;
	if (existingProvider && normalizeProviderId(existingProvider) !== normalizeProviderId(params.choice.providerId)) {
		const agents = params.config.agents;
		const defaults = agents?.defaults;
		const model = defaults?.model;
		if (defaults && model !== void 0) {
			const { model: _model, ...defaultsWithoutModel } = defaults;
			let modelWithoutPrimary;
			if (typeof model === "object" && model !== null) {
				const { primary: _primary, ...remainingModelConfig } = model;
				modelWithoutPrimary = remainingModelConfig;
			}
			providerSetupConfig = {
				...params.config,
				agents: {
					...agents,
					defaults: modelWithoutPrimary && Object.keys(modelWithoutPrimary).length > 0 ? {
						...defaultsWithoutModel,
						model: modelWithoutPrimary
					} : defaultsWithoutModel
				}
			};
		}
	}
	const configured = await runNonInteractive({
		authChoice: params.choice.choiceId,
		config: providerSetupConfig,
		baseConfig: params.baseConfig,
		opts: {
			[optionKey]: params.apiKey,
			secretInputMode: "plaintext"
		},
		runtime: isolatedRuntime,
		agentDir: params.agentDir,
		workspaceDir: params.workspaceDir,
		resolveApiKey: async (input) => typeof input.flagValue === "string" && input.flagValue.trim() ? {
			key: input.flagValue.trim(),
			source: "flag"
		} : null,
		toApiKeyCredential: ({ provider, resolved, email, metadata }) => ({
			type: "api_key",
			provider,
			key: resolved.key,
			...email ? { email } : {},
			...metadata ? { metadata } : {}
		})
	});
	if (!configured) throw new Error(methodError || "Provider setup did not produce a configuration.");
	const store = loadPersistedAuthProfileStore(params.agentDir);
	const profiles = Object.entries(store?.profiles ?? {}).map(([profileId, credential]) => ({
		profileId,
		credential
	}));
	const previousModel = resolveAgentModelPrimaryValue(params.config.agents?.defaults?.model);
	const configuredModel = resolveAgentModelPrimaryValue(configured.agents?.defaults?.model);
	const configuredProvider = configuredModel ? parseRef(configuredModel).provider : void 0;
	const configuredModelOwnedByProvider = configuredProvider !== void 0 && normalizeProviderId(configuredProvider) === normalizeProviderId(params.choice.providerId);
	const defaultModel = configuredModel && (configuredModel !== previousModel || configuredModelOwnedByProvider) ? configuredModel : params.method.starterModel;
	if (profiles.length === 0 || !defaultModel) throw new Error("Provider setup did not produce credentials and a starter model.");
	return {
		result: {
			profiles,
			defaultModel
		},
		config: configured
	};
}
//#endregion
//#region src/system-agent/setup-inference-plan.ts
function buildPreparedProviderTestPlan(params) {
	const ref = parseRef(params.modelRef);
	const projection = {
		baseConfig: params.cfg,
		preparedConfig: params.preparedConfig,
		modelRef: params.modelRef,
		providerId: ref.provider,
		pluginId: params.pluginId,
		agentId: params.routeAgentId
	};
	const prepared = params.selectedProfileId ? prepareManualAuthForActivation({
		...projection,
		profiles: params.profiles,
		selectedProfileId: params.selectedProfileId
	}) : {
		config: projectManualInferenceConfig(projection),
		profiles: [],
		selectedProfileId: void 0
	};
	return {
		runner: "embedded",
		...ref,
		modelRef: params.modelRef,
		agentDir: params.agentDir,
		config: prepared.config,
		agentId: "openclaw",
		routeAgentId: params.routeAgentId,
		...prepared.selectedProfileId ? { authProfileId: prepared.selectedProfileId } : {},
		persistModelRef: params.modelRef,
		manualAuth: {
			profiles: prepared.profiles,
			runtimeConfigBase: params.cfg,
			sourceConfigBase: params.sourceCfg,
			configPatch: createMergePatch(params.cfg, prepared.config),
			...params.pluginId ? { pluginId: params.pluginId } : {}
		}
	};
}
async function prepareSetupProviderAuthChoice(params, choice) {
	return await withPluginLifecycleLease({ signal: params.signal }, async () => {
		const enablePlugin = params.deps.enablePluginInConfig ?? enablePluginInConfig;
		const enableResult = await enablePluginWithCapabilityConsent(params.cfg, choice.pluginId, {
			workspaceDir: params.pluginWorkspaceDir,
			beforePersistentEffect: params.beforePersistentEffect,
			onCapabilityConsent: params.prompter ? createPluginCapabilityConsentPrompter(params.prompter, () => throwIfSetupInferenceCancelled(params)) : void 0
		});
		if (!enableResult.enabled) return { error: `${choice.choiceLabel} is disabled (${enableResult.reason ?? "blocked"}).` };
		const sourceEnableResult = enablePlugin(params.sourceCfg, choice.pluginId);
		if (!sourceEnableResult.enabled) return { error: `${choice.choiceLabel} is disabled (${sourceEnableResult.reason ?? "blocked"}).` };
		const provider = (params.deps.resolvePluginProviders ?? resolvePluginProvidersCore)({
			config: enableResult.config,
			workspaceDir: params.pluginWorkspaceDir,
			mode: "setup",
			includeUntrustedWorkspacePlugins: false,
			onlyPluginIds: [choice.pluginId]
		}).find((candidate) => candidate.pluginId === choice.pluginId && normalizeProviderId(candidate.id) === normalizeProviderId(choice.providerId));
		return {
			enableResult,
			sourceEnableResult,
			provider,
			method: provider?.auth.find((candidate) => candidate.id === choice.methodId)
		};
	});
}
async function buildTestPlan(params) {
	const { kind, cfg, workspaceDir } = params;
	const routeAgentId = resolveAmbientOwnerAgentId(cfg, params.routeAgentId);
	const resolveRouteModelRef = (defaultModelRef) => {
		const modelRef = params.modelRef?.trim() || defaultModelRef;
		const selected = parseRef(modelRef);
		const expected = parseRef(defaultModelRef);
		if (!selected.model || normalizeProviderId(selected.provider) !== normalizeProviderId(expected.provider)) return { error: `${modelRef} is not compatible with the ${kind} inference route.` };
		return modelRef;
	};
	const providerAutoChoiceId = parseProviderAutoSetupChoiceId(kind);
	if (providerAutoChoiceId) {
		const choice = (params.deps.resolveManifestProviderAuthChoice ?? resolveManifestProviderAuthChoice)(providerAutoChoiceId, {
			config: cfg,
			workspaceDir: params.pluginWorkspaceDir,
			includeUntrustedWorkspacePlugins: false,
			includeWorkspacePlugins: false
		});
		if (!choice || choice.appGuidedDiscovery !== true || !supportsSetupTextInference(choice.onboardingScopes)) return { error: "That detected provider is no longer available on this Gateway." };
		const providerChoice = await prepareSetupProviderAuthChoice(params, choice);
		if (providerChoice.error !== void 0) return { error: providerChoice.error };
		const { enableResult, sourceEnableResult, provider, method } = providerChoice;
		if (!provider || !method?.appGuidedSetup) return { error: "That detected provider is no longer available on this Gateway." };
		const modelRef = params.modelRef?.trim();
		if (!modelRef) return { error: "The detected provider model is missing. Run detection again." };
		try {
			const result = await method.appGuidedSetup.prepare({
				config: enableResult.config,
				env: process.env,
				workspaceDir: params.pluginWorkspaceDir,
				modelRef,
				...params.signal ? { signal: params.signal } : {}
			});
			const preparedModelRef = result?.defaultModel ? normalizeAgentModelRefForConfig(result.defaultModel) : "";
			if (!result || preparedModelRef !== modelRef) return { error: `${choice.choiceLabel} could not prepare the detected model. Run detection again.` };
			const ref = parseRef(modelRef);
			if (!ref.model || normalizeProviderId(ref.provider) !== normalizeProviderId(choice.providerId)) return { error: `${choice.choiceLabel} returned an invalid detected model.` };
			const preparedConfig = applyProviderPluginAuthMethodResultConfig({
				config: enableResult.config,
				result
			});
			const matchingProfile = result.profiles.find((profile) => normalizeProviderId(profile.credential.provider) === normalizeProviderId(ref.provider));
			if (result.profiles.length > 0 && !matchingProfile) return { error: `${choice.choiceLabel} did not return credentials for its detected model.` };
			return buildPreparedProviderTestPlan({
				cfg: enableResult.config,
				sourceCfg: sourceEnableResult.config,
				preparedConfig,
				profiles: result.profiles,
				selectedProfileId: matchingProfile?.profileId,
				modelRef,
				pluginId: choice.pluginId,
				agentDir: params.agentDir,
				routeAgentId
			});
		} catch (error) {
			return { error: `${choice.choiceLabel} could not prepare app-guided setup: ${formatErrorMessage(error)}` };
		}
	}
	switch (kind) {
		case "existing-model": {
			let route;
			try {
				route = await resolveSystemAgentConfiguredRouteFromConfig(cfg, params.routeAgentId, { loadAuthProfileStoreForRuntime: params.deps.loadAuthProfileStoreForRuntime });
			} catch (error) {
				if (error instanceof CliExecutionAuthProfileError) return {
					error: error.message,
					status: "auth"
				};
				throw error;
			}
			if (!route) return { error: "No configured default-agent inference route is available." };
			const requestedModelRef = params.modelRef?.trim();
			const requestedTarget = requestedModelRef ? canonicalizeSetupModelRef({
				cfg,
				raw: requestedModelRef,
				defaultProvider: route.provider
			}) : void 0;
			if (requestedModelRef && requestedTarget !== route.modelLabel) return { error: `The configured default model changed from ${requestedModelRef} to ${route.modelLabel}. Try setup again.` };
			return {
				runner: route.runner,
				provider: route.provider,
				model: route.model,
				modelRef: route.modelLabel,
				config: cfg,
				executionConfig: route.runConfig,
				agentId: "openclaw",
				routeAgentId: route.agentId,
				agentDir: route.agentDir,
				...route.runner === "embedded" && route.agentHarnessRuntimeOverride ? { agentHarnessRuntimeOverride: route.agentHarnessRuntimeOverride } : {},
				...route.authProfileId ? { authProfileId: route.authProfileId } : {}
			};
		}
		case "claude-cli": {
			const modelRef = resolveRouteModelRef(CLAUDE_CLI_DEFAULT_MODEL_REF);
			if (typeof modelRef !== "string") return modelRef;
			const ref = parseRef(modelRef);
			const persistProvider = resolveCliRuntimeCanonicalProvider({
				runtime: ref.provider,
				config: cfg,
				env: process.env,
				includeSetupRegistry: true
			}) ?? ref.provider;
			return {
				runner: "cli",
				...ref,
				modelRef,
				config: cfg,
				agentId: "openclaw",
				routeAgentId,
				persistModelRef: `${persistProvider}/${ref.model}`
			};
		}
		case "gemini-cli": {
			const modelRef = resolveRouteModelRef(GEMINI_CLI_DEFAULT_MODEL_REF);
			if (typeof modelRef !== "string") return modelRef;
			return {
				runner: "cli",
				...parseRef(modelRef),
				modelRef,
				config: cfg,
				agentId: "openclaw",
				routeAgentId,
				persistModelRef: modelRef
			};
		}
		case "codex-cli": {
			const modelRef = resolveRouteModelRef(CODEX_APP_SERVER_DEFAULT_MODEL_REF);
			if (typeof modelRef !== "string") return modelRef;
			const ref = parseRef(modelRef);
			if (params.codexCliApiKey) {
				const preparedAuth = prepareManualAuthForActivation({
					baseConfig: cfg,
					preparedConfig: cfg,
					profiles: [{
						profileId: "openai:codex-cli-api-key",
						credential: params.codexCliApiKey
					}],
					selectedProfileId: "openai:codex-cli-api-key",
					modelRef,
					providerId: ref.provider,
					agentId: routeAgentId
				});
				return {
					runner: "embedded",
					...ref,
					modelRef,
					agentHarnessRuntimeOverride: "codex",
					config: preparedAuth.config,
					agentId: "openclaw",
					routeAgentId,
					agentDir: params.agentDir,
					cleanupBundleMcpOnRunEnd: true,
					authProfileId: preparedAuth.selectedProfileId,
					persistModelRef: modelRef,
					manualAuth: {
						profiles: preparedAuth.profiles,
						runtimeConfigBase: cfg,
						sourceConfigBase: params.sourceCfg,
						configPatch: createMergePatch(cfg, preparedAuth.config)
					}
				};
			}
			return {
				runner: "embedded",
				...ref,
				modelRef,
				agentHarnessRuntimeOverride: "codex",
				config: cfg,
				agentId: "openclaw",
				routeAgentId,
				agentDir: params.agentDir,
				cleanupBundleMcpOnRunEnd: true,
				persistModelRef: modelRef
			};
		}
		case "openai-api-key": {
			const modelRef = resolveRouteModelRef(OPENAI_API_DEFAULT_MODEL_REF);
			if (typeof modelRef !== "string") return modelRef;
			return {
				runner: "embedded",
				...parseRef(modelRef),
				modelRef,
				config: cfg,
				agentId: "openclaw",
				routeAgentId,
				persistModelRef: modelRef
			};
		}
		case "anthropic-api-key": {
			const modelRef = resolveRouteModelRef(ANTHROPIC_API_DEFAULT_MODEL_REF);
			if (typeof modelRef !== "string") return modelRef;
			return {
				runner: "embedded",
				...parseRef(modelRef),
				modelRef,
				config: cfg,
				agentId: "openclaw",
				routeAgentId,
				persistModelRef: modelRef
			};
		}
		case "api-key":
		case "provider-auth": {
			const interactive = kind === "provider-auth";
			const apiKey = params.apiKey?.trim();
			if (!interactive && !apiKey) return { error: "Enter an API key or token first." };
			const authChoice = params.authChoice?.trim();
			if (interactive && authChoice === "custom-api-key") {
				if (params.isRemoteProviderAuth) return { error: "For a custom provider, run openclaw onboard on the Gateway host." };
				if (!params.prompter) return { error: "Custom provider setup requires an interactive CLI session." };
				const { promptCustomApiConfig } = await import("./onboard-custom-CDT-eaYr.js");
				throwIfSetupInferenceCancelled(params);
				const prepared = await waitForProviderAuth(promptCustomApiConfig({
					config: cfg,
					runtime: params.runtime,
					prompter: params.prompter,
					target: {
						agentId: routeAgentId,
						agentDir: params.agentDir,
						workspaceDir: params.pluginWorkspaceDir
					},
					setAsPrimary: false
				}), params.signal);
				throwIfSetupInferenceCancelled(params);
				return buildPreparedProviderTestPlan({
					...params,
					preparedConfig: prepared.config,
					profiles: [],
					modelRef: `${prepared.providerId}/${prepared.modelId}`,
					routeAgentId
				});
			}
			const choice = authChoice ? (params.deps.resolveManifestProviderAuthChoice ?? resolveManifestProviderAuthChoice)(authChoice, {
				config: cfg,
				workspaceDir: params.pluginWorkspaceDir,
				includeUntrustedWorkspacePlugins: false,
				includeWorkspacePlugins: false
			}) : void 0;
			if (!choice || !supportsSetupTextInference(choice.onboardingScopes) || !interactive && !supportsSetupManualSecret(choice) || interactive && (choice.assistantVisibility === "manual-only" || !choice.appGuidedAuth && choice.appGuidedDiscovery !== true)) return { error: interactive ? "That provider setup is not available on this Gateway." : "That key-based provider is not available on this Gateway." };
			const providerChoice = await prepareSetupProviderAuthChoice(params, choice);
			if (providerChoice.error !== void 0) return { error: providerChoice.error };
			const { enableResult, sourceEnableResult, provider, method } = providerChoice;
			const resolved = provider && method ? {
				provider,
				method
			} : null;
			if (!resolved || !supportsSetupTextInference(resolved.method.wizard?.onboardingScopes) || interactive && choice.appGuidedDiscovery !== true && resolved.method.kind !== "oauth" && resolved.method.kind !== "device_code") return { error: interactive ? "That provider setup is not available on this Gateway." : "That key-based provider is not available on this Gateway." };
			let result;
			let preparedConfig;
			try {
				if (interactive) {
					if (!params.prompter) return { error: "This provider login requires an interactive setup session." };
					throwIfSetupInferenceCancelled(params);
					result = await waitForProviderAuth(runProviderPluginAuthMethodUnpersisted({
						config: enableResult.config,
						runtime: params.runtime,
						...params.signal ? { signal: params.signal } : {},
						isRemote: params.isRemoteProviderAuth,
						prompter: params.prompter,
						method: resolved.method,
						agentDir: params.agentDir,
						workspaceDir
					}), params.signal);
					throwIfSetupInferenceCancelled(params);
					preparedConfig = applyProviderPluginAuthMethodResultConfig({
						config: enableResult.config,
						result
					});
					if (choice.appGuidedDiscovery === true) {
						const guidedSetup = resolved.method.appGuidedSetup;
						if (!guidedSetup) return { error: "That provider setup is not available on this Gateway." };
						const selectedModelRef = result.defaultModel ? normalizeAgentModelRefForConfig(result.defaultModel) : "";
						const candidate = selectedModelRef ? { modelRef: selectedModelRef } : await guidedSetup.detect({
							config: preparedConfig,
							env: process.env,
							workspaceDir: params.pluginWorkspaceDir,
							...params.signal ? { signal: params.signal } : {}
						});
						if (!candidate) return { error: `${resolved.provider.label} setup completed, but no compatible model was found. Add a compatible model and try again.` };
						const prepared = await guidedSetup.prepare({
							config: preparedConfig,
							env: process.env,
							workspaceDir: params.pluginWorkspaceDir,
							modelRef: candidate.modelRef,
							...params.signal ? { signal: params.signal } : {}
						});
						const preparedModelRef = prepared?.defaultModel ? normalizeAgentModelRefForConfig(prepared.defaultModel) : "";
						if (!prepared || preparedModelRef !== candidate.modelRef) return { error: `${resolved.provider.label} could not prepare its detected model. Try setup again.` };
						preparedConfig = applyProviderPluginAuthMethodResultConfig({
							config: preparedConfig,
							result: prepared
						});
						const profiles = new Map([...result.profiles, ...prepared.profiles].map((profile) => [profile.profileId, profile]));
						result = {
							...prepared,
							profiles: [...profiles.values()]
						};
					}
				} else if (resolved.method.kind === "api_key" || resolved.method.kind === "token") {
					result = await runProviderPluginAuthMethodUnpersisted({
						config: enableResult.config,
						runtime: params.runtime,
						prompter: createQuickstartNotePrompter(params.runtime),
						method: resolved.method,
						agentDir: params.agentDir,
						workspaceDir,
						secretInputMode: "plaintext",
						allowSecretRefPrompt: false,
						opts: {
							token: apiKey,
							tokenProvider: resolved.provider.id
						}
					});
					preparedConfig = applyProviderPluginAuthMethodResultConfig({
						config: enableResult.config,
						result
					});
				} else {
					const prepared = await runProviderManualSecretMethod({
						config: enableResult.config,
						baseConfig: cfg,
						choice,
						method: resolved.method,
						apiKey,
						agentDir: params.agentDir,
						workspaceDir
					});
					result = prepared.result;
					preparedConfig = prepared.config;
				}
			} catch (error) {
				if (error instanceof SetupInferenceCancelledError || params.signal?.aborted) return { error: "Provider login was cancelled." };
				const detail = error instanceof Error ? error.message : String(error);
				return { error: `${resolved.provider.label} could not prepare this ${interactive ? "login" : "credential"} for app-guided setup: ${detail}` };
			}
			const modelRef = result.defaultModel ? normalizeAgentModelRefForConfig(result.defaultModel) : "";
			if (!modelRef) return { error: `${resolved.provider.label} does not expose a starter model for app-guided setup.` };
			const ref = parseRef(modelRef);
			if (!ref.model) return { error: `${resolved.provider.label} returned an invalid starter model.` };
			const matchingProfile = result.profiles.find((profile) => normalizeProviderId(profile.credential.provider) === normalizeProviderId(ref.provider));
			if (result.profiles.length > 0 && !matchingProfile) return { error: `${resolved.provider.label} did not return credentials for its starter model.` };
			return buildPreparedProviderTestPlan({
				cfg: enableResult.config,
				sourceCfg: sourceEnableResult.config,
				preparedConfig,
				profiles: result.profiles,
				selectedProfileId: matchingProfile?.profileId,
				modelRef,
				pluginId: resolved.provider.pluginId,
				agentDir: params.agentDir,
				routeAgentId
			});
		}
		default: return { error: `Unknown inference choice "${kind}".` };
	}
}
//#endregion
//#region src/system-agent/setup-inference-activate.ts
/**
* Test one candidate with a real completion, then persist it as the setup
* default. Manual credentials are tested from a temporary auth store and
* copied into the real agent store only after success. A managed Codex install
* record may remain after a failed probe because the installed package already exists.
*/
async function activateSetupInference(params) {
	const codexCliApiKey = params.kind === "codex-cli" ? (params.deps?.readCodexCliActiveApiKey ?? readCodexCliActiveApiKey)({ allowKeychainPrompt: true }) : null;
	try {
		const result = await activateSetupInferenceUnredacted(params, codexCliApiKey ?? void 0);
		if (result.ok) return {
			...result,
			lines: await Promise.all(result.lines.map((line) => redactSetupInferenceError(line, params.apiKey, codexCliApiKey?.key)))
		};
		return {
			...result,
			error: await redactSetupInferenceError(result.error, params.apiKey, codexCliApiKey?.key)
		};
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		const redacted = await redactSetupInferenceError(message, params.apiKey, codexCliApiKey?.key);
		if (error instanceof WizardCancelledError) throw new WizardCancelledError(redacted);
		if (error instanceof WizardNavigationError) throw new WizardNavigationError(error.direction);
		if (error instanceof SetupInferenceCancelledError || params.signal?.aborted) return {
			ok: false,
			status: "unavailable",
			error: "Provider login was cancelled."
		};
		if (error instanceof SetupInferenceActivationUnavailableError) return {
			ok: false,
			status: "unavailable",
			error: redacted
		};
		if (error instanceof SetupInferenceOwnerDriftError) return {
			ok: false,
			status: "auth",
			error: redacted
		};
		if (error instanceof SetupInferenceActivationIndeterminateError) throw new SetupInferenceActivationIndeterminateError(redacted);
		throw new Error(redacted);
	}
}
async function activateSetupInferenceUnredacted(params, codexCliApiKey) {
	const deps = params.deps ?? {};
	const beforePersistentEffect = async () => {
		throwIfSetupInferenceCancelled(params);
		await params.beforePersistentEffect?.();
		throwIfSetupInferenceCancelled(params);
	};
	const resolveRouteMetadata = deps.resolvePluginMetadataSnapshot ?? resolvePluginMetadataSnapshot;
	const readSnapshot = deps.readConfigFileSnapshot ?? (await import("./config/config.js")).readConfigFileSnapshot;
	const snapshot = await readSnapshot();
	if (snapshot.exists && !snapshot.valid) throw new Error(invalidSetupConfigError(snapshot));
	const cfg = snapshot.runtimeConfig ?? snapshot.config;
	const sourceCfg = snapshot.sourceConfig ?? snapshot.config;
	const routeAgentId = resolveAmbientOwnerAgentId(cfg, params.agentId);
	const workspace = params.workspace?.trim() ? resolveUserPath(params.workspace) : resolveSetupInferenceWorkspace(snapshot);
	const tempDir = await (deps.createTempDir ?? (() => fs.mkdtemp(path.join(os.tmpdir(), "openclaw-setup-inference-"))))();
	const testAgentDir = path.join(tempDir, "agent");
	let pendingCodexInstall;
	let codexInstallOwnership = "unknown";
	let codexMetadataNeedsRestore = false;
	let verificationProgress;
	let codexProbePluginGeneration;
	const withProbePluginGeneration = (run) => codexProbePluginGeneration ? withPluginRuntimeGenerationScope(codexProbePluginGeneration, run) : run();
	try {
		const plan = await buildTestPlan({
			kind: params.kind,
			...params.modelRef !== void 0 ? { modelRef: params.modelRef } : {},
			...params.authChoice !== void 0 ? { authChoice: params.authChoice } : {},
			...params.apiKey !== void 0 ? { apiKey: params.apiKey } : {},
			cfg,
			sourceCfg,
			workspaceDir: tempDir,
			pluginWorkspaceDir: workspace,
			agentDir: testAgentDir,
			runtime: params.runtime,
			beforePersistentEffect,
			...params.prompter ? { prompter: params.prompter } : {},
			...params.signal ? { signal: params.signal } : {},
			...params.isCancelled ? { isCancelled: params.isCancelled } : {},
			...params.kind === "provider-auth" ? { isRemoteProviderAuth: params.surface === "gateway" } : {},
			...codexCliApiKey ? { codexCliApiKey } : {},
			deps,
			routeAgentId
		});
		if ("error" in plan) return {
			ok: false,
			status: plan.status ?? "unavailable",
			error: plan.error
		};
		const hasPreparedAuthProfiles = (plan.manualAuth?.profiles.length ?? 0) > 0;
		const autoLocalModelLeanUpdate = applyAutoLocalModelLean({
			config: plan.config,
			providerId: plan.provider,
			modelRef: plan.modelRef,
			previousModelRef: resolveAgentModelPrimaryValue(cfg.agents?.defaults?.model)
		});
		let testPlan = {
			...plan,
			config: autoLocalModelLeanUpdate.config
		};
		if (plan.persistModelRef) {
			const agentRuntimeId = resolveSetupAgentRuntimeId(params.kind);
			const stagedConfig = await applySystemAgentModelSelection({
				config: testPlan.config,
				model: plan.persistModelRef,
				...params.agentId ? { targetAgentId: testPlan.routeAgentId } : {},
				...agentRuntimeId ? { agentRuntimeId } : {},
				...plan.manualAuth && plan.authProfileId ? { authProfileId: plan.authProfileId } : {}
			});
			testPlan = {
				...plan,
				config: stagedConfig,
				routeAgentId: resolveAmbientOwnerAgentId(stagedConfig, params.agentId)
			};
		}
		let codexPluginPatch;
		if (params.kind === "codex-cli") {
			const preparationFailure = await withPluginLifecycleLease({ signal: params.signal }, async () => {
				const { stripPendingPluginInstallRecords } = await import("./install-record-commit-DVoT_zjZ.js");
				const codexInstallBase = stripPendingPluginInstallRecords(testPlan.config);
				const enabledCodexBase = await enablePluginWithCapabilityConsent(normalizePluginTargetConfig(codexInstallBase, "codex"), "codex", {
					workspaceDir: workspace,
					onCapabilityConsent: params.prompter ? createPluginCapabilityConsentPrompter(params.prompter) : void 0,
					beforePersistentEffect
				});
				if (!enabledCodexBase.enabled) return {
					ok: false,
					status: "unavailable",
					error: `Could not enable the Codex runtime plugin: ${enabledCodexBase.reason ?? "plugin disabled"}.`
				};
				const ensured = await (deps.ensureCodexRuntimePlugin ?? (await import("./codex-runtime-plugin-install-Di72TzP0.js")).ensureCodexRuntimePluginForModelSelection)({
					cfg: enabledCodexBase.config,
					model: plan.modelRef,
					agentId: testPlan.routeAgentId,
					prompter: params.prompter ?? createQuickstartNotePrompter(params.runtime),
					runtime: params.runtime,
					workspaceDir: tempDir,
					beforePersistentEffect
				});
				if (!ensured.ok) return {
					ok: false,
					status: ensured.status === "timed_out" ? "timeout" : "unavailable",
					error: ensured.message
				};
				codexMetadataNeedsRestore = true;
				pendingCodexInstall = ensured.cfg.plugins?.installs?.codex;
				if (pendingCodexInstall) {
					if (!await retainUnownedCodexInstall({
						record: pendingCodexInstall,
						verifyOwnership: false,
						deps
					})) return {
						ok: false,
						status: "unavailable",
						error: "Could not retain the staged Codex runtime safely. No inference route was changed; retry after checking the plugin storage directory."
					};
				}
				const preparedAuth = configureCodexCliPreparedAuth(normalizePluginTargetConfig(ensured.cfg, "codex"), codexCliApiKey ? "agent" : "user");
				if (!preparedAuth.ok) return {
					ok: false,
					status: "unavailable",
					error: preparedAuth.error
				};
				const enabledCodex = enablePluginInConfig(preparedAuth.value, "codex");
				if (!enabledCodex.enabled) return {
					ok: false,
					status: "unavailable",
					error: `Could not enable the Codex runtime plugin: ${enabledCodex.reason ?? "plugin disabled"}.`
				};
				const stagedCodexConfig = enabledCodex.config;
				codexPluginPatch = createMergePatch(codexInstallBase, stripPendingPluginInstallRecords(stagedCodexConfig));
				testPlan = {
					...testPlan,
					config: stagedCodexConfig
				};
				const refreshPluginRegistry = deps.refreshPluginRegistryAfterConfigMutation ?? (await import("./registry-refresh-x5mIxBEc.js")).refreshPluginRegistryAfterConfigMutation;
				let registryRefreshWarning;
				await refreshPluginRegistry({
					config: testPlan.config,
					reason: "source-changed",
					...testPlan.config.plugins?.installs ? { installRecords: testPlan.config.plugins.installs } : {},
					workspaceDir: workspace,
					policyPluginIds: ["codex"],
					traceCommand: "openclaw-setup-probe",
					logger: { warn: (message) => registryRefreshWarning = message }
				});
				try {
					codexProbePluginGeneration = loadSetupInferencePluginGeneration({
						config: testPlan.config,
						workspaceDir: workspace,
						selection: {
							provider: testPlan.provider,
							modelId: testPlan.model,
							runtime: "codex",
							agentId: testPlan.routeAgentId
						},
						resolvePluginMetadataSnapshot: resolveRouteMetadata
					});
				} catch (error) {
					const loadError = `Could not load the Codex runtime plugin: ${formatErrorMessage(error)}`;
					return {
						ok: false,
						status: "unavailable",
						error: registryRefreshWarning ? `${registryRefreshWarning} ${loadError}` : loadError
					};
				}
			});
			if (preparationFailure) return preparationFailure;
		}
		const metadataWorkspaceDir = getActivePluginRegistryWorkspaceDirFromState();
		const routeDeps = { pluginMetadataPlugins: (codexProbePluginGeneration?.metadataSnapshot ?? resolveRouteMetadata({
			config: testPlan.config,
			env: process.env,
			...metadataWorkspaceDir ? { workspaceDir: metadataWorkspaceDir } : {}
		})).plugins };
		const requestedAgentId = params.agentId ? testPlan.routeAgentId : void 0;
		const baselineRoute = await projectInferenceRoute(cfg, requestedAgentId, routeDeps);
		const verifiedRoute = await projectInferenceRoute(testPlan.config, requestedAgentId, routeDeps);
		const stagedRoute = verifiedRoute.route;
		const stagedExecutionRoute = await resolveSystemAgentConfiguredRouteFromConfig(testPlan.config, requestedAgentId, routeDeps);
		if (!stagedRoute || !stagedExecutionRoute || stagedRoute.runner !== testPlan.runner || stagedRoute.provider !== testPlan.provider || stagedRoute.model !== testPlan.model || stagedRoute.modelLabel !== (plan.persistModelRef ?? plan.modelRef) || plan.authProfileId && stagedRoute.authProfileId !== plan.authProfileId) return {
			ok: false,
			status: "unavailable",
			error: "The staged default-agent route does not match the requested inference candidate. Review model runtime policy and retry."
		};
		const baselineTargetModelMetadata = projectSetupTargetModelMetadata(cfg, stagedRoute.modelLabel, requestedAgentId);
		const sourceTargetModelMetadata = projectSetupTargetModelMetadata(sourceCfg, stagedRoute.modelLabel, requestedAgentId);
		testPlan = {
			...testPlan,
			executionConfig: stagedExecutionRoute.runConfig,
			agentDir: hasPreparedAuthProfiles ? testAgentDir : stagedRoute.agentDir,
			...testPlan.runner === "embedded" && stagedRoute.runner === "embedded" && stagedRoute.agentHarnessRuntimeOverride ? { agentHarnessRuntimeOverride: stagedRoute.agentHarnessRuntimeOverride } : {}
		};
		if (hasPreparedAuthProfiles && plan.manualAuth) {
			if ((await persistManualAuthProfiles({
				profiles: plan.manualAuth.profiles,
				agentDir: testAgentDir,
				deps
			})).status !== "persisted") return {
				ok: false,
				status: "unknown",
				error: "Could not stage the credential for its live inference test; try again in a moment."
			};
		}
		let stagedOwnerPluginArtifacts;
		try {
			stagedOwnerPluginArtifacts = withProbePluginGeneration(() => (deps.captureSystemAgentOwnerPluginArtifacts ?? captureSystemAgentOwnerPluginArtifacts)({
				config: stagedExecutionRoute.runConfig,
				executionRoute: stagedExecutionRoute,
				deps
			}));
		} catch {
			return {
				ok: false,
				status: "unavailable",
				error: "Could not bind the staged inference plugin runtime. Refresh or reinstall the plugin and retry."
			};
		}
		if (params.signal?.aborted || params.isCancelled?.()) return {
			ok: false,
			status: "unavailable",
			error: "Provider login was cancelled."
		};
		let test;
		verificationProgress = params.prompter?.progress("Testing your AI connection…");
		try {
			test = await withProbePluginGeneration(() => runSetupInferenceTest({
				plan: testPlan,
				tempDir,
				deps,
				authProfileStateMode: "read-only",
				requireExecutionOwner: true,
				verifyAgentTools: true,
				...params.signal ? { signal: params.signal } : {}
			}));
			throwIfSetupInferenceCancelled(params);
		} catch (error) {
			if (error instanceof SetupInferenceCancelledError || params.signal?.aborted) return {
				ok: false,
				status: "unavailable",
				error: "Provider login was cancelled."
			};
			throw error;
		}
		if (!test.ok) return {
			...test,
			disposition: "rejected-before-promotion"
		};
		verificationProgress?.update("Finishing AI setup…");
		if (plan.authProfileId && test.auth.authProfileId !== plan.authProfileId) return {
			ok: false,
			status: "auth",
			error: `The inference run used profile "${test.auth.authProfileId ?? "unknown"}" instead of the configured profile "${plan.authProfileId}". No model or credential route was saved.`
		};
		const needsPersistence = plan.persistModelRef !== void 0 || plan.manualAuth !== void 0 || codexPluginPatch !== void 0 || pendingCodexInstall !== void 0 || autoLocalModelLeanUpdate.changed;
		if (!test.auth.authFingerprint && (!test.auth.runtimeOwnerFingerprint || !test.auth.runtimeOwnerKind || !test.auth.runtimeOwnerId?.trim())) return {
			ok: false,
			status: "unknown",
			error: "Inference succeeded, but its runtime did not report an owner that OpenClaw can safely reuse. No model or credential route was saved."
		};
		if (testPlan.runner === "cli" && (!test.auth.runtimeArtifactFingerprint || !test.auth.runtimeArtifactId?.trim())) return {
			ok: false,
			status: "unknown",
			error: "Inference succeeded, but its CLI executable/package artifact could not be safely reused. No model or credential route was saved."
		};
		if (testPlan.runner === "embedded") {
			const successfulHarnessId = test.auth.agentHarnessId?.trim();
			const configuredHarnessId = testPlan.agentHarnessRuntimeOverride?.trim();
			if (!successfulHarnessId || configuredHarnessId !== void 0 && configuredHarnessId !== "auto" && successfulHarnessId !== configuredHarnessId) return {
				ok: false,
				status: "unknown",
				error: "Inference succeeded, but its exact agent harness could not be safely reused. No model or credential route was saved."
			};
			if (successfulHarnessId !== "openclaw" && (test.auth.runtimeOwnerKind !== "plugin-harness" || test.auth.runtimeOwnerId?.trim() !== successfulHarnessId || !test.auth.runtimeArtifactFingerprint || !test.auth.runtimeArtifactId?.trim())) return {
				ok: false,
				status: "unknown",
				error: "Inference succeeded, but its agent harness artifact could not be safely reused. No model or credential route was saved."
			};
		}
		let committedConfig;
		let autoLocalModelLeanApplied = false;
		let gatewayRestartRequired = false;
		if (!needsPersistence) {
			const latestSnapshot = await readSnapshot();
			const latestRuntime = latestSnapshot.exists && latestSnapshot.valid ? latestSnapshot.runtimeConfig ?? latestSnapshot.config : void 0;
			const latestRoute = latestRuntime ? await projectInferenceRoute(latestRuntime, requestedAgentId, routeDeps) : void 0;
			if (!latestRoute || !sameDefaultInferenceRoute(latestRoute, verifiedRoute)) return {
				ok: false,
				status: "unknown",
				error: "The default-agent inference route changed during its live test. Review the current model/auth/runtime settings and retry."
			};
			const latestResolvedRoute = latestRuntime ? await resolveSystemAgentConfiguredRouteFromConfig(latestRuntime, requestedAgentId, routeDeps) : null;
			if (!latestResolvedRoute) return {
				ok: false,
				status: "unknown",
				error: "The default-agent inference route could not be resolved after its live test. Review the current model/auth/runtime settings and retry."
			};
			await revalidateStableSetupInferenceOwner({
				route: latestResolvedRoute,
				auth: test.auth,
				stagedOwnerPluginArtifacts,
				deps
			});
		}
		if (needsPersistence) {
			const persistenceState = {
				committedConfig,
				autoLocalModelLeanApplied,
				codexInstallOwnership,
				gatewayRestartRequired
			};
			const persistenceFailure = await persistActivatedSetupInference({
				params,
				deps,
				plan,
				testPlan,
				test,
				codexPluginPatch,
				pendingCodexInstall,
				cfg,
				sourceCfg,
				verifiedRoute,
				baselineRoute,
				stagedRoute,
				stagedOwnerPluginArtifacts,
				baselineTargetModelMetadata,
				sourceTargetModelMetadata,
				routeDeps,
				readSnapshot,
				hasPreparedAuthProfiles,
				state: persistenceState,
				revalidateOwner: revalidateStableSetupInferenceOwner
			});
			if (persistenceFailure) return persistenceFailure;
			({committedConfig, autoLocalModelLeanApplied, codexInstallOwnership, gatewayRestartRequired} = persistenceState);
		}
		const announceAutoLocalModelLean = autoLocalModelLeanApplied && committedConfig?.agents?.defaults?.experimental?.localModelLean === true;
		let lines = [`Inference verified: ${plan.modelRef}`, ...announceAutoLocalModelLean ? [AUTO_LOCAL_MODEL_LEAN_ANNOUNCEMENT] : []];
		if (params.surface === "gateway" && params.recordSetupAudit !== false) {
			const after = await readSnapshot().catch(() => null);
			try {
				await appendSystemAgentAuditEntry({
					operation: "openclaw.setup",
					summary: "Verified and configured AI access through OpenClaw setup",
					configPath: after?.path ?? snapshot.path,
					configHashBefore: snapshot.hash ?? null,
					configHashAfter: after?.hash ?? null,
					details: {
						modelRef: plan.modelRef,
						inferenceKind: params.kind
					}
				});
			} catch (error) {
				const warning = `Inference setup completed, but OpenClaw could not record its audit entry: ${formatErrorMessage(error)}`;
				params.runtime.error?.(warning);
				lines = [...lines, warning];
			}
		}
		return {
			ok: true,
			modelRef: plan.modelRef,
			latencyMs: test.latencyMs,
			lines,
			...params.surface === "gateway" && gatewayRestartRequired ? { gatewayRestartRequired: true } : {}
		};
	} finally {
		verificationProgress?.stop();
		let codexCleanupError;
		if (pendingCodexInstall && codexInstallOwnership !== "owned") {
			if (!await retainUnownedCodexInstall({
				record: pendingCodexInstall,
				verifyOwnership: false,
				deps
			})) codexCleanupError = new SetupInferenceActivationIndeterminateError("Inference activation stopped before its Codex runtime package could be retained safely. Restart the Gateway before retrying.");
		}
		if (codexMetadataNeedsRestore) await restoreSetupPluginMetadata({
			readSnapshot,
			workspaceDir: workspace,
			deps
		});
		await cleanupSetupInferenceTempDir({
			tempDir,
			deps,
			runtime: params.runtime
		});
		if (codexCleanupError) throw codexCleanupError;
	}
}
//#endregion
//#region src/system-agent/setup-inference-verify.ts
async function verifySetupInference(params) {
	const readSnapshot = {
		...params.deps,
		...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {}
	}.readConfigFileSnapshot ?? (await import("./config/config.js")).readConfigFileSnapshot;
	const snapshot = await readSnapshot();
	if (!snapshot.exists) return {
		ok: false,
		status: "unavailable",
		error: "No OpenClaw config exists. Run `openclaw onboard` first."
	};
	if (!snapshot.valid) return {
		ok: false,
		status: "format",
		error: invalidSetupConfigError(snapshot)
	};
	const cfg = snapshot.runtimeConfig ?? snapshot.config;
	const baselineRoute = await projectInferenceRoute(cfg, params.agentId);
	let verifiedBinding;
	const verification = await verifySetupInferenceConfig({
		config: cfg,
		runtime: params.runtime,
		requireExecutionOwner: params.bindSession === true,
		...params.agentId ? { agentId: params.agentId } : {},
		...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
		...params.deps ? { deps: params.deps } : {},
		...params.bindSession ? { onVerifiedExecution: (_auth, binding) => {
			verifiedBinding = binding;
		} } : {}
	});
	if (!verification.ok) return verification;
	const latestSnapshot = await readSnapshot().catch(() => null);
	const latestConfig = latestSnapshot?.exists && latestSnapshot.valid ? latestSnapshot.runtimeConfig ?? latestSnapshot.config : void 0;
	const latestRoute = latestConfig ? await projectInferenceRoute(latestConfig, params.agentId) : void 0;
	if (!latestRoute || !sameDefaultInferenceRoute(baselineRoute, latestRoute)) return {
		ok: false,
		status: "unknown",
		error: "The inference route changed during its live test. Review current model/auth/runtime settings and retry."
	};
	if (!params.bindSession) return verification;
	if (!await resolveSystemAgentConfiguredRouteFromConfig(cfg, params.agentId) || !verifiedBinding) return {
		ok: false,
		status: "unknown",
		error: "The successful inference run did not report an exact execution binding. Retry setup before starting OpenClaw."
	};
	return {
		...verification,
		binding: verifiedBinding
	};
}
function executionRouteIdentity(route) {
	const { runConfig: _runConfig, ...identity } = route;
	return identity;
}
/**
* Strict credentials need only the static owner check. Opaque runtimes can
* prove liveness only by completing another exact turn at the side-effect
* boundary; the result must still be the original frozen route.
*/
async function resolvePersistentApplyInference(params) {
	const deps = params.deps ?? {};
	const resolveVerified = deps.resolveVerifiedInferenceRoute ?? resolveSystemAgentVerifiedInferenceRoute;
	const initialRoute = await resolveVerified(params.binding, deps);
	if (!initialRoute) return null;
	const hasCurrentOwnerPluginArtifacts = deps.hasCurrentOwnerPluginArtifacts ?? hasCurrentSystemAgentOwnerPluginArtifacts;
	if (!await hasCurrentOwnerPluginArtifacts(params.binding, deps)) return null;
	if (params.binding.auth.proofKind !== "runtime-owner") return initialRoute;
	const live = await (deps.verifyBoundInference ?? verifySetupInference)({
		runtime: params.runtime,
		bindSession: true,
		agentId: params.binding.execution.agentId,
		deps
	});
	if (!live.ok || !isDeepStrictEqual(live.binding.configuredRoute, params.binding.configuredRoute) || !isDeepStrictEqual(executionRouteIdentity(live.binding.execution), executionRouteIdentity(params.binding.execution)) || !isDeepStrictEqual(live.binding.executionFingerprint, params.binding.executionFingerprint) || !isDeepStrictEqual(live.binding.ownerPluginIds, params.binding.ownerPluginIds) || !isDeepStrictEqual(live.binding.ownerPluginArtifacts, params.binding.ownerPluginArtifacts) || !isDeepStrictEqual(live.binding.auth, params.binding.auth)) return null;
	const finalRoute = await resolveVerified(params.binding, deps);
	if (!finalRoute || !await hasCurrentOwnerPluginArtifacts(params.binding, deps)) return null;
	return finalRoute;
}
/** Live-test a staged default-agent route before any caller persists it. */
async function verifySetupInferenceConfig(params) {
	const deps = {
		...params.deps,
		...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {}
	};
	const cfg = params.config;
	const routeAgentId = resolveAmbientOwnerAgentId(cfg, params.agentId);
	if (!resolveAgentEffectiveModelPrimary(cfg, routeAgentId)) return {
		ok: false,
		status: "unavailable",
		error: "No agent model is configured. Run `openclaw onboard` first."
	};
	const tempDir = await (deps.createTempDir ?? (() => fs.mkdtemp(path.join(os.tmpdir(), "openclaw-setup-inference-"))))();
	try {
		const builtPlan = await buildTestPlan({
			kind: "existing-model",
			cfg,
			sourceCfg: cfg,
			workspaceDir: tempDir,
			pluginWorkspaceDir: tempDir,
			agentDir: path.join(tempDir, "agent"),
			runtime: params.runtime,
			routeAgentId,
			deps
		});
		if ("error" in builtPlan) return {
			ok: false,
			status: builtPlan.status ?? "unavailable",
			error: builtPlan.error
		};
		let plan = params.agentDir ? {
			...builtPlan,
			agentDir: params.agentDir
		} : builtPlan;
		if (params.authProfiles && params.authProfiles.length > 0) {
			const selectedProfile = plan.authProfileId ? params.authProfiles.find((profile) => profile.profileId === plan.authProfileId) : params.authProfiles.find((profile) => normalizeProviderId(profile.credential.provider) === normalizeProviderId(plan.provider));
			if (!selectedProfile) return {
				ok: false,
				status: "auth",
				error: plan.authProfileId ? "The staged credential does not match the configured auth profile." : "The staged credential does not belong to the configured inference provider."
			};
			const stagedAgentDir = path.join(tempDir, "agent");
			if ((await persistManualAuthProfiles({
				profiles: params.authProfiles,
				agentDir: stagedAgentDir,
				deps
			})).status !== "persisted") return {
				ok: false,
				status: "unknown",
				error: "Could not stage the credential for its live inference test; try again in a moment."
			};
			plan = {
				...plan,
				agentDir: stagedAgentDir,
				authProfileId: selectedProfile.profileId
			};
		}
		const readStagedAuthProfiles = () => {
			if (!params.authProfiles || params.authProfiles.length === 0) return;
			const { profiles } = (deps.loadAuthProfileStoreForRuntime ?? loadAuthProfileStoreForRuntime)(plan.agentDir, {
				readOnly: true,
				allowKeychainPrompt: false,
				config: plan.config,
				externalCliProviderIds: [plan.provider]
			});
			return params.authProfiles.map((profile) => {
				const credential = profiles[profile.profileId];
				if (!credential) throw new Error("staged profile missing after verification");
				return {
					...profile,
					credential
				};
			});
		};
		const retainStagedAuthProfiles = () => {
			try {
				return {
					ok: true,
					authProfiles: readStagedAuthProfiles()
				};
			} catch {
				return {
					ok: false,
					result: {
						ok: false,
						status: "unknown",
						error: "Could not retain the credential after its live inference test."
					}
				};
			}
		};
		const requiresExecutionOwner = params.requireExecutionOwner === true || params.onVerifiedExecution !== void 0;
		let configuredRoute;
		let stagedOwnerPluginArtifacts;
		if (requiresExecutionOwner) {
			configuredRoute = await resolveSystemAgentConfiguredRouteFromConfig(cfg, routeAgentId) ?? void 0;
			if (!configuredRoute) return {
				ok: false,
				status: "unknown",
				error: "The verified inference route could not be resolved for owner validation."
			};
			try {
				stagedOwnerPluginArtifacts = (deps.captureSystemAgentOwnerPluginArtifacts ?? captureSystemAgentOwnerPluginArtifacts)({
					config: cfg,
					executionRoute: configuredRoute,
					deps
				});
			} catch {
				return {
					ok: false,
					status: "unavailable",
					error: "Could not bind the configured inference plugin runtime. Refresh or reinstall the plugin and retry."
				};
			}
		}
		let test = await runSetupInferenceTest({
			plan,
			tempDir,
			deps,
			authProfileStateMode: "read-only",
			requireExecutionOwner: requiresExecutionOwner,
			verifyAgentTools: params.verifyAgentTools
		});
		let retained = retainStagedAuthProfiles();
		if (!retained.ok) return retained.result;
		let authProfiles = retained.authProfiles;
		if (test.ok) {
			const verifiedProfileId = test.auth.authProfileId;
			if (plan.authProfileId && verifiedProfileId !== plan.authProfileId) return {
				ok: false,
				status: "auth",
				error: `The inference run used profile "${verifiedProfileId ?? "unknown"}" instead of the configured profile "${plan.authProfileId}".`,
				...authProfiles ? { authProfiles } : {}
			};
			if (params.onVerifiedExecution && !plan.authProfileId && verifiedProfileId) {
				test = await runSetupInferenceTest({
					plan: {
						...plan,
						authProfileId: verifiedProfileId
					},
					tempDir,
					deps,
					authProfileStateMode: "read-only",
					requireExecutionOwner: true,
					verifyAgentTools: params.verifyAgentTools
				});
				retained = retainStagedAuthProfiles();
				if (!retained.ok) return retained.result;
				authProfiles = retained.authProfiles;
				if (!test.ok) return {
					...test,
					error: await redactSetupInferenceError(test.error),
					...authProfiles ? { authProfiles } : {}
				};
				if (test.auth.authProfileId !== verifiedProfileId) return {
					ok: false,
					status: "auth",
					error: "The selected inference credential changed during its locked verification.",
					...authProfiles ? { authProfiles } : {}
				};
			}
			if (params.requireExecutionOwner || params.onVerifiedExecution) try {
				const binding = await revalidateStableSetupInferenceOwner({
					route: configuredRoute,
					auth: test.auth,
					stagedOwnerPluginArtifacts,
					deps
				});
				params.onVerifiedExecution?.(test.auth, binding);
			} catch {
				return {
					ok: false,
					status: "auth",
					error: "The verified inference owner changed before validation completed. Retry the inference check.",
					...authProfiles ? { authProfiles } : {}
				};
			}
			return {
				ok: true,
				latencyMs: test.latencyMs,
				modelRef: plan.modelRef,
				...authProfiles ? { authProfiles } : {}
			};
		}
		return {
			...test,
			error: await redactSetupInferenceError(test.error),
			...authProfiles ? { authProfiles } : {}
		};
	} finally {
		await cleanupSetupInferenceTempDir({
			tempDir,
			deps,
			runtime: params.runtime
		});
	}
}
/** Run one tool-free completion through the configured setup inference route. */
async function completeSetupInference(params) {
	const snapshot = await (params.deps?.readConfigFileSnapshot ?? (await import("./config/config.js")).readConfigFileSnapshot)();
	if (!snapshot.exists) return {
		ok: false,
		status: "unavailable",
		error: "No OpenClaw config exists."
	};
	if (!snapshot.valid) return {
		ok: false,
		status: "format",
		error: invalidSetupConfigError(snapshot)
	};
	return await completeSetupInferenceConfig({
		config: snapshot.runtimeConfig ?? snapshot.config,
		prompt: params.prompt,
		...params.agentId ? { agentId: params.agentId } : {},
		runtime: params.runtime,
		...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
		...params.deps ? { deps: params.deps } : {}
	});
}
/** Config-injected variant used by setup clients and live provider tests. */
async function completeSetupInferenceConfig(params) {
	const deps = {
		...params.deps,
		...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {}
	};
	const routeAgentId = resolveAmbientOwnerAgentId(params.config, params.agentId);
	if (!resolveAgentEffectiveModelPrimary(params.config, routeAgentId)) return {
		ok: false,
		status: "unavailable",
		error: "No agent model is configured."
	};
	const tempDir = await (deps.createTempDir ?? (() => fs.mkdtemp(path.join(os.tmpdir(), "openclaw-setup-inference-"))))();
	try {
		const plan = await buildTestPlan({
			kind: "existing-model",
			cfg: params.config,
			sourceCfg: params.config,
			workspaceDir: tempDir,
			pluginWorkspaceDir: tempDir,
			agentDir: path.join(tempDir, "agent"),
			runtime: params.runtime,
			routeAgentId,
			deps
		});
		if ("error" in plan) return {
			ok: false,
			status: plan.status ?? "unavailable",
			error: plan.error
		};
		const result = await runSetupInferenceTest({
			plan,
			prompt: params.prompt,
			tempDir,
			deps,
			authProfileStateMode: "read-only",
			requireExecutionOwner: false
		});
		if (!result.ok) return {
			...result,
			error: await redactSetupInferenceError(result.error)
		};
		if (plan.authProfileId && result.auth.authProfileId !== plan.authProfileId) return {
			ok: false,
			status: "auth",
			error: "The inference completion used a different credential than the configured route."
		};
		return {
			ok: true,
			modelRef: plan.modelRef,
			latencyMs: result.latencyMs,
			text: result.text
		};
	} finally {
		await cleanupSetupInferenceTempDir({
			tempDir,
			deps,
			runtime: params.runtime
		});
	}
}
//#endregion
export { verifySetupInferenceConfig as a, cleanupSetupInferenceTempDir as c, verifySetupInference as i, completeSetupInferenceConfig as n, activateSetupInference as o, resolvePersistentApplyInference as r, runSetupInferenceTest as s, completeSetupInference as t };