ripple-ai-detector
Version:
🌊 Ripple AI Bug Detector - Built by an AI that knows its flaws. Catch AI-generated bugs before you commit.
206 lines • 8.73 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputFormatter = void 0;
const logger_1 = require("../utils/logger");
const chalk_1 = __importDefault(require("chalk"));
const path_1 = __importDefault(require("path"));
class OutputFormatter {
format;
constructor(format = 'console') {
this.format = format;
}
// Main method to display results
async displayResults(results) {
if (this.format === 'json') {
this.displayJSON(results);
}
else {
this.displayConsole(results);
}
}
// Display results in beautiful console format
displayConsole(results) {
// AI Detection Header
if (results.aiGenerated) {
logger_1.logger.newLine();
logger_1.logger.aiDetected('AI-generated changes detected', Math.round(results.confidence * 100));
logger_1.logger.newLine();
}
// Display issues
if (results.issues.length > 0) {
this.displayIssues(results.issues);
}
else {
logger_1.logger.success('No issues detected');
if (!results.aiGenerated) {
logger_1.logger.info('AI Detection: Low confidence - likely human-written code');
}
}
// Display summary
this.displaySummary(results);
// Display recommendations
this.displayRecommendations(results);
}
// Display issues in console
displayIssues(issues) {
logger_1.logger.info('Issues found:');
logger_1.logger.newLine();
const errors = issues.filter(i => i.severity === 'error');
const warnings = issues.filter(i => i.severity === 'warning');
// Display errors first
for (const issue of errors) {
this.displayIssue(issue);
logger_1.logger.newLine();
}
// Then warnings
for (const issue of warnings) {
this.displayIssue(issue);
logger_1.logger.newLine();
}
}
// Display individual issue
displayIssue(issue) {
const icon = issue.severity === 'error' ? '❌' : '⚠️';
const color = issue.severity === 'error' ? 'red' : 'yellow';
// Main issue message
console.log(chalk_1.default[color](`${icon} ${issue.message}`));
// File location
const relativePath = path_1.default.relative(process.cwd(), issue.file);
const location = issue.line ? `${relativePath}:${issue.line}` : relativePath;
console.log(chalk_1.default.gray(` File: ${location}`));
// Issue-specific details
this.displayIssueDetails(issue);
// Affected files (for function signature changes)
if (issue.details.affectedFiles && issue.details.affectedFiles.length > 0) {
console.log(chalk_1.default.red(' 💥 This will break:'));
for (const affected of issue.details.affectedFiles) {
const affectedPath = path_1.default.relative(process.cwd(), affected.path);
console.log(chalk_1.default.red(` - ${affectedPath}:${affected.line}`));
}
}
// Suggestions
if (issue.suggestions && issue.suggestions.length > 0) {
console.log(chalk_1.default.cyan(' 💡 Suggestions:'));
for (const suggestion of issue.suggestions) {
console.log(chalk_1.default.cyan(` • ${suggestion}`));
}
}
// Confidence score
if (issue.confidence > 0) {
const confidencePercent = Math.round(issue.confidence * 100);
const confidenceColor = issue.confidence > 0.8 ? 'green' : issue.confidence > 0.6 ? 'yellow' : 'red';
console.log(chalk_1.default[confidenceColor](` Confidence: ${confidencePercent}%`));
}
}
// Display issue-specific details
displayIssueDetails(issue) {
switch (issue.type) {
case 'function-signature-change':
if (issue.details.oldSignature && issue.details.newSignature) {
console.log(chalk_1.default.gray(` Function: ${issue.details.oldSignature} → ${issue.details.newSignature}`));
}
break;
case 'import-export-mismatch':
if (issue.details.importName && issue.details.exportName) {
console.log(chalk_1.default.gray(` Import: '${issue.details.importName}' not found`));
if (issue.details.availableExports) {
console.log(chalk_1.default.gray(` Available: ${issue.details.availableExports.join(', ')}`));
}
}
break;
case 'ai-pattern-detected':
if (issue.details.aiPatterns) {
console.log(chalk_1.default.magenta(` 🤖 AI Patterns: ${issue.details.aiPatterns.join(', ')}`));
}
break;
}
}
// Display summary
displaySummary(results) {
logger_1.logger.newLine();
logger_1.logger.separator();
const { errors, warnings, filesAnalyzed, timeMs } = results.summary;
// Summary line
const summaryParts = [];
if (errors > 0)
summaryParts.push(chalk_1.default.red(`${errors} error${errors !== 1 ? 's' : ''}`));
if (warnings > 0)
summaryParts.push(chalk_1.default.yellow(`${warnings} warning${warnings !== 1 ? 's' : ''}`));
if (summaryParts.length > 0) {
console.log(`Summary: ${summaryParts.join(', ')}`);
}
else {
logger_1.logger.success('Summary: No issues found');
}
// Analysis details
console.log(chalk_1.default.gray(`Files analyzed: ${filesAnalyzed}`));
console.log(chalk_1.default.gray(`Analysis time: ${timeMs}ms`));
if (results.confidence > 0) {
const confidencePercent = Math.round(results.confidence * 100);
console.log(chalk_1.default.gray(`Confidence: ${confidencePercent}% this analysis is accurate`));
}
}
// Display recommendations
displayRecommendations(results) {
logger_1.logger.newLine();
if (results.aiGenerated) {
logger_1.logger.tip('Recommendation: Review AI-generated changes carefully before committing');
}
if (results.issues.some(i => i.severity === 'error')) {
logger_1.logger.error('❌ Not safe to commit - fix errors first');
}
else if (results.issues.some(i => i.severity === 'warning')) {
logger_1.logger.warning('⚠️ Safe to commit, but consider fixing warnings');
}
else {
logger_1.logger.success('✅ Safe to commit');
}
}
// Display results in JSON format
displayJSON(results) {
const jsonOutput = {
success: results.success,
confidence: results.confidence,
aiGenerated: results.aiGenerated,
summary: results.summary,
issues: results.issues.map(issue => ({
id: issue.id,
type: issue.type,
severity: issue.severity,
message: issue.message,
file: issue.file,
line: issue.line,
column: issue.column,
details: issue.details,
suggestions: issue.suggestions,
confidence: issue.confidence
})),
metadata: results.metadata
};
console.log(JSON.stringify(jsonOutput, null, 2));
}
// Create upgrade prompt message
static createUpgradePrompt(current, limit) {
const remaining = limit - current;
if (remaining <= 0) {
return '🚀 Upgrade to Pro for unlimited validations: ripple.dev/pro';
}
if (remaining <= 2) {
return `⚠️ Only ${remaining} validations left this month. Upgrade: ripple.dev/pro`;
}
return `💡 ${remaining} validations remaining. Get unlimited: ripple.dev/pro`;
}
// Create value proposition message
static createValueMessage(validationsUsed) {
const hoursPerBug = 2;
const hoursSaved = validationsUsed * hoursPerBug;
const hourlyRate = 75;
const valueSaved = hoursSaved * hourlyRate;
return `💰 This month: ${validationsUsed} validations = ~${hoursSaved} hours saved = ~$${valueSaved} value!`;
}
}
exports.OutputFormatter = OutputFormatter;
//# sourceMappingURL=formatter.js.map