import { v as calculateCost } from "./fetch-AchwhzAC.js";
import { r as parseDataUrl } from "./dataUrl-BI7lhJra.js";
//#region src/providers/anthropic/util.ts
const ANTHROPIC_MODELS = [
	...["claude-mythos-preview"].map((model) => ({
		id: model,
		cost: {
			input: 25 / 1e6,
			output: 125 / 1e6
		}
	})),
	...["claude-opus-4-8"].map((model) => ({
		id: model,
		cost: {
			input: 5 / 1e6,
			output: 25 / 1e6
		}
	})),
	...["claude-opus-4-7"].map((model) => ({
		id: model,
		cost: {
			input: 5 / 1e6,
			output: 25 / 1e6
		}
	})),
	...["claude-sonnet-4-6", "claude-sonnet-4-6-latest"].map((model) => ({
		id: model,
		cost: {
			input: 3 / 1e6,
			output: 15 / 1e6
		}
	})),
	...["claude-opus-4-6", "claude-opus-4-6-latest"].map((model) => ({
		id: model,
		cost: {
			input: 5 / 1e6,
			output: 25 / 1e6
		}
	})),
	...[
		"claude-opus-4-5",
		"claude-opus-4-5-20251101",
		"claude-opus-4-5-latest"
	].map((model) => ({
		id: model,
		cost: {
			input: 5 / 1e6,
			output: 25 / 1e6
		}
	})),
	...[
		"claude-opus-4-1",
		"claude-opus-4-1-20250805",
		"claude-opus-4-20250514",
		"claude-opus-4-0",
		"claude-opus-4-latest"
	].map((model) => ({
		id: model,
		cost: {
			input: 15 / 1e6,
			output: 75 / 1e6
		}
	})),
	...[
		"claude-sonnet-4-5",
		"claude-sonnet-4-5-20250929",
		"claude-sonnet-4-5-latest",
		"claude-sonnet-4-20250514",
		"claude-sonnet-4-0",
		"claude-sonnet-4-latest"
	].map((model) => ({
		id: model,
		cost: {
			input: 3 / 1e6,
			output: 15 / 1e6
		}
	})),
	...[
		"claude-haiku-4-5",
		"claude-haiku-4-5-20251001",
		"claude-haiku-4-5-latest"
	].map((model) => ({
		id: model,
		cost: {
			input: 1 / 1e6,
			output: 5 / 1e6
		}
	})),
	...["claude-2.0"].map((model) => ({
		id: model,
		cost: {
			input: .008 / 1e3,
			output: .024 / 1e3
		}
	})),
	...["claude-2.1"].map((model) => ({
		id: model,
		cost: {
			input: .008 / 1e3,
			output: .024 / 1e3
		}
	})),
	...["claude-3-haiku-20240307", "claude-3-haiku-latest"].map((model) => ({
		id: model,
		cost: {
			input: 25e-5 / 1e3,
			output: .00125 / 1e3
		}
	})),
	...["claude-3-opus-20240229", "claude-3-opus-latest"].map((model) => ({
		id: model,
		cost: {
			input: .015 / 1e3,
			output: .075 / 1e3
		}
	})),
	...["claude-3-5-haiku-20241022", "claude-3-5-haiku-latest"].map((model) => ({
		id: model,
		cost: {
			input: .8 / 1e6,
			output: 4 / 1e6
		}
	})),
	...[
		"claude-3-5-sonnet-20240620",
		"claude-3-5-sonnet-20241022",
		"claude-3-5-sonnet-latest",
		"claude-3-7-sonnet-20250219",
		"claude-3-7-sonnet-latest"
	].map((model) => ({
		id: model,
		cost: {
			input: 3 / 1e6,
			output: 15 / 1e6
		}
	}))
];
/**
* Matches Claude Opus 4.7 model IDs across Anthropic, Bedrock (including the
* `us.`/`eu.`/`jp.`/`global.` inference-profile prefixes), Vertex, and Azure
* deployment names. Returns `false` for hypothetical suffix variants like
* `claude-opus-4-70` or `claude-opus-4-7N` so detection stays forward-compatible.
*/
function isClaudeOpus47Model(modelId) {
	return /(^|[^a-z0-9])claude-opus-4-7(?![0-9])/i.test(modelId);
}
/**
* Matches Claude Opus 4.8 model IDs across Anthropic, Bedrock (including the
* `us.`/`eu.`/`jp.`/`global.` inference-profile prefixes), Vertex, and Azure
* deployment names. The trailing `(?![0-9])` guard keeps a hypothetical
* higher-numbered `claude-opus-4-80` from matching "4.8" while still matching
* dated snapshots like `claude-opus-4-8-20260528`.
*/
function isClaudeOpus48Model(modelId) {
	return /(^|[^a-z0-9])claude-opus-4-8(?![0-9])/i.test(modelId);
}
/**
* Claude Opus 4.7 and 4.8 deprecate manual sampling controls at the model level
* — `temperature`, `top_p`, and `top_k` are adaptive, and a request that pins
* any of them returns 400 `invalid_request_error` (including promptfoo's
* built-in `temperature` default of 0). Centralizes the "omit sampling params"
* decision shared by the Anthropic, Bedrock, Vertex, and Azure providers so
* support for future models lands in one place.
*/
function isSamplingParamsDeprecatedClaudeModel(modelId) {
	return isClaudeOpus47Model(modelId) || isClaudeOpus48Model(modelId);
}
function outputFromMessage(message, showThinking) {
	const hasToolUse = message.content.some((block) => block.type === "tool_use");
	const hasThinking = message.content.some((block) => block.type === "thinking" || block.type === "redacted_thinking");
	if (hasToolUse || hasThinking) return message.content.map((block) => {
		if (block.type === "text") return block.text;
		else if (block.type === "thinking" && showThinking) return `Thinking: ${block.thinking}\nSignature: ${block.signature}`;
		else if (block.type === "redacted_thinking" && showThinking) return `Redacted Thinking: ${block.data}`;
		else if (block.type !== "thinking" && block.type !== "redacted_thinking") return JSON.stringify(block);
		return "";
	}).filter((text) => text !== "").join("\n\n");
	return message.content.map((block) => {
		return block.text;
	}).join("\n\n");
}
/**
* Automatically extracts base64 data from data URLs for Anthropic image content.
* This ensures compatibility with our universal data URL generation without requiring
* users to modify their prompt templates with Nunjucks filters.
*/
function processAnthropicImageContent(content) {
	return content.map((item) => {
		if (item.type === "image" && item.source && item.source.type === "base64") {
			const parsed = parseDataUrl(item.source.data);
			if (parsed) return {
				...item,
				source: {
					...item.source,
					media_type: item.source.media_type || parsed.mimeType,
					data: parsed.base64Data
				}
			};
		}
		return item;
	});
}
function parseMessages(messages) {
	try {
		const parsed = JSON.parse(messages);
		if (Array.isArray(parsed)) {
			const systemMessage = parsed.find((msg) => msg.role === "system");
			const thinking = parsed.find((msg) => msg.thinking)?.thinking;
			return {
				extractedMessages: parsed.filter((msg) => msg.role && msg.role !== "system").map((msg) => ({
					role: msg.role,
					content: Array.isArray(msg.content) ? processAnthropicImageContent(msg.content) : [{
						type: "text",
						text: msg.content
					}]
				})),
				system: systemMessage ? Array.isArray(systemMessage.content) ? systemMessage.content : [{
					type: "text",
					text: systemMessage.content
				}] : void 0,
				thinking
			};
		}
	} catch {}
	const lines = messages.split("\n").map((line) => line.trim()).filter((line) => line);
	let system;
	let thinking;
	const extractedMessages = [];
	let currentRole = null;
	let currentContent = [];
	const pushMessage = () => {
		if (currentRole && currentContent.length > 0) {
			extractedMessages.push({
				role: currentRole,
				content: [{
					type: "text",
					text: currentContent.join("\n")
				}]
			});
			currentContent = [];
		}
	};
	for (const line of lines) if (line.startsWith("system:")) system = [{
		type: "text",
		text: line.slice(7).trim()
	}];
	else if (line.startsWith("thinking:")) try {
		thinking = JSON.parse(line.slice(9).trim());
	} catch {}
	else if (line.startsWith("user:") || line.startsWith("assistant:")) {
		pushMessage();
		currentRole = line.startsWith("user:") ? "user" : "assistant";
		currentContent.push(line.slice(line.indexOf(":") + 1).trim());
	} else if (currentRole) currentContent.push(line);
	else {
		currentRole = "user";
		currentContent.push(line);
	}
	pushMessage();
	if (extractedMessages.length === 0 && !system) extractedMessages.push({
		role: "user",
		content: [{
			type: "text",
			text: messages.trim()
		}]
	});
	return {
		system,
		extractedMessages,
		thinking
	};
}
/**
* Compute input cost with Anthropic cache pricing applied.
* Anthropic docs: input_tokens is the non-cached portion; cache_read and cache_creation are additive.
* Cache reads cost 10% of base rate (90% discount), cache writes cost 125% of base rate (25% surcharge).
*/
function calculateCacheInputCost(baseInputRate, uncachedInputTokens, cacheRead, cacheCreation) {
	return uncachedInputTokens * baseInputRate + cacheRead * baseInputRate * .1 + cacheCreation * baseInputRate * 1.25;
}
function calculateAnthropicCost(modelName, config, promptTokens, completionTokens, cacheReadTokens, cacheCreationTokens) {
	if (config.cost != null && config.inputCost == null && config.outputCost == null) return calculateCost(modelName, config, promptTokens, completionTokens, ANTHROPIC_MODELS);
	if (!Number.isFinite(promptTokens) || !Number.isFinite(completionTokens) || typeof promptTokens === "undefined" || typeof completionTokens === "undefined") return calculateCost(modelName, config, promptTokens, completionTokens, ANTHROPIC_MODELS);
	const cacheRead = cacheReadTokens ?? 0;
	const cacheCreation = cacheCreationTokens ?? 0;
	const effectiveInputTokens = promptTokens + cacheRead + cacheCreation;
	if ([
		"claude-sonnet-4-5",
		"claude-sonnet-4-5-20250929",
		"claude-sonnet-4-5-latest",
		"claude-sonnet-4-6",
		"claude-sonnet-4-6-latest"
	].includes(modelName)) {
		const isLongContext = effectiveInputTokens > 2e5;
		const baseInputRate = config.inputCost ?? config.cost ?? (isLongContext ? 6 / 1e6 : 3 / 1e6);
		const outputRate = config.outputCost ?? config.cost ?? (isLongContext ? 22.5 / 1e6 : 15 / 1e6);
		return calculateCacheInputCost(baseInputRate, promptTokens, cacheRead, cacheCreation) + completionTokens * outputRate;
	}
	if (cacheRead || cacheCreation) {
		const modelInfo = ANTHROPIC_MODELS.find((m) => m.id === modelName);
		if (modelInfo) {
			const inputCost = config.inputCost ?? config.cost ?? modelInfo.cost.input;
			const outputCost = config.outputCost ?? config.cost ?? modelInfo.cost.output;
			return calculateCacheInputCost(inputCost, promptTokens, cacheRead, cacheCreation) + completionTokens * outputCost;
		}
	}
	return calculateCost(modelName, config, promptTokens, completionTokens, ANTHROPIC_MODELS);
}
/**
* Extract refusal details from the Anthropic stop_details field.
* Returns a human-readable string if the response was refused, or undefined otherwise.
*/
function getRefusalDetails(data) {
	if (data.stop_reason !== "refusal" || !data.stop_details) return;
	const details = data.stop_details;
	const parts = ["Content refused by Anthropic safety filters"];
	if (details.category) parts.push(`category: ${details.category}`);
	if (details.explanation) parts.push(`explanation: ${details.explanation}`);
	return parts.join(" — ");
}
function getTokenUsage(data, cached) {
	if (data.usage) {
		const cacheRead = data.usage.cache_read_input_tokens ?? 0;
		const cacheCreation = data.usage.cache_creation_input_tokens ?? 0;
		const allInputTokens = (data.usage.input_tokens ?? 0) + cacheRead + cacheCreation;
		const total_tokens = allInputTokens + (data.usage.output_tokens ?? 0);
		if (cached) return {
			cached: total_tokens,
			total: total_tokens
		};
		else {
			const usage = {
				total: total_tokens,
				prompt: allInputTokens,
				completion: data.usage.output_tokens ?? 0
			};
			if (data.usage.cache_read_input_tokens != null || data.usage.cache_creation_input_tokens != null) usage.completionDetails = {
				cacheReadInputTokens: cacheRead,
				cacheCreationInputTokens: cacheCreation
			};
			return usage;
		}
	}
	return {};
}
/**
* Processes tools configuration to handle web fetch and web search tools
*/
function processAnthropicTools(tools = []) {
	const processedTools = [];
	const requiredBetaFeatures = [];
	const addRequiredBetaFeature = (feature) => {
		if (!requiredBetaFeatures.includes(feature)) requiredBetaFeatures.push(feature);
	};
	for (const tool of tools) {
		if ("type" in tool) if (tool.type === "web_fetch_20250910") {
			processedTools.push(transformWebFetchTool(tool));
			addRequiredBetaFeature("web-fetch-2025-09-10");
		} else if (tool.type === "web_fetch_20260209") processedTools.push(transformWebFetchTool20260209(tool));
		else if (tool.type === "web_fetch_20260309") processedTools.push(transformWebFetchToolV2(tool));
		else if (tool.type === "web_search_20250305") processedTools.push(transformWebSearchTool(tool));
		else if (tool.type === "web_search_20260209") processedTools.push(transformWebSearchTool20260209(tool));
		else if (tool.type === "memory_20250818") processedTools.push(tool);
		else processedTools.push(tool);
		else processedTools.push(tool);
		if ("strict" in tool && tool.strict === true) addRequiredBetaFeature("structured-outputs-2025-11-13");
	}
	return {
		processedTools,
		requiredBetaFeatures
	};
}
/**
* Apply shared web fetch tool fields from config onto the SDK tool object.
*/
function applyWebFetchFields(tool, config) {
	if (config.allowed_callers !== void 0) tool.allowed_callers = config.allowed_callers;
	if (config.max_uses !== void 0) tool.max_uses = config.max_uses;
	if (config.allowed_domains !== void 0) tool.allowed_domains = config.allowed_domains;
	if (config.blocked_domains !== void 0) tool.blocked_domains = config.blocked_domains;
	if (config.citations !== void 0) tool.citations = config.citations;
	if (config.max_content_tokens !== void 0) tool.max_content_tokens = config.max_content_tokens;
	if (config.cache_control !== void 0) tool.cache_control = config.cache_control;
	if (config.defer_loading !== void 0) tool.defer_loading = config.defer_loading;
	if (config.strict !== void 0) tool.strict = config.strict;
}
function transformWebFetchTool(config) {
	const tool = {
		type: "web_fetch_20250910",
		name: "web_fetch"
	};
	applyWebFetchFields(tool, config);
	return tool;
}
function transformWebFetchTool20260209(config) {
	const tool = {
		type: "web_fetch_20260209",
		name: "web_fetch"
	};
	applyWebFetchFields(tool, config);
	return tool;
}
function transformWebFetchToolV2(config) {
	const tool = {
		type: "web_fetch_20260309",
		name: "web_fetch"
	};
	applyWebFetchFields(tool, config);
	if (config.use_cache !== void 0) tool.use_cache = config.use_cache;
	return tool;
}
function applyWebSearchFields(tool, config) {
	if (config.allowed_callers !== void 0) tool.allowed_callers = config.allowed_callers;
	if (config.allowed_domains !== void 0) tool.allowed_domains = config.allowed_domains;
	if (config.blocked_domains !== void 0) tool.blocked_domains = config.blocked_domains;
	if (config.cache_control !== void 0) tool.cache_control = config.cache_control;
	if (config.defer_loading !== void 0) tool.defer_loading = config.defer_loading;
	if (config.max_uses !== void 0) tool.max_uses = config.max_uses;
	if (config.strict !== void 0) tool.strict = config.strict;
	if (config.user_location !== void 0) tool.user_location = config.user_location;
}
/**
* Transform web search tool config to Anthropic beta tool format
*/
function transformWebSearchTool(config) {
	const tool = {
		type: "web_search_20250305",
		name: "web_search"
	};
	applyWebSearchFields(tool, config);
	return tool;
}
function transformWebSearchTool20260209(config) {
	const tool = {
		type: "web_search_20260209",
		name: "web_search"
	};
	applyWebSearchFields(tool, config);
	return tool;
}
//#endregion
export { isSamplingParamsDeprecatedClaudeModel as a, processAnthropicTools as c, getTokenUsage as i, calculateAnthropicCost as n, outputFromMessage as o, getRefusalDetails as r, parseMessages as s, ANTHROPIC_MODELS as t };

//# sourceMappingURL=util-BZw0tB27.js.map