ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
262 lines • 10.6 kB
JavaScript
/**
* Intelligent Tool Selection System
* Limits tools based on context to improve LLM performance (following Wordware's <15 tools rule)
*/
/**
* Intelligent Tool Selector
* Selects optimal subset of tools based on current debugging context
*/
export class IntelligentToolSelector {
allTools = [];
userHistory = new Map(); // tool usage frequency
selectionStrategy;
constructor(strategy) {
this.selectionStrategy = {
maxTools: 12, // Slightly under Wordware's 15 tool limit
selectionWeights: {
frameworkMatch: 0.3,
trainingDataRich: 0.25,
userHistoryMatch: 0.2,
costEfficiency: 0.15,
authorityLevel: 0.1
},
minimumScore: 0.3,
...strategy
};
}
/**
* Register available tools
*/
registerTools(tools) {
this.allTools = tools;
}
/**
* Select optimal tools for current context
*/
selectTools(context, requestedCategories) {
// Score all tools based on context
const scoredTools = this.scoreTools(context, requestedCategories);
// Filter by minimum score
const viableTools = scoredTools.filter(scored => scored.score >= this.selectionStrategy.minimumScore);
// Sort by score (highest first)
viableTools.sort((a, b) => b.score - a.score);
// Select top N tools
const selectedTools = viableTools
.slice(0, this.selectionStrategy.maxTools)
.map(scored => scored.tool);
const alternativeTools = viableTools
.slice(this.selectionStrategy.maxTools)
.map(scored => scored.tool);
const selectionReasoning = this.generateSelectionReasoning(context, viableTools.slice(0, this.selectionStrategy.maxTools));
return {
selectedTools,
totalAvailable: this.allTools.length,
selectionReasoning,
alternativeTools
};
}
/**
* Score tools based on current context
*/
scoreTools(context, requestedCategories) {
return this.allTools.map(tool => {
const scores = {
frameworkMatch: this.calculateFrameworkScore(tool, context),
trainingDataRich: tool.metadata.trainingDataRich ? 1.0 : 0.3,
userHistoryMatch: this.calculateUserHistoryScore(tool),
costEfficiency: this.calculateCostScore(tool, context),
authorityLevel: this.calculateAuthorityScore(tool, context)
};
// Apply category boost if requested
if (requestedCategories && requestedCategories.includes(tool.metadata.category)) {
scores.frameworkMatch *= 1.5;
}
// Calculate weighted score
const totalScore = scores.frameworkMatch * this.selectionStrategy.selectionWeights.frameworkMatch +
scores.trainingDataRich * this.selectionStrategy.selectionWeights.trainingDataRich +
scores.userHistoryMatch * this.selectionStrategy.selectionWeights.userHistoryMatch +
scores.costEfficiency * this.selectionStrategy.selectionWeights.costEfficiency +
scores.authorityLevel * this.selectionStrategy.selectionWeights.authorityLevel;
const reasoning = this.generateToolReasoning(tool, scores, context);
return {
tool,
score: Math.min(1.0, totalScore), // Cap at 1.0
reasoning
};
});
}
/**
* Calculate framework compatibility score
*/
calculateFrameworkScore(tool, context) {
if (!context.framework)
return 0.5; // Neutral if no framework specified
const compatibility = tool.metadata.frameworkCompatibility.find(fc => fc.framework === context.framework || fc.framework === 'general');
if (!compatibility)
return 0.1; // Low score if framework not supported
switch (compatibility.compatibility) {
case 'high': return 1.0;
case 'medium': return 0.7;
case 'low': return 0.4;
default: return 0.5;
}
}
/**
* Calculate user history score based on past usage
*/
calculateUserHistoryScore(tool) {
const usageCount = this.userHistory.get(tool.name) || 0;
const maxUsage = Math.max(...Array.from(this.userHistory.values()), 1);
return usageCount / maxUsage;
}
/**
* Calculate cost efficiency score
*/
calculateCostScore(tool, context) {
const costMultiplier = context.timeConstraint === 'urgent' ? 0.5 : 1.0; // Prefer faster tools when urgent
switch (tool.metadata.costLevel) {
case 'low': return 1.0 * costMultiplier;
case 'medium': return 0.7 * costMultiplier;
case 'high': return 0.4 * costMultiplier;
default: return 0.5 * costMultiplier;
}
}
/**
* Calculate authority level appropriateness score
*/
calculateAuthorityScore(tool, context) {
// Prefer lower authority tools for beginners
const authorityPenalty = context.userExperience === 'beginner' ? 0.8 : 1.0;
switch (tool.metadata.authority) {
case 'read_only': return 1.0;
case 'user_interaction': return 0.9 * authorityPenalty;
case 'file_modification': return 0.7 * authorityPenalty;
case 'system_modification': return 0.5 * authorityPenalty;
case 'network_access': return 0.8 * authorityPenalty;
default: return 0.5;
}
}
/**
* Generate reasoning for tool selection
*/
generateToolReasoning(tool, scores, context) {
const reasoning = [];
if (scores.frameworkMatch > 0.8) {
reasoning.push(`High framework compatibility with ${context.framework}`);
}
if (scores.trainingDataRich > 0.8) {
reasoning.push('Rich training data available for this tool');
}
if (scores.userHistoryMatch > 0.5) {
reasoning.push('Frequently used tool in your workflow');
}
if (scores.costEfficiency > 0.8) {
reasoning.push('Cost-efficient execution');
}
if (context.phase === 'initial' && tool.metadata.category === 'core') {
reasoning.push('Essential for initial debugging phase');
}
return reasoning;
}
/**
* Generate overall selection reasoning
*/
generateSelectionReasoning(context, selectedTools) {
const phaseDescription = this.getPhaseDescription(context.phase);
const frameworkNote = context.framework ? ` for ${context.framework}` : '';
let reasoning = `Selected ${selectedTools.length} tools optimized for ${phaseDescription}${frameworkNote}. `;
const categoryCounts = this.countCategories(selectedTools.map(st => st.tool));
const categoryDescriptions = Object.entries(categoryCounts)
.map(([category, count]) => `${count} ${category}`)
.join(', ');
reasoning += `Tool mix: ${categoryDescriptions}. `;
if (context.timeConstraint === 'urgent') {
reasoning += 'Prioritized fast-executing tools due to time constraints. ';
}
if (context.userExperience === 'beginner') {
reasoning += 'Selected user-friendly tools with lower risk levels.';
}
else if (context.userExperience === 'expert') {
reasoning += 'Included advanced tools for comprehensive analysis.';
}
return reasoning;
}
/**
* Get human-readable phase description
*/
getPhaseDescription(phase) {
switch (phase) {
case 'initial': return 'initial exploration and setup';
case 'deep_dive': return 'detailed analysis and investigation';
case 'performance': return 'performance optimization';
case 'testing': return 'testing and validation';
case 'resolution': return 'issue resolution and verification';
default: return 'debugging';
}
}
/**
* Count tools by category
*/
countCategories(tools) {
const counts = {};
for (const tool of tools) {
const category = tool.metadata.category;
counts[category] = (counts[category] || 0) + 1;
}
return counts;
}
/**
* Record tool usage for learning
*/
recordToolUsage(toolName) {
const currentCount = this.userHistory.get(toolName) || 0;
this.userHistory.set(toolName, currentCount + 1);
}
/**
* Get tool recommendations based on current context
*/
getToolRecommendations(context, excludeTools = []) {
const availableTools = this.allTools.filter(tool => !excludeTools.includes(tool.name));
const scoredTools = this.scoreTools(context);
return scoredTools
.filter(scored => !excludeTools.includes(scored.tool.name))
.sort((a, b) => b.score - a.score)
.slice(0, 3) // Top 3 recommendations
.map(scored => scored.tool);
}
/**
* Explain why a tool was or wasn't selected
*/
explainToolSelection(toolName, context) {
const tool = this.allTools.find(t => t.name === toolName);
if (!tool)
return `Tool '${toolName}' not found.`;
const scoredTool = this.scoreTools(context).find(st => st.tool.name === toolName);
if (!scoredTool)
return `Unable to score tool '${toolName}'.`;
let explanation = `Tool '${toolName}' scored ${(scoredTool.score * 100).toFixed(1)}%. `;
if (scoredTool.score >= this.selectionStrategy.minimumScore) {
explanation += 'This tool was eligible for selection. ';
}
else {
explanation += `This tool was excluded (minimum score: ${(this.selectionStrategy.minimumScore * 100).toFixed(1)}%). `;
}
if (scoredTool.reasoning.length > 0) {
explanation += `Reasons: ${scoredTool.reasoning.join(', ')}.`;
}
return explanation;
}
/**
* Update selection strategy
*/
updateStrategy(updates) {
this.selectionStrategy = { ...this.selectionStrategy, ...updates };
}
/**
* Get current selection strategy
*/
getStrategy() {
return { ...this.selectionStrategy };
}
}
//# sourceMappingURL=tool-selector.js.map