import { c as normalizeOptionalString } from "./string-coerce-Bje8XVt9.js";
import { p as resolveUserPath } from "./utils-Ba75iQOz.js";
import { c as normalizeAgentId } from "./session-key-CFPTlmUH.js";
import { c as resolveDefaultAgentId, o as resolveAgentWorkspaceDir } from "./agent-scope-config-Dqva2IWz.js";
import "./agent-scope-DcilFo3V.js";
import { c as isWindowsAbsolutePath, i as isAvatarHttpUrl, n as hasAvatarUriScheme, o as isPathWithinRoot, r as isAvatarDataUrl, s as isSupportedLocalAvatarExtension } from "./avatar-policy-B4sjA8DB.js";
import { n as resolveAgentIdentity } from "./identity-DD5-d75h.js";
import { n as loadAgentIdentityFromWorkspace, r as loadAgentIdentityFromWorkspaceAsync } from "./identity-file-C8q1rctI.js";
import fs from "node:fs";
import path from "node:path";
import { realpath, stat } from "node:fs/promises";
//#region src/agents/identity-avatar.ts
const PUBLIC_AVATAR_SOURCE_MAX_CHARS = 256;
const PUBLIC_DATA_AVATAR_HEADER_MAX_CHARS = 64;
function resolveAvatarSource(cfg, agentId, opts) {
	const normalizedAgentId = normalizeAgentId(agentId);
	const defaultAgentId = normalizeAgentId(resolveDefaultAgentId(cfg));
	const fromUiConfig = normalizeOptionalString(cfg.ui?.assistant?.avatar) ?? null;
	if (opts?.includeUiOverride) {
		if (normalizedAgentId === defaultAgentId && fromUiConfig) return fromUiConfig;
	}
	const fromConfig = normalizeOptionalString(resolveAgentIdentity(cfg, normalizedAgentId)?.avatar) ?? null;
	if (fromConfig) return fromConfig;
	const fromIdentity = normalizeOptionalString(loadAgentIdentityFromWorkspace(resolveAgentWorkspaceDir(cfg, normalizedAgentId))?.avatar) ?? null;
	if (fromIdentity) return fromIdentity;
	return opts?.includeUiOverride ? fromUiConfig : null;
}
function resolveExistingPath(value) {
	try {
		return fs.realpathSync(value);
	} catch {
		return path.resolve(value);
	}
}
function resolveLocalAvatarPath(params) {
	const workspaceRoot = resolveExistingPath(params.workspaceDir);
	const raw = params.raw;
	const realPath = resolveExistingPath(raw.startsWith("~") || path.isAbsolute(raw) ? resolveUserPath(raw) : path.resolve(workspaceRoot, raw));
	if (!isPathWithinRoot(workspaceRoot, realPath)) return {
		ok: false,
		reason: "outside_workspace"
	};
	if (!isSupportedLocalAvatarExtension(realPath)) return {
		ok: false,
		reason: "unsupported_extension"
	};
	try {
		const stat = fs.statSync(realPath);
		if (!stat.isFile()) return {
			ok: false,
			reason: "missing"
		};
		if (stat.size > 2097152) return {
			ok: false,
			reason: "too_large"
		};
	} catch {
		return {
			ok: false,
			reason: "missing"
		};
	}
	return {
		ok: true,
		filePath: realPath
	};
}
function isSafeRelativeAvatarSource(source) {
	if (source.length > PUBLIC_AVATAR_SOURCE_MAX_CHARS || source.startsWith("~") || path.isAbsolute(source) || isWindowsAbsolutePath(source) || hasAvatarUriScheme(source) && !isWindowsAbsolutePath(source) || source.includes("\0")) return false;
	return source.replace(/\\/g, "/").split("/").every((part) => part !== "..");
}
function resolvePublicAgentAvatarSource(resolved) {
	const source = normalizeOptionalString(resolved.source) ?? null;
	if (!source) return;
	if (isAvatarDataUrl(source)) {
		const commaIndex = source.indexOf(",");
		return `${commaIndex > 0 ? source.slice(0, Math.min(commaIndex, PUBLIC_DATA_AVATAR_HEADER_MAX_CHARS)) : source.slice(0, PUBLIC_DATA_AVATAR_HEADER_MAX_CHARS)},...`;
	}
	if (isAvatarHttpUrl(source)) return "remote URL";
	return isSafeRelativeAvatarSource(source) ? source : void 0;
}
const AGENT_AVATAR_CACHE_TTL_MS = 3e3;
const AGENT_AVATAR_CACHE_MAX_ENTRIES = 64;
const agentAvatarResolutionCache = /* @__PURE__ */ new Map();
function buildAgentAvatarCacheKey(cfg, agentId, includeUiOverride) {
	const normalizedAgentId = normalizeAgentId(agentId);
	const uiAvatar = normalizeOptionalString(cfg.ui?.assistant?.avatar) ?? "";
	const cfgAvatar = normalizeOptionalString(resolveAgentIdentity(cfg, normalizedAgentId)?.avatar) ?? "";
	const workspace = resolveAgentWorkspaceDir(cfg, normalizedAgentId);
	const defaultId = normalizeAgentId(resolveDefaultAgentId(cfg));
	return [
		normalizedAgentId,
		includeUiOverride ? "1" : "0",
		uiAvatar,
		cfgAvatar,
		workspace,
		defaultId
	].join("\0");
}
function computeAgentAvatarResolution(cfg, agentId, opts) {
	const source = resolveAvatarSource(cfg, agentId, opts);
	if (!source) return {
		kind: "none",
		reason: "missing"
	};
	if (isAvatarHttpUrl(source)) return {
		kind: "remote",
		url: source,
		source
	};
	if (isAvatarDataUrl(source)) return {
		kind: "data",
		url: source,
		source
	};
	const resolved = resolveLocalAvatarPath({
		raw: source,
		workspaceDir: resolveAgentWorkspaceDir(cfg, agentId)
	});
	if (!resolved.ok) return {
		kind: "none",
		reason: resolved.reason,
		source
	};
	return {
		kind: "local",
		filePath: resolved.filePath,
		source
	};
}
function resolveAgentAvatar(cfg, agentId, opts) {
	const key = buildAgentAvatarCacheKey(cfg, agentId, opts?.includeUiOverride === true);
	const now = Date.now();
	const cached = agentAvatarResolutionCache.get(key);
	if (cached && cached.expiresAt > now) return cached.resolution;
	const resolution = computeAgentAvatarResolution(cfg, agentId, opts);
	agentAvatarResolutionCache.set(key, {
		expiresAt: now + AGENT_AVATAR_CACHE_TTL_MS,
		resolution
	});
	if (agentAvatarResolutionCache.size > AGENT_AVATAR_CACHE_MAX_ENTRIES) {
		for (const [k, v] of agentAvatarResolutionCache) if (v.expiresAt <= now) agentAvatarResolutionCache.delete(k);
	}
	return resolution;
}
function __clearAgentAvatarResolutionCacheForTests() {
	agentAvatarResolutionCache.clear();
	agentAvatarInFlightCache.clear();
}
const agentAvatarInFlightCache = /* @__PURE__ */ new Map();
async function resolveExistingPathAsync(value) {
	try {
		return await realpath(value);
	} catch {
		return path.resolve(value);
	}
}
async function resolveLocalAvatarPathAsync(params) {
	const workspaceRoot = await resolveExistingPathAsync(params.workspaceDir);
	const raw = params.raw;
	const realPath = await resolveExistingPathAsync(raw.startsWith("~") || path.isAbsolute(raw) ? resolveUserPath(raw) : path.resolve(workspaceRoot, raw));
	if (!isPathWithinRoot(workspaceRoot, realPath)) return {
		ok: false,
		reason: "outside_workspace"
	};
	if (!isSupportedLocalAvatarExtension(realPath)) return {
		ok: false,
		reason: "unsupported_extension"
	};
	try {
		const info = await stat(realPath);
		if (!info.isFile()) return {
			ok: false,
			reason: "missing"
		};
		if (info.size > 2097152) return {
			ok: false,
			reason: "too_large"
		};
	} catch {
		return {
			ok: false,
			reason: "missing"
		};
	}
	return {
		ok: true,
		filePath: realPath
	};
}
async function resolveAvatarSourceAsync(cfg, agentId, opts) {
	const normalizedAgentId = normalizeAgentId(agentId);
	const defaultAgentId = normalizeAgentId(resolveDefaultAgentId(cfg));
	const fromUiConfig = normalizeOptionalString(cfg.ui?.assistant?.avatar) ?? null;
	if (opts?.includeUiOverride) {
		if (normalizedAgentId === defaultAgentId && fromUiConfig) return fromUiConfig;
	}
	const fromConfig = normalizeOptionalString(resolveAgentIdentity(cfg, normalizedAgentId)?.avatar) ?? null;
	if (fromConfig) return fromConfig;
	const fromIdentity = normalizeOptionalString((await loadAgentIdentityFromWorkspaceAsync(resolveAgentWorkspaceDir(cfg, normalizedAgentId)))?.avatar) ?? null;
	if (fromIdentity) return fromIdentity;
	return opts?.includeUiOverride ? fromUiConfig : null;
}
async function computeAgentAvatarResolutionAsync(cfg, agentId, opts) {
	const source = await resolveAvatarSourceAsync(cfg, agentId, opts);
	if (!source) return {
		kind: "none",
		reason: "missing"
	};
	if (isAvatarHttpUrl(source)) return {
		kind: "remote",
		url: source,
		source
	};
	if (isAvatarDataUrl(source)) return {
		kind: "data",
		url: source,
		source
	};
	const resolved = await resolveLocalAvatarPathAsync({
		raw: source,
		workspaceDir: resolveAgentWorkspaceDir(cfg, agentId)
	});
	if (!resolved.ok) return {
		kind: "none",
		reason: resolved.reason,
		source
	};
	return {
		kind: "local",
		filePath: resolved.filePath,
		source
	};
}
async function resolveAgentAvatarAsync(cfg, agentId, opts) {
	const key = buildAgentAvatarCacheKey(cfg, agentId, opts?.includeUiOverride === true);
	const now = Date.now();
	const cached = agentAvatarResolutionCache.get(key);
	if (cached && cached.expiresAt > now) return cached.resolution;
	const inflight = agentAvatarInFlightCache.get(key);
	if (inflight) return inflight;
	const promise = computeAgentAvatarResolutionAsync(cfg, agentId, opts).then((resolution) => {
		agentAvatarResolutionCache.set(key, {
			expiresAt: Date.now() + AGENT_AVATAR_CACHE_TTL_MS,
			resolution
		});
		if (agentAvatarResolutionCache.size > AGENT_AVATAR_CACHE_MAX_ENTRIES) {
			const pruneNow = Date.now();
			for (const [k, v] of agentAvatarResolutionCache) if (v.expiresAt <= pruneNow) agentAvatarResolutionCache.delete(k);
		}
		return resolution;
	}).finally(() => {
		if (agentAvatarInFlightCache.get(key) === promise) agentAvatarInFlightCache.delete(key);
	});
	agentAvatarInFlightCache.set(key, promise);
	return promise;
}
//#endregion
export { resolvePublicAgentAvatarSource as i, resolveAgentAvatar as n, resolveAgentAvatarAsync as r, __clearAgentAvatarResolutionCacheForTests as t };
