UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

297 lines (296 loc) 11.3 kB
import { IntentPatternEngine } from './patterns.js'; import { LLMFallbackSystem } from './llm-fallback.js'; import { ConfigLoader } from '../utils/config-loader.js'; import logger from '../../../logger.js'; export class IntentRecognitionEngine { static instance; config; patternEngine; llmFallback; recognitionStats = { totalRequests: 0, successfulRecognitions: 0, failedRecognitions: 0, strategyUsage: { pattern: 0, llm: 0, hybrid: 0 } }; constructor() { this.config = this.getDefaultConfig(); this.patternEngine = new IntentPatternEngine(); this.llmFallback = LLMFallbackSystem.getInstance(); this.initializeConfig(); } static getInstance() { if (!IntentRecognitionEngine.instance) { IntentRecognitionEngine.instance = new IntentRecognitionEngine(); } return IntentRecognitionEngine.instance; } initializeConfig() { const configLoader = ConfigLoader.getInstance(); const existingConfig = configLoader.getConfig(); if (existingConfig) { this.updateConfigFromLoaded(existingConfig); return; } configLoader.loadConfig() .then(result => { if (result.success && result.data) { this.updateConfigFromLoaded(result.data); logger.info({ config: this.config }, 'Intent Recognition Engine configuration loaded'); } else { logger.error({ error: result.error }, 'Failed to load configuration, using defaults'); } }) .catch((error) => { logger.error({ err: error }, 'Failed to load configuration, using defaults'); }); } updateConfigFromLoaded(config) { this.config = { primaryMethod: config.taskManager.nlpSettings.primaryMethod, fallbackMethod: config.taskManager.nlpSettings.fallbackMethod, minConfidence: config.taskManager.nlpSettings.minConfidence, useLlmForAmbiguous: true, maxProcessingTime: config.taskManager.nlpSettings.maxProcessingTime, cacheResults: true, cacheTTL: 300, learningEnabled: false, customPatterns: [] }; } getDefaultConfig() { return { primaryMethod: 'hybrid', fallbackMethod: 'pattern', minConfidence: 0.7, useLlmForAmbiguous: true, maxProcessingTime: 5000, cacheResults: true, cacheTTL: 300, learningEnabled: false, customPatterns: [] }; } async recognizeIntent(text, context) { const startTime = Date.now(); this.recognitionStats.totalRequests++; try { logger.debug({ text: text.substring(0, 100), strategy: this.config.primaryMethod }, 'Starting intent recognition'); let result = null; switch (this.config.primaryMethod) { case 'pattern': result = await this.recognizeWithPatterns(text, context, startTime); break; case 'llm': result = await this.recognizeWithLLM(text, context, startTime); break; case 'hybrid': result = await this.recognizeWithHybrid(text, context, startTime); break; } if (!result || result.confidence < this.config.minConfidence) { const fallbackResult = await this.tryFallbackStrategy(text, context, startTime, result); if (fallbackResult && fallbackResult.confidence > (result?.confidence || 0)) { result = fallbackResult; } } if (result) { this.recognitionStats.successfulRecognitions++; this.recognitionStats.strategyUsage[result.strategy]++; } else { this.recognitionStats.failedRecognitions++; } const processingTime = Date.now() - startTime; logger.info({ success: !!result, intent: result?.intent, confidence: result?.confidence, strategy: result?.strategy, processingTime }, 'Intent recognition completed'); return result; } catch (error) { this.recognitionStats.failedRecognitions++; logger.error({ err: error, text: text.substring(0, 100) }, 'Intent recognition failed'); return null; } } async recognizeWithPatterns(text, context, startTime) { const matches = this.patternEngine.matchIntent(text); if (matches.length === 0) { return null; } const bestMatch = matches[0]; const processingTime = startTime ? Date.now() - startTime : bestMatch.processingTime; return { intent: bestMatch.intent, confidence: bestMatch.confidence, confidenceLevel: bestMatch.confidenceLevel, entities: bestMatch.entities, strategy: 'pattern', alternatives: matches.slice(1, 3).map(match => ({ intent: match.intent, confidence: match.confidence, strategy: 'pattern' })), processingTime, metadata: { patternMatches: matches, timestamp: new Date() } }; } async recognizeWithLLM(text, context, startTime) { const llmResult = await this.llmFallback.recognizeIntent(text, 0, context); if (!llmResult) { return null; } const processingTime = startTime ? Date.now() - startTime : llmResult.metadata.processingTime; return { intent: llmResult.intent, confidence: llmResult.confidence, confidenceLevel: llmResult.confidenceLevel, entities: Array.isArray(llmResult.entities) ? llmResult.entities.reduce((acc, entity) => { if (entity && typeof entity === 'object' && 'type' in entity) { const entityObj = entity; acc[entityObj.type] = entityObj.value || entityObj.text || entity; } return acc; }, {}) : llmResult.entities || {}, strategy: 'llm', alternatives: llmResult.alternatives.map(alt => ({ intent: alt.intent, confidence: alt.confidence, strategy: 'llm' })), processingTime, metadata: { llmUsed: true, timestamp: new Date() } }; } async recognizeWithHybrid(text, context, startTime) { const patternResult = await this.recognizeWithPatterns(text, context, startTime); if (patternResult && patternResult.confidence >= this.config.minConfidence) { patternResult.strategy = 'hybrid'; return patternResult; } if (this.config.useLlmForAmbiguous) { const llmResult = await this.recognizeWithLLM(text, context, startTime); if (llmResult) { llmResult.strategy = 'hybrid'; llmResult.metadata.fallbackReason = patternResult ? 'low_pattern_confidence' : 'no_pattern_match'; if (patternResult?.metadata.patternMatches) { llmResult.metadata.patternMatches = patternResult.metadata.patternMatches; } return llmResult; } } if (patternResult) { patternResult.strategy = 'hybrid'; return patternResult; } return null; } async tryFallbackStrategy(text, context, startTime, primaryResult) { if (this.config.fallbackMethod === 'none') { return null; } logger.debug({ fallbackMethod: this.config.fallbackMethod, primarySuccess: !!primaryResult, primaryConfidence: primaryResult?.confidence }, 'Trying fallback strategy'); let fallbackResult = null; switch (this.config.fallbackMethod) { case 'pattern': if (this.config.primaryMethod !== 'pattern') { fallbackResult = await this.recognizeWithPatterns(text, context, startTime); } break; case 'llm': if (this.config.primaryMethod !== 'llm') { fallbackResult = await this.recognizeWithLLM(text, context, startTime); } break; } if (fallbackResult) { fallbackResult.metadata.fallbackReason = 'primary_strategy_failed'; } return fallbackResult; } async disambiguateIntents(text, candidates, _context) { if (candidates.length <= 1) { return candidates[0] || null; } const sorted = candidates.sort((a, b) => b.confidence - a.confidence); const best = sorted[0]; const second = sorted[1]; if (best.confidence - second.confidence > 0.2) { return best; } if (this.config.useLlmForAmbiguous) { } return best; } buildDisambiguationPrompt(text, candidates) { let prompt = `The following text has multiple possible interpretations:\n\n"${text}"\n\n`; prompt += `Possible intents:\n`; candidates.forEach((candidate, index) => { prompt += `${index + 1}. ${candidate.intent} (confidence: ${candidate.confidence.toFixed(2)})\n`; }); prompt += `\nPlease select the most likely intent and explain your reasoning.`; return prompt; } async learnFromFeedback(originalText, recognizedIntent, correctIntent, userFeedback) { if (!this.config.learningEnabled) { return; } logger.info({ originalText: originalText.substring(0, 100), recognizedIntent, correctIntent, userFeedback }, 'Learning from user feedback'); } getStatistics() { return { ...this.recognitionStats, successRate: this.recognitionStats.totalRequests > 0 ? this.recognitionStats.successfulRecognitions / this.recognitionStats.totalRequests : 0 }; } updateConfig(config) { this.config = { ...this.config, ...config }; logger.info({ config: this.config }, 'Intent Recognition Engine configuration updated'); } getConfig() { return { ...this.config }; } resetStatistics() { this.recognitionStats = { totalRequests: 0, successfulRecognitions: 0, failedRecognitions: 0, strategyUsage: { pattern: 0, llm: 0, hybrid: 0 } }; logger.info('Recognition statistics reset'); } }