#!/usr/bin/env node
import { L as state, c as logger } from "./logger-4ntIRWmf.js";
import { C as getRequestTimeoutMs, M as transformTools } from "./fetch-gOBR1GF3.js";
import { r as importModule } from "./esm-BOYGx5J1.js";
import { G as parseFileUrl, Z as getNunjucksEngine, z as maybeLoadToolsFromExternalFile } from "./util-DAS7mIn_.js";
import { t as MCPClient } from "./client-CvPvnqvw.js";
import { p as normalizeTools, v as stripExecutableToolFileReferences, x as GoogleAuthManager, y as validateFunctionCall } from "./util-Beq4CzIC2.js";
import { r as transformMCPToolsToGoogle } from "./transform-jttM7xdw.js";
import path from "path";
//#region src/providers/google/base.ts
/**
* Base class for Google AI providers.
*
* This abstract class provides shared functionality for both Google AI Studio
* and Vertex AI providers, including:
* - MCP (Model Context Protocol) client integration
* - Function callback execution
* - Tool normalization
* - Resource cleanup
*
* Subclasses must implement:
* - getApiEndpoint(): Returns the API endpoint URL
* - getAuthHeaders(): Returns authentication headers
* - callApi(): The main API call implementation
*/
/**
* Abstract base class for Google AI providers.
*
* Provides shared functionality for Google AI Studio and Vertex AI,
* with abstract methods for endpoint and authentication that differ
* between the two services.
*/
var GoogleGenericProvider = class {
	/** The model name (e.g., 'gemini-2.5-pro') */
	modelName;
	/** Provider configuration */
	config;
	/** Environment variable overrides */
	env;
	/** Whether this provider is in Vertex AI mode */
	isVertexMode;
	/** MCP client for tool integration */
	mcpClient = null;
	/** Promise that resolves when MCP initialization is complete */
	initializationPromise = null;
	/** Cache of loaded function callbacks */
	loadedFunctionCallbacks = {};
	/** Custom provider ID function */
	customId;
	constructor(modelName, options = {}) {
		const { config, id, env } = options;
		this.env = env;
		this.modelName = modelName;
		this.config = config || {};
		this.isVertexMode = GoogleAuthManager.determineVertexMode(this.config, this.env);
		GoogleAuthManager.validateAndWarn({
			apiKey: this.config.apiKey,
			credentials: this.config.credentials,
			projectId: this.config.projectId,
			region: this.config.region,
			vertexai: this.isVertexMode,
			googleAuthOptions: this.config.googleAuthOptions,
			keyFilename: this.config.keyFilename,
			scopes: this.config.scopes,
			strictMutualExclusivity: this.config.strictMutualExclusivity
		}, this.env);
		if (id) this.customId = () => id;
		if (this.config.mcp?.enabled) this.initializationPromise = this.initializeMCP();
	}
	validateFunctionToolCall(output, vars) {
		validateFunctionCall(output, this.config.tools, vars);
	}
	/**
	* Get the provider ID string.
	* Format: 'google:{model}' for AI Studio, 'vertex:{model}' for Vertex AI
	*/
	id() {
		if (this.customId) return this.customId();
		return this.isVertexMode ? `vertex:${this.modelName}` : `google:${this.modelName}`;
	}
	/**
	* Get a string representation of the provider.
	*/
	toString() {
		return `[Google ${this.isVertexMode ? "Vertex AI" : "Google AI Studio"} Provider ${this.modelName}]`;
	}
	/**
	* Get the API key for this provider.
	* Applies Nunjucks rendering to support template variables.
	*
	* @returns The API key or undefined
	*/
	requiresApiKey() {
		return !this.isVertexMode;
	}
	getApiKey() {
		const { apiKey } = GoogleAuthManager.getApiKey(this.config, this.env, this.isVertexMode);
		if (apiKey) return getNunjucksEngine().renderString(apiKey, {});
	}
	/**
	* Get the region for Vertex AI.
	*
	* @returns The region (default: 'global' for OAuth, 'us-central1' for API key)
	*/
	getRegion() {
		const hasApiKey = Boolean(this.getApiKey());
		return GoogleAuthManager.resolveRegion(this.config, this.env, hasApiKey);
	}
	/**
	* Get the project ID for Vertex AI.
	*
	* @returns Promise resolving to the project ID
	*/
	async getProjectId() {
		return GoogleAuthManager.resolveProjectId({
			projectId: this.config.projectId,
			credentials: this.config.credentials,
			googleAuthOptions: this.config.googleAuthOptions,
			keyFilename: this.config.keyFilename,
			scopes: this.config.scopes
		}, this.env);
	}
	/**
	* Initialize the MCP client for tool integration.
	*/
	async initializeMCP() {
		if (!this.config.mcp) return;
		this.mcpClient = new MCPClient(this.config.mcp);
		await this.mcpClient.initialize();
	}
	/**
	* Get all tools for the request, combining MCP tools and config tools.
	*
	* @param context - Call context with variables
	* @returns Array of Google-format tools
	*/
	async getAllTools(context, options = {}) {
		const mcpTools = this.mcpClient ? transformMCPToolsToGoogle(this.mcpClient.getAllTools()) : [];
		const configTools = (context?.prompt?.config)?.tools ?? this.config.tools;
		const requestTools = options.skipExecutableToolFiles ? stripExecutableToolFileReferences(configTools, context?.vars) : configTools;
		const loadedTools = requestTools ? await maybeLoadToolsFromExternalFile(requestTools, context?.vars) : [];
		const normalizedTools = normalizeTools(Array.isArray(loadedTools) ? transformTools(loadedTools, "google") : loadedTools ? [loadedTools] : []);
		return [...mcpTools, ...normalizedTools];
	}
	/**
	* Load a function from an external file.
	*
	* @param fileRef - File reference in format 'file://path/to/file:functionName'
	* @returns The loaded function
	*/
	async loadExternalFunction(fileRef) {
		const { filePath, functionName } = parseFileUrl(fileRef);
		try {
			const basePath = state.basePath || process.cwd();
			const resolvedPath = path.resolve(basePath, filePath);
			const normalizedBase = path.resolve(basePath);
			const normalizedResolved = path.resolve(resolvedPath);
			const relativePath = path.relative(normalizedBase, normalizedResolved);
			if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) throw new Error(`Path traversal detected: '${filePath}' resolves outside the base directory. Resolved path '${normalizedResolved}' is not within '${normalizedBase}'.`);
			logger.debug(`Loading function from ${resolvedPath}${functionName ? `:${functionName}` : ""}`);
			const requiredModule = await importModule(resolvedPath, functionName);
			if (typeof requiredModule === "function") return requiredModule;
			else if (requiredModule && typeof requiredModule === "object" && functionName && functionName in requiredModule) {
				const fn = requiredModule[functionName];
				if (typeof fn === "function") return fn;
			}
			throw new Error(`Function callback malformed: ${filePath} must export ${functionName ? `a named function '${functionName}'` : "a function or have a default export as a function"}`);
		} catch (error) {
			throw new Error(`Error loading function from ${filePath}: ${error.message || String(error)}`);
		}
	}
	/**
	* Execute a function callback with proper error handling.
	*
	* @param functionName - Name of the function to execute
	* @param args - JSON string of function arguments
	* @param config - Config containing function callbacks
	* @returns The function result
	*/
	async executeFunctionCallback(functionName, args, config) {
		try {
			let callback = this.loadedFunctionCallbacks[functionName];
			if (!callback) {
				const callbackRef = config.functionToolCallbacks?.[functionName];
				if (callbackRef && typeof callbackRef === "string") {
					const callbackStr = callbackRef;
					if (callbackStr.startsWith("file://")) callback = await this.loadExternalFunction(callbackStr);
					else {
						logger.warn(`[GoogleProvider] Inline function string for '${functionName}' is deprecated. Use 'file://path/to/module.js:functionName' for better security.`);
						try {
							callback = new Function("return " + callbackStr)();
							if (typeof callback !== "function") throw new Error(`Expression did not return a function`);
						} catch (err) {
							throw new Error(`Failed to parse inline function for '${functionName}': ${err}. Consider using 'file://' prefix to reference an external file.`);
						}
					}
					this.loadedFunctionCallbacks[functionName] = callback;
				} else if (typeof callbackRef === "function") {
					callback = callbackRef;
					this.loadedFunctionCallbacks[functionName] = callback;
				}
			}
			if (!callback) throw new Error(`No callback found for function '${functionName}'`);
			logger.debug(`Executing function '${functionName}' with args: ${args}`);
			return await callback(args);
		} catch (error) {
			logger.error(`Error executing function '${functionName}': ${error.message || String(error)}`);
			throw error;
		}
	}
	/**
	* Clean up resources (MCP client, etc.).
	* Should be called when the provider is no longer needed.
	*/
	async cleanup() {
		if (this.mcpClient) {
			if (this.initializationPromise != null) await this.initializationPromise;
			await this.mcpClient.cleanup();
			this.mcpClient = null;
		}
	}
	/**
	* Get the request timeout in milliseconds.
	*/
	getTimeout() {
		return this.config.timeoutMs || getRequestTimeoutMs();
	}
};
//#endregion
export { GoogleGenericProvider as t };

//# sourceMappingURL=base-D3nOpHdr.js.map