import { c as resolveUserPath } from "./home-dir-BFvskzn8.js";
import "./utils-B2aozS-T.js";
import { r as formatErrorMessage } from "./errors-Z0lU1pH3.js";
import { r as normalizeProviderId } from "./provider-id-DMd-TDFp.js";
import { a as parseProviderModelRef } from "./model-catalog-refs-BdjEHOKQ.js";
import { t as createSubsystemLogger } from "./subsystem-CT-8ly4J.js";
import { h as resolveAmbientOwnerAgentId } from "./agent-scope-config-adSj-fCz.js";
import { t as DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace-default-DNxmF3kK.js";
import { y as normalizeOptionalAgentRuntimeId } from "./openai-routing-WLjNjydC.js";
import { o as resolveAgentEffectiveModelPrimary } from "./agent-scope-CB42Y_8g.js";
import { t as resolveModelRuntimePolicy } from "./model-runtime-policy-BsMumtrf.js";
import { n as enablePluginInConfig, r as enablePluginWithCapabilityConsent } from "./enable-CBvmLCOP.js";
import { t as areRuntimeModelRefsEquivalent } from "./model-runtime-aliases-DNxJWY7c.js";
import { r as resolveManifestProviderAuthChoices } from "./provider-auth-choices-CVDgZn5f.js";
import { t as listRecommendedToolInstalls } from "./recommended-tool-installs-C92crn82.js";
import { a as supportsSetupTextInference, n as listSetupInferenceManualProviders, r as listSetupInferencePrepareOptions, t as listSetupInferenceAuthOptions } from "./setup-inference-auth-options-DDoD9isn.js";
import { t as resolveSetupInferenceCandidateBrandId } from "./setup-inference-brand-vm6tI0LG.js";
//#region src/system-agent/setup-inference-core.ts
const setupInferenceLog = createSubsystemLogger("system-agent/setup-inference");
/**
* Inference is the one required onboarding step (docs/cli/setup.md
* "Setup bootstrap"). This module gives structured clients (macOS app) the
* same ladder the conversation uses, with one hard guarantee: a candidate is
* persisted as the default model only after a real completion round-trips.
* A failing candidate must never leave config pointing at a broken model.
*/
const SETUP_INFERENCE_TEST_TIMEOUT_MS = 9e4;
const SETUP_INFERENCE_TEST_PROMPT = "Reply with the single word OK. Do not use tools.";
const PROVIDER_AUTO_SETUP_KIND_PREFIX = "provider-auto:";
const AUTO_LOCAL_MODEL_LEAN_ANNOUNCEMENT = "This model is small, so I set up the lean surface — switching to a bigger model later lifts it.";
/**
* The config commit may have happened, so callers must verify current setup
* instead of treating this like a definitive candidate failure and retrying.
*/
var SetupInferenceActivationIndeterminateError = class extends Error {
	constructor(..._args) {
		super(..._args);
		this.name = "SetupInferenceActivationIndeterminateError";
	}
};
var SetupInferenceActivationUnavailableError = class extends Error {
	constructor(..._args2) {
		super(..._args2);
		this.name = "SetupInferenceActivationUnavailableError";
	}
};
/**
* The live-tested owner no longer matches current config. Activation maps this
* to `{ ok: false, status: "auth" }` so the guided-onboarding ladder can move
* to its next candidate instead of crashing the CLI.
*/
var SetupInferenceOwnerDriftError = class extends Error {
	constructor(..._args3) {
		super(..._args3);
		this.name = "SetupInferenceOwnerDriftError";
	}
};
var SetupInferenceCancelledError = class extends Error {
	constructor() {
		super("Provider login was cancelled.");
	}
};
function throwIfSetupInferenceCancelled(params) {
	if (params.signal?.aborted || params.isCancelled?.()) throw new SetupInferenceCancelledError();
}
async function waitForProviderAuth(promise, signal) {
	if (!signal) return await promise;
	if (signal.aborted) throw new SetupInferenceCancelledError();
	let rejectAborted;
	const aborted = new Promise((_resolve, reject) => {
		rejectAborted = reject;
	});
	const onAbort = () => rejectAborted?.(new SetupInferenceCancelledError());
	signal.addEventListener("abort", onAbort, { once: true });
	try {
		return await Promise.race([promise, aborted]);
	} finally {
		signal.removeEventListener("abort", onAbort);
	}
}
function toProviderAutoSetupKind(choiceId) {
	return `${PROVIDER_AUTO_SETUP_KIND_PREFIX}${encodeURIComponent(choiceId)}`;
}
function parseProviderAutoSetupChoiceId(kind) {
	if (!kind.startsWith(PROVIDER_AUTO_SETUP_KIND_PREFIX)) return;
	const encoded = kind.slice(14);
	if (!encoded) return;
	try {
		return decodeURIComponent(encoded) || void 0;
	} catch {
		return;
	}
}
function invalidSetupConfigError(snapshot) {
	const issue = snapshot.issues?.[0];
	const detail = issue ? ` (${issue.path ? `${issue.path}: ` : ""}${issue.message})` : "";
	return `OpenClaw config ${snapshot.path} is invalid${detail}. Fix it before running setup.`;
}
async function redactSetupInferenceError(message, ...apiKeys) {
	const secrets = new Set(apiKeys.flatMap((apiKey) => [apiKey, apiKey?.trim()]).filter((value) => Boolean(value)));
	let redacted = message;
	for (const secret of Array.from(secrets).toSorted((a, b) => b.length - a.length)) redacted = redacted.split(secret).join("[redacted]");
	const { redactToolPayloadText } = await import("./redact-CbCOHYCT.js");
	return redactToolPayloadText(redacted);
}
function resolveCandidatePresentation(candidate, authChoices) {
	const choice = authChoices.find((entry) => entry.choiceId === candidate.kind || entry.deprecatedChoiceIds?.includes(candidate.kind) === true);
	const brandId = resolveSetupInferenceCandidateBrandId(candidate, choice?.providerId);
	return {
		...brandId ? { brandId } : {},
		...choice?.icon ? { icon: choice.icon } : {},
		...choice?.website ? { website: choice.website } : {}
	};
}
function resolveSetupInferenceWorkspace(snapshot) {
	return resolveUserPath((snapshot.exists && snapshot.valid ? snapshot.sourceConfig ?? snapshot.config : void 0)?.agents?.defaults?.workspace?.trim() || DEFAULT_AGENT_WORKSPACE_DIR);
}
//#endregion
//#region src/system-agent/setup-inference-detect.ts
function resolveConfiguredCandidateKind(config, modelRef, agentId) {
	if (!modelRef) return;
	const ref = parseProviderModelRef(modelRef);
	if (!ref) return;
	const runtime = normalizeOptionalAgentRuntimeId(resolveModelRuntimePolicy({
		config,
		provider: ref.provider,
		modelId: ref.model,
		agentId: resolveAmbientOwnerAgentId(config ?? {}, agentId)
	}).policy?.id);
	if (runtime === "codex") return "codex-cli";
	if (runtime === "claude-cli") return "claude-cli";
}
async function prepareSetupInferenceOptions(deps, agentId) {
	const { readConfigFileSnapshotWithPluginMetadata } = await import("./config/config.js");
	const { snapshot, pluginMetadataSnapshot } = await readConfigFileSnapshotWithPluginMetadata();
	if (snapshot.exists && !snapshot.valid) throw new Error(invalidSetupConfigError(snapshot));
	const cfg = snapshot.runtimeConfig ?? snapshot.config;
	const targetAgentId = resolveAmbientOwnerAgentId(cfg, agentId);
	const workspace = resolveSetupInferenceWorkspace(snapshot);
	const authChoices = (deps.resolveManifestProviderAuthChoices ?? resolveManifestProviderAuthChoices)({
		config: cfg,
		workspaceDir: workspace,
		metadataSnapshot: pluginMetadataSnapshot,
		includeUntrustedWorkspacePlugins: false,
		includeWorkspacePlugins: false
	}).filter((choice) => (deps.enablePluginInConfig ?? enablePluginInConfig)(cfg, choice.pluginId).enabled);
	return {
		cfg,
		targetAgentId,
		authChoices,
		manual: {
			manualProviders: listSetupInferenceManualProviders(authChoices),
			authOptions: listSetupInferenceAuthOptions(authChoices),
			prepareOptions: listSetupInferencePrepareOptions(authChoices),
			workspace,
			setupComplete: Boolean(resolveAgentEffectiveModelPrimary(cfg, targetAgentId))
		}
	};
}
/** Manual setup options use only config and manifests, never machine or credential probes. */
async function listManualSetupInferenceOptions(deps = {}, agentId) {
	return (await prepareSetupInferenceOptions(deps, agentId)).manual;
}
async function detectSetupInference(deps = {}, agentId) {
	const { cfg, targetAgentId, authChoices, manual } = await prepareSetupInferenceOptions(deps, agentId);
	const { workspace } = manual;
	const partial = {
		...manual,
		candidates: [],
		unavailableCandidates: [],
		recommendedInstalls: listRecommendedToolInstalls()
	};
	deps.onPartial?.(partial);
	const detected = await (deps.detectInferenceBackends ?? (await import("./onboard-inference-B6zmXp72.js")).detectInferenceBackends)({
		config: cfg,
		agentId: targetAgentId
	});
	const unavailableCandidates = [];
	const probe = deps.probeLocalCommand ?? (await import("./probes-qW7loPnc.js")).probeLocalCommand;
	const [pi, opencode] = await Promise.all([probe("pi"), probe("opencode")]);
	if (pi.found && !pi.timedOut) unavailableCandidates.push({
		id: "pi-cli",
		label: "Pi CLI",
		detail: "installed",
		reason: "Pi CLI is installed, but its whole-agent sessions require separate setup and are not a reusable guided-setup inference route."
	});
	if (opencode.found && !opencode.timedOut) unavailableCandidates.push({
		id: "opencode-cli",
		label: "OpenCode CLI",
		detail: "installed",
		reason: "OpenCode CLI is installed, but its ACP harness requires separate setup and is not a reusable guided-setup inference route."
	});
	const configuredModel = detected.find((candidate) => candidate.kind === "existing-model")?.modelRef;
	const configuredCandidateKind = resolveConfiguredCandidateKind(cfg, configuredModel, targetAgentId);
	const candidates = detected.filter((candidate) => candidate.kind !== "gemini-cli" && !(candidate.kind === configuredCandidateKind && configuredModel && areRuntimeModelRefsEquivalent(candidate.modelRef, configuredModel, { config: cfg }))).map((candidate) => Object.assign(candidate, { recommended: false }, resolveCandidatePresentation(candidate, authChoices)));
	const discoveryChoices = authChoices.filter((choice) => choice.appGuidedDiscovery === true && supportsSetupTextInference(choice.onboardingScopes));
	if (discoveryChoices.length > 0) {
		const { withPluginLifecycleLease } = await import("./plugin-lifecycle-lease-B4I1WYVu.js");
		const discovery = await withPluginLifecycleLease({}, async () => {
			let discoveryConfig = cfg;
			const enabledChoices = [];
			for (const choice of discoveryChoices) {
				if (!(await enablePluginWithCapabilityConsent(cfg, choice.pluginId, { workspaceDir: workspace })).enabled) continue;
				discoveryConfig = (deps.enablePluginInConfig ?? enablePluginInConfig)(discoveryConfig, choice.pluginId).config;
				enabledChoices.push(choice);
			}
			const providers = enabledChoices.length ? (deps.resolvePluginProviders ?? (await import("./providers.runtime.js")).resolvePluginProvidersCore)({
				config: discoveryConfig,
				workspaceDir: workspace,
				mode: "setup",
				includeUntrustedWorkspacePlugins: false,
				onlyPluginIds: [...new Set(enabledChoices.map((choice) => choice.pluginId))]
			}) : [];
			return {
				discoveryConfig,
				enabledChoices,
				providers
			};
		});
		const discovered = await Promise.all(discovery.enabledChoices.map(async (choice) => {
			const method = discovery.providers.find((candidate) => candidate.pluginId === choice.pluginId && normalizeProviderId(candidate.id) === normalizeProviderId(choice.providerId))?.auth.find((candidate) => candidate.id === choice.methodId);
			if (!method?.appGuidedSetup) return null;
			try {
				const candidate = await method.appGuidedSetup.detect({
					config: discovery.discoveryConfig,
					env: process.env,
					workspaceDir: workspace
				});
				if (!candidate) return null;
				const ref = parseProviderModelRef(candidate.modelRef);
				if (!ref || normalizeProviderId(ref.provider) !== normalizeProviderId(choice.providerId)) {
					setupInferenceLog.warn(`Ignoring invalid app-guided model ${candidate.modelRef} from ${choice.choiceId}.`);
					return null;
				}
				return Object.assign({
					kind: toProviderAutoSetupKind(choice.choiceId),
					brandId: choice.providerId,
					label: choice.choiceLabel,
					detail: candidate.detail?.trim() || "available locally",
					modelRef: candidate.modelRef,
					recommended: false,
					credentials: true
				}, choice.icon ? { icon: choice.icon } : {}, choice.website ? { website: choice.website } : {});
			} catch (error) {
				setupInferenceLog.debug(`App-guided discovery failed for ${choice.choiceId}: ${formatErrorMessage(error)}`);
				return null;
			}
		}));
		candidates.push(...discovered.filter((candidate) => candidate !== null));
	}
	return {
		...partial,
		candidates,
		unavailableCandidates,
		...configuredModel ? { configuredModel } : {},
		setupComplete: Boolean(configuredModel)
	};
}
//#endregion
export { SETUP_INFERENCE_TEST_TIMEOUT_MS as a, SetupInferenceCancelledError as c, parseProviderAutoSetupChoiceId as d, redactSetupInferenceError as f, waitForProviderAuth as g, throwIfSetupInferenceCancelled as h, SETUP_INFERENCE_TEST_PROMPT as i, SetupInferenceOwnerDriftError as l, setupInferenceLog as m, listManualSetupInferenceOptions as n, SetupInferenceActivationIndeterminateError as o, resolveSetupInferenceWorkspace as p, AUTO_LOCAL_MODEL_LEAN_ANNOUNCEMENT as r, SetupInferenceActivationUnavailableError as s, detectSetupInference as t, invalidSetupConfigError as u };
