nayan-ai 1.0.0-beta.1 → 1.0.0-beta.3
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 +5 -1
- package/dist/claude.js +14 -4
- package/dist/claude.js.map +1 -1
- package/dist/cli.js +17 -0
- package/dist/cli.js.map +1 -1
- package/dist/prompt.js +11 -9
- package/dist/prompt.js.map +1 -1
- package/package.json +5 -1
- package/.github/workflows/publish.yml +0 -26
- package/src/analyzer.ts +0 -77
- package/src/claude.ts +0 -147
- package/src/cli.ts +0 -172
- package/src/codex.ts +0 -158
- package/src/github.ts +0 -108
- package/src/index.ts +0 -6
- package/src/logs.ts +0 -253
- package/src/prompt.ts +0 -75
- package/src/repo.ts +0 -81
- package/src/types.ts +0 -51
- package/tsconfig.json +0 -19
package/README.md
CHANGED
|
@@ -21,10 +21,14 @@ A CLI tool that uses [Codex CLI](https://github.com/openai/codex) to review GitH
|
|
|
21
21
|
### Prerequisites
|
|
22
22
|
|
|
23
23
|
1. **Node.js 18+** - Required runtime
|
|
24
|
-
2. **Codex CLI** - Login to Codex CLI first:
|
|
24
|
+
2. **Codex CLI** (default) - Login to Codex CLI first:
|
|
25
25
|
```bash
|
|
26
26
|
npx @openai/codex login
|
|
27
27
|
```
|
|
28
|
+
3. **Claude Code CLI** (optional) - If using `--llm claude`:
|
|
29
|
+
```bash
|
|
30
|
+
claude login
|
|
31
|
+
```
|
|
28
32
|
|
|
29
33
|
### Install nayan-ai
|
|
30
34
|
|
package/dist/claude.js
CHANGED
|
@@ -68,6 +68,7 @@ async function runClaudeExec(repoPath, baseBranch, options) {
|
|
|
68
68
|
}
|
|
69
69
|
function parseClaudeResponse(response) {
|
|
70
70
|
// Claude with --output-format json outputs a JSON object with result field
|
|
71
|
+
let parseError = null;
|
|
71
72
|
try {
|
|
72
73
|
const parsed = JSON.parse(response);
|
|
73
74
|
// Claude JSON output has a 'result' field with the text response
|
|
@@ -90,8 +91,8 @@ function parseClaudeResponse(response) {
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
catch {
|
|
94
|
-
|
|
94
|
+
catch (err) {
|
|
95
|
+
parseError = err;
|
|
95
96
|
}
|
|
96
97
|
// Fallback: try to find raw JSON in the response
|
|
97
98
|
const jsonMatch = response.match(/\{\s*"issues"\s*:\s*\[[\s\S]*?\]\s*\}/);
|
|
@@ -109,10 +110,19 @@ function parseClaudeResponse(response) {
|
|
|
109
110
|
suggestion: item.suggestion,
|
|
110
111
|
}));
|
|
111
112
|
}
|
|
112
|
-
catch {
|
|
113
|
-
|
|
113
|
+
catch (err) {
|
|
114
|
+
parseError = err;
|
|
114
115
|
}
|
|
115
116
|
}
|
|
117
|
+
// If we couldn't parse any issues and there was an error, log it
|
|
118
|
+
if (parseError) {
|
|
119
|
+
console.warn(chalk.yellow(`\n⚠ Warning: Failed to parse Claude response: ${parseError.message}`));
|
|
120
|
+
console.warn(chalk.gray(` Response preview: ${response.slice(0, 200)}...`));
|
|
121
|
+
}
|
|
122
|
+
else if (response.trim() && !response.includes('"issues"')) {
|
|
123
|
+
console.warn(chalk.yellow(`\n⚠ Warning: Claude response does not contain expected issues format`));
|
|
124
|
+
console.warn(chalk.gray(` Response preview: ${response.slice(0, 200)}...`));
|
|
125
|
+
}
|
|
116
126
|
return [];
|
|
117
127
|
}
|
|
118
128
|
//# sourceMappingURL=claude.js.map
|
package/dist/claude.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -8,8 +8,10 @@ import { analyzeWithCodex } from './codex.js';
|
|
|
8
8
|
import { analyzeWithClaude } from './claude.js';
|
|
9
9
|
import { cloneRepo } from './repo.js';
|
|
10
10
|
import { createRequire } from 'module';
|
|
11
|
+
import { execSync } from 'child_process';
|
|
11
12
|
const require = createRequire(import.meta.url);
|
|
12
13
|
const { version } = require('../package.json');
|
|
14
|
+
const VALID_LLM_PROVIDERS = ['codex', 'claude'];
|
|
13
15
|
program
|
|
14
16
|
.name('nayan-ai')
|
|
15
17
|
.description('AI-powered PR code reviewer using Codex CLI')
|
|
@@ -23,8 +25,23 @@ program
|
|
|
23
25
|
.option('--format <format>', 'Output format: text, json', 'text')
|
|
24
26
|
.action(run);
|
|
25
27
|
program.parse();
|
|
28
|
+
function checkLLMAvailability(provider) {
|
|
29
|
+
if (provider === 'codex') {
|
|
30
|
+
execSync('npx @openai/codex --version', { stdio: 'ignore' });
|
|
31
|
+
}
|
|
32
|
+
else if (provider === 'claude') {
|
|
33
|
+
execSync('claude --version', { stdio: 'ignore' });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
26
36
|
async function run(prUrl, options) {
|
|
27
37
|
try {
|
|
38
|
+
// Validate --llm option
|
|
39
|
+
if (!VALID_LLM_PROVIDERS.includes(options.llm)) {
|
|
40
|
+
console.error(chalk.red(`Error: Invalid LLM provider '${options.llm}'. Valid options: ${VALID_LLM_PROVIDERS.join(', ')}`));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
// Check if the selected LLM CLI is available
|
|
44
|
+
checkLLMAvailability(options.llm);
|
|
28
45
|
const prInfo = parsePRReference(prUrl);
|
|
29
46
|
const githubUrl = prInfo.githubUrl;
|
|
30
47
|
console.log(chalk.bold.blue('\n🤖 Nayan AI - PR Reviewer'));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAqB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/prompt.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
export function getReviewPrompt(baseBranch) {
|
|
2
|
-
return `You are an expert code reviewer. Perform a comprehensive review of ALL code changes in this PR.
|
|
2
|
+
return `You are an expert code reviewer. Perform a DEEP, comprehensive review of ALL code changes in this PR.
|
|
3
3
|
|
|
4
|
-
STEP 1: Run "git diff
|
|
4
|
+
STEP 1: Run "git diff ${baseBranch}...HEAD" to identify all changed files.
|
|
5
5
|
|
|
6
|
-
STEP 2:
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
6
|
+
STEP 2: For EACH changed file (skip lock files like yarn.lock, package-lock.json, bun.lock):
|
|
7
|
+
- Read the FULL file to understand the complete context
|
|
8
|
+
- Understand how the changes interact with existing code
|
|
9
|
+
- Check imports, exports, and dependencies affected by the change
|
|
10
|
+
- Analyze the entire function/class that contains the change
|
|
11
|
+
- Look for issues that may not be visible in the diff alone
|
|
10
12
|
|
|
11
|
-
STEP 3:
|
|
13
|
+
STEP 3: Perform DEEP analysis - check each change for these categories:
|
|
12
14
|
|
|
13
15
|
**BUGS & LOGIC ERRORS:**
|
|
14
16
|
- Off-by-one errors in loops/arrays
|
|
@@ -70,7 +72,7 @@ STEP 4: Output ALL issues as JSON (be thorough - report every issue you find):
|
|
|
70
72
|
- **warning**: Potential problems that may cause issues in edge cases or under certain conditions. Examples: missing error handling, possible memory leaks, missing null checks for optional values, performance issues.
|
|
71
73
|
- **info**: Code quality improvements, best practices, style suggestions. Examples: dead code, code duplication, missing tests, readability improvements.
|
|
72
74
|
|
|
73
|
-
CRITICAL: Review EVERY changed file
|
|
74
|
-
If truly no issues after
|
|
75
|
+
CRITICAL: Review EVERY changed file thoroughly. Read the FULL file for each change to understand complete context. Do not skip any file. Be thorough - quality over speed.
|
|
76
|
+
If truly no issues after deep analysis, return {"issues":[]}`;
|
|
75
77
|
}
|
|
76
78
|
//# sourceMappingURL=prompt.js.map
|
package/dist/prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,OAAO;;
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,OAAO;;wBAEe,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6DAwE2B,CAAC;AAC9D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nayan-ai",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"description": "AI-powered PR code reviewer CLI using Codex CLI agent",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|
|
38
38
|
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
39
43
|
"dependencies": {
|
|
40
44
|
"chalk": "^5.6.2",
|
|
41
45
|
"commander": "^14.0.2",
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
name: Publish nayan-ai package to npm
|
|
2
|
-
on: [workflow_dispatch]
|
|
3
|
-
|
|
4
|
-
jobs:
|
|
5
|
-
publish:
|
|
6
|
-
runs-on: ubuntu-latest
|
|
7
|
-
steps:
|
|
8
|
-
- uses: actions/checkout@v4
|
|
9
|
-
|
|
10
|
-
- name: Set up Node.js
|
|
11
|
-
uses: actions/setup-node@v4
|
|
12
|
-
with:
|
|
13
|
-
node-version: 20
|
|
14
|
-
registry-url: 'https://registry.npmjs.org/'
|
|
15
|
-
always-auth: true
|
|
16
|
-
|
|
17
|
-
- name: Install dependencies
|
|
18
|
-
run: npm install
|
|
19
|
-
|
|
20
|
-
- name: Build
|
|
21
|
-
run: npm run build
|
|
22
|
-
|
|
23
|
-
- name: Publish to npm
|
|
24
|
-
run: npm publish --access public
|
|
25
|
-
env:
|
|
26
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH }}
|
package/src/analyzer.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { CodeIssue, ReviewComment } from './types.js';
|
|
2
|
-
|
|
3
|
-
export function issuesToReviewComments(issues: CodeIssue[]): ReviewComment[] {
|
|
4
|
-
return issues.map((issue) => {
|
|
5
|
-
const severityIcon = issue.severity === 'error' ? '🔴' : issue.severity === 'warning' ? '🟡' : '🔵';
|
|
6
|
-
const categoryIcon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
7
|
-
|
|
8
|
-
let body = `${severityIcon} **${categoryIcon} ${capitalize(issue.category)}**\n\n${issue.message}`;
|
|
9
|
-
if (issue.suggestion) {
|
|
10
|
-
body += `\n\n💡 **Suggestion:** ${issue.suggestion}`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
path: issue.filename,
|
|
15
|
-
line: issue.line,
|
|
16
|
-
side: 'RIGHT' as const,
|
|
17
|
-
body,
|
|
18
|
-
};
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function generateSummary(issues: CodeIssue[]): string {
|
|
23
|
-
if (issues.length === 0) {
|
|
24
|
-
return '## ✅ AI Code Review Complete\n\nNo issues found. The code looks good!';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const bySeverity = {
|
|
28
|
-
error: issues.filter((i) => i.severity === 'error'),
|
|
29
|
-
warning: issues.filter((i) => i.severity === 'warning'),
|
|
30
|
-
info: issues.filter((i) => i.severity === 'info'),
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
let summary = `## 🤖 AI Code Review Complete\n\nFound **${issues.length}** issue(s) in this PR.\n\n`;
|
|
34
|
-
|
|
35
|
-
// Group issues by severity and list them
|
|
36
|
-
if (bySeverity.error.length > 0) {
|
|
37
|
-
summary += `### 🔴 Errors (${bySeverity.error.length})\n\n`;
|
|
38
|
-
bySeverity.error.forEach((issue) => {
|
|
39
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
40
|
-
summary += `- ${icon} **\`${issue.filename}:${issue.line}\`**\n ${issue.message}`;
|
|
41
|
-
if (issue.suggestion) {
|
|
42
|
-
summary += `\n 💡 *${issue.suggestion}*`;
|
|
43
|
-
}
|
|
44
|
-
summary += '\n\n';
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (bySeverity.warning.length > 0) {
|
|
49
|
-
summary += `### 🟡 Warnings (${bySeverity.warning.length})\n\n`;
|
|
50
|
-
bySeverity.warning.forEach((issue) => {
|
|
51
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
52
|
-
summary += `- ${icon} **\`${issue.filename}:${issue.line}\`**\n ${issue.message}`;
|
|
53
|
-
if (issue.suggestion) {
|
|
54
|
-
summary += `\n 💡 *${issue.suggestion}*`;
|
|
55
|
-
}
|
|
56
|
-
summary += '\n\n';
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (bySeverity.info.length > 0) {
|
|
61
|
-
summary += `### 🔵 Info (${bySeverity.info.length})\n\n`;
|
|
62
|
-
bySeverity.info.forEach((issue) => {
|
|
63
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
64
|
-
summary += `- ${icon} **\`${issue.filename}:${issue.line}\`**\n ${issue.message}`;
|
|
65
|
-
if (issue.suggestion) {
|
|
66
|
-
summary += `\n 💡 *${issue.suggestion}*`;
|
|
67
|
-
}
|
|
68
|
-
summary += '\n\n';
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return summary.trim();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function capitalize(str: string): string {
|
|
76
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
77
|
-
}
|
package/src/claude.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import type { CodeIssue } from './types.js';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { getReviewPrompt } from './prompt.js';
|
|
5
|
-
|
|
6
|
-
export interface ClaudeOptions {
|
|
7
|
-
verbose?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export async function analyzeWithClaude(
|
|
11
|
-
repoPath: string,
|
|
12
|
-
baseBranch: string = 'origin/main',
|
|
13
|
-
options: ClaudeOptions
|
|
14
|
-
): Promise<CodeIssue[]> {
|
|
15
|
-
const response = await runClaudeExec(repoPath, baseBranch, options);
|
|
16
|
-
return parseClaudeResponse(response);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function runClaudeExec(
|
|
20
|
-
repoPath: string,
|
|
21
|
-
baseBranch: string,
|
|
22
|
-
options: ClaudeOptions
|
|
23
|
-
): Promise<string> {
|
|
24
|
-
const prompt = getReviewPrompt(baseBranch);
|
|
25
|
-
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
// Use claude with -p for print mode and --output-format json
|
|
28
|
-
const args = [
|
|
29
|
-
'-p',
|
|
30
|
-
'--output-format', 'json',
|
|
31
|
-
'--dangerously-skip-permissions',
|
|
32
|
-
prompt
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
if (options.verbose) {
|
|
36
|
-
console.log(`\n[Claude] Running: claude ${args.slice(0, 3).join(' ')} "<prompt>"`);
|
|
37
|
-
console.log(`[Claude] Working directory: ${repoPath}`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const startTime = Date.now();
|
|
41
|
-
|
|
42
|
-
const child = spawn('claude', args, {
|
|
43
|
-
cwd: repoPath,
|
|
44
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
let stdout = '';
|
|
48
|
-
let stderr = '';
|
|
49
|
-
|
|
50
|
-
child.stdout.on('data', (data) => {
|
|
51
|
-
const chunk = data.toString();
|
|
52
|
-
stdout += chunk;
|
|
53
|
-
|
|
54
|
-
if (options.verbose) {
|
|
55
|
-
process.stdout.write(chunk);
|
|
56
|
-
} else {
|
|
57
|
-
// Show progress dots
|
|
58
|
-
process.stdout.write(chalk.gray('.'));
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
child.stderr.on('data', (data) => {
|
|
63
|
-
const chunk = data.toString();
|
|
64
|
-
stderr += chunk;
|
|
65
|
-
if (options.verbose) {
|
|
66
|
-
process.stderr.write(chunk);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
child.on('close', (code) => {
|
|
71
|
-
const elapsed = Date.now() - startTime;
|
|
72
|
-
|
|
73
|
-
if (!options.verbose) {
|
|
74
|
-
console.log(); // New line after progress dots
|
|
75
|
-
}
|
|
76
|
-
console.log(`\n[Claude] Completed in ${(elapsed / 1000).toFixed(1)}s`);
|
|
77
|
-
|
|
78
|
-
if (code !== 0) {
|
|
79
|
-
const errorMsg = stderr || stdout || 'Unknown error';
|
|
80
|
-
reject(new Error(`Claude review failed (exit ${code}): ${errorMsg.slice(0, 500)}`));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
resolve(stdout);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
child.on('error', (err) => {
|
|
88
|
-
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
89
|
-
reject(new Error('claude CLI not found. Install Claude Code CLI first: https://code.claude.com'));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
reject(err);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function parseClaudeResponse(response: string): CodeIssue[] {
|
|
98
|
-
// Claude with --output-format json outputs a JSON object with result field
|
|
99
|
-
try {
|
|
100
|
-
const parsed = JSON.parse(response);
|
|
101
|
-
|
|
102
|
-
// Claude JSON output has a 'result' field with the text response
|
|
103
|
-
const text = parsed.result || parsed.text || response;
|
|
104
|
-
|
|
105
|
-
// Try to extract JSON from the text
|
|
106
|
-
const jsonMatch = text.match(/\{\s*"issues"\s*:\s*\[[\s\S]*?\]\s*\}/);
|
|
107
|
-
if (jsonMatch) {
|
|
108
|
-
const issuesJson = JSON.parse(jsonMatch[0]);
|
|
109
|
-
if (issuesJson.issues && Array.isArray(issuesJson.issues)) {
|
|
110
|
-
return issuesJson.issues
|
|
111
|
-
.filter((item: any) => item.message)
|
|
112
|
-
.map((item: any) => ({
|
|
113
|
-
filename: item.filename || 'unknown',
|
|
114
|
-
line: item.line || 0,
|
|
115
|
-
category: item.category || 'functionality',
|
|
116
|
-
severity: item.severity || 'info',
|
|
117
|
-
message: item.message,
|
|
118
|
-
suggestion: item.suggestion,
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
// Not valid JSON wrapper, try direct extraction
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Fallback: try to find raw JSON in the response
|
|
127
|
-
const jsonMatch = response.match(/\{\s*"issues"\s*:\s*\[[\s\S]*?\]\s*\}/);
|
|
128
|
-
if (jsonMatch) {
|
|
129
|
-
try {
|
|
130
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
131
|
-
return (parsed.issues || [])
|
|
132
|
-
.filter((item: any) => item.message)
|
|
133
|
-
.map((item: any) => ({
|
|
134
|
-
filename: item.filename || 'unknown',
|
|
135
|
-
line: item.line || 0,
|
|
136
|
-
category: item.category || 'functionality',
|
|
137
|
-
severity: item.severity || 'info',
|
|
138
|
-
message: item.message,
|
|
139
|
-
suggestion: item.suggestion,
|
|
140
|
-
}));
|
|
141
|
-
} catch {
|
|
142
|
-
// ignore
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return [];
|
|
147
|
-
}
|
package/src/cli.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { program } from 'commander';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import ora from 'ora';
|
|
6
|
-
import { GitHubClient, parseFiles, parsePRReference } from './github.js';
|
|
7
|
-
import { issuesToReviewComments, generateSummary } from './analyzer.js';
|
|
8
|
-
import { analyzeWithCodex, type CodexOptions } from './codex.js';
|
|
9
|
-
import { analyzeWithClaude, type ClaudeOptions } from './claude.js';
|
|
10
|
-
import { cloneRepo } from './repo.js';
|
|
11
|
-
import { createRequire } from 'module';
|
|
12
|
-
import type { CLIOptions, CodeIssue } from './types.js';
|
|
13
|
-
|
|
14
|
-
const require = createRequire(import.meta.url);
|
|
15
|
-
const { version } = require('../package.json');
|
|
16
|
-
|
|
17
|
-
program
|
|
18
|
-
.name('nayan-ai')
|
|
19
|
-
.description('AI-powered PR code reviewer using Codex CLI')
|
|
20
|
-
.version(version)
|
|
21
|
-
.argument('<pr-url>', 'GitHub PR URL (e.g., https://github.com/owner/repo/pull/123)')
|
|
22
|
-
.requiredOption('-t, --token <token>', 'GitHub personal access token')
|
|
23
|
-
.option('-v, --verbose', 'Show real-time output from Codex CLI', false)
|
|
24
|
-
.option('-d, --dry', 'Only analyze, don\'t post comments', false)
|
|
25
|
-
.option('-i, --inline', 'Post inline comments instead of summary', false)
|
|
26
|
-
.option('-l, --llm <provider>', 'LLM provider: codex (default) or claude', 'codex')
|
|
27
|
-
.option('--format <format>', 'Output format: text, json', 'text')
|
|
28
|
-
.action(run);
|
|
29
|
-
|
|
30
|
-
program.parse();
|
|
31
|
-
|
|
32
|
-
async function run(prUrl: string, options: CLIOptions) {
|
|
33
|
-
try {
|
|
34
|
-
const prInfo = parsePRReference(prUrl);
|
|
35
|
-
const githubUrl = prInfo.githubUrl;
|
|
36
|
-
|
|
37
|
-
console.log(chalk.bold.blue('\n🤖 Nayan AI - PR Reviewer'));
|
|
38
|
-
console.log('━'.repeat(40));
|
|
39
|
-
console.log(` Repository: ${chalk.cyan(`${prInfo.owner}/${prInfo.repo}`)}`);
|
|
40
|
-
console.log(` PR Number: ${chalk.cyan(`#${prInfo.number}`)}`);
|
|
41
|
-
if (githubUrl) {
|
|
42
|
-
console.log(` GitHub: ${chalk.cyan(githubUrl)}`);
|
|
43
|
-
}
|
|
44
|
-
if (options.dry) {
|
|
45
|
-
console.log(` Mode: ${chalk.yellow('Dry Run (no comments will be posted)')}`);
|
|
46
|
-
}
|
|
47
|
-
console.log('━'.repeat(40) + '\n');
|
|
48
|
-
|
|
49
|
-
const github = new GitHubClient(options.token, githubUrl);
|
|
50
|
-
|
|
51
|
-
// Fetch PR details
|
|
52
|
-
let spinner = ora('Fetching PR details...').start();
|
|
53
|
-
const pr = await github.getPullRequest(prInfo);
|
|
54
|
-
spinner.succeed(`PR: ${pr.title}`);
|
|
55
|
-
|
|
56
|
-
// Fetch changed files
|
|
57
|
-
spinner = ora('Fetching changed files...').start();
|
|
58
|
-
const files = await github.getPullRequestFiles(prInfo);
|
|
59
|
-
const fileChanges = parseFiles(files);
|
|
60
|
-
spinner.succeed(`Found ${fileChanges.length} files with changes`);
|
|
61
|
-
|
|
62
|
-
// Clone and analyze with Codex CLI
|
|
63
|
-
spinner = ora('Cloning repository...').start();
|
|
64
|
-
const repo = await cloneRepo(prInfo, options.token, githubUrl);
|
|
65
|
-
|
|
66
|
-
let issues: CodeIssue[];
|
|
67
|
-
try {
|
|
68
|
-
spinner.succeed('Repository cloned');
|
|
69
|
-
|
|
70
|
-
const llmName = options.llm === 'claude' ? 'Claude Code' : 'Codex';
|
|
71
|
-
console.log(chalk.cyan(`Running code review with ${llmName} CLI...\n`));
|
|
72
|
-
|
|
73
|
-
if (options.llm === 'claude') {
|
|
74
|
-
const claudeOpts: ClaudeOptions = { verbose: options.verbose };
|
|
75
|
-
issues = await analyzeWithClaude(repo.path, 'origin/main', claudeOpts);
|
|
76
|
-
} else {
|
|
77
|
-
const codexOpts: CodexOptions = { verbose: options.verbose };
|
|
78
|
-
issues = await analyzeWithCodex(repo.path, 'origin/main', codexOpts);
|
|
79
|
-
}
|
|
80
|
-
console.log(chalk.green(`\n✔ Analysis complete: ${issues.length} issues found`));
|
|
81
|
-
} finally {
|
|
82
|
-
await repo.cleanup();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Display results
|
|
86
|
-
console.log(chalk.bold('\n📋 Review Summary'));
|
|
87
|
-
console.log('─'.repeat(41));
|
|
88
|
-
|
|
89
|
-
if (options.format === 'json') {
|
|
90
|
-
console.log(JSON.stringify(issues, null, 2));
|
|
91
|
-
} else {
|
|
92
|
-
printIssuesSummary(issues);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Post to GitHub
|
|
96
|
-
if (!options.dry) {
|
|
97
|
-
spinner = ora('Posting review to GitHub...').start();
|
|
98
|
-
|
|
99
|
-
if (options.inline) {
|
|
100
|
-
// Post inline comments on specific lines
|
|
101
|
-
const reviewComments = issuesToReviewComments(issues);
|
|
102
|
-
const summary = generateSummary(issues);
|
|
103
|
-
await github.postReview(prInfo, pr.head.sha, summary, reviewComments);
|
|
104
|
-
spinner.succeed('Inline review posted to GitHub');
|
|
105
|
-
} else {
|
|
106
|
-
// Post summary as a PR-level comment (default)
|
|
107
|
-
const summary = generateSummary(issues);
|
|
108
|
-
await github.postComment(prInfo, summary);
|
|
109
|
-
spinner.succeed('Review summary posted to GitHub');
|
|
110
|
-
}
|
|
111
|
-
} else {
|
|
112
|
-
console.log(chalk.yellow('\nDry run mode - no comments posted to GitHub'));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
console.log(chalk.green('\n✅ Review complete!\n'));
|
|
116
|
-
} catch (error) {
|
|
117
|
-
console.error(chalk.red('\nError:'), error instanceof Error ? error.message : error);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function printIssuesSummary(issues: CodeIssue[]) {
|
|
123
|
-
if (issues.length === 0) {
|
|
124
|
-
console.log(chalk.green(' No issues found! The code looks good.'));
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const bySeverity = {
|
|
129
|
-
error: issues.filter((i) => i.severity === 'error'),
|
|
130
|
-
warning: issues.filter((i) => i.severity === 'warning'),
|
|
131
|
-
info: issues.filter((i) => i.severity === 'info'),
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Print errors
|
|
135
|
-
if (bySeverity.error.length > 0) {
|
|
136
|
-
console.log(chalk.red.bold(`\n 🔴 Errors (${bySeverity.error.length}):`));
|
|
137
|
-
for (const issue of bySeverity.error) {
|
|
138
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
139
|
-
console.log(chalk.red(` ${icon} ${issue.filename}:${issue.line}`));
|
|
140
|
-
console.log(` ${issue.message}`);
|
|
141
|
-
if (issue.suggestion) {
|
|
142
|
-
console.log(chalk.dim(` 💡 ${issue.suggestion}`));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Print warnings
|
|
148
|
-
if (bySeverity.warning.length > 0) {
|
|
149
|
-
console.log(chalk.yellow.bold(`\n 🟡 Warnings (${bySeverity.warning.length}):`));
|
|
150
|
-
for (const issue of bySeverity.warning) {
|
|
151
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
152
|
-
console.log(chalk.yellow(` ${icon} ${issue.filename}:${issue.line}`));
|
|
153
|
-
console.log(` ${issue.message}`);
|
|
154
|
-
if (issue.suggestion) {
|
|
155
|
-
console.log(chalk.dim(` 💡 ${issue.suggestion}`));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Print info
|
|
161
|
-
if (bySeverity.info.length > 0) {
|
|
162
|
-
console.log(chalk.blue.bold(`\n 🔵 Info (${bySeverity.info.length}):`));
|
|
163
|
-
for (const issue of bySeverity.info) {
|
|
164
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
165
|
-
console.log(chalk.blue(` ${icon} ${issue.filename}:${issue.line}`));
|
|
166
|
-
console.log(` ${issue.message}`);
|
|
167
|
-
if (issue.suggestion) {
|
|
168
|
-
console.log(chalk.dim(` 💡 ${issue.suggestion}`));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|