import { A as getEnvString, o as logger } from "./logger-CfDSdx1q.js";
import { w as getRequestTimeoutMs } from "./fetch-CHx36OdV.js";
import { r as fetchWithCache } from "./cache-IpWZkF7H.js";
import { i as toDataUri } from "./dataUrl-CXQl71ri.js";
import { D as resolveProjectId, E as loadCredentials, a as geminiFormatAndSystemInstructions, f as normalizeSafetySettings, g as resolveGoogleToolConfig, h as removeGoogleFunctionDeclarations, p as normalizeTools, r as createAuthCacheDiscriminator, w as getGoogleClient } from "./util-BtjL1MRK.js";
//#region src/providers/google/gemini-image.ts
/**
* Gemini native image generation provider.
*
* Uses the Gemini generateContent API with responseModalities set to include images.
* This is different from Imagen models which use the :predict endpoint.
*
* Supported models:
* - gemini-2.5-flash-image
* - gemini-3-pro-image-preview (Nano Banana Pro)
* - gemini-3.1-flash-image-preview (Nano Banana 2)
*/
var GeminiImageProvider = class {
	modelName;
	config;
	env;
	constructor(modelName, options = {}) {
		this.modelName = modelName;
		this.config = options.config || {};
		this.env = options.env;
	}
	id() {
		return `google:${this.modelName}`;
	}
	toString() {
		return `[Google Gemini Image Generation Provider ${this.modelName}]`;
	}
	getApiKey() {
		return this.config.apiKey || getEnvString("GOOGLE_API_KEY") || getEnvString("GOOGLE_GENERATIVE_AI_API_KEY") || getEnvString("GEMINI_API_KEY") || this.env?.GOOGLE_API_KEY || this.env?.GOOGLE_GENERATIVE_AI_API_KEY || this.env?.GEMINI_API_KEY;
	}
	/**
	* Gemini 3.x image models use the global Vertex endpoint.
	* Older models (e.g. gemini-2.5) use regional endpoints.
	*/
	usesGlobalVertexEndpoint() {
		return this.modelName.startsWith("gemini-3");
	}
	/**
	* imageSize is supported across Gemini 3.x image models.
	*/
	supportsImageSize() {
		return this.modelName.startsWith("gemini-3");
	}
	async callApi(prompt, context) {
		if (!prompt) return { error: "Prompt is required for image generation" };
		if (this.config.projectId || getEnvString("GOOGLE_CLOUD_PROJECT") || getEnvString("GOOGLE_PROJECT_ID") || this.env?.GOOGLE_CLOUD_PROJECT || this.env?.GOOGLE_PROJECT_ID) return this.callVertexApi(prompt, context);
		if (this.getApiKey()) return this.callAIStudioApi(prompt, context);
		return { error: "Gemini image models require either:\n1. Google AI Studio: Set GOOGLE_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or GEMINI_API_KEY environment variable\n2. Vertex AI: Set GOOGLE_CLOUD_PROJECT environment variable or provide projectId in config, and run \"gcloud auth application-default login\"" };
	}
	async callAIStudioApi(prompt, context) {
		const apiKey = this.getApiKey();
		if (!apiKey) return { error: "API key not found. Set GOOGLE_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or GEMINI_API_KEY environment variable." };
		const endpoint = `https://${this.config.apiHost || "generativelanguage.googleapis.com"}/v1beta/models/${this.modelName}:generateContent`;
		const { contents } = geminiFormatAndSystemInstructions(prompt, context?.vars);
		const body = this.buildRequestBody(contents);
		try {
			const headers = {
				"Content-Type": "application/json",
				"x-goog-api-key": apiKey,
				...this.config.headers || {}
			};
			const authDiscriminator = createAuthCacheDiscriminator(headers);
			const startTime = Date.now();
			const { data, cached } = await fetchWithCache(endpoint, {
				method: "POST",
				headers,
				body: JSON.stringify(body),
				...authDiscriminator && { _authHash: authDiscriminator }
			}, getRequestTimeoutMs(), "json", false);
			const latencyMs = Date.now() - startTime;
			return this.processResponse(data, cached, latencyMs);
		} catch (err) {
			return { error: `API call error: ${String(err)}` };
		}
	}
	async callVertexApi(prompt, context) {
		const usesGlobalVertexEndpoint = this.usesGlobalVertexEndpoint();
		const location = usesGlobalVertexEndpoint ? "global" : this.config.region || getEnvString("GOOGLE_LOCATION") || this.env?.GOOGLE_LOCATION || "us-central1";
		try {
			const { client } = await getGoogleClient({ credentials: loadCredentials(this.config.credentials) });
			const projectId = await resolveProjectId(this.config, this.env);
			if (!projectId) return { error: "Google project ID is required for Vertex AI. Set GOOGLE_PROJECT_ID or add projectId to provider config." };
			const endpoint = `${usesGlobalVertexEndpoint ? "https://aiplatform.googleapis.com" : `https://${location}-aiplatform.googleapis.com`}/v1/projects/${projectId}/locations/${location}/publishers/google/models/${this.modelName}:generateContent`;
			logger.debug(`Vertex AI Gemini Image API endpoint: ${endpoint}`);
			logger.debug(`Project ID: ${projectId}, Location: ${location}, Model: ${this.modelName}`);
			const { contents } = geminiFormatAndSystemInstructions(prompt, context?.vars);
			const body = this.buildRequestBody(contents);
			const startTime = Date.now();
			const response = await client.request({
				url: endpoint,
				method: "POST",
				headers: {
					"Content-Type": "application/json",
					...this.config.headers || {}
				},
				data: body,
				timeout: getRequestTimeoutMs()
			});
			const latencyMs = Date.now() - startTime;
			return this.processResponse(response.data, false, latencyMs);
		} catch (err) {
			if (err.response?.data?.error) return { error: `Vertex AI error: ${err.response.data.error.message || "Unknown error"}` };
			return { error: `Failed to call Vertex AI: ${err.message || "Unknown error"}` };
		}
	}
	buildRequestBody(contents) {
		const body = {
			contents,
			generationConfig: {
				responseModalities: ["TEXT", "IMAGE"],
				...this.config.temperature !== void 0 && { temperature: this.config.temperature },
				...this.config.topP !== void 0 && { topP: this.config.topP },
				...this.config.topK !== void 0 && { topK: this.config.topK },
				...this.config.maxOutputTokens !== void 0 && { maxOutputTokens: this.config.maxOutputTokens },
				...this.config.generationConfig
			}
		};
		const supportsImageSize = this.supportsImageSize();
		if (this.config.imageAspectRatio || this.config.imageSize && supportsImageSize) body.generationConfig.imageConfig = {
			...this.config.imageAspectRatio && { aspectRatio: this.config.imageAspectRatio },
			...this.config.imageSize && supportsImageSize && { imageSize: this.config.imageSize }
		};
		if (this.config.safetySettings) body.safetySettings = normalizeSafetySettings(this.config.safetySettings);
		const { toolConfig, toolsDisabled } = resolveGoogleToolConfig(this.config);
		if (toolConfig) body.toolConfig = toolConfig;
		if (Array.isArray(this.config.tools) && this.config.tools.length > 0) {
			const normalizedTools = normalizeTools(this.config.tools);
			const requestTools = toolsDisabled ? removeGoogleFunctionDeclarations(normalizedTools) : normalizedTools;
			if (requestTools.length > 0) body.tools = requestTools;
		}
		return body;
	}
	processResponse(data, cached, latencyMs) {
		logger.debug(`Response data: ${JSON.stringify(data).substring(0, 500)}...`);
		if (!data || typeof data !== "object") return { error: "Invalid response from API" };
		if (data.error) return { error: data.error.message || JSON.stringify(data.error) };
		if (!data.candidates || data.candidates.length === 0) {
			let errorDetails = "No candidates returned in API response.";
			if (data.promptFeedback?.blockReason) errorDetails = `Response blocked: ${data.promptFeedback.blockReason}`;
			return { error: errorDetails };
		}
		const candidate = data.candidates[0];
		if (candidate.finishReason && [
			"SAFETY",
			"RECITATION",
			"PROHIBITED_CONTENT",
			"BLOCKLIST",
			"SPII"
		].includes(candidate.finishReason)) return { error: `Response was blocked with finish reason: ${candidate.finishReason}` };
		if (!candidate.content?.parts) return { error: "No content parts in response" };
		const textParts = [];
		const imageParts = [];
		let totalCost = 0;
		for (const part of candidate.content.parts) if (part.text) textParts.push(part.text);
		else if (part.inlineData) {
			const mimeType = part.inlineData.mimeType || "image/png";
			const base64Data = part.inlineData.data;
			imageParts.push({
				mimeType,
				base64Data
			});
			totalCost += this.getCostPerImage();
		}
		if (imageParts.length === 0 && textParts.length === 0) return { error: "No valid content generated" };
		const tokenUsage = cached ? {
			cached: data.usageMetadata?.totalTokenCount,
			total: data.usageMetadata?.totalTokenCount,
			numRequests: 0
		} : {
			prompt: data.usageMetadata?.promptTokenCount,
			completion: data.usageMetadata?.candidatesTokenCount,
			total: data.usageMetadata?.totalTokenCount,
			numRequests: 1
		};
		const images = imageParts.length > 0 ? imageParts.map((img) => ({
			data: toDataUri(img.mimeType, img.base64Data),
			mimeType: img.mimeType
		})) : void 0;
		return {
			output: imageParts.length > 0 && textParts.length === 0 ? images[0].data : textParts.join("\n\n"),
			images,
			cached,
			latencyMs,
			cost: totalCost > 0 ? totalCost : void 0,
			tokenUsage,
			raw: data
		};
	}
	getCostPerImage() {
		return {
			"gemini-2.5-flash-image": .039,
			"gemini-2.5-flash-preview-image-generation": .039,
			"gemini-3.1-flash-image-preview": .067,
			"gemini-3-pro-image-preview": .05
		}[this.modelName] || .04;
	}
};
//#endregion
export { GeminiImageProvider };

//# sourceMappingURL=gemini-image-C3YhAcQ5.js.map