import { n as clampThinkingLevel, t as calculateCost } from "./models-k4kEajYR.js";
import { n as getEnvApiKey } from "./env-api-keys-BI4aR4GG.js";
import { t as AssistantMessageEventStream } from "./event-stream-Bz0Z073I.js";
import { i as sanitizeSurrogates, r as buildBaseOptions } from "./transform-messages-CjB2Gne2.js";
import { a as mapToolChoice, i as mapStopReason, n as convertTools, o as retainThoughtSignature, r as isThinkingPart, t as convertMessages } from "./google-shared-HDWT-v6F.js";
import { GoogleGenAI } from "@google/genai";
//#region node_modules/@mariozechner/pi-ai/dist/providers/google.js
let toolCallCounter = 0;
const streamGoogle = (model, context, options) => {
	const stream = new AssistantMessageEventStream();
	(async () => {
		const output = {
			role: "assistant",
			content: [],
			api: "google-generative-ai",
			provider: model.provider,
			model: model.id,
			usage: {
				input: 0,
				output: 0,
				cacheRead: 0,
				cacheWrite: 0,
				totalTokens: 0,
				cost: {
					input: 0,
					output: 0,
					cacheRead: 0,
					cacheWrite: 0,
					total: 0
				}
			},
			stopReason: "stop",
			timestamp: Date.now()
		};
		try {
			const client = createClient(model, options?.apiKey || getEnvApiKey(model.provider) || "", options?.headers);
			let params = buildParams(model, context, options);
			const nextParams = await options?.onPayload?.(params, model);
			if (nextParams !== void 0) params = nextParams;
			const googleStream = await client.models.generateContentStream(params);
			stream.push({
				type: "start",
				partial: output
			});
			let currentBlock = null;
			const blocks = output.content;
			const blockIndex = () => blocks.length - 1;
			for await (const chunk of googleStream) {
				output.responseId ||= chunk.responseId;
				const candidate = chunk.candidates?.[0];
				if (candidate?.content?.parts) for (const part of candidate.content.parts) {
					if (part.text !== void 0) {
						const isThinking = isThinkingPart(part);
						if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
							if (currentBlock) if (currentBlock.type === "text") stream.push({
								type: "text_end",
								contentIndex: blocks.length - 1,
								content: currentBlock.text,
								partial: output
							});
							else stream.push({
								type: "thinking_end",
								contentIndex: blockIndex(),
								content: currentBlock.thinking,
								partial: output
							});
							if (isThinking) {
								currentBlock = {
									type: "thinking",
									thinking: "",
									thinkingSignature: void 0
								};
								output.content.push(currentBlock);
								stream.push({
									type: "thinking_start",
									contentIndex: blockIndex(),
									partial: output
								});
							} else {
								currentBlock = {
									type: "text",
									text: ""
								};
								output.content.push(currentBlock);
								stream.push({
									type: "text_start",
									contentIndex: blockIndex(),
									partial: output
								});
							}
						}
						if (currentBlock.type === "thinking") {
							currentBlock.thinking += part.text;
							currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
							stream.push({
								type: "thinking_delta",
								contentIndex: blockIndex(),
								delta: part.text,
								partial: output
							});
						} else {
							currentBlock.text += part.text;
							currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
							stream.push({
								type: "text_delta",
								contentIndex: blockIndex(),
								delta: part.text,
								partial: output
							});
						}
					}
					if (part.functionCall) {
						if (currentBlock) {
							if (currentBlock.type === "text") stream.push({
								type: "text_end",
								contentIndex: blockIndex(),
								content: currentBlock.text,
								partial: output
							});
							else stream.push({
								type: "thinking_end",
								contentIndex: blockIndex(),
								content: currentBlock.thinking,
								partial: output
							});
							currentBlock = null;
						}
						const providedId = part.functionCall.id;
						const toolCall = {
							type: "toolCall",
							id: !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId) ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}` : providedId,
							name: part.functionCall.name || "",
							arguments: part.functionCall.args ?? {},
							...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
						};
						output.content.push(toolCall);
						stream.push({
							type: "toolcall_start",
							contentIndex: blockIndex(),
							partial: output
						});
						stream.push({
							type: "toolcall_delta",
							contentIndex: blockIndex(),
							delta: JSON.stringify(toolCall.arguments),
							partial: output
						});
						stream.push({
							type: "toolcall_end",
							contentIndex: blockIndex(),
							toolCall,
							partial: output
						});
					}
				}
				if (candidate?.finishReason) {
					output.stopReason = mapStopReason(candidate.finishReason);
					if (output.content.some((b) => b.type === "toolCall")) output.stopReason = "toolUse";
				}
				if (chunk.usageMetadata) {
					output.usage = {
						input: (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),
						output: (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),
						cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,
						cacheWrite: 0,
						totalTokens: chunk.usageMetadata.totalTokenCount || 0,
						cost: {
							input: 0,
							output: 0,
							cacheRead: 0,
							cacheWrite: 0,
							total: 0
						}
					};
					calculateCost(model, output.usage);
				}
			}
			if (currentBlock) if (currentBlock.type === "text") stream.push({
				type: "text_end",
				contentIndex: blockIndex(),
				content: currentBlock.text,
				partial: output
			});
			else stream.push({
				type: "thinking_end",
				contentIndex: blockIndex(),
				content: currentBlock.thinking,
				partial: output
			});
			if (options?.signal?.aborted) throw new Error("Request was aborted");
			if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
			stream.push({
				type: "done",
				reason: output.stopReason,
				message: output
			});
			stream.end();
		} catch (error) {
			for (const block of output.content) if ("index" in block) delete block.index;
			output.stopReason = options?.signal?.aborted ? "aborted" : "error";
			output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
			stream.push({
				type: "error",
				reason: output.stopReason,
				error: output
			});
			stream.end();
		}
	})();
	return stream;
};
const streamSimpleGoogle = (model, context, options) => {
	const apiKey = options?.apiKey || getEnvApiKey(model.provider);
	if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
	const base = buildBaseOptions(model, options, apiKey);
	if (!options?.reasoning) return streamGoogle(model, context, {
		...base,
		thinking: { enabled: false }
	});
	const clampedReasoning = clampThinkingLevel(model, options.reasoning);
	const effort = clampedReasoning === "off" ? "high" : clampedReasoning;
	const googleModel = model;
	if (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel) || isGemma4Model(googleModel)) return streamGoogle(model, context, {
		...base,
		thinking: {
			enabled: true,
			level: getThinkingLevel(effort, googleModel)
		}
	});
	return streamGoogle(model, context, {
		...base,
		thinking: {
			enabled: true,
			budgetTokens: getGoogleBudget(googleModel, effort, options.thinkingBudgets)
		}
	});
};
function createClient(model, apiKey, optionsHeaders) {
	const httpOptions = {};
	if (model.baseUrl) {
		httpOptions.baseUrl = model.baseUrl;
		httpOptions.apiVersion = "";
	}
	if (model.headers || optionsHeaders) httpOptions.headers = {
		...model.headers,
		...optionsHeaders
	};
	return new GoogleGenAI({
		apiKey,
		httpOptions: Object.keys(httpOptions).length > 0 ? httpOptions : void 0
	});
}
function buildParams(model, context, options = {}) {
	const contents = convertMessages(model, context);
	const generationConfig = {};
	if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
	if (options.maxTokens !== void 0) generationConfig.maxOutputTokens = options.maxTokens;
	const config = {
		...Object.keys(generationConfig).length > 0 && generationConfig,
		...context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) },
		...context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }
	};
	if (context.tools && context.tools.length > 0 && options.toolChoice) config.toolConfig = { functionCallingConfig: { mode: mapToolChoice(options.toolChoice) } };
	else config.toolConfig = void 0;
	if (options.thinking?.enabled && model.reasoning) {
		const thinkingConfig = { includeThoughts: true };
		if (options.thinking.level !== void 0) thinkingConfig.thinkingLevel = options.thinking.level;
		else if (options.thinking.budgetTokens !== void 0) thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
		config.thinkingConfig = thinkingConfig;
	} else if (model.reasoning && options.thinking && !options.thinking.enabled) config.thinkingConfig = getDisabledThinkingConfig(model);
	if (options.signal) {
		if (options.signal.aborted) throw new Error("Request aborted");
		config.abortSignal = options.signal;
	}
	return {
		model: model.id,
		contents,
		config
	};
}
function isGemma4Model(model) {
	return /gemma-?4/.test(model.id.toLowerCase());
}
function isGemini3ProModel(model) {
	return /gemini-3(?:\.\d+)?-pro/.test(model.id.toLowerCase());
}
function isGemini3FlashModel(model) {
	return /gemini-3(?:\.\d+)?-flash/.test(model.id.toLowerCase());
}
function getDisabledThinkingConfig(model) {
	if (isGemini3ProModel(model)) return { thinkingLevel: "LOW" };
	if (isGemini3FlashModel(model)) return { thinkingLevel: "MINIMAL" };
	if (isGemma4Model(model)) return { thinkingLevel: "MINIMAL" };
	return { thinkingBudget: 0 };
}
function getThinkingLevel(effort, model) {
	if (isGemini3ProModel(model)) switch (effort) {
		case "minimal":
		case "low": return "LOW";
		case "medium":
		case "high": return "HIGH";
	}
	if (isGemma4Model(model)) switch (effort) {
		case "minimal":
		case "low": return "MINIMAL";
		case "medium":
		case "high": return "HIGH";
	}
	switch (effort) {
		case "minimal": return "MINIMAL";
		case "low": return "LOW";
		case "medium": return "MEDIUM";
		case "high": return "HIGH";
	}
}
function getGoogleBudget(model, effort, customBudgets) {
	if (customBudgets?.[effort] !== void 0) return customBudgets[effort];
	if (model.id.includes("2.5-pro")) return {
		minimal: 128,
		low: 2048,
		medium: 8192,
		high: 32768
	}[effort];
	if (model.id.includes("2.5-flash-lite")) return {
		minimal: 512,
		low: 2048,
		medium: 8192,
		high: 24576
	}[effort];
	if (model.id.includes("2.5-flash")) return {
		minimal: 128,
		low: 2048,
		medium: 8192,
		high: 24576
	}[effort];
	return -1;
}
//#endregion
export { streamGoogle, streamSimpleGoogle };
