"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.router = exports.IntentRouter = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
class IntentRouter {
    data;
    userPreferences;
    constructor() {
        this.data = this.loadKeywords();
        this.userPreferences = this.loadUserPreferences();
    }
    loadKeywords() {
        const keywordsPath = path.join(__dirname, 'keywords.json');
        const rawData = fs.readFileSync(keywordsPath, 'utf-8');
        return JSON.parse(rawData);
    }
    loadUserPreferences() {
        const configPath = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.opencode', 'user-preferences.json');
        if (fs.existsSync(configPath)) {
            const rawData = fs.readFileSync(configPath, 'utf-8');
            return JSON.parse(rawData);
        }
        return {};
    }
    saveUserPreferences() {
        const configDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.opencode');
        const configPath = path.join(configDir, 'user-preferences.json');
        if (!fs.existsSync(configDir)) {
            fs.mkdirSync(configDir, { recursive: true });
        }
        fs.writeFileSync(configPath, JSON.stringify(this.userPreferences, null, 2));
    }
    /**
     * Main routing function
     */
    route(prompt) {
        const normalizedPrompt = prompt.toLowerCase().trim();
        // Check for direct agent mention
        const directAgent = this.extractDirectAgent(normalizedPrompt);
        if (directAgent) {
            return {
                primaryAgent: directAgent,
                confidence: 100,
                reasoning: ['Direct agent mention detected'],
                needsClarification: false
            };
        }
        // Calculate confidence scores for all agents
        const scores = this.calculateScores(normalizedPrompt);
        // Get top matches
        const sortedScores = Object.entries(scores)
            .sort(([, a], [, b]) => b - a)
            .filter(([, score]) => score > 0);
        if (sortedScores.length === 0) {
            return {
                primaryAgent: '@orchestrator',
                confidence: 0,
                reasoning: ['No clear intent detected'],
                needsClarification: true,
                clarificationQuestions: this.generateClarificationQuestions(normalizedPrompt)
            };
        }
        const [primaryAgent, primaryScore] = sortedScores[0];
        const [secondaryAgent, secondaryScore] = sortedScores[1] || [undefined, 0];
        // Check for workflow triggers
        const workflow = this.detectWorkflow(normalizedPrompt);
        // Determine if clarification is needed
        const needsClarification = primaryScore < 70 || this.isVaguePrompt(normalizedPrompt);
        return {
            primaryAgent,
            confidence: primaryScore,
            reasoning: this.generateReasoning(primaryAgent, primaryScore, normalizedPrompt),
            secondaryAgent: secondaryScore > 50 ? secondaryAgent : undefined,
            workflow,
            needsClarification,
            clarificationQuestions: needsClarification ? this.generateClarificationQuestions(normalizedPrompt, primaryAgent) : undefined
        };
    }
    /**
     * Extract direct agent mention from prompt
     */
    extractDirectAgent(prompt) {
        const agentMention = prompt.match(/@([\w-]+)/);
        if (agentMention) {
            const agentName = `@${agentMention[1]}`;
            // Verify agent exists
            const agentExists = Object.keys(this.data.agents).some(key => key.toLowerCase() === agentName.toLowerCase());
            return agentExists ? agentName : null;
        }
        return null;
    }
    /**
     * Calculate confidence scores for all agents
     */
    calculateScores(prompt) {
        const scores = {};
        for (const [agentName, config] of Object.entries(this.data.agents)) {
            let score = 0;
            // promptWords used for potential future word-matching logic
            void prompt.split(/\s+/);
            // Check keywords (weight: 40%)
            const keywordMatches = config.keywords.filter(kw => prompt.includes(kw)).length;
            score += (keywordMatches / config.keywords.length) * 40 * config.weight;
            // Check triggers (weight: 30%)
            const triggerMatches = config.triggers.filter(t => prompt.includes(t)).length;
            score += (triggerMatches / config.triggers.length) * 30 * config.weight;
            // Check tech stack hints (weight: 25%)
            for (const [, stackConfig] of Object.entries(this.data.tech_stacks)) {
                const stackMatches = stackConfig.keywords.filter(kw => prompt.includes(kw)).length;
                if (stackMatches > 0) {
                    score += (stackMatches / stackConfig.keywords.length) * stackConfig.confidence_boost * 0.25;
                }
            }
            // Check user preferences (weight: 5%)
            const userPref = this.userPreferences.preferredAgents?.[agentName.replace('@', '')];
            if (userPref) {
                score += 5;
            }
            // Apply penalty for ambiguity
            const ambiguityPenalty = this.calculateAmbiguityPenalty(prompt);
            score -= ambiguityPenalty;
            scores[agentName] = Math.max(0, Math.min(100, score));
        }
        return scores;
    }
    /**
     * Calculate ambiguity penalty
     */
    calculateAmbiguityPenalty(prompt) {
        let penalty = 0;
        const words = prompt.split(/\s+/);
        // Vague words penalty
        const vagueMatches = words.filter(w => this.data.ambiguity_indicators.vague.includes(w)).length;
        penalty += vagueMatches * 10;
        // Unspecific action words
        const unspecificMatches = words.filter(w => this.data.ambiguity_indicators.unspecific.includes(w)).length;
        penalty += unspecificMatches * 5;
        // Question words
        const questionMatches = words.filter(w => this.data.ambiguity_indicators.question.includes(w)).length;
        penalty += questionMatches * 3;
        // Length penalty (very short prompts are ambiguous)
        if (words.length < 3) {
            penalty += 15;
        }
        return Math.min(penalty, 50);
    }
    /**
     * Check if prompt is vague
     */
    isVaguePrompt(prompt) {
        const words = prompt.split(/\s+/);
        // Very short prompts
        if (words.length < 3)
            return true;
        // Contains mostly vague words
        const vagueCount = words.filter(w => this.data.ambiguity_indicators.vague.includes(w)).length;
        if (vagueCount / words.length > 0.3)
            return true;
        return false;
    }
    /**
     * Detect workflow from prompt
     */
    detectWorkflow(prompt) {
        for (const [workflowName, workflowConfig] of Object.entries(this.data.workflows)) {
            const matches = workflowConfig.triggers.filter(t => prompt.includes(t));
            if (matches.length > 0) {
                return workflowName;
            }
        }
        return undefined;
    }
    /**
     * Generate reasoning for routing decision
     */
    generateReasoning(agent, _score, prompt) {
        const reasoning = [];
        const agentConfig = this.data.agents[agent];
        // Find matching keywords
        const matchedKeywords = agentConfig.keywords.filter(kw => prompt.includes(kw));
        if (matchedKeywords.length > 0) {
            reasoning.push(`Matched keywords: ${matchedKeywords.join(', ')}`);
        }
        // Find matching triggers
        const matchedTriggers = agentConfig.triggers.filter(t => prompt.includes(t));
        if (matchedTriggers.length > 0) {
            reasoning.push(`Matched triggers: ${matchedTriggers.join(', ')}`);
        }
        // Check tech stack
        for (const [stack, config] of Object.entries(this.data.tech_stacks)) {
            const stackMatches = config.keywords.filter(kw => prompt.includes(kw));
            if (stackMatches.length > 0) {
                reasoning.push(`Detected tech stack: ${stack}`);
            }
        }
        // User preference
        const userPref = this.userPreferences.preferredAgents?.[agent.replace('@', '')];
        if (userPref) {
            reasoning.push(`Based on your preference`);
        }
        return reasoning;
    }
    /**
     * Generate clarification questions
     */
    generateClarificationQuestions(prompt, suggestedAgent) {
        const questions = [];
        // Check for tech stack
        const hasTechStack = Object.values(this.data.tech_stacks).some(config => config.keywords.some(kw => prompt.includes(kw)));
        if (!hasTechStack) {
            questions.push("What tech stack do you prefer? [1] React [2] Next.js [3] Vue [4] Svelte [5] Other");
        }
        // Check for project type
        const projectTypes = ['web app', 'cli', 'api', 'mobile app', 'desktop app'];
        const hasProjectType = projectTypes.some(pt => prompt.includes(pt));
        if (!hasProjectType) {
            questions.push("What type of project? [1] Web app [2] CLI tool [3] API service [4] Mobile app [5] Other");
        }
        // Suggest agent if we have one
        if (suggestedAgent) {
            const agentName = suggestedAgent.replace('@', '');
            questions.push(`Should I route to @${agentName}? [yes/no]`);
        }
        return questions;
    }
    /**
     * Learn from user override
     */
    learn(agent, task) {
        if (!this.userPreferences.overrides) {
            this.userPreferences.overrides = [];
        }
        this.userPreferences.overrides.push({
            pattern: task.toLowerCase(),
            chosen_agent: agent,
            timestamp: new Date().toISOString()
        });
        // Update preferred agent for this task type
        if (!this.userPreferences.preferredAgents) {
            this.userPreferences.preferredAgents = {};
        }
        const taskType = this.inferTaskType(task);
        this.userPreferences.preferredAgents[taskType] = agent;
        this.saveUserPreferences();
    }
    /**
     * Infer task type from prompt
     */
    inferTaskType(prompt) {
        if (prompt.includes('api'))
            return 'api';
        if (prompt.includes('frontend') || prompt.includes('ui'))
            return 'frontend';
        if (prompt.includes('backend') || prompt.includes('server'))
            return 'backend';
        if (prompt.includes('test') || prompt.includes('bug'))
            return 'testing';
        if (prompt.includes('deploy'))
            return 'devops';
        return 'general';
    }
    /**
     * Get suggested agents for a task
     */
    getSuggestions(task) {
        const result = this.route(task);
        const suggestions = [result.primaryAgent];
        if (result.secondaryAgent) {
            suggestions.push(result.secondaryAgent);
        }
        if (result.workflow) {
            const workflow = this.data.workflows[result.workflow];
            suggestions.push(...workflow.agents);
        }
        return [...new Set(suggestions)];
    }
}
exports.IntentRouter = IntentRouter;
// Export singleton
exports.router = new IntentRouter();
//# sourceMappingURL=intent-router.js.map