import { B as normalizeThinkLevel, F as formatXHighModelHint, H as normalizeVerboseLevel, P as formatThinkingLevels, W as supportsXHighThinking } from "./pi-embedded-helpers-Df7l-4vq.js";
import { B as resolveOutboundTarget, Lt as getRemoteSkillEligibility, Sn as KOI_LANE_NESTED, Ut as getSkillsSnapshotVersion, V as resolveSessionDeliveryTarget, c as runEmbeddedPiKoi, cr as lookupContextTokens, dr as applyVerboseOverride, gr as loadModelCatalog, i as runCliKoi, jr as resolveKoiTimeoutMs, lr as clearSessionAuthProfileOverride, n as getCliSessionId, nt as runWithModelFallback, o as resolveSendPolicy, p as compactEmbeddedPiSession, r as setCliSessionId, ur as applyModelOverrideToSessionEntry } from "./reply-CZUaueaY.js";
import { k as DEFAULT_CHAT_CHANNEL, s as defaultRuntime } from "./subsystem-hATE68va.js";
import { d as resolveKoiIdFromSessionKey, l as normalizeKoiId, u as normalizeMainKey } from "./session-key-B2OXLVi_.js";
import { S as ensureKoiWorkspace, a as resolveKoiDir, c as resolveKoiSkillsFilter, l as resolveKoiWorkspaceDir, n as listKoiIds, o as resolveKoiModelFallbacksOverride, s as resolveKoiModelPrimary } from "./koi-scope-BeICsBhH.js";
import { Ct as DEFAULT_PROVIDER, St as DEFAULT_MODEL, a as isCliProvider, d as resolveConfiguredModelRef, h as resolveThinkingDefault, o as modelKey, ot as ensureAuthProfileStore, t as buildAllowedModelSet, xt as DEFAULT_CONTEXT_TOKENS } from "./model-selection-DvQd6xjM.js";
import { o as loadConfig } from "./config-BOTdzMIB.js";
import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-dW6cc0qG.js";
import { C as resolveSessionResetPolicy, D as mergeSessionEntry, S as resolveChannelResetConfig, b as resolveSessionKey, i as loadSessionStore, k as resolveExplicitKoiSessionKey, l as updateSessionStore, v as normalizeAccountId, w as resolveSessionResetType, x as evaluateSessionFreshness } from "./sessions-DyqGkYWU.js";
import { r as buildWorkspaceSkillSnapshot } from "./skills-DHpPesfZ.js";
import { a as isInternalMessageChannel, d as resolveMessageChannel, i as isGatewayMessageChannel, l as normalizeMessageChannel, n as isDeliverableMessageChannel, t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-B-LM-U45.js";
import { n as resolveSessionFilePath, o as resolveStorePath } from "./paths-DSzdyYR5.js";
import { a as normalizeOutboundPayloadsForJson, i as normalizeOutboundPayloads, r as formatOutboundPayloadLog, t as deliverOutboundPayloads } from "./deliver-BU-ss2iZ.js";
import { n as emitKoiEvent, o as registerKoiRunContext, t as clearKoiRunContext } from "./koi-events-CVGX2xkt.js";
import { l as hasNonzeroUsage } from "./session-cost-usage-BiwFgQ3E.js";
import { t as createDefaultDeps } from "./deps-BkqEahC_.js";
import crypto from "node:crypto";

//#region src/cli/outbound-send-deps.ts
function createOutboundSendDeps(deps) {
	return {
		sendWhatsApp: deps.sendMessageWhatsApp,
		sendTelegram: deps.sendMessageTelegram,
		sendDiscord: deps.sendMessageDiscord,
		sendSlack: deps.sendMessageSlack,
		sendSignal: deps.sendMessageSignal,
		sendIMessage: deps.sendMessageIMessage
	};
}

//#endregion
//#region src/infra/outbound/koi-delivery.ts
function resolveKoiDeliveryPlan(params) {
	const requestedRaw = typeof params.requestedChannel === "string" ? params.requestedChannel.trim() : "";
	const requestedChannel = (requestedRaw ? normalizeMessageChannel(requestedRaw) : void 0) || "last";
	const explicitTo = typeof params.explicitTo === "string" && params.explicitTo.trim() ? params.explicitTo.trim() : void 0;
	const baseDelivery = resolveSessionDeliveryTarget({
		entry: params.sessionEntry,
		requestedChannel: requestedChannel === INTERNAL_MESSAGE_CHANNEL ? "last" : requestedChannel,
		explicitTo,
		explicitThreadId: params.explicitThreadId
	});
	const resolvedChannel = (() => {
		if (requestedChannel === INTERNAL_MESSAGE_CHANNEL) return INTERNAL_MESSAGE_CHANNEL;
		if (requestedChannel === "last") {
			if (baseDelivery.channel && baseDelivery.channel !== INTERNAL_MESSAGE_CHANNEL) return baseDelivery.channel;
			return params.wantsDelivery ? DEFAULT_CHAT_CHANNEL : INTERNAL_MESSAGE_CHANNEL;
		}
		if (isGatewayMessageChannel(requestedChannel)) return requestedChannel;
		if (baseDelivery.channel && baseDelivery.channel !== INTERNAL_MESSAGE_CHANNEL) return baseDelivery.channel;
		return params.wantsDelivery ? DEFAULT_CHAT_CHANNEL : INTERNAL_MESSAGE_CHANNEL;
	})();
	const deliveryTargetMode = explicitTo ? "explicit" : isDeliverableMessageChannel(resolvedChannel) ? "implicit" : void 0;
	const resolvedAccountId = normalizeAccountId(params.accountId) ?? (deliveryTargetMode === "implicit" ? baseDelivery.accountId : void 0);
	let resolvedTo = explicitTo;
	if (!resolvedTo && isDeliverableMessageChannel(resolvedChannel) && resolvedChannel === baseDelivery.lastChannel) resolvedTo = baseDelivery.lastTo;
	return {
		baseDelivery,
		resolvedChannel,
		resolvedTo,
		resolvedAccountId,
		resolvedThreadId: baseDelivery.threadId,
		deliveryTargetMode
	};
}
function resolveKoiOutboundTarget(params) {
	const targetMode = params.targetMode ?? params.plan.deliveryTargetMode ?? (params.plan.resolvedTo ? "explicit" : "implicit");
	if (!isDeliverableMessageChannel(params.plan.resolvedChannel)) return {
		resolvedTarget: null,
		resolvedTo: params.plan.resolvedTo,
		targetMode
	};
	if (params.validateExplicitTarget !== true && params.plan.resolvedTo) return {
		resolvedTarget: null,
		resolvedTo: params.plan.resolvedTo,
		targetMode
	};
	const resolvedTarget = resolveOutboundTarget({
		channel: params.plan.resolvedChannel,
		to: params.plan.resolvedTo,
		cfg: params.cfg,
		accountId: params.plan.resolvedAccountId,
		mode: targetMode
	});
	return {
		resolvedTarget,
		resolvedTo: resolvedTarget.ok ? resolvedTarget.to : params.plan.resolvedTo,
		targetMode
	};
}

//#endregion
//#region src/infra/outbound/envelope.ts
const isOutboundPayloadJson = (payload) => "mediaUrl" in payload;
function buildOutboundResultEnvelope(params) {
	const hasPayloads = params.payloads !== void 0;
	const payloads = params.payloads === void 0 ? void 0 : params.payloads.length === 0 ? [] : isOutboundPayloadJson(params.payloads[0]) ? params.payloads : normalizeOutboundPayloadsForJson(params.payloads);
	if (params.flattenDelivery !== false && params.delivery && !params.meta && !hasPayloads) return params.delivery;
	return {
		...hasPayloads ? { payloads } : {},
		...params.meta ? { meta: params.meta } : {},
		...params.delivery ? { delivery: params.delivery } : {}
	};
}

//#endregion
//#region src/commands/koi/delivery.ts
const NESTED_LOG_PREFIX = "[koi:nested]";
function formatNestedLogPrefix(opts) {
	const parts = [NESTED_LOG_PREFIX];
	const session = opts.sessionKey ?? opts.sessionId;
	if (session) parts.push(`session=${session}`);
	if (opts.runId) parts.push(`run=${opts.runId}`);
	const channel = opts.messageChannel ?? opts.channel;
	if (channel) parts.push(`channel=${channel}`);
	if (opts.to) parts.push(`to=${opts.to}`);
	if (opts.accountId) parts.push(`account=${opts.accountId}`);
	return parts.join(" ");
}
function logNestedOutput(runtime, opts, output) {
	const prefix = formatNestedLogPrefix(opts);
	for (const line of output.split(/\r?\n/)) {
		if (!line) continue;
		runtime.log(`${prefix} ${line}`);
	}
}
async function deliverKoiCommandResult(params) {
	const { cfg, deps, runtime, opts, sessionEntry, payloads, result } = params;
	const deliver = opts.deliver === true;
	const bestEffortDeliver = opts.bestEffortDeliver === true;
	const deliveryPlan = resolveKoiDeliveryPlan({
		sessionEntry,
		requestedChannel: opts.replyChannel ?? opts.channel,
		explicitTo: opts.replyTo ?? opts.to,
		explicitThreadId: opts.threadId,
		accountId: opts.replyAccountId ?? opts.accountId,
		wantsDelivery: deliver
	});
	const deliveryChannel = deliveryPlan.resolvedChannel;
	const deliveryPlugin = !isInternalMessageChannel(deliveryChannel) ? getChannelPlugin(normalizeChannelId(deliveryChannel) ?? deliveryChannel) : void 0;
	const isDeliveryChannelKnown = isInternalMessageChannel(deliveryChannel) || Boolean(deliveryPlugin);
	const targetMode = opts.deliveryTargetMode ?? deliveryPlan.deliveryTargetMode ?? (opts.to ? "explicit" : "implicit");
	const resolvedAccountId = deliveryPlan.resolvedAccountId;
	const resolved = deliver && isDeliveryChannelKnown && deliveryChannel ? resolveKoiOutboundTarget({
		cfg,
		plan: deliveryPlan,
		targetMode,
		validateExplicitTarget: true
	}) : {
		resolvedTarget: null,
		resolvedTo: deliveryPlan.resolvedTo,
		targetMode
	};
	const resolvedTarget = resolved.resolvedTarget;
	const deliveryTarget = resolved.resolvedTo;
	const resolvedThreadId = deliveryPlan.resolvedThreadId ?? opts.threadId;
	const resolvedReplyToId = deliveryChannel === "slack" && resolvedThreadId != null ? String(resolvedThreadId) : void 0;
	const resolvedThreadTarget = deliveryChannel === "slack" ? void 0 : resolvedThreadId;
	const logDeliveryError = (err) => {
		const message = `Delivery failed (${deliveryChannel}${deliveryTarget ? ` to ${deliveryTarget}` : ""}): ${String(err)}`;
		runtime.error?.(message);
		if (!runtime.error) runtime.log(message);
	};
	if (deliver) {
		if (!isDeliveryChannelKnown) {
			const err = /* @__PURE__ */ new Error(`Unknown channel: ${deliveryChannel}`);
			if (!bestEffortDeliver) throw err;
			logDeliveryError(err);
		} else if (resolvedTarget && !resolvedTarget.ok) {
			if (!bestEffortDeliver) throw resolvedTarget.error;
			logDeliveryError(resolvedTarget.error);
		}
	}
	const normalizedPayloads = normalizeOutboundPayloadsForJson(payloads ?? []);
	if (opts.json) {
		runtime.log(JSON.stringify(buildOutboundResultEnvelope({
			payloads: normalizedPayloads,
			meta: result.meta
		}), null, 2));
		if (!deliver) return {
			payloads: normalizedPayloads,
			meta: result.meta
		};
	}
	if (!payloads || payloads.length === 0) {
		runtime.log("No reply from koi.");
		return {
			payloads: [],
			meta: result.meta
		};
	}
	const deliveryPayloads = normalizeOutboundPayloads(payloads);
	const logPayload = (payload) => {
		if (opts.json) return;
		const output = formatOutboundPayloadLog(payload);
		if (!output) return;
		if (opts.lane === KOI_LANE_NESTED) {
			logNestedOutput(runtime, opts, output);
			return;
		}
		runtime.log(output);
	};
	if (!deliver) for (const payload of deliveryPayloads) logPayload(payload);
	if (deliver && deliveryChannel && !isInternalMessageChannel(deliveryChannel)) {
		if (deliveryTarget) await deliverOutboundPayloads({
			cfg,
			channel: deliveryChannel,
			to: deliveryTarget,
			accountId: resolvedAccountId,
			payloads: deliveryPayloads,
			replyToId: resolvedReplyToId ?? null,
			threadId: resolvedThreadTarget ?? null,
			bestEffort: bestEffortDeliver,
			onError: (err) => logDeliveryError(err),
			onPayload: logPayload,
			deps: createOutboundSendDeps(deps)
		});
	}
	return {
		payloads: normalizedPayloads,
		meta: result.meta
	};
}

//#endregion
//#region src/commands/koi/run-context.ts
function resolveKoiRunContext(opts) {
	const merged = opts.runContext ? { ...opts.runContext } : {};
	const normalizedChannel = resolveMessageChannel(merged.messageChannel ?? opts.messageChannel, opts.replyChannel ?? opts.channel);
	if (normalizedChannel) merged.messageChannel = normalizedChannel;
	const normalizedAccountId = normalizeAccountId(merged.accountId ?? opts.accountId);
	if (normalizedAccountId) merged.accountId = normalizedAccountId;
	const groupId = (merged.groupId ?? opts.groupId)?.toString().trim();
	if (groupId) merged.groupId = groupId;
	const groupChannel = (merged.groupChannel ?? opts.groupChannel)?.toString().trim();
	if (groupChannel) merged.groupChannel = groupChannel;
	const groupSpace = (merged.groupSpace ?? opts.groupSpace)?.toString().trim();
	if (groupSpace) merged.groupSpace = groupSpace;
	if (merged.currentThreadTs == null && opts.threadId != null && opts.threadId !== "" && opts.threadId !== null) merged.currentThreadTs = String(opts.threadId);
	if (!merged.currentChannelId && opts.to) {
		const trimmedTo = opts.to.trim();
		if (trimmedTo) merged.currentChannelId = trimmedTo;
	}
	return merged;
}

//#endregion
//#region src/commands/koi/session-store.ts
async function updateSessionStoreAfterKoiRun(params) {
	const { cfg, sessionId, sessionKey, storePath, sessionStore, defaultProvider, defaultModel, fallbackProvider, fallbackModel, result } = params;
	const usage = result.meta.koiMeta?.usage;
	const modelUsed = result.meta.koiMeta?.model ?? fallbackModel ?? defaultModel;
	const providerUsed = result.meta.koiMeta?.provider ?? fallbackProvider ?? defaultProvider;
	const contextTokens = params.contextTokensOverride ?? lookupContextTokens(modelUsed) ?? DEFAULT_CONTEXT_TOKENS;
	const baseEntry = sessionStore[sessionKey] ?? {
		sessionId,
		updatedAt: Date.now()
	};
	const patch = {
		sessionId,
		updatedAt: Date.now(),
		modelProvider: providerUsed,
		model: modelUsed,
		contextTokens
	};
	if (isCliProvider(providerUsed, cfg)) {
		const cliSessionId = result.meta.koiMeta?.sessionId?.trim();
		if (cliSessionId) {
			const cliPatchEntry = mergeSessionEntry(baseEntry, patch);
			setCliSessionId(cliPatchEntry, providerUsed, cliSessionId);
			patch.cliSessionIds = cliPatchEntry.cliSessionIds;
			patch.claudeCliSessionId = cliPatchEntry.claudeCliSessionId;
		}
	}
	patch.abortedLastRun = result.meta.aborted ?? false;
	if (hasNonzeroUsage(usage)) {
		const input = usage.input ?? 0;
		const output = usage.output ?? 0;
		const promptTokens = input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
		patch.inputTokens = input;
		patch.outputTokens = output;
		patch.totalTokens = promptTokens > 0 ? promptTokens : usage.total ?? input;
	}
	sessionStore[sessionKey] = mergeSessionEntry(baseEntry, patch);
	await updateSessionStore(storePath, (store) => {
		store[sessionKey] = mergeSessionEntry(store[sessionKey], patch);
	});
}

//#endregion
//#region src/commands/koi/session.ts
function resolveSessionKeyForRequest(opts) {
	const sessionCfg = opts.cfg.session;
	const scope = sessionCfg?.scope ?? "per-sender";
	const mainKey = normalizeMainKey(sessionCfg?.mainKey);
	const explicitSessionKey = opts.sessionKey?.trim() || resolveExplicitKoiSessionKey({
		cfg: opts.cfg,
		koiId: opts.koiId
	});
	const storeKoiId = resolveKoiIdFromSessionKey(explicitSessionKey);
	const storePath = resolveStorePath(sessionCfg?.store, { koiId: storeKoiId });
	const sessionStore = loadSessionStore(storePath);
	const ctx = opts.to?.trim() ? { From: opts.to } : void 0;
	let sessionKey = explicitSessionKey ?? (ctx ? resolveSessionKey(scope, ctx, mainKey) : void 0);
	if (!explicitSessionKey && opts.sessionId && (!sessionKey || sessionStore[sessionKey]?.sessionId !== opts.sessionId)) {
		const foundKey = Object.keys(sessionStore).find((key) => sessionStore[key]?.sessionId === opts.sessionId);
		if (foundKey) sessionKey = foundKey;
	}
	return {
		sessionKey,
		sessionStore,
		storePath
	};
}
function resolveSession(opts) {
	const sessionCfg = opts.cfg.session;
	const { sessionKey, sessionStore, storePath } = resolveSessionKeyForRequest({
		cfg: opts.cfg,
		to: opts.to,
		sessionId: opts.sessionId,
		sessionKey: opts.sessionKey,
		koiId: opts.koiId
	});
	const now = Date.now();
	const sessionEntry = sessionKey ? sessionStore[sessionKey] : void 0;
	const resetPolicy = resolveSessionResetPolicy({
		sessionCfg,
		resetType: resolveSessionResetType({ sessionKey }),
		resetOverride: resolveChannelResetConfig({
			sessionCfg,
			channel: sessionEntry?.lastChannel ?? sessionEntry?.channel
		})
	});
	const fresh = sessionEntry ? evaluateSessionFreshness({
		updatedAt: sessionEntry.updatedAt,
		now,
		policy: resetPolicy
	}).fresh : false;
	return {
		sessionId: opts.sessionId?.trim() || (fresh ? sessionEntry?.sessionId : void 0) || crypto.randomUUID(),
		sessionKey,
		sessionEntry,
		sessionStore,
		storePath,
		isNewSession: !fresh && !opts.sessionId,
		persistedThinking: fresh && sessionEntry?.thinkingLevel ? normalizeThinkLevel(sessionEntry.thinkingLevel) : void 0,
		persistedVerbose: fresh && sessionEntry?.verboseLevel ? normalizeVerboseLevel(sessionEntry.verboseLevel) : void 0
	};
}

//#endregion
//#region src/commands/koi.ts
async function koiCommand(opts, runtime = defaultRuntime, deps = createDefaultDeps()) {
	const body = (opts.message ?? "").trim();
	if (!body) throw new Error("Message (--message) is required");
	if (!opts.to && !opts.sessionId && !opts.sessionKey && !opts.koiId) throw new Error("Pass --to <E.164>, --session-id, or --koi to choose a session");
	const cfg = loadConfig();
	const koiIdOverrideRaw = opts.koiId?.trim();
	const koiIdOverride = koiIdOverrideRaw ? normalizeKoiId(koiIdOverrideRaw) : void 0;
	if (koiIdOverride) {
		if (!listKoiIds(cfg).includes(koiIdOverride)) {
			if (!opts.allowUnlistedKoi) throw new Error(`Unknown koi id "${koiIdOverrideRaw}"`);
			defaultRuntime.log(`[koiCommand] koi "${koiIdOverrideRaw}" not in cfg.kois.list — proceeding with id-derived workspace fallback`);
		}
	}
	const koiCfg = cfg.kois?.defaults;
	const sessionKoiId = resolveKoiIdFromSessionKey(opts.sessionKey?.trim());
	const speakerKoiId = koiIdOverride ?? sessionKoiId;
	const workspaceDirRaw = resolveKoiWorkspaceDir(cfg, speakerKoiId);
	const koiDir = resolveKoiDir(cfg, speakerKoiId);
	const workspaceDir = (await ensureKoiWorkspace({
		dir: workspaceDirRaw,
		ensureBootstrapFiles: !koiCfg?.skipBootstrap
	})).dir;
	const configuredModel = resolveConfiguredModelRef({
		cfg,
		defaultProvider: DEFAULT_PROVIDER,
		defaultModel: DEFAULT_MODEL
	});
	const thinkingLevelsHint = formatThinkingLevels(configuredModel.provider, configuredModel.model);
	const thinkOverride = normalizeThinkLevel(opts.thinking);
	const thinkOnce = normalizeThinkLevel(opts.thinkingOnce);
	if (opts.thinking && !thinkOverride) throw new Error(`Invalid thinking level. Use one of: ${thinkingLevelsHint}.`);
	if (opts.thinkingOnce && !thinkOnce) throw new Error(`Invalid one-shot thinking level. Use one of: ${thinkingLevelsHint}.`);
	const verboseOverride = normalizeVerboseLevel(opts.verbose);
	if (opts.verbose && !verboseOverride) throw new Error("Invalid verbose level. Use \"on\", \"full\", or \"off\".");
	const timeoutSecondsRaw = opts.timeout !== void 0 ? Number.parseInt(String(opts.timeout), 10) : void 0;
	if (timeoutSecondsRaw !== void 0 && (Number.isNaN(timeoutSecondsRaw) || timeoutSecondsRaw <= 0)) throw new Error("--timeout must be a positive integer (seconds)");
	const timeoutMs = resolveKoiTimeoutMs({
		cfg,
		overrideSeconds: timeoutSecondsRaw
	});
	const { sessionId, sessionKey, sessionEntry: resolvedSessionEntry, sessionStore, storePath, isNewSession, persistedThinking, persistedVerbose } = resolveSession({
		cfg,
		to: opts.to,
		sessionId: opts.sessionId,
		sessionKey: opts.sessionKey,
		koiId: koiIdOverride
	});
	let sessionEntry = resolvedSessionEntry;
	const runId = opts.runId?.trim() || sessionId;
	try {
		if (opts.deliver === true) {
			if (resolveSendPolicy({
				cfg,
				entry: sessionEntry,
				sessionKey,
				channel: sessionEntry?.channel,
				chatType: sessionEntry?.chatType
			}) === "deny") throw new Error("send blocked by session policy");
		}
		let resolvedThinkLevel = thinkOnce ?? thinkOverride ?? persistedThinking ?? koiCfg?.thinkingDefault;
		const resolvedVerboseLevel = verboseOverride ?? persistedVerbose ?? koiCfg?.verboseDefault;
		if (sessionKey) registerKoiRunContext(runId, {
			sessionKey,
			verboseLevel: resolvedVerboseLevel,
			speakerKoiId
		});
		const needsSkillsSnapshot = isNewSession || !sessionEntry?.skillsSnapshot;
		const skillsSnapshotVersion = getSkillsSnapshotVersion(workspaceDir);
		const skillFilter = resolveKoiSkillsFilter(cfg, speakerKoiId);
		const skillsSnapshot = needsSkillsSnapshot ? buildWorkspaceSkillSnapshot(workspaceDir, {
			config: cfg,
			eligibility: { remote: getRemoteSkillEligibility() },
			snapshotVersion: skillsSnapshotVersion,
			skillFilter
		}) : sessionEntry?.skillsSnapshot;
		if (skillsSnapshot && sessionStore && sessionKey && needsSkillsSnapshot) {
			const next = {
				...sessionEntry ?? {
					sessionId,
					updatedAt: Date.now()
				},
				sessionId,
				updatedAt: Date.now(),
				skillsSnapshot
			};
			sessionStore[sessionKey] = next;
			await updateSessionStore(storePath, (store) => {
				store[sessionKey] = next;
			});
			sessionEntry = next;
		}
		if (sessionStore && sessionKey) {
			const next = {
				...sessionStore[sessionKey] ?? sessionEntry ?? {
					sessionId,
					updatedAt: Date.now()
				},
				sessionId,
				updatedAt: Date.now()
			};
			if (thinkOverride) if (thinkOverride === "off") delete next.thinkingLevel;
			else next.thinkingLevel = thinkOverride;
			applyVerboseOverride(next, verboseOverride);
			sessionStore[sessionKey] = next;
			await updateSessionStore(storePath, (store) => {
				store[sessionKey] = next;
			});
		}
		const koiModelPrimary = resolveKoiModelPrimary(cfg, speakerKoiId);
		const { provider: defaultProvider, model: defaultModel } = resolveConfiguredModelRef({
			cfg: koiModelPrimary ? {
				...cfg,
				kois: {
					...cfg.kois,
					defaults: {
						...cfg.kois?.defaults,
						model: {
							...typeof cfg.kois?.defaults?.model === "object" ? cfg.kois.defaults.model : void 0,
							primary: koiModelPrimary
						}
					}
				}
			} : cfg,
			defaultProvider: DEFAULT_PROVIDER,
			defaultModel: DEFAULT_MODEL
		});
		let provider = defaultProvider;
		let model = defaultModel;
		const hasAllowlist = koiCfg?.models && Object.keys(koiCfg.models).length > 0;
		const hasStoredOverride = Boolean(sessionEntry?.modelOverride || sessionEntry?.providerOverride);
		const needsModelCatalog = hasAllowlist || hasStoredOverride;
		let allowedModelKeys = /* @__PURE__ */ new Set();
		let allowedModelCatalog = [];
		let modelCatalog = null;
		if (needsModelCatalog) {
			modelCatalog = await loadModelCatalog({ config: cfg });
			const allowed = buildAllowedModelSet({
				cfg,
				catalog: modelCatalog,
				defaultProvider,
				defaultModel
			});
			allowedModelKeys = allowed.allowedKeys;
			allowedModelCatalog = allowed.allowedCatalog;
		}
		if (sessionEntry && sessionStore && sessionKey && hasStoredOverride) {
			const entry = sessionEntry;
			const overrideProvider = sessionEntry.providerOverride?.trim() || defaultProvider;
			const overrideModel = sessionEntry.modelOverride?.trim();
			if (overrideModel) {
				const key = modelKey(overrideProvider, overrideModel);
				if (!isCliProvider(overrideProvider, cfg) && allowedModelKeys.size > 0 && !allowedModelKeys.has(key)) {
					const { updated } = applyModelOverrideToSessionEntry({
						entry,
						selection: {
							provider: defaultProvider,
							model: defaultModel,
							isDefault: true
						}
					});
					if (updated) {
						sessionStore[sessionKey] = entry;
						await updateSessionStore(storePath, (store) => {
							store[sessionKey] = entry;
						});
					}
				}
			}
		}
		const storedProviderOverride = sessionEntry?.providerOverride?.trim();
		const storedModelOverride = sessionEntry?.modelOverride?.trim();
		if (storedModelOverride) {
			const candidateProvider = storedProviderOverride || defaultProvider;
			const key = modelKey(candidateProvider, storedModelOverride);
			if (isCliProvider(candidateProvider, cfg) || allowedModelKeys.size === 0 || allowedModelKeys.has(key)) {
				provider = candidateProvider;
				model = storedModelOverride;
			}
		}
		if (sessionEntry) {
			const authProfileId = sessionEntry.authProfileOverride;
			if (authProfileId) {
				const entry = sessionEntry;
				const profile = ensureAuthProfileStore().profiles[authProfileId];
				if (!profile || profile.provider !== provider) {
					if (sessionStore && sessionKey) await clearSessionAuthProfileOverride({
						sessionEntry: entry,
						sessionStore,
						sessionKey,
						storePath
					});
				}
			}
		}
		if (!resolvedThinkLevel) {
			let catalogForThinking = modelCatalog ?? allowedModelCatalog;
			if (!catalogForThinking || catalogForThinking.length === 0) {
				modelCatalog = await loadModelCatalog({ config: cfg });
				catalogForThinking = modelCatalog;
			}
			resolvedThinkLevel = resolveThinkingDefault({
				cfg,
				provider,
				model,
				catalog: catalogForThinking
			});
		}
		if (resolvedThinkLevel === "xhigh" && !supportsXHighThinking(provider, model)) {
			if (Boolean(thinkOnce || thinkOverride)) throw new Error(`Thinking level "xhigh" is only supported for ${formatXHighModelHint()}.`);
			resolvedThinkLevel = "high";
			if (sessionEntry && sessionStore && sessionKey && sessionEntry.thinkingLevel === "xhigh") {
				const entry = sessionEntry;
				entry.thinkingLevel = "high";
				entry.updatedAt = Date.now();
				sessionStore[sessionKey] = entry;
				await updateSessionStore(storePath, (store) => {
					store[sessionKey] = entry;
				});
			}
		}
		const sessionFile = resolveSessionFilePath(sessionId, sessionEntry, { koiId: speakerKoiId });
		const trimmedBody = body.trim();
		if (trimmedBody === "/compact" || trimmedBody.startsWith("/compact ")) {
			const userInstructions = trimmedBody.slice(8).trim();
			const customInstructions = userInstructions ? `[manual-compact] ${userInstructions}` : "[manual-compact]";
			const compactResult = await compactEmbeddedPiSession({
				sessionId,
				sessionKey,
				sessionFile,
				workspaceDir,
				config: cfg,
				skillsSnapshot,
				provider,
				model,
				thinkLevel: resolvedThinkLevel,
				bashElevated: {
					enabled: false,
					allowed: false,
					defaultLevel: "off"
				},
				customInstructions,
				groupId: opts.groupId,
				groupChannel: opts.groupChannel,
				groupSpace: opts.groupSpace,
				spawnedBy: opts.spawnedBy ?? sessionEntry?.spawnedBy,
				messageChannel: opts.channel,
				senderIsOwner: true
			});
			return {
				ok: compactResult.ok,
				runId: opts.runId ?? sessionId,
				sessionId,
				sessionKey,
				koiId: speakerKoiId,
				provider,
				model,
				compaction: compactResult,
				payloads: []
			};
		}
		const startedAt = Date.now();
		let lifecycleEnded = false;
		let result;
		let fallbackProvider = provider;
		let fallbackModel = model;
		try {
			const runContext = resolveKoiRunContext(opts);
			const messageChannel = resolveMessageChannel(runContext.messageChannel, opts.replyChannel ?? opts.channel);
			const spawnedBy = opts.spawnedBy ?? sessionEntry?.spawnedBy;
			const fallbackResult = await runWithModelFallback({
				cfg,
				provider,
				model,
				koiDir,
				fallbacksOverride: resolveKoiModelFallbacksOverride(cfg, speakerKoiId),
				run: (providerOverride, modelOverride) => {
					if (isCliProvider(providerOverride, cfg)) {
						const cliSessionId = getCliSessionId(sessionEntry, providerOverride);
						return runCliKoi({
							sessionId,
							sessionKey,
							koiId: speakerKoiId,
							sessionFile,
							workspaceDir,
							config: cfg,
							prompt: body,
							provider: providerOverride,
							model: modelOverride,
							thinkLevel: resolvedThinkLevel,
							timeoutMs,
							runId,
							extraSystemPrompt: opts.extraSystemPrompt,
							cliSessionId,
							images: opts.images,
							streamParams: opts.streamParams
						});
					}
					const authProfileId = providerOverride === provider ? sessionEntry?.authProfileOverride : void 0;
					return runEmbeddedPiKoi({
						sessionId,
						sessionKey,
						koiId: speakerKoiId,
						messageChannel,
						koiAccountId: runContext.accountId,
						messageTo: opts.replyTo ?? opts.to,
						messageThreadId: opts.threadId,
						groupId: runContext.groupId,
						groupChannel: runContext.groupChannel,
						groupSpace: runContext.groupSpace,
						spawnedBy,
						currentChannelId: runContext.currentChannelId,
						currentThreadTs: runContext.currentThreadTs,
						replyToMode: runContext.replyToMode,
						hasRepliedRef: runContext.hasRepliedRef,
						senderIsOwner: true,
						sessionFile,
						workspaceDir,
						config: cfg,
						skillsSnapshot,
						prompt: body,
						images: opts.images,
						clientTools: opts.clientTools,
						provider: providerOverride,
						model: modelOverride,
						authProfileId,
						authProfileIdSource: authProfileId ? sessionEntry?.authProfileOverrideSource : void 0,
						thinkLevel: resolvedThinkLevel,
						verboseLevel: resolvedVerboseLevel,
						timeoutMs,
						runId,
						lane: opts.lane,
						abortSignal: opts.abortSignal,
						extraSystemPrompt: opts.extraSystemPrompt,
						streamParams: opts.streamParams,
						koiDir,
						onKoiEvent: (evt) => {
							if (evt.stream === "lifecycle" && typeof evt.data?.phase === "string" && (evt.data.phase === "end" || evt.data.phase === "error")) lifecycleEnded = true;
						}
					});
				}
			});
			result = fallbackResult.result;
			fallbackProvider = fallbackResult.provider;
			fallbackModel = fallbackResult.model;
			if (!lifecycleEnded) emitKoiEvent({
				runId,
				stream: "lifecycle",
				data: {
					phase: "end",
					startedAt,
					endedAt: Date.now(),
					aborted: result.meta.aborted ?? false
				}
			});
		} catch (err) {
			if (!lifecycleEnded) emitKoiEvent({
				runId,
				stream: "lifecycle",
				data: {
					phase: "error",
					startedAt,
					endedAt: Date.now(),
					error: String(err)
				}
			});
			throw err;
		}
		if (sessionStore && sessionKey) await updateSessionStoreAfterKoiRun({
			cfg,
			contextTokensOverride: koiCfg?.contextTokens,
			sessionId,
			sessionKey,
			storePath,
			sessionStore,
			defaultProvider: provider,
			defaultModel: model,
			fallbackProvider,
			fallbackModel,
			result
		});
		const payloads = result.payloads ?? [];
		return await deliverKoiCommandResult({
			cfg,
			deps,
			runtime,
			opts,
			sessionEntry,
			result,
			payloads
		});
	} finally {
		clearKoiRunContext(runId);
	}
}

//#endregion
export { createOutboundSendDeps as a, resolveKoiOutboundTarget as i, resolveSessionKeyForRequest as n, resolveKoiDeliveryPlan as r, koiCommand as t };