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
357 lines (351 loc) • 16.4 kB
JavaScript
/**
* Serena Integration Handler
*
* Implements AI-Debug ↔ Serena workflow integration
* Enables seamless debug → analyze → fix → validate cycles
*/
import { SerenaIntegrationManager } from '../integrations/serena-integration-protocol.js';
import { writeFile, mkdir } from 'fs/promises';
export class SerenaIntegrationHandler {
tools = [
{
name: 'export_findings_for_serena',
description: 'Export current debugging session findings in Serena-compatible format for code analysis and fixes. Creates JSON export with debugging context, performance issues, accessibility violations, and recommended Serena commands.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID to export findings from'
},
exportPath: {
type: 'string',
description: 'Optional path to save export file (defaults to project root)',
default: './ai-debug-findings.json'
},
includeScreenshots: {
type: 'boolean',
description: 'Include screenshot evidence in export',
default: true
},
generateSerenaCommands: {
type: 'boolean',
description: 'Generate suggested Serena commands for common fixes',
default: true
}
},
required: ['sessionId']
}
},
{
name: 'create_cross_tool_session',
description: 'Create shared session context that both AI-Debug and Serena can reference. Enables seamless workflow transitions between runtime debugging and static code analysis.',
inputSchema: {
type: 'object',
properties: {
projectPath: {
type: 'string',
description: 'Path to project being debugged',
default: '.'
},
task: {
type: 'string',
description: 'Current development task description',
default: 'debugging_session'
},
framework: {
type: 'string',
description: 'Detected framework (auto-detected if not provided)'
}
}
}
},
{
name: 'generate_serena_workflow',
description: 'Generate recommended Serena commands based on AI-Debug findings. Provides optimized command sequences for code analysis, refactoring, and fixes.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID to analyze'
},
focusArea: {
type: 'string',
enum: ['performance', 'accessibility', 'errors', 'security', 'all'],
description: 'Focus analysis on specific issue type',
default: 'all'
}
},
required: ['sessionId']
}
},
{
name: 'claude_code_sub_agent_handoff',
description: 'Coordinate handoff between AI-Debug and Serena for Claude Code sub-agents. Provides intelligent workflow orchestration with automatic tool selection and context preservation.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Current AI-Debug session ID'
},
workflowType: {
type: 'string',
enum: ['debug-analyze', 'tdd-refactor', 'performance-optimize', 'accessibility-fix'],
description: 'Type of sub-agent workflow to initiate'
},
contextSummary: {
type: 'string',
description: 'Summary of current debugging context and goals'
},
nextPhase: {
type: 'string',
enum: ['static-analysis', 'code-fixing', 'validation', 'completion'],
description: 'Next phase in the workflow',
default: 'static-analysis'
}
},
required: ['sessionId', 'workflowType', 'contextSummary']
}
}
];
async handle(toolName, args, sessions) {
switch (toolName) {
case 'export_findings_for_serena':
return this.exportFindings(args, sessions);
case 'create_cross_tool_session':
return this.createCrossToolSession(args);
case 'generate_serena_workflow':
return this.generateSerenaWorkflow(args, sessions);
case 'claude_code_sub_agent_handoff':
return this.handleSubAgentHandoff(args, sessions);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
async exportFindings(args, sessions) {
const { sessionId, exportPath = './ai-debug-findings.json', includeScreenshots = true, generateSerenaCommands = true } = args;
// Get session data
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: `❌ **Session not found**: ${sessionId}\n\nPlease start a debugging session first with \`inject_debugging\`.`
}]
};
}
try {
// Gather findings from current session
const findings = await this.gatherSessionFindings(session, includeScreenshots);
// Create export data
const exportData = {
meta: {
exported_at: new Date().toISOString(),
ai_debug_version: '2.19.1',
session_id: sessionId,
project_path: process.cwd(),
total_findings: findings.length
},
session_context: await SerenaIntegrationManager.exportSessionContext(sessionId),
findings,
serena_commands: generateSerenaCommands ? SerenaIntegrationManager.generateSerenaWorkflow(findings) : []
};
// Ensure export directory exists
const exportDir = exportPath.substring(0, exportPath.lastIndexOf('/'));
if (exportDir && exportDir !== '.') {
await mkdir(exportDir, { recursive: true });
}
// Write export file
await writeFile(exportPath, JSON.stringify(exportData, null, 2));
return {
content: [{
type: 'text',
text: `🔄 **Findings Exported for Serena**\n\n**Export File**: \`${exportPath}\`\n**Findings**: ${findings.length} issues found\n**Serena Commands**: ${exportData.serena_commands.length} suggested\n\n**Next Steps**:\n1. Open project in Serena: \`serena activate "${process.cwd()}"\`\n2. Import findings context (planned feature)\n3. Run suggested commands to analyze and fix issues\n4. Return to AI-Debug to validate fixes\n\n**🎯 Complementary Workflow Active**`
}]
};
}
catch (error) {
return {
content: [{
type: 'text',
text: `❌ **Export Failed**: ${error?.message || 'Unknown error'}\n\nPlease check session status and try again.`
}]
};
}
}
async createCrossToolSession(args) {
const { projectPath = '.', task = 'debugging_session', framework } = args;
const sharedSessionId = SerenaIntegrationManager.generateSharedSessionId(projectPath);
const crossToolSession = {
id: sharedSessionId,
project_path: projectPath,
created_at: Date.now(),
updated_at: Date.now(),
serena_active: false,
framework: framework || 'auto-detect',
primary_language: 'typescript', // TODO: Auto-detect
active_files: [],
current_task: task
};
return {
content: [{
type: 'text',
text: `🔗 **Cross-Tool Session Created**\n\n**Session ID**: \`${sharedSessionId}\`\n**Project**: ${projectPath}\n**Task**: ${task}\n\n**Integration Ready**: Both AI-Debug and Serena can now reference this session for seamless workflow transitions.\n\n**Usage**:\n- Continue debugging with AI-Debug tools\n- Export findings when ready for code analysis\n- Switch to Serena for static analysis and fixes\n- Return to AI-Debug for validation`
}],
sessionId: sharedSessionId,
crossToolSession
};
}
async generateSerenaWorkflow(args, sessions) {
const { sessionId, focusArea = 'all' } = args;
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: `❌ **Session not found**: ${sessionId}`
}]
};
}
// Gather findings and filter by focus area
const allFindings = await this.gatherSessionFindings(session, false);
const findings = focusArea === 'all' ? allFindings : allFindings.filter(f => f.type === focusArea);
const commands = SerenaIntegrationManager.generateSerenaWorkflow(findings);
return {
content: [{
type: 'text',
text: `🎯 **Serena Workflow Generated**\n\n**Focus**: ${focusArea}\n**Findings**: ${findings.length} issues\n**Commands**: ${commands.length} suggested\n\n**Recommended Serena Commands**:\n\`\`\`bash\n${commands.join('\n')}\n\`\`\`\n\n**Workflow**:\n1. Run commands in Serena to analyze code patterns\n2. Apply suggested fixes and refactoring\n3. Return to AI-Debug to validate changes with \`inject_debugging\`\n4. Run performance/accessibility audits to confirm improvements`
}]
};
}
async gatherSessionFindings(session, includeScreenshots) {
const findings = [];
// Mock implementation - in real version, gather from actual session data
// This would integrate with existing audit results, console logs, performance metrics, etc.
// Example performance finding
if (session.auditResults?.performance) {
findings.push({
id: `perf_${Date.now()}`,
sessionId: session.id,
timestamp: Date.now(),
type: 'performance',
severity: 'medium',
title: 'Large Component Re-renders',
description: 'Component re-rendering too frequently, impacting performance',
location: {
component: 'UserComponent',
file: 'src/components/UserComponent.tsx',
line: 45
},
evidence: {
metrics: {
render_count: 23,
avg_render_time: 12.5
}
},
recommendations: {
action: 'refactor',
context: 'Add memoization to prevent unnecessary re-renders',
files_to_examine: ['src/components/UserComponent.tsx'],
search_patterns: ['useMemo', 'useCallback', 'React.memo']
}
});
}
// Example accessibility finding
if (session.auditResults?.accessibility) {
findings.push({
id: `a11y_${Date.now()}`,
sessionId: session.id,
timestamp: Date.now(),
type: 'accessibility',
severity: 'high',
title: 'Missing ARIA Labels',
description: 'Interactive elements lack proper accessibility labels',
location: {
selector: 'button.submit-btn',
component: 'FormComponent'
},
evidence: {},
recommendations: {
action: 'analyze_code',
context: 'Add aria-label or aria-labelledby attributes',
search_patterns: ['aria-', 'role=', 'alt=']
}
});
}
return findings;
}
async handleSubAgentHandoff(args, sessions) {
const { sessionId, workflowType, contextSummary, nextPhase } = args;
// Get session data
const session = sessions.get(sessionId);
if (!session) {
return {
content: [{
type: 'text',
text: `❌ **Session not found**: ${sessionId}\n\nPlease start a debugging session first with \`inject_debugging\`.`
}]
};
}
try {
// Generate handoff package based on workflow type
const handoffData = await this.generateHandoffPackage(session, workflowType, nextPhase);
// Create cross-tool session for coordination
const sharedSessionId = SerenaIntegrationManager.generateSharedSessionId(process.cwd());
const crossToolSession = { id: sharedSessionId };
return {
content: [{
type: 'text',
text: `🔄 **Sub-Agent Handoff Initiated**
**Workflow Type**: ${workflowType}
**Current Phase**: Debugging Complete → ${nextPhase}
**Session ID**: ${sessionId}
**Cross-Tool Session**: ${crossToolSession.id}
**Context Summary**: ${contextSummary}
**Handoff Package Prepared**:
- 📊 Session findings: ${handoffData.findingsCount} items
- 🖼️ Visual evidence: ${handoffData.screenshotsCount} screenshots
- 🔧 Recommended actions: ${handoffData.actionsCount} suggestions
- 📁 Export path: ./ai-debug-handoff-${sessionId}.json
**Ready for**: ${nextPhase === 'static-analysis' ? 'Serena code analysis' : nextPhase}
**Next Steps**:
1. AI-Debug findings exported for cross-tool usage
2. Shared session context established
3. Ready for seamless tool transition
Use the exported data with other MCP tools or continue with AI-Debug validation.`
}]
};
}
catch (error) {
return {
content: [{
type: 'text',
text: `❌ **Sub-Agent Handoff Failed**: ${error?.message || 'Unknown error'}\n\nPlease try again or check the session status.`
}]
};
}
}
async generateHandoffPackage(session, workflowType, nextPhase) {
// Gather findings specific to workflow type
const allFindings = await this.gatherSessionFindings(session, true);
// Filter findings based on workflow type
let relevantFindings = allFindings;
if (workflowType === 'performance-optimize') {
relevantFindings = allFindings.filter(f => f.type === 'performance');
}
else if (workflowType === 'accessibility-fix') {
relevantFindings = allFindings.filter(f => f.type === 'accessibility');
}
return {
findingsCount: relevantFindings.length,
screenshotsCount: relevantFindings.filter(f => f.evidence?.screenshot).length,
actionsCount: relevantFindings.filter(f => f.recommendations?.action).length,
workflowType,
nextPhase,
findings: relevantFindings
};
}
}
//# sourceMappingURL=serena-integration-handler.js.map