const require_logger = require('./logger-q_xXORhb.cjs');
const require_esm = require('./esm-D3hKBIJw.cjs');
let fs = require("fs");
fs = require_logger.__toESM(fs);
let path = require("path");
path = require_logger.__toESM(path);
let dedent = require("dedent");
dedent = require_logger.__toESM(dedent);
let crypto = require("crypto");
crypto = require_logger.__toESM(crypto);

//#region src/providers/openai/codex-sdk.ts
/**
* Helper to load the OpenAI Codex SDK ESM module
* Uses resolvePackageEntryPoint to handle ESM-only packages with restrictive exports
*/
async function loadCodexSDK() {
	const codexPath = require_esm.resolvePackageEntryPoint("@openai/codex-sdk", require_logger.cliState_default.basePath && path.default.isAbsolute(require_logger.cliState_default.basePath) ? require_logger.cliState_default.basePath : process.cwd());
	if (!codexPath) throw new Error(dedent.default`The @openai/codex-sdk package is required but not installed.

      To use the OpenAI Codex SDK provider, install it with:
        npm install @openai/codex-sdk

      Requires Node.js 18+.

      For more information, see: https://www.promptfoo.dev/docs/providers/openai-codex-sdk/`);
	try {
		return await require_esm.importModule(codexPath);
	} catch (err) {
		require_logger.logger_default.error(`Failed to load OpenAI Codex SDK: ${err}`);
		if (err.stack) require_logger.logger_default.error(err.stack);
		throw new Error(dedent.default`Failed to load @openai/codex-sdk.

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

      Try reinstalling:
        npm install @openai/codex-sdk

      For more information, see: https://www.promptfoo.dev/docs/providers/openai-codex-sdk/`);
	}
}
const CODEX_MODEL_PRICING = {
	"gpt-5.2": {
		input: 2,
		output: 8
	},
	"gpt-5.1-codex": {
		input: 2,
		output: 8
	},
	"gpt-5.1-codex-max": {
		input: 3,
		output: 12
	},
	"gpt-5.1-codex-mini": {
		input: .5,
		output: 2
	},
	"gpt-5-codex": {
		input: 2,
		output: 8
	},
	"gpt-5-codex-mini": {
		input: .5,
		output: 2
	},
	"gpt-5": {
		input: 2,
		output: 8
	},
	"gpt-4o": {
		input: 2.5,
		output: 10
	},
	"gpt-4o-mini": {
		input: .15,
		output: .6
	},
	"gpt-4-turbo": {
		input: 10,
		output: 30
	},
	"gpt-4": {
		input: 30,
		output: 60
	},
	"o3-mini": {
		input: 1.1,
		output: 4.4
	},
	o1: {
		input: 15,
		output: 60
	},
	"o1-mini": {
		input: 3,
		output: 12
	}
};
var OpenAICodexSDKProvider = class OpenAICodexSDKProvider {
	static OPENAI_MODELS = [
		"gpt-5.2",
		"gpt-5.1-codex",
		"gpt-5.1-codex-max",
		"gpt-5.1-codex-mini",
		"gpt-5-codex",
		"gpt-5-codex-mini",
		"gpt-5",
		"gpt-4",
		"gpt-4-turbo",
		"gpt-4o",
		"gpt-4o-mini",
		"o1",
		"o1-mini",
		"o3-mini"
	];
	config;
	env;
	apiKey;
	providerId = "openai:codex-sdk";
	codexModule;
	codexInstance;
	threads = /* @__PURE__ */ new Map();
	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 && !OpenAICodexSDKProvider.OPENAI_MODELS.includes(this.config.model)) require_logger.logger_default.warn(`Using unknown model for OpenAI Codex SDK: ${this.config.model}`);
	}
	id() {
		return this.providerId;
	}
	getApiKey() {
		return this.config?.apiKey || this.env?.OPENAI_API_KEY || this.env?.CODEX_API_KEY || require_logger.getEnvString("OPENAI_API_KEY") || require_logger.getEnvString("CODEX_API_KEY");
	}
	toString() {
		return "[OpenAI Codex SDK Provider]";
	}
	async cleanup() {
		this.threads.clear();
	}
	prepareEnvironment(config) {
		const env = config.cli_env ? { ...config.cli_env } : { ...process.env };
		const sortedEnv = {};
		for (const key of Object.keys(env).sort()) if (env[key] !== void 0) sortedEnv[key] = env[key];
		if (this.apiKey) {
			sortedEnv.OPENAI_API_KEY = this.apiKey;
			sortedEnv.CODEX_API_KEY = this.apiKey;
		}
		if (this.env) for (const key of Object.keys(this.env).sort()) {
			const value = this.env[key];
			if (value !== void 0) sortedEnv[key] = value;
		}
		return sortedEnv;
	}
	validateWorkingDirectory(workingDir, skipGitCheck = false) {
		let stats;
		try {
			stats = fs.default.statSync(workingDir);
		} catch (err) {
			throw new Error(`Working directory ${workingDir} does not exist or isn't accessible: ${err.message}`);
		}
		if (!stats.isDirectory()) throw new Error(`Working directory ${workingDir} is not a directory`);
		if (!skipGitCheck) {
			const gitDir = path.default.join(workingDir, ".git");
			if (!fs.default.existsSync(gitDir)) throw new Error(dedent.default`Working directory ${workingDir} is not a Git repository.

          Codex requires a Git repository by default to prevent unrecoverable errors.

          To bypass this check, set skip_git_repo_check: true in your provider config.`);
		}
	}
	buildThreadOptions(config) {
		return {
			workingDirectory: config.working_dir,
			skipGitRepoCheck: config.skip_git_repo_check ?? false,
			...config.model ? { model: config.model } : {},
			...config.additional_directories?.length ? { additionalDirectories: config.additional_directories } : {},
			...config.sandbox_mode ? { sandboxMode: config.sandbox_mode } : {},
			...config.model_reasoning_effort ? { modelReasoningEffort: config.model_reasoning_effort } : {},
			...config.network_access_enabled !== void 0 ? { networkAccessEnabled: config.network_access_enabled } : {},
			...config.web_search_enabled !== void 0 ? { webSearchEnabled: config.web_search_enabled } : {},
			...config.approval_policy ? { approvalPolicy: config.approval_policy } : {}
		};
	}
	async getOrCreateThread(config, cacheKey) {
		const threadOptions = this.buildThreadOptions(config);
		if (config.thread_id) {
			const cached = this.threads.get(config.thread_id);
			if (cached) return cached;
			const thread$1 = this.codexInstance.resumeThread(config.thread_id, threadOptions);
			if (config.persist_threads) this.threads.set(config.thread_id, thread$1);
			return thread$1;
		}
		if (config.persist_threads && cacheKey) {
			const cached = this.threads.get(cacheKey);
			if (cached) return cached;
			const poolSize = config.thread_pool_size ?? 1;
			if (this.threads.size >= poolSize) {
				const oldestKey = this.threads.keys().next().value;
				if (oldestKey) this.threads.delete(oldestKey);
			}
		}
		const thread = this.codexInstance.startThread(threadOptions);
		if (config.persist_threads && cacheKey) this.threads.set(cacheKey, thread);
		return thread;
	}
	async runStreaming(thread, prompt, runOptions, callOptions) {
		const { events } = await thread.runStreamed(prompt, runOptions);
		const items = [];
		let usage = void 0;
		for await (const event of events) {
			if (callOptions?.abortSignal?.aborted) throw new Error("AbortError");
			switch (event.type) {
				case "item.completed":
					items.push(event.item);
					require_logger.logger_default.debug("Codex item completed", { item: event.item });
					break;
				case "turn.completed":
					usage = event.usage;
					require_logger.logger_default.debug("Codex turn completed", { usage });
					break;
			}
		}
		const agentMessages = items.filter((i) => i.type === "agent_message");
		return {
			finalResponse: agentMessages.length > 0 ? agentMessages.map((i) => i.text).join("\n") : "",
			items,
			usage
		};
	}
	generateCacheKey(config, prompt) {
		const keyData = {
			working_dir: config.working_dir,
			additional_directories: config.additional_directories,
			model: config.model,
			output_schema: config.output_schema,
			sandbox_mode: config.sandbox_mode,
			model_reasoning_effort: config.model_reasoning_effort,
			network_access_enabled: config.network_access_enabled,
			web_search_enabled: config.web_search_enabled,
			approval_policy: config.approval_policy,
			prompt
		};
		return `openai:codex-sdk:${crypto.default.createHash("sha256").update(JSON.stringify(keyData)).digest("hex")}`;
	}
	async callApi(prompt, context, callOptions) {
		const config = {
			...this.config,
			...context?.prompt?.config
		};
		const env = this.prepareEnvironment(config);
		if (!this.apiKey && !env.OPENAI_API_KEY && !env.CODEX_API_KEY) throw new Error("OpenAI API key is not set. Set OPENAI_API_KEY or CODEX_API_KEY environment variable or add \"apiKey\" to provider config.");
		if (config.working_dir) this.validateWorkingDirectory(config.working_dir, config.skip_git_repo_check);
		if (callOptions?.abortSignal?.aborted) return { error: "OpenAI Codex SDK call aborted before it started" };
		if (!this.codexModule) this.codexModule = await loadCodexSDK();
		if (!this.codexInstance) this.codexInstance = new this.codexModule.Codex({
			env,
			...config.codex_path_override ? { codexPathOverride: config.codex_path_override } : {},
			...config.base_url ? { baseUrl: config.base_url } : {}
		});
		const cacheKey = this.generateCacheKey(config, prompt);
		const thread = await this.getOrCreateThread(config, cacheKey);
		const runOptions = {};
		if (config.output_schema) runOptions.outputSchema = config.output_schema;
		if (callOptions?.abortSignal) runOptions.signal = callOptions.abortSignal;
		try {
			const turn = config.enable_streaming ? await this.runStreaming(thread, prompt, runOptions, callOptions) : await thread.run(prompt, runOptions);
			const output = turn.finalResponse || "";
			const raw = JSON.stringify(turn);
			const tokenUsage = turn.usage ? {
				prompt: turn.usage.input_tokens + (turn.usage.cached_input_tokens || 0),
				completion: turn.usage.output_tokens,
				total: turn.usage.input_tokens + (turn.usage.cached_input_tokens || 0) + turn.usage.output_tokens
			} : void 0;
			let cost = 0;
			if (tokenUsage && config.model) {
				const pricing = CODEX_MODEL_PRICING[config.model];
				if (pricing) cost = (tokenUsage.prompt || 0) * (pricing.input / 1e6) + (tokenUsage.completion || 0) * (pricing.output / 1e6);
			}
			require_logger.logger_default.debug("OpenAI Codex SDK response", {
				output,
				usage: turn.usage
			});
			return {
				output,
				tokenUsage,
				cost,
				raw,
				sessionId: thread.id || "unknown"
			};
		} catch (error) {
			if (error?.name === "AbortError" || callOptions?.abortSignal?.aborted) {
				require_logger.logger_default.warn("OpenAI Codex SDK call aborted");
				return { error: "OpenAI Codex SDK call aborted" };
			}
			require_logger.logger_default.error("Error calling OpenAI Codex SDK", { error: error.message });
			return { error: `Error calling OpenAI Codex SDK: ${error.message}` };
		} finally {
			if (!config.persist_threads && !config.thread_id && cacheKey) this.threads.delete(cacheKey);
		}
	}
};

//#endregion
exports.OpenAICodexSDKProvider = OpenAICodexSDKProvider;
//# sourceMappingURL=codex-sdk-C5jmJKIa.cjs.map