const require_logger = require('./logger-q_xXORhb.cjs');
const require_esm = require('./esm-D3hKBIJw.cjs');
require('./pythonUtils-CA-U67vF.cjs');
require('./types-DxNbVAX2.cjs');
require('./util-C-nJy5yZ.cjs');
require('./fetch--6dTWCD4.cjs');
require('./cache-BrwLt6g7.cjs');
const require_transform = require('./transform-DFn8CyvR.cjs');
const require_util$1 = require('./util-IPzLzpX6.cjs');
const require_cometapi = require('./cometapi-Zc9YHFmo.cjs');
let node_fs = require("node:fs");
node_fs = require_logger.__toESM(node_fs);
let node_path = require("node:path");
node_path = require_logger.__toESM(node_path);
let dedent = require("dedent");
dedent = require_logger.__toESM(dedent);
let node_os = require("node:os");
node_os = require_logger.__toESM(node_os);

//#region src/providers/claude-agent-sdk.ts
/**
* Claude Agent SDK Provider
*
* This provider requires the @anthropic-ai/claude-agent-sdk package to be installed separately:
*   npm install @anthropic-ai/claude-agent-sdk
*
* Two default configurations:
* - No working_dir: Runs in temp directory with no tools - behaves like plain chat API
* - With working_dir: Runs in specified directory with read-only file tools (Read/Grep/Glob/LS)
*
* User can override tool permissions with 'custom_allowed_tools', 'append_allowed_tools', 'disallowed_tools', and 'permission_mode'.
*
* For side effects (file writes, system calls, etc.), user can override permissions and use a custom working directory. They're then responsible for setup/teardown and security considerations.
*
* MCP server connection details are passed through from config. strict_mcp_config is true by default to only allow explicitly configured MCP servers.
*/
const FS_READONLY_ALLOWED_TOOLS = [
	"Read",
	"Grep",
	"Glob",
	"LS"
].sort();
const CLAUDE_CODE_MODEL_ALIASES = [
	"default",
	"sonnet",
	"opus",
	"haiku",
	"sonnet[1m]",
	"opusplan"
];
/**
* Helper to load the Claude Agent SDK ESM module
* Uses resolvePackageEntryPoint to handle ESM-only packages with restrictive exports
*/
async function loadClaudeCodeSDK() {
	const claudeCodePath = require_esm.resolvePackageEntryPoint("@anthropic-ai/claude-agent-sdk", require_logger.cliState_default.basePath && node_path.default.isAbsolute(require_logger.cliState_default.basePath) ? require_logger.cliState_default.basePath : process.cwd());
	if (!claudeCodePath) throw new Error(dedent.default`The @anthropic-ai/claude-agent-sdk package is required but not installed.

      To use the Claude Agent SDK provider, install it with:
        npm install @anthropic-ai/claude-agent-sdk

      For more information, see: https://www.promptfoo.dev/docs/providers/claude-agent-sdk/`);
	try {
		return require_esm.importModule(claudeCodePath);
	} catch (err) {
		require_logger.logger_default.error(`Failed to load Claude Agent SDK: ${err}`);
		if (err.stack) require_logger.logger_default.error(err.stack);
		throw new Error(dedent.default`Failed to load @anthropic-ai/claude-agent-sdk.

      The package was found but could not be loaded. This may be due to:
      - Incompatible Node.js version (requires Node.js 20+)
      - Corrupted installation

      Try reinstalling:
        npm install @anthropic-ai/claude-agent-sdk

      For more information, see: https://www.promptfoo.dev/docs/providers/claude-agent-sdk/`);
	}
}
/**
* Creates a canUseTool callback for handling AskUserQuestion tool in automated evaluations.
* This provides automated responses to questions that would normally require user input.
*
* The callback wraps an optional user-provided canUseTool and handles AskUserQuestion specifically,
* deferring to the wrapped callback for all other tools.
*/
function createAskUserQuestionCanUseTool(behavior = "first_option", wrappedCanUseTool) {
	return async (toolName, input, options) => {
		if (toolName !== "AskUserQuestion") {
			if (wrappedCanUseTool) return wrappedCanUseTool(toolName, input, options);
			return {
				behavior: "allow",
				updatedInput: input
			};
		}
		if (behavior === "deny") return {
			behavior: "deny",
			message: "AskUserQuestion is disabled in automated evaluation mode"
		};
		const toolInput = input;
		const answers = {};
		for (const question of toolInput.questions) {
			if (!question.options || question.options.length === 0) continue;
			let selectedLabels;
			if (behavior === "random") {
				const randomIndex = Math.floor(Math.random() * question.options.length);
				selectedLabels = [question.options[randomIndex].label];
			} else selectedLabels = [question.options[0].label];
			answers[question.question] = selectedLabels.join(", ");
		}
		return {
			behavior: "allow",
			updatedInput: {
				questions: toolInput.questions,
				answers
			}
		};
	};
}
var ClaudeCodeSDKProvider = class ClaudeCodeSDKProvider {
	static ANTHROPIC_MODELS = require_util$1.ANTHROPIC_MODELS;
	static ANTHROPIC_MODELS_NAMES = require_util$1.ANTHROPIC_MODELS.map((model) => model.id);
	config;
	env;
	apiKey;
	providerId = "anthropic:claude-agent-sdk";
	claudeCodeModule;
	constructor(options = {}) {
		const { config, env, id } = options;
		this.config = config ?? {};
		this.env = env;
		this.apiKey = this.getApiKey();
		this.providerId = id ?? this.providerId;
		if (this.config.model && !ClaudeCodeSDKProvider.ANTHROPIC_MODELS_NAMES.includes(this.config.model) && !CLAUDE_CODE_MODEL_ALIASES.includes(this.config.model)) require_logger.logger_default.warn(`Using unknown model for Claude Agent SDK: ${this.config.model}`);
		if (this.config.fallback_model && !ClaudeCodeSDKProvider.ANTHROPIC_MODELS_NAMES.includes(this.config.fallback_model) && !CLAUDE_CODE_MODEL_ALIASES.includes(this.config.fallback_model)) require_logger.logger_default.warn(`Using unknown model for Claude Agent SDK fallback: ${this.config.fallback_model}`);
	}
	id() {
		return this.providerId;
	}
	async callApi(prompt, context, callOptions) {
		const config = {
			...this.config,
			...context?.prompt?.config
		};
		const env = {};
		for (const key of Object.keys(process.env).sort()) if (process.env[key] !== void 0) env[key] = process.env[key];
		if (this.env) for (const key of Object.keys(this.env).sort()) {
			const value = this.env[key];
			if (value !== void 0) env[key] = value;
		}
		if (this.apiKey) env.ANTHROPIC_API_KEY = this.apiKey;
		if (!this.apiKey && !(env.CLAUDE_CODE_USE_BEDROCK || env.CLAUDE_CODE_USE_VERTEX)) throw new Error(dedent.default`Anthropic API key is not set. Set the ANTHROPIC_API_KEY environment variable or add "apiKey" to the provider config.

        Use CLAUDE_CODE_USE_BEDROCK or CLAUDE_CODE_USE_VERTEX environment variables to use Bedrock or Vertex instead.`);
		if (config.allow_all_tools && ("custom_allowed_tools" in config || "append_allowed_tools" in config)) throw new Error("Cannot specify both allow_all_tools and custom_allowed_tools or append_allowed_tools");
		if ("custom_allowed_tools" in config && "append_allowed_tools" in config) throw new Error("Cannot specify both custom_allowed_tools and append_allowed_tools");
		if (config.permission_mode === "bypassPermissions" && !config.allow_dangerously_skip_permissions) throw new Error("permission_mode 'bypassPermissions' requires allow_dangerously_skip_permissions: true as a safety measure");
		const defaultAllowedTools = config.working_dir ? FS_READONLY_ALLOWED_TOOLS : [];
		let allowedTools = config.allow_all_tools ? void 0 : defaultAllowedTools;
		if ("custom_allowed_tools" in config) allowedTools = Array.from(new Set(config.custom_allowed_tools ?? [])).sort();
		else if (config.append_allowed_tools) allowedTools = Array.from(new Set([...defaultAllowedTools, ...config.append_allowed_tools])).sort();
		const disallowedTools = config.disallowed_tools ? Array.from(new Set(config.disallowed_tools)).sort() : void 0;
		let isTempDir = false;
		let workingDir;
		if (config.working_dir) workingDir = config.working_dir;
		else isTempDir = true;
		let canUseTool;
		if (config.ask_user_question) canUseTool = createAskUserQuestionCanUseTool(config.ask_user_question.behavior);
		const cacheKeyQueryOptions = {
			maxTurns: config.max_turns,
			model: config.model,
			fallbackModel: config.fallback_model,
			strictMcpConfig: config.strict_mcp_config ?? true,
			permissionMode: config.permission_mode,
			systemPrompt: config.custom_system_prompt ? config.custom_system_prompt : {
				type: "preset",
				preset: "claude_code",
				append: config.append_system_prompt
			},
			maxThinkingTokens: config.max_thinking_tokens,
			allowedTools,
			disallowedTools,
			plugins: config.plugins,
			maxBudgetUsd: config.max_budget_usd,
			additionalDirectories: config.additional_directories,
			resume: config.resume,
			forkSession: config.fork_session,
			resumeSessionAt: config.resume_session_at,
			continue: config.continue,
			agents: config.agents,
			outputFormat: config.output_format,
			hooks: config.hooks,
			includePartialMessages: config.include_partial_messages,
			betas: config.betas,
			sandbox: config.sandbox,
			allowDangerouslySkipPermissions: config.allow_dangerously_skip_permissions,
			permissionPromptToolName: config.permission_prompt_tool_name,
			executable: config.executable,
			executableArgs: config.executable_args,
			extraArgs: config.extra_args,
			pathToClaudeCodeExecutable: config.path_to_claude_code_executable,
			settingSources: config.setting_sources,
			tools: config.tools,
			enableFileCheckpointing: config.enable_file_checkpointing,
			persistSession: config.persist_session,
			env
		};
		const cacheResult = await require_cometapi.initializeAgenticCache({
			cacheKeyPrefix: "anthropic:claude-agent-sdk",
			workingDir: config.working_dir,
			bustCache: context?.bustCache
		}, {
			prompt,
			cacheKeyQueryOptions
		});
		const cachedResponse = await require_cometapi.getCachedResponse(cacheResult, "Claude Agent SDK");
		if (cachedResponse) return cachedResponse;
		const mcpServers = config.mcp ? await require_transform.transformMCPConfigToClaudeCode(config.mcp) : {};
		if (workingDir) {
			let stats;
			try {
				stats = node_fs.default.statSync(workingDir);
			} catch (err) {
				throw new Error(`Working dir ${config.working_dir} does not exist or isn't accessible: ${err.message}`);
			}
			if (!stats.isDirectory()) throw new Error(`Working dir ${config.working_dir} is not a directory`);
		} else if (isTempDir) workingDir = node_fs.default.mkdtempSync(node_path.default.join(node_os.default.tmpdir(), "promptfoo-claude-agent-sdk-"));
		if (callOptions?.abortSignal?.aborted) return { error: "Claude Agent SDK call aborted before it started" };
		const abortController = new AbortController();
		let abortHandler;
		if (callOptions?.abortSignal) {
			abortHandler = () => {
				abortController.abort(callOptions.abortSignal.reason);
			};
			callOptions.abortSignal.addEventListener("abort", abortHandler);
		}
		const options = {
			...cacheKeyQueryOptions,
			abortController,
			mcpServers,
			cwd: workingDir,
			stderr: config.stderr,
			spawnClaudeCodeProcess: config.spawn_claude_code_process,
			canUseTool
		};
		const queryParams = {
			prompt,
			options
		};
		require_logger.logger_default.debug(`Calling Claude Agent SDK: ${JSON.stringify({
			prompt,
			options: {
				...options,
				mcpServers: options.mcpServers ? Object.keys(options.mcpServers) : void 0,
				env: Object.keys(env).length > 0 ? Object.keys(env) : void 0
			}
		})}`);
		try {
			if (!this.claudeCodeModule) this.claudeCodeModule = await loadClaudeCodeSDK();
			const res = await this.claudeCodeModule.query(queryParams);
			for await (const msg of res) if (msg.type == "result") {
				const raw = JSON.stringify(msg);
				const tokenUsage = {
					prompt: msg.usage?.input_tokens,
					completion: msg.usage?.output_tokens,
					total: msg.usage?.input_tokens && msg.usage?.output_tokens ? msg.usage?.input_tokens + msg.usage?.output_tokens : void 0
				};
				const cost = msg.total_cost_usd ?? 0;
				const sessionId = msg.session_id;
				if (msg.subtype == "success") {
					require_logger.logger_default.debug(`Claude Agent SDK response: ${raw}`);
					const response = {
						output: msg.structured_output !== void 0 ? msg.structured_output : msg.result,
						tokenUsage,
						cost,
						raw,
						sessionId
					};
					if (msg.structured_output !== void 0) response.metadata = {
						...response.metadata,
						structuredOutput: msg.structured_output
					};
					await require_cometapi.cacheResponse(cacheResult, response, "Claude Agent SDK");
					return response;
				} else return {
					error: `Claude Agent SDK call failed: ${msg.subtype}`,
					tokenUsage,
					cost,
					raw,
					sessionId
				};
			}
			return { error: "Claude Agent SDK call didn't return a result" };
		} catch (error) {
			if (error?.name === "AbortError" || callOptions?.abortSignal?.aborted) {
				require_logger.logger_default.warn("Claude Agent SDK call aborted");
				return { error: "Claude Agent SDK call aborted" };
			}
			require_logger.logger_default.error(`Error calling Claude Agent SDK: ${error}`);
			return { error: `Error calling Claude Agent SDK: ${error}` };
		} finally {
			if (isTempDir && workingDir) node_fs.default.rmSync(workingDir, {
				recursive: true,
				force: true
			});
			if (callOptions?.abortSignal && abortHandler) callOptions.abortSignal.removeEventListener("abort", abortHandler);
		}
	}
	toString() {
		return "[Anthropic Claude Agent SDK Provider]";
	}
	/**
	* For normal Claude Agent SDK support, just use the Anthropic API key
	* Users can also use Bedrock (with CLAUDE_CODE_USE_BEDROCK env var) or Vertex (with CLAUDE_CODE_USE_VERTEX env var)
	*/
	getApiKey() {
		return this.config?.apiKey || this.env?.ANTHROPIC_API_KEY || require_logger.getEnvString("ANTHROPIC_API_KEY");
	}
	async cleanup() {}
};

//#endregion
exports.ClaudeCodeSDKProvider = ClaudeCodeSDKProvider;
//# sourceMappingURL=claude-agent-sdk-BR8eu7B2.cjs.map