import { t as createLazyImportLoader } from "./lazy-promise-BONnzNfb.js";
import { i as hasLegacyAutoFallbackWithoutOrigin } from "./agent-scope-CMwhTQTF.js";
import { r as resolveAgentConfig } from "./agent-scope-config-Di1rn1p5.js";
import { i as listOpenAIAuthProfileProvidersForAgentRuntime } from "./openai-routing-DXJmS9CT.js";
import { n as resolveAgentHarnessPolicy } from "./harness-runtimes-DUsOXCEL.js";
import "./defaults-mDjiWzE5.js";
import { n as isStoredCredentialCompatibleWithAuthProvider } from "./order-17LFFGUW.js";
import { f as parseConfiguredModelVisibilityEntries, r as buildConfiguredModelCatalog } from "./model-selection-shared-DfNPNlQl.js";
import { a as normalizeModelRef, i as modelKey, o as normalizeProviderId, r as legacyModelKey } from "./model-selection-normalize-C6UmVR3Y.js";
import { t as resolveThinkingDefault } from "./model-thinking-default-BQ0QqA4e.js";
import { f as resolveReasoningDefault, u as resolvePersistedOverrideModelRef } from "./model-selection-BsLXn6vT.js";
import { o as resolveContextTokensForModel } from "./context-DtlDIRTg.js";
import { t as applyModelOverrideToSessionEntry } from "./model-overrides-D5WaLvcp.js";
import { n as createModelVisibilityPolicy, t as RUNTIME_MODEL_VISIBILITY_NORMALIZATION } from "./model-visibility-policy-S2N57rlz.js";
import { n as resolveStoredModelOverride, t as isStaleHeartbeatAutoFallbackOverride } from "./stored-model-override-DQuTgLC-.js";
import { t as clearSessionAuthProfileOverride } from "./session-override-4oDrh7A1.js";
import "./model-selection-directive-2OV2_UZq.js";
//#region src/auto-reply/reply/model-selection.ts
/** Model selection state for reply runs, including catalog and override handling. */
/** Creates minimal model-selection state for fast test mode. */
function createFastTestModelSelectionState(params) {
	return {
		provider: params.provider,
		model: params.model,
		allowedModelKeys: /* @__PURE__ */ new Set(),
		allowedModelCatalog: [],
		resetModelOverride: false,
		resetModelOverrideRef: void 0,
		resolveThinkingCatalog: async () => [],
		resolveDefaultThinkingLevel: async () => params.agentCfg?.thinkingDefault,
		resolveDefaultReasoningLevel: async () => "off",
		needsModelCatalog: false,
		modelContextWindow: void 0,
		modelContextTokens: void 0
	};
}
function shouldLogModelSelectionTiming() {
	return process.env.OPENCLAW_DEBUG_INGRESS_TIMING === "1";
}
const modelCatalogRuntimeLoader = createLazyImportLoader(() => import("./agents/model-catalog.runtime.js"));
const sessionAccessorRuntimeLoader = createLazyImportLoader(() => import("./session-accessor-DTh_KGQW.js"));
function normalizeRuntimeModelRef(provider, model) {
	return normalizeModelRef(provider, model, RUNTIME_MODEL_VISIBILITY_NORMALIZATION);
}
function loadModelCatalogRuntime() {
	return modelCatalogRuntimeLoader.load();
}
function loadSessionAccessorRuntime() {
	return sessionAccessorRuntimeLoader.load();
}
function findSelectedCatalogEntry(params) {
	const selectedKey = modelKey(normalizeProviderId(params.provider), params.model);
	return params.catalog?.find((entry) => modelKey(entry.provider, entry.id) === selectedKey);
}
/** Resolves provider/model, allowlist, catalog, and thinking defaults for a reply run. */
async function createModelSelectionState(params) {
	const timingEnabled = shouldLogModelSelectionTiming();
	const startMs = timingEnabled ? Date.now() : 0;
	const logStage = (stage, extra) => {
		if (!timingEnabled) return;
		const suffix = extra ? ` ${extra}` : "";
		console.log(`[model-selection] session=${params.sessionKey ?? "(no-session)"} stage=${stage} elapsedMs=${Date.now() - startMs}${suffix}`);
	};
	const { cfg, agentCfg, sessionEntry, sessionStore, sessionKey, parentSessionKey, storePath, defaultProvider, defaultModel } = params;
	let provider = params.provider;
	let model = params.model;
	const primaryProvider = params.primaryProvider ?? defaultProvider;
	const primaryModel = params.primaryModel ?? defaultModel;
	const hasAllowlist = agentCfg?.models && Object.keys(agentCfg.models).length > 0;
	const visibility = parseConfiguredModelVisibilityEntries({ cfg });
	const defaultProviderVisibleByWildcard = visibility.providerWildcards.has(normalizeProviderId(defaultProvider));
	const configuredModelCatalog = buildConfiguredModelCatalog({ cfg });
	const needsModelCatalog = params.hasModelDirective || Boolean(hasAllowlist && visibility.providerWildcards.size > 0 && !defaultProviderVisibleByWildcard);
	let allowedModelKeys = /* @__PURE__ */ new Set();
	let allowedModelCatalog = configuredModelCatalog;
	let visibilityPolicy = createModelVisibilityPolicy({
		cfg,
		catalog: configuredModelCatalog,
		defaultProvider,
		defaultModel,
		agentId: params.agentId,
		...RUNTIME_MODEL_VISIBILITY_NORMALIZATION
	});
	let modelCatalog = null;
	let resetModelOverride = false;
	let resetModelOverrideRef;
	const agentEntry = params.agentId ? resolveAgentConfig(cfg, params.agentId) : void 0;
	const directStoredOverride = resolvePersistedOverrideModelRef({
		defaultProvider,
		overrideProvider: sessionEntry?.providerOverride,
		overrideModel: sessionEntry?.modelOverride
	});
	const directStoredModelOverride = directStoredOverride ? {
		...directStoredOverride,
		source: "session"
	} : null;
	const staleHeartbeatAutoFallbackOverride = isStaleHeartbeatAutoFallbackOverride({
		isHeartbeat: params.isHeartbeat,
		hasResolvedHeartbeatModelOverride: params.hasResolvedHeartbeatModelOverride,
		sessionEntry,
		storedOverride: directStoredModelOverride,
		defaultProvider,
		defaultModel,
		primaryProvider: params.primaryProvider,
		primaryModel: params.primaryModel
	});
	const primaryHarnessPolicy = resolveAgentHarnessPolicy({
		provider: primaryProvider,
		modelId: primaryModel,
		config: cfg,
		agentId: params.agentId,
		sessionKey
	});
	const staleLegacyOpenAICodexAutoOverride = directStoredModelOverride?.source === "session" && sessionEntry?.modelOverrideSource === "auto" && normalizeProviderId(directStoredModelOverride.provider ?? "") === "openai" && normalizeProviderId(primaryProvider) === "openai" && primaryHarnessPolicy.runtime === "codex" && normalizeRuntimeModelRef("openai", directStoredModelOverride.model).model === normalizeRuntimeModelRef("openai", primaryModel).model;
	const normalizedCurrentSelection = normalizeRuntimeModelRef(provider, model);
	const normalizedDirectOverride = directStoredModelOverride ? normalizeRuntimeModelRef(directStoredModelOverride.provider, directStoredModelOverride.model) : null;
	const staleLegacyAutoFallbackWithoutOrigin = directStoredModelOverride?.source === "session" && hasLegacyAutoFallbackWithoutOrigin(sessionEntry) && normalizedDirectOverride !== null && modelKey(normalizedCurrentSelection.provider, normalizedCurrentSelection.model) !== modelKey(normalizedDirectOverride.provider, normalizedDirectOverride.model);
	const staleDirectStoredOverride = staleHeartbeatAutoFallbackOverride || staleLegacyOpenAICodexAutoOverride || staleLegacyAutoFallbackWithoutOrigin;
	if (needsModelCatalog) {
		modelCatalog = await (await loadModelCatalogRuntime()).loadModelCatalog({ config: cfg });
		logStage("catalog-loaded", `entries=${modelCatalog.length}`);
		visibilityPolicy = createModelVisibilityPolicy({
			cfg,
			catalog: modelCatalog,
			defaultProvider,
			defaultModel,
			agentId: params.agentId,
			...RUNTIME_MODEL_VISIBILITY_NORMALIZATION
		});
		allowedModelCatalog = visibilityPolicy.allowedCatalog;
		allowedModelKeys = visibilityPolicy.allowedKeys;
		logStage("allowlist-built", `allowed=${allowedModelCatalog.length} keys=${allowedModelKeys.size}`);
	} else if (hasAllowlist) {
		visibilityPolicy = createModelVisibilityPolicy({
			cfg,
			catalog: configuredModelCatalog,
			defaultProvider,
			defaultModel,
			agentId: params.agentId,
			...RUNTIME_MODEL_VISIBILITY_NORMALIZATION
		});
		allowedModelCatalog = visibilityPolicy.allowedCatalog;
		allowedModelKeys = visibilityPolicy.allowedKeys;
		logStage("configured-allowlist-built", `allowed=${allowedModelCatalog.length} keys=${allowedModelKeys.size}`);
	} else if (configuredModelCatalog.length > 0) logStage("configured-catalog-ready", `entries=${configuredModelCatalog.length}`);
	if (sessionEntry && sessionStore && sessionKey && directStoredOverride) {
		const normalizedOverride = normalizeRuntimeModelRef(directStoredOverride.provider, directStoredOverride.model);
		const key = modelKey(normalizedOverride.provider, normalizedOverride.model);
		if (staleDirectStoredOverride || !visibilityPolicy.allowsKey(key)) {
			const { updated } = applyModelOverrideToSessionEntry({
				entry: sessionEntry,
				selection: {
					provider: primaryProvider,
					model: primaryModel,
					isDefault: true
				},
				preserveAuthProfileOverride: staleDirectStoredOverride
			});
			if (updated) {
				sessionStore[sessionKey] = sessionEntry;
				if (storePath) {
					const { replaceSessionEntry } = await loadSessionAccessorRuntime();
					await replaceSessionEntry({
						storePath,
						sessionKey
					}, sessionEntry);
				}
			}
			resetModelOverride = updated;
			if (updated) resetModelOverrideRef = key;
		}
	}
	if (staleDirectStoredOverride) {
		if (modelKey(normalizedCurrentSelection.provider, normalizedCurrentSelection.model) === (normalizedDirectOverride ? modelKey(normalizedDirectOverride.provider, normalizedDirectOverride.model) : void 0)) {
			provider = primaryProvider;
			model = primaryModel;
		}
	}
	const storedOverride = resolveStoredModelOverride({
		sessionEntry,
		sessionStore,
		sessionKey,
		parentSessionKey,
		defaultProvider
	});
	const skipStoredOverride = params.skipStoredModelOverride === true || params.hasResolvedHeartbeatModelOverride === true || staleDirectStoredOverride && storedOverride?.source === "session";
	if (storedOverride?.model && !skipStoredOverride) {
		const normalizedStoredOverride = normalizeRuntimeModelRef(storedOverride.provider || defaultProvider, storedOverride.model);
		const key = modelKey(normalizedStoredOverride.provider, normalizedStoredOverride.model);
		if (visibilityPolicy.allowsKey(key)) {
			provider = normalizedStoredOverride.provider;
			model = normalizedStoredOverride.model;
		}
	}
	if (!params.hasModelDirective) {
		const allowedInitialSelection = visibilityPolicy.resolveSelection({
			provider,
			model
		});
		if (!allowedInitialSelection) throw new Error(`Configured default model "${modelKey(provider, model)}" is not allowed by agents.defaults.models, and no allowed model is available.`);
		provider = allowedInitialSelection.provider;
		model = allowedInitialSelection.model;
	}
	if (!params.skipStoredModelOverride && sessionEntry && sessionStore && sessionKey && sessionEntry.authProfileOverride) {
		const { ensureAuthProfileStore } = await import("./agents/auth-profiles.runtime.js");
		const store = ensureAuthProfileStore(void 0, { allowKeychainPrompt: false });
		logStage("auth-profile-store-loaded", `profiles=${Object.keys(store.profiles).length}`);
		const profile = store.profiles[sessionEntry.authProfileOverride];
		const harnessPolicy = resolveAgentHarnessPolicy({
			provider,
			modelId: model,
			config: cfg,
			agentId: params.agentId,
			sessionKey
		});
		const acceptedAuthProviders = listOpenAIAuthProfileProvidersForAgentRuntime({
			provider,
			harnessRuntime: harnessPolicy.runtime,
			config: cfg
		}).map(normalizeProviderId);
		if (!(profile != null && acceptedAuthProviders.some((accepted) => isStoredCredentialCompatibleWithAuthProvider({
			cfg,
			provider: accepted,
			credential: profile
		})))) await clearSessionAuthProfileOverride({
			sessionEntry,
			sessionStore,
			sessionKey,
			storePath
		});
	}
	let thinkingCatalog;
	let manifestModelCatalog = null;
	const buildThinkingCatalog = (catalog) => createModelVisibilityPolicy({
		cfg,
		catalog,
		defaultProvider,
		defaultModel,
		agentId: params.agentId,
		...RUNTIME_MODEL_VISIBILITY_NORMALIZATION
	}).allowedCatalog;
	const loadManifestCatalog = async () => {
		if (manifestModelCatalog) return manifestModelCatalog;
		const { loadManifestModelCatalog } = await loadModelCatalogRuntime();
		manifestModelCatalog = loadManifestModelCatalog({
			config: cfg,
			fallbackToMetadataScan: false
		});
		logStage("manifest-catalog-loaded", `entries=${manifestModelCatalog.length}`);
		return manifestModelCatalog;
	};
	const resolveThinkingCatalog = async () => {
		if (thinkingCatalog) return thinkingCatalog;
		let catalogForThinking = allowedModelCatalog.length > 0 ? allowedModelCatalog : modelCatalog && modelCatalog.length > 0 ? buildThinkingCatalog(modelCatalog) : [];
		let selectedCatalogEntry = findSelectedCatalogEntry({
			catalog: catalogForThinking,
			provider,
			model
		});
		if (!modelCatalog && selectedCatalogEntry?.reasoning === void 0) {
			const manifestCatalog = buildThinkingCatalog(await loadManifestCatalog());
			const manifestSelectedEntry = findSelectedCatalogEntry({
				catalog: manifestCatalog,
				provider,
				model
			});
			if (manifestSelectedEntry?.reasoning !== void 0) {
				catalogForThinking = manifestCatalog;
				selectedCatalogEntry = manifestSelectedEntry;
			}
		}
		if (!modelCatalog && (!selectedCatalogEntry || selectedCatalogEntry.reasoning === void 0)) {
			modelCatalog = await (await loadModelCatalogRuntime()).loadModelCatalog({ config: cfg });
			logStage("catalog-loaded-for-thinking", `entries=${modelCatalog.length}`);
			const runtimeCatalog = buildThinkingCatalog(modelCatalog);
			catalogForThinking = findSelectedCatalogEntry({
				catalog: runtimeCatalog,
				provider,
				model
			}) || !catalogForThinking || catalogForThinking.length === 0 ? runtimeCatalog.length > 0 ? runtimeCatalog : allowedModelCatalog : allowedModelCatalog;
		}
		thinkingCatalog = catalogForThinking.length > 0 ? catalogForThinking : void 0;
		return thinkingCatalog;
	};
	let defaultThinkingLevel;
	const resolveDefaultThinkingLevel = async () => {
		if (defaultThinkingLevel) return defaultThinkingLevel;
		const agentThinkingDefault = agentEntry?.thinkingDefault;
		if (agentThinkingDefault) {
			defaultThinkingLevel = agentThinkingDefault;
			return defaultThinkingLevel;
		}
		const configuredModels = cfg.agents?.defaults?.models;
		const canonicalKey = modelKey(provider, model);
		const legacyKey = legacyModelKey(provider, model);
		const configuredModelThinkingDefault = configuredModels?.[canonicalKey]?.params?.thinking ?? (legacyKey ? configuredModels?.[legacyKey]?.params?.thinking : void 0);
		if (configuredModelThinkingDefault === false || configuredModelThinkingDefault === "disabled" || configuredModelThinkingDefault === "none") {
			defaultThinkingLevel = "off";
			return defaultThinkingLevel;
		}
		if (configuredModelThinkingDefault === "off" || configuredModelThinkingDefault === "minimal" || configuredModelThinkingDefault === "low" || configuredModelThinkingDefault === "medium" || configuredModelThinkingDefault === "high" || configuredModelThinkingDefault === "xhigh" || configuredModelThinkingDefault === "adaptive" || configuredModelThinkingDefault === "max") {
			defaultThinkingLevel = configuredModelThinkingDefault;
			return defaultThinkingLevel;
		}
		const configuredThinkingDefault = agentCfg?.thinkingDefault;
		if (configuredThinkingDefault) {
			defaultThinkingLevel = configuredThinkingDefault;
			return defaultThinkingLevel;
		}
		const catalogForThinking = await resolveThinkingCatalog();
		defaultThinkingLevel = resolveThinkingDefault({
			cfg,
			provider,
			model,
			catalog: catalogForThinking
		}) ?? "off";
		return defaultThinkingLevel;
	};
	let defaultReasoningLevel;
	const resolveDefaultReasoningLevel = async () => {
		if (defaultReasoningLevel) return defaultReasoningLevel;
		let catalogForReasoning = modelCatalog ?? allowedModelCatalog;
		let selectedReasoningEntry = findSelectedCatalogEntry({
			catalog: catalogForReasoning,
			provider,
			model
		});
		if (!modelCatalog && selectedReasoningEntry?.reasoning === void 0) {
			const manifestCatalog = await loadManifestCatalog();
			const manifestReasoningCatalog = hasAllowlist ? buildThinkingCatalog(manifestCatalog) : manifestCatalog;
			const manifestSelectedEntry = findSelectedCatalogEntry({
				catalog: manifestReasoningCatalog,
				provider,
				model
			});
			if (manifestSelectedEntry?.reasoning !== void 0) {
				catalogForReasoning = manifestReasoningCatalog;
				selectedReasoningEntry = manifestSelectedEntry;
			}
		}
		if ((!catalogForReasoning || catalogForReasoning.length === 0) && selectedReasoningEntry?.reasoning === void 0) {
			modelCatalog = await (await loadModelCatalogRuntime()).loadModelCatalog({ config: cfg });
			logStage("catalog-loaded-for-reasoning", `entries=${modelCatalog.length}`);
			catalogForReasoning = modelCatalog;
		}
		defaultReasoningLevel = resolveReasoningDefault({
			provider,
			model,
			catalog: catalogForReasoning
		});
		return defaultReasoningLevel;
	};
	const selectedCatalogEntry = findSelectedCatalogEntry({
		catalog: modelCatalog ?? allowedModelCatalog,
		provider,
		model
	});
	return {
		provider,
		model,
		allowedModelKeys,
		allowedModelCatalog,
		resetModelOverride,
		resetModelOverrideRef,
		resolveThinkingCatalog,
		resolveDefaultThinkingLevel,
		resolveDefaultReasoningLevel,
		needsModelCatalog,
		modelContextWindow: selectedCatalogEntry?.contextWindow,
		modelContextTokens: selectedCatalogEntry?.contextTokens
	};
}
/** Resolves the context window token count for the selected provider/model. */
function resolveContextTokens(params) {
	const modelContextTokens = resolveContextTokensForModel({
		cfg: params.cfg,
		provider: params.provider,
		model: params.model,
		modelContextWindow: params.modelContextWindow,
		modelContextTokens: params.modelContextTokens,
		allowAsyncLoad: false
	});
	const agentContextTokens = typeof params.agentCfg?.contextTokens === "number" && params.agentCfg.contextTokens > 0 ? Math.floor(params.agentCfg.contextTokens) : void 0;
	if (agentContextTokens !== void 0) return modelContextTokens !== void 0 ? Math.min(agentContextTokens, modelContextTokens) : agentContextTokens;
	return modelContextTokens ?? 2e5;
}
//#endregion
export { createModelSelectionState as n, resolveContextTokens as r, createFastTestModelSelectionState as t };
