UNPKG

ripbug-ai-detector

Version:

🔥 RipBug AI Bug Detector - Built by an AI that rips its own bugs. Destroy AI-generated bugs before you commit.

206 lines 8.73 kB
"use strict"; // Feature Flags for Gradual Tree-sitter Rollout // Following Claude S4's smart rollout strategy var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FeatureFlags = void 0; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); class FeatureFlags { static config = { treeSitterEnabled: true, treeSitterPercentage: 0.3, // 30% rollout for simple files complexityThreshold: 0.7, enableForTypeScript: true, enableForComplexFiles: true, debugMode: false }; // Main decision method - should we use tree-sitter for this file? static shouldUseTreeSitter(filePath) { if (!this.config.treeSitterEnabled) { return false; } try { // Always enable for TypeScript files (tree-sitter excels here) if (this.config.enableForTypeScript && this.isTypeScriptFile(filePath)) { if (this.config.debugMode) { console.log(`🌳 Tree-sitter enabled for TypeScript file: ${filePath}`); } return true; } // Enable for complex files first (where tree-sitter shines) if (this.config.enableForComplexFiles) { const complexity = this.assessFileComplexity(filePath); if (complexity > this.config.complexityThreshold) { if (this.config.debugMode) { console.log(`🌳 Tree-sitter enabled for complex file (${complexity.toFixed(2)}): ${filePath}`); } return true; } } // Random percentage rollout for remaining files const shouldEnable = Math.random() < this.config.treeSitterPercentage; if (this.config.debugMode && shouldEnable) { console.log(`🌳 Tree-sitter enabled via random rollout: ${filePath}`); } return shouldEnable; } catch (error) { if (this.config.debugMode) { console.warn(`⚠️ Error in feature flag decision for ${filePath}:`, error); } return false; } } // Assess file complexity using heuristics static assessFileComplexity(filePath) { try { const content = fs_1.default.readFileSync(filePath, 'utf8'); let score = 0; // Complex patterns increase score if (content.includes('interface ')) score += 0.2; if (content.includes('type ')) score += 0.15; if (content.includes('<') && content.includes('>')) score += 0.2; // Generics if (content.includes('destructur') || content.includes('...')) score += 0.2; if (content.includes('async ') || content.includes('await ')) score += 0.1; if (content.match(/\{[^}]{50,}\}/)) score += 0.3; // Complex objects if (content.includes('class ')) score += 0.15; if (content.includes('extends ') || content.includes('implements ')) score += 0.1; // File size factor const lines = content.split('\n').length; if (lines > 100) score += 0.1; if (lines > 300) score += 0.1; // Import complexity const importCount = (content.match(/import .* from/g) || []).length; if (importCount > 5) score += 0.1; if (importCount > 10) score += 0.1; return Math.min(score, 1.0); } catch (error) { return 0; // Default to simple if can't read file } } // Check if file is TypeScript static isTypeScriptFile(filePath) { return filePath.endsWith('.ts') || filePath.endsWith('.tsx'); } // Runtime configuration methods static setTreeSitterEnabled(enabled) { this.config.treeSitterEnabled = enabled; if (this.config.debugMode) { console.log(`🔧 Tree-sitter globally ${enabled ? 'enabled' : 'disabled'}`); } } static setTreeSitterPercentage(percentage) { this.config.treeSitterPercentage = Math.max(0, Math.min(1, percentage)); if (this.config.debugMode) { console.log(`🔧 Tree-sitter rollout percentage set to ${(percentage * 100).toFixed(1)}%`); } } static increaseTreeSitterPercentage(increment = 0.1) { const newPercentage = Math.min(1.0, this.config.treeSitterPercentage + increment); this.setTreeSitterPercentage(newPercentage); } static decreaseTreeSitterPercentage(decrement = 0.1) { const newPercentage = Math.max(0.0, this.config.treeSitterPercentage - decrement); this.setTreeSitterPercentage(newPercentage); } static setComplexityThreshold(threshold) { this.config.complexityThreshold = Math.max(0, Math.min(1, threshold)); if (this.config.debugMode) { console.log(`🔧 Complexity threshold set to ${threshold.toFixed(2)}`); } } static setDebugMode(enabled) { this.config.debugMode = enabled; console.log(`🔧 Feature flags debug mode ${enabled ? 'enabled' : 'disabled'}`); } // Get current configuration static getConfig() { return { ...this.config }; } // Get statistics for monitoring static getStats() { return { enabled: this.config.treeSitterEnabled, rolloutPercentage: this.config.treeSitterPercentage, complexityThreshold: this.config.complexityThreshold, typeScriptEnabled: this.config.enableForTypeScript, complexFilesEnabled: this.config.enableForComplexFiles }; } // Load configuration from file (for production deployment) static loadConfig(configPath) { try { const configFile = configPath || path_1.default.join(process.cwd(), '.ripbug-features.json'); if (fs_1.default.existsSync(configFile)) { const fileConfig = JSON.parse(fs_1.default.readFileSync(configFile, 'utf8')); this.config = { ...this.config, ...fileConfig }; if (this.config.debugMode) { console.log(`🔧 Feature flags loaded from ${configFile}:`, this.config); } } } catch (error) { if (this.config.debugMode) { console.warn('⚠️ Failed to load feature flag config:', error); } } } // Save current configuration to file static saveConfig(configPath) { try { const configFile = configPath || path_1.default.join(process.cwd(), '.ripbug-features.json'); fs_1.default.writeFileSync(configFile, JSON.stringify(this.config, null, 2)); if (this.config.debugMode) { console.log(`💾 Feature flags saved to ${configFile}`); } } catch (error) { if (this.config.debugMode) { console.warn('⚠️ Failed to save feature flag config:', error); } } } // Emergency rollback - disable tree-sitter immediately static emergencyRollback() { this.config.treeSitterEnabled = false; this.config.treeSitterPercentage = 0; console.warn('🚨 EMERGENCY ROLLBACK: Tree-sitter disabled'); // Save rollback state this.saveConfig(); } // Smart rollout based on success metrics static adjustRolloutBasedOnMetrics(successRate, errorRate) { if (successRate > 0.95 && errorRate < 0.02) { // High success, low errors - increase rollout this.increaseTreeSitterPercentage(0.1); if (this.config.debugMode) { console.log(`📈 Increasing tree-sitter rollout due to high success rate (${(successRate * 100).toFixed(1)}%)`); } } else if (successRate < 0.85 || errorRate > 0.05) { // Low success or high errors - decrease rollout this.decreaseTreeSitterPercentage(0.1); if (this.config.debugMode) { console.log(`📉 Decreasing tree-sitter rollout due to issues (success: ${(successRate * 100).toFixed(1)}%, errors: ${(errorRate * 100).toFixed(1)}%)`); } } } } exports.FeatureFlags = FeatureFlags; //# sourceMappingURL=feature-flags.js.map