coderev-cli 1.0.10 → 1.0.12
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/package.json +1 -1
- package/src/cli.js +47 -44
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -214,7 +214,7 @@ program
|
|
|
214
214
|
const https = require('https');
|
|
215
215
|
const prInfo = await new Promise((resolve, reject) => {
|
|
216
216
|
https.get('https://api.github.com/repos/' + prRef.owner + '/' + prRef.repo + '/pulls/' + prRef.pr, {
|
|
217
|
-
headers: { 'User-Agent': 'coderev', 'Accept': 'application/vnd.github.v3+json', 'Authorization': '
|
|
217
|
+
headers: { 'User-Agent': 'coderev', 'Accept': 'application/vnd.github.v3+json', 'Authorization': 'token ' + token },
|
|
218
218
|
}, (r) => { let b=''; r.on('data',c=>b+=c); r.on('end',()=>{ try{resolve(JSON.parse(b))}catch{reject()}}); }).on('error', reject);
|
|
219
219
|
});
|
|
220
220
|
|
|
@@ -340,10 +340,10 @@ program
|
|
|
340
340
|
const aiResponse = await callAI(apiKey, fixPrompt, config);
|
|
341
341
|
|
|
342
342
|
// Extract patch from response
|
|
343
|
-
const patchMatch = aiResponse.match(
|
|
343
|
+
const patchMatch = aiResponse.match(/```diff\n([\s\S]*?)\n```/);
|
|
344
344
|
const patch = patchMatch ? patchMatch[1] : aiResponse;
|
|
345
345
|
|
|
346
|
-
console.log('\n' + chalk.bold('🩹 Fix Patch
|
|
346
|
+
console.log('\n' + chalk.bold('🩹 Fix Patch / 修复补丁:'));
|
|
347
347
|
console.log('━'.repeat(50));
|
|
348
348
|
console.log(patch);
|
|
349
349
|
|
|
@@ -381,7 +381,7 @@ program
|
|
|
381
381
|
const masked = JSON.parse(JSON.stringify(config));
|
|
382
382
|
if (masked.ai?.apiKey) masked.ai.apiKey = masked.ai.apiKey.slice(0, 8) + '...' + masked.ai.apiKey.slice(-4);
|
|
383
383
|
if (masked.github?.token) masked.github.token = masked.github.token.slice(0, 8) + '...' + masked.github.token.slice(-4);
|
|
384
|
-
console.log(chalk.bold('\n⚙ Active Configuration
|
|
384
|
+
console.log(chalk.bold('\n⚙ Active Configuration / 当前配置:'));
|
|
385
385
|
console.log('━'.repeat(50));
|
|
386
386
|
console.log(JSON.stringify(masked, null, 2));
|
|
387
387
|
} else if (action === 'validate') {
|
|
@@ -407,9 +407,9 @@ program
|
|
|
407
407
|
if (!parsed.ai?.provider) errors.push('Missing "ai.provider"');
|
|
408
408
|
if (!parsed.ai?.model) errors.push('Missing "ai.model"');
|
|
409
409
|
if (errors.length === 0) {
|
|
410
|
-
console.log(chalk.green(`✔ Config valid
|
|
410
|
+
console.log(chalk.green(`✔ Config valid / 配置有效: ${found}`));
|
|
411
411
|
} else {
|
|
412
|
-
console.log(chalk.yellow(`⚠ Config found but has issues
|
|
412
|
+
console.log(chalk.yellow(`⚠ Config found but has issues / 配置存在但有问题:`));
|
|
413
413
|
for (const e of errors) console.log(chalk.yellow(` ${e}`));
|
|
414
414
|
}
|
|
415
415
|
} catch (parseErr) {
|
|
@@ -463,20 +463,20 @@ program
|
|
|
463
463
|
return;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
console.log(chalk.bold('\n📊 Review Statistics'));
|
|
466
|
+
console.log(chalk.bold('\n📊 Review Statistics / 审查统计'));
|
|
467
467
|
console.log('━'.repeat(50));
|
|
468
|
-
console.log(` Period
|
|
469
|
-
console.log(` Total reviews
|
|
468
|
+
console.log(` Period / 周期: ${chalk.bold(period)}`);
|
|
469
|
+
console.log(` Total reviews / 总数: ${stats.total}`);
|
|
470
470
|
if (stats.totalAllTime > stats.total) {
|
|
471
|
-
console.log(` All time
|
|
471
|
+
console.log(` All time / 累计: ${stats.totalAllTime}`);
|
|
472
472
|
}
|
|
473
|
-
console.log(` Avg score
|
|
474
|
-
console.log(` Highest
|
|
475
|
-
console.log(` Lowest
|
|
476
|
-
console.log(` Total issues
|
|
473
|
+
console.log(` Avg score / 平均分: ${chalk.cyan(stats.averageScore)}`);
|
|
474
|
+
console.log(` Highest / 最高: ${chalk.green(stats.highestScore)}`);
|
|
475
|
+
console.log(` Lowest / 最低: ${chalk.red(stats.lowestScore)}`);
|
|
476
|
+
console.log(` Total issues / 问题数: ${chalk.yellow(stats.totalIssues)}`);
|
|
477
477
|
|
|
478
478
|
if (Object.keys(stats.issueTypes).length > 0) {
|
|
479
|
-
console.log(chalk.bold('\n Issue Types
|
|
479
|
+
console.log(chalk.bold('\n Issue Types / 问题类型:'));
|
|
480
480
|
for (const [type, count] of Object.entries(stats.issueTypes)) {
|
|
481
481
|
const icon = type === 'error' ? chalk.red('✖') : type === 'warning' ? chalk.yellow('⚠') : chalk.blue('ℹ');
|
|
482
482
|
console.log(` ${icon} ${type}: ${count}`);
|
|
@@ -484,10 +484,11 @@ program
|
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
if (Object.keys(stats.severityBreakdown).length > 0) {
|
|
487
|
-
console.log(chalk.bold('\n Severity
|
|
487
|
+
console.log(chalk.bold('\n Severity / 严重程度:'));
|
|
488
488
|
for (const [sev, count] of Object.entries(stats.severityBreakdown)) {
|
|
489
489
|
const color = sev === 'high' ? chalk.red : sev === 'medium' ? chalk.yellow : chalk.blue;
|
|
490
|
-
|
|
490
|
+
const sevLabel = sev === 'high' ? '严重' : sev === 'medium' ? '中等' : sev === 'low' ? '轻微' : sev;
|
|
491
|
+
console.log(` ${color('●')} ${sevLabel}: ${count}`);
|
|
491
492
|
}
|
|
492
493
|
}
|
|
493
494
|
|
|
@@ -640,43 +641,44 @@ async function getGitDiff(repoPath, base = 'main', head) {
|
|
|
640
641
|
|
|
641
642
|
function formatTerminal(result) {
|
|
642
643
|
const lines = [];
|
|
643
|
-
lines.push(chalk.bold('\n📋 Code Review Report'));
|
|
644
|
+
lines.push(chalk.bold('\n📋 Code Review Report / 代码审查报告'));
|
|
644
645
|
lines.push('━'.repeat(50));
|
|
645
646
|
|
|
646
647
|
if (result.summary) {
|
|
647
|
-
lines.push(
|
|
648
|
+
lines.push('\n' + chalk.bold('Summary / 摘要:') + ' ' + result.summary);
|
|
648
649
|
}
|
|
649
650
|
|
|
650
651
|
if (result.score !== undefined && result.score !== null) {
|
|
651
652
|
const color = result.score >= 80 ? chalk.green : result.score >= 50 ? chalk.yellow : chalk.red;
|
|
652
|
-
lines.push(
|
|
653
|
+
lines.push('\n' + chalk.bold('Score / 评分:') + ' ' + color(result.score + '/100'));
|
|
653
654
|
}
|
|
654
655
|
|
|
655
656
|
if (result.issues && result.issues.length > 0) {
|
|
656
|
-
lines.push(
|
|
657
|
+
lines.push('\n' + chalk.bold('Issues / 问题 (' + result.issues.length + '):'));
|
|
657
658
|
for (const issue of result.issues) {
|
|
658
659
|
const typeLabel =
|
|
659
660
|
issue.type === 'error' ? chalk.red('✖') :
|
|
660
661
|
issue.type === 'warning' ? chalk.yellow('⚠') : chalk.blue('ℹ');
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
if (issue.
|
|
665
|
-
if (issue.
|
|
662
|
+
const sevLabel = issue.severity === 'high' ? '严重' : issue.severity === 'medium' ? '中等' : issue.severity === 'low' ? '轻微' : '';
|
|
663
|
+
const severity = issue.severity ? ' [' + sevLabel + ']' : '';
|
|
664
|
+
lines.push(' ' + typeLabel + severity + ' ' + issue.message);
|
|
665
|
+
if (issue.file) lines.push(' ' + chalk.gray('File / 文件:') + ' ' + issue.file);
|
|
666
|
+
if (issue.line) lines.push(' ' + chalk.gray('Line / 行:') + ' ' + issue.line);
|
|
667
|
+
if (issue.suggestion) lines.push(' ' + chalk.gray('Suggestion / 建议:') + ' ' + issue.suggestion);
|
|
666
668
|
}
|
|
667
669
|
}
|
|
668
670
|
|
|
669
671
|
if (result.suggestions && result.suggestions.length > 0) {
|
|
670
|
-
lines.push(
|
|
672
|
+
lines.push('\n' + chalk.bold('Suggestions / 改进建议:'));
|
|
671
673
|
for (const s of result.suggestions) {
|
|
672
|
-
lines.push(
|
|
674
|
+
lines.push(' 💡 ' + s);
|
|
673
675
|
}
|
|
674
676
|
}
|
|
675
677
|
|
|
676
678
|
if (result.praise && result.praise.length > 0) {
|
|
677
|
-
lines.push(
|
|
679
|
+
lines.push('\n' + chalk.bold('👍 Good Practices / 好的实践:'));
|
|
678
680
|
for (const p of result.praise) {
|
|
679
|
-
lines.push(
|
|
681
|
+
lines.push(' ✅ ' + p);
|
|
680
682
|
}
|
|
681
683
|
}
|
|
682
684
|
|
|
@@ -685,31 +687,32 @@ function formatTerminal(result) {
|
|
|
685
687
|
}
|
|
686
688
|
|
|
687
689
|
function formatMarkdown(result) {
|
|
688
|
-
let md = '# 📋 Code Review Report
|
|
690
|
+
let md = '# 📋 Code Review Report / 代码审查报告\n\n';
|
|
689
691
|
|
|
690
|
-
if (result.summary) md +=
|
|
691
|
-
if (result.score !== undefined) md +=
|
|
692
|
+
if (result.summary) md += '**Summary / 摘要:** ' + result.summary + '\n\n';
|
|
693
|
+
if (result.score !== undefined) md += '**Score / 评分:** ' + result.score + '/100\n\n';
|
|
692
694
|
|
|
693
695
|
if (result.issues?.length) {
|
|
694
|
-
md +=
|
|
696
|
+
md += '## Issues / 问题 (' + result.issues.length + ')\n\n';
|
|
695
697
|
for (const issue of result.issues) {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
md +=
|
|
699
|
-
|
|
700
|
-
if (issue.
|
|
701
|
-
if (issue.
|
|
698
|
+
const sevLabel = issue.severity === 'high' ? '严重' : issue.severity === 'medium' ? '中等' : issue.severity === 'low' ? '轻微' : '';
|
|
699
|
+
md += '- **' + issue.type.toUpperCase() + '**';
|
|
700
|
+
if (sevLabel) md += ' [' + sevLabel + ']';
|
|
701
|
+
md += ': ' + issue.message + '\n';
|
|
702
|
+
if (issue.file) md += ' - File / 文件: `' + issue.file + '`\n';
|
|
703
|
+
if (issue.line) md += ' - Line / 行: ' + issue.line + '\n';
|
|
704
|
+
if (issue.suggestion) md += ' - Suggestion / 建议: ' + issue.suggestion + '\n';
|
|
702
705
|
}
|
|
703
706
|
}
|
|
704
707
|
|
|
705
708
|
if (result.suggestions?.length) {
|
|
706
|
-
md +=
|
|
707
|
-
for (const s of result.suggestions) md +=
|
|
709
|
+
md += '\n## Suggestions / 改进建议\n\n';
|
|
710
|
+
for (const s of result.suggestions) md += '- 💡 ' + s + '\n';
|
|
708
711
|
}
|
|
709
712
|
|
|
710
713
|
if (result.praise?.length) {
|
|
711
|
-
md +=
|
|
712
|
-
for (const p of result.praise) md +=
|
|
714
|
+
md += '\n## 👍 Good Practices / 好的实践\n\n';
|
|
715
|
+
for (const p of result.praise) md += '- ✅ ' + p + '\n';
|
|
713
716
|
}
|
|
714
717
|
|
|
715
718
|
return md;
|