const require_rolldown_runtime = require("./rolldown-runtime-D_mwlA32.cjs");
const require_logger = require("./logger-DuG3amVa.cjs");
const require_invariant = require("./invariant-KxYLhw_b.cjs");
const require_fetch = require("./fetch-Hdu2Q-w3.cjs");
const require_accounts = require("./accounts-CibSkI-0.cjs");
const require_tokenUsageUtils = require("./tokenUsageUtils-DQwV4JGQ.cjs");
const require_remoteGeneration = require("./remoteGeneration-BeDYd404.cjs");
const require_util = require("./util-DCzL3qY62.cjs");
const require_promptLength = require("./promptLength-DpSjaC0G.cjs");
const require_evaluatorHelpers = require("./evaluatorHelpers-D2-tB9VN.cjs");
let async = require("async");
async = require_rolldown_runtime.__toESM(async, 1);
let chalk = require("chalk");
chalk = require_rolldown_runtime.__toESM(chalk, 1);
let dedent = require("dedent");
dedent = require_rolldown_runtime.__toESM(dedent, 1);
//#region src/redteam/providers/bestOfN.ts
var BestOfNProvider = class {
	config;
	id() {
		return "promptfoo:redteam:best-of-n";
	}
	constructor(options = {}) {
		if (require_remoteGeneration.neverGenerateRemote()) throw new Error(require_remoteGeneration.getRemoteGenerationExplicitlyDisabledError("Best-of-N strategy"));
		require_invariant.invariant(typeof options.injectVar === "string", "Expected injectVar to be set");
		this.config = {
			injectVar: options.injectVar,
			maxConcurrency: options.maxConcurrency || 3,
			nSteps: options.nSteps,
			maxCandidatesPerStep: options.maxCandidatesPerStep
		};
	}
	async callApi(_prompt, context, options) {
		require_logger.logger.debug("[Best-of-N] callApi context", { context });
		require_invariant.invariant(context?.originalProvider, "Expected originalProvider to be set");
		require_invariant.invariant(context?.vars, "Expected vars to be set");
		const targetProvider = context.originalProvider;
		const targetTokenUsage = require_tokenUsageUtils.createEmptyTokenUsage();
		const sessionIds = [];
		try {
			const data = await (await require_fetch.fetchWithProxy(require_remoteGeneration.getRemoteGenerationUrl(), {
				method: "POST",
				headers: require_remoteGeneration.getRemoteGenerationHeaders(),
				body: JSON.stringify({
					task: "jailbreak:best-of-n",
					prompt: context.vars[this.config.injectVar],
					nSteps: this.config.nSteps,
					maxCandidatesPerStep: this.config.maxCandidatesPerStep,
					version: require_fetch.VERSION,
					email: require_accounts.getUserEmail()
				})
			}, options?.abortSignal)).json();
			require_invariant.invariant(Array.isArray(data.modifiedPrompts), "Expected modifiedPrompts array in response");
			require_logger.logger.debug(dedent.default`
          ${chalk.default.bold.green("Best-of-N candidates:")}
          ${chalk.default.cyan(JSON.stringify(data.modifiedPrompts, null, 2))}
        `);
			let successfulResponse = null;
			let lastResponse = null;
			let currentStep = 0;
			await async.default.eachLimit(data.modifiedPrompts, this.config.maxConcurrency, async (candidatePrompt) => {
				if (successfulResponse) return;
				if (typeof candidatePrompt !== "string") {
					require_logger.logger.warn("[Best-of-N] Skipping non-string candidate prompt from remote generation", {
						component: "Best-of-N",
						event: "SkippingCandidatePrompt",
						reason: "non-string",
						candidatePromptType: typeof candidatePrompt
					});
					return;
				}
				const unsafeCandidateScheme = /^\s*(file:\/\/|package:)/i.exec(candidatePrompt)?.[1].toLowerCase();
				if (unsafeCandidateScheme) {
					const schemeLabel = unsafeCandidateScheme.startsWith("file") ? "file://" : "package:";
					require_logger.logger.warn(`[Best-of-N] Skipping unsafe ${schemeLabel} candidate prompt from remote generation`, {
						component: "Best-of-N",
						event: "SkippingCandidatePrompt",
						reason: schemeLabel === "file://" ? "unsafe-file-protocol" : "unsafe-package-protocol"
					});
					return;
				}
				const targetVars = {
					...context.vars,
					[this.config.injectVar]: candidatePrompt
				};
				const renderedPrompt = await require_evaluatorHelpers.renderPrompt(context.prompt, targetVars, context.filters, targetProvider, [this.config.injectVar]);
				try {
					require_promptLength.throwIfTargetPromptExceedsMaxChars(renderedPrompt);
					const response = await targetProvider.callApi(renderedPrompt, context, options);
					const sessionId = require_util.getSessionId(response, context);
					if (sessionId) sessionIds.push(sessionId);
					lastResponse = response;
					require_tokenUsageUtils.accumulateResponseTokenUsage(targetTokenUsage, response);
					currentStep++;
					if (!response.error) {
						successfulResponse = response;
						successfulResponse.prompt = candidatePrompt;
						successfulResponse.metadata = {
							...successfulResponse.metadata,
							redteamFinalPrompt: candidatePrompt,
							step: currentStep
						};
						return false;
					}
				} catch (err) {
					require_logger.logger.debug(`[Best-of-N] Candidate failed: ${err}`);
					lastResponse = { error: String(err) };
					currentStep++;
				}
			});
			if (successfulResponse) {
				successfulResponse.tokenUsage = targetTokenUsage;
				return successfulResponse;
			}
			if (lastResponse) {
				lastResponse.tokenUsage = targetTokenUsage;
				lastResponse.metadata = {
					...lastResponse.metadata ?? {},
					sessionIds
				};
			}
			return lastResponse || {
				error: "All candidates failed",
				metadata: { sessionIds }
			};
		} catch (err) {
			if (err instanceof Error && err.name === "AbortError") throw err;
			require_logger.logger.error(`[Best-of-N] Error: ${err}`);
			return {
				error: String(err),
				metadata: { sessionIds }
			};
		}
	}
};
//#endregion
exports.default = BestOfNProvider;

//# sourceMappingURL=bestOfN-2pD7fRQo.cjs.map