zai-mcp-server
Version:
🚀 REVOLUTIONARY AI-to-AI Collaboration Platform v6.1! NEW: Advanced Debugging Tools with Screenshot Analysis, Console Error Parsing, Automated Fix Generation, 5 Specialized Debugging Agents, Visual UI Analysis, JavaScript Error Intelligence, CSS/HTML Fix
574 lines (498 loc) • 19.8 kB
JavaScript
/**
* Android Fix Generator - Generates Android-specific code fixes
* Creates XML layout fixes, Kotlin/Java code fixes, and Material Design improvements
*/
export class AndroidFixGenerator {
constructor(multiProviderAI) {
this.multiProviderAI = multiProviderAI;
this.androidFixTemplates = new Map();
this.materialDesignTemplates = new Map();
this.accessibilityTemplates = new Map();
this.initializeAndroidFixTemplates();
console.log('🔧 Android Fix Generator initialized with mobile-specific templates');
}
/**
* Initialize Android-specific fix templates
*/
initializeAndroidFixTemplates() {
// Layout fix templates
this.androidFixTemplates.set('touch_target_small', {
type: 'xml',
template: (context) => `
<!-- Fix: Increase touch target size to meet accessibility guidelines -->
<${context.viewType}
android:layout_width="${Math.max(context.currentWidth, 48)}dp"
android:layout_height="${Math.max(context.currentHeight, 48)}dp"
android:minWidth="48dp"
android:minHeight="48dp"
${context.existingAttributes} />`,
description: 'Increase touch target size to minimum 48dp',
confidence: 95
});
this.androidFixTemplates.set('missing_content_description', {
type: 'xml',
template: (context) => `
<!-- Fix: Add content description for accessibility -->
<${context.viewType}
android:contentDescription="${context.suggestedDescription}"
${context.existingAttributes} />`,
description: 'Add content description for screen reader accessibility',
confidence: 90
});
this.androidFixTemplates.set('color_contrast_low', {
type: 'xml',
template: (context) => `
<!-- Fix: Improve color contrast for accessibility -->
<${context.viewType}
android:textColor="${context.improvedTextColor}"
android:background="${context.improvedBackgroundColor}"
${context.existingAttributes} />`,
description: 'Improve color contrast to meet WCAG guidelines',
confidence: 85
});
this.androidFixTemplates.set('spacing_inconsistent', {
type: 'xml',
template: (context) => `
<!-- Fix: Apply consistent 8dp baseline grid spacing -->
<${context.viewType}
android:layout_margin="${context.baselineSpacing}dp"
android:padding="${context.baselinePadding}dp"
${context.existingAttributes} />`,
description: 'Apply Material Design 8dp baseline grid',
confidence: 88
});
this.androidFixTemplates.set('layout_complex', {
type: 'xml',
template: (context) => `
<!-- Fix: Flatten layout hierarchy using ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
${context.optimizedChildViews}
</androidx.constraintlayout.widget.ConstraintLayout>`,
description: 'Optimize layout hierarchy with ConstraintLayout',
confidence: 80
});
// Kotlin/Java fix templates
this.androidFixTemplates.set('memory_leak', {
type: 'kotlin',
template: (context) => `
// Fix: Prevent memory leak by using WeakReference
class ${context.className} {
private var ${context.variableName}: WeakReference<${context.type}>? = null
fun set${context.capitalizedName}(${context.paramName}: ${context.type}) {
this.${context.variableName} = WeakReference(${context.paramName})
}
fun get${context.capitalizedName}(): ${context.type}? {
return ${context.variableName}?.get()
}
}`,
description: 'Fix memory leak using WeakReference',
confidence: 85
});
this.androidFixTemplates.set('network_error_handling', {
type: 'kotlin',
template: (context) => `
// Fix: Add proper network error handling
suspend fun ${context.functionName}(): Result<${context.returnType}> {
return try {
val response = ${context.networkCall}
if (response.isSuccessful) {
Result.success(response.body()!!)
} else {
Result.failure(HttpException(response))
}
} catch (e: IOException) {
Result.failure(NetworkException("Network connection failed", e))
} catch (e: Exception) {
Result.failure(UnknownException("Unexpected error", e))
}
}`,
description: 'Add comprehensive network error handling',
confidence: 90
});
this.androidFixTemplates.set('ui_thread_violation', {
type: 'kotlin',
template: (context) => `
// Fix: Move network operation off UI thread
class ${context.className} {
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
fun ${context.functionName}() {
scope.launch {
try {
val result = withContext(Dispatchers.IO) {
${context.networkOperation}
}
// Update UI on main thread
${context.uiUpdate}
} catch (e: Exception) {
handleError(e)
}
}
}
private fun handleError(error: Exception) {
// Show error message to user
Log.e("${context.className}", "Operation failed", error)
}
}`,
description: 'Move network operations to background thread',
confidence: 92
});
// Material Design fix templates
this.materialDesignTemplates.set('elevation_excessive', {
type: 'xml',
template: (context) => `
<!-- Fix: Reduce elevation to Material Design recommendations -->
<${context.viewType}
android:elevation="${Math.min(context.currentElevation, 24)}dp"
${context.existingAttributes} />`,
description: 'Reduce elevation to maximum 24dp',
confidence: 95
});
this.materialDesignTemplates.set('typography_non_standard', {
type: 'xml',
template: (context) => `
<!-- Fix: Use Material Design typography scale -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearance${context.materialTextStyle}"
android:textSize="${context.materialTextSize}sp"
${context.existingAttributes} />`,
description: 'Apply Material Design typography scale',
confidence: 88
});
// Accessibility fix templates
this.accessibilityTemplates.set('focus_order_illogical', {
type: 'xml',
template: (context) => `
<!-- Fix: Improve focus order for accessibility -->
<${context.viewType}
android:nextFocusDown="@id/${context.nextFocusDown}"
android:nextFocusUp="@id/${context.nextFocusUp}"
android:nextFocusLeft="@id/${context.nextFocusLeft}"
android:nextFocusRight="@id/${context.nextFocusRight}"
${context.existingAttributes} />`,
description: 'Define logical focus order for keyboard navigation',
confidence: 85
});
}
/**
* Generate Android-specific fix for an issue
*/
async generateAndroidFix(issue, deviceInfo, options = {}) {
console.log(`🔧 Generating Android fix for: ${issue.type}`);
try {
// Determine fix approach
const fixApproach = this.determineAndroidFixApproach(issue);
let fix;
if (fixApproach.useTemplate) {
fix = await this.generateTemplatedAndroidFix(issue, fixApproach, deviceInfo, options);
} else {
fix = await this.generateAIAndroidFix(issue, deviceInfo, options);
}
if (!fix) {
console.log(`⚠️ No Android fix generated for issue: ${issue.type}`);
return null;
}
// Add Android-specific metadata
fix.platform = 'android';
fix.deviceInfo = deviceInfo;
fix.materialDesignCompliant = this.checkMaterialDesignCompliance(fix);
fix.accessibilityImproved = this.checkAccessibilityImprovement(fix, issue);
// Validate Android fix
const validation = this.validateAndroidFix(fix, options);
if (!validation.valid) {
console.log(`❌ Android fix validation failed: ${validation.errors.join(', ')}`);
return null;
}
console.log(`✅ Android fix generated successfully`);
return fix;
} catch (error) {
console.error(`❌ Android fix generation failed for ${issue.type}:`, error.message);
return null;
}
}
/**
* Determine Android fix approach
*/
determineAndroidFixApproach(issue) {
// Check Android-specific templates first
if (this.androidFixTemplates.has(issue.type)) {
return {
useTemplate: true,
templateKey: issue.type,
templateSource: 'android',
confidence: 0.9
};
}
// Check Material Design templates
if (this.materialDesignTemplates.has(issue.type)) {
return {
useTemplate: true,
templateKey: issue.type,
templateSource: 'material',
confidence: 0.85
};
}
// Check accessibility templates
if (this.accessibilityTemplates.has(issue.type)) {
return {
useTemplate: true,
templateKey: issue.type,
templateSource: 'accessibility',
confidence: 0.88
};
}
// Use AI for complex Android fixes
return {
useTemplate: false,
requiresAI: true,
confidence: 0.7
};
}
/**
* Generate fix using Android templates
*/
async generateTemplatedAndroidFix(issue, fixApproach, deviceInfo, options) {
let template;
// Get template from appropriate source
switch (fixApproach.templateSource) {
case 'android':
template = this.androidFixTemplates.get(fixApproach.templateKey);
break;
case 'material':
template = this.materialDesignTemplates.get(fixApproach.templateKey);
break;
case 'accessibility':
template = this.accessibilityTemplates.get(fixApproach.templateKey);
break;
default:
throw new Error(`Unknown template source: ${fixApproach.templateSource}`);
}
if (!template) {
throw new Error(`Template not found: ${fixApproach.templateKey}`);
}
// Extract Android-specific context
const context = this.extractAndroidContext(issue, template.type, deviceInfo);
// Generate code from template
const code = template.template(context);
return {
id: `android_fix_${issue.id}_${Date.now()}`,
issueId: issue.id,
issueType: issue.type,
type: template.type,
approach: 'template',
code: code.trim(),
description: template.description,
confidence: template.confidence,
context,
generated: Date.now(),
platform: 'android'
};
}
/**
* Generate fix using AI for Android
*/
async generateAIAndroidFix(issue, deviceInfo, options) {
const prompt = this.buildAndroidFixPrompt(issue, deviceInfo, options);
const response = await this.multiProviderAI.generateResponse(prompt, {
maxTokens: 600,
temperature: 0.1
});
const parsedFix = this.parseAndroidFixResponse(response, issue);
return {
id: `android_fix_${issue.id}_${Date.now()}`,
issueId: issue.id,
issueType: issue.type,
type: parsedFix.type,
approach: 'ai_generated',
code: parsedFix.code,
description: parsedFix.description,
confidence: 75,
context: parsedFix.context,
generated: Date.now(),
platform: 'android'
};
}
/**
* Build prompt for Android AI fix generation
*/
buildAndroidFixPrompt(issue, deviceInfo, options) {
let prompt = `Generate an Android-specific code fix for this mobile app issue:\n\n`;
prompt += `Issue Type: ${issue.type}\n`;
prompt += `Description: ${issue.description}\n`;
prompt += `Severity: ${issue.severity}\n`;
prompt += `Category: ${issue.category}\n\n`;
prompt += `Device Information:\n`;
prompt += `- Model: ${deviceInfo.model}\n`;
prompt += `- Android Version: ${deviceInfo.version}\n`;
prompt += `- SDK Level: ${deviceInfo.sdk}\n\n`;
if (issue.location) {
prompt += `UI Location: x=${issue.location.x}, y=${issue.location.y}, `;
prompt += `width=${issue.location.width}, height=${issue.location.height}\n\n`;
}
prompt += `Requirements:\n`;
prompt += `1. Provide Android-specific code (XML layout, Kotlin, or Java)\n`;
prompt += `2. Follow Material Design guidelines\n`;
prompt += `3. Ensure accessibility compliance\n`;
prompt += `4. Include proper comments explaining the fix\n`;
prompt += `5. Consider mobile performance implications\n\n`;
prompt += `Format the response as:\n`;
prompt += `TYPE: [xml|kotlin|java|gradle]\n`;
prompt += `DESCRIPTION: [brief description]\n`;
prompt += `CODE:\n[actual Android fix code]\n`;
return prompt;
}
/**
* Parse Android AI fix response
*/
parseAndroidFixResponse(response, issue) {
const lines = response.split('\n');
let type = 'xml';
let description = 'AI-generated Android fix';
let code = '';
let inCodeSection = false;
for (const line of lines) {
if (line.startsWith('TYPE:')) {
type = line.replace('TYPE:', '').trim().toLowerCase();
} else if (line.startsWith('DESCRIPTION:')) {
description = line.replace('DESCRIPTION:', '').trim();
} else if (line.startsWith('CODE:')) {
inCodeSection = true;
} else if (inCodeSection) {
code += line + '\n';
}
}
return {
type,
description,
code: code.trim(),
context: { originalIssue: issue }
};
}
/**
* Extract Android-specific context for fix generation
*/
extractAndroidContext(issue, fixType, deviceInfo) {
const context = {
deviceInfo,
viewType: this.extractViewType(issue),
existingAttributes: this.extractExistingAttributes(issue),
baselineSpacing: 8, // Material Design baseline
baselinePadding: 16
};
// Type-specific context extraction
if (fixType === 'xml') {
context.currentWidth = issue.location?.width || 48;
context.currentHeight = issue.location?.height || 48;
context.suggestedDescription = this.generateContentDescription(issue);
context.improvedTextColor = this.suggestAccessibleTextColor(issue);
context.improvedBackgroundColor = this.suggestAccessibleBackgroundColor(issue);
} else if (fixType === 'kotlin' || fixType === 'java') {
context.className = this.extractClassName(issue);
context.functionName = this.extractFunctionName(issue);
context.variableName = this.extractVariableName(issue);
context.networkCall = this.extractNetworkCall(issue);
context.returnType = this.extractReturnType(issue);
}
return context;
}
/**
* Validate Android fix
*/
validateAndroidFix(fix, options) {
const errors = [];
const warnings = [];
// Android-specific validation
if (fix.type === 'xml') {
const xmlValidation = this.validateAndroidXML(fix.code);
if (!xmlValidation.valid) {
errors.push(`XML validation: ${xmlValidation.message}`);
}
} else if (fix.type === 'kotlin') {
const kotlinValidation = this.validateKotlinSyntax(fix.code);
if (!kotlinValidation.valid) {
errors.push(`Kotlin validation: ${kotlinValidation.message}`);
}
}
// Material Design compliance check
if (!this.checkMaterialDesignCompliance(fix)) {
warnings.push('Fix may not fully comply with Material Design guidelines');
}
return {
valid: errors.length === 0,
errors,
warnings
};
}
// Helper methods for context extraction
extractViewType(issue) {
const typeMap = {
'touch_target_small': 'Button',
'missing_content_description': 'ImageView',
'color_contrast_low': 'TextView',
'spacing_inconsistent': 'View'
};
return typeMap[issue.type] || 'View';
}
extractExistingAttributes(issue) {
return 'android:layout_width="wrap_content"\n android:layout_height="wrap_content"';
}
generateContentDescription(issue) {
const descriptions = {
'missing_content_description': 'Button to perform action',
'touch_target_small': 'Interactive element'
};
return descriptions[issue.type] || 'UI element';
}
suggestAccessibleTextColor(issue) {
return '@color/material_on_surface_emphasis_high_type';
}
suggestAccessibleBackgroundColor(issue) {
return '@color/material_surface';
}
extractClassName(issue) {
return 'MainActivity';
}
extractFunctionName(issue) {
return 'performNetworkOperation';
}
extractVariableName(issue) {
return 'activityRef';
}
extractNetworkCall(issue) {
return 'apiService.getData()';
}
extractReturnType(issue) {
return 'ApiResponse';
}
// Validation methods
validateAndroidXML(code) {
// Basic XML validation
const openTags = (code.match(/</g) || []).length;
const closeTags = (code.match(/>/g) || []).length;
if (openTags !== closeTags) {
return { valid: false, message: 'Unmatched XML tags' };
}
return { valid: true };
}
validateKotlinSyntax(code) {
// Basic Kotlin syntax validation
const braceCount = (code.match(/{/g) || []).length - (code.match(/}/g) || []).length;
if (braceCount !== 0) {
return { valid: false, message: 'Unmatched braces in Kotlin code' };
}
return { valid: true };
}
checkMaterialDesignCompliance(fix) {
// Check if fix follows Material Design principles
const materialKeywords = ['material', 'dp', 'sp', 'elevation', 'textAppearance'];
return materialKeywords.some(keyword => fix.code.toLowerCase().includes(keyword));
}
checkAccessibilityImprovement(fix, issue) {
// Check if fix improves accessibility
const accessibilityKeywords = ['contentDescription', 'minWidth', 'minHeight', 'nextFocus'];
return accessibilityKeywords.some(keyword => fix.code.includes(keyword));
}
}