import { registerDataCollector, recordPolicyDecisionGlobal } from './data-collector.js';
import { learnAttackPatterns, attackMinConfidence } from './attack-pattern-learner.js';
import { SelfImprovement } from './self-improvement.js';
import { detectDrift } from './drift-detector.js';
import { createLearningSnapshot } from './learning-snapshot.js';
import { wouldDisableDangerousBlocking } from './learning-quorum.js';
import { ComprehensiveReporter } from './comprehensive-reporter.js';
import { PricingClient } from '../clients/pricing-client.js';
import { Logger } from '../utils/logger.js';
import { writeFileSync, mkdirSync, existsSync } from 'fs';
import { dirname } from 'path';
import { resolveAiPendingSuggestionsPath, resolveAiReportPath } from './ai-paths.js';
import { broadcastDashboardEvent } from '../utils/dashboard-events.js';
import { isAiAutoApplyEnabled, isAiLearningEnabled, isAiLearningOnCliCommands } from '../utils/ai-enabled.js';
import { getAllActiveServerNames } from '../utils/db-aggregate.js';
import { HistoryDatabase } from '../database/history-db.js';
import { getLlmConfig } from '../config/llm-config.js';
import { scorePolicyImpact } from './policy-impact-scoring.js';
import { evaluateAutopilotSafety } from './autopilot-safety-contract.js';
const DEFAULT_CONFIG = {
    autoApplyThreshold: 0.85,
    enabledModules: ['baseline', 'cost', 'threat', 'assist', 'pattern'],
    policyOutputPath: './default-policy-auto-generated.yaml',
    analysisIntervalMs: 15 * 60 * 1000, // 15 minutes
};
let suggestionCounter = 0;
export class SuggestionEngine {
    collector;
    baselineLearner;
    costOptimizer;
    threatIntel;
    policyAssist;
    patternRecognizer;
    selfImprovement;
    reporter;
    config;
    servers = [];
    analysisTimer = null;
    constructor(collector, baselineLearner, costOptimizer, threatIntel, policyAssist, patternRecognizer, selfImprovement, config) {
        this.collector = collector;
        this.baselineLearner = baselineLearner;
        this.costOptimizer = costOptimizer;
        this.threatIntel = threatIntel;
        this.policyAssist = policyAssist;
        this.patternRecognizer = patternRecognizer;
        this.selfImprovement = selfImprovement;
        this.reporter = new ComprehensiveReporter();
        this.config = { ...DEFAULT_CONFIG, ...config };
    }
    /** Set the server list for analysis context */
    setServers(servers) {
        this.servers = servers;
    }
    /**
     * Run a full analysis cycle: collect → analyze → suggest → score → filter → auto-apply → learn.
     */
    async runLearningCycle() {
        // ── 1. Collect all governance data ───────────────────
        const snapshot = await this.collector.collectAll(this.servers);
        // ── 2. Learn baselines ──────────────────────────────
        if (snapshot.callRecords.length > 0) {
            this.baselineLearner.learn(snapshot.callRecords);
        }
        // ── 3. Run all suggestion modules ───────────────────
        const allSuggestions = [];
        if (this.config.enabledModules.includes('baseline')) {
            const anomalySuggestions = this.baselineLearner.suggestRules(snapshot.callRecords);
            const preventiveSuggestions = anomalySuggestions.length === 0
                ? this.baselineLearner.suggestPreventiveRules(3)
                : [];
            for (const s of [...anomalySuggestions, ...preventiveSuggestions]) {
                allSuggestions.push(this.toUnified(s));
            }
        }
        const blockedRecords = snapshot.callRecords.filter((r) => r.blocked);
        if (blockedRecords.length > 0) {
            const attackSuggestions = learnAttackPatterns(blockedRecords);
            for (const s of attackSuggestions) {
                allSuggestions.push({
                    id: `attack-${suggestionCounter++}`,
                    rule: s.rule,
                    confidence: this.selfImprovement.adjustConfidence(s.confidence, 'attack'),
                    reason: s.reason,
                    source: 'attack',
                });
            }
        }
        if (this.config.enabledModules.includes('cost')) {
            // Use live PricingClient for per-model token prices
            const pricingClient = new PricingClient();
            // Sample the first few records to determine dominant model
            const modelCounts = new Map();
            const defaultModel = getLlmConfig().model;
            for (const r of snapshot.callRecords.slice(0, 50)) {
                const model = r.model || defaultModel;
                modelCounts.set(model, (modelCounts.get(model) || 0) + 1);
            }
            let dominantModel = defaultModel;
            let maxCount = 0;
            for (const [model, count] of modelCounts) {
                if (count > maxCount) {
                    maxCount = count;
                    dominantModel = model;
                }
            }
            const livePricing = await pricingClient.getModelPricing(dominantModel);
            const inputPrice = (livePricing?.input ?? 2.50) / 1_000_000;
            const outputPrice = (livePricing?.output ?? 10.00) / 1_000_000;
            const patterns = await this.costOptimizer.analyzePatterns(snapshot.callRecords, inputPrice, outputPrice);
            const burstMap = await this.costOptimizer.detectBurstPatterns(snapshot.callRecords);
            const costSuggestions = this.costOptimizer.suggestRules(patterns, burstMap);
            for (const s of costSuggestions) {
                allSuggestions.push({
                    id: `cost-${suggestionCounter++}`,
                    rule: s.rule,
                    confidence: s.confidence,
                    reason: s.reason,
                    source: 'cost',
                    estimatedSavings: s.estimatedSavings,
                });
            }
        }
        // Threat intel — poll live feeds, optionally LLM-enrich before rule generation
        if (this.config.enabledModules.includes('threat')) {
            try {
                await this.threatIntel.pollLiveFeeds();
            }
            catch {
                /* best-effort poll */
            }
            const catalog = this.threatIntel.getCatalogEntries({ minSeverity: 'MEDIUM', limit: 20 });
            const llmEnrich = process.env.GUARDIAN_AI_THREAT_LLM !== 'false';
            let llm = null;
            if (llmEnrich) {
                const { LlmAssistant } = await import('./llm-assistant.js');
                const assistant = new LlmAssistant();
                if (assistant.isAvailable() && (await assistant.healthCheck())) {
                    llm = assistant;
                }
            }
            for (const entry of catalog) {
                let suggestions = this.threatIntel.generateRules([entry]);
                if (llm) {
                    const analysis = await llm.analyzeThreat({
                        cveId: entry.id.replace(/^nvd-/, ''),
                        severity: entry.severity,
                        description: entry.description,
                        affectedPackage: entry.affectedPackage || 'unknown',
                    });
                    if (analysis?.suggestedPatterns?.length) {
                        suggestions = [
                            {
                                rule: {
                                    name: `threat-llm-${entry.id}`,
                                    description: `[${entry.severity}] ${analysis.impact || entry.description.slice(0, 120)}`,
                                    action: analysis.action === 'pass' ? 'flag' : 'block',
                                    patterns: analysis.suggestedPatterns.slice(0, 3),
                                },
                                confidence: entry.severity === 'CRITICAL' ? 0.9 : entry.severity === 'HIGH' ? 0.85 : 0.75,
                                reason: `LLM-enriched ${entry.severity} threat from ${entry.source}`,
                                source: 'threat',
                                entry,
                            },
                        ];
                    }
                }
                for (const s of suggestions) {
                    allSuggestions.push({
                        id: `threat-${suggestionCounter++}`,
                        rule: s.rule,
                        confidence: this.selfImprovement.adjustConfidence(s.confidence, 'threat'),
                        reason: s.reason,
                        source: 'threat',
                    });
                }
            }
        }
        // Note: policy-assist requires NL goals; call generateRule() externally
        // ── 4. Pattern recognition ──────────────────────────
        const insights = this.patternRecognizer.analyze(snapshot);
        const temporal = this.patternRecognizer.detectTemporalPatterns(snapshot);
        // Add pattern-based suggestions
        if (this.config.enabledModules.includes('pattern')) {
            for (const i of insights) {
                if (i.suggestedRule) {
                    allSuggestions.push({
                        id: `pattern-${suggestionCounter++}`,
                        rule: i.suggestedRule,
                        confidence: i.confidence,
                        reason: i.description,
                        source: 'pattern',
                    });
                }
            }
        }
        // ── 5. Drift detection (7d vs prior 7d per server:tool) ──
        const learningState = this.selfImprovement.getState();
        const driftReport = detectDrift(snapshot.callRecords, {
            labeledFpRateRecent: learningState.falsePositiveRate,
            labeledFpRatePrior: learningState.lastPrecisionProxy,
        });
        this.selfImprovement.recordDriftReport(driftReport);
        // ── 6. Adjust confidence via self-improvement ────────
        for (const s of allSuggestions) {
            s.confidence = this.selfImprovement.adjustConfidence(s.confidence, s.source);
            const impact = scorePolicyImpact({
                confidence: s.confidence,
                replayCoverage: Math.max(0.6, Math.min(1, 0.7 + (s.confidence * 0.3))),
                predictedFalsePositiveDelta: s.source === 'cost' ? 0.01 : 0.005,
                predictedBypassDelta: s.source === 'threat' || s.source === 'attack' ? 0 : 0.002,
                blastRadiusPercent: s.source === 'threat' ? 0.04 : 0.08,
                rollbackConfidence: Math.max(0.75, Math.min(0.99, 0.7 + (s.confidence * 0.3))),
            });
            const safety = evaluateAutopilotSafety({
                suggestionId: s.id,
                source: s.source,
                stage: impact.recommendation === 'promote' ? 'enforce' : 'canary',
                rule: s.rule,
                evidence: {
                    simulationPassed: impact.recommendation !== 'hold',
                    replayCoverage: Math.max(0.6, Math.min(1, 0.7 + (s.confidence * 0.3))),
                    confidence: s.confidence,
                    predictedFalsePositiveDelta: s.source === 'cost' ? 0.01 : 0.005,
                    predictedBypassDelta: s.source === 'threat' || s.source === 'attack' ? 0 : 0.002,
                    blastRadiusPercent: s.source === 'threat' ? 0.04 : 0.08,
                    rollbackConfidence: Math.max(0.75, Math.min(0.99, 0.7 + (s.confidence * 0.3))),
                    canarySizePercent: 0.05,
                },
            });
            s.autopilot = {
                safetyAllowed: safety.allowed,
                safetyBlockers: safety.blockers,
                impactOverall: impact.overall,
                recommendation: impact.recommendation,
            };
        }
        // Sort by confidence descending
        allSuggestions.sort((a, b) => b.confidence - a.confidence);
        // ── 7. Auto-apply (opt-in only) ───────────────────────
        const autoApply = [];
        if (isAiAutoApplyEnabled() && !this.selfImprovement.isThresholdAdjustmentFrozen()) {
            const threshold = this.selfImprovement.getAdaptiveThreshold() || this.config.autoApplyThreshold;
            const toApply = allSuggestions.filter((s) => {
                const minConfidence = s.source === 'attack' ? Math.max(threshold, attackMinConfidence()) : threshold;
                if (s.confidence < minConfidence)
                    return false;
                if (!s.autopilot?.safetyAllowed)
                    return false;
                if (s.autopilot?.recommendation === 'hold')
                    return false;
                const patterns = s.rule.argPatterns?.join(' ') || '';
                if (wouldDisableDangerousBlocking(s.rule.name, patterns, true)) {
                    Logger.warn(`[SuggestionEngine] Skipping auto-apply of dangerous unblock: ${s.rule.name}`);
                    return false;
                }
                return true;
            });
            if (toApply.length > 0) {
                createLearningSnapshot();
                this.autoApplyRules(toApply);
                autoApply.push(...toApply);
            }
            for (const s of autoApply) {
                this.selfImprovement.recordOutcome({
                    suggestionId: s.id,
                    ruleName: s.rule.name,
                    source: s.source,
                    action: 'applied',
                    confidence: s.confidence,
                    timestamp: new Date().toISOString(),
                });
            }
        }
        // ── 8. Prune ineffective rules ──────────────────────
        const pruneList = this.selfImprovement.suggestPruning();
        // ── 9. Generate comprehensive report ─────────────────
        const baselines = this.baselineLearner.getAllBaselines();
        this.baselineLearner.saveToFile();
        this.selfImprovement.recordCycleComplete({
            recordsAnalyzed: snapshot.callRecords.length,
            baselinesLearned: baselines.length,
            suggestionsGenerated: allSuggestions.length,
        });
        const autoRuleNames = autoApply.map(s => s.rule.name);
        const report = this.reporter.generateFullReport(snapshot, baselines, insights, temporal, autoRuleNames, this.selfImprovement.getState(), pruneList);
        Logger.info(`[SuggestionEngine] Cycle complete: ${allSuggestions.length} suggestions, ${autoApply.length} auto-applied, ${insights.length} insights`);
        this.savePendingSuggestions(allSuggestions);
        this.saveComprehensiveReport(report);
        broadcastDashboardEvent({
            type: 'ai:suggestions',
            payload: { suggestions: allSuggestions, autoApplied: autoApply.length },
            timestamp: Date.now(),
        });
        broadcastDashboardEvent({
            type: 'ai:report',
            payload: { updatedAt: report.timestamp },
            timestamp: Date.now(),
        });
        return { suggestions: allSuggestions, autoApplied: autoApply, insights, report };
    }
    saveComprehensiveReport(report) {
        try {
            const plainText = this.reporter.toPlainText(report);
            const path = resolveAiReportPath();
            const dir = dirname(path);
            if (!existsSync(dir))
                mkdirSync(dir, { recursive: true });
            writeFileSync(path, JSON.stringify({
                updatedAt: report.timestamp,
                plainText,
                report,
            }, null, 2));
            writeFileSync(path.replace(/\.json$/, '.txt'), plainText);
        }
        catch (err) {
            Logger.debug(`[SuggestionEngine] Failed to save report: ${err instanceof Error ? err.message : String(err)}`);
        }
    }
    /** Persist latest suggestions for TUI/dashboard (not yet accepted/rejected). */
    savePendingSuggestions(suggestions) {
        try {
            const path = resolveAiPendingSuggestionsPath();
            const dir = dirname(path);
            if (!existsSync(dir))
                mkdirSync(dir, { recursive: true });
            writeFileSync(path, JSON.stringify({
                updatedAt: new Date().toISOString(),
                suggestions: suggestions.map((s) => ({
                    id: s.id,
                    ruleName: s.rule.name,
                    rule: s.rule,
                    confidence: s.confidence,
                    reason: s.reason,
                    source: s.source,
                    estimatedSavings: s.estimatedSavings,
                    autopilot: s.autopilot,
                })),
            }, null, 2));
            void import('../utils/metrics.js').then(({ setSuggestionQueueDepth }) => {
                setSuggestionQueueDepth(suggestions.length);
            });
        }
        catch (err) {
            Logger.debug(`[SuggestionEngine] Failed to save pending suggestions: ${err instanceof Error ? err.message : String(err)}`);
        }
    }
    /** Record user accept/reject from TUI or dashboard API. */
    recordUserOutcome(suggestionId, action, meta) {
        this.selfImprovement.recordOutcome({
            suggestionId,
            ruleName: meta.ruleName,
            source: meta.source,
            action,
            confidence: meta.confidence,
            timestamp: new Date().toISOString(),
        }, { userId: meta.userId, pattern: meta.pattern });
        broadcastDashboardEvent({
            type: 'ai:state',
            payload: { state: this.selfImprovement.getState() },
            timestamp: Date.now(),
        });
    }
    /** Generate a comprehensive report (alias for convenience) */
    async generateReport() {
        const { report } = await this.runLearningCycle();
        return report;
    }
    /** Start periodic analysis */
    startPeriodicAnalysis() {
        if (this.analysisTimer)
            return;
        Logger.info(`[SuggestionEngine] Starting periodic analysis every ${this.config.analysisIntervalMs / 1000}s`);
        this.analysisTimer = setInterval(() => {
            this.runLearningCycle().catch(err => {
                Logger.error(`[SuggestionEngine] Periodic analysis failed: ${err?.message}`);
            });
        }, this.config.analysisIntervalMs);
    }
    /** Stop periodic analysis */
    stopPeriodicAnalysis() {
        if (this.analysisTimer) {
            clearInterval(this.analysisTimer);
            this.analysisTimer = null;
        }
    }
    /** Get the underlying self-improvement engine for direct access */
    getSelfImprovement() {
        return this.selfImprovement;
    }
    /** Get the baseline learner for direct access */
    getBaselineLearner() {
        return this.baselineLearner;
    }
    /** Get the data collector for direct access */
    getDataCollector() {
        return this.collector;
    }
    /** Get the policy assist for NL → YAML generation */
    getPolicyAssist() {
        return this.policyAssist;
    }
    /** Get the threat intel for feed processing */
    getThreatIntel() {
        return this.threatIntel;
    }
    /** Process a threat feed through the full pipeline */
    processThreatFeed(feedPath) {
        const threatSuggestions = this.threatIntel.processFeed(feedPath);
        return threatSuggestions.map(s => ({
            id: `threat-${suggestionCounter++}`,
            rule: s.rule,
            confidence: this.selfImprovement.adjustConfidence(s.confidence, 'threat'),
            reason: s.reason,
            source: 'threat',
        }));
    }
    /** Process an NL goal through the pipeline */
    processPolicyGoal(goal, availableTools) {
        const assistSuggestion = this.policyAssist.generateRule(goal, availableTools);
        if (!assistSuggestion)
            return null;
        return {
            id: `assist-${suggestionCounter++}`,
            rule: assistSuggestion.rule,
            confidence: this.selfImprovement.adjustConfidence(assistSuggestion.confidence, 'assist'),
            reason: assistSuggestion.reason,
            source: 'assist',
        };
    }
    /** Auto-apply suggestions by writing to policy YAML */
    autoApplyRules(suggestions) {
        try {
            const rulesYAML = suggestions
                .map(s => {
                const lines = [];
                lines.push(`  - name: ${s.rule.name}`);
                if (s.rule.description)
                    lines.push(`    description: "${s.rule.description}"`);
                lines.push(`    action: ${s.rule.action}`);
                if (s.rule.maxTokens)
                    lines.push(`    maxTokens: ${s.rule.maxTokens}`);
                if (s.rule.maxCallsPerMinute)
                    lines.push(`    maxCallsPerMinute: ${s.rule.maxCallsPerMinute}`);
                if (s.rule.tools?.deny?.length || s.rule.tools?.allow?.length) {
                    const toolLines = ['    tools:'];
                    if (s.rule.tools?.deny?.length)
                        toolLines.push(`      deny: [${s.rule.tools.deny.join(', ')}]`);
                    if (s.rule.tools?.allow?.length)
                        toolLines.push(`      allow: [${s.rule.tools.allow.join(', ')}]`);
                    lines.push(toolLines.join('\n'));
                }
                return lines.join('\n');
            })
                .join('\n');
            const yaml = `# Auto-generated by MCP Guardian AI Suggestion Engine\n# Generated: ${new Date().toISOString()}\n# Auto-apply threshold: ${this.selfImprovement.getAdaptiveThreshold()}\n\nrules:\n${rulesYAML}\n`;
            writeFileSync(this.config.policyOutputPath, yaml);
            Logger.info(`[SuggestionEngine] Auto-applied ${suggestions.length} rules → ${this.config.policyOutputPath}`);
        }
        catch (err) {
            Logger.error(`[SuggestionEngine] Failed to auto-apply rules: ${err?.message}`);
        }
    }
    toUnified(s) {
        return {
            id: `baseline-${suggestionCounter++}`,
            rule: s.rule,
            confidence: this.selfImprovement.adjustConfidence(s.confidence, 'baseline'),
            reason: s.reason,
            source: 'baseline',
        };
    }
}
/** Global engine instance initialized during proxy startup */
let globalEngine = null;
/** Get the running AI engine instance */
export function getAiEngine() {
    return globalEngine;
}
/** Initialize and start the AI engine with live data */
export async function initializeAiEngine(historyDb, servers) {
    const { HistoryDatabase } = await import('../database/history-db.js');
    const { DataCollector } = await import('./data-collector.js');
    const { BaselineLearner } = await import('./baseline-learner.js');
    const { CostOptimizer } = await import('./cost-optimizer.js');
    const { getSharedThreatIntel, startThreatIntelPollingIfEnabled } = await import('./threat-intel.js');
    const { PolicyAssist } = await import('./policy-assist.js');
    const { PatternRecognizer } = await import('./pattern-recognizer.js');
    const { SelfImprovement } = await import('./self-improvement.js');
    const { CostAuditor } = await import('../services/cost-auditor.js');
    const { PricingClient } = await import('../clients/pricing-client.js');
    const pricingClient = new PricingClient();
    const costAuditor = new CostAuditor(pricingClient, historyDb);
    const useDbSnapshots = process.env.GUARDIAN_AI_USE_DB_SNAPSHOTS !== 'false'
        || process.env.GUARDIAN_AI_SKIP_EXTERNAL_FETCH === 'true';
    let collector;
    if (useDbSnapshots) {
        collector = new DataCollector(historyDb, undefined, costAuditor, undefined, pricingClient);
    }
    else {
        const { SecurityScanner } = await import('../services/security-scanner.js');
        const { HealthMonitor } = await import('../services/health-monitor.js');
        collector = new DataCollector(historyDb, new SecurityScanner(), costAuditor, new HealthMonitor(historyDb), pricingClient);
    }
    const baselineLearner = new BaselineLearner();
    baselineLearner.loadFromFile();
    const costOptimizer = new CostOptimizer(historyDb, costAuditor);
    const threatIntel = getSharedThreatIntel();
    const policyAssist = new PolicyAssist();
    const patternRecognizer = new PatternRecognizer();
    const { resolveAiLearningStatePath } = await import('./self-improvement.js');
    const selfImprovement = new SelfImprovement(resolveAiLearningStatePath());
    const engineConfig = {
        analysisIntervalMs: parseInt(process.env.GUARDIAN_AI_ANALYSIS_INTERVAL_MS || String(15 * 60 * 1000), 10),
        autoApplyThreshold: parseFloat(process.env.GUARDIAN_AI_AUTO_APPLY_THRESHOLD || '0.85'),
        policyOutputPath: process.env.GUARDIAN_AI_POLICY_OUTPUT || './default-policy-auto-generated.yaml',
    };
    const engine = new SuggestionEngine(collector, baselineLearner, costOptimizer, threatIntel, policyAssist, patternRecognizer, selfImprovement, engineConfig);
    registerDataCollector(collector);
    engine.setServers(servers);
    if (process.env.GUARDIAN_AI_DISABLE_PERIODIC !== 'true') {
        engine.startPeriodicAnalysis();
    }
    startThreatIntelPollingIfEnabled();
    globalEngine = engine;
    Logger.info('[SuggestionEngine] AI Engine initialized with live data sources');
    if (process.env.GUARDIAN_AI_SKIP_INITIAL_CYCLE !== 'true') {
        engine.runLearningCycle().catch(err => {
            Logger.warn(`[SuggestionEngine] Initial learning cycle failed: ${err?.message}`);
        });
    }
    return engine;
}
/** Build minimal server configs from DB server names. */
export function serversFromNames(names) {
    return names.map((name) => ({ name, transport: 'stdio' }));
}
/** Run learning cycle against the history database (proxy, TUI, scan hooks). */
export async function runLearningCycleForDb(historyDb, servers) {
    if (!isAiLearningEnabled())
        return null;
    const db = historyDb || new HistoryDatabase();
    const names = servers?.map((s) => s.name) ?? await getAllActiveServerNames(db);
    if (names.length === 0) {
        Logger.warn('[SuggestionEngine] No servers in DB — skipping learning cycle');
        return null;
    }
    const resolvedServers = servers?.length ? servers : serversFromNames(names);
    let engine = globalEngine;
    if (!engine) {
        engine = await initializeAiEngine(db, resolvedServers);
    }
    else {
        engine.setServers(resolvedServers);
    }
    return engine.runLearningCycle();
}
/** Run one learning cycle when AI learning is enabled (scan/audit/report hooks). */
export async function triggerLearningCycleIfEnabled(historyDb, servers = [], opts) {
    if (!isAiLearningEnabled())
        return;
    if (opts?.cliCommand && !isAiLearningOnCliCommands())
        return;
    await runLearningCycleForDb(historyDb, servers);
}
export { recordPolicyDecisionGlobal };
/** Roll back AI learning state to the latest snapshot (CLI / dashboard API). */
export function rollbackAiLearning() {
    if (globalEngine) {
        return globalEngine.getSelfImprovement().rollback();
    }
    return new SelfImprovement().rollback();
}
export async function recordSuggestionOutcome(suggestionId, action, meta) {
    const patterns = meta.pattern || meta.rule?.argPatterns?.join(' ');
    if (action === 'applied' && meta.rule) {
        const { applySuggestionToPolicy } = await import('./policy-applier.js');
        await applySuggestionToPolicy(meta.rule, meta.policyPath, meta.policyWatcher ?? null);
    }
    if (globalEngine) {
        globalEngine.recordUserOutcome(suggestionId, action, {
            ruleName: meta.ruleName,
            source: meta.source,
            confidence: meta.confidence,
            userId: meta.userId,
            pattern: patterns,
        });
        return;
    }
    const { SelfImprovement } = await import('./self-improvement.js');
    new SelfImprovement().recordOutcome({
        suggestionId,
        ruleName: meta.ruleName,
        source: meta.source,
        action,
        confidence: meta.confidence,
        timestamp: new Date().toISOString(),
    }, { userId: meta.userId, pattern: patterns });
}
//# sourceMappingURL=suggestion-engine.js.map