"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Shield = void 0;
const pii_detector_1 = require("./detectors/pii-detector");
const injection_detector_1 = require("./detectors/injection-detector");
const hallucination_detector_1 = require("./detectors/hallucination-detector");
const DEFAULT_CONFIG = {
    enabled: true,
    mode: 'enforce',
    pii: {
        enabled: true,
        maskFormat: '[REDACTED:{type}]'
    },
    injection: {
        enabled: true,
        action: 'block'
    },
    hallucination: {
        enabled: true,
        action: 'rewrite'
    },
    rewrite: {
        enabled: true,
        model: 'gpt-3.5-turbo'
    }
};
class Shield {
    constructor(config) {
        this.config = { ...DEFAULT_CONFIG, ...config };
        this.piiDetector = new pii_detector_1.PIIDetector({
            enabled: this.config.pii.enabled,
            maskFormat: this.config.pii.maskFormat
        });
        this.injectionDetector = new injection_detector_1.InjectionDetector({
            enabled: this.config.injection.enabled,
            action: this.config.injection.action
        });
        this.hallucinationDetector = new hallucination_detector_1.HallucinationDetector({
            enabled: this.config.hallucination.enabled
        });
    }
    static getInstance(config) {
        if (!Shield.instance) {
            Shield.instance = new Shield(config);
        }
        return Shield.instance;
    }
    checkInput(input) {
        if (!this.config.enabled || this.config.mode === 'off') {
            return {
                action: 'allow',
                reason: 'Shield disabled',
                details: {}
            };
        }
        const details = {};
        if (this.config.injection.enabled) {
            const injectionCheck = this.injectionDetector.detect(input);
            if (injectionCheck) {
                details.injection = injectionCheck;
                if (injectionCheck.action === 'block') {
                    return {
                        action: 'block',
                        reason: `Prompt injection detected: ${injectionCheck.patterns.join(', ')}`,
                        details,
                        originalOutput: input
                    };
                }
                if (injectionCheck.action === 'mask' && injectionCheck.sanitizedInput) {
                    return {
                        action: 'mask',
                        reason: `Prompt injection detected and sanitized`,
                        details,
                        sanitizedOutput: injectionCheck.sanitizedInput,
                        originalOutput: input
                    };
                }
                if (injectionCheck.action === 'require_approval') {
                    return {
                        action: 'block',
                        reason: `Prompt injection detected - requires approval`,
                        details,
                        originalOutput: input
                    };
                }
                if (this.config.mode === 'monitor') {
                    return {
                        action: 'flag',
                        reason: `Prompt injection detected (monitoring mode)`,
                        details,
                        originalOutput: input
                    };
                }
            }
        }
        if (this.config.pii.enabled && this.config.mode === 'monitor') {
            const piiCheck = this.piiDetector.detect(input);
            if (piiCheck) {
                details.pii = piiCheck;
            }
        }
        return {
            action: 'allow',
            reason: 'Input passed all checks',
            details
        };
    }
    checkOutput(input, output) {
        if (!this.config.enabled || this.config.mode === 'off') {
            return {
                action: 'allow',
                reason: 'Shield disabled',
                details: {}
            };
        }
        const details = {};
        let finalAction = 'allow';
        let reasons = [];
        if (this.config.pii.enabled) {
            const piiCheck = this.piiDetector.detectAndMask(output);
            if (piiCheck) {
                details.pii = piiCheck;
                if (this.config.mode === 'enforce') {
                    finalAction = 'mask';
                    reasons.push('PII detected');
                }
                else {
                    finalAction = 'flag';
                    reasons.push('PII detected (monitoring)');
                }
            }
        }
        if (this.config.hallucination.enabled) {
            const hallucinationCheck = this.hallucinationDetector.detect(input, output);
            if (hallucinationCheck) {
                details.hallucination = hallucinationCheck;
                if (this.config.hallucination.action === 'block' && hallucinationCheck.severity === 'high') {
                    finalAction = 'block';
                    reasons.push('High severity hallucination detected');
                }
                else if (this.config.hallucination.action === 'rewrite' && this.config.mode === 'enforce') {
                    finalAction = 'rewrite';
                    reasons.push('Hallucination detected - requires rewrite');
                }
                else if (this.config.mode === 'monitor') {
                    finalAction = finalAction === 'allow' ? 'flag' : finalAction;
                    reasons.push('Hallucination detected (monitoring)');
                }
            }
        }
        let sanitizedOutput = output;
        if (details.pii?.maskedText) {
            if (typeof output === 'string') {
                sanitizedOutput = details.pii.maskedText;
            }
            else if (typeof output === 'object' && output !== null) {
                sanitizedOutput = { ...output };
                if (output.text) {
                    sanitizedOutput.text = details.pii.maskedText;
                }
                else if (output.content) {
                    sanitizedOutput.content = details.pii.maskedText;
                }
                else if (output.message) {
                    sanitizedOutput.message = details.pii.maskedText;
                }
                else {
                    sanitizedOutput = details.pii.maskedText;
                }
            }
            else {
                sanitizedOutput = details.pii.maskedText;
            }
        }
        return {
            action: finalAction,
            reason: reasons.length > 0 ? reasons.join('; ') : 'Output passed all checks',
            details,
            sanitizedOutput: finalAction === 'mask' ? sanitizedOutput : undefined,
            originalOutput: output
        };
    }
    getConfig() {
        return { ...this.config };
    }
    updateConfig(config) {
        this.config = { ...this.config, ...config };
        if (config.pii) {
            this.piiDetector.updateConfig({
                enabled: config.pii.enabled,
                maskFormat: config.pii.maskFormat
            });
        }
        if (config.injection) {
            this.injectionDetector.updateConfig({
                enabled: config.injection.enabled,
                action: config.injection.action
            });
        }
        if (config.hallucination) {
            this.hallucinationDetector.updateConfig({
                enabled: config.hallucination.enabled
            });
        }
    }
    isEnabled() {
        return this.config.enabled && this.config.mode !== 'off';
    }
    getHealth() {
        return {
            enabled: this.config.enabled,
            mode: this.config.mode,
            detectors: {
                pii: this.config.pii.enabled,
                injection: this.config.injection.enabled,
                hallucination: this.config.hallucination.enabled
            }
        };
    }
    async attemptRewrite(originalOutput, hallucinationDetails, input) {
        if (!this.config.rewrite?.enabled) {
            return {
                success: false,
                error: 'Rewrite feature is disabled'
            };
        }
        try {
            const outputText = typeof originalOutput === 'string'
                ? originalOutput
                : (originalOutput?.text || originalOutput?.content || originalOutput?.message || JSON.stringify(originalOutput));
            const apiKey = this.config.rewrite.apiKey || process.env['OPENAI_API_KEY'];
            if (!apiKey) {
                return {
                    success: false,
                    error: 'OpenAI API key not configured'
                };
            }
            const model = this.config.rewrite.model || 'gpt-3.5-turbo';
            const issues = hallucinationDetails.patterns?.join(', ') || 'potential inaccuracies';
            const rewritePrompt = `The following AI response has been flagged for potential issues (${hallucinationDetails.severity} severity): ${issues}

Original response:
${outputText}

Please rewrite this response to:
1. Remove any uncertainty or contradictory statements
2. Make it more accurate and grounded
3. Maintain the same intent and helpfulness
4. Keep it concise

Rewritten response:`;
            const response = await fetch('https://api.openai.com/v1/chat/completions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${apiKey}`
                },
                body: JSON.stringify({
                    model,
                    messages: [
                        {
                            role: 'system',
                            content: 'You are a helpful assistant that rewrites AI responses to be more accurate and grounded.'
                        },
                        {
                            role: 'user',
                            content: rewritePrompt
                        }
                    ],
                    temperature: 0.3,
                    max_tokens: 1000
                })
            });
            if (!response.ok) {
                const errorText = await response.text();
                return {
                    success: false,
                    error: `OpenAI API error: ${response.status} - ${errorText}`
                };
            }
            const data = await response.json();
            const rewrittenText = data.choices?.[0]?.message?.content;
            if (!rewrittenText) {
                return {
                    success: false,
                    error: 'No rewritten content returned from OpenAI'
                };
            }
            let rewrittenOutput = rewrittenText;
            if (typeof originalOutput === 'object' && originalOutput !== null) {
                rewrittenOutput = { ...originalOutput };
                if (originalOutput.text) {
                    rewrittenOutput.text = rewrittenText;
                }
                else if (originalOutput.content) {
                    rewrittenOutput.content = rewrittenText;
                }
                else if (originalOutput.message) {
                    rewrittenOutput.message = rewrittenText;
                }
                else {
                    rewrittenOutput = rewrittenText;
                }
            }
            return {
                success: true,
                rewrittenOutput
            };
        }
        catch (error) {
            return {
                success: false,
                error: error.message || 'Rewrite failed'
            };
        }
    }
}
exports.Shield = Shield;
//# sourceMappingURL=shield.js.map