nayan-ai 1.0.0-beta.3 → 1.0.0-beta.5
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 +101 -14
- package/dist/cli.js +21 -157
- package/dist/cli.js.map +1 -1
- package/dist/common/claude.d.ts +6 -0
- package/dist/common/claude.js +180 -0
- package/dist/common/claude.js.map +1 -0
- package/dist/common/codex.d.ts +6 -0
- package/dist/common/codex.js +169 -0
- package/dist/common/codex.js.map +1 -0
- package/dist/common/github.d.ts +22 -0
- package/dist/common/github.js +153 -0
- package/dist/common/github.js.map +1 -0
- package/dist/common/logs.d.ts +15 -0
- package/dist/common/logs.js +154 -0
- package/dist/common/logs.js.map +1 -0
- package/dist/{types.d.ts → common/types.d.ts} +36 -1
- package/dist/common/types.js.map +1 -0
- package/dist/common/utils.d.ts +3 -0
- package/dist/common/utils.js +11 -0
- package/dist/common/utils.js.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/{analyzer.d.ts → review/analyzer.d.ts} +1 -1
- package/dist/review/analyzer.js.map +1 -0
- package/dist/review/command.d.ts +2 -0
- package/dist/review/command.js +111 -0
- package/dist/review/command.js.map +1 -0
- package/dist/review/prompt.js.map +1 -0
- package/dist/scan/command.d.ts +2 -0
- package/dist/scan/command.js +700 -0
- package/dist/scan/command.js.map +1 -0
- package/dist/scan/fixer.d.ts +30 -0
- package/dist/scan/fixer.js +264 -0
- package/dist/scan/fixer.js.map +1 -0
- package/dist/scan/prompt.d.ts +4 -0
- package/dist/scan/prompt.js +175 -0
- package/dist/scan/prompt.js.map +1 -0
- package/package.json +2 -2
- package/dist/analyzer.js.map +0 -1
- package/dist/claude.d.ts +0 -5
- package/dist/claude.js +0 -128
- package/dist/claude.js.map +0 -1
- package/dist/codex.d.ts +0 -5
- package/dist/codex.js +0 -129
- package/dist/codex.js.map +0 -1
- package/dist/github.d.ts +0 -15
- package/dist/github.js +0 -88
- package/dist/github.js.map +0 -1
- package/dist/logs.d.ts +0 -34
- package/dist/logs.js +0 -219
- package/dist/logs.js.map +0 -1
- package/dist/prompt.js.map +0 -1
- package/dist/repo.d.ts +0 -8
- package/dist/repo.js +0 -61
- package/dist/repo.js.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{types.js → common/types.js} +0 -0
- /package/dist/{analyzer.js → review/analyzer.js} +0 -0
- /package/dist/{prompt.d.ts → review/prompt.d.ts} +0 -0
- /package/dist/{prompt.js → review/prompt.js} +0 -0
package/README.md
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
# Nayan AI 🤖
|
|
2
2
|
|
|
3
|
-
A CLI tool that uses [Codex
|
|
3
|
+
A CLI tool that uses [Codex](https://github.com/openai/codex) or [Claude Code](https://code.claude.com) to review GitHub Pull Requests and scan repositories for security vulnerabilities with AI-powered agentic analysis and auto-fix capabilities.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### PR Review
|
|
8
|
+
- **🤖 Agentic Review**: Uses Codex CLI or Claude Code CLI's intelligent coding agents for deep code analysis
|
|
8
9
|
- **🐛 Bug Detection**: Finds logic errors, null pointer issues, race conditions, and edge cases
|
|
9
10
|
- **🔐 Security Analysis**: Detects SQL injection, XSS, hardcoded secrets, and auth issues
|
|
10
11
|
- **⚡ Performance Checks**: Identifies memory leaks, N+1 queries, and unnecessary computations
|
|
11
12
|
- **🛡️ Error Handling**: Catches missing try/catch, unhandled promises, and silent failures
|
|
12
13
|
- **✅ Test Coverage**: Checks if tests are added for new functionality
|
|
13
|
-
- **🖥️ Local Execution**: Run reviews from your terminal, no GitHub Actions required
|
|
14
|
-
- **🏢 Enterprise Support**: Works with GitHub Enterprise Server (auto-detected)
|
|
15
|
-
- **🔒 Private Repos**: Full support for private repositories
|
|
16
14
|
- **💬 Inline Comments**: Posts review comments directly on the relevant lines of code
|
|
17
15
|
- **📊 Summary Report**: Provides an overview of all issues found
|
|
18
16
|
|
|
17
|
+
### Vulnerability Scanning
|
|
18
|
+
- **🔍 Multi-Language Support**: Scans npm, Python, Go, Rust, Ruby, PHP, Java, and .NET projects
|
|
19
|
+
- **🤖 AI-Powered Analysis**: Uses Codex or Claude to detect vulnerabilities beyond native tools
|
|
20
|
+
- **📋 CVE Tracking**: Lists all CVE identifiers found in dependencies
|
|
21
|
+
- **🔧 Auto-Fix**: Generates fixes and creates PRs automatically with `--fix` flag
|
|
22
|
+
- **🎯 Context-Aware Severity**: Adjusts severity based on project type (bundled vs server-side)
|
|
23
|
+
|
|
24
|
+
### General
|
|
25
|
+
- **🖥️ Local Execution**: Run from your terminal, no GitHub Actions / Jenkins required
|
|
26
|
+
- **🏢 Enterprise Support**: Works with GitHub Enterprise Server (auto-detected)
|
|
27
|
+
- **🔒 Private Repos**: Full support for private repositories
|
|
28
|
+
|
|
19
29
|
## Installation
|
|
20
30
|
|
|
21
31
|
### Prerequisites
|
|
@@ -38,20 +48,97 @@ npm install -g nayan-ai
|
|
|
38
48
|
|
|
39
49
|
## Usage
|
|
40
50
|
|
|
41
|
-
###
|
|
51
|
+
### Review Command
|
|
52
|
+
|
|
53
|
+
Review a GitHub Pull Request for code issues:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
nayan-ai review https://github.com/owner/repo/pull/123 --token ghp_xxx
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Review Options
|
|
60
|
+
|
|
61
|
+
| Option | Description |
|
|
62
|
+
|--------|-------------|
|
|
63
|
+
| `-t, --token` | GitHub personal access token (required) |
|
|
64
|
+
| `-l, --llm` | LLM provider: `codex` (default) or `claude` |
|
|
65
|
+
| `-d, --dry` | Analyze without posting comments to GitHub |
|
|
66
|
+
| `-i, --inline` | Post inline comments on files instead of summary |
|
|
67
|
+
|
|
68
|
+
### Scan Command
|
|
69
|
+
|
|
70
|
+
Scan a GitHub repository for package vulnerabilities using native tools + AI analysis:
|
|
42
71
|
|
|
43
72
|
```bash
|
|
44
|
-
#
|
|
45
|
-
nayan-ai https://github.com/owner/repo
|
|
73
|
+
# Basic scan - detect and analyze all projects in the repo
|
|
74
|
+
nayan-ai scan https://github.com/owner/repo --token ghp_xxx
|
|
75
|
+
|
|
76
|
+
# Scan specific paths in the repo (detects all projects inside)
|
|
77
|
+
nayan-ai scan https://github.com/owner/repo --token ghp_xxx --paths packages/api,packages/web
|
|
78
|
+
|
|
79
|
+
# Auto-fix vulnerabilities and create a PR
|
|
80
|
+
nayan-ai scan https://github.com/owner/repo --token ghp_xxx --fix
|
|
81
|
+
|
|
82
|
+
# Auto-fix with custom branch name
|
|
83
|
+
nayan-ai scan https://github.com/owner/repo --token ghp_xxx --fix --branch nayan-ai/security-updates
|
|
46
84
|
```
|
|
47
85
|
|
|
48
|
-
|
|
86
|
+
#### Scan Options
|
|
87
|
+
|
|
88
|
+
| Option | Description |
|
|
89
|
+
|--------|-------------|
|
|
90
|
+
| `-t, --token` | GitHub personal access token (required) |
|
|
91
|
+
| `-l, --llm` | LLM provider: `codex` (default) or `claude` |
|
|
92
|
+
| `-p, --paths` | Comma-separated list of paths to scan for projects |
|
|
93
|
+
| `-f, --fix` | Auto-fix vulnerabilities and create a PR |
|
|
94
|
+
| `-b, --branch` | Branch name for fix PR (default: `nayan-ai/security-fixes-<timestamp>`) |
|
|
95
|
+
|
|
96
|
+
#### Scan Output
|
|
97
|
+
|
|
98
|
+
The scan provides:
|
|
99
|
+
- **Per-project vulnerabilities** grouped by severity (Critical, High, Medium, Low)
|
|
100
|
+
- **CVE identifiers** for each vulnerability
|
|
101
|
+
- **Suggested fixes** with package version updates
|
|
102
|
+
- **Breaking changes warnings** when applicable
|
|
103
|
+
|
|
104
|
+
#### Auto-Fix Workflow
|
|
105
|
+
|
|
106
|
+
When using `--fix`, Nayan AI will:
|
|
107
|
+
1. Analyze vulnerabilities and generate fixes using AI
|
|
108
|
+
2. Create a new branch with the fixes
|
|
109
|
+
3. Update manifest files (package.json, requirements.txt, etc.)
|
|
110
|
+
4. Commit and push changes
|
|
111
|
+
5. Create a Pull Request with detailed description of all changes
|
|
112
|
+
|
|
113
|
+
#### Supported Project Types
|
|
114
|
+
|
|
115
|
+
| Type | Manifest | Lock Files | Native Scanner |
|
|
116
|
+
|------|----------|------------|----------------|
|
|
117
|
+
| **npm** | package.json | package-lock.json, yarn.lock, pnpm-lock.yaml | `npm audit` |
|
|
118
|
+
| **Python** | requirements.txt | Pipfile.lock, poetry.lock | `pip-audit` |
|
|
119
|
+
| **Go** | go.mod | go.sum | `govulncheck` |
|
|
120
|
+
| **Rust** | Cargo.toml | Cargo.lock | `cargo audit` |
|
|
121
|
+
| **Ruby** | Gemfile | Gemfile.lock | `bundle audit` |
|
|
122
|
+
| **PHP** | composer.json | composer.lock | `composer audit` |
|
|
123
|
+
| **Java** | pom.xml | - | `mvn dependency-check` |
|
|
124
|
+
| **.NET** | *.csproj | packages.lock.json | `dotnet list --vulnerable` |
|
|
125
|
+
|
|
126
|
+
#### Context-Aware Severity
|
|
127
|
+
|
|
128
|
+
The AI adjusts vulnerability severity based on project context:
|
|
129
|
+
|
|
130
|
+
- **Bundled/Static Projects** (React, Vue, Angular, SPAs):
|
|
131
|
+
- DevDependencies → LOW (not in production bundle)
|
|
132
|
+
- Build tools (webpack, babel, eslint) → LOW
|
|
133
|
+
- Only runtime deps in client bundle → HIGH
|
|
134
|
+
|
|
135
|
+
- **Server-side Projects** (Node.js APIs, Express):
|
|
136
|
+
- Runtime dependencies → HIGH
|
|
137
|
+
- DevDependencies → LOW
|
|
49
138
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| `-d, --dry` | Analyze without posting comments to Github |
|
|
54
|
-
| `-i, --inline` | Post inline comments on files instead of summary |
|
|
139
|
+
- **Libraries** (npm/pypi packages):
|
|
140
|
+
- Runtime deps → HIGH (affects consumers)
|
|
141
|
+
- DevDependencies → LOW
|
|
55
142
|
|
|
56
143
|
## License
|
|
57
144
|
|
package/dist/cli.js
CHANGED
|
@@ -1,172 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from 'commander';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import { GitHubClient, parseFiles, parsePRReference } from './github.js';
|
|
6
|
-
import { issuesToReviewComments, generateSummary } from './analyzer.js';
|
|
7
|
-
import { analyzeWithCodex } from './codex.js';
|
|
8
|
-
import { analyzeWithClaude } from './claude.js';
|
|
9
|
-
import { cloneRepo } from './repo.js';
|
|
10
3
|
import { createRequire } from 'module';
|
|
11
|
-
import {
|
|
4
|
+
import { reviewCommand } from './review/command.js';
|
|
5
|
+
import { scanCommand } from './scan/command.js';
|
|
12
6
|
const require = createRequire(import.meta.url);
|
|
13
7
|
const { version } = require('../package.json');
|
|
14
|
-
const VALID_LLM_PROVIDERS = ['codex', 'claude'];
|
|
15
8
|
program
|
|
16
9
|
.name('nayan-ai')
|
|
17
|
-
.description('AI
|
|
18
|
-
.version(version)
|
|
10
|
+
.description('AI powered code reviewer using Codex & Claude Code agents')
|
|
11
|
+
.version(version);
|
|
12
|
+
program
|
|
13
|
+
.command('review')
|
|
14
|
+
.description('Review a GitHub Pull Request')
|
|
19
15
|
.argument('<pr-url>', 'GitHub PR URL (e.g., https://github.com/owner/repo/pull/123)')
|
|
20
16
|
.requiredOption('-t, --token <token>', 'GitHub personal access token')
|
|
21
|
-
.option('-v, --verbose', 'Show real-time output from
|
|
17
|
+
.option('-v, --verbose', 'Show real-time output from CLI', false)
|
|
22
18
|
.option('-d, --dry', 'Only analyze, don\'t post comments', false)
|
|
23
19
|
.option('-i, --inline', 'Post inline comments instead of summary', false)
|
|
24
20
|
.option('-l, --llm <provider>', 'LLM provider: codex (default) or claude', 'codex')
|
|
25
21
|
.option('--format <format>', 'Output format: text, json', 'text')
|
|
26
|
-
.action(
|
|
22
|
+
.action((prUrl, options) => reviewCommand(prUrl, options));
|
|
23
|
+
program
|
|
24
|
+
.command('scan')
|
|
25
|
+
.description('Scan a GitHub repository for package vulnerabilities using AI')
|
|
26
|
+
.argument('<repo-url>', 'GitHub repo URL (e.g., https://github.com/owner/repo)')
|
|
27
|
+
.requiredOption('-t, --token <token>', 'GitHub personal access token')
|
|
28
|
+
.option('-p, --paths <paths>', 'Comma-separated list of paths to scan for projects')
|
|
29
|
+
.option('-l, --llm <provider>', 'LLM provider: codex (default) or claude', 'codex')
|
|
30
|
+
.option('-v, --verbose', 'Show real-time output from CLI', false)
|
|
31
|
+
.option('--format <format>', 'Output format: text, json', 'text')
|
|
32
|
+
.option('-f, --fix', 'Auto-fix vulnerabilities and create a PR with changes', false)
|
|
33
|
+
.option('-b, --branch <name>', 'Branch name for fix PR', 'nayan-ai/security-fixes-' + Date.now())
|
|
34
|
+
.action((repoUrl, options) => scanCommand(repoUrl, options));
|
|
27
35
|
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
|
-
}
|
|
36
|
-
async function run(prUrl, options) {
|
|
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);
|
|
45
|
-
const prInfo = parsePRReference(prUrl);
|
|
46
|
-
const githubUrl = prInfo.githubUrl;
|
|
47
|
-
console.log(chalk.bold.blue('\n🤖 Nayan AI - PR Reviewer'));
|
|
48
|
-
console.log('━'.repeat(40));
|
|
49
|
-
console.log(` Repository: ${chalk.cyan(`${prInfo.owner}/${prInfo.repo}`)}`);
|
|
50
|
-
console.log(` PR Number: ${chalk.cyan(`#${prInfo.number}`)}`);
|
|
51
|
-
if (githubUrl) {
|
|
52
|
-
console.log(` GitHub: ${chalk.cyan(githubUrl)}`);
|
|
53
|
-
}
|
|
54
|
-
if (options.dry) {
|
|
55
|
-
console.log(` Mode: ${chalk.yellow('Dry Run (no comments will be posted)')}`);
|
|
56
|
-
}
|
|
57
|
-
console.log('━'.repeat(40) + '\n');
|
|
58
|
-
const github = new GitHubClient(options.token, githubUrl);
|
|
59
|
-
// Fetch PR details
|
|
60
|
-
let spinner = ora('Fetching PR details...').start();
|
|
61
|
-
const pr = await github.getPullRequest(prInfo);
|
|
62
|
-
spinner.succeed(`PR: ${pr.title}`);
|
|
63
|
-
// Fetch changed files
|
|
64
|
-
spinner = ora('Fetching changed files...').start();
|
|
65
|
-
const files = await github.getPullRequestFiles(prInfo);
|
|
66
|
-
const fileChanges = parseFiles(files);
|
|
67
|
-
spinner.succeed(`Found ${fileChanges.length} files with changes`);
|
|
68
|
-
// Clone and analyze with Codex CLI
|
|
69
|
-
spinner = ora('Cloning repository...').start();
|
|
70
|
-
const repo = await cloneRepo(prInfo, options.token, githubUrl);
|
|
71
|
-
let issues;
|
|
72
|
-
try {
|
|
73
|
-
spinner.succeed('Repository cloned');
|
|
74
|
-
const llmName = options.llm === 'claude' ? 'Claude Code' : 'Codex';
|
|
75
|
-
console.log(chalk.cyan(`Running code review with ${llmName} CLI...\n`));
|
|
76
|
-
if (options.llm === 'claude') {
|
|
77
|
-
const claudeOpts = { verbose: options.verbose };
|
|
78
|
-
issues = await analyzeWithClaude(repo.path, 'origin/main', claudeOpts);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
const codexOpts = { verbose: options.verbose };
|
|
82
|
-
issues = await analyzeWithCodex(repo.path, 'origin/main', codexOpts);
|
|
83
|
-
}
|
|
84
|
-
console.log(chalk.green(`\n✔ Analysis complete: ${issues.length} issues found`));
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
await repo.cleanup();
|
|
88
|
-
}
|
|
89
|
-
// Display results
|
|
90
|
-
console.log(chalk.bold('\n📋 Review Summary'));
|
|
91
|
-
console.log('─'.repeat(41));
|
|
92
|
-
if (options.format === 'json') {
|
|
93
|
-
console.log(JSON.stringify(issues, null, 2));
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
printIssuesSummary(issues);
|
|
97
|
-
}
|
|
98
|
-
// Post to GitHub
|
|
99
|
-
if (!options.dry) {
|
|
100
|
-
spinner = ora('Posting review to GitHub...').start();
|
|
101
|
-
if (options.inline) {
|
|
102
|
-
// Post inline comments on specific lines
|
|
103
|
-
const reviewComments = issuesToReviewComments(issues);
|
|
104
|
-
const summary = generateSummary(issues);
|
|
105
|
-
await github.postReview(prInfo, pr.head.sha, summary, reviewComments);
|
|
106
|
-
spinner.succeed('Inline review posted to GitHub');
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
// Post summary as a PR-level comment (default)
|
|
110
|
-
const summary = generateSummary(issues);
|
|
111
|
-
await github.postComment(prInfo, summary);
|
|
112
|
-
spinner.succeed('Review summary posted to GitHub');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
console.log(chalk.yellow('\nDry run mode - no comments posted to GitHub'));
|
|
117
|
-
}
|
|
118
|
-
console.log(chalk.green('\n✅ Review complete!\n'));
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
console.error(chalk.red('\nError:'), error instanceof Error ? error.message : error);
|
|
122
|
-
process.exit(1);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function printIssuesSummary(issues) {
|
|
126
|
-
if (issues.length === 0) {
|
|
127
|
-
console.log(chalk.green(' No issues found! The code looks good.'));
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
const bySeverity = {
|
|
131
|
-
error: issues.filter((i) => i.severity === 'error'),
|
|
132
|
-
warning: issues.filter((i) => i.severity === 'warning'),
|
|
133
|
-
info: issues.filter((i) => i.severity === 'info'),
|
|
134
|
-
};
|
|
135
|
-
// Print errors
|
|
136
|
-
if (bySeverity.error.length > 0) {
|
|
137
|
-
console.log(chalk.red.bold(`\n 🔴 Errors (${bySeverity.error.length}):`));
|
|
138
|
-
for (const issue of bySeverity.error) {
|
|
139
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
140
|
-
console.log(chalk.red(` ${icon} ${issue.filename}:${issue.line}`));
|
|
141
|
-
console.log(` ${issue.message}`);
|
|
142
|
-
if (issue.suggestion) {
|
|
143
|
-
console.log(chalk.dim(` 💡 ${issue.suggestion}`));
|
|
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
|
-
// Print info
|
|
160
|
-
if (bySeverity.info.length > 0) {
|
|
161
|
-
console.log(chalk.blue.bold(`\n 🔵 Info (${bySeverity.info.length}):`));
|
|
162
|
-
for (const issue of bySeverity.info) {
|
|
163
|
-
const icon = issue.category === 'functionality' ? '🐛' : issue.category === 'readability' ? '📖' : '⚡';
|
|
164
|
-
console.log(chalk.blue(` ${icon} ${issue.filename}:${issue.line}`));
|
|
165
|
-
console.log(` ${issue.message}`);
|
|
166
|
-
if (issue.suggestion) {
|
|
167
|
-
console.log(chalk.dim(` 💡 ${issue.suggestion}`));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
36
|
//# sourceMappingURL=cli.js.map
|
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,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,2DAA2D,CAAC;KACxE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,QAAQ,CAAC,UAAU,EAAE,8DAA8D,CAAC;KACpF,cAAc,CAAC,qBAAqB,EAAE,8BAA8B,CAAC;KACrE,MAAM,CAAC,eAAe,EAAE,gCAAgC,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,oCAAoC,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,cAAc,EAAE,yCAAyC,EAAE,KAAK,CAAC;KACxE,MAAM,CAAC,sBAAsB,EAAE,yCAAyC,EAAE,OAAO,CAAC;KAClF,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,CAAC;KAChE,MAAM,CAAC,CAAC,KAAa,EAAE,OAAsB,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpF,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,+DAA+D,CAAC;KAC5E,QAAQ,CAAC,YAAY,EAAE,uDAAuD,CAAC;KAC/E,cAAc,CAAC,qBAAqB,EAAE,8BAA8B,CAAC;KACrE,MAAM,CAAC,qBAAqB,EAAE,oDAAoD,CAAC;KACnF,MAAM,CAAC,sBAAsB,EAAE,yCAAyC,EAAE,OAAO,CAAC;KAClF,MAAM,CAAC,eAAe,EAAE,gCAAgC,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,uDAAuD,EAAE,KAAK,CAAC;KACnF,MAAM,CAAC,qBAAqB,EAAE,wBAAwB,EAAE,0BAA0B,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;KAChG,MAAM,CAAC,CAAC,OAAe,EAAE,OAAoB,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpF,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeIssue } from './types.js';
|
|
2
|
+
export interface ClaudeOptions {
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const analyzeWithClaude: (repoPath: string, prompt: string, options: ClaudeOptions) => Promise<CodeIssue[]>;
|
|
6
|
+
export declare const analyzeWithClaudeRaw: (repoPath: string, prompt: string, options: ClaudeOptions) => Promise<any>;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export const analyzeWithClaude = async (repoPath, prompt, options) => {
|
|
4
|
+
const response = await runClaudeExec(repoPath, prompt, options);
|
|
5
|
+
return parseClaudeResponse(response);
|
|
6
|
+
};
|
|
7
|
+
export const analyzeWithClaudeRaw = async (repoPath, prompt, options) => {
|
|
8
|
+
const response = await runClaudeExec(repoPath, prompt, options);
|
|
9
|
+
return parseClaudeResponseRaw(response);
|
|
10
|
+
};
|
|
11
|
+
const runClaudeExec = (repoPath, prompt, options) => new Promise((resolve, reject) => {
|
|
12
|
+
const args = ['-p', '--output-format', 'json', prompt];
|
|
13
|
+
if (options.verbose) {
|
|
14
|
+
console.log(`\n[Claude] Running: claude ${args.slice(0, 3).join(' ')} "<prompt>"`);
|
|
15
|
+
console.log(`[Claude] Working directory: ${repoPath}`);
|
|
16
|
+
}
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
const child = spawn('claude', args, { cwd: repoPath, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
19
|
+
let stdout = '';
|
|
20
|
+
let stderr = '';
|
|
21
|
+
child.stdout.on('data', (data) => {
|
|
22
|
+
const chunk = data.toString();
|
|
23
|
+
stdout += chunk;
|
|
24
|
+
if (options.verbose) {
|
|
25
|
+
process.stdout.write(chunk);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
process.stdout.write(chalk.gray('.'));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
child.stderr.on('data', (data) => {
|
|
32
|
+
const chunk = data.toString();
|
|
33
|
+
stderr += chunk;
|
|
34
|
+
if (options.verbose)
|
|
35
|
+
process.stderr.write(chunk);
|
|
36
|
+
});
|
|
37
|
+
child.on('close', (code) => {
|
|
38
|
+
if (!options.verbose)
|
|
39
|
+
console.log();
|
|
40
|
+
console.log(`\n[Claude] Completed in ${((Date.now() - startTime) / 1000).toFixed(1)}s`);
|
|
41
|
+
if (code !== 0) {
|
|
42
|
+
reject(new Error(`Claude review failed (exit ${code}): ${(stderr || stdout || 'Unknown error').slice(0, 500)}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
resolve(stdout);
|
|
46
|
+
});
|
|
47
|
+
child.on('error', (err) => {
|
|
48
|
+
if (err.code === 'ENOENT') {
|
|
49
|
+
reject(new Error('claude CLI not found. Install Claude Code CLI first: https://code.claude.com'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
reject(err);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
const mapIssue = (item) => ({
|
|
56
|
+
filename: item.filename || item.package || 'unknown',
|
|
57
|
+
line: item.line || 0,
|
|
58
|
+
category: item.category || 'functionality',
|
|
59
|
+
severity: item.severity || 'info',
|
|
60
|
+
message: item.message || item.title || item.description,
|
|
61
|
+
suggestion: item.suggestion || item.fixedIn,
|
|
62
|
+
// Preserve vulnerability-specific fields for scan command
|
|
63
|
+
package: item.package,
|
|
64
|
+
version: item.version,
|
|
65
|
+
title: item.title,
|
|
66
|
+
description: item.description,
|
|
67
|
+
fixedIn: item.fixedIn,
|
|
68
|
+
cve: item.cve,
|
|
69
|
+
});
|
|
70
|
+
const extractItems = (json) => {
|
|
71
|
+
if (Array.isArray(json.issues))
|
|
72
|
+
return json.issues;
|
|
73
|
+
if (Array.isArray(json.vulnerabilities))
|
|
74
|
+
return json.vulnerabilities;
|
|
75
|
+
return [];
|
|
76
|
+
};
|
|
77
|
+
const extractFixData = (text) => {
|
|
78
|
+
const fixMatch = text.match(/\{[\s\S]*"(?:fixes|updatedManifest)"[\s\S]*\}/);
|
|
79
|
+
if (!fixMatch)
|
|
80
|
+
return null;
|
|
81
|
+
try {
|
|
82
|
+
const parsed = JSON.parse(fixMatch[0]);
|
|
83
|
+
if (parsed.fixes || parsed.updatedManifest)
|
|
84
|
+
return parsed;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// ignore
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
};
|
|
91
|
+
const extractIssuesFromText = (text) => {
|
|
92
|
+
// First check for fix response
|
|
93
|
+
const fixData = extractFixData(text);
|
|
94
|
+
if (fixData) {
|
|
95
|
+
return [{
|
|
96
|
+
...mapIssue({ message: 'Fix response' }),
|
|
97
|
+
_rawFixData: fixData
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
100
|
+
const jsonMatch = text.match(/\{\s*"(?:issues|vulnerabilities)"\s*:\s*\[[\s\S]*?\]\s*\}/);
|
|
101
|
+
if (!jsonMatch)
|
|
102
|
+
return null;
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
105
|
+
const items = extractItems(parsed);
|
|
106
|
+
if (items.length > 0) {
|
|
107
|
+
return items.filter((item) => item.message || item.package || item.title).map(mapIssue);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// ignore
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
};
|
|
115
|
+
const parseClaudeResponse = (response) => {
|
|
116
|
+
try {
|
|
117
|
+
const parsed = JSON.parse(response);
|
|
118
|
+
const text = parsed.result || parsed.text || response;
|
|
119
|
+
// Check for fix response first
|
|
120
|
+
const fixData = extractFixData(typeof text === 'string' ? text : JSON.stringify(text));
|
|
121
|
+
if (fixData) {
|
|
122
|
+
return [{
|
|
123
|
+
...mapIssue({ message: 'Fix response' }),
|
|
124
|
+
_rawFixData: fixData
|
|
125
|
+
}];
|
|
126
|
+
}
|
|
127
|
+
const issues = extractIssuesFromText(text);
|
|
128
|
+
if (issues)
|
|
129
|
+
return issues;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Not valid JSON wrapper
|
|
133
|
+
}
|
|
134
|
+
const issues = extractIssuesFromText(response);
|
|
135
|
+
if (issues)
|
|
136
|
+
return issues;
|
|
137
|
+
if (response.trim() && !response.includes('"issues"') && !response.includes('"vulnerabilities"')) {
|
|
138
|
+
console.warn(chalk.yellow(`\n⚠ Warning: Claude response does not contain expected format`));
|
|
139
|
+
console.warn(chalk.gray(` Response preview: ${response.slice(0, 200)}...`));
|
|
140
|
+
}
|
|
141
|
+
return [];
|
|
142
|
+
};
|
|
143
|
+
const parseClaudeResponseRaw = (response) => {
|
|
144
|
+
try {
|
|
145
|
+
const parsed = JSON.parse(response);
|
|
146
|
+
const text = parsed.result || parsed.text || response;
|
|
147
|
+
// Try to parse the text as JSON
|
|
148
|
+
if (typeof text === 'string') {
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(text);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Text contains JSON somewhere
|
|
154
|
+
const jsonMatch = text.match(/\{[\s\S]*"(?:fixes|updatedManifest|issues|vulnerabilities)"[\s\S]*\}/);
|
|
155
|
+
if (jsonMatch) {
|
|
156
|
+
return JSON.parse(jsonMatch[0]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// If parsed already has the structure we need
|
|
161
|
+
if (parsed.fixes || parsed.updatedManifest) {
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Not valid JSON wrapper
|
|
167
|
+
}
|
|
168
|
+
// Try to find JSON in raw response
|
|
169
|
+
const jsonMatch = response.match(/\{[\s\S]*"(?:fixes|updatedManifest|issues|vulnerabilities)"[\s\S]*\}/);
|
|
170
|
+
if (jsonMatch) {
|
|
171
|
+
try {
|
|
172
|
+
return JSON.parse(jsonMatch[0]);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// ignore
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/common/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeIssue } from './types.js';
|
|
2
|
+
export interface CodexOptions {
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const analyzeWithCodex: (repoPath: string, prompt: string, options: CodexOptions) => Promise<CodeIssue[]>;
|
|
6
|
+
export declare const analyzeWithCodexRaw: (repoPath: string, prompt: string, options: CodexOptions) => Promise<any>;
|