codeflow-hook 1.3.0 → 1.4.0

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.
Files changed (2) hide show
  1. package/bin/codeflow-hook.js +102 -73
  2. package/package.json +1 -1
@@ -11,6 +11,9 @@ import readline from 'readline';
11
11
  import { indexProject } from './rag.js';
12
12
  import { orchestrateReview } from './agents.js';
13
13
 
14
+ // Import CLI integration service
15
+ import { indexProject, analyzeDiff } from '../services/cli-integration/src/index.js';
16
+
14
17
  // Export for use in agents module
15
18
  export { callAIProvider };
16
19
 
@@ -18,8 +21,8 @@ const program = new Command();
18
21
 
19
22
  program
20
23
  .name('codeflow-hook')
21
- .description('Interactive CI/CD simulator and AI-powered code reviewer')
22
- .version('1.0.0');
24
+ .description('Interactive CI/CD simulator and AI-powered code reviewer with EKG backend integration')
25
+ .version('4.0.0');
23
26
 
24
27
  // Configure AI provider settings
25
28
  program
@@ -199,41 +202,34 @@ program
199
202
  }
200
203
  });
201
204
 
202
- // Index project knowledge base for RAG
205
+ // Index repository via EKG Ingestion Service (Phase 4)
203
206
  program
204
207
  .command('index')
205
- .description('Index project files for Retrieval-Augmented Generation (RAG)')
206
- .option('-d, --dry-run', 'Show what files would be indexed without actually indexing')
208
+ .description('Index repository via EKG Ingestion Service')
209
+ .option('-d, --dry-run', 'Show what would be indexed without actually indexing')
207
210
  .action(async (options) => {
208
211
  try {
209
- const configPath = path.join(os.homedir(), '.codeflow-hook', 'config.json');
212
+ const spinner = ora('Submitting repository for EKG analysis...').start();
210
213
 
211
- if (!fs.existsSync(configPath)) {
212
- console.log(chalk.red('No configuration found. Run: codeflow-hook config -k <api-key>'));
213
- process.exit(1);
214
- }
214
+ const result = await indexProject({
215
+ dryRun: options.dryRun || false
216
+ });
215
217
 
216
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
217
- const spinner = ora('Indexing project knowledge base...').start();
218
+ spinner.succeed('Repository indexing initiated');
219
+ console.log(chalk.green(`✅ ${result.message}`));
218
220
 
219
- if (options.dryRun) {
220
- spinner.stop();
221
- console.log(chalk.blue('🔍 Dry run mode - files to be indexed:'));
222
- const { findKeyFiles } = await import('./rag.js');
223
- const keyFiles = await findKeyFiles(process.cwd());
224
- keyFiles.forEach(file => console.log(chalk.gray(` - ${file}`)));
225
- console.log(chalk.green(`📊 Total files to index: ${keyFiles.length}`));
226
- return;
221
+ if (result.repositoryId) {
222
+ console.log(chalk.blue(`📋 Repository ID: ${result.repositoryId}`));
227
223
  }
228
224
 
229
- const result = await indexProject(config);
225
+ if (result.stats) {
226
+ console.log(chalk.gray(`📊 Stats: ${JSON.stringify(result.stats, null, 2)}`));
227
+ }
230
228
 
231
- spinner.succeed('Knowledge base indexing complete');
232
- console.log(chalk.green(`✅ Indexed ${result.indexedFiles} files with ${result.totalChunks} chunks`));
233
- console.log(chalk.blue('📁 Knowledge base stored in: .codeflow/index/'));
229
+ console.log(chalk.cyan('🔗 Repository submitted to EKG Ingestion Service for analysis'));
234
230
 
235
231
  } catch (error) {
236
- console.error(chalk.red(`❌ Indexing failed: ${error.message}`));
232
+ console.log(chalk.red(`❌ Indexing failed: ${error.message}`));
237
233
  process.exit(1);
238
234
  }
239
235
  });
@@ -298,13 +294,12 @@ exit 0
298
294
  }
299
295
  });
300
296
 
301
- // Analyze diff with specialized AI agents
297
+ // Analyze diff with EKG Query Service context enhancement (Phase 4)
302
298
  program
303
299
  .command('analyze-diff')
304
- .description('Analyze git diff using specialized AI agents (RAG-enhanced)')
300
+ .description('Analyze git diff using EKG context enhancement')
305
301
  .argument('[diff]', 'Git diff content')
306
- .option('--legacy', 'Use legacy monolithic analysis instead of agentic workflow')
307
- .option('--no-rag', 'Disable RAG context retrieval')
302
+ .option('--legacy', 'Use legacy analysis instead of EKG-enhanced analysis')
308
303
  .action(async (diff, options) => {
309
304
  try {
310
305
  // Read diff content from stdin or argument
@@ -317,63 +312,34 @@ program
317
312
  diffContent = Buffer.concat(chunks).toString('utf8');
318
313
  }
319
314
 
320
- const configPath = path.join(os.homedir(), '.codeflow-hook', 'config.json');
321
-
322
- if (!fs.existsSync(configPath)) {
323
- console.log(chalk.red('No configuration found. Run: codeflow-hook config -k <api-key>'));
324
- process.exit(1);
325
- }
326
-
327
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
328
-
329
315
  if (diffContent.trim() === '') {
330
316
  console.log(chalk.gray('â„šī¸ No changes to analyze'));
331
317
  return;
332
318
  }
333
319
 
334
- // Legacy mode: use original monolithic analysis
335
- if (options.legacy) {
336
- const spinner = ora(`Analyzing code with ${config.provider}...`).start();
337
- const prompt = generateCodeReviewPrompt(diffContent);
320
+ console.log(chalk.blue('đŸ”Ŧ Analyzing diff with EKG context enhancement...'));
338
321
 
339
- let result;
340
- try {
341
- result = await callAIProvider(config, prompt);
342
- } catch (error) {
343
- spinner.fail('Analysis failed');
344
- console.error(chalk.red(`AI API Error: ${error.message}`));
345
- process.exit(1);
346
- }
347
-
348
- spinner.succeed('Analysis complete');
349
- displayAnalysisResults(result);
350
- return;
351
- }
322
+ const result = await analyzeDiff(diffContent, {
323
+ legacy: options.legacy || false,
324
+ outputFormat: 'console'
325
+ });
352
326
 
353
- // Agentic workflow mode
354
- const spinner = ora(`Running specialized code review agents...`).start();
327
+ if (result.success) {
328
+ console.log(chalk.green(`✅ ${result.message}`));
329
+ displayEKGAnalysisResults(result.analysis);
355
330
 
356
- let results;
357
- try {
358
- if (options.rag === false) {
359
- // Force no RAG context
360
- const { orchestrateReviewWithoutRAG } = await import('./agents.js');
361
- results = await orchestrateReviewWithoutRAG(diffContent, config);
362
- } else {
363
- // Use RAG-enabled workflow
364
- results = await orchestrateReview(diffContent, config);
331
+ if (result.stats) {
332
+ console.log(chalk.gray(`📊 EKG Queries: ${result.stats.ekg_queries}`));
333
+ console.log(chalk.gray(`đŸ‘Ĩ Similar Repos Found: ${result.stats.similar_repos_found}`));
334
+ console.log(chalk.gray(`âąī¸ Analysis Time: ${result.stats.analysis_time}ms`));
365
335
  }
366
- } catch (error) {
367
- spinner.fail('Analysis failed');
368
- console.error(chalk.red(`Agent analysis failed: ${error.message}`));
336
+ } else {
337
+ console.log(chalk.red(`❌ Analysis failed: ${result.message}`));
369
338
  process.exit(1);
370
339
  }
371
340
 
372
- spinner.succeed('Agentic analysis complete');
373
- displayAgenticResults(results);
374
-
375
341
  } catch (error) {
376
- console.log(chalk.red(`Configuration error: ${error.message}`));
342
+ console.log(chalk.red(`❌ Analysis error: ${error.message}`));
377
343
  process.exit(1);
378
344
  }
379
345
  });
@@ -734,5 +700,68 @@ function getTypeIcon(type) {
734
700
  }
735
701
  }
736
702
 
703
+ // Display EKG-enhanced analysis results (Phase 4)
704
+ function displayEKGAnalysisResults(analysis) {
705
+ if (!analysis) {
706
+ console.log(chalk.yellow('âš ī¸ No analysis results available'));
707
+ return;
708
+ }
709
+
710
+ // Display summary
711
+ if (analysis.summary) {
712
+ console.log(chalk.blue('📊 Analysis Summary:'));
713
+ console.log(` 📁 Files modified: ${analysis.summary.totalFiles}`);
714
+ console.log(` ➕ Additions: ${analysis.summary.totalAdditions}`);
715
+ console.log(` ➖ Deletions: ${analysis.summary.totalDeletions}`);
716
+ console.log(` 🧠 EKG enhanced: ${analysis.summary.ekgEnhanced ? 'Yes' : 'No'}`);
717
+ console.log();
718
+ }
719
+
720
+ // Display EKG context information
721
+ if (analysis.ekg_context) {
722
+ console.log(chalk.blue('🧠 EKG Context:'));
723
+ console.log(` 📚 Patterns analyzed: ${analysis.ekg_context.patterns_analyzed || 0}`);
724
+ console.log(` đŸ‘Ĩ Similar repositories: ${analysis.ekg_context.similar_repositories_found || 0}`);
725
+ console.log(` 🔍 Repository known to EKG: ${analysis.ekg_context.repository_known ? 'Yes' : 'No'}`);
726
+ console.log();
727
+ }
728
+
729
+ // Display issues
730
+ if (analysis.issues && analysis.issues.length > 0) {
731
+ console.log(chalk.yellow('âš ī¸ Issues Found:'));
732
+ analysis.issues.forEach(issue => {
733
+ const severityColor = getSeverityColor(issue.severity);
734
+ const typeIcon = getTypeIcon(issue.type);
735
+ console.log(` ${severityColor}${typeIcon} ${issue.severity}: ${issue.description}`);
736
+ });
737
+ console.log();
738
+ }
739
+
740
+ // Display recommendations
741
+ if (analysis.recommendations && analysis.recommendations.length > 0) {
742
+ console.log(chalk.green('💡 Recommendations:'));
743
+ analysis.recommendations.forEach(rec => {
744
+ const severityColor = getSeverityColor(rec.severity);
745
+ console.log(` ${severityColor}â€ĸ ${rec.description}`);
746
+ if (rec.file) {
747
+ console.log(chalk.gray(` 📁 File: ${rec.file}`));
748
+ }
749
+ });
750
+ console.log();
751
+ }
752
+
753
+ // Display file details
754
+ if (analysis.files && analysis.files.length > 0) {
755
+ console.log(chalk.blue('📂 Files Changed:'));
756
+ analysis.files.forEach(file => {
757
+ const changeType = file.isNew ? 'NEW' : 'MODIFIED';
758
+ const changeColor = file.isNew ? chalk.green : chalk.blue;
759
+ console.log(`${changeColor} ${changeType} ${file.path} (${file.language})`);
760
+ console.log(chalk.gray(` +${file.additions} -${file.deletions} changes`));
761
+ });
762
+ console.log();
763
+ }
764
+ }
765
+
737
766
  // Make sure the final line uses parseAsync
738
767
  program.parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeflow-hook",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "An interactive CI/CD simulator and lightweight pre-push code reviewer using Gemini AI",
5
5
  "type": "module",
6
6
  "main": "index.js",