"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.StrategyRegistry = void 0;
exports.createStrategyRegistry = createStrategyRegistry;
exports.createEnhancedStrategyRegistry = createEnhancedStrategyRegistry;
const scrollingStrategy_1 = require("./scrollingStrategy");
const startupStrategy_1 = require("./startupStrategy");
const interactionStrategy_1 = require("./interactionStrategy");
const sceneReconstructionStrategy_1 = require("./sceneReconstructionStrategy");
const strategySelector_1 = require("../core/strategySelector");
// =============================================================================
// Strategy Registry
// =============================================================================
/**
 * Registry that holds all available staged analysis strategies.
 *
 * Matching modes:
 * - Keyword-first: Try keyword triggers, fall back to LLM if no match
 * - LLM-only: Skip keywords, always use LLM semantic understanding
 * - Keyword-only: Only use keyword triggers (legacy mode)
 */
class StrategyRegistry {
    constructor() {
        this.strategies = [];
        this.llmSelector = null;
        this.matchMode = 'keyword_first';
    }
    /**
     * Register a new strategy. Strategies are matched in registration order,
     * so register more specific strategies before general ones.
     */
    register(strategy) {
        this.strategies.push(strategy);
    }
    /**
     * Set the LLM selector for semantic matching.
     */
    setLLMSelector(selector) {
        this.llmSelector = selector;
    }
    /**
     * Set the match mode.
     */
    setMatchMode(mode) {
        this.matchMode = mode;
    }
    /**
     * Find the first strategy whose trigger matches the given query.
     * Returns null if no strategy matches (analysis falls through to generic path).
     *
     * This is the legacy synchronous method that only uses keyword matching.
     */
    match(query) {
        for (const strategy of this.strategies) {
            if (strategy.trigger(query)) {
                return strategy;
            }
        }
        return null;
    }
    /**
     * Enhanced matching with optional LLM semantic understanding.
     *
     * @param query - User's natural language query
     * @param intent - Parsed intent (if available)
     * @param traceContext - Trace metadata (for LLM context)
     * @returns Match result with strategy and metadata
     */
    async matchEnhanced(query, intent, traceContext) {
        // Mode 1: Keyword-only (legacy)
        if (this.matchMode === 'keyword_only') {
            return this.matchKeywordOnly(query);
        }
        // Mode 2: LLM-only
        if (this.matchMode === 'llm_only') {
            if (this.llmSelector && intent && traceContext) {
                return this.matchLLMOnly(query, intent, traceContext);
            }
            // Guardrail: avoid dropping strategy selection when LLM context is incomplete.
            // Fall back to keyword matching instead of returning no strategy.
            const keywordFallback = this.match(query);
            if (keywordFallback) {
                return {
                    strategy: keywordFallback,
                    matchMethod: 'keyword',
                    confidence: 1.0,
                    shouldFallback: false,
                };
            }
            return {
                strategy: null,
                matchMethod: 'none',
                confidence: 0,
                shouldFallback: true,
                fallbackReason: 'LLM-only 模式缺少 intent/traceContext，且关键词未匹配策略',
            };
        }
        // Mode 3: Keyword-first, fall back to LLM
        // Try keyword match first
        const keywordMatch = this.match(query);
        if (keywordMatch) {
            return {
                strategy: keywordMatch,
                matchMethod: 'keyword',
                confidence: 1.0,
                shouldFallback: false,
            };
        }
        // No keyword match - try LLM if available
        if (this.llmSelector && intent && traceContext) {
            return this.matchWithLLM(query, intent, traceContext);
        }
        // No match
        return {
            strategy: null,
            matchMethod: 'none',
            confidence: 0,
            shouldFallback: true,
            fallbackReason: '没有匹配的分析策略（关键词未匹配，LLM 不可用）',
        };
    }
    /**
     * Keyword-only matching (legacy mode).
     */
    matchKeywordOnly(query) {
        const strategy = this.match(query);
        if (strategy) {
            return {
                strategy,
                matchMethod: 'keyword',
                confidence: 1.0,
                shouldFallback: false,
            };
        }
        return {
            strategy: null,
            matchMethod: 'none',
            confidence: 0,
            shouldFallback: true,
            fallbackReason: '没有匹配的分析策略',
        };
    }
    /**
     * LLM-only matching (semantic understanding).
     */
    async matchLLMOnly(query, intent, traceContext) {
        return this.matchWithLLM(query, intent, traceContext);
    }
    /**
     * Match using LLM semantic understanding.
     */
    async matchWithLLM(query, intent, traceContext) {
        if (!this.llmSelector) {
            return {
                strategy: null,
                matchMethod: 'none',
                confidence: 0,
                shouldFallback: true,
                fallbackReason: 'LLM 选择器未配置',
            };
        }
        try {
            // Convert strategies to definitions for LLM
            const definitions = this.strategies.map(strategySelector_1.strategyToDefinition);
            // Call LLM selector
            const result = await this.llmSelector.selectStrategy(query, intent, definitions, traceContext);
            return this.processLLMResult(result);
        }
        catch (error) {
            console.warn(`[StrategyRegistry] LLM matching failed: ${error.message}`);
            return {
                strategy: null,
                matchMethod: 'none',
                confidence: 0,
                shouldFallback: true,
                fallbackReason: `LLM 匹配失败: ${error.message}`,
            };
        }
    }
    /**
     * Process LLM selection result.
     */
    processLLMResult(result) {
        if (result.shouldFallback || !result.selected) {
            return {
                strategy: null,
                matchMethod: 'llm',
                confidence: result.candidates[0]?.confidence || 0,
                reasoning: result.candidates[0]?.reasoning,
                shouldFallback: true,
                fallbackReason: result.fallbackReason,
            };
        }
        // Find the strategy by ID
        const strategy = this.strategies.find(s => s.id === result.selected.strategyId);
        if (!strategy) {
            return {
                strategy: null,
                matchMethod: 'llm',
                confidence: result.selected.confidence,
                reasoning: result.selected.reasoning,
                shouldFallback: true,
                fallbackReason: `策略 ${result.selected.strategyId} 未在注册表中找到`,
            };
        }
        return {
            strategy,
            matchMethod: 'llm',
            confidence: result.selected.confidence,
            reasoning: result.selected.reasoning,
            shouldFallback: false,
        };
    }
    /**
     * Get strategy definitions for LLM prompt context.
     */
    getDefinitions() {
        return this.strategies.map(strategySelector_1.strategyToDefinition);
    }
    /** Get all registered strategies (for debugging/introspection) */
    getAll() {
        return [...this.strategies];
    }
    /** Get strategy by ID */
    getById(id) {
        return this.strategies.find(s => s.id === id);
    }
}
exports.StrategyRegistry = StrategyRegistry;
// =============================================================================
// Factory Functions
// =============================================================================
/**
 * Create a pre-configured strategy registry with all built-in strategies.
 */
function createStrategyRegistry() {
    const registry = new StrategyRegistry();
    // Register strategies in order of specificity (more specific first)
    registry.register(scrollingStrategy_1.scrollingStrategy);
    registry.register(startupStrategy_1.startupStrategy);
    registry.register(interactionStrategy_1.interactionStrategy);
    registry.register(sceneReconstructionStrategy_1.sceneReconstructionQuickStrategy);
    // Scene reconstruction is a catch-all for overview queries
    registry.register(sceneReconstructionStrategy_1.sceneReconstructionStrategy);
    return registry;
}
/**
 * Create a strategy registry with LLM semantic matching enabled.
 *
 * @param modelRouter - Model router for LLM calls
 * @param matchMode - Matching mode (default: keyword_first)
 */
function createEnhancedStrategyRegistry(modelRouter, matchMode = 'keyword_first') {
    const registry = createStrategyRegistry();
    // Set up LLM selector
    const llmSelector = (0, strategySelector_1.createLLMStrategySelector)(modelRouter);
    registry.setLLMSelector(llmSelector);
    registry.setMatchMode(matchMode);
    return registry;
}
//# sourceMappingURL=registry.js.map