UX-agent / cli /lib /UXAnalyzer.js
AUXteam's picture
Deploying UX Analyst AI to Hugging Face (V2)
21cac8a verified
const AnalysisService = require('../../backend/services/analysisService');
const ScreenshotService = require('../../backend/services/screenshotService');
const AICritiqueService = require('../../backend/services/aiCritiqueService');
const VisualDesignAnalyzer = require('../../backend/services/visualDesignAnalyzer');
const CodeGenerationService = require('../../backend/services/codeGenerationService');
const { initializeDatabase } = require('../../backend/database/init');
class UXAnalyzer {
constructor(config) {
this.config = config;
this.services = null;
}
async initialize() {
if (this.services) return;
// Initialize database
await initializeDatabase();
// Initialize services
const screenshotService = new ScreenshotService(this.config);
const aiCritiqueService = new AICritiqueService(this.config);
const visualDesignAnalyzer = new VisualDesignAnalyzer();
const codeGenerationService = new CodeGenerationService({
geminiApiKey: this.config.ai.geminiApiKey,
logger: console
});
const analysisService = new AnalysisService({
screenshotService,
aiCritiqueService,
visualDesignAnalyzer,
codeGenerationService,
config: this.config
});
this.services = {
analysisService,
screenshotService,
aiCritiqueService,
visualDesignAnalyzer,
codeGenerationService
};
}
async analyze(url, options = {}, progressCallback = null) {
await this.initialize();
const defaultOptions = {
viewports: ['desktop', 'tablet', 'mobile'],
analysisType: 'comprehensive',
includeAccessibility: false,
includeCodeGeneration: true
};
const finalOptions = { ...defaultOptions, ...options };
// Start analysis
const analysisResult = await this.services.analysisService.analyzeWebsite(url, finalOptions);
const analysisId = analysisResult.analysisId;
// Poll for progress if callback provided
if (progressCallback) {
await this.monitorProgress(analysisId, progressCallback);
}
// Wait for completion and get results
const result = await this.waitForCompletion(analysisId);
return this.formatResult(result);
}
async monitorProgress(analysisId, callback) {
const checkProgress = async () => {
try {
const result = await this.services.analysisService.getAnalysisResult(analysisId);
if (result) {
callback({
percent: result.progress || 0,
stage: result.stage || 'Processing',
status: result.status
});
if (result.status === 'completed' || result.status === 'failed') {
return;
}
}
// Continue monitoring
setTimeout(checkProgress, 2000);
} catch (error) {
// Continue monitoring on error
setTimeout(checkProgress, 2000);
}
};
await checkProgress();
}
async waitForCompletion(analysisId, maxWaitTime = 300000) { // 5 minutes max
const startTime = Date.now();
return new Promise((resolve, reject) => {
const checkCompletion = async () => {
try {
const result = await this.services.analysisService.getAnalysisResult(analysisId);
if (result && result.status === 'completed') {
resolve(result);
return;
}
if (result && result.status === 'failed') {
reject(new Error(result.errorMessage || 'Analysis failed'));
return;
}
// Check timeout
if (Date.now() - startTime > maxWaitTime) {
reject(new Error('Analysis timeout'));
return;
}
// Continue waiting
setTimeout(checkCompletion, 2000);
} catch (error) {
reject(error);
}
};
checkCompletion();
});
}
formatResult(rawResult) {
const formatted = {
id: rawResult.id,
url: rawResult.url,
status: rawResult.status,
createdAt: rawResult.createdAt,
completedAt: rawResult.completedAt,
screenshots: rawResult.screenshots || [],
results: rawResult.results || {}
};
// Extract key results for easier CLI access
if (rawResult.results) {
formatted.accessibility = rawResult.results.accessibility;
formatted.uxCritique = rawResult.results.ux_critique;
formatted.report = rawResult.results.final_report;
formatted.implementationCode = rawResult.results.implementation_code;
}
return formatted;
}
async cleanup() {
if (this.services?.screenshotService) {
// Close any open browsers
await this.services.screenshotService.cleanup?.();
}
}
}
module.exports = UXAnalyzer;