recoder-code 2.2.1 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,6 +25,7 @@ const TaskManager = require('./task-manager.js');
25
25
  const DevToolsIntegration = require('./dev-tools-integration.js');
26
26
  const VisionAnalyzer = require('./vision-analyzer.js');
27
27
  const NaturalLanguageProcessor = require('./natural-language-processor.js');
28
+ const TodoManager = require('./todo-manager.js');
28
29
 
29
30
  // Create logs and sessions directories
30
31
  const logsDir = path.join(process.cwd(), 'logs');
@@ -35,10 +36,17 @@ const sessionsDir = path.join(process.cwd(), 'sessions');
35
36
  }
36
37
  });
37
38
 
39
+ // Initialize unified error handling for interactive mode
40
+ const UnifiedErrorHandler = require('./unified-error-handler.js');
41
+ const errorHandler = UnifiedErrorHandler.instance;
42
+ errorHandler.initialize();
43
+
38
44
  class InteractiveRecoderChat {
39
45
  constructor() {
40
- this.apiKey = config.apiKey;
41
- this.model = config.model;
46
+ // Load user configuration
47
+ this.userConfig = this.loadUserConfig();
48
+ this.apiKey = this.userConfig.apiKey || config.apiKey;
49
+ this.model = this.userConfig.model || config.model;
42
50
  this.maxTokens = config.maxTokens;
43
51
  this.temperature = config.temperature;
44
52
 
@@ -106,6 +114,12 @@ class InteractiveRecoderChat {
106
114
  sessionId: this.sessionId
107
115
  });
108
116
 
117
+ // Initialize todo manager for production-ready task tracking
118
+ this.todoManager = new TodoManager({ user: process.env.USER || 'developer' });
119
+
120
+ // Add comprehensive promise rejection handling
121
+ this.setupGlobalErrorHandlers();
122
+
109
123
  // Initialize advanced systems
110
124
  this.contextEngine = null;
111
125
  this.slashCommands = null;
@@ -152,7 +166,11 @@ class InteractiveRecoderChat {
152
166
 
153
167
  // Initialize context engine for codebase understanding
154
168
  this.contextEngine = new ContextEngine();
155
- await this.contextEngine.initialize();
169
+ try {
170
+ await this.contextEngine.initialize();
171
+ } catch (contextError) {
172
+ console.log(chalk.yellow(`⚠️ Context engine initialization failed: ${contextError.message}`));
173
+ }
156
174
 
157
175
  // Initialize MCP client for model communication
158
176
  this.mcpClient = new MCPClient();
@@ -162,30 +180,46 @@ class InteractiveRecoderChat {
162
180
 
163
181
  // Initialize rules engine with project context
164
182
  this.rulesEngine = new RulesEngine(this.projectManager);
165
- await this.rulesEngine.autoDiscoverProjectRules();
183
+ try {
184
+ await this.rulesEngine.autoDiscoverProjectRules();
185
+ } catch (rulesError) {
186
+ console.log(chalk.yellow(`⚠️ Rules engine initialization failed: ${rulesError.message}`));
187
+ }
166
188
 
167
189
  // Initialize task manager with full integration
168
190
  this.taskManager = new TaskManager(this.projectManager, this.contextEngine, this.rulesEngine);
169
- this.taskManager.setupSmartAutomationTriggers();
191
+ try {
192
+ this.taskManager.setupSmartAutomationTriggers();
193
+ } catch (automationError) {
194
+ console.log(chalk.yellow(`⚠️ Automation setup failed: ${automationError.message}`));
195
+ }
170
196
 
171
197
  // Initialize development tools integration
172
198
  this.devTools = new DevToolsIntegration(this.contextEngine, this.projectManager, this.taskManager);
173
- await this.devTools.setupIDEIntegration();
174
- await this.devTools.setupGitIntegration();
175
- await this.devTools.setupDatabaseIntegration();
176
- await this.devTools.setupPerformanceMonitoring();
199
+ try {
200
+ await this.devTools.setupIDEIntegration();
201
+ await this.devTools.setupGitIntegration();
202
+ await this.devTools.setupDatabaseIntegration();
203
+ await this.devTools.setupPerformanceMonitoring();
204
+ } catch (devToolsError) {
205
+ console.log(chalk.yellow(`⚠️ Dev tools setup failed: ${devToolsError.message}`));
206
+ }
177
207
 
178
208
  // Initialize vision analyzer with model manager and context engine
179
209
  this.visionAnalyzer = new VisionAnalyzer(this.modelManager, this.contextEngine);
180
210
 
181
- // Initialize slash commands system with all dependencies including vision analyzer
182
- this.slashCommands = new SlashCommandsEngine(this.contextEngine, this.projectManager, this.visionAnalyzer);
211
+ // Initialize slash commands system with all dependencies including vision analyzer and todo manager
212
+ this.slashCommands = new SlashCommandsEngine(this.contextEngine, this.projectManager, this.visionAnalyzer, this.todoManager);
183
213
 
184
214
  // Initialize natural language processor with access to all systems
185
215
  this.nlProcessor = new NaturalLanguageProcessor(this);
186
216
 
187
217
  // Set up system integrations
188
- await this.setupSystemIntegrations();
218
+ try {
219
+ await this.setupSystemIntegrations();
220
+ } catch (integrationError) {
221
+ console.log(chalk.yellow(`⚠️ System integrations setup failed: ${integrationError.message}`));
222
+ }
189
223
 
190
224
  // Enable auto model switching based on context
191
225
  this.enableIntelligentModelSwitching();
@@ -1182,32 +1216,100 @@ class InteractiveRecoderChat {
1182
1216
  displayWelcome() {
1183
1217
  console.clear();
1184
1218
 
1185
- // Beautiful welcome screen with neon purple/white/gray theme
1186
- console.log('');
1187
- console.log(chalk.magenta('╭─────────────────────────────────────────────────────────────╮'));
1188
- console.log(chalk.magenta('│') + chalk.white.bold(' ✨ Welcome to Recoder Code ') + chalk.magenta('│'));
1189
- console.log(chalk.magenta('╰─────────────────────────────────────────────────────────────╯'));
1219
+ // Enhanced welcome screen with gradient effects and animations
1190
1220
  console.log('');
1191
1221
 
1192
- // Stylized ASCII art in neon purple
1193
- console.log(chalk.magenta.bold('██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗'));
1194
- console.log(chalk.magenta.bold('██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗'));
1195
- console.log(chalk.magenta.bold('██████╔╝█████╗ ██║ ██║ ██║██║ ██║█████╗ ██████╔╝'));
1196
- console.log(chalk.white('██╔══██╗██╔══╝ ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗'));
1197
- console.log(chalk.white('██║ ██║███████╗╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║'));
1198
- console.log(chalk.gray('╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
1222
+ // Animated gradient border
1223
+ this.displayAnimatedBorder();
1224
+
1225
+ // Beautiful gradient ASCII art
1226
+ console.log('');
1227
+ this.displayGradientLogo();
1199
1228
  console.log('');
1200
1229
 
1201
- // Status line
1202
- console.log(chalk.gray('Press Enter to continue'));
1230
+ // Dynamic status information
1231
+ this.displayDynamicStatus();
1203
1232
  console.log('');
1204
1233
 
1205
- // Add bottom status hints like Claude Code
1206
- this.showStatusHints();
1234
+ // Enhanced status hints with themes
1235
+ this.showEnhancedStatusHints();
1207
1236
 
1208
1237
  this.rl.prompt();
1209
1238
  }
1210
1239
 
1240
+ displayAnimatedBorder() {
1241
+ const colors = ['magenta', 'cyan', 'blue', 'magenta'];
1242
+ const border = '╭─────────────────────────────────────────────────────────────╮';
1243
+ const title = '│ ✨ Welcome to Recoder Code - AI Terminal │';
1244
+ const bottom = '╰─────────────────────────────────────────────────────────────╯';
1245
+
1246
+ console.log(chalk[colors[0]](border));
1247
+ console.log(chalk[colors[1]](title));
1248
+ console.log(chalk[colors[2]](bottom));
1249
+ }
1250
+
1251
+ displayGradientLogo() {
1252
+ // Beautiful gradient ASCII art with purple to cyan transition
1253
+ const lines = [
1254
+ '██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗',
1255
+ '██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗',
1256
+ '██████╔╝█████╗ ██║ ██║ ██║██║ ██║█████╗ ██████╔╝',
1257
+ '██╔══██╗██╔══╝ ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗',
1258
+ '██║ ██║███████╗╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║',
1259
+ '╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'
1260
+ ];
1261
+
1262
+ const gradientColors = ['magenta', 'magenta', 'cyan', 'blue', 'blue', 'gray'];
1263
+
1264
+ lines.forEach((line, index) => {
1265
+ console.log(chalk[gradientColors[index]].bold(line));
1266
+ });
1267
+ }
1268
+
1269
+ displayDynamicStatus() {
1270
+ const currentTime = new Date().toLocaleTimeString();
1271
+ const projectContext = this.getCurrentProjectContext();
1272
+
1273
+ console.log(chalk.gray('┌─ Session Info ─────────────────────────────────────────────┐'));
1274
+ console.log(chalk.gray('│') + chalk.white(` 🕐 Started: ${currentTime}`) +
1275
+ chalk.gray(' │'));
1276
+ console.log(chalk.gray('│') + chalk.cyan(` 📁 Project: ${projectContext.name || 'recoder-code'}`) +
1277
+ chalk.gray(' │'));
1278
+ console.log(chalk.gray('│') + chalk.green(` 🤖 Model: ${this.model || 'claude-sonnet-4'}`) +
1279
+ chalk.gray(' │'));
1280
+ console.log(chalk.gray('└────────────────────────────────────────────────────────────┘'));
1281
+ }
1282
+
1283
+ getCurrentProjectContext() {
1284
+ try {
1285
+ const packageJson = require(process.cwd() + '/package.json');
1286
+ return {
1287
+ name: packageJson.name || 'Unknown Project',
1288
+ version: packageJson.version || '1.0.0'
1289
+ };
1290
+ } catch (error) {
1291
+ return { name: 'recoder-code', version: '2.0.0' };
1292
+ }
1293
+ }
1294
+
1295
+ showEnhancedStatusHints() {
1296
+ console.log(chalk.gray('┌─ Quick Commands ───────────────────────────────────────────┐'));
1297
+ console.log(chalk.gray('│') + chalk.yellow(' ! ') + chalk.white('bash mode') +
1298
+ chalk.gray(' • ') + chalk.yellow('/ ') + chalk.white('commands') +
1299
+ chalk.gray(' • ') + chalk.yellow('tab ') + chalk.white('autocomplete') +
1300
+ chalk.gray(' ') + chalk.red('ESC ') + chalk.white('exit') +
1301
+ chalk.gray(' │'));
1302
+ console.log(chalk.gray('└────────────────────────────────────────────────────────────┘'));
1303
+
1304
+ console.log(chalk.gray('┌─ Features ─────────────────────────────────────────────────┐'));
1305
+ console.log(chalk.gray('│') + chalk.magenta(' 📁 ') + chalk.white(this.getCurrentProjectContext().name) +
1306
+ chalk.gray(' • ') + chalk.green('✨ ') + chalk.white('AI Ready') +
1307
+ chalk.gray(' • ') + chalk.cyan('Ctrl+S ') + chalk.white('save') +
1308
+ chalk.gray(' • ') + chalk.blue('Ctrl+H ') + chalk.white('help') +
1309
+ chalk.gray(' │'));
1310
+ console.log(chalk.gray('└────────────────────────────────────────────────────────────┘'));
1311
+ }
1312
+
1211
1313
  showError(error) {
1212
1314
  // Beautiful error display like Claude Code
1213
1315
  console.log(chalk.red('╭─────────────────────────────────────────╮'));
@@ -1324,6 +1426,24 @@ class InteractiveRecoderChat {
1324
1426
  case 'save':
1325
1427
  this.saveCurrentSession();
1326
1428
  break;
1429
+ case 'analyze':
1430
+ this.performCodeAnalysis();
1431
+ break;
1432
+ case 'git':
1433
+ this.showGitStatus();
1434
+ break;
1435
+ case 'review':
1436
+ this.performCodeReview();
1437
+ break;
1438
+ case 'optimize':
1439
+ this.performOptimizationAnalysis();
1440
+ break;
1441
+ case 'security':
1442
+ this.performSecurityAnalysis();
1443
+ break;
1444
+ case 'theme':
1445
+ this.cycleTheme();
1446
+ break;
1327
1447
  default:
1328
1448
  console.log(chalk.red(`Unknown command: ${input}`));
1329
1449
  console.log(chalk.gray('Type /help for available commands'));
@@ -1335,17 +1455,37 @@ class InteractiveRecoderChat {
1335
1455
  showHelp() {
1336
1456
  console.log('');
1337
1457
  console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
1338
- console.log(chalk.magenta('│') + chalk.white.bold(' Available Commands ') + chalk.magenta('│'));
1458
+ console.log(chalk.magenta('│') + chalk.white.bold(' 🚀 Available Commands ') + chalk.magenta('│'));
1339
1459
  console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
1340
1460
  console.log('');
1341
- console.log(chalk.gray('/help ') + chalk.white('Show this help message'));
1342
- console.log(chalk.gray('/clear ') + chalk.white('Clear the screen'));
1343
- console.log(chalk.gray('/status ') + chalk.white('Show system status'));
1344
- console.log(chalk.gray('/history ') + chalk.white('Show conversation history'));
1345
- console.log(chalk.gray('/session ') + chalk.white('Show current session info'));
1346
- console.log(chalk.gray('/watch ') + chalk.white('Show watched files'));
1347
- console.log(chalk.gray('/save ') + chalk.white('Save current session'));
1348
- console.log(chalk.gray('/exit ') + chalk.white('Exit Recoder Code'));
1461
+
1462
+ console.log(chalk.cyan('📋 Basic Commands:'));
1463
+ console.log(chalk.gray(' /help ') + chalk.white('Show this help message'));
1464
+ console.log(chalk.gray(' /clear ') + chalk.white('Clear the screen'));
1465
+ console.log(chalk.gray(' /status ') + chalk.white('Show system status'));
1466
+ console.log(chalk.gray(' /exit ') + chalk.white('Exit the terminal'));
1467
+ console.log('');
1468
+
1469
+ console.log(chalk.green('🔍 Analysis Commands:'));
1470
+ console.log(chalk.gray(' /analyze ') + chalk.white('Perform intelligent code analysis'));
1471
+ console.log(chalk.gray(' /review ') + chalk.white('AI-powered code review'));
1472
+ console.log(chalk.gray(' /security') + chalk.white('Security vulnerability analysis'));
1473
+ console.log(chalk.gray(' /optimize') + chalk.white('Performance optimization suggestions'));
1474
+ console.log('');
1475
+
1476
+ console.log(chalk.blue('🌿 Git Commands:'));
1477
+ console.log(chalk.gray(' /git ') + chalk.white('Show git repository status'));
1478
+ console.log('');
1479
+
1480
+ console.log(chalk.magenta('🎨 Customization:'));
1481
+ console.log(chalk.gray(' /theme ') + chalk.white('Cycle through visual themes'));
1482
+ console.log('');
1483
+
1484
+ console.log(chalk.yellow('💾 Session Management:'));
1485
+ console.log(chalk.gray(' /history ') + chalk.white('Show conversation history'));
1486
+ console.log(chalk.gray(' /session ') + chalk.white('Show current session info'));
1487
+ console.log(chalk.gray(' /save ') + chalk.white('Save current session'));
1488
+ console.log(chalk.gray(' /watch ') + chalk.white('Show watched files'));
1349
1489
  console.log('');
1350
1490
  }
1351
1491
 
@@ -4092,42 +4232,1316 @@ ${projectInfo}`
4092
4232
  }
4093
4233
  }
4094
4234
 
4095
- async cleanup() {
4096
- this.logger.info('Starting cleanup process');
4235
+ setupGlobalErrorHandlers() {
4236
+ // Register domain-specific handlers with unified error handler
4237
+ errorHandler.registerHandler('interactive', (error) => {
4238
+ if (this.logger) {
4239
+ this.logger.error('Interactive mode error', {
4240
+ error: error?.toString(),
4241
+ stack: error?.stack
4242
+ });
4243
+ }
4244
+
4245
+ // In debug mode, show detailed error for interactive context
4246
+ if (process.env.RECODER_DEBUG === 'true') {
4247
+ console.log(chalk.blue('\n🔍 Interactive Context Error:'));
4248
+ console.log(chalk.gray(error?.toString()));
4249
+ if (error?.stack) {
4250
+ console.log(chalk.gray(error.stack.split('\n').slice(0, 5).join('\n')));
4251
+ }
4252
+ }
4253
+ });
4254
+
4255
+ // Register MCP error handler for graceful degradation
4256
+ errorHandler.registerHandler('mcp', (error) => {
4257
+ // MCP errors are non-critical, just log for debugging
4258
+ if (process.env.RECODER_DEBUG === 'true') {
4259
+ console.log(chalk.gray('🔌 MCP connection issue (non-critical):'), error?.message);
4260
+ }
4261
+ });
4262
+
4263
+ // Handle warnings specifically
4264
+ process.on('warning', (warning) => {
4265
+ if (warning.name === 'PromiseRejectionHandledWarning' ||
4266
+ warning.name === 'UnhandledPromiseRejectionWarning') {
4267
+ if (this.logger) {
4268
+ this.logger.warn('Promise warning', { name: warning.name, message: warning.message });
4269
+ }
4270
+ }
4271
+ });
4272
+ }
4273
+
4274
+ // ========== INTELLIGENT FEATURES ==========
4275
+
4276
+ performCodeAnalysis() {
4277
+ console.log(chalk.cyan('🔍 Analyzing Codebase...'));
4278
+ console.log('');
4097
4279
 
4098
- // Clean up streaming and loading animations
4099
- this.stopProgressiveLoading();
4100
- this.stopStreamingDisplay();
4280
+ const analysis = this.analyzeCurrentProject();
4101
4281
 
4102
- if (this.fileWatcher) {
4103
- this.fileWatcher.close();
4104
- this.fileWatcher = null;
4105
- this.logger.debug('File watcher closed');
4282
+ console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
4283
+ console.log(chalk.magenta('│') + chalk.white.bold(' 📊 Code Analysis Results ') + chalk.magenta('│'));
4284
+ console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
4285
+ console.log('');
4286
+
4287
+ console.log(chalk.cyan('📁 Project Structure:'));
4288
+ console.log(chalk.white(` • Files: ${analysis.fileCount}`));
4289
+ console.log(chalk.white(` • Languages: ${analysis.languages.join(', ')}`));
4290
+ console.log(chalk.white(` • Main Language: ${analysis.mainLanguage}`));
4291
+ console.log('');
4292
+
4293
+ console.log(chalk.green('✅ Strengths:'));
4294
+ analysis.strengths.forEach(strength => {
4295
+ console.log(chalk.white(` • ${strength}`));
4296
+ });
4297
+ console.log('');
4298
+
4299
+ console.log(chalk.yellow('💡 Suggestions:'));
4300
+ analysis.suggestions.forEach(suggestion => {
4301
+ console.log(chalk.white(` • ${suggestion}`));
4302
+ });
4303
+ console.log('');
4304
+ }
4305
+
4306
+ analyzeCurrentProject() {
4307
+ const fs = require('fs');
4308
+ const path = require('path');
4309
+
4310
+ try {
4311
+ const analysis = {
4312
+ fileCount: 0,
4313
+ languages: new Set(),
4314
+ fileTypes: {},
4315
+ dependencies: [],
4316
+ devDependencies: [],
4317
+ strengths: [],
4318
+ issues: [],
4319
+ suggestions: []
4320
+ };
4321
+
4322
+ // Scan actual files in project
4323
+ const scanDirectory = (dir, depth = 0) => {
4324
+ if (depth > 3) return; // Limit depth
4325
+
4326
+ try {
4327
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
4328
+
4329
+ for (const entry of entries) {
4330
+ const fullPath = path.join(dir, entry.name);
4331
+
4332
+ // Skip node_modules, .git, etc.
4333
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
4334
+
4335
+ if (entry.isFile()) {
4336
+ analysis.fileCount++;
4337
+ const ext = path.extname(entry.name).toLowerCase();
4338
+
4339
+ // Count file types
4340
+ analysis.fileTypes[ext] = (analysis.fileTypes[ext] || 0) + 1;
4341
+
4342
+ // Detect languages
4343
+ const languageMap = {
4344
+ '.js': 'JavaScript',
4345
+ '.ts': 'TypeScript',
4346
+ '.py': 'Python',
4347
+ '.java': 'Java',
4348
+ '.cpp': 'C++',
4349
+ '.c': 'C',
4350
+ '.cs': 'C#',
4351
+ '.go': 'Go',
4352
+ '.rs': 'Rust',
4353
+ '.php': 'PHP',
4354
+ '.rb': 'Ruby',
4355
+ '.json': 'JSON',
4356
+ '.md': 'Markdown',
4357
+ '.html': 'HTML',
4358
+ '.css': 'CSS',
4359
+ '.scss': 'SCSS',
4360
+ '.yaml': 'YAML',
4361
+ '.yml': 'YAML'
4362
+ };
4363
+
4364
+ if (languageMap[ext]) {
4365
+ analysis.languages.add(languageMap[ext]);
4366
+ }
4367
+ } else if (entry.isDirectory()) {
4368
+ scanDirectory(fullPath, depth + 1);
4369
+ }
4370
+ }
4371
+ } catch (error) {
4372
+ // Skip directories we can't read
4373
+ }
4374
+ };
4375
+
4376
+ // Scan from current directory
4377
+ scanDirectory(process.cwd());
4378
+
4379
+ // Analyze package.json if it exists
4380
+ try {
4381
+ const packagePath = path.join(process.cwd(), 'package.json');
4382
+ if (fs.existsSync(packagePath)) {
4383
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
4384
+ analysis.dependencies = Object.keys(packageJson.dependencies || {});
4385
+ analysis.devDependencies = Object.keys(packageJson.devDependencies || {});
4386
+
4387
+ // Analyze dependencies for insights
4388
+ if (analysis.dependencies.includes('express')) analysis.strengths.push('Express.js web framework detected');
4389
+ if (analysis.dependencies.includes('react')) analysis.strengths.push('React frontend framework detected');
4390
+ if (analysis.dependencies.includes('chalk')) analysis.strengths.push('Terminal styling with chalk');
4391
+ if (analysis.devDependencies.includes('jest')) analysis.strengths.push('Jest testing framework configured');
4392
+ if (analysis.devDependencies.includes('eslint')) analysis.strengths.push('ESLint code linting configured');
4393
+ }
4394
+ } catch (error) {
4395
+ analysis.issues.push('Could not read package.json');
4396
+ }
4397
+
4398
+ // Generate insights based on actual analysis
4399
+ const languageArray = Array.from(analysis.languages);
4400
+ const mainLanguage = this.determineMainLanguage(analysis.fileTypes);
4401
+
4402
+ if (analysis.fileCount === 0) {
4403
+ analysis.issues.push('No files found in project');
4404
+ } else if (analysis.fileCount > 1000) {
4405
+ analysis.issues.push('Large project detected - consider optimization');
4406
+ }
4407
+
4408
+ if (!languageArray.includes('TypeScript') && languageArray.includes('JavaScript')) {
4409
+ analysis.suggestions.push('Consider migrating to TypeScript for better type safety');
4410
+ }
4411
+
4412
+ if (!analysis.fileTypes['.md']) {
4413
+ analysis.suggestions.push('Add README.md and documentation');
4414
+ }
4415
+
4416
+ if (analysis.dependencies.length === 0) {
4417
+ analysis.suggestions.push('Consider using npm/yarn for dependency management');
4418
+ }
4419
+
4420
+ if (!analysis.devDependencies.includes('jest') && !analysis.devDependencies.includes('mocha')) {
4421
+ analysis.suggestions.push('Add testing framework (Jest/Mocha)');
4422
+ }
4423
+
4424
+ return {
4425
+ fileCount: analysis.fileCount,
4426
+ languages: languageArray,
4427
+ mainLanguage: mainLanguage,
4428
+ fileTypes: analysis.fileTypes,
4429
+ dependencies: analysis.dependencies,
4430
+ devDependencies: analysis.devDependencies,
4431
+ strengths: analysis.strengths.length > 0 ? analysis.strengths : ['Project structure analyzed'],
4432
+ issues: analysis.issues,
4433
+ suggestions: analysis.suggestions.length > 0 ? analysis.suggestions : ['Project appears well-structured']
4434
+ };
4435
+
4436
+ } catch (error) {
4437
+ return {
4438
+ fileCount: 0,
4439
+ languages: ['Unknown'],
4440
+ mainLanguage: 'Unknown',
4441
+ fileTypes: {},
4442
+ dependencies: [],
4443
+ devDependencies: [],
4444
+ strengths: ['Basic analysis attempted'],
4445
+ issues: [`Analysis error: ${error.message}`],
4446
+ suggestions: ['Ensure proper file permissions']
4447
+ };
4106
4448
  }
4449
+ }
4450
+
4451
+ determineMainLanguage(fileTypes) {
4452
+ let maxCount = 0;
4453
+ let mainExt = '';
4107
4454
 
4108
- // Cleanup voice manager
4109
- if (this.voiceManager) {
4110
- this.voiceManager.cleanup();
4111
- this.logger.debug('Voice manager cleaned up');
4455
+ for (const [ext, count] of Object.entries(fileTypes)) {
4456
+ if (count > maxCount && ext !== '.md' && ext !== '.json') {
4457
+ maxCount = count;
4458
+ mainExt = ext;
4459
+ }
4112
4460
  }
4113
4461
 
4114
- // Cleanup collaboration manager
4115
- if (this.collaborationManager) {
4116
- this.collaborationManager.cleanup();
4117
- this.logger.debug('Collaboration manager cleaned up');
4462
+ const languageMap = {
4463
+ '.js': 'JavaScript',
4464
+ '.ts': 'TypeScript',
4465
+ '.py': 'Python',
4466
+ '.java': 'Java',
4467
+ '.cpp': 'C++',
4468
+ '.go': 'Go',
4469
+ '.rs': 'Rust'
4470
+ };
4471
+
4472
+ return languageMap[mainExt] || 'Mixed';
4473
+ }
4474
+
4475
+ showGitStatus() {
4476
+ console.log(chalk.cyan('📊 Git Repository Status'));
4477
+ console.log('');
4478
+
4479
+ const { execSync } = require('child_process');
4480
+
4481
+ try {
4482
+ // Check if git is available
4483
+ execSync('git --version', { stdio: 'ignore' });
4484
+
4485
+ // Check if we're in a git repository
4486
+ execSync('git rev-parse --git-dir', { stdio: 'ignore' });
4487
+
4488
+ console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
4489
+ console.log(chalk.magenta('│') + chalk.white.bold(' 🌿 Git Repository Analysis ') + chalk.magenta('│'));
4490
+ console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
4491
+ console.log('');
4492
+
4493
+ // Get comprehensive git information
4494
+ const gitInfo = this.getGitInformation();
4495
+
4496
+ // Display branch information
4497
+ console.log(chalk.green(`🌿 Current Branch: ${gitInfo.currentBranch}`));
4498
+ if (gitInfo.upstreamBranch) {
4499
+ console.log(chalk.blue(`🔗 Upstream: ${gitInfo.upstreamBranch}`));
4500
+ }
4501
+
4502
+ // Show commits ahead/behind
4503
+ if (gitInfo.aheadBehind.ahead > 0 || gitInfo.aheadBehind.behind > 0) {
4504
+ console.log(chalk.yellow(`📊 Sync Status: ${gitInfo.aheadBehind.ahead} ahead, ${gitInfo.aheadBehind.behind} behind`));
4505
+ }
4506
+ console.log('');
4507
+
4508
+ // Show working directory status
4509
+ if (gitInfo.statusFiles.length > 0) {
4510
+ console.log(chalk.yellow('📝 Working Directory Changes:'));
4511
+
4512
+ const statusCounts = { modified: 0, added: 0, deleted: 0, untracked: 0 };
4513
+
4514
+ gitInfo.statusFiles.forEach(file => {
4515
+ let statusIcon = '❓';
4516
+ let statusColor = 'white';
4517
+
4518
+ if (file.status.includes('M')) {
4519
+ statusIcon = '📝';
4520
+ statusColor = 'yellow';
4521
+ statusCounts.modified++;
4522
+ } else if (file.status.includes('A')) {
4523
+ statusIcon = '➕';
4524
+ statusColor = 'green';
4525
+ statusCounts.added++;
4526
+ } else if (file.status.includes('D')) {
4527
+ statusIcon = '🗑️';
4528
+ statusColor = 'red';
4529
+ statusCounts.deleted++;
4530
+ } else if (file.status.includes('??')) {
4531
+ statusIcon = '❔';
4532
+ statusColor = 'gray';
4533
+ statusCounts.untracked++;
4534
+ }
4535
+
4536
+ console.log(chalk[statusColor](` ${statusIcon} ${file.file}`));
4537
+ });
4538
+
4539
+ console.log('');
4540
+ console.log(chalk.cyan('📊 Summary:'));
4541
+ if (statusCounts.modified > 0) console.log(chalk.yellow(` 📝 ${statusCounts.modified} modified`));
4542
+ if (statusCounts.added > 0) console.log(chalk.green(` ➕ ${statusCounts.added} added`));
4543
+ if (statusCounts.deleted > 0) console.log(chalk.red(` 🗑️ ${statusCounts.deleted} deleted`));
4544
+ if (statusCounts.untracked > 0) console.log(chalk.gray(` ❔ ${statusCounts.untracked} untracked`));
4545
+
4546
+ } else {
4547
+ console.log(chalk.green('✅ Working directory clean'));
4548
+ }
4549
+
4550
+ console.log('');
4551
+
4552
+ // Show recent commits with more detail
4553
+ console.log(chalk.blue('📚 Recent Commits:'));
4554
+ gitInfo.recentCommits.forEach((commit, index) => {
4555
+ const timeAgo = this.getTimeAgo(commit.date);
4556
+ console.log(chalk.gray(` ${index + 1}. ${commit.hash} ${commit.message}`));
4557
+ console.log(chalk.gray(` by ${commit.author} ${timeAgo}`));
4558
+ });
4559
+
4560
+ console.log('');
4561
+
4562
+ // Show repository statistics
4563
+ console.log(chalk.cyan('📈 Repository Stats:'));
4564
+ console.log(chalk.white(` 🏷️ Total Tags: ${gitInfo.stats.totalTags}`));
4565
+ console.log(chalk.white(` 🌿 Total Branches: ${gitInfo.stats.totalBranches}`));
4566
+ console.log(chalk.white(` 📝 Total Commits: ${gitInfo.stats.totalCommits}`));
4567
+ console.log(chalk.white(` 👥 Contributors: ${gitInfo.stats.contributors}`));
4568
+
4569
+ } catch (error) {
4570
+ if (error.message.includes('not a git repository')) {
4571
+ console.log(chalk.red('❌ Not a git repository'));
4572
+ console.log(chalk.gray('Initialize with: git init'));
4573
+ } else if (error.message.includes('git --version')) {
4574
+ console.log(chalk.red('❌ Git not installed or not in PATH'));
4575
+ } else {
4576
+ console.log(chalk.red(`❌ Git error: ${error.message}`));
4577
+ }
4118
4578
  }
4579
+ console.log('');
4580
+ }
4581
+
4582
+ getGitInformation() {
4583
+ const { execSync } = require('child_process');
4119
4584
 
4120
- // Cleanup plugins
4121
- if (this.pluginManager) {
4122
- await this.pluginManager.cleanup();
4123
- this.logger.debug('Plugins cleaned up');
4585
+ try {
4586
+ // Get current branch
4587
+ const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
4588
+
4589
+ // Get upstream branch
4590
+ let upstreamBranch = null;
4591
+ try {
4592
+ upstreamBranch = execSync('git rev-parse --abbrev-ref @{upstream}', { encoding: 'utf8' }).trim();
4593
+ } catch (e) {
4594
+ // No upstream branch
4595
+ }
4596
+
4597
+ // Get ahead/behind count
4598
+ let aheadBehind = { ahead: 0, behind: 0 };
4599
+ if (upstreamBranch) {
4600
+ try {
4601
+ const aheadBehindOutput = execSync(`git rev-list --count --left-right ${upstreamBranch}...HEAD`, { encoding: 'utf8' }).trim();
4602
+ const [behind, ahead] = aheadBehindOutput.split('\t').map(Number);
4603
+ aheadBehind = { ahead, behind };
4604
+ } catch (e) {
4605
+ // Can't determine ahead/behind
4606
+ }
4607
+ }
4608
+
4609
+ // Get status files
4610
+ const statusOutput = execSync('git status --porcelain', { encoding: 'utf8' });
4611
+ const statusFiles = statusOutput.split('\n')
4612
+ .filter(line => line.trim())
4613
+ .map(line => ({
4614
+ status: line.substring(0, 2),
4615
+ file: line.substring(3)
4616
+ }));
4617
+
4618
+ // Get recent commits with detailed info
4619
+ const commitOutput = execSync('git log --oneline --format="%H|%s|%an|%ad" --date=iso -10', { encoding: 'utf8' });
4620
+ const recentCommits = commitOutput.split('\n')
4621
+ .filter(line => line.trim())
4622
+ .map(line => {
4623
+ const [hash, message, author, date] = line.split('|');
4624
+ return {
4625
+ hash: hash.substring(0, 8),
4626
+ message,
4627
+ author,
4628
+ date: new Date(date)
4629
+ };
4630
+ });
4631
+
4632
+ // Get repository statistics
4633
+ const totalTags = execSync('git tag --list | wc -l', { encoding: 'utf8' }).trim();
4634
+ const totalBranches = execSync('git branch -a | wc -l', { encoding: 'utf8' }).trim();
4635
+ const totalCommits = execSync('git rev-list --count HEAD', { encoding: 'utf8' }).trim();
4636
+ const contributors = execSync('git shortlog -sn | wc -l', { encoding: 'utf8' }).trim();
4637
+
4638
+ return {
4639
+ currentBranch,
4640
+ upstreamBranch,
4641
+ aheadBehind,
4642
+ statusFiles,
4643
+ recentCommits,
4644
+ stats: {
4645
+ totalTags: parseInt(totalTags) || 0,
4646
+ totalBranches: parseInt(totalBranches) || 0,
4647
+ totalCommits: parseInt(totalCommits) || 0,
4648
+ contributors: parseInt(contributors) || 0
4649
+ }
4650
+ };
4651
+
4652
+ } catch (error) {
4653
+ throw error;
4124
4654
  }
4655
+ }
4656
+
4657
+ getTimeAgo(date) {
4658
+ const now = new Date();
4659
+ const diffMs = now - date;
4660
+ const diffMins = Math.floor(diffMs / 60000);
4661
+ const diffHours = Math.floor(diffMs / 3600000);
4662
+ const diffDays = Math.floor(diffMs / 86400000);
4663
+
4664
+ if (diffMins < 60) return `${diffMins} minutes ago`;
4665
+ if (diffHours < 24) return `${diffHours} hours ago`;
4666
+ if (diffDays < 30) return `${diffDays} days ago`;
4667
+ return date.toLocaleDateString();
4668
+ }
4669
+
4670
+ performCodeReview() {
4671
+ console.log(chalk.cyan('🔍 Performing AI Code Review...'));
4672
+ console.log('');
4125
4673
 
4126
- // End session logging
4127
- if (this.logger) {
4128
- this.logger.endSession();
4129
- this.logger.info('Session cleanup completed');
4674
+ console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
4675
+ console.log(chalk.magenta('│') + chalk.white.bold(' 🤖 AI Code Review ') + chalk.magenta('│'));
4676
+ console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
4677
+ console.log('');
4678
+
4679
+ const review = this.generateRealCodeReview();
4680
+
4681
+ // Display scores with color coding
4682
+ const getScoreColor = (score) => {
4683
+ if (score >= 90) return 'green';
4684
+ if (score >= 75) return 'yellow';
4685
+ return 'red';
4686
+ };
4687
+
4688
+ console.log(chalk[getScoreColor(review.scores.quality)](`✅ Code Quality: ${review.scores.quality}/100`));
4689
+ console.log(chalk[getScoreColor(review.scores.maintainability)](`📊 Maintainability: ${review.scores.maintainability}/100`));
4690
+ console.log(chalk[getScoreColor(review.scores.security)](`🛡️ Security: ${review.scores.security}/100`));
4691
+ console.log(chalk[getScoreColor(review.scores.testCoverage)](`🧪 Test Coverage: ${review.scores.testCoverage}/100`));
4692
+ console.log('');
4693
+
4694
+ // Display architecture analysis
4695
+ if (review.architecture.length > 0) {
4696
+ console.log(chalk.blue('🏗️ Architecture Analysis:'));
4697
+ review.architecture.forEach(item => {
4698
+ console.log(chalk.white(` • ${item.type}: ${item.description}`));
4699
+ if (item.file) {
4700
+ console.log(chalk.gray(` File: ${item.file}`));
4701
+ }
4702
+ });
4703
+ console.log('');
4704
+ }
4705
+
4706
+ // Display code quality issues
4707
+ if (review.qualityIssues.length > 0) {
4708
+ console.log(chalk.yellow('⚠️ Code Quality Issues:'));
4709
+ review.qualityIssues.forEach(issue => {
4710
+ console.log(chalk.white(` • ${issue.type}: ${issue.description}`));
4711
+ console.log(chalk.gray(` File: ${issue.file}:${issue.line}`));
4712
+ });
4713
+ console.log('');
4714
+ }
4715
+
4716
+ // Display maintainability metrics
4717
+ if (review.maintainabilityMetrics.length > 0) {
4718
+ console.log(chalk.cyan('📈 Maintainability Metrics:'));
4719
+ review.maintainabilityMetrics.forEach(metric => {
4720
+ console.log(chalk.white(` • ${metric.metric}: ${metric.value} (${metric.assessment})`));
4721
+ if (metric.suggestion) {
4722
+ console.log(chalk.gray(` Suggestion: ${metric.suggestion}`));
4723
+ }
4724
+ });
4725
+ console.log('');
4726
+ }
4727
+
4728
+ // Display AI recommendations
4729
+ if (review.recommendations.length > 0) {
4730
+ console.log(chalk.cyan('💡 AI-Powered Recommendations:'));
4731
+ review.recommendations.forEach(rec => {
4732
+ console.log(chalk.white(` • ${rec.category}: ${rec.suggestion}`));
4733
+ if (rec.priority) {
4734
+ console.log(chalk.gray(` Priority: ${rec.priority}`));
4735
+ }
4736
+ });
4737
+ console.log('');
4130
4738
  }
4739
+
4740
+ // Display overall assessment
4741
+ const overallScore = Math.round((review.scores.quality + review.scores.maintainability + review.scores.security + review.scores.testCoverage) / 4);
4742
+ console.log(chalk[getScoreColor(overallScore)](`🎯 Overall Code Health: ${overallScore}/100`));
4743
+ }
4744
+
4745
+ generateRealCodeReview() {
4746
+ const fs = require('fs');
4747
+ const path = require('path');
4748
+
4749
+ const review = {
4750
+ scores: {
4751
+ quality: 100,
4752
+ maintainability: 100,
4753
+ security: 100,
4754
+ testCoverage: 50
4755
+ },
4756
+ architecture: [],
4757
+ qualityIssues: [],
4758
+ maintainabilityMetrics: [],
4759
+ recommendations: []
4760
+ };
4761
+
4762
+ // Code quality patterns to analyze
4763
+ const qualityPatterns = [
4764
+ { pattern: /function\s+\w+\s*\([^)]*\)\s*\{[\s\S]{500,}?\}/, type: 'Long Function', description: 'Function exceeds recommended length' },
4765
+ { pattern: /if\s*\([^)]+\)\s*\{[\s\S]*?if\s*\([^)]+\)\s*\{[\s\S]*?if\s*\([^)]+\)/, type: 'Deep Nesting', description: 'Excessive nesting depth detected' },
4766
+ { pattern: /var\s+\w+/, type: 'Var Usage', description: 'Use const/let instead of var' },
4767
+ { pattern: /==\s*(?!null)/, type: 'Loose Equality', description: 'Use strict equality (===) instead' },
4768
+ { pattern: /console\.log/, type: 'Debug Code', description: 'Remove console.log from production code' },
4769
+ { pattern: /\.catch\s*\(\s*\(\s*\)\s*=>\s*\{\s*\}\s*\)/, type: 'Empty Catch', description: 'Empty catch block - handle errors properly' }
4770
+ ];
4771
+
4772
+ // Maintainability patterns
4773
+ const maintainabilityPatterns = [
4774
+ { pattern: /\/\*[\s\S]*?\*\/|\/\/.*$/gm, type: 'Comments', description: 'Code documentation' },
4775
+ { pattern: /class\s+\w+/, type: 'Classes', description: 'Object-oriented structure' },
4776
+ { pattern: /export\s+/, type: 'Modules', description: 'Modular architecture' },
4777
+ { pattern: /import\s+.*from/, type: 'Dependencies', description: 'Dependency management' }
4778
+ ];
4779
+
4780
+ // Architecture patterns
4781
+ const architecturePatterns = [
4782
+ { pattern: /class\s+\w+Manager/, type: 'Manager Pattern', description: 'Centralized management logic' },
4783
+ { pattern: /\.on\(|\.emit\(/, type: 'Event-Driven', description: 'Event-driven architecture' },
4784
+ { pattern: /async\s+function|await\s+/, type: 'Async Pattern', description: 'Asynchronous programming patterns' },
4785
+ { pattern: /module\.exports\s*=/, type: 'Module System', description: 'CommonJS module pattern' }
4786
+ ];
4787
+
4788
+ let totalLines = 0;
4789
+ let totalFunctions = 0;
4790
+ let totalClasses = 0;
4791
+ let commentLines = 0;
4792
+ let testFiles = 0;
4793
+
4794
+ // Analyze codebase
4795
+ const analyzeDirectory = (dir, depth = 0) => {
4796
+ if (depth > 3) return;
4797
+
4798
+ try {
4799
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
4800
+
4801
+ for (const entry of entries) {
4802
+ const fullPath = path.join(dir, entry.name);
4803
+
4804
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
4805
+
4806
+ if (entry.isFile() && this.isCodeFile(entry.name)) {
4807
+ this.analyzeCodeFile(fullPath, qualityPatterns, maintainabilityPatterns, architecturePatterns, review);
4808
+
4809
+ // Count metrics
4810
+ const content = fs.readFileSync(fullPath, 'utf8');
4811
+ const lines = content.split('\n');
4812
+ totalLines += lines.length;
4813
+
4814
+ // Count functions and classes
4815
+ totalFunctions += (content.match(/function\s+\w+|=>\s*\{|\w+\s*:\s*function/g) || []).length;
4816
+ totalClasses += (content.match(/class\s+\w+/g) || []).length;
4817
+
4818
+ // Count comments
4819
+ commentLines += (content.match(/\/\*[\s\S]*?\*\/|\/\/.*$/gm) || []).length;
4820
+
4821
+ // Check if it's a test file
4822
+ if (entry.name.includes('test') || entry.name.includes('spec')) {
4823
+ testFiles++;
4824
+ }
4825
+
4826
+ } else if (entry.isDirectory()) {
4827
+ analyzeDirectory(fullPath, depth + 1);
4828
+ }
4829
+ }
4830
+ } catch (error) {
4831
+ // Skip directories we can't read
4832
+ }
4833
+ };
4834
+
4835
+ analyzeDirectory(process.cwd());
4836
+
4837
+ // Calculate scores based on findings
4838
+ const qualityIssueCount = review.qualityIssues.length;
4839
+ review.scores.quality = Math.max(0, 100 - (qualityIssueCount * 5));
4840
+
4841
+ // Maintainability score based on structure and documentation
4842
+ const commentRatio = totalLines > 0 ? (commentLines / totalLines) * 100 : 0;
4843
+ const avgFunctionsPerFile = totalFunctions > 0 ? totalFunctions / (totalLines / 50) : 0;
4844
+
4845
+ review.scores.maintainability = Math.max(0, 100 -
4846
+ (avgFunctionsPerFile > 10 ? 20 : 0) -
4847
+ (commentRatio < 10 ? 15 : 0) -
4848
+ (totalClasses === 0 ? 10 : 0));
4849
+
4850
+ // Test coverage estimation
4851
+ review.scores.testCoverage = Math.min(100, testFiles * 20);
4852
+
4853
+ // Add maintainability metrics
4854
+ review.maintainabilityMetrics.push({
4855
+ metric: 'Comment Ratio',
4856
+ value: `${commentRatio.toFixed(1)}%`,
4857
+ assessment: commentRatio > 15 ? 'Good' : commentRatio > 5 ? 'Fair' : 'Poor',
4858
+ suggestion: commentRatio < 10 ? 'Add more documentation' : null
4859
+ });
4860
+
4861
+ review.maintainabilityMetrics.push({
4862
+ metric: 'Total Lines of Code',
4863
+ value: totalLines.toString(),
4864
+ assessment: totalLines < 5000 ? 'Manageable' : totalLines < 15000 ? 'Large' : 'Very Large'
4865
+ });
4866
+
4867
+ review.maintainabilityMetrics.push({
4868
+ metric: 'Functions Count',
4869
+ value: totalFunctions.toString(),
4870
+ assessment: 'Active'
4871
+ });
4872
+
4873
+ review.maintainabilityMetrics.push({
4874
+ metric: 'Classes Count',
4875
+ value: totalClasses.toString(),
4876
+ assessment: totalClasses > 0 ? 'Object-oriented' : 'Functional'
4877
+ });
4878
+
4879
+ // Generate AI-powered recommendations
4880
+ if (qualityIssueCount > 0) {
4881
+ review.recommendations.push({
4882
+ category: 'Code Quality',
4883
+ suggestion: 'Address code quality issues to improve maintainability',
4884
+ priority: 'High'
4885
+ });
4886
+ }
4887
+
4888
+ if (review.scores.testCoverage < 70) {
4889
+ review.recommendations.push({
4890
+ category: 'Testing',
4891
+ suggestion: 'Increase test coverage with unit and integration tests',
4892
+ priority: 'High'
4893
+ });
4894
+ }
4895
+
4896
+ if (commentRatio < 10) {
4897
+ review.recommendations.push({
4898
+ category: 'Documentation',
4899
+ suggestion: 'Add more inline documentation and comments',
4900
+ priority: 'Medium'
4901
+ });
4902
+ }
4903
+
4904
+ review.recommendations.push({
4905
+ category: 'Architecture',
4906
+ suggestion: 'Consider implementing design patterns for better code organization',
4907
+ priority: 'Medium'
4908
+ });
4909
+
4910
+ review.recommendations.push({
4911
+ category: 'Performance',
4912
+ suggestion: 'Profile critical code paths and optimize bottlenecks',
4913
+ priority: 'Low'
4914
+ });
4915
+
4916
+ review.recommendations.push({
4917
+ category: 'Security',
4918
+ suggestion: 'Implement input validation and security best practices',
4919
+ priority: 'High'
4920
+ });
4921
+
4922
+ return review;
4923
+ }
4924
+
4925
+ analyzeCodeFile(filePath, qualityPatterns, maintainabilityPatterns, architecturePatterns, review) {
4926
+ const fs = require('fs');
4927
+
4928
+ try {
4929
+ const content = fs.readFileSync(filePath, 'utf8');
4930
+ const lines = content.split('\n');
4931
+
4932
+ // Check for quality issues
4933
+ for (const patternInfo of qualityPatterns) {
4934
+ if (patternInfo.pattern.test(content)) {
4935
+ review.qualityIssues.push({
4936
+ type: patternInfo.type,
4937
+ description: patternInfo.description,
4938
+ file: filePath.replace(process.cwd(), '.'),
4939
+ line: this.findPatternLine(lines, patternInfo.pattern)
4940
+ });
4941
+ }
4942
+ }
4943
+
4944
+ // Check architecture patterns
4945
+ for (const patternInfo of architecturePatterns) {
4946
+ if (patternInfo.pattern.test(content)) {
4947
+ review.architecture.push({
4948
+ type: patternInfo.type,
4949
+ description: patternInfo.description,
4950
+ file: filePath.replace(process.cwd(), '.')
4951
+ });
4952
+ }
4953
+ }
4954
+
4955
+ } catch (error) {
4956
+ // Skip files we can't read
4957
+ }
4958
+ }
4959
+
4960
+ findPatternLine(lines, pattern) {
4961
+ for (let i = 0; i < lines.length; i++) {
4962
+ if (pattern.test(lines[i])) {
4963
+ return i + 1;
4964
+ }
4965
+ }
4966
+ return 1;
4967
+ }
4968
+
4969
+ performSecurityAnalysis() {
4970
+ console.log(chalk.cyan('🛡️ Performing Security Analysis...'));
4971
+ console.log('');
4972
+
4973
+ console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
4974
+ console.log(chalk.magenta('│') + chalk.white.bold(' 🛡️ Security Vulnerability Scan ') + chalk.magenta('│'));
4975
+ console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
4976
+ console.log('');
4977
+
4978
+ const securityReport = this.performRealSecurityScan();
4979
+
4980
+ // Display security score
4981
+ let scoreColor = 'green';
4982
+ if (securityReport.score < 70) scoreColor = 'red';
4983
+ else if (securityReport.score < 85) scoreColor = 'yellow';
4984
+
4985
+ console.log(chalk[scoreColor](`🛡️ Security Score: ${securityReport.score}/100`));
4986
+ console.log('');
4987
+
4988
+ // Display vulnerabilities by severity
4989
+ if (securityReport.vulnerabilities.critical.length > 0) {
4990
+ console.log(chalk.red('🚨 Critical Vulnerabilities:'));
4991
+ securityReport.vulnerabilities.critical.forEach(vuln => {
4992
+ console.log(chalk.red(` • ${vuln.type}: ${vuln.description}`));
4993
+ console.log(chalk.gray(` File: ${vuln.file}:${vuln.line}`));
4994
+ });
4995
+ console.log('');
4996
+ }
4997
+
4998
+ if (securityReport.vulnerabilities.high.length > 0) {
4999
+ console.log(chalk.red('⚠️ High Risk Issues:'));
5000
+ securityReport.vulnerabilities.high.forEach(vuln => {
5001
+ console.log(chalk.yellow(` • ${vuln.type}: ${vuln.description}`));
5002
+ console.log(chalk.gray(` File: ${vuln.file}:${vuln.line}`));
5003
+ });
5004
+ console.log('');
5005
+ }
5006
+
5007
+ if (securityReport.vulnerabilities.medium.length > 0) {
5008
+ console.log(chalk.yellow('⚠️ Medium Risk Issues:'));
5009
+ securityReport.vulnerabilities.medium.forEach(vuln => {
5010
+ console.log(chalk.yellow(` • ${vuln.type}: ${vuln.description}`));
5011
+ console.log(chalk.gray(` File: ${vuln.file}:${vuln.line}`));
5012
+ });
5013
+ console.log('');
5014
+ }
5015
+
5016
+ if (securityReport.vulnerabilities.low.length > 0) {
5017
+ console.log(chalk.cyan('ℹ️ Low Risk Issues:'));
5018
+ securityReport.vulnerabilities.low.forEach(vuln => {
5019
+ console.log(chalk.cyan(` • ${vuln.type}: ${vuln.description}`));
5020
+ console.log(chalk.gray(` File: ${vuln.file}:${vuln.line}`));
5021
+ });
5022
+ console.log('');
5023
+ }
5024
+
5025
+ // Show dependency vulnerabilities
5026
+ if (securityReport.dependencyIssues.length > 0) {
5027
+ console.log(chalk.yellow('📦 Dependency Vulnerabilities:'));
5028
+ securityReport.dependencyIssues.forEach(dep => {
5029
+ console.log(chalk.yellow(` • ${dep.name}@${dep.version}: ${dep.issue}`));
5030
+ console.log(chalk.gray(` Severity: ${dep.severity}, Fix: ${dep.fix}`));
5031
+ });
5032
+ console.log('');
5033
+ }
5034
+
5035
+ // Show recommendations
5036
+ if (securityReport.recommendations.length > 0) {
5037
+ console.log(chalk.cyan('💡 Security Recommendations:'));
5038
+ securityReport.recommendations.forEach(rec => {
5039
+ console.log(chalk.white(` • ${rec}`));
5040
+ });
5041
+ console.log('');
5042
+ }
5043
+
5044
+ // Summary
5045
+ const totalIssues = securityReport.vulnerabilities.critical.length +
5046
+ securityReport.vulnerabilities.high.length +
5047
+ securityReport.vulnerabilities.medium.length +
5048
+ securityReport.vulnerabilities.low.length;
5049
+
5050
+ if (totalIssues === 0) {
5051
+ console.log(chalk.green('✅ No security vulnerabilities detected in code scan'));
5052
+ } else {
5053
+ console.log(chalk.yellow(`📊 Total Issues Found: ${totalIssues}`));
5054
+ }
5055
+ }
5056
+
5057
+ performRealSecurityScan() {
5058
+ const fs = require('fs');
5059
+ const path = require('path');
5060
+
5061
+ const securityReport = {
5062
+ score: 100,
5063
+ vulnerabilities: {
5064
+ critical: [],
5065
+ high: [],
5066
+ medium: [],
5067
+ low: []
5068
+ },
5069
+ dependencyIssues: [],
5070
+ recommendations: []
5071
+ };
5072
+
5073
+ // Security patterns to detect
5074
+ const securityPatterns = {
5075
+ critical: [
5076
+ { pattern: /password\s*=\s*['"][^'"]+['"]/, type: 'Hardcoded Password', description: 'Hardcoded password detected' },
5077
+ { pattern: /api[_-]?key\s*=\s*['"][^'"]+['"]/, type: 'Hardcoded API Key', description: 'Hardcoded API key detected' },
5078
+ { pattern: /secret\s*=\s*['"][^'"]+['"]/, type: 'Hardcoded Secret', description: 'Hardcoded secret detected' },
5079
+ { pattern: /eval\s*\(/, type: 'Code Injection', description: 'Use of eval() detected - potential code injection risk' }
5080
+ ],
5081
+ high: [
5082
+ { pattern: /exec\s*\(.*\$/, type: 'Command Injection', description: 'Potential command injection vulnerability' },
5083
+ { pattern: /innerHTML\s*=/, type: 'XSS Risk', description: 'Use of innerHTML - potential XSS vulnerability' },
5084
+ { pattern: /document\.write\s*\(/, type: 'XSS Risk', description: 'Use of document.write - potential XSS vulnerability' },
5085
+ { pattern: /sql\s*=.*\+/, type: 'SQL Injection', description: 'Potential SQL injection vulnerability' }
5086
+ ],
5087
+ medium: [
5088
+ { pattern: /console\.log\s*\(.*password/, type: 'Information Disclosure', description: 'Password logged to console' },
5089
+ { pattern: /console\.log\s*\(.*token/, type: 'Information Disclosure', description: 'Token logged to console' },
5090
+ { pattern: /http:\/\//, type: 'Insecure Protocol', description: 'Use of insecure HTTP protocol' },
5091
+ { pattern: /Math\.random\s*\(\)/, type: 'Weak Cryptography', description: 'Use of Math.random() for security purposes' }
5092
+ ],
5093
+ low: [
5094
+ { pattern: /TODO.*security/, type: 'Security TODO', description: 'Security-related TODO comment' },
5095
+ { pattern: /FIXME.*security/, type: 'Security FIXME', description: 'Security-related FIXME comment' },
5096
+ { pattern: /\.trim\s*\(\)\.length/, type: 'Input Validation', description: 'Consider more robust input validation' }
5097
+ ]
5098
+ };
5099
+
5100
+ // Scan files for security issues
5101
+ const scanDirectory = (dir, depth = 0) => {
5102
+ if (depth > 3) return;
5103
+
5104
+ try {
5105
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
5106
+
5107
+ for (const entry of entries) {
5108
+ const fullPath = path.join(dir, entry.name);
5109
+
5110
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
5111
+
5112
+ if (entry.isFile() && this.isCodeFile(entry.name)) {
5113
+ this.scanFileForSecurity(fullPath, securityPatterns, securityReport);
5114
+ } else if (entry.isDirectory()) {
5115
+ scanDirectory(fullPath, depth + 1);
5116
+ }
5117
+ }
5118
+ } catch (error) {
5119
+ // Skip directories we can't read
5120
+ }
5121
+ };
5122
+
5123
+ scanDirectory(process.cwd());
5124
+
5125
+ // Check dependencies for known vulnerabilities
5126
+ this.checkDependencyVulnerabilities(securityReport);
5127
+
5128
+ // Calculate final score
5129
+ const criticalCount = securityReport.vulnerabilities.critical.length;
5130
+ const highCount = securityReport.vulnerabilities.high.length;
5131
+ const mediumCount = securityReport.vulnerabilities.medium.length;
5132
+ const lowCount = securityReport.vulnerabilities.low.length;
5133
+
5134
+ securityReport.score = Math.max(0, 100 - (criticalCount * 25) - (highCount * 15) - (mediumCount * 10) - (lowCount * 5));
5135
+
5136
+ // Generate recommendations based on findings
5137
+ if (criticalCount > 0) {
5138
+ securityReport.recommendations.push('🚨 Address critical vulnerabilities immediately');
5139
+ }
5140
+ if (highCount > 0) {
5141
+ securityReport.recommendations.push('⚠️ Review and fix high-risk security issues');
5142
+ }
5143
+
5144
+ securityReport.recommendations.push('🔒 Use environment variables for sensitive data');
5145
+ securityReport.recommendations.push('🛡️ Implement input validation and sanitization');
5146
+ securityReport.recommendations.push('📦 Keep dependencies updated regularly');
5147
+ securityReport.recommendations.push('🔍 Consider using a security linter (ESLint security plugin)');
5148
+
5149
+ return securityReport;
5150
+ }
5151
+
5152
+ isCodeFile(filename) {
5153
+ const codeExtensions = ['.js', '.ts', '.py', '.java', '.cpp', '.c', '.cs', '.go', '.rs', '.php', '.rb'];
5154
+ return codeExtensions.some(ext => filename.toLowerCase().endsWith(ext));
5155
+ }
5156
+
5157
+ scanFileForSecurity(filePath, patterns, report) {
5158
+ const fs = require('fs');
5159
+
5160
+ try {
5161
+ const content = fs.readFileSync(filePath, 'utf8');
5162
+ const lines = content.split('\n');
5163
+
5164
+ for (const [severity, patternList] of Object.entries(patterns)) {
5165
+ for (const patternInfo of patternList) {
5166
+ for (let i = 0; i < lines.length; i++) {
5167
+ if (patternInfo.pattern.test(lines[i])) {
5168
+ report.vulnerabilities[severity].push({
5169
+ type: patternInfo.type,
5170
+ description: patternInfo.description,
5171
+ file: filePath.replace(process.cwd(), '.'),
5172
+ line: i + 1,
5173
+ code: lines[i].trim()
5174
+ });
5175
+ }
5176
+ }
5177
+ }
5178
+ }
5179
+ } catch (error) {
5180
+ // Skip files we can't read
5181
+ }
5182
+ }
5183
+
5184
+ checkDependencyVulnerabilities(report) {
5185
+ const fs = require('fs');
5186
+ const path = require('path');
5187
+
5188
+ try {
5189
+ const packagePath = path.join(process.cwd(), 'package.json');
5190
+ if (!fs.existsSync(packagePath)) return;
5191
+
5192
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
5193
+ const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
5194
+
5195
+ // Check for known vulnerable packages (simplified check)
5196
+ const knownVulnerablePackages = {
5197
+ 'lodash': { versions: ['< 4.17.21'], issue: 'Prototype pollution vulnerability', severity: 'High', fix: 'Update to latest version' },
5198
+ 'node-forge': { versions: ['< 1.0.0'], issue: 'RSA PKCS#1 signature verification issue', severity: 'High', fix: 'Update to 1.0.0+' },
5199
+ 'axios': { versions: ['< 0.21.2'], issue: 'Server-side request forgery', severity: 'Medium', fix: 'Update to 0.21.2+' }
5200
+ };
5201
+
5202
+ for (const [depName, version] of Object.entries(dependencies)) {
5203
+ if (knownVulnerablePackages[depName]) {
5204
+ const vuln = knownVulnerablePackages[depName];
5205
+ report.dependencyIssues.push({
5206
+ name: depName,
5207
+ version: version,
5208
+ issue: vuln.issue,
5209
+ severity: vuln.severity,
5210
+ fix: vuln.fix
5211
+ });
5212
+ }
5213
+ }
5214
+ } catch (error) {
5215
+ // Could not check dependencies
5216
+ }
5217
+ }
5218
+
5219
+ performOptimizationAnalysis() {
5220
+ console.log(chalk.cyan('⚡ Analyzing Performance...'));
5221
+ console.log('');
5222
+
5223
+ console.log(chalk.magenta('╭─────────────────────────────────────────╮'));
5224
+ console.log(chalk.magenta('│') + chalk.white.bold(' ⚡ Performance Analysis ') + chalk.magenta('│'));
5225
+ console.log(chalk.magenta('╰─────────────────────────────────────────╯'));
5226
+ console.log('');
5227
+
5228
+ const perfReport = this.performRealPerformanceAnalysis();
5229
+
5230
+ // Display performance score
5231
+ let scoreColor = 'green';
5232
+ if (perfReport.score < 60) scoreColor = 'red';
5233
+ else if (perfReport.score < 80) scoreColor = 'yellow';
5234
+
5235
+ console.log(chalk[scoreColor](`⚡ Performance Score: ${perfReport.score}/100`));
5236
+ console.log('');
5237
+
5238
+ // Display bottlenecks
5239
+ if (perfReport.bottlenecks.length > 0) {
5240
+ console.log(chalk.yellow('🐌 Performance Bottlenecks Detected:'));
5241
+ perfReport.bottlenecks.forEach(bottleneck => {
5242
+ console.log(chalk.white(` • ${bottleneck.type}: ${bottleneck.description}`));
5243
+ console.log(chalk.gray(` File: ${bottleneck.file}:${bottleneck.line}`));
5244
+ });
5245
+ console.log('');
5246
+ }
5247
+
5248
+ // Display file size issues
5249
+ if (perfReport.fileSizeIssues.length > 0) {
5250
+ console.log(chalk.yellow('📁 Large File Issues:'));
5251
+ perfReport.fileSizeIssues.forEach(issue => {
5252
+ console.log(chalk.white(` • ${issue.file}: ${issue.sizeKB}KB (${issue.description})`));
5253
+ });
5254
+ console.log('');
5255
+ }
5256
+
5257
+ // Display dependency analysis
5258
+ if (perfReport.dependencyImpact.heavyDependencies.length > 0) {
5259
+ console.log(chalk.yellow('📦 Heavy Dependencies:'));
5260
+ perfReport.dependencyImpact.heavyDependencies.forEach(dep => {
5261
+ console.log(chalk.white(` • ${dep}: Large bundle size impact`));
5262
+ });
5263
+ console.log('');
5264
+ }
5265
+
5266
+ // Display optimization suggestions
5267
+ if (perfReport.optimizations.length > 0) {
5268
+ console.log(chalk.cyan('🚀 Optimization Suggestions:'));
5269
+ perfReport.optimizations.forEach(opt => {
5270
+ console.log(chalk.white(` • ${opt}`));
5271
+ });
5272
+ console.log('');
5273
+ }
5274
+
5275
+ // Show memory usage patterns
5276
+ if (perfReport.memoryPatterns.length > 0) {
5277
+ console.log(chalk.blue('🧠 Memory Usage Patterns:'));
5278
+ perfReport.memoryPatterns.forEach(pattern => {
5279
+ console.log(chalk.white(` • ${pattern.type}: ${pattern.description}`));
5280
+ if (pattern.file) {
5281
+ console.log(chalk.gray(` File: ${pattern.file}:${pattern.line}`));
5282
+ }
5283
+ });
5284
+ console.log('');
5285
+ }
5286
+
5287
+ // Summary
5288
+ const totalIssues = perfReport.bottlenecks.length + perfReport.fileSizeIssues.length;
5289
+ if (totalIssues === 0) {
5290
+ console.log(chalk.green('✅ No major performance issues detected'));
5291
+ } else {
5292
+ console.log(chalk.yellow(`📊 Total Performance Issues: ${totalIssues}`));
5293
+ }
5294
+ }
5295
+
5296
+ performRealPerformanceAnalysis() {
5297
+ const fs = require('fs');
5298
+ const path = require('path');
5299
+
5300
+ const perfReport = {
5301
+ score: 100,
5302
+ bottlenecks: [],
5303
+ fileSizeIssues: [],
5304
+ dependencyImpact: {
5305
+ heavyDependencies: [],
5306
+ totalDependencies: 0
5307
+ },
5308
+ memoryPatterns: [],
5309
+ optimizations: []
5310
+ };
5311
+
5312
+ // Performance anti-patterns to detect
5313
+ const performancePatterns = [
5314
+ { pattern: /for\s*\(.*\.length.*\)/, type: 'Loop Optimization', description: 'Loop with .length in condition - cache length outside loop' },
5315
+ { pattern: /document\.getElementById.*\(/, type: 'DOM Query', description: 'Repeated DOM queries - consider caching elements' },
5316
+ { pattern: /\$\(.*\)\..*\$\(.*\)/, type: 'jQuery Chaining', description: 'Multiple jQuery selectors - consider chaining or caching' },
5317
+ { pattern: /setInterval\s*\(.*1\)/, type: 'High Frequency Timer', description: 'Very high frequency interval detected' },
5318
+ { pattern: /JSON\.parse\s*\(.*JSON\.stringify/, type: 'Deep Clone', description: 'Inefficient deep cloning - consider structured clone or lodash' },
5319
+ { pattern: /new\s+Array\s*\(/, type: 'Array Constructor', description: 'Use array literal [] instead of new Array()' },
5320
+ { pattern: /\.innerHTML\s*\+=/, type: 'DOM Manipulation', description: 'Inefficient DOM updates - consider batch operations' },
5321
+ { pattern: /require\s*\(.*\).*require\s*\(.*\)/, type: 'Module Loading', description: 'Multiple requires in same scope - consider combining imports' }
5322
+ ];
5323
+
5324
+ // Memory leak patterns
5325
+ const memoryPatterns = [
5326
+ { pattern: /addEventListener.*(?!removeEventListener)/, type: 'Event Listener Leak', description: 'Event listener without cleanup' },
5327
+ { pattern: /setInterval.*(?!clearInterval)/, type: 'Timer Leak', description: 'setInterval without clearInterval' },
5328
+ { pattern: /setTimeout.*(?!clearTimeout)/, type: 'Timer Leak', description: 'setTimeout pattern that might not clear' },
5329
+ { pattern: /closure.*function.*closure/, type: 'Closure Chain', description: 'Potential closure memory retention' }
5330
+ ];
5331
+
5332
+ // Scan files for performance issues
5333
+ const scanDirectory = (dir, depth = 0) => {
5334
+ if (depth > 3) return;
5335
+
5336
+ try {
5337
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
5338
+
5339
+ for (const entry of entries) {
5340
+ const fullPath = path.join(dir, entry.name);
5341
+
5342
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
5343
+
5344
+ if (entry.isFile()) {
5345
+ // Check file size
5346
+ const stats = fs.statSync(fullPath);
5347
+ const sizeKB = Math.round(stats.size / 1024);
5348
+
5349
+ if (sizeKB > 500 && this.isCodeFile(entry.name)) {
5350
+ perfReport.fileSizeIssues.push({
5351
+ file: fullPath.replace(process.cwd(), '.'),
5352
+ sizeKB: sizeKB,
5353
+ description: sizeKB > 1000 ? 'Very large file - consider splitting' : 'Large file - review for optimization'
5354
+ });
5355
+ }
5356
+
5357
+ // Scan code files for performance patterns
5358
+ if (this.isCodeFile(entry.name)) {
5359
+ this.scanFileForPerformance(fullPath, performancePatterns, memoryPatterns, perfReport);
5360
+ }
5361
+ } else if (entry.isDirectory()) {
5362
+ scanDirectory(fullPath, depth + 1);
5363
+ }
5364
+ }
5365
+ } catch (error) {
5366
+ // Skip directories we can't read
5367
+ }
5368
+ };
5369
+
5370
+ scanDirectory(process.cwd());
5371
+
5372
+ // Analyze dependencies
5373
+ this.analyzeDependencyPerformance(perfReport);
5374
+
5375
+ // Calculate score based on findings
5376
+ const bottleneckCount = perfReport.bottlenecks.length;
5377
+ const fileSizeIssueCount = perfReport.fileSizeIssues.length;
5378
+ const memoryIssueCount = perfReport.memoryPatterns.length;
5379
+
5380
+ perfReport.score = Math.max(0, 100 - (bottleneckCount * 10) - (fileSizeIssueCount * 5) - (memoryIssueCount * 8));
5381
+
5382
+ // Generate optimization recommendations
5383
+ if (bottleneckCount > 0) {
5384
+ perfReport.optimizations.push('🔧 Address performance bottlenecks in critical code paths');
5385
+ }
5386
+ if (fileSizeIssueCount > 0) {
5387
+ perfReport.optimizations.push('📦 Consider code splitting for large files');
5388
+ }
5389
+ if (memoryIssueCount > 0) {
5390
+ perfReport.optimizations.push('🧠 Implement proper memory management and cleanup');
5391
+ }
5392
+
5393
+ perfReport.optimizations.push('⚡ Use Web Workers for CPU-intensive tasks');
5394
+ perfReport.optimizations.push('🗂️ Implement lazy loading for non-critical resources');
5395
+ perfReport.optimizations.push('📊 Add performance monitoring and profiling');
5396
+ perfReport.optimizations.push('🔄 Consider using virtual scrolling for large lists');
5397
+
5398
+ return perfReport;
5399
+ }
5400
+
5401
+ scanFileForPerformance(filePath, performancePatterns, memoryPatterns, report) {
5402
+ const fs = require('fs');
5403
+
5404
+ try {
5405
+ const content = fs.readFileSync(filePath, 'utf8');
5406
+ const lines = content.split('\n');
5407
+
5408
+ // Check for performance bottlenecks
5409
+ for (const patternInfo of performancePatterns) {
5410
+ for (let i = 0; i < lines.length; i++) {
5411
+ if (patternInfo.pattern.test(lines[i])) {
5412
+ report.bottlenecks.push({
5413
+ type: patternInfo.type,
5414
+ description: patternInfo.description,
5415
+ file: filePath.replace(process.cwd(), '.'),
5416
+ line: i + 1,
5417
+ code: lines[i].trim()
5418
+ });
5419
+ }
5420
+ }
5421
+ }
5422
+
5423
+ // Check for memory patterns
5424
+ for (const patternInfo of memoryPatterns) {
5425
+ for (let i = 0; i < lines.length; i++) {
5426
+ if (patternInfo.pattern.test(lines[i])) {
5427
+ report.memoryPatterns.push({
5428
+ type: patternInfo.type,
5429
+ description: patternInfo.description,
5430
+ file: filePath.replace(process.cwd(), '.'),
5431
+ line: i + 1,
5432
+ code: lines[i].trim()
5433
+ });
5434
+ }
5435
+ }
5436
+ }
5437
+ } catch (error) {
5438
+ // Skip files we can't read
5439
+ }
5440
+ }
5441
+
5442
+ analyzeDependencyPerformance(report) {
5443
+ const fs = require('fs');
5444
+ const path = require('path');
5445
+
5446
+ try {
5447
+ const packagePath = path.join(process.cwd(), 'package.json');
5448
+ if (!fs.existsSync(packagePath)) return;
5449
+
5450
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
5451
+ const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
5452
+
5453
+ report.dependencyImpact.totalDependencies = Object.keys(dependencies).length;
5454
+
5455
+ // Known heavy dependencies that impact performance
5456
+ const heavyDependencies = ['lodash', 'moment', 'jquery', 'axios', 'react', 'vue', 'angular'];
5457
+
5458
+ for (const depName of Object.keys(dependencies)) {
5459
+ if (heavyDependencies.includes(depName)) {
5460
+ report.dependencyImpact.heavyDependencies.push(depName);
5461
+ }
5462
+ }
5463
+
5464
+ // Add recommendations based on dependency analysis
5465
+ if (dependencies['lodash']) {
5466
+ report.optimizations.push('Consider using native ES6 methods instead of lodash where possible');
5467
+ }
5468
+ if (dependencies['moment']) {
5469
+ report.optimizations.push('Consider using date-fns or dayjs instead of moment.js for smaller bundle size');
5470
+ }
5471
+
5472
+ } catch (error) {
5473
+ // Skip dependency analysis if package.json is not readable
5474
+ }
5475
+ }
5476
+
5477
+ cycleTheme() {
5478
+ if (!this.currentTheme) this.currentTheme = 'neon-purple';
5479
+
5480
+ const themes = ['neon-purple', 'matrix-green', 'ocean-blue', 'sunset-orange'];
5481
+ const currentIndex = themes.indexOf(this.currentTheme);
5482
+ const nextIndex = (currentIndex + 1) % themes.length;
5483
+ this.currentTheme = themes[nextIndex];
5484
+
5485
+ console.log(chalk.cyan(`🎨 Theme switched to: ${this.currentTheme}`));
5486
+ console.log(chalk.gray('New color scheme will apply to future messages'));
5487
+ console.log('');
5488
+ }
5489
+
5490
+ async cleanup() {
5491
+ this.logger.info('Starting cleanup process');
5492
+
5493
+ // Clean up streaming and loading animations
5494
+ this.stopProgressiveLoading();
5495
+ this.stopStreamingDisplay();
5496
+
5497
+ if (this.fileWatcher) {
5498
+ this.fileWatcher.close();
5499
+ this.fileWatcher = null;
5500
+ this.logger.debug('File watcher closed');
5501
+ }
5502
+
5503
+ // Cleanup voice manager
5504
+ if (this.voiceManager) {
5505
+ this.voiceManager.cleanup();
5506
+ this.logger.debug('Voice manager cleaned up');
5507
+ }
5508
+
5509
+ // Cleanup collaboration manager
5510
+ if (this.collaborationManager) {
5511
+ this.collaborationManager.cleanup();
5512
+ this.logger.debug('Collaboration manager cleaned up');
5513
+ }
5514
+
5515
+ // Cleanup plugins
5516
+ if (this.pluginManager) {
5517
+ await this.pluginManager.cleanup();
5518
+ this.logger.debug('Plugins cleaned up');
5519
+ }
5520
+
5521
+ // End session logging
5522
+ if (this.logger) {
5523
+ this.logger.endSession();
5524
+ this.logger.info('Session cleanup completed');
5525
+ }
5526
+ }
5527
+
5528
+ /**
5529
+ * Load user configuration from onboarding
5530
+ */
5531
+ loadUserConfig() {
5532
+ const path = require('path');
5533
+ const fs = require('fs');
5534
+ const configFile = path.join(require('os').homedir(), '.recoder-code', 'config.json');
5535
+
5536
+ try {
5537
+ if (fs.existsSync(configFile)) {
5538
+ return JSON.parse(fs.readFileSync(configFile, 'utf8'));
5539
+ }
5540
+ } catch (error) {
5541
+ // Return empty config if can't load
5542
+ }
5543
+
5544
+ return {};
4131
5545
  }
4132
5546
 
4133
5547
  start() {