vantaverse-ai-reviewer 0.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 +129 -0
- package/bin/cli.js +12 -0
- package/dist/ai/agent.d.ts +54 -0
- package/dist/ai/agent.d.ts.map +1 -0
- package/dist/ai/agent.js +141 -0
- package/dist/ai/agent.js.map +1 -0
- package/dist/ai/gemini-client.d.ts +37 -0
- package/dist/ai/gemini-client.d.ts.map +1 -0
- package/dist/ai/gemini-client.js +75 -0
- package/dist/ai/gemini-client.js.map +1 -0
- package/dist/ai/prompts.d.ts +25 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +176 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/auth/token-manager.d.ts +33 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +97 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/commands/config.d.ts +12 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +84 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/scan.d.ts +14 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +110 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/core/executor.d.ts +33 -0
- package/dist/core/executor.d.ts.map +1 -0
- package/dist/core/executor.js +149 -0
- package/dist/core/executor.js.map +1 -0
- package/dist/core/framework-detector.d.ts +20 -0
- package/dist/core/framework-detector.d.ts.map +1 -0
- package/dist/core/framework-detector.js +155 -0
- package/dist/core/framework-detector.js.map +1 -0
- package/dist/core/scanner.d.ts +34 -0
- package/dist/core/scanner.d.ts.map +1 -0
- package/dist/core/scanner.js +172 -0
- package/dist/core/scanner.js.map +1 -0
- package/dist/core/security.d.ts +40 -0
- package/dist/core/security.d.ts.map +1 -0
- package/dist/core/security.js +118 -0
- package/dist/core/security.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/reporters/markdown.d.ts +25 -0
- package/dist/reporters/markdown.d.ts.map +1 -0
- package/dist/reporters/markdown.js +135 -0
- package/dist/reporters/markdown.js.map +1 -0
- package/dist/utils/logger.d.ts +50 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Manager - Secure storage for Gemini API token
|
|
3
|
+
* Uses 'conf' for encrypted local storage
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if a valid token is stored
|
|
7
|
+
*/
|
|
8
|
+
export declare function hasToken(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Get the stored Gemini token
|
|
11
|
+
*/
|
|
12
|
+
export declare function getToken(): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Store a new Gemini token
|
|
15
|
+
*/
|
|
16
|
+
export declare function setToken(token: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clear the stored token
|
|
19
|
+
*/
|
|
20
|
+
export declare function clearToken(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Validate token format (basic check)
|
|
23
|
+
*/
|
|
24
|
+
export declare function isValidTokenFormat(token: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Interactively prompt for token if not set
|
|
27
|
+
*/
|
|
28
|
+
export declare function ensureToken(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Show token configuration status
|
|
31
|
+
*/
|
|
32
|
+
export declare function showTokenStatus(): void;
|
|
33
|
+
//# sourceMappingURL=token-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG5C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAGjC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAgCnD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAWtC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Manager - Secure storage for Gemini API token
|
|
3
|
+
* Uses 'conf' for encrypted local storage
|
|
4
|
+
*/
|
|
5
|
+
import Conf from 'conf';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
const config = new Conf({
|
|
9
|
+
projectName: 'ai-reviewer',
|
|
10
|
+
encryptionKey: 'ai-reviewer-secure-storage-v1',
|
|
11
|
+
schema: {
|
|
12
|
+
geminiToken: { type: 'string' },
|
|
13
|
+
configuredAt: { type: 'string' }
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Check if a valid token is stored
|
|
18
|
+
*/
|
|
19
|
+
export function hasToken() {
|
|
20
|
+
return !!config.get('geminiToken');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the stored Gemini token
|
|
24
|
+
*/
|
|
25
|
+
export function getToken() {
|
|
26
|
+
return config.get('geminiToken');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store a new Gemini token
|
|
30
|
+
*/
|
|
31
|
+
export function setToken(token) {
|
|
32
|
+
config.set('geminiToken', token);
|
|
33
|
+
config.set('configuredAt', new Date().toISOString());
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clear the stored token
|
|
37
|
+
*/
|
|
38
|
+
export function clearToken() {
|
|
39
|
+
config.delete('geminiToken');
|
|
40
|
+
config.delete('configuredAt');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate token format (basic check)
|
|
44
|
+
*/
|
|
45
|
+
export function isValidTokenFormat(token) {
|
|
46
|
+
// Gemini API keys are typically 39 characters
|
|
47
|
+
return token.length >= 30 && token.length <= 50 && /^[A-Za-z0-9_-]+$/.test(token);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Interactively prompt for token if not set
|
|
51
|
+
*/
|
|
52
|
+
export async function ensureToken() {
|
|
53
|
+
const existing = getToken();
|
|
54
|
+
if (existing) {
|
|
55
|
+
return existing;
|
|
56
|
+
}
|
|
57
|
+
console.log(chalk.yellow('\n🔑 Gemini API token not found.\n'));
|
|
58
|
+
console.log(chalk.dim('Get your API key from: https://aistudio.google.com/apikey\n'));
|
|
59
|
+
const { token } = await inquirer.prompt([
|
|
60
|
+
{
|
|
61
|
+
type: 'password',
|
|
62
|
+
name: 'token',
|
|
63
|
+
message: 'Enter your Gemini API token:',
|
|
64
|
+
mask: '*',
|
|
65
|
+
validate: (input) => {
|
|
66
|
+
if (!input.trim()) {
|
|
67
|
+
return 'Token is required';
|
|
68
|
+
}
|
|
69
|
+
if (!isValidTokenFormat(input.trim())) {
|
|
70
|
+
return 'Invalid token format. Should be 30-50 alphanumeric characters.';
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
const trimmedToken = token.trim();
|
|
77
|
+
setToken(trimmedToken);
|
|
78
|
+
console.log(chalk.green('✓ Token saved securely.\n'));
|
|
79
|
+
return trimmedToken;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Show token configuration status
|
|
83
|
+
*/
|
|
84
|
+
export function showTokenStatus() {
|
|
85
|
+
if (hasToken()) {
|
|
86
|
+
const configuredAt = config.get('configuredAt');
|
|
87
|
+
console.log(chalk.green('✓ Gemini token is configured'));
|
|
88
|
+
if (configuredAt) {
|
|
89
|
+
console.log(chalk.dim(` Configured: ${new Date(configuredAt).toLocaleString()}`));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(chalk.yellow('⚠ Gemini token is not configured'));
|
|
94
|
+
console.log(chalk.dim(' Run "ai-reviewer scan" to configure'));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=token-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Command - Manage AI Reviewer configuration
|
|
3
|
+
*/
|
|
4
|
+
export type ConfigAction = 'show' | 'reset' | 'token';
|
|
5
|
+
export interface ConfigOptions {
|
|
6
|
+
action?: ConfigAction;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Execute the config command
|
|
10
|
+
*/
|
|
11
|
+
export declare function config(options?: ConfigOptions): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBvE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Command - Manage AI Reviewer configuration
|
|
3
|
+
*/
|
|
4
|
+
import * as logger from '../utils/logger.js';
|
|
5
|
+
import { hasToken, showTokenStatus, clearToken, ensureToken } from '../auth/token-manager.js';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
/**
|
|
8
|
+
* Execute the config command
|
|
9
|
+
*/
|
|
10
|
+
export async function config(options = {}) {
|
|
11
|
+
const action = options.action || 'show';
|
|
12
|
+
switch (action) {
|
|
13
|
+
case 'show':
|
|
14
|
+
await showConfig();
|
|
15
|
+
break;
|
|
16
|
+
case 'reset':
|
|
17
|
+
await resetConfig();
|
|
18
|
+
break;
|
|
19
|
+
case 'token':
|
|
20
|
+
await configureToken();
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
logger.error(`Unknown action: ${action}`);
|
|
24
|
+
logger.info('Available actions: show, reset, token');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Show current configuration
|
|
29
|
+
*/
|
|
30
|
+
async function showConfig() {
|
|
31
|
+
logger.header('AI Reviewer Configuration');
|
|
32
|
+
showTokenStatus();
|
|
33
|
+
console.log();
|
|
34
|
+
logger.info('Available commands:');
|
|
35
|
+
console.log(' ai-reviewer config --action token - Update API token');
|
|
36
|
+
console.log(' ai-reviewer config --action reset - Clear all settings');
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reset all configuration
|
|
40
|
+
*/
|
|
41
|
+
async function resetConfig() {
|
|
42
|
+
if (!hasToken()) {
|
|
43
|
+
logger.info('No configuration to reset.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { confirm } = await inquirer.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: 'confirm',
|
|
49
|
+
name: 'confirm',
|
|
50
|
+
message: 'Are you sure you want to clear all settings including your API token?',
|
|
51
|
+
default: false
|
|
52
|
+
}
|
|
53
|
+
]);
|
|
54
|
+
if (confirm) {
|
|
55
|
+
clearToken();
|
|
56
|
+
logger.success('Configuration reset successfully.');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
logger.info('Reset cancelled.');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Configure or update the API token
|
|
64
|
+
*/
|
|
65
|
+
async function configureToken() {
|
|
66
|
+
if (hasToken()) {
|
|
67
|
+
const { override } = await inquirer.prompt([
|
|
68
|
+
{
|
|
69
|
+
type: 'confirm',
|
|
70
|
+
name: 'override',
|
|
71
|
+
message: 'A token is already configured. Do you want to replace it?',
|
|
72
|
+
default: false
|
|
73
|
+
}
|
|
74
|
+
]);
|
|
75
|
+
if (!override) {
|
|
76
|
+
logger.info('Token update cancelled.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
clearToken();
|
|
80
|
+
}
|
|
81
|
+
await ensureToken();
|
|
82
|
+
logger.success('Token configured successfully.');
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,QAAQ,MAAM,UAAU,CAAC;AAQhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAyB,EAAE;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;IAExC,QAAQ,MAAM,EAAE,CAAC;QACb,KAAK,MAAM;YACP,MAAM,UAAU,EAAE,CAAC;YACnB,MAAM;QACV,KAAK,OAAO;YACR,MAAM,WAAW,EAAE,CAAC;YACpB,MAAM;QACV,KAAK,OAAO;YACR,MAAM,cAAc,EAAE,CAAC;YACvB,MAAM;QACV;YACI,MAAM,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IAC7D,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU;IACrB,MAAM,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;IAE3C,eAAe,EAAE,CAAC;IAElB,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;AAC7E,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW;IACtB,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO;IACX,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAuB;QAC5D;YACI,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,uEAAuE;YAChF,OAAO,EAAE,KAAK;SACjB;KACJ,CAAC,CAAC;IAEH,IAAI,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,CAAC;QACb,MAAM,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACJ,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACpC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc;IACzB,IAAI,QAAQ,EAAE,EAAE,CAAC;QACb,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAwB;YAC9D;gBACI,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,2DAA2D;gBACpE,OAAO,EAAE,KAAK;aACjB;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO;QACX,CAAC;QAED,UAAU,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan Command - Main analysis command
|
|
3
|
+
*/
|
|
4
|
+
export interface ScanOptions {
|
|
5
|
+
output?: string;
|
|
6
|
+
json?: boolean;
|
|
7
|
+
types?: string;
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Execute the scan command
|
|
12
|
+
*/
|
|
13
|
+
export declare function scan(options?: ScanOptions): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHnE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scan Command - Main analysis command
|
|
3
|
+
*/
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import * as logger from '../utils/logger.js';
|
|
6
|
+
import { ensureToken } from '../auth/token-manager.js';
|
|
7
|
+
import { detectFramework, getFrameworkHints } from '../core/framework-detector.js';
|
|
8
|
+
import { scanRepository, getScanSummary } from '../core/scanner.js';
|
|
9
|
+
import { createGeminiClient } from '../ai/gemini-client.js';
|
|
10
|
+
import { createAgent } from '../ai/agent.js';
|
|
11
|
+
import { generateMarkdownReport, writeReport, generateJsonReport } from '../reporters/markdown.js';
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
/**
|
|
14
|
+
* Execute the scan command
|
|
15
|
+
*/
|
|
16
|
+
export async function scan(options = {}) {
|
|
17
|
+
const repoRoot = process.cwd();
|
|
18
|
+
logger.banner();
|
|
19
|
+
// Ensure we have a token
|
|
20
|
+
const spin = logger.spinner('Checking Gemini API token...');
|
|
21
|
+
spin.start();
|
|
22
|
+
try {
|
|
23
|
+
const token = await ensureToken();
|
|
24
|
+
spin.succeed('Gemini API token ready');
|
|
25
|
+
// Validate token with a quick check
|
|
26
|
+
spin.start('Validating API access...');
|
|
27
|
+
const client = createGeminiClient(token);
|
|
28
|
+
const isValid = await client.validateKey();
|
|
29
|
+
if (!isValid) {
|
|
30
|
+
spin.fail('Invalid Gemini API token');
|
|
31
|
+
logger.error('Please check your token and try again.');
|
|
32
|
+
logger.info('Get a new key at: https://aistudio.google.com/apikey');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
spin.succeed('API access validated');
|
|
36
|
+
// Detect framework
|
|
37
|
+
spin.start('Detecting project framework...');
|
|
38
|
+
const framework = await detectFramework(repoRoot);
|
|
39
|
+
spin.succeed(`Detected: ${framework.displayName}`);
|
|
40
|
+
if (options.verbose) {
|
|
41
|
+
logger.info(`Framework hints: ${getFrameworkHints(framework.name)}`);
|
|
42
|
+
}
|
|
43
|
+
// Scan repository
|
|
44
|
+
spin.start('Scanning repository...');
|
|
45
|
+
const scanResult = await scanRepository(repoRoot, framework);
|
|
46
|
+
spin.succeed(`Found ${scanResult.files.length} files`);
|
|
47
|
+
if (options.verbose) {
|
|
48
|
+
console.log();
|
|
49
|
+
console.log(getScanSummary(scanResult));
|
|
50
|
+
}
|
|
51
|
+
if (scanResult.files.length === 0) {
|
|
52
|
+
logger.warn('No files found to analyze. Check your project structure.');
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
// Parse analysis types
|
|
56
|
+
const analysisTypes = options.types
|
|
57
|
+
? options.types.split(',')
|
|
58
|
+
: ['overview', 'security', 'codeQuality', 'accessibility'];
|
|
59
|
+
// Run AI analysis
|
|
60
|
+
logger.header('Running AI Analysis');
|
|
61
|
+
logger.info(`Analysis types: ${analysisTypes.join(', ')}`);
|
|
62
|
+
console.log();
|
|
63
|
+
spin.start('Analyzing code with Gemini AI...');
|
|
64
|
+
const agent = createAgent(client, {
|
|
65
|
+
repoRoot,
|
|
66
|
+
framework,
|
|
67
|
+
analysisTypes
|
|
68
|
+
});
|
|
69
|
+
const result = await agent.analyze(scanResult);
|
|
70
|
+
spin.succeed(`Analysis complete (${(result.duration / 1000).toFixed(1)}s)`);
|
|
71
|
+
// Generate report
|
|
72
|
+
const outputFile = options.output || 'AI_REVIEW_REPORT.md';
|
|
73
|
+
const metadata = {
|
|
74
|
+
framework,
|
|
75
|
+
scanResult,
|
|
76
|
+
generatedAt: new Date(),
|
|
77
|
+
modelName: client.getModelName()
|
|
78
|
+
};
|
|
79
|
+
if (options.json) {
|
|
80
|
+
const jsonReport = generateJsonReport(result, metadata);
|
|
81
|
+
const jsonPath = outputFile.replace('.md', '.json');
|
|
82
|
+
await fs.promises.writeFile(path.resolve(jsonPath), JSON.stringify(jsonReport, null, 2), 'utf-8');
|
|
83
|
+
logger.success(`JSON report generated: ${jsonPath}`);
|
|
84
|
+
}
|
|
85
|
+
const markdownReport = generateMarkdownReport(result, metadata);
|
|
86
|
+
const reportPath = await writeReport(markdownReport, outputFile);
|
|
87
|
+
logger.success(`Report generated: ${outputFile}`);
|
|
88
|
+
// Summary
|
|
89
|
+
console.log();
|
|
90
|
+
logger.divider();
|
|
91
|
+
logger.stats({
|
|
92
|
+
'Files Analyzed': scanResult.files.length,
|
|
93
|
+
'Tokens Used': result.totalTokens.toLocaleString(),
|
|
94
|
+
'Duration': `${(result.duration / 1000).toFixed(1)}s`,
|
|
95
|
+
'Report': reportPath
|
|
96
|
+
});
|
|
97
|
+
logger.divider();
|
|
98
|
+
console.log();
|
|
99
|
+
logger.success('Analysis complete! 🎉');
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
spin.fail('Analysis failed');
|
|
103
|
+
logger.error(error instanceof Error ? error.message : 'Unknown error');
|
|
104
|
+
if (options.verbose && error instanceof Error) {
|
|
105
|
+
console.error(error.stack);
|
|
106
|
+
}
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Command Executor - Run safe commands for context gathering
|
|
3
|
+
*/
|
|
4
|
+
export interface CommandResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
stdout: string;
|
|
7
|
+
stderr: string;
|
|
8
|
+
exitCode: number | null;
|
|
9
|
+
command: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class ExecutorError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Execute a command safely within the repository
|
|
16
|
+
*/
|
|
17
|
+
export declare function executeCommand(command: string, args: string[], cwd: string, options?: {
|
|
18
|
+
timeout?: number;
|
|
19
|
+
maxOutput?: number;
|
|
20
|
+
}): Promise<CommandResult>;
|
|
21
|
+
/**
|
|
22
|
+
* Gather repository context using safe commands
|
|
23
|
+
*/
|
|
24
|
+
export declare function gatherRepoContext(repoRoot: string): Promise<Record<string, string>>;
|
|
25
|
+
/**
|
|
26
|
+
* Run type checking and gather errors
|
|
27
|
+
*/
|
|
28
|
+
export declare function runTypeCheck(repoRoot: string): Promise<string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Run ESLint if available
|
|
31
|
+
*/
|
|
32
|
+
export declare function runLint(repoRoot: string): Promise<string[]>;
|
|
33
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI9B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACL,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACjB,GACP,OAAO,CAAC,aAAa,CAAC,CAmExB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAqCzF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBtE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBjE"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Command Executor - Run safe commands for context gathering
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
import { isAllowedCommand, sanitizeArgs } from './security.js';
|
|
6
|
+
export class ExecutorError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'ExecutorError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Execute a command safely within the repository
|
|
14
|
+
*/
|
|
15
|
+
export async function executeCommand(command, args, cwd, options = {}) {
|
|
16
|
+
const { timeout = 30000, maxOutput = 100000 } = options;
|
|
17
|
+
// Validate command is allowed
|
|
18
|
+
if (!isAllowedCommand(command)) {
|
|
19
|
+
throw new ExecutorError(`Command "${command}" is not in the allowed list`);
|
|
20
|
+
}
|
|
21
|
+
// Sanitize arguments
|
|
22
|
+
const sanitizedArgs = sanitizeArgs(args);
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
let stdout = '';
|
|
25
|
+
let stderr = '';
|
|
26
|
+
let timedOut = false;
|
|
27
|
+
const proc = spawn(command, sanitizedArgs, {
|
|
28
|
+
cwd,
|
|
29
|
+
shell: true,
|
|
30
|
+
timeout,
|
|
31
|
+
env: {
|
|
32
|
+
...process.env,
|
|
33
|
+
// Force non-interactive mode
|
|
34
|
+
CI: 'true',
|
|
35
|
+
FORCE_COLOR: '0'
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const timeoutId = setTimeout(() => {
|
|
39
|
+
timedOut = true;
|
|
40
|
+
proc.kill('SIGTERM');
|
|
41
|
+
}, timeout);
|
|
42
|
+
proc.stdout?.on('data', (data) => {
|
|
43
|
+
if (stdout.length < maxOutput) {
|
|
44
|
+
stdout += data.toString();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
proc.stderr?.on('data', (data) => {
|
|
48
|
+
if (stderr.length < maxOutput) {
|
|
49
|
+
stderr += data.toString();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
proc.on('close', (code) => {
|
|
53
|
+
clearTimeout(timeoutId);
|
|
54
|
+
resolve({
|
|
55
|
+
success: code === 0 && !timedOut,
|
|
56
|
+
stdout: stdout.slice(0, maxOutput),
|
|
57
|
+
stderr: stderr.slice(0, maxOutput),
|
|
58
|
+
exitCode: timedOut ? null : code,
|
|
59
|
+
command: `${command} ${sanitizedArgs.join(' ')}`
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
proc.on('error', (error) => {
|
|
63
|
+
clearTimeout(timeoutId);
|
|
64
|
+
resolve({
|
|
65
|
+
success: false,
|
|
66
|
+
stdout: '',
|
|
67
|
+
stderr: error.message,
|
|
68
|
+
exitCode: null,
|
|
69
|
+
command: `${command} ${sanitizedArgs.join(' ')}`
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Gather repository context using safe commands
|
|
76
|
+
*/
|
|
77
|
+
export async function gatherRepoContext(repoRoot) {
|
|
78
|
+
const context = {};
|
|
79
|
+
// Get git info
|
|
80
|
+
const gitStatus = await executeCommand('git', ['status', '--short'], repoRoot);
|
|
81
|
+
if (gitStatus.success) {
|
|
82
|
+
context['git_status'] = gitStatus.stdout || 'Clean working tree';
|
|
83
|
+
}
|
|
84
|
+
const gitLog = await executeCommand('git', ['log', '--oneline', '-5'], repoRoot);
|
|
85
|
+
if (gitLog.success) {
|
|
86
|
+
context['recent_commits'] = gitLog.stdout;
|
|
87
|
+
}
|
|
88
|
+
const gitBranch = await executeCommand('git', ['branch', '--show-current'], repoRoot);
|
|
89
|
+
if (gitBranch.success) {
|
|
90
|
+
context['current_branch'] = gitBranch.stdout.trim();
|
|
91
|
+
}
|
|
92
|
+
// Get npm info
|
|
93
|
+
const npmList = await executeCommand('npm', ['list', '--depth=0', '--json'], repoRoot);
|
|
94
|
+
if (npmList.success) {
|
|
95
|
+
try {
|
|
96
|
+
const deps = JSON.parse(npmList.stdout);
|
|
97
|
+
context['dependencies'] = Object.keys(deps.dependencies || {}).join(', ');
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Ignore parse errors
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Check for TypeScript
|
|
104
|
+
const tscVersion = await executeCommand('npx', ['tsc', '--version'], repoRoot);
|
|
105
|
+
if (tscVersion.success) {
|
|
106
|
+
context['typescript_version'] = tscVersion.stdout.trim();
|
|
107
|
+
}
|
|
108
|
+
return context;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Run type checking and gather errors
|
|
112
|
+
*/
|
|
113
|
+
export async function runTypeCheck(repoRoot) {
|
|
114
|
+
const result = await executeCommand('npx', ['tsc', '--noEmit', '--pretty', 'false'], repoRoot, {
|
|
115
|
+
timeout: 60000
|
|
116
|
+
});
|
|
117
|
+
if (result.success) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
// Parse TypeScript errors
|
|
121
|
+
const errors = [];
|
|
122
|
+
const lines = result.stdout.split('\n');
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (line.includes('error TS')) {
|
|
125
|
+
errors.push(line.trim());
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return errors.slice(0, 20); // Limit to 20 errors
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Run ESLint if available
|
|
132
|
+
*/
|
|
133
|
+
export async function runLint(repoRoot) {
|
|
134
|
+
const result = await executeCommand('npx', ['eslint', '.', '--format', 'compact', '--max-warnings', '50'], repoRoot, {
|
|
135
|
+
timeout: 60000
|
|
136
|
+
});
|
|
137
|
+
if (result.success) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
const issues = [];
|
|
141
|
+
const lines = result.stdout.split('\n');
|
|
142
|
+
for (const line of lines) {
|
|
143
|
+
if (line.includes('Warning') || line.includes('Error')) {
|
|
144
|
+
issues.push(line.trim());
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return issues.slice(0, 20);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework Detector - Auto-detect project type
|
|
3
|
+
*/
|
|
4
|
+
export type Framework = 'nextjs' | 'react' | 'vite' | 'angular' | 'vue' | 'svelte' | 'django' | 'flask' | 'express' | 'nestjs' | 'unknown';
|
|
5
|
+
export interface FrameworkInfo {
|
|
6
|
+
name: Framework;
|
|
7
|
+
displayName: string;
|
|
8
|
+
scanPatterns: string[];
|
|
9
|
+
ignorePatterns: string[];
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detect the framework used in a project
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectFramework(repoRoot: string): Promise<FrameworkInfo>;
|
|
16
|
+
/**
|
|
17
|
+
* Get framework-specific analysis hints
|
|
18
|
+
*/
|
|
19
|
+
export declare function getFrameworkHints(framework: Framework): string;
|
|
20
|
+
//# sourceMappingURL=framework-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-detector.d.ts","sourceRoot":"","sources":["../../src/core/framework-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,MAAM,SAAS,GACf,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,KAAK,GACL,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,CAAC;AAEhB,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACvB;AAuED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAkE9E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAgB9D"}
|