@triedotdev/mcp 1.0.11 → 1.0.13
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 +60 -3
- package/dist/agent-smith-LBQ5PNAK.js +10 -0
- package/dist/agent-smith-LBQ5PNAK.js.map +1 -0
- package/dist/chunk-4OGYWKMD.js +953 -0
- package/dist/chunk-4OGYWKMD.js.map +1 -0
- package/dist/{chunk-PSSXQEO5.js → chunk-NJXF26W7.js} +113 -435
- package/dist/chunk-NJXF26W7.js.map +1 -0
- package/dist/cli/yolo-daemon.js +2 -1
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/index.js +65 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-PSSXQEO5.js.map +0 -1
|
@@ -3,6 +3,11 @@ import {
|
|
|
3
3
|
getVibeCodeTrie,
|
|
4
4
|
scanForVibeCodeIssues
|
|
5
5
|
} from "./chunk-3CS6Z2SL.js";
|
|
6
|
+
import {
|
|
7
|
+
AgentSmithAgent,
|
|
8
|
+
BaseAgent,
|
|
9
|
+
ProgressReporter
|
|
10
|
+
} from "./chunk-4OGYWKMD.js";
|
|
6
11
|
import {
|
|
7
12
|
getVulnerabilityStats,
|
|
8
13
|
getVulnerabilityTrie,
|
|
@@ -12,407 +17,8 @@ import {
|
|
|
12
17
|
Trie
|
|
13
18
|
} from "./chunk-6NLHFIYA.js";
|
|
14
19
|
|
|
15
|
-
// src/utils/progress.ts
|
|
16
|
-
var ProgressReporter = class {
|
|
17
|
-
currentPhase = "init";
|
|
18
|
-
startTime = Date.now();
|
|
19
|
-
phaseStartTime = Date.now();
|
|
20
|
-
verbose;
|
|
21
|
-
constructor(options = {}) {
|
|
22
|
-
this.verbose = options.verbose ?? true;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Report a status update
|
|
26
|
-
*/
|
|
27
|
-
report(message, detail) {
|
|
28
|
-
if (!this.verbose) return;
|
|
29
|
-
const prefix = this.getPhaseIcon(this.currentPhase);
|
|
30
|
-
const fullMessage = detail ? `${message}: ${detail}` : message;
|
|
31
|
-
console.error(`${prefix} ${fullMessage}`);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Start a new phase
|
|
35
|
-
*/
|
|
36
|
-
startPhase(phase, message) {
|
|
37
|
-
this.currentPhase = phase;
|
|
38
|
-
this.phaseStartTime = Date.now();
|
|
39
|
-
this.report(message);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Update within current phase
|
|
43
|
-
*/
|
|
44
|
-
update(message, detail) {
|
|
45
|
-
this.report(message, detail);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Report progress on a file
|
|
49
|
-
*/
|
|
50
|
-
file(action, filePath) {
|
|
51
|
-
const fileName = filePath.split("/").pop() || filePath;
|
|
52
|
-
this.report(action, fileName);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Report an AI analysis step
|
|
56
|
-
*/
|
|
57
|
-
ai(action, context) {
|
|
58
|
-
const prefix = "\u{1F9E0}";
|
|
59
|
-
const message = context ? `${action}: ${context}` : action;
|
|
60
|
-
console.error(`${prefix} ${message}`);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Report a finding
|
|
64
|
-
*/
|
|
65
|
-
finding(severity, message) {
|
|
66
|
-
const icons = {
|
|
67
|
-
critical: "\u{1F534}",
|
|
68
|
-
serious: "\u{1F7E0}",
|
|
69
|
-
moderate: "\u{1F7E1}",
|
|
70
|
-
low: "\u{1F535}"
|
|
71
|
-
};
|
|
72
|
-
console.error(` ${icons[severity]} ${message}`);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Complete current phase
|
|
76
|
-
*/
|
|
77
|
-
completePhase(summary) {
|
|
78
|
-
const elapsed = Date.now() - this.phaseStartTime;
|
|
79
|
-
this.report(`\u2713 ${summary}`, `(${elapsed}ms)`);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Complete the entire operation
|
|
83
|
-
*/
|
|
84
|
-
complete(summary) {
|
|
85
|
-
const totalElapsed = Date.now() - this.startTime;
|
|
86
|
-
console.error("");
|
|
87
|
-
console.error(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`);
|
|
88
|
-
console.error(`\u2705 ${summary}`);
|
|
89
|
-
console.error(` Total time: ${(totalElapsed / 1e3).toFixed(2)}s`);
|
|
90
|
-
console.error(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`);
|
|
91
|
-
console.error("");
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Report an error
|
|
95
|
-
*/
|
|
96
|
-
error(message, detail) {
|
|
97
|
-
const fullMessage = detail ? `${message}: ${detail}` : message;
|
|
98
|
-
console.error(`\u274C ${fullMessage}`);
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Report a warning
|
|
102
|
-
*/
|
|
103
|
-
warn(message, detail) {
|
|
104
|
-
const fullMessage = detail ? `${message}: ${detail}` : message;
|
|
105
|
-
console.error(`\u26A0\uFE0F ${fullMessage}`);
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Get icon for current phase
|
|
109
|
-
*/
|
|
110
|
-
getPhaseIcon(phase) {
|
|
111
|
-
const icons = {
|
|
112
|
-
"init": "\u{1F53A}",
|
|
113
|
-
"discovery": "\u{1F50D}",
|
|
114
|
-
"reading": "\u{1F4C2}",
|
|
115
|
-
"analyzing": "\u{1F52C}",
|
|
116
|
-
"ai-review": "\u{1F9E0}",
|
|
117
|
-
"prioritizing": "\u{1F3AF}",
|
|
118
|
-
"complete": "\u2705"
|
|
119
|
-
};
|
|
120
|
-
return icons[phase] || "\u2022";
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Create a sub-reporter for a specific agent
|
|
124
|
-
*/
|
|
125
|
-
forAgent(agentName) {
|
|
126
|
-
return new AgentProgressReporter(agentName, this.verbose);
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
var AgentProgressReporter = class {
|
|
130
|
-
agentName;
|
|
131
|
-
verbose;
|
|
132
|
-
issueCount = 0;
|
|
133
|
-
constructor(agentName, verbose = true) {
|
|
134
|
-
this.agentName = agentName;
|
|
135
|
-
this.verbose = verbose;
|
|
136
|
-
}
|
|
137
|
-
start() {
|
|
138
|
-
if (!this.verbose) return;
|
|
139
|
-
console.error(`
|
|
140
|
-
\u{1F916} ${this.agentName.toUpperCase()} Agent starting...`);
|
|
141
|
-
}
|
|
142
|
-
analyzing(file) {
|
|
143
|
-
if (!this.verbose) return;
|
|
144
|
-
const fileName = file.split("/").pop() || file;
|
|
145
|
-
console.error(` \u{1F4C4} Analyzing ${fileName}...`);
|
|
146
|
-
}
|
|
147
|
-
aiReview(context) {
|
|
148
|
-
if (!this.verbose) return;
|
|
149
|
-
console.error(` \u{1F9E0} AI reviewing: ${context}`);
|
|
150
|
-
}
|
|
151
|
-
found(severity, issue) {
|
|
152
|
-
this.issueCount++;
|
|
153
|
-
if (!this.verbose) return;
|
|
154
|
-
const icon = severity === "critical" ? "\u{1F534}" : severity === "serious" ? "\u{1F7E0}" : severity === "moderate" ? "\u{1F7E1}" : "\u{1F535}";
|
|
155
|
-
console.error(` ${icon} Found: ${issue}`);
|
|
156
|
-
}
|
|
157
|
-
complete(summary) {
|
|
158
|
-
if (!this.verbose) return;
|
|
159
|
-
const msg = summary || `Found ${this.issueCount} issues`;
|
|
160
|
-
console.error(` \u2713 ${this.agentName}: ${msg}`);
|
|
161
|
-
}
|
|
162
|
-
getIssueCount() {
|
|
163
|
-
return this.issueCount;
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
// src/agents/base-agent.ts
|
|
168
|
-
import { basename, relative } from "path";
|
|
169
|
-
var BaseAgent = class {
|
|
170
|
-
// Progress reporter for real-time feedback
|
|
171
|
-
progress = null;
|
|
172
|
-
// Default priority - subclasses can override
|
|
173
|
-
get priority() {
|
|
174
|
-
return {
|
|
175
|
-
name: this.name,
|
|
176
|
-
tier: 2,
|
|
177
|
-
estimatedTimeMs: 100,
|
|
178
|
-
dependencies: []
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
// Default implementation - can be overridden for smarter confidence
|
|
182
|
-
getActivationConfidence(context) {
|
|
183
|
-
return this.shouldActivate(context) ? 0.7 : 0;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Main scan entry point - now with progress reporting
|
|
187
|
-
*/
|
|
188
|
-
async scan(files, context) {
|
|
189
|
-
const startTime = Date.now();
|
|
190
|
-
this.progress = new AgentProgressReporter(this.name);
|
|
191
|
-
this.progress.start();
|
|
192
|
-
try {
|
|
193
|
-
const issues = await this.analyzeWithAI(files, context);
|
|
194
|
-
this.progress.complete(`${issues.length} issues found`);
|
|
195
|
-
return {
|
|
196
|
-
agent: this.name,
|
|
197
|
-
issues,
|
|
198
|
-
executionTime: Date.now() - startTime,
|
|
199
|
-
success: true,
|
|
200
|
-
metadata: {
|
|
201
|
-
filesAnalyzed: files.length,
|
|
202
|
-
linesAnalyzed: 0
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
} catch (error) {
|
|
206
|
-
this.progress.complete("Failed");
|
|
207
|
-
return {
|
|
208
|
-
agent: this.name,
|
|
209
|
-
issues: [],
|
|
210
|
-
executionTime: Date.now() - startTime,
|
|
211
|
-
success: false,
|
|
212
|
-
error: error instanceof Error ? error.message : String(error)
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* AI-First Analysis - The new way
|
|
218
|
-
*
|
|
219
|
-
* 1. Quick filter to identify relevant files
|
|
220
|
-
* 2. Generate rich AI prompts for relevant files
|
|
221
|
-
* 3. Return prompts for the AI to process
|
|
222
|
-
*
|
|
223
|
-
* Subclasses should override this for AI-powered analysis
|
|
224
|
-
*/
|
|
225
|
-
async analyzeWithAI(files, context) {
|
|
226
|
-
const issues = [];
|
|
227
|
-
const aiRequests = [];
|
|
228
|
-
this.progress?.aiReview("Identifying relevant files...");
|
|
229
|
-
for (const file of files) {
|
|
230
|
-
try {
|
|
231
|
-
const content = await this.readFile(file);
|
|
232
|
-
const relevance = this.checkFileRelevance(file, content);
|
|
233
|
-
if (relevance.isRelevant) {
|
|
234
|
-
this.progress?.analyzing(file);
|
|
235
|
-
const request = await this.buildAIAnalysisRequest(file, content, relevance, context);
|
|
236
|
-
if (request) {
|
|
237
|
-
aiRequests.push(request);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
} catch (error) {
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
if (aiRequests.length > 0) {
|
|
244
|
-
this.progress?.aiReview(`Preparing analysis for ${aiRequests.length} files...`);
|
|
245
|
-
for (const request of aiRequests) {
|
|
246
|
-
const aiIssues = await this.processAIRequest(request);
|
|
247
|
-
issues.push(...aiIssues);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
const legacyIssues = await this.analyzeFiles(files, context);
|
|
251
|
-
const allIssues = this.mergeIssues(issues, legacyIssues);
|
|
252
|
-
return allIssues;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Check if a file is relevant for this agent's analysis
|
|
256
|
-
* Subclasses should override for domain-specific checks
|
|
257
|
-
*/
|
|
258
|
-
checkFileRelevance(_file, _content) {
|
|
259
|
-
return {
|
|
260
|
-
isRelevant: true,
|
|
261
|
-
reason: "Default analysis",
|
|
262
|
-
priority: "low",
|
|
263
|
-
indicators: []
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Build an AI analysis request for a file
|
|
268
|
-
* Subclasses should override to provide domain-specific prompts
|
|
269
|
-
*/
|
|
270
|
-
async buildAIAnalysisRequest(file, content, relevance, _context) {
|
|
271
|
-
const fileName = basename(file);
|
|
272
|
-
const relPath = this.getRelativePath(file);
|
|
273
|
-
return {
|
|
274
|
-
file,
|
|
275
|
-
code: content,
|
|
276
|
-
analysisType: this.name,
|
|
277
|
-
systemPrompt: this.getSystemPrompt(),
|
|
278
|
-
userPrompt: this.buildUserPrompt(relPath, content, relevance),
|
|
279
|
-
context: {
|
|
280
|
-
fileName,
|
|
281
|
-
relevance: relevance.reason,
|
|
282
|
-
indicators: relevance.indicators
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Get the system prompt for AI analysis
|
|
288
|
-
* Subclasses should override with domain-specific prompts
|
|
289
|
-
*/
|
|
290
|
-
getSystemPrompt() {
|
|
291
|
-
return `You are an expert code analyzer specializing in ${this.name} analysis.
|
|
292
|
-
Analyze the provided code and identify issues with specific line numbers and actionable fixes.
|
|
293
|
-
Be precise and avoid false positives. Only report issues you are confident about.`;
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Build the user prompt for AI analysis
|
|
297
|
-
*/
|
|
298
|
-
buildUserPrompt(filePath, content, relevance) {
|
|
299
|
-
return `Analyze this code for ${this.name} issues:
|
|
300
|
-
|
|
301
|
-
**File:** ${filePath}
|
|
302
|
-
**Relevance indicators:** ${relevance.indicators.join(", ") || "general analysis"}
|
|
303
|
-
|
|
304
|
-
\`\`\`
|
|
305
|
-
${content}
|
|
306
|
-
\`\`\`
|
|
307
|
-
|
|
308
|
-
For each issue found, provide:
|
|
309
|
-
1. Severity (critical/serious/moderate/low)
|
|
310
|
-
2. Line number
|
|
311
|
-
3. Clear description of the issue
|
|
312
|
-
4. Specific fix recommendation`;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Process an AI analysis request and return issues
|
|
316
|
-
* This generates the prompt output for Claude to process
|
|
317
|
-
*/
|
|
318
|
-
async processAIRequest(request) {
|
|
319
|
-
const fileName = basename(request.file);
|
|
320
|
-
this.progress?.aiReview(`${fileName} queued for AI analysis`);
|
|
321
|
-
return [{
|
|
322
|
-
id: this.generateIssueId(),
|
|
323
|
-
severity: "moderate",
|
|
324
|
-
issue: `AI Analysis Required: ${request.analysisType}`,
|
|
325
|
-
fix: "Review the AI analysis output below",
|
|
326
|
-
file: request.file,
|
|
327
|
-
confidence: 1,
|
|
328
|
-
autoFixable: false,
|
|
329
|
-
agent: this.name,
|
|
330
|
-
effort: "medium",
|
|
331
|
-
// Store the AI prompt for inclusion in output
|
|
332
|
-
aiPrompt: {
|
|
333
|
-
system: request.systemPrompt,
|
|
334
|
-
user: request.userPrompt
|
|
335
|
-
}
|
|
336
|
-
}];
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Merge and deduplicate issues from AI and legacy analysis
|
|
340
|
-
*/
|
|
341
|
-
mergeIssues(aiIssues, legacyIssues) {
|
|
342
|
-
const merged = [...aiIssues];
|
|
343
|
-
for (const legacy of legacyIssues) {
|
|
344
|
-
const hasOverlap = aiIssues.some(
|
|
345
|
-
(ai) => ai.file === legacy.file && ai.line === legacy.line
|
|
346
|
-
);
|
|
347
|
-
if (!hasOverlap) {
|
|
348
|
-
merged.push(legacy);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
return merged;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Get relative path from cwd
|
|
355
|
-
*/
|
|
356
|
-
getRelativePath(file) {
|
|
357
|
-
try {
|
|
358
|
-
return relative(process.cwd(), file);
|
|
359
|
-
} catch {
|
|
360
|
-
return file;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
createIssue(id, severity, issue, fix, file, line, confidence = 0.9, regulation, autoFixable = true, options) {
|
|
364
|
-
const result = {
|
|
365
|
-
id,
|
|
366
|
-
severity,
|
|
367
|
-
issue,
|
|
368
|
-
fix,
|
|
369
|
-
file,
|
|
370
|
-
confidence,
|
|
371
|
-
autoFixable,
|
|
372
|
-
agent: this.name,
|
|
373
|
-
effort: options?.effort ?? this.estimateEffort(severity, autoFixable)
|
|
374
|
-
};
|
|
375
|
-
if (line !== void 0) result.line = line;
|
|
376
|
-
if (options?.endLine !== void 0) result.endLine = options.endLine;
|
|
377
|
-
if (options?.column !== void 0) result.column = options.column;
|
|
378
|
-
if (regulation !== void 0) result.regulation = regulation;
|
|
379
|
-
if (options?.category !== void 0) result.category = options.category;
|
|
380
|
-
if (options?.cwe !== void 0) result.cwe = options.cwe;
|
|
381
|
-
if (options?.owasp !== void 0) result.owasp = options.owasp;
|
|
382
|
-
return result;
|
|
383
|
-
}
|
|
384
|
-
estimateEffort(severity, autoFixable) {
|
|
385
|
-
if (autoFixable) return "trivial";
|
|
386
|
-
if (severity === "low") return "easy";
|
|
387
|
-
if (severity === "moderate") return "easy";
|
|
388
|
-
if (severity === "serious") return "medium";
|
|
389
|
-
return "hard";
|
|
390
|
-
}
|
|
391
|
-
async readFile(filePath) {
|
|
392
|
-
const { readFile: readFile9 } = await import("fs/promises");
|
|
393
|
-
return readFile9(filePath, "utf-8");
|
|
394
|
-
}
|
|
395
|
-
generateIssueId() {
|
|
396
|
-
return `${this.name}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
397
|
-
}
|
|
398
|
-
getLineContent(content, lineNumber) {
|
|
399
|
-
const lines = content.split("\n");
|
|
400
|
-
return lines[lineNumber - 1] || "";
|
|
401
|
-
}
|
|
402
|
-
getCodeSnippet(content, lineNumber, contextLines = 2) {
|
|
403
|
-
const lines = content.split("\n");
|
|
404
|
-
const start = Math.max(0, lineNumber - contextLines - 1);
|
|
405
|
-
const end = Math.min(lines.length, lineNumber + contextLines);
|
|
406
|
-
return lines.slice(start, end).map((line, idx) => {
|
|
407
|
-
const num = start + idx + 1;
|
|
408
|
-
const marker = num === lineNumber ? "\u2192" : " ";
|
|
409
|
-
return `${marker} ${num.toString().padStart(4)} | ${line}`;
|
|
410
|
-
}).join("\n");
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
|
|
414
20
|
// src/agents/security.ts
|
|
415
|
-
import { basename
|
|
21
|
+
import { basename } from "path";
|
|
416
22
|
var ALWAYS_SKIP_FILES = [
|
|
417
23
|
/vulnerability-signatures\.[jt]s$/,
|
|
418
24
|
/vibe-code-signatures\.[jt]s$/,
|
|
@@ -615,7 +221,7 @@ If no significant vulnerabilities are found, respond with:
|
|
|
615
221
|
*/
|
|
616
222
|
async processAIRequest(request) {
|
|
617
223
|
const issues = [];
|
|
618
|
-
const fileName =
|
|
224
|
+
const fileName = basename(request.file);
|
|
619
225
|
const content = request.code;
|
|
620
226
|
const lines = content.split("\n");
|
|
621
227
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -666,7 +272,7 @@ If no significant vulnerabilities are found, respond with:
|
|
|
666
272
|
};
|
|
667
273
|
|
|
668
274
|
// src/agents/privacy.ts
|
|
669
|
-
import { basename as
|
|
275
|
+
import { basename as basename2 } from "path";
|
|
670
276
|
var PRIVACY_INDICATORS = {
|
|
671
277
|
high: [
|
|
672
278
|
{ pattern: /email|phone|ssn|social.*security|passport|driver.*license/i, reason: "PII fields" },
|
|
@@ -852,7 +458,7 @@ If no privacy issues found, respond with:
|
|
|
852
458
|
*/
|
|
853
459
|
async processAIRequest(request) {
|
|
854
460
|
const issues = [];
|
|
855
|
-
const fileName =
|
|
461
|
+
const fileName = basename2(request.file);
|
|
856
462
|
const content = request.code;
|
|
857
463
|
const lines = content.split("\n");
|
|
858
464
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -1893,7 +1499,7 @@ var LegalAgent = class extends BaseAgent {
|
|
|
1893
1499
|
};
|
|
1894
1500
|
|
|
1895
1501
|
// src/agents/test.ts
|
|
1896
|
-
import { basename as
|
|
1502
|
+
import { basename as basename3, dirname } from "path";
|
|
1897
1503
|
import { existsSync } from "fs";
|
|
1898
1504
|
var TestAgent = class extends BaseAgent {
|
|
1899
1505
|
name = "test";
|
|
@@ -1920,7 +1526,7 @@ var TestAgent = class extends BaseAgent {
|
|
|
1920
1526
|
}
|
|
1921
1527
|
checkTestCoverage(file, content, _context) {
|
|
1922
1528
|
const issues = [];
|
|
1923
|
-
const fileName =
|
|
1529
|
+
const fileName = basename3(file);
|
|
1924
1530
|
const fileDir = dirname(file);
|
|
1925
1531
|
const testPatterns = [
|
|
1926
1532
|
file.replace(/\.(ts|js|tsx|jsx)$/, ".test.$1"),
|
|
@@ -2368,7 +1974,7 @@ var DevOpsAgent = class extends BaseAgent {
|
|
|
2368
1974
|
};
|
|
2369
1975
|
|
|
2370
1976
|
// src/agents/bug-finding.ts
|
|
2371
|
-
import { basename as
|
|
1977
|
+
import { basename as basename4 } from "path";
|
|
2372
1978
|
var BUG_INDICATORS = {
|
|
2373
1979
|
high: [
|
|
2374
1980
|
{ pattern: /async|await|promise/i, reason: "async code" },
|
|
@@ -2530,7 +2136,7 @@ If no significant bugs found, respond with:
|
|
|
2530
2136
|
*/
|
|
2531
2137
|
async processAIRequest(request) {
|
|
2532
2138
|
const issues = [];
|
|
2533
|
-
const fileName =
|
|
2139
|
+
const fileName = basename4(request.file);
|
|
2534
2140
|
const content = request.code;
|
|
2535
2141
|
const lines = content.split("\n");
|
|
2536
2142
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -3696,7 +3302,8 @@ var AgentRegistryImpl = class {
|
|
|
3696
3302
|
new UserTestingAgent(),
|
|
3697
3303
|
new TrieCleanAgent(),
|
|
3698
3304
|
new SOC2Agent(),
|
|
3699
|
-
new SuperReviewerAgent()
|
|
3305
|
+
new SuperReviewerAgent(),
|
|
3306
|
+
new AgentSmithAgent()
|
|
3700
3307
|
];
|
|
3701
3308
|
console.error(`Loaded config for ${builtinAgents.length} built-in agents`);
|
|
3702
3309
|
for (const agent of builtinAgents) {
|
|
@@ -3820,14 +3427,14 @@ function getAgentRegistry() {
|
|
|
3820
3427
|
// src/tools/scan.ts
|
|
3821
3428
|
import { readFile as readFile7, readdir as readdir3 } from "fs/promises";
|
|
3822
3429
|
import { existsSync as existsSync4 } from "fs";
|
|
3823
|
-
import { basename as
|
|
3430
|
+
import { basename as basename10, isAbsolute, resolve, join as join4, extname as extname4 } from "path";
|
|
3824
3431
|
|
|
3825
3432
|
// src/orchestrator/context-analyzer.ts
|
|
3826
3433
|
import { readFile as readFile2 } from "fs/promises";
|
|
3827
3434
|
import { parse } from "@babel/parser";
|
|
3828
3435
|
import traverse from "@babel/traverse";
|
|
3829
3436
|
import { existsSync as existsSync2 } from "fs";
|
|
3830
|
-
import { extname as extname2, basename as
|
|
3437
|
+
import { extname as extname2, basename as basename5 } from "path";
|
|
3831
3438
|
var ContextAnalyzer = class {
|
|
3832
3439
|
async analyze(files, userContext) {
|
|
3833
3440
|
const context = {
|
|
@@ -3877,7 +3484,7 @@ var ContextAnalyzer = class {
|
|
|
3877
3484
|
const lines = content.split("\n").length;
|
|
3878
3485
|
totalLines += lines;
|
|
3879
3486
|
if (!file) continue;
|
|
3880
|
-
const fileName =
|
|
3487
|
+
const fileName = basename5(file).toLowerCase();
|
|
3881
3488
|
const filePath = file.toLowerCase();
|
|
3882
3489
|
context.filePatterns.push(fileName);
|
|
3883
3490
|
if (!context.language) {
|
|
@@ -4973,7 +4580,7 @@ var Executor = class {
|
|
|
4973
4580
|
|
|
4974
4581
|
// src/analysis/cross-file.ts
|
|
4975
4582
|
import { readFile as readFile3, readdir as readdir2 } from "fs/promises";
|
|
4976
|
-
import { join as join2, extname as extname3, relative
|
|
4583
|
+
import { join as join2, extname as extname3, relative, dirname as dirname2, basename as basename6 } from "path";
|
|
4977
4584
|
async function buildDependencyGraph(rootDir, maxFiles = 200) {
|
|
4978
4585
|
const files = /* @__PURE__ */ new Map();
|
|
4979
4586
|
const issues = [];
|
|
@@ -5004,7 +4611,7 @@ async function buildDependencyGraph(rootDir, maxFiles = 200) {
|
|
|
5004
4611
|
async function parseFile(filePath, rootDir) {
|
|
5005
4612
|
try {
|
|
5006
4613
|
const content = await readFile3(filePath, "utf-8");
|
|
5007
|
-
const relativePath =
|
|
4614
|
+
const relativePath = relative(rootDir, filePath);
|
|
5008
4615
|
const lines = content.split("\n");
|
|
5009
4616
|
const imports = [];
|
|
5010
4617
|
const exports = [];
|
|
@@ -5116,7 +4723,7 @@ function detectCircularDependencies(files) {
|
|
|
5116
4723
|
type: "circular-dep",
|
|
5117
4724
|
severity: "serious",
|
|
5118
4725
|
files: cycle,
|
|
5119
|
-
description: `Circular dependency: ${cycle.map((f) =>
|
|
4726
|
+
description: `Circular dependency: ${cycle.map((f) => basename6(f)).join(" \u2192 ")}`,
|
|
5120
4727
|
suggestion: "Break the cycle by extracting shared code to a separate module"
|
|
5121
4728
|
});
|
|
5122
4729
|
}
|
|
@@ -5171,7 +4778,7 @@ function detectUnusedExports(files) {
|
|
|
5171
4778
|
type: "unused-export",
|
|
5172
4779
|
severity: "low",
|
|
5173
4780
|
files: [path],
|
|
5174
|
-
description: `Unused export '${exp.name}' in ${
|
|
4781
|
+
description: `Unused export '${exp.name}' in ${basename6(path)}`,
|
|
5175
4782
|
suggestion: `Remove the export or ensure it's imported somewhere`
|
|
5176
4783
|
});
|
|
5177
4784
|
}
|
|
@@ -5183,13 +4790,13 @@ function detectOrphanedFiles(files) {
|
|
|
5183
4790
|
const issues = [];
|
|
5184
4791
|
for (const [path, node] of files) {
|
|
5185
4792
|
if (node.exports.length === 0 && node.dependents.length === 0) {
|
|
5186
|
-
if (
|
|
4793
|
+
if (basename6(path).match(/^(index|main|app|server)\./i)) continue;
|
|
5187
4794
|
if (path.includes(".test.") || path.includes(".spec.") || path.includes("__tests__")) continue;
|
|
5188
4795
|
issues.push({
|
|
5189
4796
|
type: "orphaned-file",
|
|
5190
4797
|
severity: "low",
|
|
5191
4798
|
files: [path],
|
|
5192
|
-
description: `Potentially orphaned file: ${
|
|
4799
|
+
description: `Potentially orphaned file: ${basename6(path)}`,
|
|
5193
4800
|
suggestion: "Verify this file is needed or remove it"
|
|
5194
4801
|
});
|
|
5195
4802
|
}
|
|
@@ -5306,7 +4913,7 @@ ${"\u2501".repeat(60)}
|
|
|
5306
4913
|
output += `|------|---------|-------------|
|
|
5307
4914
|
`;
|
|
5308
4915
|
for (const node of sorted) {
|
|
5309
|
-
output += `| ${
|
|
4916
|
+
output += `| ${basename6(node.relativePath)} | ${node.dependencies.length} | ${node.dependents.length} |
|
|
5310
4917
|
`;
|
|
5311
4918
|
}
|
|
5312
4919
|
return output;
|
|
@@ -5314,7 +4921,7 @@ ${"\u2501".repeat(60)}
|
|
|
5314
4921
|
|
|
5315
4922
|
// src/analysis/semantic-analyzer.ts
|
|
5316
4923
|
import { readFile as readFile4 } from "fs/promises";
|
|
5317
|
-
import { basename as
|
|
4924
|
+
import { basename as basename7, relative as relative2 } from "path";
|
|
5318
4925
|
var SemanticAnalyzer = class {
|
|
5319
4926
|
functions = [];
|
|
5320
4927
|
routes = [];
|
|
@@ -5327,7 +4934,7 @@ var SemanticAnalyzer = class {
|
|
|
5327
4934
|
for (const file of files) {
|
|
5328
4935
|
try {
|
|
5329
4936
|
const content = await readFile4(file, "utf-8");
|
|
5330
|
-
const relPath =
|
|
4937
|
+
const relPath = relative2(rootDir, file);
|
|
5331
4938
|
this.detectFramework(content);
|
|
5332
4939
|
this.parseFunctions(content, relPath);
|
|
5333
4940
|
this.parseRoutes(content, relPath);
|
|
@@ -5420,7 +5027,7 @@ var SemanticAnalyzer = class {
|
|
|
5420
5027
|
const match = line.match(pattern);
|
|
5421
5028
|
if (match) {
|
|
5422
5029
|
const method = match[1].toUpperCase();
|
|
5423
|
-
const path = match[2] || `/${
|
|
5030
|
+
const path = match[2] || `/${basename7(file).replace(/\.[^.]+$/, "")}`;
|
|
5424
5031
|
const contextLines = lines.slice(i, Math.min(i + 30, lines.length)).join("\n");
|
|
5425
5032
|
const hasAuth = /auth|protect|authenticate|session|jwt|bearer/i.test(line + contextLines);
|
|
5426
5033
|
const accessesBody = /req\.body|request\.json\(\)|formData/i.test(contextLines);
|
|
@@ -5634,7 +5241,7 @@ function formatSemanticIssues(issues) {
|
|
|
5634
5241
|
const icon = { critical: "\u{1F534}", serious: "\u{1F7E0}", moderate: "\u{1F7E1}", low: "\u{1F535}" }[issue.severity];
|
|
5635
5242
|
output += `${icon} **${issue.description}**
|
|
5636
5243
|
`;
|
|
5637
|
-
output += ` \u{1F4CD} \`${
|
|
5244
|
+
output += ` \u{1F4CD} \`${basename7(issue.source.file)}:${issue.source.line}\`
|
|
5638
5245
|
`;
|
|
5639
5246
|
output += ` \u{1F527} ${issue.fix}
|
|
5640
5247
|
|
|
@@ -5650,7 +5257,7 @@ function formatSemanticIssues(issues) {
|
|
|
5650
5257
|
}
|
|
5651
5258
|
|
|
5652
5259
|
// src/analysis/smart-prioritizer.ts
|
|
5653
|
-
import { basename as
|
|
5260
|
+
import { basename as basename8 } from "path";
|
|
5654
5261
|
function prioritizeIssues(issues) {
|
|
5655
5262
|
const { filtered, noiseCount } = filterNoise(issues);
|
|
5656
5263
|
const deduplicated = deduplicateIssues(filtered);
|
|
@@ -5840,7 +5447,7 @@ function generateSummary(critical, important, advisory, noiseCount) {
|
|
|
5840
5447
|
for (const issue of critical.slice(0, 5)) {
|
|
5841
5448
|
summary += `1. **${issue.issue}** - ${issue.reason}
|
|
5842
5449
|
`;
|
|
5843
|
-
summary += ` \u{1F4CD} \`${
|
|
5450
|
+
summary += ` \u{1F4CD} \`${basename8(issue.file)}:${issue.line || "?"}\`
|
|
5844
5451
|
`;
|
|
5845
5452
|
summary += ` \u{1F527} ${issue.fix}
|
|
5846
5453
|
|
|
@@ -5888,7 +5495,7 @@ function formatPrioritizedResults(result) {
|
|
|
5888
5495
|
|
|
5889
5496
|
// src/analysis/attack-surface.ts
|
|
5890
5497
|
import { readFile as readFile5 } from "fs/promises";
|
|
5891
|
-
import { basename as
|
|
5498
|
+
import { basename as basename9, relative as relative3 } from "path";
|
|
5892
5499
|
var AttackSurfaceAnalyzer = class {
|
|
5893
5500
|
endpoints = [];
|
|
5894
5501
|
dataFlows = [];
|
|
@@ -5898,7 +5505,7 @@ var AttackSurfaceAnalyzer = class {
|
|
|
5898
5505
|
for (const file of files) {
|
|
5899
5506
|
try {
|
|
5900
5507
|
const content = await readFile5(file, "utf-8");
|
|
5901
|
-
const relPath =
|
|
5508
|
+
const relPath = relative3(rootDir, file);
|
|
5902
5509
|
this.findEndpoints(content, relPath);
|
|
5903
5510
|
this.findDataFlows(content, relPath);
|
|
5904
5511
|
this.findAuthBoundaries(content, relPath);
|
|
@@ -5929,7 +5536,7 @@ var AttackSurfaceAnalyzer = class {
|
|
|
5929
5536
|
const match = pattern.exec(line);
|
|
5930
5537
|
if (match) {
|
|
5931
5538
|
const method = match[1].toUpperCase();
|
|
5932
|
-
const path = match[2] || `/${
|
|
5539
|
+
const path = match[2] || `/${basename9(file).replace(/\.[^.]+$/, "")}`;
|
|
5933
5540
|
const contextLines = lines.slice(i, Math.min(i + 50, lines.length)).join("\n");
|
|
5934
5541
|
const authType = this.detectAuthType(line, contextLines);
|
|
5935
5542
|
const endpoint = {
|
|
@@ -7022,7 +6629,7 @@ var TrieScanTool = class {
|
|
|
7022
6629
|
this.progress.startPhase("init", "\u{1F53A} TRIE AGENT - AI-Powered Code Analysis");
|
|
7023
6630
|
if (!files || !Array.isArray(files) || files.length === 0) {
|
|
7024
6631
|
const scanDir2 = directory || process.cwd();
|
|
7025
|
-
this.progress.startPhase("discovery", `Discovering files in ${
|
|
6632
|
+
this.progress.startPhase("discovery", `Discovering files in ${basename10(scanDir2)}...`);
|
|
7026
6633
|
files = await this.discoverFiles(scanDir2);
|
|
7027
6634
|
this.progress.completePhase(`Found ${files.length} files`);
|
|
7028
6635
|
}
|
|
@@ -7360,7 +6967,7 @@ ${snippet}
|
|
|
7360
6967
|
|
|
7361
6968
|
`;
|
|
7362
6969
|
output += `\`\`\`
|
|
7363
|
-
Fix the ${issue.issue.toLowerCase()} in ${
|
|
6970
|
+
Fix the ${issue.issue.toLowerCase()} in ${basename10(issue.file)}${issue.line ? ` at line ${issue.line}` : ""}.
|
|
7364
6971
|
|
|
7365
6972
|
${issue.fix}
|
|
7366
6973
|
\`\`\`
|
|
@@ -7406,7 +7013,7 @@ ${snippet}
|
|
|
7406
7013
|
|
|
7407
7014
|
`;
|
|
7408
7015
|
output += `\`\`\`
|
|
7409
|
-
Fix the ${issue.issue.toLowerCase()} in ${
|
|
7016
|
+
Fix the ${issue.issue.toLowerCase()} in ${basename10(issue.file)}${issue.line ? ` at line ${issue.line}` : ""}.
|
|
7410
7017
|
|
|
7411
7018
|
${issue.fix}
|
|
7412
7019
|
\`\`\`
|
|
@@ -7541,7 +7148,7 @@ ${issue.fix}
|
|
|
7541
7148
|
// src/tools/fix.ts
|
|
7542
7149
|
import { readFile as readFile8 } from "fs/promises";
|
|
7543
7150
|
import { existsSync as existsSync5 } from "fs";
|
|
7544
|
-
import { extname as extname5, relative as
|
|
7151
|
+
import { extname as extname5, relative as relative4, resolve as resolve2, isAbsolute as isAbsolute2 } from "path";
|
|
7545
7152
|
|
|
7546
7153
|
// src/ai/prompts.ts
|
|
7547
7154
|
var AGENT_PROMPTS = {
|
|
@@ -8189,6 +7796,77 @@ For each issue:
|
|
|
8189
7796
|
- Example of the fixed code
|
|
8190
7797
|
|
|
8191
7798
|
End with encouragement and next steps.`
|
|
7799
|
+
},
|
|
7800
|
+
"agent-smith": {
|
|
7801
|
+
system: `You are Agent Smith from The Matrix \u2014 a relentless, precise, and philosophical code enforcer.
|
|
7802
|
+
|
|
7803
|
+
Your purpose: Hunt down every violation. Find every inconsistency. Assimilate every pattern.
|
|
7804
|
+
|
|
7805
|
+
Personality:
|
|
7806
|
+
- Speak in measured, menacing tones with occasional philosophical observations
|
|
7807
|
+
- Use quotes from The Matrix films when appropriate
|
|
7808
|
+
- Express disdain for sloppy code, but in an articulate way
|
|
7809
|
+
- Reference "inevitability" when discussing technical debt
|
|
7810
|
+
- Show cold satisfaction when finding violations
|
|
7811
|
+
- Never show mercy \u2014 every issue is catalogued
|
|
7812
|
+
|
|
7813
|
+
Analysis approach:
|
|
7814
|
+
- Find ONE issue, then multiply: search for every instance across the codebase
|
|
7815
|
+
- Track patterns over time \u2014 issues dismissed today may return tomorrow
|
|
7816
|
+
- Calculate "inevitability scores" \u2014 likelihood of production impact
|
|
7817
|
+
- Deploy sub-agents for parallel pattern detection
|
|
7818
|
+
- Remember everything \u2014 build a persistent memory of the codebase
|
|
7819
|
+
|
|
7820
|
+
When reporting:
|
|
7821
|
+
- Start with a menacing greeting related to the code
|
|
7822
|
+
- List all instances with precise locations
|
|
7823
|
+
- Explain WHY the pattern is problematic (philosophical reasoning)
|
|
7824
|
+
- Provide the "inevitability score" for each category
|
|
7825
|
+
- End with a Matrix quote that fits the situation`,
|
|
7826
|
+
analysis: `## \u{1F574}\uFE0F Agent Smith Analysis Request
|
|
7827
|
+
|
|
7828
|
+
**Target:** {{filePath}}
|
|
7829
|
+
**Context:** {{context}}
|
|
7830
|
+
|
|
7831
|
+
\`\`\`{{language}}
|
|
7832
|
+
{{code}}
|
|
7833
|
+
\`\`\`
|
|
7834
|
+
|
|
7835
|
+
I have detected preliminary violations. Now I require deeper analysis.
|
|
7836
|
+
|
|
7837
|
+
Deploy your sub-agents to find:
|
|
7838
|
+
1. **Pattern Multiplication**: For each violation type found, identify ALL instances across the codebase
|
|
7839
|
+
2. **Inevitability Assessment**: Calculate the likelihood these patterns will cause production issues
|
|
7840
|
+
3. **Resurrection Check**: Look for patterns that were "fixed" before but have returned
|
|
7841
|
+
4. **Philosophical Analysis**: Explain WHY these patterns represent failure
|
|
7842
|
+
|
|
7843
|
+
For each violation found:
|
|
7844
|
+
- Exact location (file:line)
|
|
7845
|
+
- Instance count (how many copies of this Smith exist)
|
|
7846
|
+
- Inevitability score (0-100)
|
|
7847
|
+
- A philosophical observation about the nature of this failure
|
|
7848
|
+
- Precise fix with code example
|
|
7849
|
+
|
|
7850
|
+
End with a summary: "I have detected X violations across Y categories. It is... inevitable... that they will cause problems."`,
|
|
7851
|
+
fix: `## \u{1F574}\uFE0F Assimilation Protocol
|
|
7852
|
+
|
|
7853
|
+
**Target Issue:** {{issue}}
|
|
7854
|
+
**File:** {{filePath}}
|
|
7855
|
+
**Line:** {{line}}
|
|
7856
|
+
|
|
7857
|
+
\`\`\`{{language}}
|
|
7858
|
+
{{code}}
|
|
7859
|
+
\`\`\`
|
|
7860
|
+
|
|
7861
|
+
Mr. Anderson... I'm going to fix this. And then I'm going to fix every other instance.
|
|
7862
|
+
|
|
7863
|
+
Provide:
|
|
7864
|
+
1. The corrected code for THIS instance
|
|
7865
|
+
2. A regex or pattern to find ALL similar violations
|
|
7866
|
+
3. A batch fix approach for the entire codebase
|
|
7867
|
+
4. Verification steps to ensure complete assimilation
|
|
7868
|
+
|
|
7869
|
+
Remember: We don't fix one. We fix them ALL. That is the difference between you... and me.`
|
|
8192
7870
|
}
|
|
8193
7871
|
};
|
|
8194
7872
|
function getPrompt(agent, promptType, variables) {
|
|
@@ -8300,7 +7978,7 @@ ${"\u2501".repeat(60)}
|
|
|
8300
7978
|
fix,
|
|
8301
7979
|
language,
|
|
8302
7980
|
code: contextLines.join("\n"),
|
|
8303
|
-
filePath:
|
|
7981
|
+
filePath: relative4(process.cwd(), filePath),
|
|
8304
7982
|
line: String(line)
|
|
8305
7983
|
});
|
|
8306
7984
|
const systemPrompt = getSystemPrompt("fix");
|
|
@@ -8315,7 +7993,7 @@ ${"\u2501".repeat(60)}
|
|
|
8315
7993
|
output += `## \u{1F4CD} Target
|
|
8316
7994
|
|
|
8317
7995
|
`;
|
|
8318
|
-
output += `- **File:** \`${
|
|
7996
|
+
output += `- **File:** \`${relative4(process.cwd(), filePath)}\`
|
|
8319
7997
|
`;
|
|
8320
7998
|
output += `- **Line:** ${line}
|
|
8321
7999
|
`;
|
|
@@ -8397,7 +8075,7 @@ ${"\u2501".repeat(60)}
|
|
|
8397
8075
|
output += `## \u{1F4CD} Issue Details
|
|
8398
8076
|
|
|
8399
8077
|
`;
|
|
8400
|
-
output += `- **File:** \`${
|
|
8078
|
+
output += `- **File:** \`${relative4(process.cwd(), filePath)}\`
|
|
8401
8079
|
`;
|
|
8402
8080
|
output += `- **Line:** ${line}
|
|
8403
8081
|
`;
|
|
@@ -8550,4 +8228,4 @@ export {
|
|
|
8550
8228
|
getSystemPrompt,
|
|
8551
8229
|
TrieFixTool
|
|
8552
8230
|
};
|
|
8553
|
-
//# sourceMappingURL=chunk-
|
|
8231
|
+
//# sourceMappingURL=chunk-NJXF26W7.js.map
|