//#region src/agent/bootstrap/bootstrap-context.ts
const DEFAULT_BOOTSTRAP_MAX_CHARS = 12e3;
const DEFAULT_BOOTSTRAP_TOTAL_MAX_CHARS = 6e4;
const MIN_BOOTSTRAP_FILE_BUDGET_CHARS = 64;
const BOOTSTRAP_HEAD_RATIO = .75;
const BOOTSTRAP_TAIL_RATIO = .25;
function resolveBootstrapMaxChars(config) {
	return config?.agents?.defaults?.bootstrapMaxChars ?? 12e3;
}
function resolveBootstrapTotalMaxChars(config) {
	return config?.agents?.defaults?.bootstrapTotalMaxChars ?? 6e4;
}
function clampToBudget(content, budget) {
	if (budget <= 0) return "";
	if (content.length <= budget) return content;
	if (budget <= 3) return content.slice(0, budget);
	return `${content.slice(0, budget - 1)}…`;
}
function trimBootstrapContent(content, fileName, maxChars) {
	const trimmed = content.trimEnd();
	if (trimmed.length <= maxChars) return {
		content: trimmed,
		truncated: false,
		originalLength: trimmed.length,
		maxChars
	};
	const markerTemplate = (head, tail) => `\n\n[...truncated ${fileName}: kept ${head}+${tail} of ${trimmed.length} chars...]\n\n`;
	let headChars = Math.floor(maxChars * BOOTSTRAP_HEAD_RATIO);
	let tailChars = Math.floor(maxChars * BOOTSTRAP_TAIL_RATIO);
	let marker = markerTemplate(headChars, tailChars);
	let renderedLength = headChars + tailChars + marker.length;
	while (renderedLength > maxChars && (headChars > 0 || tailChars > 0)) {
		if (tailChars >= headChars && tailChars > 0) tailChars -= 1;
		else if (headChars > 0) headChars -= 1;
		else break;
		marker = markerTemplate(headChars, tailChars);
		renderedLength = headChars + tailChars + marker.length;
	}
	const head = trimmed.slice(0, headChars);
	const tail = tailChars > 0 ? trimmed.slice(-tailChars) : "";
	const bounded = `${head}${marker}${tail}`;
	return {
		content: bounded.length > maxChars ? bounded.slice(0, maxChars) : bounded,
		truncated: true,
		originalLength: trimmed.length,
		maxChars
	};
}
function buildBootstrapContextFiles(files, opts) {
	const maxChars = opts?.maxChars ?? 12e3;
	let remainingTotalChars = Math.max(1, Math.floor(opts?.totalMaxChars ?? Math.max(maxChars, 6e4)));
	const result = [];
	for (const file of files) {
		if (remainingTotalChars <= 0) break;
		const pathValue = file.path.trim();
		if (!pathValue) {
			opts?.warn?.(`skipping bootstrap file "${file.name}" — missing path`);
			continue;
		}
		if (file.missing) {
			const capped = clampToBudget(`[MISSING] Expected at: ${pathValue}`, remainingTotalChars);
			if (!capped) break;
			remainingTotalChars = Math.max(0, remainingTotalChars - capped.length);
			result.push({
				path: pathValue,
				content: capped
			});
			continue;
		}
		if (remainingTotalChars < MIN_BOOTSTRAP_FILE_BUDGET_CHARS) {
			opts?.warn?.(`remaining bootstrap budget is ${remainingTotalChars} chars (<${MIN_BOOTSTRAP_FILE_BUDGET_CHARS}); skipping additional bootstrap files`);
			break;
		}
		const fileMaxChars = Math.max(1, Math.min(maxChars, remainingTotalChars));
		const trimmed = trimBootstrapContent(file.content ?? "", file.name, fileMaxChars);
		const contentWithinBudget = clampToBudget(trimmed.content, remainingTotalChars);
		if (!contentWithinBudget) continue;
		if (trimmed.truncated || contentWithinBudget.length < trimmed.content.length) opts?.warn?.(`profile bootstrap file ${file.name} is ${trimmed.originalLength} chars (limit ${trimmed.maxChars}); truncating in injected context`);
		remainingTotalChars = Math.max(0, remainingTotalChars - contentWithinBudget.length);
		result.push({
			path: pathValue,
			content: contentWithinBudget
		});
	}
	return result;
}
//#endregion
export { DEFAULT_BOOTSTRAP_MAX_CHARS, DEFAULT_BOOTSTRAP_TOTAL_MAX_CHARS, buildBootstrapContextFiles, resolveBootstrapMaxChars, resolveBootstrapTotalMaxChars };

//# sourceMappingURL=bootstrap-context.js.map