"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DialogueSession = exports.DEFAULT_DIALOGUE_CONFIG = void 0;
exports.createQueryId = createQueryId;
exports.createHypothesisId = createHypothesisId;
exports.buildModuleQuery = buildModuleQuery;
/**
 * Dialogue Protocol
 *
 * Manages the conversation flow between cross-domain experts and module experts.
 * Handles:
 * - Dialogue session lifecycle
 * - Context management across turns
 * - Query/response history tracking
 * - Turn limits and termination conditions
 */
const uuid_1 = require("../../../utils/uuid");
/**
 * Default dialogue configuration
 */
exports.DEFAULT_DIALOGUE_CONFIG = {
    maxTurns: 8,
    confidenceThreshold: 0.85,
    allowUserIntervention: true,
    maxHypotheses: 5,
    turnTimeoutMs: 30000,
};
/**
 * DialogueSession - Manages a single dialogue between expert and modules
 */
class DialogueSession {
    constructor(expertId, traceId, originalQuery, config = {}, options) {
        this.state = 'initialized';
        this.eventHandlers = [];
        this.sessionId = (0, uuid_1.uuidv4)();
        this.expertId = expertId;
        this.config = { ...exports.DEFAULT_DIALOGUE_CONFIG, ...config };
        // Initialize context
        this.context = {
            sessionId: this.sessionId,
            traceId,
            turnNumber: 0,
            architecture: options?.architecture,
            packageName: options?.packageName,
            originalQuery,
            queryHistory: [],
            responseHistory: [],
            collectedFindings: [],
            activeHypotheses: [],
            variables: {},
            traceProcessorService: options?.traceProcessorService,
        };
        // Initialize stats
        this.stats = {
            totalTurns: 0,
            totalQueries: 0,
            totalFindings: 0,
            modulesQueried: new Set(),
            hypothesesExplored: 0,
            totalExecutionTimeMs: 0,
            startTime: Date.now(),
        };
    }
    // ===========================================================================
    // State Management
    // ===========================================================================
    /**
     * Get current dialogue state
     */
    getState() {
        return this.state;
    }
    /**
     * Get current context
     */
    getContext() {
        return { ...this.context };
    }
    /**
     * Get dialogue statistics
     */
    getStats() {
        return { ...this.stats, modulesQueried: new Set(this.stats.modulesQueried) };
    }
    /**
     * Check if dialogue can continue
     */
    canContinue() {
        return (this.state === 'initialized' ||
            this.state === 'running') && this.context.turnNumber < this.config.maxTurns;
    }
    /**
     * Check if max turns reached
     */
    isMaxTurnsReached() {
        return this.context.turnNumber >= this.config.maxTurns;
    }
    // ===========================================================================
    // Turn Management
    // ===========================================================================
    /**
     * Start a new dialogue turn
     */
    startTurn() {
        if (!this.canContinue()) {
            throw new Error(`Cannot start turn: state=${this.state}, turn=${this.context.turnNumber}`);
        }
        this.context.turnNumber++;
        this.stats.totalTurns++;
        this.state = 'running';
        this.emitEvent('turn_started', {
            turnNumber: this.context.turnNumber,
            maxTurns: this.config.maxTurns,
        });
        return this.context.turnNumber;
    }
    /**
     * Record a query sent to a module
     */
    recordQuery(query) {
        // Add context to query if not present
        if (!query.context) {
            query.context = this.context;
        }
        this.context.queryHistory.push(query);
        this.stats.totalQueries++;
        this.stats.modulesQueried.add(query.targetModule);
        this.emitEvent('module_queried', {
            queryId: query.queryId,
            targetModule: query.targetModule,
            questionId: query.questionId,
            turnNumber: this.context.turnNumber,
        });
    }
    /**
     * Record a response from a module
     */
    recordResponse(response) {
        this.context.responseHistory.push(response);
        this.stats.totalExecutionTimeMs += response.executionTimeMs;
        // Collect findings
        if (response.findings.length > 0) {
            this.context.collectedFindings.push(...response.findings);
            this.stats.totalFindings += response.findings.length;
            for (const finding of response.findings) {
                this.emitEvent('finding_discovered', {
                    findingId: finding.id,
                    severity: finding.severity,
                    title: finding.title,
                    sourceModule: finding.sourceModule,
                    confidence: finding.confidence,
                });
            }
        }
        this.emitEvent('module_responded', {
            queryId: response.queryId,
            success: response.success,
            findingsCount: response.findings.length,
            suggestionsCount: response.suggestions.length,
            confidence: response.confidence,
        });
    }
    // ===========================================================================
    // Hypothesis Management
    // ===========================================================================
    /**
     * Add a new hypothesis
     */
    addHypothesis(hypothesis) {
        // Check max hypotheses limit
        if (this.context.activeHypotheses.length >= this.config.maxHypotheses) {
            // Remove lowest confidence hypothesis
            this.context.activeHypotheses.sort((a, b) => b.confidence - a.confidence);
            this.context.activeHypotheses.pop();
        }
        this.context.activeHypotheses.push(hypothesis);
        this.stats.hypothesesExplored++;
        this.emitEvent('hypothesis_created', {
            hypothesisId: hypothesis.id,
            title: hypothesis.title,
            category: hypothesis.category,
            component: hypothesis.component,
            confidence: hypothesis.confidence,
        });
    }
    /**
     * Update an existing hypothesis
     */
    updateHypothesis(hypothesisId, updates) {
        const index = this.context.activeHypotheses.findIndex(h => h.id === hypothesisId);
        if (index === -1)
            return null;
        const hypothesis = this.context.activeHypotheses[index];
        const updated = {
            ...hypothesis,
            ...updates,
            updatedAt: Date.now(),
        };
        this.context.activeHypotheses[index] = updated;
        this.emitEvent('hypothesis_updated', {
            hypothesisId: updated.id,
            status: updated.status,
            confidence: updated.confidence,
            supportingCount: updated.supportingEvidence.length,
            contradictingCount: updated.contradictingEvidence.length,
        });
        return updated;
    }
    /**
     * Get the highest confidence hypothesis
     */
    getTopHypothesis() {
        if (this.context.activeHypotheses.length === 0)
            return null;
        return this.context.activeHypotheses
            .filter(h => h.status !== 'rejected')
            .sort((a, b) => b.confidence - a.confidence)[0] || null;
    }
    /**
     * Check if any hypothesis meets confidence threshold
     */
    hasConfidentHypothesis() {
        return this.context.activeHypotheses.some(h => h.status !== 'rejected' && h.confidence >= this.config.confidenceThreshold);
    }
    // ===========================================================================
    // Variable Management
    // ===========================================================================
    /**
     * Set a variable for use in subsequent queries
     */
    setVariable(key, value) {
        this.context.variables[key] = value;
    }
    /**
     * Get a variable
     */
    getVariable(key) {
        return this.context.variables[key];
    }
    /**
     * Get all variables
     */
    getVariables() {
        return { ...this.context.variables };
    }
    // ===========================================================================
    // Decision Recording
    // ===========================================================================
    /**
     * Record a decision made by the expert
     */
    recordDecision(decision) {
        this.emitEvent('decision_made', {
            action: decision.action,
            reasoning: decision.reasoning,
            hasConclusion: !!decision.conclusion,
            hasForkRequest: !!decision.forkRequest,
            hasUserQuestion: !!decision.userQuestion,
            nextQueriesCount: decision.nextQueries?.length || 0,
        });
        // Update state based on decision
        switch (decision.action) {
            case 'conclude':
                this.state = 'concluded';
                this.stats.endTime = Date.now();
                break;
            case 'ask_user':
                if (this.config.allowUserIntervention) {
                    this.state = 'waiting_user';
                }
                break;
            // 'continue' and 'fork' keep state as 'running'
        }
    }
    /**
     * Resume after user response
     */
    resumeWithUserResponse(response) {
        if (this.state !== 'waiting_user') {
            throw new Error(`Cannot resume: state is ${this.state}, expected 'waiting_user'`);
        }
        this.context.variables['user_response'] = response;
        this.state = 'running';
    }
    // ===========================================================================
    // Termination
    // ===========================================================================
    /**
     * Conclude the dialogue
     */
    conclude() {
        this.state = 'concluded';
        this.stats.endTime = Date.now();
        this.emitEvent('dialogue_completed', {
            state: 'concluded',
            totalTurns: this.stats.totalTurns,
            totalFindings: this.stats.totalFindings,
            totalExecutionTimeMs: this.stats.totalExecutionTimeMs,
        });
    }
    /**
     * Mark as timed out
     */
    timeout() {
        this.state = 'timeout';
        this.stats.endTime = Date.now();
        this.emitEvent('dialogue_completed', {
            state: 'timeout',
            turnNumber: this.context.turnNumber,
        });
    }
    /**
     * Mark as error
     */
    error(message) {
        this.state = 'error';
        this.stats.endTime = Date.now();
        this.emitEvent('error', {
            message,
            turnNumber: this.context.turnNumber,
        });
    }
    // ===========================================================================
    // Event Handling
    // ===========================================================================
    /**
     * Register an event handler
     */
    onEvent(handler) {
        this.eventHandlers.push(handler);
    }
    /**
     * Remove an event handler
     */
    offEvent(handler) {
        const index = this.eventHandlers.indexOf(handler);
        if (index !== -1) {
            this.eventHandlers.splice(index, 1);
        }
    }
    /**
     * Emit an event
     */
    emitEvent(type, data) {
        const event = {
            type,
            timestamp: Date.now(),
            expertId: this.expertId,
            turnNumber: this.context.turnNumber,
            data,
        };
        for (const handler of this.eventHandlers) {
            try {
                handler(event);
            }
            catch (e) {
                console.error('[DialogueSession] Event handler error:', e);
            }
        }
    }
}
exports.DialogueSession = DialogueSession;
/**
 * Create a unique query ID
 */
function createQueryId(moduleTarget, turnNumber) {
    return `${moduleTarget}_t${turnNumber}_${Date.now()}`;
}
/**
 * Create a unique hypothesis ID
 */
function createHypothesisId(category, component) {
    return `hyp_${category}_${component}_${Date.now()}`;
}
/**
 * Build a ModuleQuery from parameters
 */
function buildModuleQuery(targetModule, questionId, params, context) {
    return {
        queryId: createQueryId(targetModule, context.turnNumber),
        targetModule,
        questionId,
        params,
        context,
    };
}
//# sourceMappingURL=dialogueProtocol.js.map