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
632 lines (606 loc) โข 25.6 kB
JavaScript
/**
* Code Quality Integration Handler
* Implements file change detection, visual validation, and refactoring safety net
* Based on user feedback for systematic development cycle enhancement
*/
import { FileChangeMonitor } from '../utils/file-change-monitor.js';
import { VisualValidationEngine } from '../utils/visual-validation-engine.js';
import { RefactoringSafetyNet } from '../utils/refactoring-safety-net.js';
export class CodeQualityIntegrationHandler {
tools = [
{
name: 'start_file_change_monitoring',
description: 'Start monitoring file changes during development with automatic screenshot capture',
inputSchema: {
type: 'object',
properties: {
projectPath: {
type: 'string',
description: 'Root path of the project to monitor'
},
filePatterns: {
type: 'array',
items: { type: 'string' },
description: 'File patterns to monitor (e.g., ["*.ts", "*.tsx", "*.js", "*.jsx"])',
default: ['*.ts', '*.tsx', '*.js', '*.jsx', '*.vue', '*.svelte']
},
screenshotOnChange: {
type: 'boolean',
description: 'Automatically capture screenshots when files change',
default: true
},
sessionId: {
type: 'string',
description: 'Active debugging session ID for screenshot capture'
}
},
required: ['projectPath', 'sessionId']
}
},
{
name: 'stop_file_change_monitoring',
description: 'Stop file change monitoring and generate change report',
inputSchema: {
type: 'object',
properties: {
generateReport: {
type: 'boolean',
description: 'Generate a detailed report of all changes detected',
default: true
}
}
}
},
{
name: 'capture_refactoring_baseline',
description: 'Capture baseline screenshots and state before major refactoring',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Active debugging session ID'
},
refactoringName: {
type: 'string',
description: 'Name/description of the refactoring being performed'
},
criticalPages: {
type: 'array',
items: { type: 'string' },
description: 'URLs of critical pages to capture for comparison'
},
includeState: {
type: 'boolean',
description: 'Include application state in baseline capture',
default: true
}
},
required: ['sessionId', 'refactoringName']
}
},
{
name: 'validate_after_refactoring',
description: 'Compare current state with baseline after refactoring completion',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Active debugging session ID'
},
baselineId: {
type: 'string',
description: 'ID of the baseline to compare against'
},
toleranceLevel: {
type: 'string',
enum: ['strict', 'moderate', 'loose'],
description: 'Visual comparison tolerance level',
default: 'moderate'
}
},
required: ['sessionId', 'baselineId']
}
},
{
name: 'setup_visual_test_integration',
description: 'Integrate with test runners for automatic visual validation during tests',
inputSchema: {
type: 'object',
properties: {
testFramework: {
type: 'string',
enum: ['jest', 'cypress', 'playwright', 'vitest'],
description: 'Test framework to integrate with'
},
testPattern: {
type: 'string',
description: 'Test file pattern to watch',
default: '**/*.test.{js,ts,jsx,tsx}'
},
screenshotOnFailure: {
type: 'boolean',
description: 'Capture screenshots when tests fail',
default: true
},
sessionId: {
type: 'string',
description: 'Active debugging session ID'
}
},
required: ['testFramework', 'sessionId']
}
},
{
name: 'analyze_ui_stability',
description: 'Analyze UI stability across file changes and provide stability score',
inputSchema: {
type: 'object',
properties: {
timeRange: {
type: 'string',
description: 'Time range to analyze (e.g., "1h", "24h", "7d")',
default: '1h'
},
includePerformance: {
type: 'boolean',
description: 'Include performance metrics in stability analysis',
default: true
}
}
}
},
{
name: 'set_code_quality_gates',
description: 'Configure automated quality gates for file size limits and test coverage',
inputSchema: {
type: 'object',
properties: {
maxFileSize: {
type: 'number',
description: 'Maximum file size in lines (default: 300)',
default: 300
},
minTestCoverage: {
type: 'number',
description: 'Minimum test coverage percentage',
default: 80
},
enableSizeWarnings: {
type: 'boolean',
description: 'Show warnings when files exceed size limits',
default: true
},
blockOnFailure: {
type: 'boolean',
description: 'Block operations when quality gates fail',
default: false
}
}
}
},
{
name: 'get_change_impact_analysis',
description: 'Analyze the impact of recent file changes on UI and functionality',
inputSchema: {
type: 'object',
properties: {
changeId: {
type: 'string',
description: 'Specific change ID to analyze, or latest if not provided'
},
includeVisualDiff: {
type: 'boolean',
description: 'Include visual differences in the analysis',
default: true
},
includePerformanceImpact: {
type: 'boolean',
description: 'Include performance impact analysis',
default: true
}
}
}
}
];
fileChangeMonitor;
visualValidationEngine;
refactoringSafetyNet;
constructor() {
this.fileChangeMonitor = new FileChangeMonitor();
this.visualValidationEngine = new VisualValidationEngine();
this.refactoringSafetyNet = new RefactoringSafetyNet();
}
async handle(toolName, args, sessions) {
try {
switch (toolName) {
case 'start_file_change_monitoring':
return await this.startFileChangeMonitoring(args, sessions);
case 'stop_file_change_monitoring':
return await this.stopFileChangeMonitoring(args);
case 'capture_refactoring_baseline':
return await this.captureRefactoringBaseline(args, sessions);
case 'validate_after_refactoring':
return await this.validateAfterRefactoring(args, sessions);
case 'setup_visual_test_integration':
return await this.setupVisualTestIntegration(args, sessions);
case 'analyze_ui_stability':
return await this.analyzeUIStability(args);
case 'set_code_quality_gates':
return await this.setCodeQualityGates(args);
case 'get_change_impact_analysis':
return await this.getChangeImpactAnalysis(args);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
catch (error) {
return {
content: [{
type: 'text',
text: `Error in Code Quality Integration: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
/**
* Start monitoring file changes with automatic screenshot capture
*/
async startFileChangeMonitoring(args, sessions) {
const { projectPath, filePatterns, screenshotOnChange, sessionId } = args;
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: 'โ No active debugging session found. Please start a session with inject_debugging first.'
}]
};
}
const monitoringConfig = await this.fileChangeMonitor.startMonitoring({
projectPath,
filePatterns: filePatterns || ['*.ts', '*.tsx', '*.js', '*.jsx', '*.vue', '*.svelte'],
screenshotOnChange,
sessionId,
session
});
return {
content: [{
type: 'text',
text: `๐ **File Change Monitoring Started**
๐ **Project Path**: ${projectPath}
๐ **File Patterns**: ${filePatterns?.join(', ') || 'Default patterns'}
๐ธ **Screenshot on Change**: ${screenshotOnChange ? 'Enabled' : 'Disabled'}
๐ **Monitor ID**: ${monitoringConfig.monitorId}
โ
Monitoring ${monitoringConfig.watchedFiles} files for changes.
๐ All changes will be logged with timestamps and impact analysis.
${screenshotOnChange ? '๐ท Screenshots will be automatically captured when files change.' : ''}
**Next Steps:**
1. Make code changes as part of your development workflow
2. Screenshots and change logs will be captured automatically
3. Use \`stop_file_change_monitoring\` to get a comprehensive report`
}]
};
}
/**
* Stop file change monitoring and generate report
*/
async stopFileChangeMonitoring(args) {
const { generateReport } = args;
const report = await this.fileChangeMonitor.stopMonitoring(generateReport);
if (!report) {
return {
content: [{
type: 'text',
text: 'โ ๏ธ No active file monitoring session found.'
}]
};
}
let responseText = `๐ **File Change Monitoring Stopped**
๐ **Session Summary**:
- **Duration**: ${report.duration}
- **Files Changed**: ${report.changedFiles.length}
- **Total Changes**: ${report.totalChanges}
- **Screenshots Captured**: ${report.screenshotsCaptured}
`;
if (report.changedFiles.length > 0) {
responseText += `๐ **Changed Files**:\n`;
report.changedFiles.forEach((file) => {
responseText += `- \`${file.path}\` (${file.changeCount} changes)\n`;
});
}
if (report.uiStabilityScore !== undefined) {
responseText += `\n๐ฏ **UI Stability Score**: ${report.uiStabilityScore}/100\n`;
if (report.uiStabilityScore < 80) {
responseText += `โ ๏ธ UI stability below recommended threshold. Consider reviewing recent changes.\n`;
}
}
if (generateReport && report.detailedReport) {
responseText += `\n๐ **Detailed Report**: Available at ${report.detailedReport}`;
}
return {
content: [{
type: 'text',
text: responseText
}]
};
}
/**
* Capture baseline before refactoring
*/
async captureRefactoringBaseline(args, sessions) {
const { sessionId, refactoringName, criticalPages, includeState } = args;
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: 'โ No active debugging session found. Please start a session with inject_debugging first.'
}]
};
}
const baseline = await this.refactoringSafetyNet.captureBaseline({
sessionId,
refactoringName,
criticalPages: criticalPages || [],
includeState,
session
});
return {
content: [{
type: 'text',
text: `๐ธ **Refactoring Baseline Captured**
๐ท๏ธ **Refactoring**: ${refactoringName}
๐ **Baseline ID**: ${baseline.baselineId}
๐
**Captured At**: ${new Date(baseline.timestamp).toLocaleString()}
๐ **Captured Data**:
- **Screenshots**: ${baseline.screenshots.length} pages
- **Application State**: ${includeState ? 'Included' : 'Not included'}
- **Performance Metrics**: ${baseline.performanceMetrics ? 'Captured' : 'Not captured'}
${criticalPages && criticalPages.length > 0 ? `๐ **Critical Pages Captured**:\n${criticalPages.map((page) => `- ${page}`).join('\n')}` : ''}
โ
**Ready for Refactoring**: You can now safely make your changes.
๐ **After refactoring**, use \`validate_after_refactoring\` with baseline ID: \`${baseline.baselineId}\``
}]
};
}
/**
* Validate changes after refactoring
*/
async validateAfterRefactoring(args, sessions) {
const { sessionId, baselineId, toleranceLevel } = args;
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: 'โ No active debugging session found. Please start a session with inject_debugging first.'
}]
};
}
const validation = await this.refactoringSafetyNet.validateAfterRefactoring({
sessionId,
baselineId,
toleranceLevel: toleranceLevel || 'moderate',
session
});
if (!validation.baseline) {
return {
content: [{
type: 'text',
text: `โ Baseline with ID '${baselineId}' not found. Please check the baseline ID.`
}]
};
}
let responseText = `๐ **Refactoring Validation Results**
๐ท๏ธ **Refactoring**: ${validation.baseline.refactoringName}
๐ **Baseline ID**: ${baselineId}
๐ **Overall Score**: ${validation.overallScore}/100
`;
// Visual comparison results
if (validation.visualComparison.length > 0) {
responseText += `๐ธ **Visual Comparison Results**:\n`;
validation.visualComparison.forEach((result) => {
const status = result.similarity > 90 ? 'โ
' : result.similarity > 75 ? 'โ ๏ธ' : 'โ';
responseText += `${status} ${result.page}: ${result.similarity}% similarity\n`;
});
}
// Performance impact
if (validation.performanceImpact) {
const impact = validation.performanceImpact;
responseText += `\nโก **Performance Impact**:\n`;
responseText += `- Load Time: ${impact.loadTimeChange > 0 ? '+' : ''}${impact.loadTimeChange}ms\n`;
responseText += `- Memory Usage: ${impact.memoryChange > 0 ? '+' : ''}${impact.memoryChange}MB\n`;
}
// Issues found
if (validation.issuesFound.length > 0) {
responseText += `\n๐จ **Issues Found**:\n`;
validation.issuesFound.forEach((issue) => {
responseText += `- ${issue.severity.toUpperCase()}: ${issue.description}\n`;
});
}
// Recommendations
if (validation.recommendations.length > 0) {
responseText += `\n๐ก **Recommendations**:\n`;
validation.recommendations.forEach((rec) => {
responseText += `- ${rec}\n`;
});
}
const overallStatus = validation.overallScore >= 90 ? '๐ Refactoring successful!' :
validation.overallScore >= 75 ? 'โ ๏ธ Refactoring mostly successful with minor issues' :
'๐จ Refactoring has significant issues that need attention';
responseText += `\n${overallStatus}`;
return {
content: [{
type: 'text',
text: responseText
}]
};
}
/**
* Setup visual test integration
*/
async setupVisualTestIntegration(args, sessions) {
const { testFramework, testPattern, screenshotOnFailure, sessionId } = args;
const integration = await this.visualValidationEngine.setupTestIntegration({
testFramework,
testPattern,
screenshotOnFailure,
sessionId
});
return {
content: [{
type: 'text',
text: `๐งช **Visual Test Integration Setup Complete**
๐ง **Test Framework**: ${testFramework}
๐ **Test Pattern**: ${testPattern}
๐ธ **Screenshot on Failure**: ${screenshotOnFailure ? 'Enabled' : 'Disabled'}
๐ **Integration ID**: ${integration.integrationId}
โ
**Configuration Applied**:
- Test watcher started for pattern: \`${testPattern}\`
- Visual validation hooks installed
- Screenshot capture ${screenshotOnFailure ? 'enabled' : 'disabled'} on test failures
๐ **Next Steps**:
1. Run your tests normally with \`${testFramework === 'jest' ? 'npm test' : testFramework === 'cypress' ? 'npx cypress run' : 'npx playwright test'}\`
2. Visual validation will run automatically during tests
3. Screenshots will be captured for failed tests (if enabled)
4. Use \`analyze_ui_stability\` to review test results and UI changes`
}]
};
}
/**
* Analyze UI stability
*/
async analyzeUIStability(args) {
const { timeRange, includePerformance } = args;
const analysis = await this.visualValidationEngine.analyzeUIStability({
timeRange: timeRange || '1h',
includePerformance
});
let responseText = `๐ **UI Stability Analysis** (${timeRange || '1h'})
๐ฏ **Overall Stability Score**: ${analysis.stabilityScore}/100
๐ **Metrics**:
- **Screenshots Analyzed**: ${analysis.screenshotsAnalyzed}
- **Visual Changes Detected**: ${analysis.visualChanges}
- **Critical Issues**: ${analysis.criticalIssues}
- **Minor Issues**: ${analysis.minorIssues}
`;
if (includePerformance && analysis.performanceMetrics) {
responseText += `โก **Performance Metrics**:
- **Average Load Time**: ${analysis.performanceMetrics.avgLoadTime}ms
- **Performance Trend**: ${analysis.performanceMetrics.trend}
- **Memory Usage**: ${analysis.performanceMetrics.avgMemoryUsage}MB
`;
}
if (analysis.recommendations.length > 0) {
responseText += `๐ก **Recommendations**:\n`;
analysis.recommendations.forEach((rec) => {
responseText += `- ${rec}\n`;
});
}
const stabilityStatus = analysis.stabilityScore >= 90 ? '๐ข Excellent' :
analysis.stabilityScore >= 75 ? '๐ก Good' :
analysis.stabilityScore >= 60 ? '๐ Fair' : '๐ด Poor';
responseText += `\n**UI Stability Status**: ${stabilityStatus}`;
return {
content: [{
type: 'text',
text: responseText
}]
};
}
/**
* Set code quality gates
*/
async setCodeQualityGates(args) {
const { maxFileSize, minTestCoverage, enableSizeWarnings, blockOnFailure } = args;
// This would integrate with your existing file size and test coverage monitoring
const gates = {
maxFileSize: maxFileSize || 300,
minTestCoverage: minTestCoverage || 80,
enableSizeWarnings: enableSizeWarnings !== false,
blockOnFailure: blockOnFailure || false
};
return {
content: [{
type: 'text',
text: `โ๏ธ **Code Quality Gates Configured**
๐ **File Size Limit**: ${gates.maxFileSize} lines
๐ **Minimum Test Coverage**: ${gates.minTestCoverage}%
โ ๏ธ **Size Warnings**: ${gates.enableSizeWarnings ? 'Enabled' : 'Disabled'}
๐ซ **Block on Failure**: ${gates.blockOnFailure ? 'Enabled' : 'Disabled'}
โ
**Quality Gates Active**: Your development workflow will now enforce these quality standards.
**Integration Points**:
- File changes will be checked against size limits
- Test coverage will be monitored during development
- Visual validation will include quality gate checks
- ${gates.blockOnFailure ? 'Operations will be blocked if gates fail' : 'Warnings will be shown for gate failures'}`
}]
};
}
/**
* Get change impact analysis
*/
async getChangeImpactAnalysis(args) {
const { changeId, includeVisualDiff, includePerformanceImpact } = args;
const analysis = await this.fileChangeMonitor.getChangeImpactAnalysis({
changeId,
includeVisualDiff,
includePerformanceImpact
});
if (!analysis.change) {
return {
content: [{
type: 'text',
text: `โ No change found${changeId ? ` with ID '${changeId}'` : ' (no recent changes detected)'}.`
}]
};
}
let responseText = `๐ **Change Impact Analysis**
๐
**Change Time**: ${new Date(analysis.change.timestamp).toLocaleString()}
๐ **Files Modified**: ${analysis.change.files?.length || 1}
๐ง **Change Type**: ${analysis.change.type}
๐ **Impact Summary**:
- **UI Impact**: ${analysis.uiImpact}
- **Functionality Impact**: ${analysis.functionalityImpact}
- **Performance Impact**: ${analysis.performanceImpact}
`;
if (analysis.change.files && analysis.change.files.length > 0) {
responseText += `๐ **Modified Files**:\n`;
analysis.change.files.forEach((file) => {
responseText += `- \`${file.path}\` (${file.linesChanged} lines)\n`;
});
}
else {
responseText += `๐ **Modified File**: \`${analysis.change.path}\` (${analysis.change.linesChanged || 0} lines)\n`;
}
if (includeVisualDiff && analysis.visualDiff) {
responseText += `\n๐ธ **Visual Changes**:
- **Screenshots Compared**: ${analysis.visualDiff.screenshotsCompared}
- **Visual Similarity**: ${analysis.visualDiff.similarity}%
- **Changes Detected**: ${analysis.visualDiff.changesDetected}
`;
}
if (includePerformanceImpact && analysis.performanceAnalysis) {
responseText += `โก **Performance Analysis**:
- **Load Time Change**: ${analysis.performanceAnalysis.loadTimeChange}ms
- **Bundle Size Change**: ${analysis.performanceAnalysis.bundleSizeChange}KB
- **Memory Impact**: ${analysis.performanceAnalysis.memoryImpact}MB
`;
}
if (analysis.recommendations.length > 0) {
responseText += `๐ก **Recommendations**:\n`;
analysis.recommendations.forEach((rec) => {
responseText += `- ${rec}\n`;
});
}
return {
content: [{
type: 'text',
text: responseText
}]
};
}
}
export default CodeQualityIntegrationHandler;
//# sourceMappingURL=code-quality-integration-handler.js.map