import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
import { A as getEnvString, o as logger } from "./logger-CfDSdx1q.js";
import { A as parseChatPrompt, w as getRequestTimeoutMs } from "./fetch-CHx36OdV.js";
import { Ct as getNunjucksEngine, ct as maybeLoadFromExternalFile, yt as renderVarsInObject } from "./util-DqNaBNjn.js";
import { r as fetchWithCache } from "./cache-IpWZkF7H.js";
import { a as geminiFormatAndSystemInstructions, b as CHAT_MODELS, c as getLastPromptSafetyRatings, d as mergeParts, f as normalizeSafetySettings, g as resolveGoogleToolConfig, h as removeGoogleFunctionDeclarations, i as formatCandidateContents, l as isNonCandidateStreamChunk, n as collectGroundingMetadata, o as getCandidate, r as createAuthCacheDiscriminator, t as calculateGoogleCost, u as mergeGoogleCompletionOptions } from "./util-BtjL1MRK.js";
import { t as GoogleGenericProvider } from "./base-BGrauzJm.js";
//#region src/providers/google/ai.studio.ts
var ai_studio_exports = /* @__PURE__ */ __exportAll({
	AIStudioChatProvider: () => AIStudioChatProvider,
	AIStudioEmbeddingProvider: () => AIStudioEmbeddingProvider,
	getGoogleAiStudioProviders: () => getGoogleAiStudioProviders
});
const DEFAULT_API_HOST = "generativelanguage.googleapis.com";
const GENERATE_CONTENT_MODEL_PREFIXES = [
	"gemini",
	"gemma",
	"codegemma",
	"paligemma"
];
function usesGenerateContentApi(modelName) {
	return GENERATE_CONTENT_MODEL_PREFIXES.some((prefix) => modelName.startsWith(prefix));
}
function shouldBustCache(context) {
	return context?.bustCache ?? context?.debug ?? false;
}
/**
* Google AI Studio provider for Gemini models.
*
* Extends GoogleGenericProvider for shared functionality like MCP integration,
* authentication management, and resource cleanup.
*/
var AIStudioChatProvider = class extends GoogleGenericProvider {
	constructor(modelName, options = {}) {
		if (!CHAT_MODELS.includes(modelName)) logger.debug(`Using unknown Google chat model: ${modelName}`);
		super(modelName, {
			...options,
			config: {
				...options.config,
				vertexai: false
			}
		});
	}
	/**
	* Get the API endpoint URL for Google AI Studio.
	*
	* @param action - Optional action like 'generateContent'
	* @returns The full API endpoint URL
	*/
	getApiEndpoint(action) {
		const apiVersion = this.getApiVersion();
		const baseUrl = this.getApiBaseUrl();
		const actionSuffix = action ? `:${action}` : "";
		return `${baseUrl}/${apiVersion}/models/${this.modelName}${actionSuffix}`;
	}
	/**
	* Get the API version.
	*
	* Uses config.apiVersion if set, otherwise defaults to v1beta — Google's
	* primary endpoint for current Gemini models, including the Gemini 3.x
	* family. The legacy gemini-2.0-flash-thinking-exp model only responds on
	* v1alpha. Set config.apiVersion to 'v1alpha' to opt into preview-only
	* features such as media_resolution.
	*/
	getApiVersion() {
		if (this.config.apiVersion) return this.config.apiVersion;
		return this.modelName === "gemini-2.0-flash-thinking-exp" ? "v1alpha" : "v1beta";
	}
	/**
	* Get the API host for Google AI Studio.
	* Public for use by integrations like Adaline Gateway.
	*/
	getApiHost() {
		const apiHost = this.config.apiHost || this.env?.GOOGLE_API_HOST || this.env?.PALM_API_HOST || getEnvString("GOOGLE_API_HOST") || getEnvString("PALM_API_HOST") || DEFAULT_API_HOST;
		return getNunjucksEngine().renderString(apiHost, {});
	}
	/**
	* Get the base URL for Google AI Studio API.
	*/
	getApiBaseUrl() {
		const apiHost = this.config.apiHost || this.env?.GOOGLE_API_HOST || this.env?.PALM_API_HOST || getEnvString("GOOGLE_API_HOST") || getEnvString("PALM_API_HOST");
		if (apiHost) return `https://${getNunjucksEngine().renderString(apiHost, {})}`;
		if (this.config.apiBaseUrl || this.env?.GOOGLE_API_BASE_URL || getEnvString("GOOGLE_API_BASE_URL")) return this.config.apiBaseUrl || this.env?.GOOGLE_API_BASE_URL || getEnvString("GOOGLE_API_BASE_URL");
		return `https://${getNunjucksEngine().renderString(DEFAULT_API_HOST, {})}`;
	}
	/**
	* Get authentication headers for Google AI Studio.
	* API key is passed via x-goog-api-key header for improved security.
	*/
	async getAuthHeaders() {
		const headers = {
			"Content-Type": "application/json",
			...this.config.headers
		};
		const apiKey = this.getApiKey();
		if (apiKey) headers["x-goog-api-key"] = apiKey;
		return headers;
	}
	/**
	* Call the Google AI Studio API.
	*/
	async callApi(prompt, context) {
		if (this.initializationPromise != null) await this.initializationPromise;
		if (!this.getApiKey()) throw new Error("Google API key is not set. Set the GOOGLE_API_KEY or GEMINI_API_KEY environment variable or add `apiKey` to the provider config.");
		if (usesGenerateContentApi(this.modelName)) return this.callGemini(prompt, context);
		const config = mergeGoogleCompletionOptions(this.config, context?.prompt?.config);
		const body = {
			prompt: { messages: parseChatPrompt(prompt, [{ content: prompt }]) },
			temperature: config.temperature,
			topP: config.topP,
			topK: config.topK,
			safetySettings: normalizeSafetySettings(config.safetySettings),
			stopSequences: config.stopSequences,
			maxOutputTokens: config.maxOutputTokens
		};
		let data, cached = false;
		try {
			const baseUrl = this.getApiBaseUrl();
			const headers = await this.getAuthHeaders();
			const authDiscriminator = createAuthCacheDiscriminator(headers);
			({data, cached} = await fetchWithCache(`${baseUrl}/v1beta3/models/${this.modelName}:generateMessage`, {
				method: "POST",
				headers,
				body: JSON.stringify(body),
				...authDiscriminator && { _authHash: authDiscriminator }
			}, getRequestTimeoutMs(), "json", shouldBustCache(context)));
		} catch (err) {
			return { error: `API call error: ${String(err)}` };
		}
		if (!data?.candidates || data.candidates.length === 0) return { error: `API did not return any candidate responses: ${JSON.stringify(data)}` };
		try {
			const output = data.candidates[0].content;
			const tokenUsage = cached ? {
				cached: data.usageMetadata?.totalTokenCount,
				total: data.usageMetadata?.totalTokenCount,
				numRequests: 0,
				...data.usageMetadata?.thoughtsTokenCount !== void 0 && { completionDetails: {
					reasoning: data.usageMetadata.thoughtsTokenCount,
					acceptedPrediction: 0,
					rejectedPrediction: 0
				} }
			} : {
				prompt: data.usageMetadata?.promptTokenCount,
				completion: data.usageMetadata?.candidatesTokenCount,
				total: data.usageMetadata?.totalTokenCount,
				numRequests: 1,
				...data.usageMetadata?.thoughtsTokenCount !== void 0 && { completionDetails: {
					reasoning: data.usageMetadata.thoughtsTokenCount,
					acceptedPrediction: 0,
					rejectedPrediction: 0
				} }
			};
			const completionForCost = data.usageMetadata?.candidatesTokenCount == null ? void 0 : data.usageMetadata.candidatesTokenCount + (data.usageMetadata?.thoughtsTokenCount ?? 0);
			return {
				output,
				tokenUsage,
				cost: cached ? void 0 : calculateGoogleCost(this.modelName, config, data.usageMetadata?.promptTokenCount, completionForCost),
				raw: data,
				cached
			};
		} catch (err) {
			return { error: `API response error: ${String(err)}: ${JSON.stringify(data)}` };
		}
	}
	/**
	* Call the Gemini API specifically.
	*/
	async callGemini(prompt, context) {
		if (!this.getApiKey()) throw new Error("Google API key is not set. Set the GOOGLE_API_KEY or GEMINI_API_KEY environment variable or add `apiKey` to the provider config.");
		const config = mergeGoogleCompletionOptions(this.config, context?.prompt?.config);
		const { contents, systemInstruction } = geminiFormatAndSystemInstructions(prompt, context?.vars, config.systemInstruction, { useAssistantRole: config.useAssistantRole });
		const { toolConfig, toolsDisabled } = resolveGoogleToolConfig(config);
		const allTools = await this.getAllTools(context, { skipExecutableToolFiles: toolsDisabled });
		const requestTools = toolsDisabled ? removeGoogleFunctionDeclarations(allTools) : allTools;
		const body = {
			contents,
			generationConfig: {
				...config.temperature !== void 0 && { temperature: config.temperature },
				...config.topP !== void 0 && { topP: config.topP },
				...config.topK !== void 0 && { topK: config.topK },
				...config.stopSequences !== void 0 && { stopSequences: config.stopSequences },
				...config.maxOutputTokens !== void 0 && { maxOutputTokens: config.maxOutputTokens },
				...config.generationConfig
			},
			safetySettings: normalizeSafetySettings(config.safetySettings),
			...toolConfig ? { toolConfig } : {},
			...requestTools.length > 0 ? { tools: requestTools } : {},
			...systemInstruction ? { system_instruction: systemInstruction } : {}
		};
		if (config.responseSchema) {
			if (body.generationConfig.response_schema) throw new Error("`responseSchema` provided but `generationConfig.response_schema` already set.");
			const schema = maybeLoadFromExternalFile(renderVarsInObject(config.responseSchema, context?.vars));
			body.generationConfig.response_schema = schema;
			body.generationConfig.response_mime_type = "application/json";
		}
		let data;
		let cached = false;
		try {
			const endpoint = this.getApiEndpoint("generateContent");
			const headers = await this.getAuthHeaders();
			const authDiscriminator = createAuthCacheDiscriminator(headers);
			({data, cached} = await fetchWithCache(endpoint, {
				method: "POST",
				headers,
				body: JSON.stringify(body),
				...authDiscriminator && { _authHash: authDiscriminator }
			}, getRequestTimeoutMs(), "json", shouldBustCache(context)));
		} catch (err) {
			return { error: `API call error: ${String(err)}` };
		}
		const dataWithResponse = Array.isArray(data) ? data : [data];
		const lastData = dataWithResponse[dataWithResponse.length - 1];
		if (!lastData) return { error: `No response data found in response: ${JSON.stringify(data)}` };
		let output;
		let candidate;
		try {
			for (const datum of dataWithResponse) {
				if (Array.isArray(data) && isNonCandidateStreamChunk(datum)) continue;
				const candidateForChunk = getCandidate(datum);
				if (candidateForChunk.finishReason === "STOP" && !candidateForChunk.content?.parts) continue;
				candidate = candidateForChunk;
				output = mergeParts(output, formatCandidateContents(candidate));
			}
			if (output === void 0 || candidate === void 0) throw new Error(`No output found in response: ${JSON.stringify(data)}`);
		} catch (err) {
			return { error: `${String(err)}` };
		}
		const finalCandidate = candidate;
		try {
			let guardrails;
			const promptSafetyRatings = getLastPromptSafetyRatings(dataWithResponse);
			if (promptSafetyRatings || finalCandidate.safetyRatings) {
				const flaggedInput = promptSafetyRatings?.some((r) => r.probability !== "NEGLIGIBLE");
				const flaggedOutput = finalCandidate.safetyRatings?.some((r) => r.probability !== "NEGLIGIBLE");
				guardrails = {
					flaggedInput,
					flaggedOutput,
					flagged: flaggedInput || flaggedOutput
				};
			}
			const grounding = collectGroundingMetadata(dataWithResponse);
			const tokenUsage = cached ? {
				cached: lastData.usageMetadata?.totalTokenCount,
				total: lastData.usageMetadata?.totalTokenCount,
				numRequests: 0,
				...lastData.usageMetadata?.thoughtsTokenCount !== void 0 && { completionDetails: {
					reasoning: lastData.usageMetadata.thoughtsTokenCount,
					acceptedPrediction: 0,
					rejectedPrediction: 0
				} }
			} : {
				prompt: lastData.usageMetadata?.promptTokenCount,
				completion: lastData.usageMetadata?.candidatesTokenCount,
				total: lastData.usageMetadata?.totalTokenCount,
				numRequests: 1,
				...lastData.usageMetadata?.thoughtsTokenCount !== void 0 && { completionDetails: {
					reasoning: lastData.usageMetadata.thoughtsTokenCount,
					acceptedPrediction: 0,
					rejectedPrediction: 0
				} }
			};
			const completionForCost = lastData.usageMetadata?.candidatesTokenCount == null ? void 0 : lastData.usageMetadata.candidatesTokenCount + (lastData.usageMetadata?.thoughtsTokenCount ?? 0);
			const cost = cached ? void 0 : calculateGoogleCost(this.modelName, config, lastData.usageMetadata?.promptTokenCount, completionForCost);
			return {
				output,
				tokenUsage,
				cost,
				raw: data,
				cached,
				...guardrails && { guardrails },
				metadata: { ...grounding }
			};
		} catch (err) {
			return { error: `API response error: ${String(err)}: ${JSON.stringify(data)}` };
		}
	}
};
/**
* Google AI Studio embedding provider.
*
* Calls the Gemini API `:embedContent` endpoint and normalizes the response
* into `ProviderEmbeddingResponse`.
*
* Exposes the three standard knobs the Gemini API accepts: `taskType`
* (optimizes the vector for a particular use case), `outputDimensionality`
* (truncates the vector; useful for storage cost), and `title` (only
* meaningful when `taskType` is `RETRIEVAL_DOCUMENT`).
*/
var AIStudioEmbeddingProvider = class extends AIStudioChatProvider {
	id() {
		if (this.customId) return this.customId();
		return `google:embedding:${this.modelName}`;
	}
	toString() {
		return `[Google AI Studio Embedding Provider ${this.modelName}]`;
	}
	async callApi(_prompt, _context) {
		return { error: `Provider ${this.id()} is an embedding provider; use a non-embedding google: provider for chat completions.` };
	}
	async callEmbeddingApi(text) {
		if (!this.getApiKey()) return { error: "Google API key is not set. Set the GOOGLE_API_KEY or GEMINI_API_KEY environment variable or add `apiKey` to the provider config." };
		if (typeof text !== "string") return { error: `Invalid input type for embedding API. Expected string, got ${typeof text}.` };
		const config = this.config;
		const body = {
			content: { parts: [{ text }] },
			...config.taskType !== void 0 && { taskType: config.taskType },
			...config.outputDimensionality !== void 0 && { outputDimensionality: config.outputDimensionality },
			...config.title !== void 0 && { title: config.title }
		};
		let data;
		let cached = false;
		try {
			const endpoint = this.getApiEndpoint("embedContent");
			const headers = await this.getAuthHeaders();
			const authDiscriminator = createAuthCacheDiscriminator(headers);
			({data, cached} = await fetchWithCache(endpoint, {
				method: "POST",
				headers,
				body: JSON.stringify(body),
				...authDiscriminator && { _authHash: authDiscriminator }
			}, getRequestTimeoutMs(), "json"));
		} catch (err) {
			logger.error(`Google AI Studio embedding API call error: ${String(err)}`);
			return { error: `API call error: ${String(err)}` };
		}
		const values = data?.embedding?.values;
		if (!values) return { error: `No embedding found in Google AI Studio response: ${JSON.stringify(data)}` };
		const promptTokens = data?.usageMetadata?.promptTokenCount;
		return {
			embedding: values,
			tokenUsage: cached ? {
				cached: promptTokens ?? 0,
				total: promptTokens ?? 0,
				numRequests: 0
			} : {
				total: promptTokens ?? 0,
				numRequests: 1
			},
			cached
		};
	}
};
const DEFAULT_AI_STUDIO_MODEL = "gemini-2.5-pro";
function getGoogleAiStudioProviders(env) {
	const gradingProvider = new AIStudioChatProvider(DEFAULT_AI_STUDIO_MODEL, { env });
	return {
		gradingJsonProvider: new AIStudioChatProvider(DEFAULT_AI_STUDIO_MODEL, {
			env,
			config: { generationConfig: { response_mime_type: "application/json" } }
		}),
		gradingProvider,
		llmRubricProvider: new AIStudioChatProvider(DEFAULT_AI_STUDIO_MODEL, { env }),
		suggestionsProvider: gradingProvider,
		synthesizeProvider: gradingProvider
	};
}
//#endregion
export { getGoogleAiStudioProviders as n, ai_studio_exports as t };

//# sourceMappingURL=ai.studio-sB0BtTr2.js.map