UNPKG

@emmahyde/thinking-patterns

Version:

MCP server combining systematic thinking, mental models, debugging approaches, and stochastic algorithms for comprehensive cognitive pattern support

318 lines (317 loc) 15.4 kB
export class ToolRecommendationEngine { constructor() { this.toolDescriptions = { 'mental_model': 'Structured thinking frameworks like first principles, opportunity cost analysis, and systematic problem decomposition', 'debugging_approach': 'Systematic debugging methods including binary search, divide and conquer, and cause elimination', 'stochastic_algorithm': 'Probabilistic decision-making tools including MDPs, Monte Carlo methods, and Bayesian optimization', 'collaborative_reasoning': 'Multi-perspective problem solving with diverse viewpoints and stakeholder analysis', 'decision_framework': 'Structured decision analysis with criteria evaluation and outcome modeling', 'metacognitive_monitoring': 'Self-assessment of reasoning quality and knowledge gaps', 'scientific_method': 'Formal hypothesis testing and experimental validation', 'structured_argumentation': 'Dialectical reasoning and systematic argument analysis', 'visual_reasoning': 'Diagram-based thinking and spatial problem solving' }; this.problemDomainMappings = { 'technical': ['debugging_approach', 'scientific_method', 'mental_model'], 'strategic': ['decision_framework', 'collaborative_reasoning', 'stochastic_algorithm'], 'research': ['scientific_method', 'metacognitive_monitoring', 'mental_model'], 'design': ['visual_reasoning', 'collaborative_reasoning', 'structured_argumentation'], 'analysis': ['mental_model', 'debugging_approach', 'metacognitive_monitoring'] }; } generateRecommendations(thought, thoughtNumber, totalThoughts, context) { const recommendations = []; const thoughtContent = thought.toLowerCase(); // Analyze thought content for keywords and context const analysisResults = this.analyzeThoughtContent(thoughtContent); // Generate recommendations based on thinking stage const stageRecommendations = this.getStageBasedRecommendations(thoughtNumber, totalThoughts, analysisResults); // Generate domain-specific recommendations const domainRecommendations = this.getDomainSpecificRecommendations(context.problemDomain || 'general', analysisResults); // Combine and score recommendations const combinedRecommendations = this.combineRecommendations(stageRecommendations, domainRecommendations, context.availableTools); // Sort by confidence and return top recommendations return combinedRecommendations .sort((a, b) => b.confidence - a.confidence) .slice(0, 5); } generateCurrentStep(thought, thoughtNumber, totalThoughts, context) { const recommendations = this.generateRecommendations(thought, thoughtNumber, totalThoughts, context); const analysisResults = this.analyzeThoughtContent(thought.toLowerCase()); return { stepDescription: this.generateStepDescription(thought, thoughtNumber, totalThoughts), recommendedTools: recommendations, expectedOutcome: this.generateExpectedOutcome(analysisResults, thoughtNumber, totalThoughts), nextStepConditions: this.generateNextStepConditions(analysisResults, thoughtNumber, totalThoughts), stepNumber: thoughtNumber, complexityLevel: this.assessComplexity(analysisResults), estimatedDuration: this.estimateDuration(analysisResults, recommendations.length) }; } analyzeThoughtContent(thought) { const keywords = this.extractKeywords(thought); const intent = this.classifyIntent(thought, keywords); const complexity = this.assessContentComplexity(thought, keywords); const domain = this.inferDomain(keywords, intent); return { keywords, intent, complexity, domain }; } extractKeywords(thought) { const problemKeywords = ['problem', 'issue', 'challenge', 'difficulty', 'error', 'bug', 'debug']; const analysisKeywords = ['analyze', 'examine', 'investigate', 'research', 'study']; const decisionKeywords = ['decide', 'choose', 'select', 'option', 'alternative']; const planningKeywords = ['plan', 'strategy', 'approach', 'method', 'process']; const evaluationKeywords = ['evaluate', 'assess', 'measure', 'test', 'validate']; const allKeywords = [ ...problemKeywords, ...analysisKeywords, ...decisionKeywords, ...planningKeywords, ...evaluationKeywords ]; return allKeywords.filter(keyword => thought.includes(keyword)); } classifyIntent(thought, keywords) { if (keywords.some(k => ['problem', 'issue', 'challenge'].includes(k))) return 'problem-identification'; if (keywords.some(k => ['analyze', 'examine', 'research'].includes(k))) return 'analysis'; if (keywords.some(k => ['decide', 'choose', 'select'].includes(k))) return 'decision-making'; if (keywords.some(k => ['plan', 'strategy', 'approach'].includes(k))) return 'planning'; if (keywords.some(k => ['evaluate', 'assess', 'test'].includes(k))) return 'evaluation'; return 'exploration'; } assessContentComplexity(thought, keywords) { let complexity = 0.5; // Base complexity // Length factor if (thought.length > 200) complexity += 0.2; if (thought.length > 500) complexity += 0.2; // Keyword density factor complexity += Math.min(keywords.length * 0.1, 0.3); // Technical terms factor const technicalTerms = ['algorithm', 'system', 'architecture', 'implementation', 'optimization']; if (technicalTerms.some(term => thought.includes(term))) complexity += 0.2; return Math.min(complexity, 1.0); } inferDomain(keywords, intent) { const technicalIndicators = ['bug', 'error', 'system', 'algorithm', 'implementation']; const strategicIndicators = ['strategy', 'plan', 'decision', 'option', 'business']; const researchIndicators = ['research', 'study', 'investigate', 'analyze']; if (technicalIndicators.some(ind => keywords.includes(ind))) return 'technical'; if (strategicIndicators.some(ind => keywords.includes(ind))) return 'strategic'; if (researchIndicators.some(ind => keywords.includes(ind))) return 'research'; return 'general'; } getStageBasedRecommendations(thoughtNumber, totalThoughts, analysis) { const stage = this.determineThinkingStage(thoughtNumber, totalThoughts); const recommendations = []; switch (stage) { case 'initial': recommendations.push({ toolName: 'mental_model', confidence: 0.8, rationale: 'Mental models help structure initial problem understanding and break down complex issues', priority: 1, alternativeTools: ['debugging_approach'] }); if (analysis.intent === 'problem-identification') { recommendations.push({ toolName: 'debugging_approach', confidence: 0.7, rationale: 'Debugging approaches provide systematic methods for identifying root causes', priority: 2 }); } break; case 'middle': if (analysis.intent === 'analysis') { recommendations.push({ toolName: 'scientific_method', confidence: 0.8, rationale: 'Scientific method provides rigorous analysis framework for mid-stage investigation', priority: 1 }); } recommendations.push({ toolName: 'metacognitive_monitoring', confidence: 0.6, rationale: 'Monitor reasoning quality and identify knowledge gaps during analysis', priority: 3 }); break; case 'final': recommendations.push({ toolName: 'decision_framework', confidence: 0.9, rationale: 'Decision frameworks help evaluate options and make final choices', priority: 1 }); if (analysis.domain === 'strategic') { recommendations.push({ toolName: 'collaborative_reasoning', confidence: 0.7, rationale: 'Multiple perspectives validate final decisions and identify blind spots', priority: 2 }); } break; } return recommendations; } getDomainSpecificRecommendations(domain, analysis) { const domainTools = this.problemDomainMappings[domain] || []; const recommendations = []; domainTools.forEach((tool, index) => { let confidence = 0.6 - (index * 0.1); // Decrease confidence for lower priority tools let rationale = this.generateDomainRationale(tool, domain, analysis); // Boost confidence based on analysis results if (this.toolMatchesAnalysis(tool, analysis)) { confidence += 0.2; } recommendations.push({ toolName: tool, confidence: Math.min(confidence, 1.0), rationale, priority: index + 1 }); }); return recommendations; } combineRecommendations(stageRecs, domainRecs, availableTools) { const combined = new Map(); // Add stage-based recommendations stageRecs.forEach(rec => { if (availableTools.includes(rec.toolName)) { combined.set(rec.toolName, rec); } }); // Merge domain-based recommendations domainRecs.forEach(rec => { if (availableTools.includes(rec.toolName)) { const existing = combined.get(rec.toolName); if (existing) { // Combine confidence scores and rationales existing.confidence = Math.min((existing.confidence + rec.confidence) / 2 + 0.1, 1.0); existing.rationale = `${existing.rationale}; ${rec.rationale}`; } else { combined.set(rec.toolName, rec); } } }); return Array.from(combined.values()); } determineThinkingStage(thoughtNumber, totalThoughts) { // Handle edge cases first if (totalThoughts === 1) return 'final'; // Single thought is always final if (thoughtNumber === 1 && totalThoughts > 1) return 'initial'; if (thoughtNumber === totalThoughts) return 'final'; // For sequences with 2 thoughts, first is initial, second is final if (totalThoughts === 2) { return thoughtNumber === 1 ? 'initial' : 'final'; } // For longer sequences, use proportional logic const progress = thoughtNumber / totalThoughts; if (progress <= 0.33) return 'initial'; if (progress >= 0.67) return 'final'; return 'middle'; } toolMatchesAnalysis(toolName, analysis) { const toolIntentMap = { 'debugging_approach': ['problem-identification'], 'scientific_method': ['analysis', 'evaluation'], 'decision_framework': ['decision-making'], 'mental_model': ['exploration', 'problem-identification'], 'collaborative_reasoning': ['planning', 'decision-making'] }; const matchingIntents = toolIntentMap[toolName] || []; return matchingIntents.includes(analysis.intent); } generateDomainRationale(toolName, domain, analysis) { const baseDescription = this.toolDescriptions[toolName] || 'Tool for systematic analysis'; const domainContext = `Particularly effective for ${domain} domain problems`; return `${baseDescription}. ${domainContext}`; } generateStepDescription(thought, thoughtNumber, totalThoughts) { const stage = this.determineThinkingStage(thoughtNumber, totalThoughts); const stageDescriptions = { initial: 'Initial problem analysis and framework establishment', middle: 'Deep analysis and systematic investigation', final: 'Solution synthesis and decision formulation' }; return `${stageDescriptions[stage]} (Step ${thoughtNumber}/${totalThoughts})`; } generateExpectedOutcome(analysis, thoughtNumber, totalThoughts) { const stage = this.determineThinkingStage(thoughtNumber, totalThoughts); switch (stage) { case 'initial': return 'Clear problem definition and analytical framework'; case 'middle': return 'Detailed analysis results and validated insights'; case 'final': return 'Concrete solution or decision with supporting rationale'; default: return 'Progressive understanding and actionable insights'; } } generateNextStepConditions(analysis, thoughtNumber, totalThoughts) { const stage = this.determineThinkingStage(thoughtNumber, totalThoughts); switch (stage) { case 'initial': return [ 'Problem scope clearly defined', 'Key variables identified', 'Analysis approach selected' ]; case 'middle': return [ 'Sufficient data gathered', 'Analysis methods validated', 'Initial hypotheses tested' ]; case 'final': return [ 'All options evaluated', 'Decision criteria met', 'Implementation plan outlined' ]; default: return ['Current step objectives achieved']; } } assessComplexity(analysis) { if (analysis.complexity < 0.4) return 'low'; if (analysis.complexity < 0.7) return 'medium'; return 'high'; } estimateDuration(analysis, toolCount) { const baseTime = 5; // minutes const complexityMultiplier = { 'low': 1, 'medium': 1.5, 'high': 2.5 }; const complexity = this.assessComplexity(analysis); const toolMultiplier = 1 + (toolCount * 0.3); const estimatedMinutes = baseTime * complexityMultiplier[complexity] * toolMultiplier; if (estimatedMinutes < 10) return '5-10 minutes'; if (estimatedMinutes < 30) return '15-30 minutes'; if (estimatedMinutes < 60) return '30-60 minutes'; return '1+ hours'; } }