const require_rolldown_runtime = require("./rolldown-runtime-D_mwlA32.cjs");
const require_logger = require("./logger-DuG3amVa.cjs");
const require_fetch = require("./fetch-Hdu2Q-w3.cjs");
const require_util = require("./util-M3cOWPu3.cjs");
const require_cache = require("./cache-JYoIjHBA.cjs");
const require_tokenUsageUtils = require("./tokenUsageUtils-DQwV4JGQ.cjs");
const require_util$1 = require("./util-pMUEO1m7.cjs");
const require_chat = require("./chat-Bl2LfE5B.cjs");
const require_client = require("./client-4POX6S5z.cjs");
const require_transform = require("./transform-6Fcy98Wj.cjs");
const require_util$2 = require("./util-BYWxXWQj.cjs");
let node_fs = require("node:fs");
node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
let node_path = require("node:path");
node_path = require_rolldown_runtime.__toESM(node_path, 1);
let crypto = require("crypto");
let _anthropic_ai_sdk = require("@anthropic-ai/sdk");
_anthropic_ai_sdk = require_rolldown_runtime.__toESM(_anthropic_ai_sdk, 1);
let node_child_process = require("node:child_process");
let node_os = require("node:os");
node_os = require_rolldown_runtime.__toESM(node_os, 1);
//#region src/providers/anthropic/claudeCodeAuth.ts
/**
* Claude Code prepends this identity block as the first `system` message when
* calling the Anthropic Messages API with an OAuth token. As of 2025-Q4 the
* API returns HTTP 400 `invalid_request_error` when an OAuth-authenticated
* request's first system block is not this exact string, so any caller
* reusing a Claude Code OAuth token must inject this block before the
* user-provided system prompt. Re-verify if Anthropic ships an OAuth-native
* `/v1/messages` path that drops the requirement.
*/
const CLAUDE_CODE_IDENTITY_PROMPT = "You are Claude Code, Anthropic's official CLI for Claude.";
/**
* Anthropic beta headers required when authenticating the Messages API with a
* Claude Code OAuth token (e.g. a Claude Max subscription access token, or a
* long-lived token minted by `claude setup-token`).
*
* - `oauth-2025-04-20` enables OAuth bearer tokens on `/v1/messages`.
* - `claude-code-20250219` enables the Claude Code tool-use surface area the
*   OAuth token is scoped to.
*
* Revisit if Anthropic ships an OAuth-native Messages path that no longer
* requires these betas.
*/
const CLAUDE_CODE_OAUTH_BETA_FEATURES = Object.freeze(["claude-code-20250219", "oauth-2025-04-20"]);
/**
* The `user-agent` value Claude Code CLI sends on OAuth-authenticated
* Messages requests. Anthropic's API gates OAuth tokens to the Claude Code
* app identity, so requests that use a different user-agent fail with 401.
*
* The `1.0.0` suffix is cosmetic — Anthropic gates on the `claude-cli`
* product identifier, not the semver. Revisit if OAuth requests start
* returning 401 after SDK or CLI updates.
*/
const CLAUDE_CODE_USER_AGENT = "claude-cli/1.0.0 (external, promptfoo)";
const CLAUDE_CODE_KEYCHAIN_SERVICE = "Claude Code-credentials";
const CLAUDE_CODE_CREDENTIALS_FILE = node_path.default.join(".claude", ".credentials.json");
function resolveCredentialsPath() {
	return node_path.default.join(node_os.default.homedir(), CLAUDE_CODE_CREDENTIALS_FILE);
}
/**
* `security` exits with status 44 when the requested generic-password entry
* does not exist. Any other non-zero exit (or throw) indicates a real failure
* — ACL denial, corrupted entry, missing binary, timeout — and is worth a
* `warn` log rather than silently falling through.
*/
const SECURITY_ENTRY_NOT_FOUND = 44;
function parseCredential(raw) {
	if (!raw || typeof raw !== "object") return {
		ok: false,
		reason: "credential JSON is not an object"
	};
	const claudeAiOauth = raw.claudeAiOauth;
	if (!claudeAiOauth || typeof claudeAiOauth !== "object") return {
		ok: false,
		reason: "missing `claudeAiOauth` object"
	};
	const inner = claudeAiOauth;
	const accessToken = inner.accessToken;
	if (typeof accessToken !== "string" || !accessToken) return {
		ok: false,
		reason: "missing `claudeAiOauth.accessToken` string"
	};
	const credential = { accessToken };
	if (typeof inner.refreshToken === "string" && inner.refreshToken) credential.refreshToken = inner.refreshToken;
	if (typeof inner.expiresAt === "number" && Number.isFinite(inner.expiresAt)) credential.expiresAt = inner.expiresAt;
	if (typeof inner.subscriptionType === "string") credential.subscriptionType = inner.subscriptionType;
	return {
		ok: true,
		credential
	};
}
function parseJsonBlob(blob) {
	let parsed;
	try {
		parsed = JSON.parse(blob);
	} catch (err) {
		return {
			ok: false,
			reason: `invalid JSON: ${err instanceof Error ? err.message : String(err)}`
		};
	}
	return parseCredential(parsed);
}
function readFromMacosKeychain() {
	if (process.platform !== "darwin") return null;
	let out;
	try {
		out = (0, node_child_process.execFileSync)("security", [
			"find-generic-password",
			"-s",
			CLAUDE_CODE_KEYCHAIN_SERVICE,
			"-w"
		], {
			encoding: "utf-8",
			stdio: [
				"ignore",
				"pipe",
				"ignore"
			],
			timeout: 5e3
		});
	} catch (err) {
		if (err?.status === SECURITY_ENTRY_NOT_FOUND) {
			require_logger.logger.debug("[anthropic] No Claude Code credential entry in the macOS keychain; trying file fallback.");
			return null;
		}
		require_logger.logger.warn("[anthropic] Failed to read Claude Code credential from macOS keychain; falling back to file lookup.", { error: err instanceof Error ? err.message : String(err) });
		return null;
	}
	const trimmed = out.trim();
	if (!trimmed) {
		require_logger.logger.warn("[anthropic] Claude Code macOS keychain entry is empty. Run `claude /login` to refresh it.");
		return null;
	}
	const result = parseJsonBlob(trimmed);
	if (!result.ok) {
		require_logger.logger.warn(`[anthropic] Claude Code macOS keychain entry is malformed (${result.reason}). Run \`claude /login\` to refresh it.`);
		return null;
	}
	return result.credential;
}
function readFromFile() {
	const filePath = resolveCredentialsPath();
	if (!node_fs.default.existsSync(filePath)) return null;
	let raw;
	try {
		raw = node_fs.default.readFileSync(filePath, "utf-8");
	} catch (err) {
		require_logger.logger.warn(`[anthropic] Claude Code credentials file at ${filePath} exists but could not be read. Run \`claude /login\` to refresh it.`, { error: err instanceof Error ? err.message : String(err) });
		return null;
	}
	const result = parseJsonBlob(raw);
	if (!result.ok) {
		require_logger.logger.warn(`[anthropic] Claude Code credentials file at ${filePath} is malformed (${result.reason}). Run \`claude /login\` to refresh it.`);
		return null;
	}
	return result.credential;
}
/**
* Loads a Claude Code OAuth credential from the local environment.
*
* Resolution order:
* 1. macOS keychain (`security find-generic-password -s "Claude Code-credentials"`)
*    — only attempted on darwin.
* 2. `$HOME/.claude/.credentials.json` — the Linux/Windows default used by
*    Claude Code, and a fallback on macOS when the keychain entry is missing.
*    On Windows this resolves to `%USERPROFILE%\.claude\.credentials.json`.
*
* Returns `null` when no credential is available. Callers should check
* {@link isCredentialExpired} on a non-null return before using it — this
* function does not filter out expired credentials so callers can decide
* whether to warn, refuse, or surface a 401 to the user.
*
* Never throws. Missing credentials fall through silently; corrupted or
* unreadable credentials are logged at `warn` level with a reason so broken
* setups are diagnosable without enabling debug logging.
*/
function loadClaudeCodeCredential() {
	return readFromMacosKeychain() ?? readFromFile();
}
/**
* Returns `true` when the credential's `expiresAt` (ms since epoch) is in the
* past. Credentials without an `expiresAt` are treated as non-expired — the
* Anthropic API will reject them with a 401 if the token is actually invalid.
*/
function isCredentialExpired(credential) {
	if (credential.expiresAt == null) return false;
	return Date.now() >= credential.expiresAt;
}
//#endregion
//#region src/providers/anthropic/generic.ts
const ANTHROPIC_CACHE_HASH_CONTEXT = "promptfoo:anthropic:cache-key:v1";
function isPlainObject(value) {
	if (value === null || typeof value !== "object") return false;
	const proto = Object.getPrototypeOf(value);
	return proto === Object.prototype || proto === null;
}
function canonicalize(value) {
	if (Array.isArray(value)) return value.map(canonicalize);
	if (isPlainObject(value)) {
		const entries = Object.keys(value).sort().map((k) => [k, canonicalize(value[k])]);
		return Object.fromEntries(entries);
	}
	return value;
}
function hashAnthropicCacheValue(value) {
	const canonical = canonicalize(value);
	const serialized = typeof canonical === "string" ? canonical : JSON.stringify(canonical) ?? String(canonical);
	return (0, crypto.createHash)("sha256").update(ANTHROPIC_CACHE_HASH_CONTEXT).update("\0").update(serialized).digest("hex");
}
function getAnthropicAuthCacheNamespace(apiKey) {
	return (0, crypto.createHmac)("sha256", apiKey).update(`${ANTHROPIC_CACHE_HASH_CONTEXT}:auth`).digest("hex");
}
/**
* Generic provider class for Anthropic APIs.
*
* Serves as a base class with shared functionality for all Anthropic
* subclass providers. Handles API key resolution and, for subclasses that
* opt in via {@link AnthropicGenericProvider.SUPPORTS_CLAUDE_CODE_OAUTH},
* falls back to an OAuth token loaded from a local Claude Code session so
* Claude.ai subscribers can run evals without a separate console API key.
*
* The OAuth fallback is opt-in so it only affects
* `AnthropicMessagesProvider`. Claude Code OAuth tokens are gated to the
* Messages API (`/v1/messages`) — forwarding them to the legacy
* text-completion endpoint would fail at request time, which would cause
* `anthropic:completion:*` configs to bypass promptfoo's upfront preflight
* check and then produce a less useful error for every test case.
*/
var AnthropicGenericProvider = class {
	/**
	* Subclasses that can authenticate via a Claude Code OAuth session
	* should override this to `true`. The base class's constructor reads the
	* flag from `this.constructor` so only OAuth-capable subclasses attempt
	* the credential lookup (and only they honor `apiKeyRequired: false`).
	*/
	static SUPPORTS_CLAUDE_CODE_OAUTH = false;
	modelName;
	config;
	env;
	apiKey;
	/**
	* `true` when this provider is authenticating via a Claude Code OAuth token
	* rather than a standard `ANTHROPIC_API_KEY`. Subclasses use this to inject
	* the Claude Code identity system block that Anthropic's API requires for
	* OAuth-authenticated Messages requests.
	*/
	usingClaudeCodeOAuth;
	/**
	* The Claude Code credential used to authenticate, when
	* `usingClaudeCodeOAuth` is `true`. Kept so subclasses can re-check expiry
	* at request time and surface a "run `claude /login`" error instead of a
	* raw 401 from the SDK.
	*/
	claudeCodeCredential;
	anthropic;
	constructor(modelName, options = {}) {
		const { config, id, env } = options;
		this.env = env;
		this.modelName = modelName;
		this.config = config || {};
		this.apiKey = this.getApiKey();
		this.usingClaudeCodeOAuth = false;
		let authToken;
		const defaultHeaders = {};
		const subclass = this.constructor;
		if (!this.apiKey && this.config.apiKeyRequired === false && subclass.SUPPORTS_CLAUDE_CODE_OAUTH) {
			const credential = loadClaudeCodeCredential();
			if (credential) {
				if (isCredentialExpired(credential)) require_logger.logger.warn("[anthropic] Claude Code OAuth credential is expired. Run `claude /login` to refresh it.");
				else require_logger.logger.debug("[anthropic] Authenticating with Claude Code OAuth credential from local session.");
				authToken = credential.accessToken;
				this.usingClaudeCodeOAuth = true;
				this.claudeCodeCredential = credential;
				defaultHeaders["anthropic-beta"] = CLAUDE_CODE_OAUTH_BETA_FEATURES.join(",");
				defaultHeaders["user-agent"] = CLAUDE_CODE_USER_AGENT;
				defaultHeaders["x-app"] = "cli";
			} else require_logger.logger.warn("[anthropic] apiKeyRequired is false but no Claude Code credential was found. Run `claude /login` to create one, or set ANTHROPIC_API_KEY.");
		}
		this.anthropic = new _anthropic_ai_sdk.default({
			apiKey: this.apiKey ?? null,
			authToken: authToken ?? null,
			baseURL: this.getApiBaseUrl(),
			...Object.keys(defaultHeaders).length > 0 ? { defaultHeaders } : {}
		});
		this.id = id ? () => id : this.id;
	}
	id() {
		return `anthropic:${this.modelName}`;
	}
	toString() {
		return `[Anthropic Provider ${this.modelName}]`;
	}
	/**
	* Whether promptfoo's preflight check should require an API key before
	* dispatching requests to this provider. Returns `false` only for
	* OAuth-capable subclasses (see {@link SUPPORTS_CLAUDE_CODE_OAUTH}) when
	* the user has opted in via `apiKeyRequired: false`. All other subclasses
	* keep the preflight check so missing-credential errors surface upfront
	* rather than at per-request call time.
	*/
	requiresApiKey() {
		if (this.constructor.SUPPORTS_CLAUDE_CODE_OAUTH && this.config.apiKeyRequired === false) return false;
		return true;
	}
	getApiKey() {
		return this.config?.apiKey || this.env?.ANTHROPIC_API_KEY || require_logger.getEnvString("ANTHROPIC_API_KEY");
	}
	getApiBaseUrl() {
		return this.config?.apiBaseUrl || this.env?.ANTHROPIC_BASE_URL || require_logger.getEnvString("ANTHROPIC_BASE_URL");
	}
	getCacheIdentityHash() {
		return hashAnthropicCacheValue({ apiBaseUrl: this.getApiBaseUrl() });
	}
	getCacheAuthNamespace() {
		const apiKey = this.apiKey ?? this.getApiKey();
		return apiKey ? getAnthropicAuthCacheNamespace(apiKey) : "no-api-key";
	}
	/**
	* Base implementation - should be overridden by specific provider implementations
	*/
	async callApi(_prompt, _context) {
		throw new Error("Not implemented: callApi must be implemented by subclasses");
	}
};
//#endregion
//#region src/providers/anthropic/messages.ts
const DEFAULT_MAX_MCP_TOOL_CALLS = 8;
async function finalMessageWithStreamedStopDetails(stream) {
	let streamedStopDetails;
	stream.on?.("streamEvent", (event) => {
		if (event.type === "message_delta" && event.delta.stop_details != null) streamedStopDetails = event.delta.stop_details;
	});
	const finalMessage = await stream.finalMessage();
	return finalMessage.stop_details == null && streamedStopDetails != null ? {
		...finalMessage,
		stop_details: streamedStopDetails
	} : finalMessage;
}
function parseEnvFloat(value) {
	if (value === void 0) return;
	const parsed = Number.parseFloat(value);
	return Number.isNaN(parsed) ? void 0 : parsed;
}
function resolveThinkingConfig(configThinking, promptThinking) {
	return configThinking ?? promptThinking;
}
function isThinkingEnabled(thinking) {
	return thinking?.type === "enabled" || thinking?.type === "adaptive";
}
function normalizeHeadersForCacheKey(headers) {
	if (Object.keys(headers).length === 0) return;
	return Object.entries(headers).map(([name, value]) => ({
		name: name.toLowerCase(),
		valueHash: hashAnthropicCacheValue(value)
	})).sort((headerA, headerB) => {
		const nameComparison = headerA.name.localeCompare(headerB.name);
		return nameComparison === 0 ? headerA.valueHash.localeCompare(headerB.valueHash) : nameComparison;
	});
}
function getMessagesRequestMetadata(params) {
	const mcpServers = params.mcp_servers;
	return {
		model: params.model,
		max_tokens: params.max_tokens,
		messageCount: params.messages.length,
		stream: params.stream,
		temperature: params.temperature,
		hasSystem: params.system !== void 0,
		stopSequenceCount: Array.isArray(params.stop_sequences) ? params.stop_sequences.length : void 0,
		thinkingEnabled: isThinkingEnabled(params.thinking),
		toolCount: Array.isArray(params.tools) ? params.tools.length : void 0,
		hasToolChoice: params.tool_choice !== void 0,
		hasMetadata: params.metadata !== void 0,
		hasMcpServers: Array.isArray(mcpServers) && mcpServers.length > 0,
		hasOutputConfig: params.output_config !== void 0
	};
}
function getMessagesResponseMetadata(response) {
	return {
		model: response.model,
		type: response.type,
		contentBlockCount: Array.isArray(response.content) ? response.content.length : void 0,
		stopReason: response.stop_reason,
		inputTokens: response.usage?.input_tokens,
		outputTokens: response.usage?.output_tokens,
		cacheReadInputTokens: response.usage?.cache_read_input_tokens,
		cacheCreationInputTokens: response.usage?.cache_creation_input_tokens
	};
}
function getMaxMcpToolCalls(config) {
	if (config.max_tool_calls == null) return DEFAULT_MAX_MCP_TOOL_CALLS;
	if (!Number.isFinite(config.max_tool_calls) || config.max_tool_calls < 0) return DEFAULT_MAX_MCP_TOOL_CALLS;
	return Math.floor(config.max_tool_calls);
}
function getMcpContinuationParams(params, messages) {
	if (params.tool_choice?.type === "any" || params.tool_choice?.type === "tool") {
		const { tool_choice: _toolChoice, ...continuationParams } = params;
		return {
			...continuationParams,
			messages
		};
	}
	return {
		...params,
		messages
	};
}
function normalizeMcpToolContent(content) {
	if (content == null) return "";
	if (typeof content === "string") return content;
	if (Array.isArray(content)) return content.map((part) => {
		if (typeof part === "string") return part;
		if (part && typeof part === "object") {
			if ("text" in part && part.text != null) return String(part.text);
			if ("json" in part) return JSON.stringify(part.json);
			if ("data" in part) return JSON.stringify(part.data);
			return JSON.stringify(part);
		}
		return String(part);
	}).join("\n");
	return JSON.stringify(content);
}
function coerceMcpToolInput(input) {
	if (input == null || input === "") return {};
	if (typeof input === "string") {
		const parsed = JSON.parse(input);
		return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
	}
	return typeof input === "object" && !Array.isArray(input) ? input : {};
}
function mergeAnthropicUsage(messages) {
	const usageEntries = messages.map((message) => message.usage).filter((usage) => usage != null);
	if (usageEntries.length === 0) return;
	const [firstUsage, ...remainingUsageEntries] = usageEntries;
	return remainingUsageEntries.reduce((acc, usage) => ({
		...usage,
		input_tokens: acc.input_tokens + (usage.input_tokens ?? 0),
		output_tokens: acc.output_tokens + (usage.output_tokens ?? 0),
		cache_creation_input_tokens: (acc.cache_creation_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0),
		cache_read_input_tokens: (acc.cache_read_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0)
	}), firstUsage);
}
function withMergedAnthropicUsage(response, responses) {
	const usage = mergeAnthropicUsage(responses);
	return usage ? {
		...response,
		usage
	} : response;
}
function getAnthropicCostFromMessage(modelName, config, message) {
	return require_util$2.calculateAnthropicCost(modelName, config, message.usage?.input_tokens, message.usage?.output_tokens, message.usage?.cache_read_input_tokens ?? void 0, message.usage?.cache_creation_input_tokens ?? void 0);
}
var AnthropicMessagesProvider = class AnthropicMessagesProvider extends AnthropicGenericProvider {
	mcpClient = null;
	initializationPromise = null;
	samplingParamsDeprecationWarned = false;
	manualThinkingConversionWarned = false;
	static SUPPORTS_CLAUDE_CODE_OAUTH = true;
	static ANTHROPIC_MODELS = require_util$2.ANTHROPIC_MODELS;
	static ANTHROPIC_MODELS_NAMES = require_util$2.ANTHROPIC_MODELS.map((model) => model.id);
	constructor(modelName, options = {}) {
		if (!AnthropicMessagesProvider.ANTHROPIC_MODELS_NAMES.includes(modelName)) require_logger.logger.warn(`Using unknown Anthropic model: ${modelName}`);
		super(modelName, options);
		const { id } = options;
		this.id = id ? () => id : this.id;
		if (this.config.mcp?.enabled) this.initializationPromise = this.initializeMCP();
	}
	async initializeMCP() {
		this.mcpClient = new require_client.MCPClient(this.config.mcp);
		await this.mcpClient.initialize();
	}
	async cleanup() {
		if (this.mcpClient) {
			await this.initializationPromise;
			await this.mcpClient.cleanup();
			this.mcpClient = null;
		}
	}
	async resolveMcpToolUse({ config, headers, initialResponse, params, shouldStream }) {
		if (!this.mcpClient) return { response: initialResponse };
		const mcpToolNames = new Set(this.mcpClient.getAllTools().map((tool) => tool.name));
		if (mcpToolNames.size === 0) return { response: initialResponse };
		const maxToolCalls = getMaxMcpToolCalls(config);
		if (maxToolCalls === 0) return { response: initialResponse };
		let response = initialResponse;
		const responses = [initialResponse];
		let messages = params.messages;
		let executedMcpToolCalls = 0;
		for (let iteration = 0; iteration < maxToolCalls; iteration++) {
			const responseToolUses = response.content.filter((block) => block.type === "tool_use");
			const toolUses = responseToolUses.filter((block) => mcpToolNames.has(block.name));
			if (toolUses.length === 0) return { response: withMergedAnthropicUsage(response, responses) };
			if (toolUses.length !== responseToolUses.length) {
				require_logger.logger.warn("Skipping Anthropic MCP continuation because the response mixes MCP and non-MCP tool_use blocks.");
				return { response: withMergedAnthropicUsage(response, responses) };
			}
			if (executedMcpToolCalls + toolUses.length > maxToolCalls) return {
				response: withMergedAnthropicUsage(response, responses),
				error: `Anthropic MCP tool execution exceeded max_tool_calls=${maxToolCalls}. Increase provider config.max_tool_calls if this evaluation legitimately needs more tool calls.`
			};
			executedMcpToolCalls += toolUses.length;
			const toolResultBlocks = await Promise.all(toolUses.map((toolUse) => this.callMcpToolForAnthropic(toolUse)));
			messages = [
				...messages,
				{
					role: "assistant",
					content: response.content
				},
				{
					role: "user",
					content: toolResultBlocks
				}
			];
			const nextParams = getMcpContinuationParams(params, messages);
			if (shouldStream) response = await finalMessageWithStreamedStopDetails(await this.anthropic.messages.stream(nextParams, { ...Object.keys(headers).length > 0 ? { headers } : {} }));
			else response = await this.anthropic.messages.create(nextParams, { ...Object.keys(headers).length > 0 ? { headers } : {} });
			require_logger.logger.debug("Anthropic Messages API MCP follow-up response", { response: getMessagesResponseMetadata(response) });
			responses.push(response);
		}
		const unresolvedToolUses = response.content.filter((block) => block.type === "tool_use" && mcpToolNames.has(block.name));
		return {
			response: withMergedAnthropicUsage(response, responses),
			...unresolvedToolUses.length > 0 ? { error: `Anthropic MCP tool execution exceeded max_tool_calls=${maxToolCalls}. Increase provider config.max_tool_calls if this evaluation legitimately needs more tool calls.` } : {}
		};
	}
	async callMcpToolForAnthropic(toolUse) {
		try {
			const result = await this.mcpClient.callTool(toolUse.name, coerceMcpToolInput(toolUse.input));
			if (require_util$1.isMcpErrorResult(result)) return {
				type: "tool_result",
				tool_use_id: toolUse.id,
				content: `MCP Tool Error (${toolUse.name}): ${require_util$1.getMcpErrorMessage(result)}`,
				is_error: true
			};
			return {
				type: "tool_result",
				tool_use_id: toolUse.id,
				content: normalizeMcpToolContent(result.content)
			};
		} catch (error) {
			return {
				type: "tool_result",
				tool_use_id: toolUse.id,
				content: `MCP Tool Error (${toolUse.name}): ${error instanceof Error ? error.message : String(error)}`,
				is_error: true
			};
		}
	}
	toString() {
		if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
		return `[Anthropic Messages Provider ${this.modelName}]`;
	}
	async callApi(prompt, context) {
		if (this.initializationPromise != null) await this.initializationPromise;
		if (!this.apiKey && !this.usingClaudeCodeOAuth) throw new Error("Anthropic API key is not set. Set the ANTHROPIC_API_KEY environment variable or add `apiKey` to the provider config. Alternatively, if you have an active Claude Code session, set `apiKeyRequired: false` in the provider config to authenticate via Claude Code.");
		if (this.usingClaudeCodeOAuth && this.claudeCodeCredential && isCredentialExpired(this.claudeCodeCredential)) throw new Error("Claude Code OAuth credential is expired. Run `claude /login` to refresh it, then re-run the eval.");
		if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
		const spanContext = {
			system: "anthropic",
			operationName: "chat",
			model: this.modelName,
			providerId: this.id(),
			maxTokens: this.config.max_tokens,
			temperature: this.config.temperature,
			testIndex: context?.test?.vars?.__testIdx,
			promptLabel: context?.prompt?.label,
			traceparent: context?.traceparent,
			requestBody: prompt
		};
		const resultExtractor = (response) => {
			const result = {};
			if (response.tokenUsage) result.tokenUsage = {
				prompt: response.tokenUsage.prompt,
				completion: response.tokenUsage.completion,
				total: response.tokenUsage.total,
				cached: response.tokenUsage.cached,
				completionDetails: response.tokenUsage.completionDetails
			};
			if (response.finishReason) result.finishReasons = [response.finishReason];
			if (response.cached !== void 0) result.cacheHit = response.cached;
			if (response.output !== void 0) result.responseBody = typeof response.output === "string" ? response.output : JSON.stringify(response.output);
			return result;
		};
		return require_util.withGenAISpan(spanContext, () => this.callApiInternal(prompt, context), resultExtractor);
	}
	/**
	* Internal implementation of callApi without tracing wrapper.
	*/
	async callApiInternal(prompt, context) {
		const config = {
			...this.config,
			...context?.prompt?.config
		};
		const { system, extractedMessages, thinking } = require_util$2.parseMessages(prompt);
		let mcpTools = [];
		if (this.mcpClient) mcpTools = require_transform.transformMCPToolsToAnthropic(this.mcpClient.getAllTools());
		const { processedTools: processedConfigTools, requiredBetaFeatures } = require_util$2.processAnthropicTools(require_fetch.transformTools(await require_util.maybeLoadToolsFromExternalFile(config.tools, context?.vars) || [], "anthropic"));
		const allTools = [...mcpTools, ...processedConfigTools];
		const processedOutputFormat = require_util.maybeLoadResponseFormatFromExternalFile(config.output_format, context?.vars);
		const samplingParamsDeprecated = require_util$2.isSamplingParamsDeprecatedClaudeModel(this.modelName);
		let resolvedThinking = resolveThinkingConfig(config.thinking, thinking);
		if (samplingParamsDeprecated && resolvedThinking?.type === "enabled") {
			if (!this.manualThinkingConversionWarned) {
				require_logger.logger.warn("Manual extended thinking (thinking.type \"enabled\") is not supported on Claude Opus 4.7 and 4.8 and has been converted to adaptive thinking. Use thinking: { type: \"adaptive\" } with effort to control reasoning depth.");
				this.manualThinkingConversionWarned = true;
			}
			resolvedThinking = { type: "adaptive" };
		}
		const thinkingEnabled = isThinkingEnabled(resolvedThinking);
		if (thinkingEnabled) {
			if (config.top_k != null) require_logger.logger.warn("top_k is incompatible with extended thinking and will be omitted. Remove top_k from your config or disable thinking.");
			if (config.temperature != null) require_logger.logger.warn("temperature is incompatible with extended thinking and will be omitted. Remove temperature from your config or disable thinking.");
			if (config.top_p != null && (config.top_p < .95 || config.top_p > 1)) require_logger.logger.warn(`top_p must be between 0.95 and 1.0 with extended thinking (got ${config.top_p}). Clamping to valid range.`);
		}
		let resolvedToolChoice;
		if (config.tool_choice) {
			const transformed = require_fetch.transformToolChoice(config.tool_choice, "anthropic");
			if (thinkingEnabled && (transformed.type === "any" || transformed.type === "tool")) require_logger.logger.warn(`tool_choice type '${transformed.type}' (forced tool use) is incompatible with extended thinking and will be omitted. Use 'auto' or remove tool_choice.`);
			else resolvedToolChoice = transformed;
		}
		let resolvedTopP;
		if (config.top_p != null) resolvedTopP = thinkingEnabled ? Math.max(.95, Math.min(1, config.top_p)) : config.top_p;
		if (config.temperature != null && resolvedTopP != null && !thinkingEnabled) require_logger.logger.warn("temperature is incompatible with top_p on Anthropic and will be omitted. Remove one of these parameters.");
		if (this.modelName.startsWith("claude-opus-4-6") && extractedMessages.length > 0) {
			if (extractedMessages[extractedMessages.length - 1].role === "assistant") require_logger.logger.warn("Assistant message prefilling is not supported on Claude Opus 4.6 and will cause a 400 error. Remove the trailing assistant message from your prompt.");
		}
		const explicitSamplingParam = config.temperature != null || config.top_p != null || config.top_k != null || parseEnvFloat(this.env?.ANTHROPIC_TEMPERATURE) != null || parseEnvFloat(process.env.ANTHROPIC_TEMPERATURE) != null;
		if (samplingParamsDeprecated && explicitSamplingParam && !this.samplingParamsDeprecationWarned) {
			require_logger.logger.warn("temperature is deprecated on Claude Opus 4.7 and 4.8 and will be omitted (along with top_p and top_k). Remove these sampling parameters from your config (or unset ANTHROPIC_TEMPERATURE) to silence this warning.");
			this.samplingParamsDeprecationWarned = true;
		}
		const omitTemperature = resolvedTopP != null || thinkingEnabled || samplingParamsDeprecated;
		const resolvedSystem = this.usingClaudeCodeOAuth ? [{
			type: "text",
			text: CLAUDE_CODE_IDENTITY_PROMPT
		}, ...system ?? []] : system;
		const shouldStream = config.stream ?? false;
		const params = {
			model: this.modelName,
			...resolvedSystem && resolvedSystem.length > 0 ? { system: resolvedSystem } : {},
			max_tokens: config.max_tokens ?? require_logger.getEnvInt("ANTHROPIC_MAX_TOKENS", thinkingEnabled ? 2048 : 1024),
			messages: extractedMessages,
			stream: shouldStream,
			...omitTemperature ? {} : { temperature: config.temperature ?? parseEnvFloat(this.env?.ANTHROPIC_TEMPERATURE) ?? require_logger.getEnvFloat("ANTHROPIC_TEMPERATURE", 0) },
			...resolvedTopP == null || samplingParamsDeprecated ? {} : { top_p: resolvedTopP },
			...config.top_k == null || thinkingEnabled || samplingParamsDeprecated ? {} : { top_k: config.top_k },
			...config.cache_control ? { cache_control: config.cache_control } : {},
			...config.service_tier ? { service_tier: config.service_tier } : {},
			...config.stop_sequences?.length ? { stop_sequences: config.stop_sequences } : {},
			...config.metadata ? { metadata: config.metadata } : {},
			...allTools.length > 0 ? { tools: allTools } : {},
			...resolvedToolChoice ? { tool_choice: resolvedToolChoice } : {},
			...resolvedThinking ? { thinking: resolvedThinking } : {},
			...processedOutputFormat || config.effort ? { output_config: {
				...processedOutputFormat ? { format: processedOutputFormat } : {},
				...config.effort ? { effort: config.effort } : {}
			} } : {},
			...typeof config?.extra_body === "object" && config.extra_body ? config.extra_body : {}
		};
		require_logger.logger.debug("Calling Anthropic Messages API", { params: getMessagesRequestMetadata(params) });
		const headers = { ...config.headers || {} };
		let allBetaFeatures = [...config.beta || [], ...requiredBetaFeatures];
		const userBetaHeader = config.headers?.["anthropic-beta"];
		if (typeof userBetaHeader === "string" && userBetaHeader.length > 0) allBetaFeatures.push(...userBetaHeader.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0));
		if (processedOutputFormat && !allBetaFeatures.includes("structured-outputs-2025-11-13")) allBetaFeatures.push("structured-outputs-2025-11-13");
		if (this.usingClaudeCodeOAuth) allBetaFeatures.push(...CLAUDE_CODE_OAUTH_BETA_FEATURES);
		allBetaFeatures = [...new Set(allBetaFeatures)];
		if (allBetaFeatures.length > 0) headers["anthropic-beta"] = allBetaFeatures.join(",");
		if (this.usingClaudeCodeOAuth) {
			headers["user-agent"] = CLAUDE_CODE_USER_AGENT;
			headers["x-app"] = "cli";
		}
		const cache = await require_cache.getCache();
		const { metadata: _metadata, ...cacheKeyParams } = params;
		const cacheKeyHeaders = normalizeHeadersForCacheKey(headers);
		const cacheKey = `anthropic:messages:${this.modelName}:${this.getCacheIdentityHash()}:${this.getCacheAuthNamespace()}:${hashAnthropicCacheValue({
			...cacheKeyParams,
			...cacheKeyHeaders ? { headers: cacheKeyHeaders } : {}
		})}`;
		const shouldUseResponseCache = require_cache.isCacheEnabled() && config.mcp?.enabled !== true;
		if (shouldUseResponseCache) {
			const cachedResponse = await cache.get(cacheKey);
			if (cachedResponse) {
				require_logger.logger.debug("Returning cached Anthropic Messages response", { model: this.modelName });
				try {
					const parsedCachedResponse = JSON.parse(cachedResponse);
					const finishReason = require_chat.normalizeFinishReason(parsedCachedResponse.stop_reason);
					let output = require_util$2.outputFromMessage(parsedCachedResponse, config.showThinking ?? true);
					if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
						output = JSON.parse(output);
					} catch (error) {
						require_logger.logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
					}
					const cachedRefusalDetails = require_util$2.getRefusalDetails(parsedCachedResponse);
					return {
						output,
						tokenUsage: require_util$2.getTokenUsage(parsedCachedResponse, true),
						...finishReason && { finishReason },
						...cachedRefusalDetails && { guardrails: {
							flagged: true,
							reason: cachedRefusalDetails
						} },
						cost: getAnthropicCostFromMessage(this.modelName, config, parsedCachedResponse),
						cached: true
					};
				} catch {
					return {
						output: cachedResponse,
						tokenUsage: require_tokenUsageUtils.createEmptyTokenUsage()
					};
				}
			}
		}
		const requestOptions = Object.keys(headers).length > 0 ? { headers } : {};
		try {
			let initialMessage;
			if (shouldStream) {
				initialMessage = await finalMessageWithStreamedStopDetails(await this.anthropic.messages.stream(params, requestOptions));
				require_logger.logger.debug(`Anthropic Messages API streaming complete`, { finalMessage: getMessagesResponseMetadata(initialMessage) });
			} else {
				initialMessage = await this.anthropic.messages.create(params, requestOptions);
				require_logger.logger.debug(`Anthropic Messages API response`, { response: getMessagesResponseMetadata(initialMessage) });
			}
			const { error, response: resolvedMessage } = await this.resolveMcpToolUse({
				config,
				headers,
				initialResponse: initialMessage,
				params,
				shouldStream
			});
			if (error) return {
				error,
				tokenUsage: require_util$2.getTokenUsage(resolvedMessage, false),
				cost: getAnthropicCostFromMessage(this.modelName, config, resolvedMessage)
			};
			if (shouldUseResponseCache) try {
				await cache.set(cacheKey, JSON.stringify(resolvedMessage));
			} catch (err) {
				require_logger.logger.error(`Failed to cache response: ${String(err)}`);
			}
			const finishReason = require_chat.normalizeFinishReason(resolvedMessage.stop_reason);
			let output = require_util$2.outputFromMessage(resolvedMessage, config.showThinking ?? true);
			if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
				output = JSON.parse(output);
			} catch (error) {
				require_logger.logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
			}
			const refusalDetails = require_util$2.getRefusalDetails(resolvedMessage);
			if (refusalDetails) require_logger.logger.warn(refusalDetails);
			return {
				output,
				tokenUsage: require_util$2.getTokenUsage(resolvedMessage, false),
				...finishReason && { finishReason },
				...refusalDetails && { guardrails: {
					flagged: true,
					reason: refusalDetails
				} },
				cost: getAnthropicCostFromMessage(this.modelName, config, resolvedMessage)
			};
		} catch (err) {
			require_logger.logger.error(`Anthropic Messages API call error: ${err instanceof Error ? err.message : String(err)}`);
			if (err instanceof _anthropic_ai_sdk.APIError && err.error) {
				const errorDetails = err.error;
				return { error: `API call error: ${errorDetails.error.message}, status ${err.status}, type ${errorDetails.error.type}` };
			}
			return { error: `API call error: ${err instanceof Error ? err.message : String(err)}` };
		}
	}
};
//#endregion
Object.defineProperty(exports, "AnthropicGenericProvider", {
	enumerable: true,
	get: function() {
		return AnthropicGenericProvider;
	}
});
Object.defineProperty(exports, "AnthropicMessagesProvider", {
	enumerable: true,
	get: function() {
		return AnthropicMessagesProvider;
	}
});
Object.defineProperty(exports, "hashAnthropicCacheValue", {
	enumerable: true,
	get: function() {
		return hashAnthropicCacheValue;
	}
});

//# sourceMappingURL=messages-ByZknv1K.cjs.map