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.
- package/bin/codeflow-hook.js +102 -73
- package/package.json +1 -1
package/bin/codeflow-hook.js
CHANGED
|
@@ -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('
|
|
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
|
|
205
|
+
// Index repository via EKG Ingestion Service (Phase 4)
|
|
203
206
|
program
|
|
204
207
|
.command('index')
|
|
205
|
-
.description('Index
|
|
206
|
-
.option('-d, --dry-run', 'Show what
|
|
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
|
|
212
|
+
const spinner = ora('Submitting repository for EKG analysis...').start();
|
|
210
213
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
214
|
+
const result = await indexProject({
|
|
215
|
+
dryRun: options.dryRun || false
|
|
216
|
+
});
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
+
spinner.succeed('Repository indexing initiated');
|
|
219
|
+
console.log(chalk.green(`â
${result.message}`));
|
|
218
220
|
|
|
219
|
-
if (
|
|
220
|
-
|
|
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
|
-
|
|
225
|
+
if (result.stats) {
|
|
226
|
+
console.log(chalk.gray(`đ Stats: ${JSON.stringify(result.stats, null, 2)}`));
|
|
227
|
+
}
|
|
230
228
|
|
|
231
|
-
|
|
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.
|
|
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
|
|
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
|
|
300
|
+
.description('Analyze git diff using EKG context enhancement')
|
|
305
301
|
.argument('[diff]', 'Git diff content')
|
|
306
|
-
.option('--legacy', 'Use legacy
|
|
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
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
354
|
-
|
|
327
|
+
if (result.success) {
|
|
328
|
+
console.log(chalk.green(`â
${result.message}`));
|
|
329
|
+
displayEKGAnalysisResults(result.analysis);
|
|
355
330
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
}
|
|
367
|
-
|
|
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(
|
|
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);
|