git-ai-review 2.3.3 → 2.4.1
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/dist/cli.d.ts +1 -0
- package/dist/cli.js +20 -7
- package/dist/precommit.d.ts +1 -0
- package/dist/precommit.js +1 -1
- package/dist/review.d.ts +1 -0
- package/dist/review.js +42 -0
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export declare function hasVerboseFlag(args: string[]): boolean;
|
|
|
12
12
|
export declare function hasClaudeFlag(args: string[]): boolean;
|
|
13
13
|
export declare function hasCodexFlag(args: string[]): boolean;
|
|
14
14
|
export declare function hasCopilotFlag(args: string[]): boolean;
|
|
15
|
+
export declare function hasAllReviewersFlag(args: string[]): boolean;
|
|
15
16
|
export declare function runCli(argv?: string[], deps?: CliDeps): Promise<number>;
|
package/dist/cli.js
CHANGED
|
@@ -22,10 +22,11 @@ function printHelp(log) {
|
|
|
22
22
|
log(' install Install .githooks/pre-commit and set core.hooksPath');
|
|
23
23
|
log('');
|
|
24
24
|
log('Options:');
|
|
25
|
-
log(' --codex
|
|
26
|
-
log(' --copilot
|
|
27
|
-
log(' --claude
|
|
28
|
-
log(' --
|
|
25
|
+
log(' --codex Force Codex reviewer only (skip Copilot/Claude fallback)');
|
|
26
|
+
log(' --copilot Force Copilot reviewer only (skip Codex/Claude)');
|
|
27
|
+
log(' --claude Force Claude reviewer only (skip Codex/Copilot)');
|
|
28
|
+
log(' --all-reviewers Run all 3 reviewers sequentially (not just first available)');
|
|
29
|
+
log(' --verbose Write full prompt and raw model outputs to .git/ai-review-verbose.log');
|
|
29
30
|
}
|
|
30
31
|
export function hasVerboseFlag(args) {
|
|
31
32
|
return args.includes('--verbose');
|
|
@@ -39,22 +40,34 @@ export function hasCodexFlag(args) {
|
|
|
39
40
|
export function hasCopilotFlag(args) {
|
|
40
41
|
return args.includes('--copilot');
|
|
41
42
|
}
|
|
43
|
+
export function hasAllReviewersFlag(args) {
|
|
44
|
+
return args.includes('--all-reviewers');
|
|
45
|
+
}
|
|
42
46
|
export async function runCli(argv = process.argv.slice(2), deps = DEFAULT_CLI_DEPS) {
|
|
47
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
48
|
+
printHelp(deps.log);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
43
51
|
const command = argv[0] || 'help';
|
|
44
52
|
const args = argv.slice(1);
|
|
45
53
|
const verbose = hasVerboseFlag(args);
|
|
46
54
|
const useClaude = hasClaudeFlag(args);
|
|
47
55
|
const useCodex = hasCodexFlag(args);
|
|
48
56
|
const useCopilot = hasCopilotFlag(args);
|
|
57
|
+
const allReviewers = hasAllReviewersFlag(args);
|
|
49
58
|
const cwd = deps.getCwd();
|
|
50
59
|
const selectedCount = [useClaude, useCodex, useCopilot].filter(Boolean).length;
|
|
51
60
|
if (selectedCount > 1) {
|
|
52
61
|
deps.log('Error: --claude, --codex, and --copilot are mutually exclusive.');
|
|
53
62
|
return 1;
|
|
54
63
|
}
|
|
64
|
+
if (allReviewers && selectedCount > 0) {
|
|
65
|
+
deps.log('Error: --all-reviewers cannot be combined with --claude, --codex, or --copilot.');
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
55
68
|
const reviewer = useClaude ? 'claude' : useCodex ? 'codex' : useCopilot ? 'copilot' : undefined;
|
|
56
69
|
if (command === 'review') {
|
|
57
|
-
const result = await deps.runReview(cwd, { verbose, reviewer });
|
|
70
|
+
const result = await deps.runReview(cwd, { verbose, reviewer, allReviewers });
|
|
58
71
|
return result.pass ? 0 : 1;
|
|
59
72
|
}
|
|
60
73
|
if (command === 'diff') {
|
|
@@ -65,14 +78,14 @@ export async function runCli(argv = process.argv.slice(2), deps = DEFAULT_CLI_DE
|
|
|
65
78
|
deps.log('Error: diff command requires a base branch. Usage: git-ai-review diff <base> [head]');
|
|
66
79
|
return 1;
|
|
67
80
|
}
|
|
68
|
-
const result = await deps.runReview(cwd, { verbose, reviewer }, {
|
|
81
|
+
const result = await deps.runReview(cwd, { verbose, reviewer, allReviewers }, {
|
|
69
82
|
getStagedDiff: () => getDiffBetweenRefs(base, head, cwd),
|
|
70
83
|
buildPrompt: (diff, promptCwd) => buildPrompt(diff, promptCwd, `Branch diff (${base}...${head})`),
|
|
71
84
|
});
|
|
72
85
|
return result.pass ? 0 : 1;
|
|
73
86
|
}
|
|
74
87
|
if (command === 'pre-commit') {
|
|
75
|
-
return await deps.runPreCommit(cwd, { verbose, reviewer });
|
|
88
|
+
return await deps.runPreCommit(cwd, { verbose, reviewer, allReviewers });
|
|
76
89
|
}
|
|
77
90
|
if (command === 'install') {
|
|
78
91
|
deps.installPreCommitHook();
|
package/dist/precommit.d.ts
CHANGED
package/dist/precommit.js
CHANGED
|
@@ -42,7 +42,7 @@ export async function runPreCommit(cwd = process.cwd(), options = {}, deps = {})
|
|
|
42
42
|
printLastReport(reportPath);
|
|
43
43
|
return 1;
|
|
44
44
|
}
|
|
45
|
-
const review = await runReviewFn(cwd, { verbose, reviewer: options.reviewer });
|
|
45
|
+
const review = await runReviewFn(cwd, { verbose, reviewer: options.reviewer, allReviewers: options.allReviewers });
|
|
46
46
|
if (review.pass) {
|
|
47
47
|
rmSync(failCountPath, { force: true });
|
|
48
48
|
return 0;
|
package/dist/review.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare function clearLastUnavailable(cwd: string): void;
|
|
|
7
7
|
export interface RunReviewOptions {
|
|
8
8
|
verbose?: boolean;
|
|
9
9
|
reviewer?: 'claude' | 'codex' | 'copilot';
|
|
10
|
+
allReviewers?: boolean;
|
|
10
11
|
}
|
|
11
12
|
export interface RunReviewDeps {
|
|
12
13
|
getStagedDiff: () => string;
|
package/dist/review.js
CHANGED
|
@@ -488,6 +488,13 @@ function printReview(model, result, usage) {
|
|
|
488
488
|
export async function runReview(cwd = process.cwd(), options = {}, deps = {}) {
|
|
489
489
|
const verbose = options.verbose === true;
|
|
490
490
|
const reviewer = options.reviewer;
|
|
491
|
+
const allReviewers = options.allReviewers === true;
|
|
492
|
+
const verboseLogPath = verbose ? resolve(cwd, getGitPath('ai-review-verbose.log')) : null;
|
|
493
|
+
const verboseLines = [];
|
|
494
|
+
const appendVerbose = (line) => {
|
|
495
|
+
if (verbose)
|
|
496
|
+
verboseLines.push(line);
|
|
497
|
+
};
|
|
491
498
|
const runtimeDeps = {
|
|
492
499
|
getStagedDiff,
|
|
493
500
|
buildPrompt,
|
|
@@ -507,6 +514,9 @@ export async function runReview(cwd = process.cwd(), options = {}, deps = {}) {
|
|
|
507
514
|
}
|
|
508
515
|
const prompt = runtimeDeps.buildPrompt(diff, cwd);
|
|
509
516
|
if (verbose) {
|
|
517
|
+
appendVerbose(`[${new Date().toISOString()}] ----- REVIEW PROMPT (FULL) -----`);
|
|
518
|
+
appendVerbose(prompt);
|
|
519
|
+
appendVerbose('----- END REVIEW PROMPT -----\n');
|
|
510
520
|
runtimeDeps.log('----- REVIEW PROMPT (FULL) -----');
|
|
511
521
|
runtimeDeps.log(prompt);
|
|
512
522
|
runtimeDeps.log('----- END REVIEW PROMPT -----');
|
|
@@ -526,6 +536,27 @@ export async function runReview(cwd = process.cwd(), options = {}, deps = {}) {
|
|
|
526
536
|
runtimeDeps.log('Running Codex review (--codex)...');
|
|
527
537
|
codex = await runtimeDeps.runCodex(prompt, verbose, true);
|
|
528
538
|
}
|
|
539
|
+
else if (allReviewers) {
|
|
540
|
+
const runners = [
|
|
541
|
+
['codex', 'Codex', runtimeDeps.runCodex],
|
|
542
|
+
['copilot', 'Copilot', runtimeDeps.runCopilot],
|
|
543
|
+
['claude', 'Claude', runtimeDeps.runClaude],
|
|
544
|
+
];
|
|
545
|
+
const results = {
|
|
546
|
+
codex: { available: false },
|
|
547
|
+
copilot: { available: false },
|
|
548
|
+
claude: { available: false },
|
|
549
|
+
};
|
|
550
|
+
for (const [name, label, runner] of runners) {
|
|
551
|
+
runtimeDeps.log(`Running ${label} review...`);
|
|
552
|
+
appendVerbose(`[${new Date().toISOString()}] Running ${label} review...`);
|
|
553
|
+
results[name] = await runner(prompt, verbose);
|
|
554
|
+
appendVerbose(`[${new Date().toISOString()}] ${label}: ${results[name].available ? 'completed' : 'unavailable'}`);
|
|
555
|
+
}
|
|
556
|
+
claude = results.claude;
|
|
557
|
+
codex = results.codex;
|
|
558
|
+
copilot = results.copilot;
|
|
559
|
+
}
|
|
529
560
|
else {
|
|
530
561
|
const lastUnavailable = readLastUnavailable(cwd);
|
|
531
562
|
const fallbackOrder = buildFallbackOrder(lastUnavailable);
|
|
@@ -593,6 +624,17 @@ export async function runReview(cwd = process.cwd(), options = {}, deps = {}) {
|
|
|
593
624
|
}
|
|
594
625
|
const verdict = evaluateResults(claude, codex, copilot);
|
|
595
626
|
console.log(`\n${verdict.reason}`);
|
|
627
|
+
if (verboseLogPath && verboseLines.length > 0) {
|
|
628
|
+
appendVerbose(`\n[${new Date().toISOString()}] Verdict: ${verdict.reason}`);
|
|
629
|
+
appendVerbose(`Report: ${JSON.stringify(report, null, 2)}`);
|
|
630
|
+
try {
|
|
631
|
+
writeFileSync(verboseLogPath, verboseLines.join('\n'), 'utf8');
|
|
632
|
+
console.log(`Verbose log written to: ${verboseLogPath}`);
|
|
633
|
+
}
|
|
634
|
+
catch {
|
|
635
|
+
console.error(`Warning: could not write verbose log to ${verboseLogPath}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
596
638
|
return { pass: verdict.pass, reportPath, reason: verdict.reason };
|
|
597
639
|
}
|
|
598
640
|
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-ai-review",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Review your git diff with local Codex CLI, Copilot CLI, or Claude CLI — run manually in one command or automatically as a git hook",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|