/**
 * GeminiAdapter -- Google Gemini platform adapter for governance enforcement.
 *
 * Maps Gemini's function_calling format (functionCall.name / functionCall.args)
 * to the unified GovernanceAdapter interface. Supports Gemini tool declarations,
 * tool_config modes, and function_calling_config.
 *
 * Pure TypeScript -- no Google SDK dependency required.
 *
 * @connexum/ai-governance
 */
import { ActionDecisionType, } from '../adapters/index.js';
/* ------------------------------------------------------------------ */
/*  GeminiAdapter                                                      */
/* ------------------------------------------------------------------ */
export class GeminiAdapter {
    name = 'gemini';
    config = null;
    blockedFunctions = new Set();
    allowedFunctions = null;
    approvalRequiredFunctions = new Set();
    toolDeclarations = new Map();
    functionCallingMode = 'AUTO';
    modeAllowedNames = null;
    auditLog = [];
    /* ---- GovernanceAdapter interface ---- */
    initialize(config) {
        this.config = config;
        this.name = config.adapterName;
        const opts = config.platformOptions ?? {};
        // Blocked functions list
        const blocked = opts['blockedFunctions'];
        if (Array.isArray(blocked)) {
            this.blockedFunctions = new Set(blocked);
        }
        // Explicit allow list (if set, only these are allowed)
        const allowed = opts['allowedFunctions'];
        if (Array.isArray(allowed)) {
            this.allowedFunctions = new Set(allowed);
        }
        // Functions requiring approval
        const approval = opts['approvalRequiredFunctions'];
        if (Array.isArray(approval)) {
            this.approvalRequiredFunctions = new Set(approval);
        }
        // Register tool declarations if provided
        const declarations = opts['toolDeclarations'];
        if (Array.isArray(declarations)) {
            for (const decl of declarations) {
                this.toolDeclarations.set(decl.name, decl);
            }
        }
        // Apply tool_config / function_calling_config
        const toolConfig = opts['toolConfig'];
        if (toolConfig?.functionCallingConfig) {
            this.applyFunctionCallingConfig(toolConfig.functionCallingConfig);
        }
    }
    preAction(context) {
        const { toolName } = context;
        // If function calling mode is NONE, deny everything
        if (this.functionCallingMode === 'NONE') {
            return this.decide(ActionDecisionType.DENY, `Function calling disabled (mode=NONE)`);
        }
        // If mode restricts to specific names, enforce that
        if (this.modeAllowedNames && !this.modeAllowedNames.has(toolName)) {
            return this.decide(ActionDecisionType.DENY, `Function "${toolName}" not in function_calling_config allowedFunctionNames`);
        }
        // Check explicit block list
        if (this.blockedFunctions.has(toolName)) {
            return this.decide(ActionDecisionType.DENY, `Function "${toolName}" is blocked by governance policy`);
        }
        // Check explicit allow list (if configured)
        if (this.allowedFunctions && !this.allowedFunctions.has(toolName)) {
            return this.decide(ActionDecisionType.DENY, `Function "${toolName}" not in governance allow list`);
        }
        // Check approval-required list
        if (this.approvalRequiredFunctions.has(toolName)) {
            return this.decide(ActionDecisionType.REQUIRE_APPROVAL, `Function "${toolName}" requires approval`);
        }
        return this.decide(ActionDecisionType.ALLOW, `Function "${toolName}" permitted`);
    }
    postAction(context, result) {
        const entry = {
            timestamp: context.timestamp,
            functionName: context.toolName,
            decision: result.success ? ActionDecisionType.ALLOW : ActionDecisionType.DENY,
            reason: result.error ?? 'completed',
            agentName: context.agent.name,
            durationMs: result.durationMs,
        };
        this.auditLog.push(entry);
    }
    getCapabilities() {
        return {
            preAction: true,
            postAction: true,
            auditLogging: true,
            circuitBreaker: false,
            approvalQueue: false,
            tamperDetection: false,
        };
    }
    /* ---- Gemini-specific methods ---- */
    /**
     * Convert a Gemini functionCall object to a unified ActionContext.
     */
    mapFunctionCallToContext(functionCall, agentName) {
        const agent = {
            name: agentName ?? this.config?.adapterName ?? 'unknown',
            role: 'gemini-agent',
        };
        return {
            toolName: functionCall.name,
            input: functionCall.args ?? {},
            agent,
            timestamp: new Date().toISOString(),
            sessionInfo: {
                platform: 'gemini',
                originalFunctionCall: functionCall,
            },
        };
    }
    /**
     * Wrap a Gemini function call with governance enforcement.
     *
     * This is the primary integration point: intercept a functionCall from
     * Gemini's response, run governance checks, and return the decision
     * alongside the normalized context.
     */
    wrapFunctionCall(functionCall, agentName) {
        const context = this.mapFunctionCallToContext(functionCall, agentName);
        const decision = this.preAction(context);
        this.auditLog.push({
            timestamp: context.timestamp,
            functionName: functionCall.name,
            decision: decision.type,
            reason: decision.reason,
            agentName: context.agent.name,
        });
        return {
            allowed: decision.type === 'ALLOW',
            decision,
            functionCall,
            context,
        };
    }
    /**
     * Register Gemini tool declarations for capability checking.
     */
    registerToolDeclarations(declarations) {
        for (const decl of declarations) {
            this.toolDeclarations.set(decl.name, decl);
        }
    }
    /**
     * Check if a function name is declared in the registered tools.
     */
    isFunctionDeclared(name) {
        return this.toolDeclarations.has(name);
    }
    /**
     * Apply a Gemini function_calling_config to governance rules.
     */
    applyFunctionCallingConfig(config) {
        this.functionCallingMode = config.mode;
        if (config.mode === 'ANY' && config.allowedFunctionNames) {
            this.modeAllowedNames = new Set(config.allowedFunctionNames);
        }
        else {
            this.modeAllowedNames = null;
        }
    }
    /**
     * Get the current function calling mode.
     */
    getFunctionCallingMode() {
        return this.functionCallingMode;
    }
    /**
     * Get the audit log.
     */
    getAuditLog() {
        return this.auditLog;
    }
    /**
     * Clear the audit log.
     */
    clearAuditLog() {
        this.auditLog = [];
    }
    /* ---- Internal helpers ---- */
    decide(type, reason) {
        return { type, reason };
    }
}
//# sourceMappingURL=gemini.js.map