jstar-reviewer 2.2.0 ā 2.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/jstar.js +1 -1
- package/dist/scripts/reviewer.js +106 -3
- package/package.json +9 -10
- package/scripts/reviewer.ts +98 -3
package/bin/jstar.js
CHANGED
package/dist/scripts/reviewer.js
CHANGED
|
@@ -91,6 +91,32 @@ function chunkDiffByFile(diff) {
|
|
|
91
91
|
function sleep(ms) {
|
|
92
92
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
93
93
|
}
|
|
94
|
+
async function getDefaultBranch() {
|
|
95
|
+
try {
|
|
96
|
+
// Method 1: Check remote HEAD (most reliable)
|
|
97
|
+
try {
|
|
98
|
+
const remote = await git.remote(['show', 'origin']);
|
|
99
|
+
if (typeof remote === 'string') {
|
|
100
|
+
const match = remote.match(/HEAD branch: (\S+)/);
|
|
101
|
+
if (match)
|
|
102
|
+
return match[1];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
// No remote or network issue, proceed to local check
|
|
107
|
+
}
|
|
108
|
+
// Method 2: Check which common branch exists locally
|
|
109
|
+
const branches = await git.branchLocal();
|
|
110
|
+
if (branches.all.includes('main'))
|
|
111
|
+
return 'main';
|
|
112
|
+
if (branches.all.includes('master'))
|
|
113
|
+
return 'master';
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
// Fallback
|
|
117
|
+
}
|
|
118
|
+
return 'main';
|
|
119
|
+
}
|
|
94
120
|
/**
|
|
95
121
|
* Filter issues by confidence threshold and log what was removed
|
|
96
122
|
*/
|
|
@@ -172,12 +198,89 @@ async function main() {
|
|
|
172
198
|
const detective = new detective_1.Detective(SOURCE_DIR);
|
|
173
199
|
await detective.scan();
|
|
174
200
|
detective.report();
|
|
175
|
-
// 1.
|
|
176
|
-
const
|
|
201
|
+
// 1. Determine Diff Target
|
|
202
|
+
const args = process.argv.slice(2);
|
|
203
|
+
let diff;
|
|
204
|
+
let reviewTarget = "Staged Changes";
|
|
205
|
+
if (args.includes('--last')) {
|
|
206
|
+
reviewTarget = "Last Commit";
|
|
207
|
+
diff = await git.diff(["HEAD~1", "HEAD"]);
|
|
208
|
+
}
|
|
209
|
+
else if (args.includes('--commit')) {
|
|
210
|
+
const hashIndex = args.indexOf('--commit') + 1;
|
|
211
|
+
if (hashIndex < args.length) {
|
|
212
|
+
const hash = args[hashIndex];
|
|
213
|
+
reviewTarget = `Commit ${hash}`;
|
|
214
|
+
diff = await git.diff([`${hash}~1`, `${hash}`]);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
logger_1.Logger.error(chalk_1.default.red("ā Missing commit hash for --commit"));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (args.includes('--range')) {
|
|
222
|
+
const rangeIndex = args.indexOf('--range') + 1;
|
|
223
|
+
if (rangeIndex + 1 < args.length) {
|
|
224
|
+
const start = args[rangeIndex];
|
|
225
|
+
const end = args[rangeIndex + 1];
|
|
226
|
+
reviewTarget = `Range ${start}..${end}`;
|
|
227
|
+
diff = await git.diff([start, end]);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
logger_1.Logger.error(chalk_1.default.red("ā Missing arguments for --range (usage: --range <start> <end>)"));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (args.includes('--pr')) {
|
|
235
|
+
const prIndex = args.indexOf('--pr');
|
|
236
|
+
// Check for --base flag first
|
|
237
|
+
let baseBranch = 'main';
|
|
238
|
+
if (args.includes('--base')) {
|
|
239
|
+
const baseIndex = args.indexOf('--base') + 1;
|
|
240
|
+
if (baseIndex < args.length) {
|
|
241
|
+
baseBranch = args[baseIndex];
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
logger_1.Logger.error(chalk_1.default.red("ā Missing branch name for --base"));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
// Check positional argument (backward compatibility)
|
|
250
|
+
const potentialBase = args[prIndex + 1];
|
|
251
|
+
if (potentialBase && !potentialBase.startsWith('--')) {
|
|
252
|
+
baseBranch = potentialBase;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// Auto-detect
|
|
256
|
+
baseBranch = await getDefaultBranch();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
reviewTarget = `PR (HEAD vs ${baseBranch})`;
|
|
260
|
+
// Use triple-dot for merge-base difference (what a PR shows)
|
|
261
|
+
try {
|
|
262
|
+
diff = await git.diff([`${baseBranch}...HEAD`]);
|
|
263
|
+
}
|
|
264
|
+
catch (e) {
|
|
265
|
+
logger_1.Logger.error(chalk_1.default.red(`ā Failed to diff against ${baseBranch}. Does the branch exist?`));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// Default: Staged changes
|
|
271
|
+
diff = await git.diff(["--staged"]);
|
|
272
|
+
}
|
|
177
273
|
if (!diff) {
|
|
178
|
-
|
|
274
|
+
if (reviewTarget === "Staged Changes") {
|
|
275
|
+
logger_1.Logger.info(chalk_1.default.green("\nā
No staged changes to review. (Did you 'git add'?)"));
|
|
276
|
+
logger_1.Logger.info(chalk_1.default.dim(" Tip: Use '--last' to review the previous commit."));
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
logger_1.Logger.info(chalk_1.default.green(`\nā
No changes found in ${reviewTarget}.`));
|
|
280
|
+
}
|
|
179
281
|
return;
|
|
180
282
|
}
|
|
283
|
+
logger_1.Logger.info(chalk_1.default.blue(`\nš Reviewing: ${reviewTarget}`));
|
|
181
284
|
// 2. Load the Brain
|
|
182
285
|
if (!fs.existsSync(STORAGE_DIR)) {
|
|
183
286
|
logger_1.Logger.error(chalk_1.default.red("ā Local Brain not found. Run 'pnpm run index:init' first."));
|
package/package.json
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jstar-reviewer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Local-First, Context-Aware AI Code Reviewer - Works with any language",
|
|
5
5
|
"bin": {
|
|
6
6
|
"jstar": "bin/jstar.js"
|
|
7
7
|
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "tsc",
|
|
10
|
-
"index:init": "ts-node scripts/indexer.ts --init",
|
|
11
|
-
"index:watch": "ts-node scripts/indexer.ts --watch",
|
|
12
|
-
"review": "ts-node scripts/reviewer.ts",
|
|
13
|
-
"chat": "ts-node scripts/chat.ts",
|
|
14
|
-
"detect": "ts-node scripts/detective.ts",
|
|
15
|
-
"prepare": "husky install"
|
|
16
|
-
},
|
|
17
8
|
"keywords": [
|
|
18
9
|
"code-review",
|
|
19
10
|
"ai",
|
|
@@ -65,5 +56,13 @@
|
|
|
65
56
|
"type": "commonjs",
|
|
66
57
|
"bugs": {
|
|
67
58
|
"url": "https://github.com/JStaRFilms/jstar-code-review/issues"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsc",
|
|
62
|
+
"index:init": "ts-node scripts/indexer.ts --init",
|
|
63
|
+
"index:watch": "ts-node scripts/indexer.ts --watch",
|
|
64
|
+
"review": "ts-node scripts/reviewer.ts",
|
|
65
|
+
"chat": "ts-node scripts/chat.ts",
|
|
66
|
+
"detect": "ts-node scripts/detective.ts"
|
|
68
67
|
}
|
|
69
68
|
}
|
package/scripts/reviewer.ts
CHANGED
|
@@ -69,6 +69,30 @@ function sleep(ms: number): Promise<void> {
|
|
|
69
69
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
async function getDefaultBranch(): Promise<string> {
|
|
73
|
+
try {
|
|
74
|
+
// Method 1: Check remote HEAD (most reliable)
|
|
75
|
+
try {
|
|
76
|
+
const remote = await git.remote(['show', 'origin']);
|
|
77
|
+
if (typeof remote === 'string') {
|
|
78
|
+
const match = remote.match(/HEAD branch: (\S+)/);
|
|
79
|
+
if (match) return match[1];
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// No remote or network issue, proceed to local check
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Method 2: Check which common branch exists locally
|
|
86
|
+
const branches = await git.branchLocal();
|
|
87
|
+
if (branches.all.includes('main')) return 'main';
|
|
88
|
+
if (branches.all.includes('master')) return 'master';
|
|
89
|
+
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// Fallback
|
|
92
|
+
}
|
|
93
|
+
return 'main';
|
|
94
|
+
}
|
|
95
|
+
|
|
72
96
|
/**
|
|
73
97
|
* Filter issues by confidence threshold and log what was removed
|
|
74
98
|
*/
|
|
@@ -165,13 +189,84 @@ async function main() {
|
|
|
165
189
|
await detective.scan();
|
|
166
190
|
detective.report();
|
|
167
191
|
|
|
168
|
-
// 1.
|
|
169
|
-
const
|
|
192
|
+
// 1. Determine Diff Target
|
|
193
|
+
const args = process.argv.slice(2);
|
|
194
|
+
let diff: string;
|
|
195
|
+
let reviewTarget = "Staged Changes";
|
|
196
|
+
|
|
197
|
+
if (args.includes('--last')) {
|
|
198
|
+
reviewTarget = "Last Commit";
|
|
199
|
+
diff = await git.diff(["HEAD~1", "HEAD"]);
|
|
200
|
+
} else if (args.includes('--commit')) {
|
|
201
|
+
const hashIndex = args.indexOf('--commit') + 1;
|
|
202
|
+
if (hashIndex < args.length) {
|
|
203
|
+
const hash = args[hashIndex];
|
|
204
|
+
reviewTarget = `Commit ${hash}`;
|
|
205
|
+
diff = await git.diff([`${hash}~1`, `${hash}`]);
|
|
206
|
+
} else {
|
|
207
|
+
Logger.error(chalk.red("ā Missing commit hash for --commit"));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
} else if (args.includes('--range')) {
|
|
211
|
+
const rangeIndex = args.indexOf('--range') + 1;
|
|
212
|
+
if (rangeIndex + 1 < args.length) {
|
|
213
|
+
const start = args[rangeIndex];
|
|
214
|
+
const end = args[rangeIndex + 1];
|
|
215
|
+
reviewTarget = `Range ${start}..${end}`;
|
|
216
|
+
diff = await git.diff([start, end]);
|
|
217
|
+
} else {
|
|
218
|
+
Logger.error(chalk.red("ā Missing arguments for --range (usage: --range <start> <end>)"));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
} else if (args.includes('--pr')) {
|
|
222
|
+
const prIndex = args.indexOf('--pr');
|
|
223
|
+
// Check for --base flag first
|
|
224
|
+
let baseBranch = 'main';
|
|
225
|
+
|
|
226
|
+
if (args.includes('--base')) {
|
|
227
|
+
const baseIndex = args.indexOf('--base') + 1;
|
|
228
|
+
if (baseIndex < args.length) {
|
|
229
|
+
baseBranch = args[baseIndex];
|
|
230
|
+
} else {
|
|
231
|
+
Logger.error(chalk.red("ā Missing branch name for --base"));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
// Check positional argument (backward compatibility)
|
|
236
|
+
const potentialBase = args[prIndex + 1];
|
|
237
|
+
if (potentialBase && !potentialBase.startsWith('--')) {
|
|
238
|
+
baseBranch = potentialBase;
|
|
239
|
+
} else {
|
|
240
|
+
// Auto-detect
|
|
241
|
+
baseBranch = await getDefaultBranch();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
reviewTarget = `PR (HEAD vs ${baseBranch})`;
|
|
246
|
+
// Use triple-dot for merge-base difference (what a PR shows)
|
|
247
|
+
try {
|
|
248
|
+
diff = await git.diff([`${baseBranch}...HEAD`]);
|
|
249
|
+
} catch (e) {
|
|
250
|
+
Logger.error(chalk.red(`ā Failed to diff against ${baseBranch}. Does the branch exist?`));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
// Default: Staged changes
|
|
255
|
+
diff = await git.diff(["--staged"]);
|
|
256
|
+
}
|
|
257
|
+
|
|
170
258
|
if (!diff) {
|
|
171
|
-
|
|
259
|
+
if (reviewTarget === "Staged Changes") {
|
|
260
|
+
Logger.info(chalk.green("\nā
No staged changes to review. (Did you 'git add'?)"));
|
|
261
|
+
Logger.info(chalk.dim(" Tip: Use '--last' to review the previous commit."));
|
|
262
|
+
} else {
|
|
263
|
+
Logger.info(chalk.green(`\nā
No changes found in ${reviewTarget}.`));
|
|
264
|
+
}
|
|
172
265
|
return;
|
|
173
266
|
}
|
|
174
267
|
|
|
268
|
+
Logger.info(chalk.blue(`\nš Reviewing: ${reviewTarget}`));
|
|
269
|
+
|
|
175
270
|
// 2. Load the Brain
|
|
176
271
|
if (!fs.existsSync(STORAGE_DIR)) {
|
|
177
272
|
Logger.error(chalk.red("ā Local Brain not found. Run 'pnpm run index:init' first."));
|