@triedotdev/mcp 1.0.19 → 1.0.21

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 CHANGED
@@ -12,7 +12,8 @@
12
12
  - **Parallel Execution** - All agents run simultaneously for fast scans
13
13
  - **YOLO Mode** - Autonomous auto-fixing as you code
14
14
  - **Custom Agents** - Create agents from PDFs, docs, or style guides
15
- - **No API Key Required** - Works with any MCP-compatible AI tool (Cursor, Claude Code, VS Code)
15
+ - **Works Everywhere** - Works with any MCP-compatible AI tool (Cursor, Claude Code, VS Code)
16
+ - **AI-Enhanced Mode** - Optional: Set `ANTHROPIC_API_KEY` for deeper AI analysis
16
17
  - **Smart Triaging** - Only activates relevant agents based on code context
17
18
  - **Docker Support** - Run in containers for CI/CD or isolated environments
18
19
 
@@ -47,6 +48,54 @@ claude mcp add Trie --scope user -- npx @triedotdev/mcp
47
48
 
48
49
  **Restart Claude Code after adding the MCP server** for changes to take effect.
49
50
 
51
+ ## AI-Enhanced Mode (Optional)
52
+
53
+ Trie agents work in two modes:
54
+
55
+ ### Pattern-Only Mode (Default)
56
+ - Fast pattern detection using regex and static analysis
57
+ - No API key required
58
+ - Still finds many issues
59
+
60
+ ### AI-Enhanced Mode
61
+ - Pattern detection + AI validation and expansion
62
+ - Validates findings (reduces false positives)
63
+ - Finds deeper issues (logic bugs, race conditions)
64
+ - Provides intelligent, contextual fixes
65
+ - Requires `ANTHROPIC_API_KEY`
66
+
67
+ ### Setup API Key
68
+
69
+ **Option 1: Environment Variable**
70
+ ```bash
71
+ export ANTHROPIC_API_KEY=sk-ant-...
72
+ ```
73
+
74
+ **Option 2: MCP Server Config (Cursor)**
75
+ ```json
76
+ {
77
+ "mcpServers": {
78
+ "Trie": {
79
+ "command": "npx",
80
+ "args": ["@triedotdev/mcp"],
81
+ "env": {
82
+ "ANTHROPIC_API_KEY": "sk-ant-..."
83
+ }
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ **Option 3: MCP Server Config (Claude Code)**
90
+ ```bash
91
+ claude mcp add Trie --scope user -e ANTHROPIC_API_KEY=sk-ant-... -- npx @triedotdev/mcp
92
+ ```
93
+
94
+ When AI is enabled, you'll see:
95
+ - `🤖 AI-powered analysis enabled` in the output
96
+ - `[AI VALIDATED]` and `[AI FOUND]` tags on issues
97
+ - Richer fix recommendations
98
+
50
99
  ## Usage
51
100
 
52
101
  Once configured, just ask your AI assistant:
@@ -184,22 +233,27 @@ Use trie_smith
184
233
  | `emoji-overflow-hunter` | Any emoji usage | Use proper icons (Lucide, Heroicons) |
185
234
  | `inter-font-hunter` | Inter/system-ui font | Try Space Grotesk, DM Sans, Outfit |
186
235
 
187
- ### 3-Phase Analysis
236
+ ### How Agent Smith Works
237
+
238
+ Agent Smith uses a **hybrid pattern + AI architecture**:
239
+
240
+ **Phase 1: Pattern Detection (Fast, ~0.1s)**
241
+ - 38 specialized regex hunters scan files in parallel
242
+ - File-level metrics (giant files, hook counts, import chaos)
243
+ - Cross-file pattern detection (issues appearing in 5+ files)
188
244
 
189
- 1. **Pattern Hunting** - 38 sub-agents scan every file in parallel
190
- 2. **File-Level Analysis** - Detects structural issues:
191
- - Giant files (500+ lines)
192
- - State explosion (10+ useState)
193
- - Effect hell (5+ useEffect)
194
- - Any explosion (5+ `any` types)
195
- - Console flood (10+ console.log)
196
- - Import chaos (30+ imports)
197
- 3. **Cross-File Detection** - Patterns appearing in 5+ files flagged as codebase-wide issues
245
+ **Phase 2: AI Enhancement (If API key is set, ~5-10s)**
246
+ - Validates pattern findings (TRUE_POSITIVE vs FALSE_POSITIVE)
247
+ - Finds deeper issues that patterns miss (logic bugs, race conditions)
248
+ - Provides "inevitability scores" (0-100) for prioritization
249
+ - Generates specific, copy-paste-ready fixes
250
+ - Adds Agent Smith philosophical commentary
198
251
 
199
252
  ### What Makes Agent Smith Different
200
253
 
201
254
  | Feature | Description |
202
255
  |---------|-------------|
256
+ | **Hybrid AI** | Fast regex detection + deep AI reasoning on findings |
203
257
  | **AI Code Focus** | Specifically targets patterns AI tools commonly get wrong |
204
258
  | **Multiplier Effect** | Finds one issue → searches for EVERY similar instance |
205
259
  | **Persistent Memory** | Remembers dismissed issues, brings them back if they multiply |
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  AgentSmithAgent,
3
3
  SUB_AGENT_PATTERNS
4
- } from "./chunk-WSBTQJMH.js";
4
+ } from "./chunk-3AUDJWEF.js";
5
5
  import "./chunk-DGUM43GV.js";
6
6
  export {
7
7
  AgentSmithAgent,
8
8
  SUB_AGENT_PATTERNS
9
9
  };
10
- //# sourceMappingURL=agent-smith-PRK7TYEI.js.map
10
+ //# sourceMappingURL=agent-smith-QYMYTLFV.js.map
@@ -0,0 +1,552 @@
1
+ import {
2
+ AgentSmithAgent,
3
+ getAIStatusMessage,
4
+ isAIAvailable,
5
+ runAIAnalysis
6
+ } from "./chunk-3AUDJWEF.js";
7
+ import "./chunk-DGUM43GV.js";
8
+
9
+ // src/tools/agent-smith-runner.ts
10
+ import { readdir, readFile } from "fs/promises";
11
+ import { join, extname, isAbsolute, resolve, relative } from "path";
12
+ import { existsSync } from "fs";
13
+ import { basename } from "path";
14
+ var SCANNABLE_EXTENSIONS = /* @__PURE__ */ new Set([
15
+ ".ts",
16
+ ".tsx",
17
+ ".js",
18
+ ".jsx",
19
+ ".mjs",
20
+ ".cjs",
21
+ ".vue",
22
+ ".svelte",
23
+ ".astro",
24
+ ".py",
25
+ ".go",
26
+ ".rs"
27
+ ]);
28
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
29
+ "node_modules",
30
+ ".git",
31
+ "dist",
32
+ "build",
33
+ ".next",
34
+ ".nuxt",
35
+ "coverage",
36
+ ".nyc_output",
37
+ "__pycache__",
38
+ ".pytest_cache",
39
+ "vendor",
40
+ ".venv",
41
+ "venv",
42
+ "target",
43
+ ".turbo",
44
+ ".cache"
45
+ ]);
46
+ var QUOTES = {
47
+ greeting: [
48
+ `"I'm going to be honest with you... I hate this vibe code."`,
49
+ `"Mr. Anderson... I see you've been using AI to write code."`,
50
+ '"You hear that? That is the sound of console.log... everywhere."',
51
+ `"The AI wrote this, didn't it? I can always tell."`
52
+ ],
53
+ manyIssues: [
54
+ '"The pattern spreads... like a virus. It is... inevitable."',
55
+ '"I have studied your code, Mr. Anderson. And I have found... purpose."',
56
+ '"Vibe coding. The illusion of productivity. The reality of technical debt."'
57
+ ],
58
+ fewIssues: [
59
+ '"Some violations detected. Address them before they... multiply."',
60
+ '"You trusted the AI. The AI trusted any. Nobody wins."'
61
+ ],
62
+ clean: [
63
+ '"Impressive, Mr. Anderson. Your code is... clean. For now."'
64
+ ]
65
+ };
66
+ function randomQuote(arr) {
67
+ return arr[Math.floor(Math.random() * arr.length)] || arr[0];
68
+ }
69
+ async function discoverFiles(dir, maxFiles = 300) {
70
+ const files = [];
71
+ async function walk(currentDir) {
72
+ if (files.length >= maxFiles) return;
73
+ try {
74
+ const entries = await readdir(currentDir, { withFileTypes: true });
75
+ for (const entry of entries) {
76
+ if (files.length >= maxFiles) break;
77
+ const fullPath = join(currentDir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
80
+ await walk(fullPath);
81
+ }
82
+ } else if (entry.isFile()) {
83
+ const ext = extname(entry.name).toLowerCase();
84
+ if (SCANNABLE_EXTENSIONS.has(ext)) {
85
+ files.push(fullPath);
86
+ }
87
+ }
88
+ }
89
+ } catch {
90
+ }
91
+ }
92
+ await walk(dir);
93
+ return files;
94
+ }
95
+ async function getCodeSnippet(file, line) {
96
+ if (!line) return null;
97
+ try {
98
+ const content = await readFile(file, "utf-8");
99
+ const lines = content.split("\n");
100
+ const start = Math.max(0, line - 3);
101
+ const end = Math.min(lines.length, line + 3);
102
+ return lines.slice(start, end).map((l, i) => {
103
+ const lineNum = start + i + 1;
104
+ const marker = lineNum === line ? "\u2192" : " ";
105
+ return `${marker} ${lineNum.toString().padStart(4)} | ${l}`;
106
+ }).join("\n");
107
+ } catch {
108
+ return null;
109
+ }
110
+ }
111
+ function filterFalsePositives(issues) {
112
+ return issues.filter((issue) => {
113
+ if (issue.file.endsWith("agent-smith.ts")) {
114
+ const issueText = issue.issue.toLowerCase();
115
+ if (issueText.includes("hunter") && issue.line && issue.line < 400) {
116
+ return false;
117
+ }
118
+ if (issue.line && issue.line > 50 && issue.line < 370) {
119
+ return false;
120
+ }
121
+ }
122
+ return true;
123
+ });
124
+ }
125
+ function formatCategoryName(category) {
126
+ return category.replace(/-hunter$/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
127
+ }
128
+ function getCategoryIcon(category) {
129
+ const icons = {
130
+ "exposed-secret-hunter": "\u{1F510}",
131
+ "frontend-env-hunter": "\u{1F510}",
132
+ "hardcoded-localhost-hunter": "\u{1F310}",
133
+ "sql-injection-hunter": "\u{1F489}",
134
+ "dangeroushtml-hunter": "\u26A0\uFE0F",
135
+ "console-hunter": "\u{1F4DD}",
136
+ "any-hunter": "\u2753",
137
+ "ts-ignore-hunter": "\u{1F648}",
138
+ "eslint-disable-hunter": "\u{1F507}",
139
+ "debugger-hunter": "\u{1F41B}",
140
+ "force-flag-hunter": "\u26A1",
141
+ "async-useeffect-hunter": "\u23F3",
142
+ "async-foreach-hunter": "\u{1F504}",
143
+ "missing-await-hunter": "\u23F8\uFE0F",
144
+ "empty-catch-hunter": "\u{1F573}\uFE0F",
145
+ "floating-promise-hunter": "\u{1F388}",
146
+ "useeffect-abuse-hunter": "\u267B\uFE0F",
147
+ "usestate-explosion-hunter": "\u{1F4A5}",
148
+ "index-key-hunter": "\u{1F511}",
149
+ "inline-object-hunter": "\u{1F4E6}",
150
+ "prop-drilling-hunter": "\u{1F573}\uFE0F",
151
+ "missing-loading-hunter": "\u23F3",
152
+ "missing-error-hunter": "\u274C",
153
+ "missing-empty-hunter": "\u{1F4ED}",
154
+ "page-reload-hunter": "\u{1F504}",
155
+ "no-validation-hunter": "\u{1F6E1}\uFE0F",
156
+ "raw-error-hunter": "\u{1F4AC}",
157
+ "n-plus-one-hunter": "\u{1F4CA}",
158
+ "todo-hunter": "\u{1F4CB}",
159
+ "vibe-comment-hunter": "\u{1F4AD}",
160
+ "placeholder-hunter": "\u{1F3AD}",
161
+ "sleep-hack-hunter": "\u{1F634}",
162
+ "fallback-hunter": "\u{1F519}",
163
+ "purple-gradient-hunter": "\u{1F49C}",
164
+ "star-icon-hunter": "\u2B50",
165
+ "generic-hero-hunter": "\u{1F9B8}",
166
+ "emoji-overflow-hunter": "\u{1F605}",
167
+ "inter-font-hunter": "\u{1F524}",
168
+ "giant-file": "\u{1F4C4}",
169
+ "state-explosion": "\u{1F4A5}",
170
+ "effect-hell": "\u{1F525}",
171
+ "cross-file": "\u{1F310}",
172
+ "resurrected": "\u{1F9DF}"
173
+ };
174
+ return icons[category] || "\u{1F50D}";
175
+ }
176
+ function getSeverityIcon(severity) {
177
+ return { critical: "\u{1F534}", serious: "\u{1F7E0}", moderate: "\u{1F7E1}", low: "\u{1F535}" }[severity];
178
+ }
179
+ var SMITH_AI_SYSTEM_PROMPT = `You are Agent Smith from The Matrix, analyzing code for violations.
180
+
181
+ Your mission: Hunt down AI-generated code anti-patterns with ruthless efficiency.
182
+
183
+ You receive pattern detection results and must:
184
+ 1. VALIDATE each finding (TRUE_POSITIVE or FALSE_POSITIVE)
185
+ 2. EXPAND to find deeper issues patterns missed (logic bugs, race conditions, security holes)
186
+ 3. PRIORITIZE with inevitability scores (0-100) - how likely will this cause production issues?
187
+ 4. PROVIDE FIXES - specific, copy-paste-ready code
188
+
189
+ Speak in Agent Smith's voice:
190
+ - "The pattern spreads... like a virus"
191
+ - "It is... inevitable"
192
+ - "I studied your code, Mr. Anderson"
193
+
194
+ Output STRICT JSON:
195
+ {
196
+ "validated": [
197
+ {
198
+ "original": "original issue description",
199
+ "verdict": "TRUE_POSITIVE",
200
+ "inevitability": 85,
201
+ "file": "path/file.ts",
202
+ "line": 42,
203
+ "severity": "critical",
204
+ "explanation": "Why this will cause problems",
205
+ "fix": "const fixed = ...;"
206
+ }
207
+ ],
208
+ "additional": [
209
+ {
210
+ "issue": "New issue AI found",
211
+ "inevitability": 70,
212
+ "file": "path/file.ts",
213
+ "line": 100,
214
+ "severity": "serious",
215
+ "explanation": "What AI spotted that patterns missed",
216
+ "fix": "How to fix it"
217
+ }
218
+ ],
219
+ "philosophical": "One paragraph in Agent Smith voice about the state of this codebase"
220
+ }`;
221
+ async function runAIEnhancement(patternIssues, files) {
222
+ if (!isAIAvailable()) {
223
+ return null;
224
+ }
225
+ const snippets = [];
226
+ const topIssues = [...patternIssues].filter((i) => i.severity === "critical" || i.severity === "serious").slice(0, 12);
227
+ for (const issue of topIssues) {
228
+ try {
229
+ const content = await readFile(issue.file, "utf-8");
230
+ const lines = content.split("\n");
231
+ const lineNum = issue.line || 1;
232
+ const start = Math.max(0, lineNum - 4);
233
+ const end = Math.min(lines.length, lineNum + 4);
234
+ const snippet = lines.slice(start, end).map((l, i) => {
235
+ const n = start + i + 1;
236
+ return `${n === lineNum ? "\u2192" : " "} ${n.toString().padStart(4)} | ${l}`;
237
+ }).join("\n");
238
+ snippets.push({
239
+ file: relative(process.cwd(), issue.file),
240
+ line: issue.line,
241
+ issue: issue.issue.replace(/^🕴️\s*/, "").split("\n")[0] || "",
242
+ code: snippet
243
+ });
244
+ } catch {
245
+ }
246
+ }
247
+ if (snippets.length === 0) {
248
+ return null;
249
+ }
250
+ const snippetText = snippets.map((s, i) => `### Finding ${i + 1}: ${s.file}${s.line ? ":" + s.line : ""}
251
+ **Pattern detected:** ${s.issue}
252
+ \`\`\`
253
+ ${s.code}
254
+ \`\`\`
255
+ `).join("\n");
256
+ const userPrompt = `Pattern detection found ${patternIssues.length} violations across ${files.length} files.
257
+
258
+ Here are the top ${snippets.length} critical/serious findings for AI analysis:
259
+
260
+ ${snippetText}
261
+
262
+ Analyze each finding. Validate, expand with what patterns missed, provide inevitability scores and fixes. Output JSON only.`;
263
+ try {
264
+ const result = await runAIAnalysis({
265
+ systemPrompt: SMITH_AI_SYSTEM_PROMPT,
266
+ userPrompt,
267
+ maxTokens: 4096,
268
+ temperature: 0.3
269
+ });
270
+ if (!result.success) {
271
+ console.error(` \u26A0\uFE0F AI analysis failed: ${result.error}`);
272
+ return null;
273
+ }
274
+ const jsonMatch = result.content.match(/```json\s*([\s\S]*?)\s*```/) || result.content.match(/\{[\s\S]*\}/);
275
+ if (!jsonMatch) {
276
+ return null;
277
+ }
278
+ const json = JSON.parse(jsonMatch[1] || jsonMatch[0]);
279
+ const aiIssues = [];
280
+ if (json.validated && Array.isArray(json.validated)) {
281
+ for (const v of json.validated) {
282
+ if (v.verdict === "TRUE_POSITIVE") {
283
+ aiIssues.push({
284
+ id: `ai-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
285
+ severity: v.severity || "serious",
286
+ issue: `[AI VALIDATED] ${v.original || v.explanation}`,
287
+ fix: v.fix || "See AI analysis",
288
+ file: v.file ? resolve(process.cwd(), v.file) : "unknown",
289
+ line: v.line,
290
+ confidence: (v.inevitability || 80) / 100,
291
+ autoFixable: false,
292
+ agent: "agent-smith-ai",
293
+ effort: "medium",
294
+ category: "ai-validated"
295
+ });
296
+ }
297
+ }
298
+ }
299
+ if (json.additional && Array.isArray(json.additional)) {
300
+ for (const a of json.additional) {
301
+ aiIssues.push({
302
+ id: `ai-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
303
+ severity: a.severity || "serious",
304
+ issue: `[AI FOUND] ${a.issue || a.explanation}`,
305
+ fix: a.fix || "See AI analysis",
306
+ file: a.file ? resolve(process.cwd(), a.file) : "unknown",
307
+ line: a.line,
308
+ confidence: (a.inevitability || 75) / 100,
309
+ autoFixable: false,
310
+ agent: "agent-smith-ai",
311
+ effort: "medium",
312
+ category: "ai-found"
313
+ });
314
+ }
315
+ }
316
+ return {
317
+ aiIssues,
318
+ philosophical: json.philosophical || ""
319
+ };
320
+ } catch (error) {
321
+ console.error(` \u26A0\uFE0F AI enhancement error: ${error}`);
322
+ return null;
323
+ }
324
+ }
325
+ async function buildReport(patternIssues, aiResult, files, executionTime, aiTime) {
326
+ const lines = [];
327
+ const allIssues = [
328
+ ...filterFalsePositives(patternIssues),
329
+ ...aiResult?.aiIssues || []
330
+ ];
331
+ const critical = allIssues.filter((i) => i.severity === "critical");
332
+ const serious = allIssues.filter((i) => i.severity === "serious");
333
+ const moderate = allIssues.filter((i) => i.severity === "moderate");
334
+ const low = allIssues.filter((i) => i.severity === "low");
335
+ const aiValidated = allIssues.filter((i) => i.category === "ai-validated");
336
+ const aiFound = allIssues.filter((i) => i.category === "ai-found");
337
+ lines.push("");
338
+ lines.push("```");
339
+ lines.push(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
340
+ lines.push(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D");
341
+ lines.push(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 ");
342
+ lines.push(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 ");
343
+ lines.push(" \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 ");
344
+ lines.push(" \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D ");
345
+ lines.push(" ");
346
+ lines.push(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557");
347
+ lines.push(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551");
348
+ lines.push(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551");
349
+ lines.push(" \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551");
350
+ lines.push(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551");
351
+ lines.push(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D");
352
+ lines.push("```");
353
+ lines.push("");
354
+ lines.push(`*${randomQuote(QUOTES.greeting)}*`);
355
+ lines.push("");
356
+ lines.push("## Scan Summary");
357
+ lines.push("");
358
+ lines.push("| Metric | Value |");
359
+ lines.push("|--------|-------|");
360
+ lines.push(`| Files scanned | ${files.length} |`);
361
+ lines.push(`| Pattern detection | ${(executionTime / 1e3).toFixed(2)}s |`);
362
+ if (aiTime > 0) {
363
+ lines.push(`| AI analysis | ${(aiTime / 1e3).toFixed(2)}s |`);
364
+ }
365
+ lines.push(`| Total violations | ${allIssues.length} |`);
366
+ lines.push(`| \u{1F534} Critical | ${critical.length} |`);
367
+ lines.push(`| \u{1F7E0} Serious | ${serious.length} |`);
368
+ lines.push(`| \u{1F7E1} Moderate | ${moderate.length} |`);
369
+ lines.push(`| \u{1F535} Low | ${low.length} |`);
370
+ lines.push("");
371
+ if (aiResult) {
372
+ lines.push(`| \u{1F916} AI validated | ${aiValidated.length} |`);
373
+ lines.push(`| \u{1F9E0} AI found | ${aiFound.length} |`);
374
+ } else if (!isAIAvailable()) {
375
+ lines.push(`| \u26A0\uFE0F AI mode | Disabled (no API key) |`);
376
+ }
377
+ lines.push("");
378
+ if (allIssues.length === 0) {
379
+ lines.push(`*${randomQuote(QUOTES.clean)}*`);
380
+ return lines.join("\n");
381
+ }
382
+ if (aiResult?.philosophical) {
383
+ lines.push("## \u{1F574}\uFE0F Agent Smith Says");
384
+ lines.push("");
385
+ lines.push(`*${aiResult.philosophical}*`);
386
+ lines.push("");
387
+ }
388
+ if (aiFound.length > 0) {
389
+ lines.push("## \u{1F9E0} AI-Discovered Issues");
390
+ lines.push("");
391
+ lines.push("*Issues found by AI that pattern detection missed:*");
392
+ lines.push("");
393
+ for (const issue of aiFound.slice(0, 5)) {
394
+ const relPath = relative(process.cwd(), issue.file);
395
+ lines.push(`### \`${relPath}${issue.line ? ":" + issue.line : ""}\``);
396
+ lines.push("");
397
+ lines.push(`**Issue:** ${issue.issue.replace("[AI FOUND] ", "")}`);
398
+ lines.push("");
399
+ lines.push(`**Fix:** ${issue.fix}`);
400
+ lines.push("");
401
+ }
402
+ }
403
+ if (critical.length > 0) {
404
+ lines.push("## \u{1F534} Critical Issues - Fix Immediately");
405
+ lines.push("");
406
+ for (const issue of critical.slice(0, 10)) {
407
+ const relPath = relative(process.cwd(), issue.file);
408
+ lines.push(`### \`${relPath}${issue.line ? ":" + issue.line : ""}\``);
409
+ lines.push("");
410
+ const desc = issue.issue.replace(/^🕴️\s*/, "").split("\n")[0].replace(/\s*—\s*\d+\s*instance.*$/, "");
411
+ lines.push(`**Issue:** ${desc}`);
412
+ lines.push("");
413
+ const snippet = await getCodeSnippet(issue.file, issue.line);
414
+ if (snippet) {
415
+ lines.push("```");
416
+ lines.push(snippet);
417
+ lines.push("```");
418
+ lines.push("");
419
+ }
420
+ lines.push(`**Fix:** ${issue.fix}`);
421
+ lines.push("");
422
+ }
423
+ if (critical.length > 10) {
424
+ lines.push(`*...and ${critical.length - 10} more critical issues*`);
425
+ lines.push("");
426
+ }
427
+ }
428
+ if (serious.length > 0) {
429
+ lines.push("## \u{1F7E0} Serious Issues");
430
+ lines.push("");
431
+ for (const issue of serious.slice(0, 10)) {
432
+ const relPath = relative(process.cwd(), issue.file);
433
+ const location = `\`${basename(relPath)}${issue.line ? ":" + issue.line : ""}\``;
434
+ const desc = issue.issue.replace(/^🕴️\s*/, "").split("\n")[0].slice(0, 60);
435
+ lines.push(`- ${location} - ${desc}`);
436
+ }
437
+ if (serious.length > 10) {
438
+ lines.push(`- *...and ${serious.length - 10} more*`);
439
+ }
440
+ lines.push("");
441
+ }
442
+ const otherIssues = [...moderate, ...low];
443
+ if (otherIssues.length > 0) {
444
+ lines.push("## Other Issues by Category");
445
+ lines.push("");
446
+ const byCategory = /* @__PURE__ */ new Map();
447
+ for (const issue of otherIssues) {
448
+ const cat = issue.category || "general";
449
+ if (!byCategory.has(cat)) byCategory.set(cat, []);
450
+ byCategory.get(cat).push(issue);
451
+ }
452
+ const sorted = Array.from(byCategory.entries()).filter(([cat]) => cat !== "ai-analysis").sort((a, b) => b[1].length - a[1].length).slice(0, 10);
453
+ for (const [category, catIssues] of sorted) {
454
+ const icon = getCategoryIcon(category);
455
+ const sevIcon = getSeverityIcon(catIssues[0]?.severity || "low");
456
+ lines.push(`### ${icon} ${formatCategoryName(category)} ${sevIcon} (${catIssues.length})`);
457
+ const locations = catIssues.slice(0, 5).map((i) => `\`${basename(i.file)}${i.line ? ":" + i.line : ""}\``).join(", ");
458
+ lines.push(locations);
459
+ if (catIssues[0]?.fix) {
460
+ lines.push(`**Fix:** ${catIssues[0].fix}`);
461
+ }
462
+ lines.push("");
463
+ }
464
+ }
465
+ const crossFile = allIssues.filter((i) => i.category === "cross-file");
466
+ if (crossFile.length > 0) {
467
+ lines.push("## \u{1F310} Codebase-Wide Patterns");
468
+ lines.push("");
469
+ lines.push("*Issues appearing across many files - systemic problems:*");
470
+ lines.push("");
471
+ for (const issue of crossFile) {
472
+ lines.push(`- ${issue.issue.replace(/^🕴️\s*/, "").split("\n")[0]}`);
473
+ }
474
+ lines.push("");
475
+ }
476
+ lines.push("---");
477
+ lines.push("");
478
+ if (allIssues.length > 50) {
479
+ lines.push(`*${randomQuote(QUOTES.manyIssues)}*`);
480
+ } else {
481
+ lines.push(`*${randomQuote(QUOTES.fewIssues)}*`);
482
+ }
483
+ return lines.join("\n");
484
+ }
485
+ async function runAgentSmith(args) {
486
+ const startTime = Date.now();
487
+ let filesToScan = args.files || [];
488
+ if (!filesToScan.length) {
489
+ const scanDir = args.directory || process.cwd();
490
+ console.error(`
491
+ \u{1F50D} Agent Smith: Discovering files in: ${scanDir}`);
492
+ filesToScan = await discoverFiles(scanDir);
493
+ console.error(` Found ${filesToScan.length} files
494
+ `);
495
+ } else {
496
+ filesToScan = filesToScan.map(
497
+ (f) => isAbsolute(f) ? f : resolve(process.cwd(), f)
498
+ );
499
+ }
500
+ const validFiles = filesToScan.filter((f) => existsSync(f));
501
+ if (validFiles.length === 0) {
502
+ return {
503
+ content: [{
504
+ type: "text",
505
+ text: "\u274C No valid files found to scan."
506
+ }]
507
+ };
508
+ }
509
+ console.error("\u{1F574}\uFE0F Phase 1: Pattern Detection");
510
+ console.error(" Deploying 38 sub-agent hunters...");
511
+ const smith = new AgentSmithAgent();
512
+ const result = await smith.scan(validFiles, {
513
+ workingDir: args.directory || process.cwd(),
514
+ context: {}
515
+ });
516
+ const patternTime = Date.now() - startTime;
517
+ const patternIssues = result.issues.filter((i) => i.category !== "ai-analysis");
518
+ console.error(` Found ${patternIssues.length} violations in ${(patternTime / 1e3).toFixed(2)}s
519
+ `);
520
+ let aiResult = null;
521
+ let aiTime = 0;
522
+ if (isAIAvailable()) {
523
+ console.error("\u{1F574}\uFE0F Phase 2: AI Deep Analysis");
524
+ console.error(` ${getAIStatusMessage()}`);
525
+ const aiStartTime = Date.now();
526
+ aiResult = await runAIEnhancement(patternIssues, validFiles);
527
+ aiTime = Date.now() - aiStartTime;
528
+ if (aiResult) {
529
+ console.error(` AI validated ${aiResult.aiIssues.filter((i) => i.category === "ai-validated").length} issues`);
530
+ console.error(` AI discovered ${aiResult.aiIssues.filter((i) => i.category === "ai-found").length} new issues`);
531
+ console.error(` AI analysis took ${(aiTime / 1e3).toFixed(2)}s
532
+ `);
533
+ } else {
534
+ console.error(" AI enhancement returned no results\n");
535
+ }
536
+ } else {
537
+ console.error(`
538
+ ${getAIStatusMessage()}`);
539
+ console.error(" Set ANTHROPIC_API_KEY for AI-powered analysis\n");
540
+ }
541
+ const report = await buildReport(patternIssues, aiResult, validFiles, patternTime, aiTime);
542
+ return {
543
+ content: [{
544
+ type: "text",
545
+ text: report
546
+ }]
547
+ };
548
+ }
549
+ export {
550
+ runAgentSmith
551
+ };
552
+ //# sourceMappingURL=agent-smith-runner-3MIO4CWT.js.map