lamps-code-review 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/LICENSE +21 -0
- package/README.md +357 -0
- package/bin/lamps-review.js +7 -0
- package/dist/cli/commands/review.d.ts +9 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +149 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +41 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/analyzer/ai/index.d.ts +28 -0
- package/dist/core/analyzer/ai/index.d.ts.map +1 -0
- package/dist/core/analyzer/ai/index.js +171 -0
- package/dist/core/analyzer/ai/index.js.map +1 -0
- package/dist/core/analyzer/ai/openrouter.d.ts +26 -0
- package/dist/core/analyzer/ai/openrouter.d.ts.map +1 -0
- package/dist/core/analyzer/ai/openrouter.js +77 -0
- package/dist/core/analyzer/ai/openrouter.js.map +1 -0
- package/dist/core/analyzer/ai/prompts.d.ts +32 -0
- package/dist/core/analyzer/ai/prompts.d.ts.map +1 -0
- package/dist/core/analyzer/ai/prompts.js +171 -0
- package/dist/core/analyzer/ai/prompts.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +67 -0
- package/dist/core/analyzer/index.d.ts.map +1 -0
- package/dist/core/analyzer/index.js +224 -0
- package/dist/core/analyzer/index.js.map +1 -0
- package/dist/core/analyzer/static/index.d.ts +21 -0
- package/dist/core/analyzer/static/index.d.ts.map +1 -0
- package/dist/core/analyzer/static/index.js +69 -0
- package/dist/core/analyzer/static/index.js.map +1 -0
- package/dist/core/analyzer/types.d.ts +70 -0
- package/dist/core/analyzer/types.d.ts.map +1 -0
- package/dist/core/analyzer/types.js +27 -0
- package/dist/core/analyzer/types.js.map +1 -0
- package/dist/core/config/index.d.ts +28 -0
- package/dist/core/config/index.d.ts.map +1 -0
- package/dist/core/config/index.js +109 -0
- package/dist/core/config/index.js.map +1 -0
- package/dist/core/detector/index.d.ts +10 -0
- package/dist/core/detector/index.d.ts.map +1 -0
- package/dist/core/detector/index.js +306 -0
- package/dist/core/detector/index.js.map +1 -0
- package/dist/core/reporter/formats/json.d.ts +13 -0
- package/dist/core/reporter/formats/json.d.ts.map +1 -0
- package/dist/core/reporter/formats/json.js +23 -0
- package/dist/core/reporter/formats/json.js.map +1 -0
- package/dist/core/reporter/index.d.ts +15 -0
- package/dist/core/reporter/index.d.ts.map +1 -0
- package/dist/core/reporter/index.js +183 -0
- package/dist/core/reporter/index.js.map +1 -0
- package/dist/core/scanner/ignore-rules.d.ts +13 -0
- package/dist/core/scanner/ignore-rules.d.ts.map +1 -0
- package/dist/core/scanner/ignore-rules.js +162 -0
- package/dist/core/scanner/ignore-rules.js.map +1 -0
- package/dist/core/scanner/index.d.ts +16 -0
- package/dist/core/scanner/index.d.ts.map +1 -0
- package/dist/core/scanner/index.js +191 -0
- package/dist/core/scanner/index.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +188 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +13 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +54 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +159 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI Analyzer module
|
|
4
|
+
* Uses OpenRouter to perform AI-powered code review
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.OpenRouterError = exports.AIAnalyzer = void 0;
|
|
41
|
+
exports.createAIAnalyzer = createAIAnalyzer;
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const types_js_1 = require("../types.js");
|
|
44
|
+
const openrouter_js_1 = require("./openrouter.js");
|
|
45
|
+
const prompts_js_1 = require("./prompts.js");
|
|
46
|
+
const index_js_1 = require("../../config/index.js");
|
|
47
|
+
/** Maximum file size to include in AI analysis (100KB) */
|
|
48
|
+
const MAX_FILE_SIZE_FOR_AI = 100 * 1024;
|
|
49
|
+
/** Maximum total content size to send to AI (500KB) */
|
|
50
|
+
const MAX_TOTAL_CONTENT_SIZE = 500 * 1024;
|
|
51
|
+
/**
|
|
52
|
+
* AI-powered code analyzer using OpenRouter
|
|
53
|
+
*/
|
|
54
|
+
class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
55
|
+
constructor(config) {
|
|
56
|
+
super();
|
|
57
|
+
this.config = config;
|
|
58
|
+
this.name = 'ai';
|
|
59
|
+
this.phase = 'ai';
|
|
60
|
+
this.description = 'AI-powered code review using OpenRouter';
|
|
61
|
+
}
|
|
62
|
+
async analyze(context) {
|
|
63
|
+
const startTime = Date.now();
|
|
64
|
+
// Check for API key
|
|
65
|
+
if (!(0, index_js_1.hasOpenRouterKey)()) {
|
|
66
|
+
return this.createResult([
|
|
67
|
+
{
|
|
68
|
+
ruleId: 'ai/no-api-key',
|
|
69
|
+
severity: 'info',
|
|
70
|
+
file: '',
|
|
71
|
+
message: 'AI analysis skipped: OPENROUTER_API_KEY environment variable not set',
|
|
72
|
+
},
|
|
73
|
+
], startTime, { skipped: true, reason: 'no-api-key' });
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
// Load file contents
|
|
77
|
+
const filesWithContent = await this.loadFileContents(context.files);
|
|
78
|
+
if (filesWithContent.length === 0) {
|
|
79
|
+
return this.createResult([], startTime, {
|
|
80
|
+
skipped: true,
|
|
81
|
+
reason: 'no-files',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Build the prompt
|
|
85
|
+
const userPrompt = (0, prompts_js_1.buildUserPrompt)(filesWithContent, context.frameworks, this.config.customPrompt);
|
|
86
|
+
// Call AI
|
|
87
|
+
const apiKey = (0, index_js_1.getOpenRouterKey)();
|
|
88
|
+
const response = await (0, openrouter_js_1.chat)(prompts_js_1.DEFAULT_SYSTEM_PROMPT, userPrompt, this.config, apiKey);
|
|
89
|
+
// Parse response
|
|
90
|
+
const parsed = (0, prompts_js_1.parseAIResponse)(response);
|
|
91
|
+
// Convert to findings
|
|
92
|
+
const findings = parsed.findings.map((f) => ({
|
|
93
|
+
ruleId: f.ruleId,
|
|
94
|
+
severity: f.severity,
|
|
95
|
+
file: f.file,
|
|
96
|
+
line: f.line,
|
|
97
|
+
message: f.message,
|
|
98
|
+
suggestion: f.suggestion,
|
|
99
|
+
}));
|
|
100
|
+
return this.createResult(findings, startTime, {
|
|
101
|
+
model: this.config.model,
|
|
102
|
+
summary: parsed.summary,
|
|
103
|
+
filesAnalyzed: filesWithContent.length,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// Handle errors gracefully
|
|
108
|
+
const errorMessage = error instanceof openrouter_js_1.OpenRouterError
|
|
109
|
+
? error.message
|
|
110
|
+
: error instanceof Error
|
|
111
|
+
? error.message
|
|
112
|
+
: 'Unknown error during AI analysis';
|
|
113
|
+
return this.createResult([
|
|
114
|
+
{
|
|
115
|
+
ruleId: 'ai/error',
|
|
116
|
+
severity: 'warning',
|
|
117
|
+
file: '',
|
|
118
|
+
message: `AI analysis failed: ${errorMessage}`,
|
|
119
|
+
},
|
|
120
|
+
], startTime, { error: errorMessage });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Load file contents for AI analysis
|
|
125
|
+
* Respects size limits and filters appropriately
|
|
126
|
+
*/
|
|
127
|
+
async loadFileContents(files) {
|
|
128
|
+
const result = [];
|
|
129
|
+
let totalSize = 0;
|
|
130
|
+
// Sort by size (smaller files first) to maximize coverage
|
|
131
|
+
const sortedFiles = [...files].sort((a, b) => a.size - b.size);
|
|
132
|
+
for (const file of sortedFiles) {
|
|
133
|
+
// Skip files that are too large
|
|
134
|
+
if (file.size > MAX_FILE_SIZE_FOR_AI) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Check total size limit
|
|
138
|
+
if (totalSize + file.size > MAX_TOTAL_CONTENT_SIZE) {
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
// Load content if not already loaded
|
|
143
|
+
let content = file.content;
|
|
144
|
+
if (content === undefined) {
|
|
145
|
+
content = await fs.promises.readFile(file.path, 'utf-8');
|
|
146
|
+
}
|
|
147
|
+
result.push({
|
|
148
|
+
...file,
|
|
149
|
+
content,
|
|
150
|
+
});
|
|
151
|
+
totalSize += file.size;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Skip files that can't be read
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.AIAnalyzer = AIAnalyzer;
|
|
162
|
+
/**
|
|
163
|
+
* Create an AI analyzer with the given configuration
|
|
164
|
+
*/
|
|
165
|
+
function createAIAnalyzer(config) {
|
|
166
|
+
return new AIAnalyzer(config);
|
|
167
|
+
}
|
|
168
|
+
// Re-export for convenience
|
|
169
|
+
var openrouter_js_2 = require("./openrouter.js");
|
|
170
|
+
Object.defineProperty(exports, "OpenRouterError", { enumerable: true, get: function () { return openrouter_js_2.OpenRouterError; } });
|
|
171
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter API client
|
|
3
|
+
* Handles communication with OpenRouter for AI model access
|
|
4
|
+
*/
|
|
5
|
+
import type { AIConfig } from '../../../types/index.js';
|
|
6
|
+
/** OpenRouter chat message */
|
|
7
|
+
interface ChatMessage {
|
|
8
|
+
role: 'system' | 'user' | 'assistant';
|
|
9
|
+
content: string;
|
|
10
|
+
}
|
|
11
|
+
/** Error from OpenRouter API */
|
|
12
|
+
export declare class OpenRouterError extends Error {
|
|
13
|
+
readonly code?: string | undefined;
|
|
14
|
+
readonly status?: number | undefined;
|
|
15
|
+
constructor(message: string, code?: string | undefined, status?: number | undefined);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Call OpenRouter API with a prompt
|
|
19
|
+
*/
|
|
20
|
+
export declare function callOpenRouter(messages: ChatMessage[], config: AIConfig, apiKey: string): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Simple helper to create a chat completion
|
|
23
|
+
*/
|
|
24
|
+
export declare function chat(systemPrompt: string, userPrompt: string, config: AIConfig, apiKey: string): Promise<string>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=openrouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/openrouter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAKxD,8BAA8B;AAC9B,UAAU,WAAW;IACnB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAuBD,gCAAgC;AAChC,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,IAAI,CAAC,EAAE,MAAM;aACb,MAAM,CAAC,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,WAAW,EAAE,EACvB,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAED;;GAEG;AACH,wBAAsB,IAAI,CACxB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAOjB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenRouter API client
|
|
4
|
+
* Handles communication with OpenRouter for AI model access
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.OpenRouterError = void 0;
|
|
8
|
+
exports.callOpenRouter = callOpenRouter;
|
|
9
|
+
exports.chat = chat;
|
|
10
|
+
/** OpenRouter API endpoint */
|
|
11
|
+
const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
|
12
|
+
/** Error from OpenRouter API */
|
|
13
|
+
class OpenRouterError extends Error {
|
|
14
|
+
constructor(message, code, status) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.status = status;
|
|
18
|
+
this.name = 'OpenRouterError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.OpenRouterError = OpenRouterError;
|
|
22
|
+
/**
|
|
23
|
+
* Call OpenRouter API with a prompt
|
|
24
|
+
*/
|
|
25
|
+
async function callOpenRouter(messages, config, apiKey) {
|
|
26
|
+
const response = await fetch(OPENROUTER_API_URL, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
headers: {
|
|
29
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
'HTTP-Referer': 'https://github.com/lamps-code-review',
|
|
32
|
+
'X-Title': 'LampsCodeReview',
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
model: config.model,
|
|
36
|
+
messages,
|
|
37
|
+
max_tokens: config.maxTokens,
|
|
38
|
+
temperature: config.temperature,
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const errorText = await response.text();
|
|
43
|
+
let errorMessage = `OpenRouter API error: ${response.status}`;
|
|
44
|
+
try {
|
|
45
|
+
const errorJson = JSON.parse(errorText);
|
|
46
|
+
if (errorJson.error?.message) {
|
|
47
|
+
errorMessage = errorJson.error.message;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Use raw error text if not JSON
|
|
52
|
+
if (errorText) {
|
|
53
|
+
errorMessage = errorText;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
throw new OpenRouterError(errorMessage, undefined, response.status);
|
|
57
|
+
}
|
|
58
|
+
const data = (await response.json());
|
|
59
|
+
if (data.error) {
|
|
60
|
+
throw new OpenRouterError(data.error.message, data.error.code);
|
|
61
|
+
}
|
|
62
|
+
if (!data.choices || data.choices.length === 0) {
|
|
63
|
+
throw new OpenRouterError('No response from AI model');
|
|
64
|
+
}
|
|
65
|
+
return data.choices[0].message.content;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Simple helper to create a chat completion
|
|
69
|
+
*/
|
|
70
|
+
async function chat(systemPrompt, userPrompt, config, apiKey) {
|
|
71
|
+
const messages = [
|
|
72
|
+
{ role: 'system', content: systemPrompt },
|
|
73
|
+
{ role: 'user', content: userPrompt },
|
|
74
|
+
];
|
|
75
|
+
return callOpenRouter(messages, config, apiKey);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=openrouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/openrouter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAiDH,wCAmDC;AAKD,oBAYC;AAjHD,8BAA8B;AAC9B,MAAM,kBAAkB,GAAG,+CAA+C,CAAC;AA6B3E,gCAAgC;AAChC,MAAa,eAAgB,SAAQ,KAAK;IACxC,YACE,OAAe,EACC,IAAa,EACb,MAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAS;QACb,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AATD,0CASC;AAED;;GAEG;AACI,KAAK,UAAU,cAAc,CAClC,QAAuB,EACvB,MAAgB,EAChB,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,kBAAkB,EAAE;QAC/C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,eAAe,EAAE,UAAU,MAAM,EAAE;YACnC,cAAc,EAAE,kBAAkB;YAClC,cAAc,EAAE,sCAAsC;YACtD,SAAS,EAAE,iBAAiB;SAC7B;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,SAAS;YAC5B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,YAAY,GAAG,yBAAyB,QAAQ,CAAC,MAAM,EAAE,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACxC,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;gBAC7B,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;YACzC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;YACjC,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,GAAG,SAAS,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,MAAM,IAAI,eAAe,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;IAE3D,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,eAAe,CAAC,2BAA2B,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;AACzC,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,IAAI,CACxB,YAAoB,EACpB,UAAkB,EAClB,MAAgB,EAChB,MAAc;IAEd,MAAM,QAAQ,GAAkB;QAC9B,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;QACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;KACtC,CAAC;IAEF,OAAO,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI review prompts
|
|
3
|
+
* Contains the system and user prompts for code review
|
|
4
|
+
*/
|
|
5
|
+
import type { DetectionResult, FileInfo } from '../../../types/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Default system prompt for code review
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_SYSTEM_PROMPT = "You are an expert senior software engineer conducting a thorough code review. Your goal is to identify issues that matter and provide actionable feedback.\n\nFocus on:\n1. **Security vulnerabilities** - SQL injection, XSS, command injection, auth issues, secrets exposure\n2. **Bugs and logic errors** - Off-by-one errors, null/undefined handling, race conditions\n3. **Performance issues** - N+1 queries, memory leaks, unnecessary re-renders, inefficient algorithms\n4. **Code quality** - Complexity, readability, maintainability, code smells\n5. **Best practices** - Framework-specific patterns, TypeScript/Python idioms, error handling\n6. **Architecture** - Coupling, cohesion, separation of concerns, scalability\n\nBe specific and actionable. Don't nitpick style issues unless they affect readability significantly.\n\nYou MUST respond with valid JSON only. No markdown, no explanations outside the JSON.";
|
|
10
|
+
/**
|
|
11
|
+
* Build the user prompt with codebase content
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildUserPrompt(files: FileInfo[], frameworks: DetectionResult, customPrompt?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Parse AI response into structured findings
|
|
16
|
+
*/
|
|
17
|
+
export interface AIReviewResponse {
|
|
18
|
+
findings: Array<{
|
|
19
|
+
ruleId: string;
|
|
20
|
+
severity: string;
|
|
21
|
+
file: string;
|
|
22
|
+
line?: number;
|
|
23
|
+
message: string;
|
|
24
|
+
suggestion?: string;
|
|
25
|
+
}>;
|
|
26
|
+
summary: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse the AI response, handling various formats
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseAIResponse(response: string): AIReviewResponse;
|
|
32
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,qBAAqB,m5BAYoD,CAAC;AAEvF;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,eAAe,EAC3B,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAoER;AAyBD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA0ClE"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI review prompts
|
|
4
|
+
* Contains the system and user prompts for code review
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_SYSTEM_PROMPT = void 0;
|
|
8
|
+
exports.buildUserPrompt = buildUserPrompt;
|
|
9
|
+
exports.parseAIResponse = parseAIResponse;
|
|
10
|
+
/**
|
|
11
|
+
* Default system prompt for code review
|
|
12
|
+
*/
|
|
13
|
+
exports.DEFAULT_SYSTEM_PROMPT = `You are an expert senior software engineer conducting a thorough code review. Your goal is to identify issues that matter and provide actionable feedback.
|
|
14
|
+
|
|
15
|
+
Focus on:
|
|
16
|
+
1. **Security vulnerabilities** - SQL injection, XSS, command injection, auth issues, secrets exposure
|
|
17
|
+
2. **Bugs and logic errors** - Off-by-one errors, null/undefined handling, race conditions
|
|
18
|
+
3. **Performance issues** - N+1 queries, memory leaks, unnecessary re-renders, inefficient algorithms
|
|
19
|
+
4. **Code quality** - Complexity, readability, maintainability, code smells
|
|
20
|
+
5. **Best practices** - Framework-specific patterns, TypeScript/Python idioms, error handling
|
|
21
|
+
6. **Architecture** - Coupling, cohesion, separation of concerns, scalability
|
|
22
|
+
|
|
23
|
+
Be specific and actionable. Don't nitpick style issues unless they affect readability significantly.
|
|
24
|
+
|
|
25
|
+
You MUST respond with valid JSON only. No markdown, no explanations outside the JSON.`;
|
|
26
|
+
/**
|
|
27
|
+
* Build the user prompt with codebase content
|
|
28
|
+
*/
|
|
29
|
+
function buildUserPrompt(files, frameworks, customPrompt) {
|
|
30
|
+
const frameworkList = frameworks.frameworks
|
|
31
|
+
.map((f) => `${f.framework} (${Math.round(f.confidence * 100)}%)`)
|
|
32
|
+
.join(', ');
|
|
33
|
+
const languageList = frameworks.languages.join(', ');
|
|
34
|
+
let prompt = '';
|
|
35
|
+
// Add custom prompt if provided
|
|
36
|
+
if (customPrompt) {
|
|
37
|
+
prompt += `## Additional Review Instructions\n${customPrompt}\n\n`;
|
|
38
|
+
}
|
|
39
|
+
prompt += `## Codebase Information
|
|
40
|
+
- **Primary Framework**: ${frameworks.primary || 'None detected'}
|
|
41
|
+
- **All Frameworks**: ${frameworkList || 'None detected'}
|
|
42
|
+
- **Languages**: ${languageList || 'Unknown'}
|
|
43
|
+
- **Files to Review**: ${files.length}
|
|
44
|
+
|
|
45
|
+
## Files
|
|
46
|
+
|
|
47
|
+
`;
|
|
48
|
+
// Add file contents
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
if (file.content) {
|
|
51
|
+
prompt += `### ${file.relativePath}\n\`\`\`${getLanguageId(file.extension)}\n${file.content}\n\`\`\`\n\n`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
prompt += `## Response Format
|
|
55
|
+
|
|
56
|
+
Respond with a JSON object containing your findings:
|
|
57
|
+
|
|
58
|
+
\`\`\`json
|
|
59
|
+
{
|
|
60
|
+
"findings": [
|
|
61
|
+
{
|
|
62
|
+
"ruleId": "ai/<category>-<specific-issue>",
|
|
63
|
+
"severity": "error" | "warning" | "info" | "hint",
|
|
64
|
+
"file": "relative/path/to/file.ts",
|
|
65
|
+
"line": 42,
|
|
66
|
+
"message": "Clear description of the issue",
|
|
67
|
+
"suggestion": "How to fix it (optional)"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"summary": "Brief overall assessment of the codebase"
|
|
71
|
+
}
|
|
72
|
+
\`\`\`
|
|
73
|
+
|
|
74
|
+
Rule ID categories:
|
|
75
|
+
- \`ai/security-*\` for security issues
|
|
76
|
+
- \`ai/bug-*\` for bugs and logic errors
|
|
77
|
+
- \`ai/perf-*\` for performance issues
|
|
78
|
+
- \`ai/quality-*\` for code quality issues
|
|
79
|
+
- \`ai/practice-*\` for best practice violations
|
|
80
|
+
- \`ai/arch-*\` for architectural concerns
|
|
81
|
+
|
|
82
|
+
Severity levels:
|
|
83
|
+
- \`error\`: Critical issues that must be fixed (security vulnerabilities, definite bugs)
|
|
84
|
+
- \`warning\`: Important issues that should be addressed (potential bugs, performance problems)
|
|
85
|
+
- \`info\`: Suggestions for improvement (code quality, best practices)
|
|
86
|
+
- \`hint\`: Minor observations (style, optional improvements)
|
|
87
|
+
|
|
88
|
+
If there are no issues, return: {"findings": [], "summary": "No significant issues found."}`;
|
|
89
|
+
return prompt;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Map file extension to language identifier for syntax highlighting
|
|
93
|
+
*/
|
|
94
|
+
function getLanguageId(extension) {
|
|
95
|
+
const map = {
|
|
96
|
+
'.ts': 'typescript',
|
|
97
|
+
'.tsx': 'tsx',
|
|
98
|
+
'.js': 'javascript',
|
|
99
|
+
'.jsx': 'jsx',
|
|
100
|
+
'.py': 'python',
|
|
101
|
+
'.json': 'json',
|
|
102
|
+
'.yaml': 'yaml',
|
|
103
|
+
'.yml': 'yaml',
|
|
104
|
+
'.md': 'markdown',
|
|
105
|
+
'.css': 'css',
|
|
106
|
+
'.scss': 'scss',
|
|
107
|
+
'.html': 'html',
|
|
108
|
+
'.vue': 'vue',
|
|
109
|
+
'.svelte': 'svelte',
|
|
110
|
+
};
|
|
111
|
+
return map[extension] || extension.slice(1) || 'text';
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Parse the AI response, handling various formats
|
|
115
|
+
*/
|
|
116
|
+
function parseAIResponse(response) {
|
|
117
|
+
// Try to extract JSON from the response
|
|
118
|
+
let jsonStr = response.trim();
|
|
119
|
+
// Remove markdown code blocks if present
|
|
120
|
+
const jsonMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
121
|
+
if (jsonMatch) {
|
|
122
|
+
jsonStr = jsonMatch[1].trim();
|
|
123
|
+
}
|
|
124
|
+
// Try to find JSON object in the response
|
|
125
|
+
const objectMatch = jsonStr.match(/\{[\s\S]*\}/);
|
|
126
|
+
if (objectMatch) {
|
|
127
|
+
jsonStr = objectMatch[0];
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const parsed = JSON.parse(jsonStr);
|
|
131
|
+
// Validate structure
|
|
132
|
+
if (!Array.isArray(parsed.findings)) {
|
|
133
|
+
return { findings: [], summary: 'Failed to parse AI response' };
|
|
134
|
+
}
|
|
135
|
+
// Normalize findings
|
|
136
|
+
parsed.findings = parsed.findings.map((f) => ({
|
|
137
|
+
ruleId: f.ruleId || 'ai/unknown',
|
|
138
|
+
severity: normalizeSeverity(f.severity),
|
|
139
|
+
file: f.file || 'unknown',
|
|
140
|
+
line: typeof f.line === 'number' ? f.line : undefined,
|
|
141
|
+
message: f.message || 'No description provided',
|
|
142
|
+
suggestion: f.suggestion,
|
|
143
|
+
}));
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Return empty findings if parsing fails
|
|
148
|
+
return {
|
|
149
|
+
findings: [],
|
|
150
|
+
summary: 'Failed to parse AI response: ' + response.slice(0, 200),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Normalize severity to valid values
|
|
156
|
+
*/
|
|
157
|
+
function normalizeSeverity(severity) {
|
|
158
|
+
const normalized = severity?.toLowerCase();
|
|
159
|
+
if (['error', 'warning', 'info', 'hint'].includes(normalized)) {
|
|
160
|
+
return normalized;
|
|
161
|
+
}
|
|
162
|
+
// Map common alternatives
|
|
163
|
+
if (normalized === 'critical' || normalized === 'high')
|
|
164
|
+
return 'error';
|
|
165
|
+
if (normalized === 'medium')
|
|
166
|
+
return 'warning';
|
|
167
|
+
if (normalized === 'low')
|
|
168
|
+
return 'info';
|
|
169
|
+
return 'info';
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyzer pipeline module
|
|
3
|
+
* Orchestrates running multiple analyzers in phases
|
|
4
|
+
*/
|
|
5
|
+
import type { Analyzer, AnalysisContext, AnalyzerPhase, AIConfig } from '../../types/index.js';
|
|
6
|
+
import type { PipelineOptions, PipelineResult, PipelineEventListener } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Analyzer pipeline - orchestrates running analyzers in phases
|
|
9
|
+
*/
|
|
10
|
+
export declare class AnalyzerPipeline {
|
|
11
|
+
private analyzers;
|
|
12
|
+
private listeners;
|
|
13
|
+
private options;
|
|
14
|
+
constructor(options?: PipelineOptions, aiConfig?: AIConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Register an analyzer
|
|
17
|
+
*/
|
|
18
|
+
registerAnalyzer(analyzer: Analyzer): void;
|
|
19
|
+
/**
|
|
20
|
+
* Unregister an analyzer by name
|
|
21
|
+
*/
|
|
22
|
+
unregisterAnalyzer(name: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get all registered analyzers
|
|
25
|
+
*/
|
|
26
|
+
getAnalyzers(): Analyzer[];
|
|
27
|
+
/**
|
|
28
|
+
* Get analyzers for a specific phase
|
|
29
|
+
*/
|
|
30
|
+
getAnalyzersForPhase(phase: AnalyzerPhase): Analyzer[];
|
|
31
|
+
/**
|
|
32
|
+
* Add an event listener
|
|
33
|
+
*/
|
|
34
|
+
addEventListener(listener: PipelineEventListener): void;
|
|
35
|
+
/**
|
|
36
|
+
* Remove an event listener
|
|
37
|
+
*/
|
|
38
|
+
removeEventListener(listener: PipelineEventListener): void;
|
|
39
|
+
/**
|
|
40
|
+
* Emit an event to all listeners
|
|
41
|
+
*/
|
|
42
|
+
private emit;
|
|
43
|
+
/**
|
|
44
|
+
* Run the analysis pipeline
|
|
45
|
+
*/
|
|
46
|
+
run(context: AnalysisContext): Promise<PipelineResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Run a single analyzer with timeout
|
|
49
|
+
*/
|
|
50
|
+
private runAnalyzer;
|
|
51
|
+
/**
|
|
52
|
+
* Create a timeout promise
|
|
53
|
+
*/
|
|
54
|
+
private timeout;
|
|
55
|
+
/**
|
|
56
|
+
* Get enabled analyzers based on config
|
|
57
|
+
*/
|
|
58
|
+
private getEnabledAnalyzers;
|
|
59
|
+
/**
|
|
60
|
+
* Create the final pipeline result
|
|
61
|
+
*/
|
|
62
|
+
private createResult;
|
|
63
|
+
}
|
|
64
|
+
export * from './types.js';
|
|
65
|
+
export { createStaticAnalyzer } from './static/index.js';
|
|
66
|
+
export { createAIAnalyzer } from './ai/index.js';
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAkB,aAAa,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC/G,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,OAAO,CAA4B;gBAE/B,OAAO,GAAE,eAAoB,EAAE,QAAQ,CAAC,EAAE,QAAQ;IAiB9D;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAO1C;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIzC;;OAEG;IACH,YAAY,IAAI,QAAQ,EAAE;IAI1B;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,QAAQ,EAAE;IAItD;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAIvD;;OAEG;IACH,mBAAmB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAO1D;;OAEG;IACH,OAAO,CAAC,IAAI;IAUZ;;OAEG;IACG,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IA4E5D;;OAEG;YACW,WAAW;IAgBzB;;OAEG;IACH,OAAO,CAAC,OAAO;IAQf;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,YAAY;CAYrB;AAGD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|