Spaces:
Paused
Paused
| ; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.main = main; | |
| const options_1 = require("./options"); | |
| const prompts_1 = require("./prompts"); | |
| const bot_1 = require("./bot"); | |
| const local_context_1 = require("./local-context"); | |
| const console_reporter_1 = require("./console-reporter"); | |
| const child_process_1 = require("child_process"); | |
| const fs_1 = require("fs"); | |
| const HELP_TEXT = ` | |
| PRIX CLI - Local AI PR Reviewer | |
| Usage: | |
| prix-cli [options] | |
| Options: | |
| --staged Review staged files (git diff --cached) | |
| --diff <ref> Review files changed since given git ref | |
| --files <paths> Review specific files (comma-separated) | |
| --model <name> LLM model to use (default: llama-3.1-8b-instant) | |
| --min-confidence <n> Minimum confidence threshold (0-100) | |
| --min-severity <lvl> Minimum severity to report (critical|major|minor|info) | |
| --disable-review Skip code review, only generate summary | |
| --disable-notes Skip release notes generation | |
| --max-files <n> Maximum files to review (0 = unlimited) | |
| --path-filters <p> Path filters (comma-separated, e.g., "src/**,lib/**") | |
| --system-message <m> Additional system message | |
| --language <lang> Output language (default: en-US) | |
| --output <fmt> Output format: console (default) or json | |
| --help, -h Show this help message | |
| Examples: | |
| prix-cli --staged Review staged changes | |
| prix-cli --diff HEAD~1 Review changes since last commit | |
| prix-cli --files src/app.ts,lib/util.ts Review specific files | |
| prix-cli --min-severity major Only show major/critical issues | |
| Pre-commit Hook: | |
| Add to .git/hooks/pre-commit: | |
| npx prix-cli --staged --output console | |
| `; | |
| function parseArgs(argv) { | |
| const args = {}; | |
| for (let i = 2; i < argv.length; i++) { | |
| const arg = argv[i]; | |
| switch (arg) { | |
| case '--staged': | |
| args.staged = true; | |
| break; | |
| case '--diff': | |
| args.diff = argv[++i]; | |
| break; | |
| case '--files': | |
| args.files = argv[++i].split(','); | |
| break; | |
| case '--model': | |
| args.model = argv[++i]; | |
| break; | |
| case '--min-confidence': | |
| args.minConfidence = parseInt(argv[++i], 10); | |
| break; | |
| case '--min-severity': | |
| args.minSeverity = argv[++i]; | |
| break; | |
| case '--disable-review': | |
| args.disableReview = true; | |
| break; | |
| case '--disable-notes': | |
| args.disableReleaseNotes = true; | |
| break; | |
| case '--max-files': | |
| args.maxFiles = parseInt(argv[++i], 10); | |
| break; | |
| case '--path-filters': | |
| args.pathFilters = argv[++i].split(','); | |
| break; | |
| case '--system-message': | |
| args.systemMessage = argv[++i]; | |
| break; | |
| case '--language': | |
| args.language = argv[++i]; | |
| break; | |
| case '--output': | |
| args.output = argv[++i]; | |
| break; | |
| case '--help': | |
| case '-h': | |
| args.help = true; | |
| break; | |
| } | |
| } | |
| return args; | |
| } | |
| function getStagedFiles() { | |
| try { | |
| const output = (0, child_process_1.execSync)('git diff --cached --name-only', { | |
| encoding: 'utf8', | |
| cwd: process.cwd() | |
| }); | |
| return output.split('\n').filter(f => f.trim()); | |
| } | |
| catch (e) { | |
| console.error('Failed to get staged files:', e); | |
| return []; | |
| } | |
| } | |
| function getChangedFiles(sinceRef) { | |
| try { | |
| const output = (0, child_process_1.execSync)(`git diff --name-only ${sinceRef}`, { | |
| encoding: 'utf8', | |
| cwd: process.cwd() | |
| }); | |
| return output.split('\n').filter(f => f.trim()); | |
| } | |
| catch (e) { | |
| console.error(`Failed to get changed files since ${sinceRef}:`, e); | |
| return []; | |
| } | |
| } | |
| async function runLocalReview(args) { | |
| const info = console.log; | |
| const error = console.error; | |
| info('๐ PRIX CLI - Starting local code review...\n'); | |
| if (!process.env.GROQ_API_KEY && !process.env.AI_API_KEY) { | |
| error('โ Error: GROQ_API_KEY or AI_API_KEY environment variable is required'); | |
| return 1; | |
| } | |
| let filesToReview = []; | |
| if (args.staged) { | |
| filesToReview = getStagedFiles(); | |
| info(`๐ Reviewing ${filesToReview.length} staged files\n`); | |
| } | |
| else if (args.diff) { | |
| filesToReview = getChangedFiles(args.diff); | |
| info(`๐ Reviewing ${filesToReview.length} files changed since ${args.diff}\n`); | |
| } | |
| else if (args.files) { | |
| filesToReview = args.files.filter(f => (0, fs_1.existsSync)(f)); | |
| info(`๐ Reviewing ${filesToReview.length} specified files\n`); | |
| } | |
| else { | |
| error('โ Error: Must specify --staged, --diff <ref>, or --files <paths>'); | |
| return 1; | |
| } | |
| if (filesToReview.length === 0) { | |
| info('โ No files to review'); | |
| return 0; | |
| } | |
| const options = new options_1.Options(false, args.disableReview || false, args.disableReleaseNotes || false, args.maxFiles?.toString() || '0', false, false, args.pathFilters || null, args.systemMessage || '', args.model || 'llama-3.1-8b-instant', 'llama-3.3-70b-versatile', '0.0', '3', '120000', '6', '6', process.env.API_BASE_URL || 'https://api.groq.com/openai/v1', args.language || 'en-US', false, args.minSeverity || 'minor', args.minConfidence?.toString() || '0', 'false', 'true'); | |
| const prompts = new prompts_1.Prompts(); | |
| const localContext = new local_context_1.LocalContextEngine(filesToReview); | |
| const reporter = new console_reporter_1.LocalConsoleReporter(); | |
| info('๐ค Initializing AI models...'); | |
| let lightBot = null; | |
| let heavyBot = null; | |
| try { | |
| lightBot = new bot_1.Bot(options, new options_1.AIOptions(options.lightModel, options.lightTokenLimits, options.modelTemperature)); | |
| } | |
| catch (e) { | |
| error(`โ Failed to initialize light model: ${e}`); | |
| return 1; | |
| } | |
| try { | |
| heavyBot = new bot_1.Bot(options, new options_1.AIOptions(options.heavyModel, options.heavyTokenLimits, options.modelTemperature)); | |
| } | |
| catch (e) { | |
| error(`โ Failed to initialize heavy model: ${e}`); | |
| return 1; | |
| } | |
| info('โ AI models initialized\n'); | |
| try { | |
| await localContext.initialize(); | |
| const findings = await localContext.runReview(lightBot, heavyBot, options, prompts); | |
| reporter.printFindings(findings, { | |
| output: args.output || 'console', | |
| minSeverity: options.minimumSeverity, | |
| minConfidence: options.minConfidence | |
| }); | |
| const critical = findings.filter(f => f.severity === 'critical').length; | |
| const major = findings.filter(f => f.severity === 'major').length; | |
| info(`\n๐ Summary: ${critical} critical, ${major} major, ${findings.length} total findings`); | |
| if (critical > 0) { | |
| info('\nโ ๏ธ Critical issues found! Consider fixing before committing.'); | |
| return 1; | |
| } | |
| else if (major > 0) { | |
| info('\nโน๏ธ Major issues found. Review recommended before committing.'); | |
| return 0; | |
| } | |
| else { | |
| info('\nโ No significant issues found.'); | |
| return 0; | |
| } | |
| } | |
| catch (e) { | |
| error(`\nโ Review failed: ${e}`); | |
| return 1; | |
| } | |
| } | |
| async function main(argv) { | |
| const args = parseArgs(argv); | |
| if (args.help) { | |
| console.log(HELP_TEXT); | |
| return 0; | |
| } | |
| return runLocalReview(args); | |
| } | |
| if (require.main === module) { | |
| main(process.argv) | |
| .then(code => { | |
| process.exit(code); | |
| }) | |
| .catch(e => { | |
| console.error('Fatal error:', e); | |
| process.exit(1); | |
| }); | |
| } | |
| //# sourceMappingURL=cli.js.map |