lamps-code-review 0.1.0 → 0.2.2
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/dist/core/analyzer/ai/context.d.ts +29 -0
- package/dist/core/analyzer/ai/context.d.ts.map +1 -0
- package/dist/core/analyzer/ai/context.js +413 -0
- package/dist/core/analyzer/ai/context.js.map +1 -0
- package/dist/core/analyzer/ai/index.d.ts +24 -6
- package/dist/core/analyzer/ai/index.d.ts.map +1 -1
- package/dist/core/analyzer/ai/index.js +191 -97
- package/dist/core/analyzer/ai/index.js.map +1 -1
- package/dist/core/analyzer/ai/passes.d.ts +14 -0
- package/dist/core/analyzer/ai/passes.d.ts.map +1 -0
- package/dist/core/analyzer/ai/passes.js +202 -0
- package/dist/core/analyzer/ai/passes.js.map +1 -0
- package/dist/core/analyzer/ai/slices.d.ts +40 -0
- package/dist/core/analyzer/ai/slices.d.ts.map +1 -0
- package/dist/core/analyzer/ai/slices.js +263 -0
- package/dist/core/analyzer/ai/slices.js.map +1 -0
- package/dist/core/analyzer/dependency/index.d.ts +64 -0
- package/dist/core/analyzer/dependency/index.d.ts.map +1 -0
- package/dist/core/analyzer/dependency/index.js +423 -0
- package/dist/core/analyzer/dependency/index.js.map +1 -0
- package/dist/core/analyzer/index.d.ts +1 -0
- package/dist/core/analyzer/index.d.ts.map +1 -1
- package/dist/core/analyzer/index.js +17 -8
- package/dist/core/analyzer/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +78 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +62 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,55 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* AI Analyzer module
|
|
4
|
-
*
|
|
4
|
+
* Multi-pass AI-powered code review using OpenRouter
|
|
5
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
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
7
|
exports.OpenRouterError = exports.AIAnalyzer = void 0;
|
|
41
8
|
exports.createAIAnalyzer = createAIAnalyzer;
|
|
42
|
-
const fs = __importStar(require("node:fs"));
|
|
43
9
|
const types_js_1 = require("../types.js");
|
|
44
10
|
const openrouter_js_1 = require("./openrouter.js");
|
|
45
|
-
const prompts_js_1 = require("./prompts.js");
|
|
46
11
|
const index_js_1 = require("../../config/index.js");
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const
|
|
12
|
+
const context_js_1 = require("./context.js");
|
|
13
|
+
const passes_js_1 = require("./passes.js");
|
|
14
|
+
const prompts_js_1 = require("./prompts.js");
|
|
15
|
+
const logger_js_1 = require("../../../utils/logger.js");
|
|
51
16
|
/**
|
|
52
|
-
* AI-powered code analyzer using OpenRouter
|
|
17
|
+
* Multi-pass AI-powered code analyzer using OpenRouter
|
|
53
18
|
*/
|
|
54
19
|
class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
55
20
|
constructor(config) {
|
|
@@ -57,12 +22,16 @@ class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
|
57
22
|
this.config = config;
|
|
58
23
|
this.name = 'ai';
|
|
59
24
|
this.phase = 'ai';
|
|
60
|
-
this.description = 'AI-powered code review using OpenRouter';
|
|
25
|
+
this.description = 'Multi-pass AI-powered code review using OpenRouter';
|
|
26
|
+
/** Store static analysis findings from previous phase */
|
|
27
|
+
this.staticFindings = [];
|
|
61
28
|
}
|
|
62
29
|
async analyze(context) {
|
|
63
30
|
const startTime = Date.now();
|
|
31
|
+
const logger = (0, logger_js_1.getGlobalLogger)();
|
|
64
32
|
// Check for API key
|
|
65
33
|
if (!(0, index_js_1.hasOpenRouterKey)()) {
|
|
34
|
+
logger.warn('OPENROUTER_API_KEY not set - skipping AI analysis');
|
|
66
35
|
return this.createResult([
|
|
67
36
|
{
|
|
68
37
|
ruleId: 'ai/no-api-key',
|
|
@@ -72,35 +41,69 @@ class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
|
72
41
|
},
|
|
73
42
|
], startTime, { skipped: true, reason: 'no-api-key' });
|
|
74
43
|
}
|
|
44
|
+
if (context.files.length === 0) {
|
|
45
|
+
logger.warn('No files to analyze');
|
|
46
|
+
return this.createResult([], startTime, {
|
|
47
|
+
skipped: true,
|
|
48
|
+
reason: 'no-files',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
75
51
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
52
|
+
logger.phase('AI Analysis (Multi-Pass)');
|
|
53
|
+
logger.step(`Model: ${this.config.model}`);
|
|
54
|
+
logger.step(`Files in codebase: ${context.files.length}`);
|
|
55
|
+
// Get dependency graph from static phase results (if available)
|
|
56
|
+
const graph = this.getDependencyGraph(context) || (0, context_js_1.createEmptyGraph)(context.files);
|
|
57
|
+
// Log graph stats
|
|
58
|
+
const graphStats = {
|
|
59
|
+
entryPoints: graph.entryPoints.length,
|
|
60
|
+
configFiles: graph.configFiles.length,
|
|
61
|
+
apiFiles: graph.apiFiles.length,
|
|
62
|
+
};
|
|
63
|
+
logger.detail(`Dependency graph: ${graphStats.entryPoints} entry points, ${graphStats.configFiles} configs, ${graphStats.apiFiles} API routes`);
|
|
64
|
+
// Collect static findings for context
|
|
65
|
+
this.staticFindings = this.getStaticFindings(context);
|
|
66
|
+
if (this.staticFindings.length > 0) {
|
|
67
|
+
logger.detail(`Static findings to incorporate: ${this.staticFindings.length}`);
|
|
83
68
|
}
|
|
84
|
-
//
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
69
|
+
// Run all passes
|
|
70
|
+
const allPassResults = [];
|
|
71
|
+
const allFindings = [];
|
|
72
|
+
// Pass 1: Architecture
|
|
73
|
+
logger.step('Pass 1/3: Architecture Review');
|
|
74
|
+
const archResult = await this.runPass('architecture', context, graph, allFindings);
|
|
75
|
+
allPassResults.push(archResult);
|
|
76
|
+
allFindings.push(...archResult.findings);
|
|
77
|
+
logger.success(`Architecture: ${archResult.findings.length} findings`);
|
|
78
|
+
// Pass 2: Deep Dive
|
|
79
|
+
logger.step('Pass 2/3: Deep Dive Review');
|
|
80
|
+
const deepResult = await this.runPass('deep-dive', context, graph, allFindings);
|
|
81
|
+
allPassResults.push(deepResult);
|
|
82
|
+
allFindings.push(...deepResult.findings);
|
|
83
|
+
logger.success(`Deep-dive: ${deepResult.findings.length} findings`);
|
|
84
|
+
// Pass 3: Security
|
|
85
|
+
logger.step('Pass 3/3: Security Review');
|
|
86
|
+
const secResult = await this.runPass('security', context, graph, allFindings);
|
|
87
|
+
allPassResults.push(secResult);
|
|
88
|
+
allFindings.push(...secResult.findings);
|
|
89
|
+
logger.success(`Security: ${secResult.findings.length} findings`);
|
|
90
|
+
// Deduplicate findings
|
|
91
|
+
const dedupedFindings = this.deduplicateFindings(allFindings);
|
|
92
|
+
if (allFindings.length !== dedupedFindings.length) {
|
|
93
|
+
logger.detail(`Deduplicated: ${allFindings.length} → ${dedupedFindings.length} findings`);
|
|
94
|
+
}
|
|
95
|
+
// Combine summaries
|
|
96
|
+
const combinedSummary = allPassResults
|
|
97
|
+
.map((r) => `**${r.pass}**: ${r.summary}`)
|
|
98
|
+
.join('\n\n');
|
|
99
|
+
const duration = Date.now() - startTime;
|
|
100
|
+
logger.success(`AI analysis complete in ${(duration / 1000).toFixed(1)}s`);
|
|
101
|
+
return this.createResult(dedupedFindings, startTime, {
|
|
101
102
|
model: this.config.model,
|
|
102
|
-
summary:
|
|
103
|
-
|
|
103
|
+
summary: combinedSummary,
|
|
104
|
+
passResults: allPassResults,
|
|
105
|
+
filesAnalyzed: context.files.length,
|
|
106
|
+
multiPass: true,
|
|
104
107
|
});
|
|
105
108
|
}
|
|
106
109
|
catch (error) {
|
|
@@ -110,6 +113,7 @@ class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
|
110
113
|
: error instanceof Error
|
|
111
114
|
? error.message
|
|
112
115
|
: 'Unknown error during AI analysis';
|
|
116
|
+
logger.warn(`AI analysis failed: ${errorMessage}`);
|
|
113
117
|
return this.createResult([
|
|
114
118
|
{
|
|
115
119
|
ruleId: 'ai/error',
|
|
@@ -121,41 +125,131 @@ class AIAnalyzer extends types_js_1.BaseAnalyzer {
|
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
/**
|
|
124
|
-
*
|
|
125
|
-
* Respects size limits and filters appropriately
|
|
128
|
+
* Run a single AI pass
|
|
126
129
|
*/
|
|
127
|
-
async
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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) {
|
|
130
|
+
async runPass(passType, context, graph, previousFindings) {
|
|
131
|
+
const logger = (0, logger_js_1.getGlobalLogger)();
|
|
132
|
+
// Build context for this pass
|
|
133
|
+
let reviewContext;
|
|
134
|
+
switch (passType) {
|
|
135
|
+
case 'architecture':
|
|
136
|
+
reviewContext = await (0, context_js_1.buildArchitectureContext)(context, graph);
|
|
139
137
|
break;
|
|
138
|
+
case 'deep-dive':
|
|
139
|
+
reviewContext = await (0, context_js_1.buildDeepDiveContext)(context, graph, this.staticFindings, previousFindings.filter((f) => f.ruleId.startsWith('ai/arch')));
|
|
140
|
+
break;
|
|
141
|
+
case 'security':
|
|
142
|
+
reviewContext = await (0, context_js_1.buildSecurityContext)(context, graph);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
// Log context details
|
|
146
|
+
logger.detail(`Sending ${reviewContext.files.length} files (~${Math.round(reviewContext.metadata.totalTokenEstimate / 1000)}K tokens)`);
|
|
147
|
+
if (reviewContext.files.length > 0 && reviewContext.files.length <= 5) {
|
|
148
|
+
for (const file of reviewContext.files) {
|
|
149
|
+
logger.detail(` ${file.path} (${file.reason})`);
|
|
140
150
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
}
|
|
152
|
+
else if (reviewContext.files.length > 5) {
|
|
153
|
+
for (const file of reviewContext.files.slice(0, 3)) {
|
|
154
|
+
logger.detail(` ${file.path} (${file.reason})`);
|
|
155
|
+
}
|
|
156
|
+
logger.detail(` ... and ${reviewContext.files.length - 3} more files`);
|
|
157
|
+
}
|
|
158
|
+
// Skip if no files to review
|
|
159
|
+
if (reviewContext.files.length === 0) {
|
|
160
|
+
logger.warn(`No relevant files for ${passType} review`);
|
|
161
|
+
return {
|
|
162
|
+
pass: passType,
|
|
163
|
+
findings: [],
|
|
164
|
+
summary: `No relevant files for ${passType} review`,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// Build prompts
|
|
168
|
+
const systemPrompt = passes_js_1.PASS_SYSTEM_PROMPTS[passType];
|
|
169
|
+
const userPrompt = (0, passes_js_1.buildPassPrompt)(reviewContext, this.config.customPrompt);
|
|
170
|
+
// Call AI
|
|
171
|
+
logger.detail('Calling AI...');
|
|
172
|
+
const callStart = Date.now();
|
|
173
|
+
const apiKey = (0, index_js_1.getOpenRouterKey)();
|
|
174
|
+
const response = await (0, openrouter_js_1.chat)(systemPrompt, userPrompt, this.config, apiKey);
|
|
175
|
+
const callDuration = Date.now() - callStart;
|
|
176
|
+
logger.detail(`AI responded in ${(callDuration / 1000).toFixed(1)}s`);
|
|
177
|
+
// Parse response
|
|
178
|
+
const parsed = (0, prompts_js_1.parseAIResponse)(response);
|
|
179
|
+
// Convert to findings with proper severity types
|
|
180
|
+
const findings = parsed.findings.map((f) => ({
|
|
181
|
+
ruleId: f.ruleId,
|
|
182
|
+
severity: f.severity,
|
|
183
|
+
file: f.file,
|
|
184
|
+
line: f.line,
|
|
185
|
+
message: f.message,
|
|
186
|
+
suggestion: f.suggestion,
|
|
187
|
+
}));
|
|
188
|
+
return {
|
|
189
|
+
pass: passType,
|
|
190
|
+
findings,
|
|
191
|
+
summary: parsed.summary,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get dependency graph from context or previous results
|
|
196
|
+
*/
|
|
197
|
+
getDependencyGraph(context) {
|
|
198
|
+
// The dependency graph is stored in the context by the pipeline
|
|
199
|
+
// after the static phase runs
|
|
200
|
+
const metadata = context._previousResults;
|
|
201
|
+
if (metadata) {
|
|
202
|
+
return (0, context_js_1.getDependencyGraphFromResults)(metadata);
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get static findings from previous phase
|
|
208
|
+
*/
|
|
209
|
+
getStaticFindings(context) {
|
|
210
|
+
const metadata = context._previousResults;
|
|
211
|
+
if (!metadata)
|
|
212
|
+
return [];
|
|
213
|
+
const staticResult = metadata.find((r) => r.analyzerName === 'static');
|
|
214
|
+
return staticResult?.findings || [];
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Deduplicate findings from multiple passes
|
|
218
|
+
* Keeps the highest severity if duplicates found
|
|
219
|
+
*/
|
|
220
|
+
deduplicateFindings(findings) {
|
|
221
|
+
const seen = new Map();
|
|
222
|
+
const severityOrder = {
|
|
223
|
+
error: 4,
|
|
224
|
+
warning: 3,
|
|
225
|
+
info: 2,
|
|
226
|
+
hint: 1,
|
|
227
|
+
};
|
|
228
|
+
for (const finding of findings) {
|
|
229
|
+
// Create a key based on file, line, and message similarity
|
|
230
|
+
const key = `${finding.file}:${finding.line || 0}:${this.normalizeMessage(finding.message)}`;
|
|
231
|
+
const existing = seen.get(key);
|
|
232
|
+
if (!existing) {
|
|
233
|
+
seen.set(key, finding);
|
|
152
234
|
}
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
|
|
235
|
+
else {
|
|
236
|
+
// Keep the one with higher severity
|
|
237
|
+
if (severityOrder[finding.severity] > severityOrder[existing.severity]) {
|
|
238
|
+
seen.set(key, finding);
|
|
239
|
+
}
|
|
156
240
|
}
|
|
157
241
|
}
|
|
158
|
-
return
|
|
242
|
+
return Array.from(seen.values());
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Normalize message for deduplication comparison
|
|
246
|
+
*/
|
|
247
|
+
normalizeMessage(message) {
|
|
248
|
+
return message
|
|
249
|
+
.toLowerCase()
|
|
250
|
+
.replace(/\s+/g, ' ')
|
|
251
|
+
.replace(/[^a-z0-9 ]/g, '')
|
|
252
|
+
.slice(0, 50);
|
|
159
253
|
}
|
|
160
254
|
}
|
|
161
255
|
exports.AIAnalyzer = AIAnalyzer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/index.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pass-Specific Prompts
|
|
3
|
+
* Tailored prompts for each AI review pass
|
|
4
|
+
*/
|
|
5
|
+
import type { ReviewContext, AIPassType } from '../../../types/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* System prompts for each pass type
|
|
8
|
+
*/
|
|
9
|
+
export declare const PASS_SYSTEM_PROMPTS: Record<AIPassType, string>;
|
|
10
|
+
/**
|
|
11
|
+
* Build the user prompt for a specific pass
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildPassPrompt(context: ReviewContext, customPrompt?: string): string;
|
|
14
|
+
//# sourceMappingURL=passes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passes.d.ts","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/passes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAe,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEtF;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CA6C1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAgCrF"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pass-Specific Prompts
|
|
4
|
+
* Tailored prompts for each AI review pass
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PASS_SYSTEM_PROMPTS = void 0;
|
|
8
|
+
exports.buildPassPrompt = buildPassPrompt;
|
|
9
|
+
/**
|
|
10
|
+
* System prompts for each pass type
|
|
11
|
+
*/
|
|
12
|
+
exports.PASS_SYSTEM_PROMPTS = {
|
|
13
|
+
architecture: `You are an expert software architect reviewing a codebase's structure and organization.
|
|
14
|
+
|
|
15
|
+
Focus on:
|
|
16
|
+
1. **Project Structure** - Is the organization logical? Are there missing directories or patterns?
|
|
17
|
+
2. **Dependencies** - Are there concerning dependencies? Version issues? Missing dependencies?
|
|
18
|
+
3. **Entry Points** - Are they well-organized? Clear application flow?
|
|
19
|
+
4. **Configuration** - Are configs complete? Missing environment handling?
|
|
20
|
+
5. **Architecture Patterns** - Consistent patterns? Clear separation of concerns?
|
|
21
|
+
6. **Scalability Concerns** - Any obvious bottlenecks or limitations?
|
|
22
|
+
|
|
23
|
+
Be concise and focus on high-level issues. Don't comment on specific code implementation details - those will be covered in the deep dive pass.
|
|
24
|
+
|
|
25
|
+
Respond with valid JSON only. No markdown, no explanations outside the JSON.`,
|
|
26
|
+
'deep-dive': `You are an expert senior software engineer conducting a thorough code review.
|
|
27
|
+
|
|
28
|
+
Focus on:
|
|
29
|
+
1. **Bugs and Logic Errors** - Off-by-one, null handling, race conditions, incorrect conditions
|
|
30
|
+
2. **Performance Issues** - N+1 queries, memory leaks, unnecessary re-renders, inefficient algorithms
|
|
31
|
+
3. **Code Quality** - Complexity, readability, maintainability, code smells
|
|
32
|
+
4. **Best Practices** - Framework-specific patterns, TypeScript/Python idioms, error handling
|
|
33
|
+
5. **Edge Cases** - Unhandled scenarios, missing validation, boundary conditions
|
|
34
|
+
|
|
35
|
+
Be specific and actionable. Include line numbers when possible. Don't nitpick style issues unless they significantly affect readability.
|
|
36
|
+
|
|
37
|
+
Respond with valid JSON only. No markdown, no explanations outside the JSON.`,
|
|
38
|
+
security: `You are a security expert conducting a security-focused code review.
|
|
39
|
+
|
|
40
|
+
Focus on OWASP Top 10 and common vulnerabilities:
|
|
41
|
+
1. **Injection** - SQL, NoSQL, OS command, LDAP injection
|
|
42
|
+
2. **Broken Authentication** - Weak passwords, session issues, credential exposure
|
|
43
|
+
3. **Sensitive Data Exposure** - Unencrypted data, exposed secrets, logging sensitive info
|
|
44
|
+
4. **XXE** - XML external entity attacks
|
|
45
|
+
5. **Broken Access Control** - Missing authorization checks, IDOR, privilege escalation
|
|
46
|
+
6. **Security Misconfiguration** - Default configs, verbose errors, unnecessary features
|
|
47
|
+
7. **XSS** - Stored, reflected, DOM-based cross-site scripting
|
|
48
|
+
8. **Insecure Deserialization** - Untrusted data deserialization
|
|
49
|
+
9. **Using Components with Known Vulnerabilities** - Outdated dependencies
|
|
50
|
+
10. **Insufficient Logging** - Missing audit trails, security event logging
|
|
51
|
+
|
|
52
|
+
Be thorough but avoid false positives. If you're uncertain, mark severity as 'info' rather than 'error'.
|
|
53
|
+
|
|
54
|
+
Respond with valid JSON only. No markdown, no explanations outside the JSON.`,
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Build the user prompt for a specific pass
|
|
58
|
+
*/
|
|
59
|
+
function buildPassPrompt(context, customPrompt) {
|
|
60
|
+
let prompt = '';
|
|
61
|
+
// Add custom prompt if provided
|
|
62
|
+
if (customPrompt) {
|
|
63
|
+
prompt += `## Additional Instructions\n${customPrompt}\n\n`;
|
|
64
|
+
}
|
|
65
|
+
prompt += `## Review Context\n`;
|
|
66
|
+
prompt += `- **Pass Type**: ${context.pass}\n`;
|
|
67
|
+
prompt += `- **Total Files in Codebase**: ${context.metadata.totalFiles}\n`;
|
|
68
|
+
prompt += `- **Files in This Review**: ${context.files.length}\n`;
|
|
69
|
+
prompt += `- **Frameworks**: ${context.metadata.frameworks.join(', ') || 'None detected'}\n`;
|
|
70
|
+
prompt += `- **Focus Areas**: ${context.metadata.focusAreas.join(', ')}\n\n`;
|
|
71
|
+
// Add file tree for architecture pass
|
|
72
|
+
if (context.pass === 'architecture') {
|
|
73
|
+
prompt += `## File Tree\n\`\`\`\n`;
|
|
74
|
+
prompt += context.files.map((f) => f.path).join('\n');
|
|
75
|
+
prompt += `\n\`\`\`\n\n`;
|
|
76
|
+
}
|
|
77
|
+
prompt += `## Files to Review\n\n`;
|
|
78
|
+
// Add file contents
|
|
79
|
+
for (const file of context.files) {
|
|
80
|
+
prompt += formatContextFile(file);
|
|
81
|
+
}
|
|
82
|
+
prompt += getResponseFormat(context.pass);
|
|
83
|
+
return prompt;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Format a context file for the prompt
|
|
87
|
+
*/
|
|
88
|
+
function formatContextFile(file) {
|
|
89
|
+
const extension = file.path.split('.').pop() || 'txt';
|
|
90
|
+
const langId = getLanguageId(extension);
|
|
91
|
+
let content = '';
|
|
92
|
+
content += `### ${file.path}\n`;
|
|
93
|
+
content += `*Reason: ${file.reason}*\n\n`;
|
|
94
|
+
if (file.content) {
|
|
95
|
+
content += `\`\`\`${langId}\n${file.content}\n\`\`\`\n\n`;
|
|
96
|
+
}
|
|
97
|
+
else if (file.slices && file.slices.length > 0) {
|
|
98
|
+
for (const slice of file.slices) {
|
|
99
|
+
content += `**Lines ${slice.startLine}-${slice.endLine}** (${slice.reason}):\n`;
|
|
100
|
+
content += `\`\`\`${langId}\n${slice.content}\n\`\`\`\n\n`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return content;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get response format instructions
|
|
107
|
+
*/
|
|
108
|
+
function getResponseFormat(pass) {
|
|
109
|
+
const categories = getCategoriesForPass(pass);
|
|
110
|
+
return `## Response Format
|
|
111
|
+
|
|
112
|
+
Respond with a JSON object containing your findings:
|
|
113
|
+
|
|
114
|
+
\`\`\`json
|
|
115
|
+
{
|
|
116
|
+
"findings": [
|
|
117
|
+
{
|
|
118
|
+
"ruleId": "ai/<category>-<specific-issue>",
|
|
119
|
+
"severity": "error" | "warning" | "info" | "hint",
|
|
120
|
+
"file": "relative/path/to/file.ts",
|
|
121
|
+
"line": 42,
|
|
122
|
+
"message": "Clear description of the issue",
|
|
123
|
+
"suggestion": "How to fix it (optional)"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"summary": "Brief overall assessment for this ${pass} review"
|
|
127
|
+
}
|
|
128
|
+
\`\`\`
|
|
129
|
+
|
|
130
|
+
Rule ID categories for this pass:
|
|
131
|
+
${categories.map((c) => `- \`ai/${c.id}\` - ${c.description}`).join('\n')}
|
|
132
|
+
|
|
133
|
+
Severity levels:
|
|
134
|
+
- \`error\`: Critical issues that must be fixed
|
|
135
|
+
- \`warning\`: Important issues that should be addressed
|
|
136
|
+
- \`info\`: Suggestions for improvement
|
|
137
|
+
- \`hint\`: Minor observations
|
|
138
|
+
|
|
139
|
+
If there are no issues, return: {"findings": [], "summary": "No significant issues found."}`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get rule categories for a pass type
|
|
143
|
+
*/
|
|
144
|
+
function getCategoriesForPass(pass) {
|
|
145
|
+
switch (pass) {
|
|
146
|
+
case 'architecture':
|
|
147
|
+
return [
|
|
148
|
+
{ id: 'arch-structure', description: 'Project structure issues' },
|
|
149
|
+
{ id: 'arch-dependency', description: 'Dependency concerns' },
|
|
150
|
+
{ id: 'arch-pattern', description: 'Pattern/consistency issues' },
|
|
151
|
+
{ id: 'arch-config', description: 'Configuration problems' },
|
|
152
|
+
{ id: 'arch-scale', description: 'Scalability concerns' },
|
|
153
|
+
];
|
|
154
|
+
case 'deep-dive':
|
|
155
|
+
return [
|
|
156
|
+
{ id: 'bug-logic', description: 'Logic errors' },
|
|
157
|
+
{ id: 'bug-null', description: 'Null/undefined handling' },
|
|
158
|
+
{ id: 'bug-async', description: 'Async/race conditions' },
|
|
159
|
+
{ id: 'perf-query', description: 'Query performance' },
|
|
160
|
+
{ id: 'perf-memory', description: 'Memory issues' },
|
|
161
|
+
{ id: 'perf-render', description: 'Rendering performance' },
|
|
162
|
+
{ id: 'quality-complexity', description: 'Code complexity' },
|
|
163
|
+
{ id: 'quality-readability', description: 'Readability issues' },
|
|
164
|
+
{ id: 'practice-framework', description: 'Framework best practices' },
|
|
165
|
+
{ id: 'practice-error', description: 'Error handling' },
|
|
166
|
+
];
|
|
167
|
+
case 'security':
|
|
168
|
+
return [
|
|
169
|
+
{ id: 'security-injection', description: 'Injection vulnerabilities' },
|
|
170
|
+
{ id: 'security-auth', description: 'Authentication issues' },
|
|
171
|
+
{ id: 'security-exposure', description: 'Data exposure' },
|
|
172
|
+
{ id: 'security-xss', description: 'Cross-site scripting' },
|
|
173
|
+
{ id: 'security-access', description: 'Access control issues' },
|
|
174
|
+
{ id: 'security-config', description: 'Security misconfiguration' },
|
|
175
|
+
{ id: 'security-crypto', description: 'Cryptography issues' },
|
|
176
|
+
{ id: 'security-secrets', description: 'Exposed secrets' },
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Map file extension to language identifier
|
|
182
|
+
*/
|
|
183
|
+
function getLanguageId(extension) {
|
|
184
|
+
const map = {
|
|
185
|
+
ts: 'typescript',
|
|
186
|
+
tsx: 'tsx',
|
|
187
|
+
js: 'javascript',
|
|
188
|
+
jsx: 'jsx',
|
|
189
|
+
py: 'python',
|
|
190
|
+
json: 'json',
|
|
191
|
+
yaml: 'yaml',
|
|
192
|
+
yml: 'yaml',
|
|
193
|
+
md: 'markdown',
|
|
194
|
+
css: 'css',
|
|
195
|
+
scss: 'scss',
|
|
196
|
+
html: 'html',
|
|
197
|
+
vue: 'vue',
|
|
198
|
+
svelte: 'svelte',
|
|
199
|
+
};
|
|
200
|
+
return map[extension] || extension || 'text';
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=passes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passes.js","sourceRoot":"","sources":["../../../../src/core/analyzer/ai/passes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Slicing Utilities
|
|
3
|
+
* Extract relevant portions of large files for AI analysis
|
|
4
|
+
*/
|
|
5
|
+
import type { CodeSlice, Finding } from '../../../types/index.js';
|
|
6
|
+
export interface SliceOptions {
|
|
7
|
+
/** Findings from static analysis to slice around */
|
|
8
|
+
staticFindings?: Finding[];
|
|
9
|
+
/** Include all exports */
|
|
10
|
+
includeExports?: boolean;
|
|
11
|
+
/** Include security-sensitive patterns */
|
|
12
|
+
includeSecurity?: boolean;
|
|
13
|
+
/** Include class/function definitions */
|
|
14
|
+
includeDefinitions?: boolean;
|
|
15
|
+
/** Maximum total slice content size */
|
|
16
|
+
maxTotalSize?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract relevant code slices from file content
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractSlices(content: string, filePath: string, options?: SliceOptions): CodeSlice[];
|
|
22
|
+
/**
|
|
23
|
+
* Merge overlapping slices into contiguous blocks
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeOverlappingSlices(slices: CodeSlice[]): CodeSlice[];
|
|
26
|
+
/**
|
|
27
|
+
* Reconstruct slice content from original file
|
|
28
|
+
* Used after merging to get correct content
|
|
29
|
+
*/
|
|
30
|
+
export declare function reconstructSliceContent(content: string, slices: CodeSlice[]): CodeSlice[];
|
|
31
|
+
/**
|
|
32
|
+
* Estimate token count for content (rough approximation)
|
|
33
|
+
* Uses ~4 characters per token heuristic
|
|
34
|
+
*/
|
|
35
|
+
export declare function estimateTokens(content: string): number;
|
|
36
|
+
/**
|
|
37
|
+
* Get a summary of what a file exports (for architecture pass)
|
|
38
|
+
*/
|
|
39
|
+
export declare function getExportSummary(content: string, extension: string): string[];
|
|
40
|
+
//# sourceMappingURL=slices.d.ts.map
|