jstar-reviewer 2.0.4 → 2.1.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/README.md +7 -4
- package/bin/jstar.js +28 -15
- package/dist/scripts/config.js +70 -2
- package/dist/scripts/indexer.js +6 -9
- package/dist/scripts/reviewer.js +10 -1
- package/package.json +8 -9
- package/scripts/config.ts +42 -2
- package/scripts/indexer.ts +9 -11
- package/scripts/reviewer.ts +12 -1
- package/setup.js +1 -1
package/README.md
CHANGED
|
@@ -37,10 +37,13 @@ curl -fsSL https://raw.githubusercontent.com/JStaRFilms/jstar-code-review/v2.0.0
|
|
|
37
37
|
|
|
38
38
|
### After Install:
|
|
39
39
|
|
|
40
|
-
1.
|
|
41
|
-
2.
|
|
42
|
-
3. Run `jstar init` to build the brain
|
|
43
|
-
4.
|
|
40
|
+
1. **Check Config**: The tool now **auto-creates** `.env.example` and `.jstar/` when you run it.
|
|
41
|
+
2. **Add Keys**: Copy `.env.example` → `.env.local` and add your `GOOGLE_API_KEY` and `GROQ_API_KEY`.
|
|
42
|
+
3. **Index**: Run `jstar init` (or `pnpm run index:init`) to build the brain.
|
|
43
|
+
4. **Review**: Stage changes (`git add`) and run `jstar review` (or `pnpm run review`).
|
|
44
|
+
|
|
45
|
+
For a detailed walkthrough, see **[ONBOARDING.md](./ONBOARDING.md)**.
|
|
46
|
+
|
|
44
47
|
|
|
45
48
|
---
|
|
46
49
|
|
package/bin/jstar.js
CHANGED
|
@@ -134,35 +134,48 @@ function runScript(scriptName) {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
const REQUIRED_ENV_VARS = {
|
|
138
|
+
'GOOGLE_API_KEY': '# Required: Google API key for Gemini embeddings\nGOOGLE_API_KEY=your_google_api_key_here',
|
|
139
|
+
'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
|
|
140
|
+
'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
|
|
141
|
+
};
|
|
142
|
+
|
|
137
143
|
function createSetupFiles() {
|
|
138
144
|
const cwd = process.cwd();
|
|
139
145
|
|
|
140
|
-
// Create .jstar directory
|
|
146
|
+
// 1. Create .jstar directory
|
|
141
147
|
const jstarDir = path.join(cwd, '.jstar');
|
|
142
148
|
if (!fs.existsSync(jstarDir)) {
|
|
143
149
|
fs.mkdirSync(jstarDir, { recursive: true });
|
|
144
150
|
log(`${COLORS.green}✓${COLORS.reset} Created .jstar/`);
|
|
145
151
|
}
|
|
146
152
|
|
|
147
|
-
// Create .env.example
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
GOOGLE_API_KEY=your_google_api_key_here
|
|
153
|
+
// 2. Create/Update .env.example
|
|
154
|
+
const envExamplePath = path.join(cwd, '.env.example');
|
|
155
|
+
if (fs.existsSync(envExamplePath)) {
|
|
156
|
+
let content = fs.readFileSync(envExamplePath, 'utf-8');
|
|
157
|
+
let addedKeys = [];
|
|
153
158
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
for (const [key, template] of Object.entries(REQUIRED_ENV_VARS)) {
|
|
160
|
+
if (!content.includes(key)) {
|
|
161
|
+
content += '\n' + template + '\n';
|
|
162
|
+
addedKeys.push(key);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
157
165
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
if (addedKeys.length > 0) {
|
|
167
|
+
fs.writeFileSync(envExamplePath, content);
|
|
168
|
+
log(`${COLORS.green}✓${COLORS.reset} Updated .env.example with missing keys: ${addedKeys.join(', ')}`);
|
|
169
|
+
} else {
|
|
170
|
+
log(`${COLORS.dim} .env.example already exists and is up to date${COLORS.reset}`);
|
|
171
|
+
}
|
|
162
172
|
} else {
|
|
163
|
-
|
|
173
|
+
const initialEnv = "# J-Star Code Reviewer\n" + Object.values(REQUIRED_ENV_VARS).join("\n") + "\n";
|
|
174
|
+
fs.writeFileSync(envExamplePath, initialEnv);
|
|
175
|
+
log(`${COLORS.green}✓${COLORS.reset} Created .env.example`);
|
|
164
176
|
}
|
|
165
177
|
|
|
178
|
+
|
|
166
179
|
// Update .gitignore
|
|
167
180
|
const gitignorePath = path.join(cwd, '.gitignore');
|
|
168
181
|
const gitignoreAdditions = `
|
package/dist/scripts/config.js
CHANGED
|
@@ -1,17 +1,85 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.Config = void 0;
|
|
7
40
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
// --- Auto-Setup Logic ---
|
|
44
|
+
const REQUIRED_ENV_VARS = {
|
|
45
|
+
'GOOGLE_API_KEY': '# Required: Google API key for Gemini embeddings\nGOOGLE_API_KEY=your_google_api_key_here',
|
|
46
|
+
'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
|
|
47
|
+
'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
|
|
48
|
+
};
|
|
49
|
+
function ensureSetup() {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const jstarDir = path.join(cwd, ".jstar");
|
|
52
|
+
const envExamplePath = path.join(cwd, ".env.example");
|
|
53
|
+
// 1. Ensure .jstar exists
|
|
54
|
+
if (!fs.existsSync(jstarDir)) {
|
|
55
|
+
fs.mkdirSync(jstarDir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
// 2. Ensure .env.example is up to date
|
|
58
|
+
if (fs.existsSync(envExamplePath)) {
|
|
59
|
+
let content = fs.readFileSync(envExamplePath, 'utf-8');
|
|
60
|
+
let missing = false;
|
|
61
|
+
for (const [key, template] of Object.entries(REQUIRED_ENV_VARS)) {
|
|
62
|
+
if (!content.includes(key)) {
|
|
63
|
+
content += `\n${template}\n`;
|
|
64
|
+
missing = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (missing) {
|
|
68
|
+
fs.writeFileSync(envExamplePath, content);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const initialEnv = "# J-Star Code Reviewer\n" + Object.values(REQUIRED_ENV_VARS).join("\n") + "\n";
|
|
73
|
+
fs.writeFileSync(envExamplePath, initialEnv);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Run setup check
|
|
77
|
+
ensureSetup();
|
|
8
78
|
// Load .env.local first, then .env
|
|
9
79
|
dotenv_1.default.config({ path: ".env.local" });
|
|
10
80
|
dotenv_1.default.config();
|
|
11
81
|
/**
|
|
12
82
|
* Default fallback values.
|
|
13
|
-
* These are intentional fallbacks when environment variables are not configured.
|
|
14
|
-
* Override via REVIEW_MODEL_NAME env var for production use.
|
|
15
83
|
*/
|
|
16
84
|
const DEFAULT_MODEL = "moonshotai/kimi-k2-instruct-0905";
|
|
17
85
|
exports.Config = {
|
package/dist/scripts/indexer.js
CHANGED
|
@@ -42,19 +42,16 @@ const mock_llm_1 = require("./mock-llm");
|
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const fs = __importStar(require("fs"));
|
|
44
44
|
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
-
const dotenv_1 = __importDefault(require("dotenv"));
|
|
46
|
-
// Load .env.local first, then .env
|
|
47
|
-
dotenv_1.default.config({ path: ".env.local" });
|
|
48
|
-
dotenv_1.default.config();
|
|
49
45
|
// Configuration
|
|
50
46
|
const STORAGE_DIR = path.join(process.cwd(), ".jstar", "storage");
|
|
51
47
|
const SOURCE_DIR = path.join(process.cwd(), "scripts"); // Changed from src/ to scripts/
|
|
52
|
-
// Ensure OpenAI Key exists (LlamaIndex default) or fallback if we configured something else
|
|
53
|
-
// (We are using local now, so this check is less critical, but good to have if we revert)
|
|
54
|
-
// if (!process.env.OPENAI_API_KEY) {
|
|
55
|
-
// console.warn(chalk.yellow("⚠️ OPENAI_API_KEY not found. Embeddings may fail unless you have configured a local model."));
|
|
56
|
-
// }
|
|
57
48
|
async function main() {
|
|
49
|
+
// 0. Environment Validation
|
|
50
|
+
if (!process.env.GOOGLE_API_KEY) {
|
|
51
|
+
console.error(chalk_1.default.red("❌ Missing GOOGLE_API_KEY!"));
|
|
52
|
+
console.log(chalk_1.default.yellow("\nPlease ensure you have a .env.local file. Check .env.example for a template.\n"));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
58
55
|
const args = process.argv.slice(2);
|
|
59
56
|
const isWatch = args.includes("--watch");
|
|
60
57
|
console.log(chalk_1.default.blue("🧠 J-Star Indexer: Scanning codebase..."));
|
package/dist/scripts/reviewer.js
CHANGED
|
@@ -125,7 +125,16 @@ function parseReviewResponse(text) {
|
|
|
125
125
|
// --- Main ---
|
|
126
126
|
async function main() {
|
|
127
127
|
console.log(chalk_1.default.blue("🕵️ J-Star Reviewer: Analyzing your changes...\n"));
|
|
128
|
-
// 0.
|
|
128
|
+
// 0. Environment Validation
|
|
129
|
+
if (!process.env.GOOGLE_API_KEY || !process.env.GROQ_API_KEY) {
|
|
130
|
+
console.error(chalk_1.default.red("❌ Missing API Keys!"));
|
|
131
|
+
console.log(chalk_1.default.yellow("\nPlease ensure you have a .env.local file with:"));
|
|
132
|
+
console.log(chalk_1.default.white("- GOOGLE_API_KEY"));
|
|
133
|
+
console.log(chalk_1.default.white("- GROQ_API_KEY"));
|
|
134
|
+
console.log(chalk_1.default.white("\nCheck .env.example for a template.\n"));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// 1. Detective
|
|
129
138
|
console.log(chalk_1.default.blue("🔎 Running Detective Engine..."));
|
|
130
139
|
const detective = new detective_1.Detective(SOURCE_DIR);
|
|
131
140
|
await detective.scan();
|
package/package.json
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jstar-reviewer",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.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
|
-
"detect": "ts-node scripts/detective.ts",
|
|
14
|
-
"prepare": "husky install"
|
|
15
|
-
},
|
|
16
8
|
"keywords": [
|
|
17
9
|
"code-review",
|
|
18
10
|
"ai",
|
|
@@ -62,5 +54,12 @@
|
|
|
62
54
|
"type": "commonjs",
|
|
63
55
|
"bugs": {
|
|
64
56
|
"url": "https://github.com/JStaRFilms/jstar-code-review/issues"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"index:init": "ts-node scripts/indexer.ts --init",
|
|
61
|
+
"index:watch": "ts-node scripts/indexer.ts --watch",
|
|
62
|
+
"review": "ts-node scripts/reviewer.ts",
|
|
63
|
+
"detect": "ts-node scripts/detective.ts"
|
|
65
64
|
}
|
|
66
65
|
}
|
package/scripts/config.ts
CHANGED
|
@@ -1,14 +1,53 @@
|
|
|
1
1
|
import dotenv from "dotenv";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
2
4
|
import { Severity } from "./types";
|
|
3
5
|
|
|
6
|
+
// --- Auto-Setup Logic ---
|
|
7
|
+
const REQUIRED_ENV_VARS = {
|
|
8
|
+
'GOOGLE_API_KEY': '# Required: Google API key for Gemini embeddings\nGOOGLE_API_KEY=your_google_api_key_here',
|
|
9
|
+
'GROQ_API_KEY': '# Required: Groq API key for LLM reviews\nGROQ_API_KEY=your_groq_api_key_here',
|
|
10
|
+
'REVIEW_MODEL_NAME': '# Optional: Override the default model\n# REVIEW_MODEL_NAME=moonshotai/kimi-k2-instruct-0905'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function ensureSetup() {
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const jstarDir = path.join(cwd, ".jstar");
|
|
16
|
+
const envExamplePath = path.join(cwd, ".env.example");
|
|
17
|
+
|
|
18
|
+
// 1. Ensure .jstar exists
|
|
19
|
+
if (!fs.existsSync(jstarDir)) {
|
|
20
|
+
fs.mkdirSync(jstarDir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 2. Ensure .env.example is up to date
|
|
24
|
+
if (fs.existsSync(envExamplePath)) {
|
|
25
|
+
let content = fs.readFileSync(envExamplePath, 'utf-8');
|
|
26
|
+
let missing = false;
|
|
27
|
+
for (const [key, template] of Object.entries(REQUIRED_ENV_VARS)) {
|
|
28
|
+
if (!content.includes(key)) {
|
|
29
|
+
content += `\n${template}\n`;
|
|
30
|
+
missing = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (missing) {
|
|
34
|
+
fs.writeFileSync(envExamplePath, content);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
const initialEnv = "# J-Star Code Reviewer\n" + Object.values(REQUIRED_ENV_VARS).join("\n") + "\n";
|
|
38
|
+
fs.writeFileSync(envExamplePath, initialEnv);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Run setup check
|
|
43
|
+
ensureSetup();
|
|
44
|
+
|
|
4
45
|
// Load .env.local first, then .env
|
|
5
46
|
dotenv.config({ path: ".env.local" });
|
|
6
47
|
dotenv.config();
|
|
7
48
|
|
|
8
49
|
/**
|
|
9
50
|
* Default fallback values.
|
|
10
|
-
* These are intentional fallbacks when environment variables are not configured.
|
|
11
|
-
* Override via REVIEW_MODEL_NAME env var for production use.
|
|
12
51
|
*/
|
|
13
52
|
const DEFAULT_MODEL = "moonshotai/kimi-k2-instruct-0905";
|
|
14
53
|
|
|
@@ -19,3 +58,4 @@ export const Config = {
|
|
|
19
58
|
MEDIUM: 5
|
|
20
59
|
}
|
|
21
60
|
};
|
|
61
|
+
|
package/scripts/indexer.ts
CHANGED
|
@@ -9,28 +9,26 @@ import { MockLLM } from "./mock-llm";
|
|
|
9
9
|
import * as path from "path";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import chalk from "chalk";
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
// Load .env.local first, then .env
|
|
15
|
-
dotenv.config({ path: ".env.local" });
|
|
16
|
-
dotenv.config();
|
|
12
|
+
import { Config } from "./config";
|
|
17
13
|
|
|
18
14
|
// Configuration
|
|
19
15
|
const STORAGE_DIR = path.join(process.cwd(), ".jstar", "storage");
|
|
20
16
|
const SOURCE_DIR = path.join(process.cwd(), "scripts"); // Changed from src/ to scripts/
|
|
21
17
|
|
|
22
|
-
// Ensure OpenAI Key exists (LlamaIndex default) or fallback if we configured something else
|
|
23
|
-
// (We are using local now, so this check is less critical, but good to have if we revert)
|
|
24
|
-
// if (!process.env.OPENAI_API_KEY) {
|
|
25
|
-
// console.warn(chalk.yellow("⚠️ OPENAI_API_KEY not found. Embeddings may fail unless you have configured a local model."));
|
|
26
|
-
// }
|
|
27
|
-
|
|
28
18
|
async function main() {
|
|
19
|
+
// 0. Environment Validation
|
|
20
|
+
if (!process.env.GOOGLE_API_KEY) {
|
|
21
|
+
console.error(chalk.red("❌ Missing GOOGLE_API_KEY!"));
|
|
22
|
+
console.log(chalk.yellow("\nPlease ensure you have a .env.local file. Check .env.example for a template.\n"));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
29
26
|
const args = process.argv.slice(2);
|
|
30
27
|
const isWatch = args.includes("--watch");
|
|
31
28
|
|
|
32
29
|
console.log(chalk.blue("🧠 J-Star Indexer: Scanning codebase..."));
|
|
33
30
|
|
|
31
|
+
|
|
34
32
|
// 1. Load documents (Your Code)
|
|
35
33
|
if (!fs.existsSync(SOURCE_DIR)) {
|
|
36
34
|
console.error(chalk.red(`❌ Source directory not found: ${SOURCE_DIR}`));
|
package/scripts/reviewer.ts
CHANGED
|
@@ -109,8 +109,19 @@ function parseReviewResponse(text: string): LLMReviewResponse {
|
|
|
109
109
|
async function main() {
|
|
110
110
|
console.log(chalk.blue("🕵️ J-Star Reviewer: Analyzing your changes...\n"));
|
|
111
111
|
|
|
112
|
-
// 0.
|
|
112
|
+
// 0. Environment Validation
|
|
113
|
+
if (!process.env.GOOGLE_API_KEY || !process.env.GROQ_API_KEY) {
|
|
114
|
+
console.error(chalk.red("❌ Missing API Keys!"));
|
|
115
|
+
console.log(chalk.yellow("\nPlease ensure you have a .env.local file with:"));
|
|
116
|
+
console.log(chalk.white("- GOOGLE_API_KEY"));
|
|
117
|
+
console.log(chalk.white("- GROQ_API_KEY"));
|
|
118
|
+
console.log(chalk.white("\nCheck .env.example for a template.\n"));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 1. Detective
|
|
113
123
|
console.log(chalk.blue("🔎 Running Detective Engine..."));
|
|
124
|
+
|
|
114
125
|
const detective = new Detective(SOURCE_DIR);
|
|
115
126
|
await detective.scan();
|
|
116
127
|
detective.report();
|
package/setup.js
CHANGED
|
@@ -115,7 +115,7 @@ async function main() {
|
|
|
115
115
|
|
|
116
116
|
// HARDCODED: Tagged release URL - NOT configurable for security
|
|
117
117
|
// To update, modify this constant and publish a new version of setup.js
|
|
118
|
-
const BASE_URL = 'https://raw.githubusercontent.com/JStaRFilms/jstar-code-review/v2.
|
|
118
|
+
const BASE_URL = 'https://raw.githubusercontent.com/JStaRFilms/jstar-code-review/v2.1.0';
|
|
119
119
|
|
|
120
120
|
// Validate URL matches our exact expected pattern (defense in depth)
|
|
121
121
|
function isValidUrl(url) {
|