//#region src/media-shared/http/api-key-rotation.ts
const ROTATABLE_PATTERNS = [
	/\b401\b/,
	/\b403\b/,
	/\b429\b/,
	/unauthorized/i,
	/forbidden/i,
	/rate[\s_-]?limit/i,
	/quota/i,
	/invalid[\s_-]?api[\s_-]?key/i,
	/api[\s_-]?key.*(invalid|expired|revoked)/i
];
/**
* Default retry classifier: rotate on auth / quota signals (401/403/429 + textual hints).
* Network errors and 5xx are intentionally NOT rotated (see file-level DECISION).
*/
function isRotatableAuthFailure(message) {
	if (!message) return false;
	for (const pattern of ROTATABLE_PATTERNS) if (pattern.test(message)) return true;
	return false;
}
function dedupeApiKeys(raw) {
	const seen = /* @__PURE__ */ new Set();
	const keys = [];
	for (const value of raw) {
		const apiKey = value.trim();
		if (!apiKey || seen.has(apiKey)) continue;
		seen.add(apiKey);
		keys.push(apiKey);
	}
	return keys;
}
function formatMessage(error) {
	if (error instanceof Error) return error.message;
	if (typeof error === "string") return error;
	try {
		return JSON.stringify(error);
	} catch {
		return String(error);
	}
}
/**
* Run `execute(apiKey)` with each candidate key in turn until one succeeds or all
* keys are exhausted. The last error is rethrown when no key succeeds.
*
* Throws synchronously when no usable keys are configured (caller should detect
* this via NotConfiguredError semantics in the upstream provider plugin).
*/
async function executeWithApiKeyRotation(options) {
	const keys = dedupeApiKeys(options.apiKeys);
	if (keys.length === 0) throw new Error(`No API keys configured for provider "${options.provider}".`);
	let lastError;
	for (let attempt = 0; attempt < keys.length; attempt += 1) {
		const apiKey = keys[attempt];
		try {
			return await options.execute(apiKey);
		} catch (error) {
			lastError = error;
			const message = formatMessage(error);
			const params = {
				apiKey,
				error,
				attempt,
				message
			};
			if (!(options.shouldRetry ? options.shouldRetry(params) : isRotatableAuthFailure(message)) || attempt + 1 >= keys.length) break;
			options.onRetry?.(params);
		}
	}
	if (lastError === void 0) throw new Error(`Failed to run API request for provider "${options.provider}".`);
	throw lastError;
}
/**
* Collect candidate keys for a provider from a primary slot + an optional list of
* extras (typically read from config under e.g. `apiKeys: string[]`).
*
* Empty / duplicate values are dropped. The primary key (when set) always comes
* first so that single-key callers see no behavioral change.
*/
function collectProviderApiKeysForExecution(input) {
	const primary = input.primaryApiKey?.trim();
	return dedupeApiKeys(primary ? [primary, ...input.extraApiKeys ?? []] : [...input.extraApiKeys ?? []]);
}
//#endregion
export { collectProviderApiKeysForExecution, executeWithApiKeyRotation, isRotatableAuthFailure };

//# sourceMappingURL=api-key-rotation.js.map