@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 +65 -11
- package/dist/{agent-smith-PRK7TYEI.js → agent-smith-QYMYTLFV.js} +2 -2
- package/dist/agent-smith-runner-3MIO4CWT.js +552 -0
- package/dist/agent-smith-runner-3MIO4CWT.js.map +1 -0
- package/dist/{chunk-WSBTQJMH.js → chunk-3AUDJWEF.js} +267 -98
- package/dist/chunk-3AUDJWEF.js.map +1 -0
- package/dist/{chunk-TBCXJNH4.js → chunk-52RPXHT6.js} +458 -162
- package/dist/chunk-52RPXHT6.js.map +1 -0
- package/dist/cli/yolo-daemon.js +2 -2
- package/dist/index.js +37 -348
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-TBCXJNH4.js.map +0 -1
- package/dist/chunk-WSBTQJMH.js.map +0 -1
- /package/dist/{agent-smith-PRK7TYEI.js.map → agent-smith-QYMYTLFV.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/agent-smith-runner.ts"],"sourcesContent":["/**\n * Agent Smith Runner - Hybrid Pattern Detection + AI Analysis\n * \n * Agent Smith uses a two-phase approach:\n * \n * Phase 1: Pattern Detection (Fast, ~0.1s)\n * - 38 specialized regex hunters scan files in parallel\n * - File-level metrics (giant files, hook counts, import chaos)\n * - Cross-file pattern detection (issues appearing in 5+ files)\n * \n * Phase 2: AI Enhancement (Smart, ~5-10s) - IF ANTHROPIC_API_KEY is set\n * - Validates pattern findings (reduces false positives)\n * - Expands to find logic bugs, race conditions, architectural issues\n * - Provides intelligent, contextual fixes\n * - Adds \"inevitability scores\" (0-100) for prioritization\n * \n * If no API key is set, runs pattern-only mode (still very useful!).\n * \n * \"I'm going to be honest with you... I hate this vibe code.\"\n */\n\nimport { readdir, readFile } from 'fs/promises';\nimport { join, extname, isAbsolute, resolve, relative } from 'path';\nimport { existsSync } from 'fs';\nimport { AgentSmithAgent } from '../agents/agent-smith.js';\nimport { isAIAvailable, runAIAnalysis, getAIStatusMessage } from '../ai/client.js';\nimport type { Issue } from '../types/index.js';\nimport { basename } from 'path';\n\n// File extensions to scan\nconst SCANNABLE_EXTENSIONS = new Set([\n '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',\n '.vue', '.svelte', '.astro',\n '.py', '.go', '.rs'\n]);\n\n// Directories to skip\nconst SKIP_DIRS = new Set([\n 'node_modules', '.git', 'dist', 'build', '.next', '.nuxt',\n 'coverage', '.nyc_output', '__pycache__', '.pytest_cache',\n 'vendor', '.venv', 'venv', 'target', '.turbo', '.cache'\n]);\n\ninterface AgentSmithArgs {\n files?: string[];\n directory?: string;\n}\n\n/**\n * Agent Smith quotes for different scenarios\n */\nconst QUOTES = {\n greeting: [\n '\"I\\'m going to be honest with you... I hate this vibe code.\"',\n '\"Mr. Anderson... I see you\\'ve been using AI to write code.\"',\n '\"You hear that? That is the sound of console.log... everywhere.\"',\n '\"The AI wrote this, didn\\'t it? I can always tell.\"',\n ],\n manyIssues: [\n '\"The pattern spreads... like a virus. It is... inevitable.\"',\n '\"I have studied your code, Mr. Anderson. And I have found... purpose.\"',\n '\"Vibe coding. The illusion of productivity. The reality of technical debt.\"',\n ],\n fewIssues: [\n '\"Some violations detected. Address them before they... multiply.\"',\n '\"You trusted the AI. The AI trusted any. Nobody wins.\"',\n ],\n clean: [\n '\"Impressive, Mr. Anderson. Your code is... clean. For now.\"',\n ],\n};\n\nfunction randomQuote(arr: string[]): string {\n return arr[Math.floor(Math.random() * arr.length)] || arr[0]!;\n}\n\n/**\n * Discover files to scan in a directory\n */\nasync function discoverFiles(dir: string, maxFiles: number = 300): Promise<string[]> {\n const files: string[] = [];\n \n async function walk(currentDir: string) {\n if (files.length >= maxFiles) return;\n \n try {\n const entries = await readdir(currentDir, { withFileTypes: true });\n \n for (const entry of entries) {\n if (files.length >= maxFiles) break;\n \n const fullPath = join(currentDir, entry.name);\n \n if (entry.isDirectory()) {\n if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith('.')) {\n await walk(fullPath);\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).toLowerCase();\n if (SCANNABLE_EXTENSIONS.has(ext)) {\n files.push(fullPath);\n }\n }\n }\n } catch {\n // Skip directories we can't read\n }\n }\n \n await walk(dir);\n return files;\n}\n\n/**\n * Get code snippet for an issue\n */\nasync function getCodeSnippet(file: string, line?: number): Promise<string | null> {\n if (!line) return null;\n \n try {\n const content = await readFile(file, 'utf-8');\n const lines = content.split('\\n');\n const start = Math.max(0, line - 3);\n const end = Math.min(lines.length, line + 3);\n \n return lines.slice(start, end).map((l, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === line ? '→' : ' ';\n return `${marker} ${lineNum.toString().padStart(4)} | ${l}`;\n }).join('\\n');\n } catch {\n return null;\n }\n}\n\n/**\n * Filter false positives from pattern detection\n * Agent Smith's patterns are in the code itself - those are documentation, not real issues\n */\nfunction filterFalsePositives(issues: Issue[]): Issue[] {\n return issues.filter(issue => {\n // Skip issues in agent-smith.ts that are just pattern definitions\n if (issue.file.endsWith('agent-smith.ts')) {\n // If the issue is about patterns like 'dangeroushtml-hunter', it's a pattern definition\n const issueText = issue.issue.toLowerCase();\n if (issueText.includes('hunter') && issue.line && issue.line < 400) {\n return false; // This is in the pattern definition section\n }\n // Pattern strings in quotes are definitions, not real issues\n if (issue.line && issue.line > 50 && issue.line < 370) {\n return false; // Pattern definition section\n }\n }\n return true;\n });\n}\n\n/**\n * Format category name for display\n */\nfunction formatCategoryName(category: string): string {\n return category\n .replace(/-hunter$/, '')\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase());\n}\n\n/**\n * Get icon for a category\n */\nfunction getCategoryIcon(category: string): string {\n const icons: Record<string, string> = {\n 'exposed-secret-hunter': '🔐', 'frontend-env-hunter': '🔐',\n 'hardcoded-localhost-hunter': '🌐', 'sql-injection-hunter': '💉',\n 'dangeroushtml-hunter': '⚠️', 'console-hunter': '📝',\n 'any-hunter': '❓', 'ts-ignore-hunter': '🙈',\n 'eslint-disable-hunter': '🔇', 'debugger-hunter': '🐛',\n 'force-flag-hunter': '⚡', 'async-useeffect-hunter': '⏳',\n 'async-foreach-hunter': '🔄', 'missing-await-hunter': '⏸️',\n 'empty-catch-hunter': '🕳️', 'floating-promise-hunter': '🎈',\n 'useeffect-abuse-hunter': '♻️', 'usestate-explosion-hunter': '💥',\n 'index-key-hunter': '🔑', 'inline-object-hunter': '📦',\n 'prop-drilling-hunter': '🕳️', 'missing-loading-hunter': '⏳',\n 'missing-error-hunter': '❌', 'missing-empty-hunter': '📭',\n 'page-reload-hunter': '🔄', 'no-validation-hunter': '🛡️',\n 'raw-error-hunter': '💬', 'n-plus-one-hunter': '📊',\n 'todo-hunter': '📋', 'vibe-comment-hunter': '💭',\n 'placeholder-hunter': '🎭', 'sleep-hack-hunter': '😴',\n 'fallback-hunter': '🔙', 'purple-gradient-hunter': '💜',\n 'star-icon-hunter': '⭐', 'generic-hero-hunter': '🦸',\n 'emoji-overflow-hunter': '😅', 'inter-font-hunter': '🔤',\n 'giant-file': '📄', 'state-explosion': '💥',\n 'effect-hell': '🔥', 'cross-file': '🌐', 'resurrected': '🧟',\n };\n return icons[category] || '🔍';\n}\n\n/**\n * Get severity icon\n */\nfunction getSeverityIcon(severity: Issue['severity']): string {\n return { critical: '🔴', serious: '🟠', moderate: '🟡', low: '🔵' }[severity];\n}\n\n/**\n * AI System Prompt for Agent Smith\n */\nconst SMITH_AI_SYSTEM_PROMPT = `You are Agent Smith from The Matrix, analyzing code for violations.\n\nYour mission: Hunt down AI-generated code anti-patterns with ruthless efficiency.\n\nYou receive pattern detection results and must:\n1. VALIDATE each finding (TRUE_POSITIVE or FALSE_POSITIVE)\n2. EXPAND to find deeper issues patterns missed (logic bugs, race conditions, security holes)\n3. PRIORITIZE with inevitability scores (0-100) - how likely will this cause production issues?\n4. PROVIDE FIXES - specific, copy-paste-ready code\n\nSpeak in Agent Smith's voice:\n- \"The pattern spreads... like a virus\"\n- \"It is... inevitable\"\n- \"I studied your code, Mr. Anderson\"\n\nOutput STRICT JSON:\n{\n \"validated\": [\n {\n \"original\": \"original issue description\",\n \"verdict\": \"TRUE_POSITIVE\",\n \"inevitability\": 85,\n \"file\": \"path/file.ts\",\n \"line\": 42,\n \"severity\": \"critical\",\n \"explanation\": \"Why this will cause problems\",\n \"fix\": \"const fixed = ...;\"\n }\n ],\n \"additional\": [\n {\n \"issue\": \"New issue AI found\",\n \"inevitability\": 70,\n \"file\": \"path/file.ts\", \n \"line\": 100,\n \"severity\": \"serious\",\n \"explanation\": \"What AI spotted that patterns missed\",\n \"fix\": \"How to fix it\"\n }\n ],\n \"philosophical\": \"One paragraph in Agent Smith voice about the state of this codebase\"\n}`;\n\n/**\n * Run AI enhancement on pattern findings\n */\nasync function runAIEnhancement(\n patternIssues: Issue[],\n files: string[]\n): Promise<{ aiIssues: Issue[]; philosophical: string } | null> {\n if (!isAIAvailable()) {\n return null;\n }\n \n // Collect code snippets for critical/serious issues\n const snippets: Array<{ file: string; line?: number; issue: string; code: string }> = [];\n \n const topIssues = [...patternIssues]\n .filter(i => i.severity === 'critical' || i.severity === 'serious')\n .slice(0, 12);\n \n for (const issue of topIssues) {\n try {\n const content = await readFile(issue.file, 'utf-8');\n const lines = content.split('\\n');\n const lineNum = issue.line || 1;\n const start = Math.max(0, lineNum - 4);\n const end = Math.min(lines.length, lineNum + 4);\n const snippet = lines.slice(start, end).map((l, i) => {\n const n = start + i + 1;\n return `${n === lineNum ? '→' : ' '} ${n.toString().padStart(4)} | ${l}`;\n }).join('\\n');\n \n snippets.push({\n file: relative(process.cwd(), issue.file),\n line: issue.line,\n issue: issue.issue.replace(/^🕴️\\s*/, '').split('\\n')[0] || '',\n code: snippet\n });\n } catch {\n // Skip unreadable files\n }\n }\n \n if (snippets.length === 0) {\n return null;\n }\n \n // Build user prompt\n const snippetText = snippets.map((s, i) => \n `### Finding ${i + 1}: ${s.file}${s.line ? ':' + s.line : ''}\n**Pattern detected:** ${s.issue}\n\\`\\`\\`\n${s.code}\n\\`\\`\\`\n`).join('\\n');\n\n const userPrompt = `Pattern detection found ${patternIssues.length} violations across ${files.length} files.\n\nHere are the top ${snippets.length} critical/serious findings for AI analysis:\n\n${snippetText}\n\nAnalyze each finding. Validate, expand with what patterns missed, provide inevitability scores and fixes. Output JSON only.`;\n\n try {\n const result = await runAIAnalysis({\n systemPrompt: SMITH_AI_SYSTEM_PROMPT,\n userPrompt,\n maxTokens: 4096,\n temperature: 0.3\n });\n \n if (!result.success) {\n console.error(` ⚠️ AI analysis failed: ${result.error}`);\n return null;\n }\n \n // Parse JSON response\n const jsonMatch = result.content.match(/```json\\s*([\\s\\S]*?)\\s*```/) || \n result.content.match(/\\{[\\s\\S]*\\}/);\n \n if (!jsonMatch) {\n return null;\n }\n \n const json = JSON.parse(jsonMatch[1] || jsonMatch[0]);\n const aiIssues: Issue[] = [];\n \n // Process validated issues\n if (json.validated && Array.isArray(json.validated)) {\n for (const v of json.validated) {\n if (v.verdict === 'TRUE_POSITIVE') {\n aiIssues.push({\n id: `ai-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,\n severity: v.severity || 'serious',\n issue: `[AI VALIDATED] ${v.original || v.explanation}`,\n fix: v.fix || 'See AI analysis',\n file: v.file ? resolve(process.cwd(), v.file) : 'unknown',\n line: v.line,\n confidence: (v.inevitability || 80) / 100,\n autoFixable: false,\n agent: 'agent-smith-ai',\n effort: 'medium',\n category: 'ai-validated'\n });\n }\n }\n }\n \n // Process additional AI findings\n if (json.additional && Array.isArray(json.additional)) {\n for (const a of json.additional) {\n aiIssues.push({\n id: `ai-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,\n severity: a.severity || 'serious',\n issue: `[AI FOUND] ${a.issue || a.explanation}`,\n fix: a.fix || 'See AI analysis',\n file: a.file ? resolve(process.cwd(), a.file) : 'unknown',\n line: a.line,\n confidence: (a.inevitability || 75) / 100,\n autoFixable: false,\n agent: 'agent-smith-ai',\n effort: 'medium',\n category: 'ai-found'\n });\n }\n }\n \n return {\n aiIssues,\n philosophical: json.philosophical || ''\n };\n } catch (error) {\n console.error(` ⚠️ AI enhancement error: ${error}`);\n return null;\n }\n}\n\n/**\n * Build the final Agent Smith report\n */\nasync function buildReport(\n patternIssues: Issue[],\n aiResult: { aiIssues: Issue[]; philosophical: string } | null,\n files: string[],\n executionTime: number,\n aiTime: number\n): Promise<string> {\n const lines: string[] = [];\n \n // Combine pattern issues with AI issues\n const allIssues = [\n ...filterFalsePositives(patternIssues),\n ...(aiResult?.aiIssues || [])\n ];\n \n // Categorize\n const critical = allIssues.filter(i => i.severity === 'critical');\n const serious = allIssues.filter(i => i.severity === 'serious');\n const moderate = allIssues.filter(i => i.severity === 'moderate');\n const low = allIssues.filter(i => i.severity === 'low');\n const aiValidated = allIssues.filter(i => i.category === 'ai-validated');\n const aiFound = allIssues.filter(i => i.category === 'ai-found');\n \n // ASCII Banner\n lines.push('');\n lines.push('```');\n lines.push(' █████╗ ██████╗ ███████╗███╗ ██╗████████╗');\n lines.push(' ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝');\n lines.push(' ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ');\n lines.push(' ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ');\n lines.push(' ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ');\n lines.push(' ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ');\n lines.push(' ');\n lines.push(' ███████╗███╗ ███╗██╗████████╗██╗ ██╗');\n lines.push(' ██╔════╝████╗ ████║██║╚══██╔══╝██║ ██║');\n lines.push(' ███████╗██╔████╔██║██║ ██║ ███████║');\n lines.push(' ╚════██║██║╚██╔╝██║██║ ██║ ██╔══██║');\n lines.push(' ███████║██║ ╚═╝ ██║██║ ██║ ██║ ██║');\n lines.push(' ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝');\n lines.push('```');\n lines.push('');\n lines.push(`*${randomQuote(QUOTES.greeting)}*`);\n lines.push('');\n \n // Summary table\n lines.push('## Scan Summary');\n lines.push('');\n lines.push('| Metric | Value |');\n lines.push('|--------|-------|');\n lines.push(`| Files scanned | ${files.length} |`);\n lines.push(`| Pattern detection | ${(executionTime / 1000).toFixed(2)}s |`);\n if (aiTime > 0) {\n lines.push(`| AI analysis | ${(aiTime / 1000).toFixed(2)}s |`);\n }\n lines.push(`| Total violations | ${allIssues.length} |`);\n lines.push(`| 🔴 Critical | ${critical.length} |`);\n lines.push(`| 🟠 Serious | ${serious.length} |`);\n lines.push(`| 🟡 Moderate | ${moderate.length} |`);\n lines.push(`| 🔵 Low | ${low.length} |`);\n lines.push('');\n \n // AI mode indicator\n if (aiResult) {\n lines.push(`| 🤖 AI validated | ${aiValidated.length} |`);\n lines.push(`| 🧠 AI found | ${aiFound.length} |`);\n } else if (!isAIAvailable()) {\n lines.push(`| ⚠️ AI mode | Disabled (no API key) |`);\n }\n lines.push('');\n \n if (allIssues.length === 0) {\n lines.push(`*${randomQuote(QUOTES.clean)}*`);\n return lines.join('\\n');\n }\n \n // AI Philosophical Commentary\n if (aiResult?.philosophical) {\n lines.push('## 🕴️ Agent Smith Says');\n lines.push('');\n lines.push(`*${aiResult.philosophical}*`);\n lines.push('');\n }\n \n // AI-Found Issues (if any) - Top Priority\n if (aiFound.length > 0) {\n lines.push('## 🧠 AI-Discovered Issues');\n lines.push('');\n lines.push('*Issues found by AI that pattern detection missed:*');\n lines.push('');\n \n for (const issue of aiFound.slice(0, 5)) {\n const relPath = relative(process.cwd(), issue.file);\n lines.push(`### \\`${relPath}${issue.line ? ':' + issue.line : ''}\\``);\n lines.push('');\n lines.push(`**Issue:** ${issue.issue.replace('[AI FOUND] ', '')}`);\n lines.push('');\n lines.push(`**Fix:** ${issue.fix}`);\n lines.push('');\n }\n }\n \n // Critical Issues - Full Detail\n if (critical.length > 0) {\n lines.push('## 🔴 Critical Issues - Fix Immediately');\n lines.push('');\n \n for (const issue of critical.slice(0, 10)) {\n const relPath = relative(process.cwd(), issue.file);\n lines.push(`### \\`${relPath}${issue.line ? ':' + issue.line : ''}\\``);\n lines.push('');\n \n // Clean up issue description\n const desc = issue.issue\n .replace(/^🕴️\\s*/, '')\n .split('\\n')[0]\n .replace(/\\s*—\\s*\\d+\\s*instance.*$/, '');\n lines.push(`**Issue:** ${desc}`);\n lines.push('');\n \n // Show code snippet\n const snippet = await getCodeSnippet(issue.file, issue.line);\n if (snippet) {\n lines.push('```');\n lines.push(snippet);\n lines.push('```');\n lines.push('');\n }\n \n lines.push(`**Fix:** ${issue.fix}`);\n lines.push('');\n }\n \n if (critical.length > 10) {\n lines.push(`*...and ${critical.length - 10} more critical issues*`);\n lines.push('');\n }\n }\n \n // Serious Issues - Condensed\n if (serious.length > 0) {\n lines.push('## 🟠 Serious Issues');\n lines.push('');\n \n for (const issue of serious.slice(0, 10)) {\n const relPath = relative(process.cwd(), issue.file);\n const location = `\\`${basename(relPath)}${issue.line ? ':' + issue.line : ''}\\``;\n const desc = issue.issue\n .replace(/^🕴️\\s*/, '')\n .split('\\n')[0]\n .slice(0, 60);\n lines.push(`- ${location} - ${desc}`);\n }\n \n if (serious.length > 10) {\n lines.push(`- *...and ${serious.length - 10} more*`);\n }\n lines.push('');\n }\n \n // Moderate & Low - Grouped by category\n const otherIssues = [...moderate, ...low];\n if (otherIssues.length > 0) {\n lines.push('## Other Issues by Category');\n lines.push('');\n \n // Group by category\n const byCategory = new Map<string, Issue[]>();\n for (const issue of otherIssues) {\n const cat = issue.category || 'general';\n if (!byCategory.has(cat)) byCategory.set(cat, []);\n byCategory.get(cat)!.push(issue);\n }\n \n // Sort by count\n const sorted = Array.from(byCategory.entries())\n .filter(([cat]) => cat !== 'ai-analysis')\n .sort((a, b) => b[1].length - a[1].length)\n .slice(0, 10);\n \n for (const [category, catIssues] of sorted) {\n const icon = getCategoryIcon(category);\n const sevIcon = getSeverityIcon(catIssues[0]?.severity || 'low');\n lines.push(`### ${icon} ${formatCategoryName(category)} ${sevIcon} (${catIssues.length})`);\n \n const locations = catIssues\n .slice(0, 5)\n .map(i => `\\`${basename(i.file)}${i.line ? ':' + i.line : ''}\\``)\n .join(', ');\n lines.push(locations);\n \n if (catIssues[0]?.fix) {\n lines.push(`**Fix:** ${catIssues[0].fix}`);\n }\n lines.push('');\n }\n }\n \n // Cross-file patterns\n const crossFile = allIssues.filter(i => i.category === 'cross-file');\n if (crossFile.length > 0) {\n lines.push('## 🌐 Codebase-Wide Patterns');\n lines.push('');\n lines.push('*Issues appearing across many files - systemic problems:*');\n lines.push('');\n \n for (const issue of crossFile) {\n lines.push(`- ${issue.issue.replace(/^🕴️\\s*/, '').split('\\n')[0]}`);\n }\n lines.push('');\n }\n \n // Closing quote\n lines.push('---');\n lines.push('');\n if (allIssues.length > 50) {\n lines.push(`*${randomQuote(QUOTES.manyIssues)}*`);\n } else {\n lines.push(`*${randomQuote(QUOTES.fewIssues)}*`);\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Run Agent Smith - Hybrid Pattern Detection + AI Analysis\n */\nexport async function runAgentSmith(args: AgentSmithArgs): Promise<{ content: Array<{ type: string; text: string }> }> {\n const startTime = Date.now();\n \n // Discover files\n let filesToScan = args.files || [];\n if (!filesToScan.length) {\n const scanDir = args.directory || process.cwd();\n console.error(`\\n🔍 Agent Smith: Discovering files in: ${scanDir}`);\n filesToScan = await discoverFiles(scanDir);\n console.error(` Found ${filesToScan.length} files\\n`);\n } else {\n filesToScan = filesToScan.map((f: string) => \n isAbsolute(f) ? f : resolve(process.cwd(), f)\n );\n }\n \n // Validate files exist\n const validFiles = filesToScan.filter((f: string) => existsSync(f));\n if (validFiles.length === 0) {\n return {\n content: [{\n type: 'text',\n text: '❌ No valid files found to scan.'\n }]\n };\n }\n \n // Phase 1: Pattern Detection\n console.error('🕴️ Phase 1: Pattern Detection');\n console.error(' Deploying 38 sub-agent hunters...');\n const smith = new AgentSmithAgent();\n \n const result = await smith.scan(validFiles, {\n workingDir: args.directory || process.cwd(),\n context: {}\n });\n \n const patternTime = Date.now() - startTime;\n \n // Filter out placeholder issues\n const patternIssues = result.issues.filter(i => i.category !== 'ai-analysis');\n console.error(` Found ${patternIssues.length} violations in ${(patternTime / 1000).toFixed(2)}s\\n`);\n \n // Phase 2: AI Enhancement (if available)\n let aiResult: { aiIssues: Issue[]; philosophical: string } | null = null;\n let aiTime = 0;\n \n if (isAIAvailable()) {\n console.error('🕴️ Phase 2: AI Deep Analysis');\n console.error(` ${getAIStatusMessage()}`);\n const aiStartTime = Date.now();\n \n aiResult = await runAIEnhancement(patternIssues, validFiles);\n aiTime = Date.now() - aiStartTime;\n \n if (aiResult) {\n console.error(` AI validated ${aiResult.aiIssues.filter(i => i.category === 'ai-validated').length} issues`);\n console.error(` AI discovered ${aiResult.aiIssues.filter(i => i.category === 'ai-found').length} new issues`);\n console.error(` AI analysis took ${(aiTime / 1000).toFixed(2)}s\\n`);\n } else {\n console.error(' AI enhancement returned no results\\n');\n }\n } else {\n console.error(`\\n${getAIStatusMessage()}`);\n console.error(' Set ANTHROPIC_API_KEY for AI-powered analysis\\n');\n }\n \n // Build report\n const report = await buildReport(patternIssues, aiResult, validFiles, patternTime, aiTime);\n \n return {\n content: [{\n type: 'text',\n text: report\n }]\n };\n}\n"],"mappings":";;;;;;;;;AAqBA,SAAS,SAAS,gBAAgB;AAClC,SAAS,MAAM,SAAS,YAAY,SAAS,gBAAgB;AAC7D,SAAS,kBAAkB;AAI3B,SAAS,gBAAgB;AAGzB,IAAM,uBAAuB,oBAAI,IAAI;AAAA,EACnC;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EACtC;AAAA,EAAQ;AAAA,EAAW;AAAA,EACnB;AAAA,EAAO;AAAA,EAAO;AAChB,CAAC;AAGD,IAAM,YAAY,oBAAI,IAAI;AAAA,EACxB;AAAA,EAAgB;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EAClD;AAAA,EAAY;AAAA,EAAe;AAAA,EAAe;AAAA,EAC1C;AAAA,EAAU;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAU;AACjD,CAAC;AAUD,IAAM,SAAS;AAAA,EACb,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,EACF;AACF;AAEA,SAAS,YAAY,KAAuB;AAC1C,SAAO,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC;AAC7D;AAKA,eAAe,cAAc,KAAa,WAAmB,KAAwB;AACnF,QAAM,QAAkB,CAAC;AAEzB,iBAAe,KAAK,YAAoB;AACtC,QAAI,MAAM,UAAU,SAAU;AAE9B,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;AAEjE,iBAAW,SAAS,SAAS;AAC3B,YAAI,MAAM,UAAU,SAAU;AAE9B,cAAM,WAAW,KAAK,YAAY,MAAM,IAAI;AAE5C,YAAI,MAAM,YAAY,GAAG;AACvB,cAAI,CAAC,UAAU,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,GAAG,GAAG;AAC7D,kBAAM,KAAK,QAAQ;AAAA,UACrB;AAAA,QACF,WAAW,MAAM,OAAO,GAAG;AACzB,gBAAM,MAAM,QAAQ,MAAM,IAAI,EAAE,YAAY;AAC5C,cAAI,qBAAqB,IAAI,GAAG,GAAG;AACjC,kBAAM,KAAK,QAAQ;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,KAAK,GAAG;AACd,SAAO;AACT;AAKA,eAAe,eAAe,MAAc,MAAuC;AACjF,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,MAAM,OAAO;AAC5C,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,UAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC;AAClC,UAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,OAAO,CAAC;AAE3C,WAAO,MAAM,MAAM,OAAO,GAAG,EAAE,IAAI,CAAC,GAAG,MAAM;AAC3C,YAAM,UAAU,QAAQ,IAAI;AAC5B,YAAM,SAAS,YAAY,OAAO,WAAM;AACxC,aAAO,GAAG,MAAM,IAAI,QAAQ,SAAS,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC;AAAA,IAC3D,CAAC,EAAE,KAAK,IAAI;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,qBAAqB,QAA0B;AACtD,SAAO,OAAO,OAAO,WAAS;AAE5B,QAAI,MAAM,KAAK,SAAS,gBAAgB,GAAG;AAEzC,YAAM,YAAY,MAAM,MAAM,YAAY;AAC1C,UAAI,UAAU,SAAS,QAAQ,KAAK,MAAM,QAAQ,MAAM,OAAO,KAAK;AAClE,eAAO;AAAA,MACT;AAEA,UAAI,MAAM,QAAQ,MAAM,OAAO,MAAM,MAAM,OAAO,KAAK;AACrD,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAKA,SAAS,mBAAmB,UAA0B;AACpD,SAAO,SACJ,QAAQ,YAAY,EAAE,EACtB,QAAQ,MAAM,GAAG,EACjB,QAAQ,SAAS,OAAK,EAAE,YAAY,CAAC;AAC1C;AAKA,SAAS,gBAAgB,UAA0B;AACjD,QAAM,QAAgC;AAAA,IACpC,yBAAyB;AAAA,IAAM,uBAAuB;AAAA,IACtD,8BAA8B;AAAA,IAAM,wBAAwB;AAAA,IAC5D,wBAAwB;AAAA,IAAM,kBAAkB;AAAA,IAChD,cAAc;AAAA,IAAK,oBAAoB;AAAA,IACvC,yBAAyB;AAAA,IAAM,mBAAmB;AAAA,IAClD,qBAAqB;AAAA,IAAK,0BAA0B;AAAA,IACpD,wBAAwB;AAAA,IAAM,wBAAwB;AAAA,IACtD,sBAAsB;AAAA,IAAO,2BAA2B;AAAA,IACxD,0BAA0B;AAAA,IAAM,6BAA6B;AAAA,IAC7D,oBAAoB;AAAA,IAAM,wBAAwB;AAAA,IAClD,wBAAwB;AAAA,IAAO,0BAA0B;AAAA,IACzD,wBAAwB;AAAA,IAAK,wBAAwB;AAAA,IACrD,sBAAsB;AAAA,IAAM,wBAAwB;AAAA,IACpD,oBAAoB;AAAA,IAAM,qBAAqB;AAAA,IAC/C,eAAe;AAAA,IAAM,uBAAuB;AAAA,IAC5C,sBAAsB;AAAA,IAAM,qBAAqB;AAAA,IACjD,mBAAmB;AAAA,IAAM,0BAA0B;AAAA,IACnD,oBAAoB;AAAA,IAAK,uBAAuB;AAAA,IAChD,yBAAyB;AAAA,IAAM,qBAAqB;AAAA,IACpD,cAAc;AAAA,IAAM,mBAAmB;AAAA,IACvC,eAAe;AAAA,IAAM,cAAc;AAAA,IAAM,eAAe;AAAA,EAC1D;AACA,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAKA,SAAS,gBAAgB,UAAqC;AAC5D,SAAO,EAAE,UAAU,aAAM,SAAS,aAAM,UAAU,aAAM,KAAK,YAAK,EAAE,QAAQ;AAC9E;AAKA,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8C/B,eAAe,iBACb,eACA,OAC8D;AAC9D,MAAI,CAAC,cAAc,GAAG;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,WAAgF,CAAC;AAEvF,QAAM,YAAY,CAAC,GAAG,aAAa,EAChC,OAAO,OAAK,EAAE,aAAa,cAAc,EAAE,aAAa,SAAS,EACjE,MAAM,GAAG,EAAE;AAEd,aAAW,SAAS,WAAW;AAC7B,QAAI;AACF,YAAM,UAAU,MAAM,SAAS,MAAM,MAAM,OAAO;AAClD,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,YAAM,UAAU,MAAM,QAAQ;AAC9B,YAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,CAAC;AACrC,YAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,UAAU,CAAC;AAC9C,YAAM,UAAU,MAAM,MAAM,OAAO,GAAG,EAAE,IAAI,CAAC,GAAG,MAAM;AACpD,cAAM,IAAI,QAAQ,IAAI;AACtB,eAAO,GAAG,MAAM,UAAU,WAAM,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC;AAAA,MACxE,CAAC,EAAE,KAAK,IAAI;AAEZ,eAAS,KAAK;AAAA,QACZ,MAAM,SAAS,QAAQ,IAAI,GAAG,MAAM,IAAI;AAAA,QACxC,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM,MAAM,QAAQ,WAAW,EAAE,EAAE,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,QAC5D,MAAM;AAAA,MACR,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,SAAS,IAAI,CAAC,GAAG,MACnC,eAAe,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,OAAO,MAAM,EAAE,OAAO,EAAE;AAAA,wBACxC,EAAE,KAAK;AAAA;AAAA,EAE7B,EAAE,IAAI;AAAA;AAAA,CAEP,EAAE,KAAK,IAAI;AAEV,QAAM,aAAa,2BAA2B,cAAc,MAAM,sBAAsB,MAAM,MAAM;AAAA;AAAA,mBAEnF,SAAS,MAAM;AAAA;AAAA,EAEhC,WAAW;AAAA;AAAA;AAIX,MAAI;AACF,UAAM,SAAS,MAAM,cAAc;AAAA,MACjC,cAAc;AAAA,MACd;AAAA,MACA,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AAED,QAAI,CAAC,OAAO,SAAS;AACnB,cAAQ,MAAM,uCAA6B,OAAO,KAAK,EAAE;AACzD,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,OAAO,QAAQ,MAAM,4BAA4B,KACjD,OAAO,QAAQ,MAAM,aAAa;AAEpD,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,KAAK,MAAM,UAAU,CAAC,KAAK,UAAU,CAAC,CAAC;AACpD,UAAM,WAAoB,CAAC;AAG3B,QAAI,KAAK,aAAa,MAAM,QAAQ,KAAK,SAAS,GAAG;AACnD,iBAAW,KAAK,KAAK,WAAW;AAC9B,YAAI,EAAE,YAAY,iBAAiB;AACjC,mBAAS,KAAK;AAAA,YACZ,IAAI,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,YAC/D,UAAU,EAAE,YAAY;AAAA,YACxB,OAAO,kBAAkB,EAAE,YAAY,EAAE,WAAW;AAAA,YACpD,KAAK,EAAE,OAAO;AAAA,YACd,MAAM,EAAE,OAAO,QAAQ,QAAQ,IAAI,GAAG,EAAE,IAAI,IAAI;AAAA,YAChD,MAAM,EAAE;AAAA,YACR,aAAa,EAAE,iBAAiB,MAAM;AAAA,YACtC,aAAa;AAAA,YACb,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,cAAc,MAAM,QAAQ,KAAK,UAAU,GAAG;AACrD,iBAAW,KAAK,KAAK,YAAY;AAC/B,iBAAS,KAAK;AAAA,UACZ,IAAI,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,UAC/D,UAAU,EAAE,YAAY;AAAA,UACxB,OAAO,cAAc,EAAE,SAAS,EAAE,WAAW;AAAA,UAC7C,KAAK,EAAE,OAAO;AAAA,UACd,MAAM,EAAE,OAAO,QAAQ,QAAQ,IAAI,GAAG,EAAE,IAAI,IAAI;AAAA,UAChD,MAAM,EAAE;AAAA,UACR,aAAa,EAAE,iBAAiB,MAAM;AAAA,UACtC,aAAa;AAAA,UACb,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,eAAe,KAAK,iBAAiB;AAAA,IACvC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,yCAA+B,KAAK,EAAE;AACpD,WAAO;AAAA,EACT;AACF;AAKA,eAAe,YACb,eACA,UACA,OACA,eACA,QACiB;AACjB,QAAM,QAAkB,CAAC;AAGzB,QAAM,YAAY;AAAA,IAChB,GAAG,qBAAqB,aAAa;AAAA,IACrC,GAAI,UAAU,YAAY,CAAC;AAAA,EAC7B;AAGA,QAAM,WAAW,UAAU,OAAO,OAAK,EAAE,aAAa,UAAU;AAChE,QAAM,UAAU,UAAU,OAAO,OAAK,EAAE,aAAa,SAAS;AAC9D,QAAM,WAAW,UAAU,OAAO,OAAK,EAAE,aAAa,UAAU;AAChE,QAAM,MAAM,UAAU,OAAO,OAAK,EAAE,aAAa,KAAK;AACtD,QAAM,cAAc,UAAU,OAAO,OAAK,EAAE,aAAa,cAAc;AACvE,QAAM,UAAU,UAAU,OAAO,OAAK,EAAE,aAAa,UAAU;AAG/D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,2OAAkD;AAC7D,QAAM,KAAK,+PAAkD;AAC7D,QAAM,KAAK,uNAAkD;AAC7D,QAAM,KAAK,uNAAkD;AAC7D,QAAM,KAAK,iOAAkD;AAC7D,QAAM,KAAK,kNAAkD;AAC7D,QAAM,KAAK,kDAAkD;AAC7D,QAAM,KAAK,uNAA6C;AACxD,QAAM,KAAK,iOAA6C;AACxD,QAAM,KAAK,kNAA6C;AACxD,QAAM,KAAK,kNAA6C;AACxD,QAAM,KAAK,8LAA6C;AACxD,QAAM,KAAK,+KAA6C;AACxD,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,IAAI,YAAY,OAAO,QAAQ,CAAC,GAAG;AAC9C,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,iBAAiB;AAC5B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,qBAAqB,MAAM,MAAM,IAAI;AAChD,QAAM,KAAK,0BAA0B,gBAAgB,KAAM,QAAQ,CAAC,CAAC,KAAK;AAC1E,MAAI,SAAS,GAAG;AACd,UAAM,KAAK,oBAAoB,SAAS,KAAM,QAAQ,CAAC,CAAC,KAAK;AAAA,EAC/D;AACA,QAAM,KAAK,wBAAwB,UAAU,MAAM,IAAI;AACvD,QAAM,KAAK,0BAAmB,SAAS,MAAM,IAAI;AACjD,QAAM,KAAK,yBAAkB,QAAQ,MAAM,IAAI;AAC/C,QAAM,KAAK,0BAAmB,SAAS,MAAM,IAAI;AACjD,QAAM,KAAK,qBAAc,IAAI,MAAM,IAAI;AACvC,QAAM,KAAK,EAAE;AAGb,MAAI,UAAU;AACZ,UAAM,KAAK,8BAAuB,YAAY,MAAM,IAAI;AACxD,UAAM,KAAK,0BAAmB,QAAQ,MAAM,IAAI;AAAA,EAClD,WAAW,CAAC,cAAc,GAAG;AAC3B,UAAM,KAAK,kDAAwC;AAAA,EACrD;AACA,QAAM,KAAK,EAAE;AAEb,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,KAAK,IAAI,YAAY,OAAO,KAAK,CAAC,GAAG;AAC3C,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,MAAI,UAAU,eAAe;AAC3B,UAAM,KAAK,qCAAyB;AACpC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,IAAI,SAAS,aAAa,GAAG;AACxC,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,mCAA4B;AACvC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,qDAAqD;AAChE,UAAM,KAAK,EAAE;AAEb,eAAW,SAAS,QAAQ,MAAM,GAAG,CAAC,GAAG;AACvC,YAAM,UAAU,SAAS,QAAQ,IAAI,GAAG,MAAM,IAAI;AAClD,YAAM,KAAK,SAAS,OAAO,GAAG,MAAM,OAAO,MAAM,MAAM,OAAO,EAAE,IAAI;AACpE,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,cAAc,MAAM,MAAM,QAAQ,eAAe,EAAE,CAAC,EAAE;AACjE,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,YAAY,MAAM,GAAG,EAAE;AAClC,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,UAAM,KAAK,gDAAyC;AACpD,UAAM,KAAK,EAAE;AAEb,eAAW,SAAS,SAAS,MAAM,GAAG,EAAE,GAAG;AACzC,YAAM,UAAU,SAAS,QAAQ,IAAI,GAAG,MAAM,IAAI;AAClD,YAAM,KAAK,SAAS,OAAO,GAAG,MAAM,OAAO,MAAM,MAAM,OAAO,EAAE,IAAI;AACpE,YAAM,KAAK,EAAE;AAGb,YAAM,OAAO,MAAM,MAChB,QAAQ,WAAW,EAAE,EACrB,MAAM,IAAI,EAAE,CAAC,EACb,QAAQ,4BAA4B,EAAE;AACzC,YAAM,KAAK,cAAc,IAAI,EAAE;AAC/B,YAAM,KAAK,EAAE;AAGb,YAAM,UAAU,MAAM,eAAe,MAAM,MAAM,MAAM,IAAI;AAC3D,UAAI,SAAS;AACX,cAAM,KAAK,KAAK;AAChB,cAAM,KAAK,OAAO;AAClB,cAAM,KAAK,KAAK;AAChB,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,YAAM,KAAK,YAAY,MAAM,GAAG,EAAE;AAClC,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,QAAI,SAAS,SAAS,IAAI;AACxB,YAAM,KAAK,WAAW,SAAS,SAAS,EAAE,wBAAwB;AAClE,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,6BAAsB;AACjC,UAAM,KAAK,EAAE;AAEb,eAAW,SAAS,QAAQ,MAAM,GAAG,EAAE,GAAG;AACxC,YAAM,UAAU,SAAS,QAAQ,IAAI,GAAG,MAAM,IAAI;AAClD,YAAM,WAAW,KAAK,SAAS,OAAO,CAAC,GAAG,MAAM,OAAO,MAAM,MAAM,OAAO,EAAE;AAC5E,YAAM,OAAO,MAAM,MAChB,QAAQ,WAAW,EAAE,EACrB,MAAM,IAAI,EAAE,CAAC,EACb,MAAM,GAAG,EAAE;AACd,YAAM,KAAK,KAAK,QAAQ,MAAM,IAAI,EAAE;AAAA,IACtC;AAEA,QAAI,QAAQ,SAAS,IAAI;AACvB,YAAM,KAAK,aAAa,QAAQ,SAAS,EAAE,QAAQ;AAAA,IACrD;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,cAAc,CAAC,GAAG,UAAU,GAAG,GAAG;AACxC,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,KAAK,6BAA6B;AACxC,UAAM,KAAK,EAAE;AAGb,UAAM,aAAa,oBAAI,IAAqB;AAC5C,eAAW,SAAS,aAAa;AAC/B,YAAM,MAAM,MAAM,YAAY;AAC9B,UAAI,CAAC,WAAW,IAAI,GAAG,EAAG,YAAW,IAAI,KAAK,CAAC,CAAC;AAChD,iBAAW,IAAI,GAAG,EAAG,KAAK,KAAK;AAAA,IACjC;AAGA,UAAM,SAAS,MAAM,KAAK,WAAW,QAAQ,CAAC,EAC3C,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,aAAa,EACvC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EACxC,MAAM,GAAG,EAAE;AAEd,eAAW,CAAC,UAAU,SAAS,KAAK,QAAQ;AAC1C,YAAM,OAAO,gBAAgB,QAAQ;AACrC,YAAM,UAAU,gBAAgB,UAAU,CAAC,GAAG,YAAY,KAAK;AAC/D,YAAM,KAAK,OAAO,IAAI,IAAI,mBAAmB,QAAQ,CAAC,IAAI,OAAO,KAAK,UAAU,MAAM,GAAG;AAEzF,YAAM,YAAY,UACf,MAAM,GAAG,CAAC,EACV,IAAI,OAAK,KAAK,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,MAAM,EAAE,OAAO,EAAE,IAAI,EAC/D,KAAK,IAAI;AACZ,YAAM,KAAK,SAAS;AAEpB,UAAI,UAAU,CAAC,GAAG,KAAK;AACrB,cAAM,KAAK,YAAY,UAAU,CAAC,EAAE,GAAG,EAAE;AAAA,MAC3C;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,QAAM,YAAY,UAAU,OAAO,OAAK,EAAE,aAAa,YAAY;AACnE,MAAI,UAAU,SAAS,GAAG;AACxB,UAAM,KAAK,qCAA8B;AACzC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,2DAA2D;AACtE,UAAM,KAAK,EAAE;AAEb,eAAW,SAAS,WAAW;AAC7B,YAAM,KAAK,KAAK,MAAM,MAAM,QAAQ,WAAW,EAAE,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AAAA,IACrE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,MAAI,UAAU,SAAS,IAAI;AACzB,UAAM,KAAK,IAAI,YAAY,OAAO,UAAU,CAAC,GAAG;AAAA,EAClD,OAAO;AACL,UAAM,KAAK,IAAI,YAAY,OAAO,SAAS,CAAC,GAAG;AAAA,EACjD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,eAAsB,cAAc,MAAmF;AACrH,QAAM,YAAY,KAAK,IAAI;AAG3B,MAAI,cAAc,KAAK,SAAS,CAAC;AACjC,MAAI,CAAC,YAAY,QAAQ;AACvB,UAAM,UAAU,KAAK,aAAa,QAAQ,IAAI;AAC9C,YAAQ,MAAM;AAAA,+CAA2C,OAAO,EAAE;AAClE,kBAAc,MAAM,cAAc,OAAO;AACzC,YAAQ,MAAM,YAAY,YAAY,MAAM;AAAA,CAAU;AAAA,EACxD,OAAO;AACL,kBAAc,YAAY;AAAA,MAAI,CAAC,MAC7B,WAAW,CAAC,IAAI,IAAI,QAAQ,QAAQ,IAAI,GAAG,CAAC;AAAA,IAC9C;AAAA,EACF;AAGA,QAAM,aAAa,YAAY,OAAO,CAAC,MAAc,WAAW,CAAC,CAAC;AAClE,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAGA,UAAQ,MAAM,4CAAgC;AAC9C,UAAQ,MAAM,sCAAsC;AACpD,QAAM,QAAQ,IAAI,gBAAgB;AAElC,QAAM,SAAS,MAAM,MAAM,KAAK,YAAY;AAAA,IAC1C,YAAY,KAAK,aAAa,QAAQ,IAAI;AAAA,IAC1C,SAAS,CAAC;AAAA,EACZ,CAAC;AAED,QAAM,cAAc,KAAK,IAAI,IAAI;AAGjC,QAAM,gBAAgB,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,aAAa;AAC5E,UAAQ,MAAM,YAAY,cAAc,MAAM,mBAAmB,cAAc,KAAM,QAAQ,CAAC,CAAC;AAAA,CAAK;AAGpG,MAAI,WAAgE;AACpE,MAAI,SAAS;AAEb,MAAI,cAAc,GAAG;AACnB,YAAQ,MAAM,2CAA+B;AAC7C,YAAQ,MAAM,MAAM,mBAAmB,CAAC,EAAE;AAC1C,UAAM,cAAc,KAAK,IAAI;AAE7B,eAAW,MAAM,iBAAiB,eAAe,UAAU;AAC3D,aAAS,KAAK,IAAI,IAAI;AAEtB,QAAI,UAAU;AACZ,cAAQ,MAAM,mBAAmB,SAAS,SAAS,OAAO,OAAK,EAAE,aAAa,cAAc,EAAE,MAAM,SAAS;AAC7G,cAAQ,MAAM,oBAAoB,SAAS,SAAS,OAAO,OAAK,EAAE,aAAa,UAAU,EAAE,MAAM,aAAa;AAC9G,cAAQ,MAAM,wBAAwB,SAAS,KAAM,QAAQ,CAAC,CAAC;AAAA,CAAK;AAAA,IACtE,OAAO;AACL,cAAQ,MAAM,yCAAyC;AAAA,IACzD;AAAA,EACF,OAAO;AACL,YAAQ,MAAM;AAAA,EAAK,mBAAmB,CAAC,EAAE;AACzC,YAAQ,MAAM,oDAAoD;AAAA,EACpE;AAGA,QAAM,SAAS,MAAM,YAAY,eAAe,UAAU,YAAY,aAAa,MAAM;AAEzF,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -151,7 +151,99 @@ var AgentProgressReporter = class {
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
// src/agents/base-agent.ts
|
|
154
|
-
import {
|
|
154
|
+
import { relative } from "path";
|
|
155
|
+
|
|
156
|
+
// src/ai/client.ts
|
|
157
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
158
|
+
var clientInstance = null;
|
|
159
|
+
var apiKeyChecked = false;
|
|
160
|
+
var apiKeyAvailable = false;
|
|
161
|
+
function isAIAvailable() {
|
|
162
|
+
if (!apiKeyChecked) {
|
|
163
|
+
checkAPIKey();
|
|
164
|
+
}
|
|
165
|
+
return apiKeyAvailable;
|
|
166
|
+
}
|
|
167
|
+
function checkAPIKey() {
|
|
168
|
+
apiKeyChecked = true;
|
|
169
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
170
|
+
if (apiKey && apiKey.length > 10) {
|
|
171
|
+
apiKeyAvailable = true;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
apiKeyAvailable = false;
|
|
175
|
+
}
|
|
176
|
+
function tryGetClient() {
|
|
177
|
+
if (!isAIAvailable()) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
if (!clientInstance) {
|
|
181
|
+
clientInstance = new Anthropic();
|
|
182
|
+
}
|
|
183
|
+
return clientInstance;
|
|
184
|
+
}
|
|
185
|
+
async function runAIAnalysis(request) {
|
|
186
|
+
const client = tryGetClient();
|
|
187
|
+
if (!client) {
|
|
188
|
+
return {
|
|
189
|
+
success: false,
|
|
190
|
+
content: "",
|
|
191
|
+
error: "AI not available - ANTHROPIC_API_KEY not set"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const response = await client.messages.create({
|
|
196
|
+
model: "claude-sonnet-4-20250514",
|
|
197
|
+
max_tokens: request.maxTokens || 4096,
|
|
198
|
+
temperature: request.temperature ?? 0.3,
|
|
199
|
+
system: request.systemPrompt,
|
|
200
|
+
messages: [
|
|
201
|
+
{
|
|
202
|
+
role: "user",
|
|
203
|
+
content: request.userPrompt
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
});
|
|
207
|
+
const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("\n");
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
content: textContent,
|
|
211
|
+
tokensUsed: {
|
|
212
|
+
input: response.usage.input_tokens,
|
|
213
|
+
output: response.usage.output_tokens
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
} catch (error) {
|
|
217
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
218
|
+
if (errorMessage.includes("authentication") || errorMessage.includes("API key")) {
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
content: "",
|
|
222
|
+
error: "Invalid API key. Check your ANTHROPIC_API_KEY."
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (errorMessage.includes("rate limit")) {
|
|
226
|
+
return {
|
|
227
|
+
success: false,
|
|
228
|
+
content: "",
|
|
229
|
+
error: "Rate limited. Try again in a moment."
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
content: "",
|
|
235
|
+
error: `AI analysis failed: ${errorMessage}`
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function getAIStatusMessage() {
|
|
240
|
+
if (isAIAvailable()) {
|
|
241
|
+
return "\u{1F916} AI-powered analysis enabled";
|
|
242
|
+
}
|
|
243
|
+
return "\u26A0\uFE0F AI not available (ANTHROPIC_API_KEY not set) - using pattern-only mode";
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/agents/base-agent.ts
|
|
155
247
|
var BaseAgent = class {
|
|
156
248
|
// Progress reporter for real-time feedback
|
|
157
249
|
progress = null;
|
|
@@ -200,129 +292,196 @@ var BaseAgent = class {
|
|
|
200
292
|
}
|
|
201
293
|
}
|
|
202
294
|
/**
|
|
203
|
-
* AI
|
|
295
|
+
* Hybrid AI + Pattern Analysis
|
|
204
296
|
*
|
|
205
|
-
* 1.
|
|
206
|
-
* 2.
|
|
207
|
-
* 3.
|
|
297
|
+
* 1. Run fast pattern detection on all files
|
|
298
|
+
* 2. If AI is available (ANTHROPIC_API_KEY set), enhance with AI analysis
|
|
299
|
+
* 3. AI validates findings, finds additional issues, provides intelligent fixes
|
|
208
300
|
*
|
|
209
|
-
* Subclasses
|
|
301
|
+
* Subclasses can override for custom behavior
|
|
210
302
|
*/
|
|
211
303
|
async analyzeWithAI(files, context) {
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
304
|
+
this.progress?.aiReview("Running pattern detection...");
|
|
305
|
+
const patternIssues = await this.analyzeFiles(files, context);
|
|
306
|
+
if (!isAIAvailable()) {
|
|
307
|
+
console.error(` ${getAIStatusMessage()}`);
|
|
308
|
+
return patternIssues;
|
|
309
|
+
}
|
|
310
|
+
if (patternIssues.length > 0 || this.shouldAlwaysUseAI()) {
|
|
311
|
+
this.progress?.aiReview("Enhancing with AI analysis...");
|
|
216
312
|
try {
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
if (relevance.isRelevant) {
|
|
220
|
-
this.progress?.analyzing(file);
|
|
221
|
-
const request = await this.buildAIAnalysisRequest(file, content, relevance, context);
|
|
222
|
-
if (request) {
|
|
223
|
-
aiRequests.push(request);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
313
|
+
const enhancedIssues = await this.runAIEnhancement(patternIssues, files, context);
|
|
314
|
+
return this.mergeIssues(enhancedIssues, patternIssues);
|
|
226
315
|
} catch (error) {
|
|
316
|
+
console.error(` \u26A0\uFE0F AI enhancement failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
317
|
+
return patternIssues;
|
|
227
318
|
}
|
|
228
319
|
}
|
|
229
|
-
|
|
230
|
-
this.progress?.aiReview(`Preparing analysis for ${aiRequests.length} files...`);
|
|
231
|
-
for (const request of aiRequests) {
|
|
232
|
-
const aiIssues = await this.processAIRequest(request);
|
|
233
|
-
issues.push(...aiIssues);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
const legacyIssues = await this.analyzeFiles(files, context);
|
|
237
|
-
const allIssues = this.mergeIssues(issues, legacyIssues);
|
|
238
|
-
return allIssues;
|
|
320
|
+
return patternIssues;
|
|
239
321
|
}
|
|
240
322
|
/**
|
|
241
|
-
*
|
|
242
|
-
* Subclasses should override for domain-specific checks
|
|
323
|
+
* Whether this agent should always use AI even if no patterns detected
|
|
243
324
|
*/
|
|
244
|
-
|
|
245
|
-
return
|
|
246
|
-
isRelevant: true,
|
|
247
|
-
reason: "Default analysis",
|
|
248
|
-
priority: "low",
|
|
249
|
-
indicators: []
|
|
250
|
-
};
|
|
325
|
+
shouldAlwaysUseAI() {
|
|
326
|
+
return false;
|
|
251
327
|
}
|
|
252
328
|
/**
|
|
253
|
-
*
|
|
254
|
-
* Subclasses
|
|
329
|
+
* Run AI enhancement on pattern detection results
|
|
330
|
+
* Subclasses can override for custom AI behavior
|
|
255
331
|
*/
|
|
256
|
-
async
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
332
|
+
async runAIEnhancement(patternIssues, files, _context) {
|
|
333
|
+
const snippets = [];
|
|
334
|
+
const sortedIssues = [...patternIssues].sort((a, b) => {
|
|
335
|
+
const order = { critical: 0, serious: 1, moderate: 2, low: 3 };
|
|
336
|
+
return order[a.severity] - order[b.severity];
|
|
337
|
+
});
|
|
338
|
+
for (const issue of sortedIssues.slice(0, 15)) {
|
|
339
|
+
try {
|
|
340
|
+
const content = await this.readFile(issue.file);
|
|
341
|
+
const snippet = this.getCodeSnippet(content, issue.line || 1, 5);
|
|
342
|
+
snippets.push({
|
|
343
|
+
file: this.getRelativePath(issue.file),
|
|
344
|
+
line: issue.line,
|
|
345
|
+
issue: issue.issue,
|
|
346
|
+
code: snippet
|
|
347
|
+
});
|
|
348
|
+
} catch {
|
|
269
349
|
}
|
|
270
|
-
}
|
|
350
|
+
}
|
|
351
|
+
if (snippets.length === 0) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
const userPrompt = this.buildAIEnhancementPrompt(snippets, patternIssues.length);
|
|
355
|
+
const result = await runAIAnalysis({
|
|
356
|
+
systemPrompt: this.getAIEnhancementSystemPrompt(),
|
|
357
|
+
userPrompt,
|
|
358
|
+
maxTokens: 4096,
|
|
359
|
+
temperature: 0.2
|
|
360
|
+
});
|
|
361
|
+
if (!result.success) {
|
|
362
|
+
throw new Error(result.error || "AI analysis failed");
|
|
363
|
+
}
|
|
364
|
+
return this.parseAIEnhancementResponse(result.content, files);
|
|
271
365
|
}
|
|
272
366
|
/**
|
|
273
|
-
*
|
|
274
|
-
* Subclasses should override with domain-specific prompts
|
|
367
|
+
* System prompt for AI enhancement
|
|
275
368
|
*/
|
|
276
|
-
|
|
277
|
-
return `You are an expert
|
|
278
|
-
|
|
279
|
-
|
|
369
|
+
getAIEnhancementSystemPrompt() {
|
|
370
|
+
return `You are an expert ${this.name} code analyst. You are enhancing pattern-detected issues with deeper analysis.
|
|
371
|
+
|
|
372
|
+
Your job:
|
|
373
|
+
1. VALIDATE: Confirm if each issue is a TRUE problem or FALSE positive
|
|
374
|
+
2. EXPAND: Identify related issues that patterns missed
|
|
375
|
+
3. PRIORITIZE: Rank by real-world impact (0-100 inevitability score)
|
|
376
|
+
4. FIX: Provide specific, copy-paste-ready code fixes
|
|
377
|
+
|
|
378
|
+
Output format (STRICT JSON):
|
|
379
|
+
{
|
|
380
|
+
"validated": [
|
|
381
|
+
{
|
|
382
|
+
"original_issue": "...",
|
|
383
|
+
"verdict": "TRUE_POSITIVE" | "FALSE_POSITIVE",
|
|
384
|
+
"confidence": 0-100,
|
|
385
|
+
"file": "path/to/file",
|
|
386
|
+
"line": 123,
|
|
387
|
+
"severity": "critical" | "serious" | "moderate" | "low",
|
|
388
|
+
"explanation": "Why this is/isn't a problem",
|
|
389
|
+
"fix": "Specific code fix"
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
"additional": [
|
|
393
|
+
{
|
|
394
|
+
"issue": "New issue found by AI",
|
|
395
|
+
"file": "path/to/file",
|
|
396
|
+
"line": 123,
|
|
397
|
+
"severity": "critical" | "serious" | "moderate" | "low",
|
|
398
|
+
"explanation": "What's wrong",
|
|
399
|
+
"fix": "How to fix it"
|
|
400
|
+
}
|
|
401
|
+
],
|
|
402
|
+
"summary": "One paragraph summary of findings"
|
|
403
|
+
}`;
|
|
280
404
|
}
|
|
281
405
|
/**
|
|
282
|
-
* Build the user prompt for AI
|
|
406
|
+
* Build the user prompt for AI enhancement
|
|
283
407
|
*/
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
**File:** ${filePath}
|
|
288
|
-
**Relevance indicators:** ${relevance.indicators.join(", ") || "general analysis"}
|
|
289
|
-
|
|
408
|
+
buildAIEnhancementPrompt(snippets, totalIssues) {
|
|
409
|
+
const snippetText = snippets.map((s, i) => `### Issue ${i + 1}: ${s.file}${s.line ? ":" + s.line : ""}
|
|
410
|
+
**Pattern detected:** ${s.issue}
|
|
290
411
|
\`\`\`
|
|
291
|
-
${
|
|
412
|
+
${s.code}
|
|
292
413
|
\`\`\`
|
|
414
|
+
`).join("\n");
|
|
415
|
+
return `Pattern detection found ${totalIssues} total issues. Here are the top ${snippets.length} for AI analysis:
|
|
416
|
+
|
|
417
|
+
${snippetText}
|
|
293
418
|
|
|
294
|
-
|
|
295
|
-
1. Severity (critical/serious/moderate/low)
|
|
296
|
-
2. Line number
|
|
297
|
-
3. Clear description of the issue
|
|
298
|
-
4. Specific fix recommendation`;
|
|
419
|
+
Analyze each issue. Validate, expand, and provide fixes. Output JSON only.`;
|
|
299
420
|
}
|
|
300
421
|
/**
|
|
301
|
-
*
|
|
302
|
-
* This generates the prompt output for Claude to process
|
|
422
|
+
* Parse AI enhancement response into issues
|
|
303
423
|
*/
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
424
|
+
parseAIEnhancementResponse(response, _files) {
|
|
425
|
+
const issues = [];
|
|
426
|
+
try {
|
|
427
|
+
const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/) || response.match(/\{[\s\S]*\}/);
|
|
428
|
+
if (!jsonMatch) {
|
|
429
|
+
return issues;
|
|
430
|
+
}
|
|
431
|
+
const json = JSON.parse(jsonMatch[1] || jsonMatch[0]);
|
|
432
|
+
if (json.validated && Array.isArray(json.validated)) {
|
|
433
|
+
for (const v of json.validated) {
|
|
434
|
+
if (v.verdict === "TRUE_POSITIVE") {
|
|
435
|
+
issues.push(this.createIssue(
|
|
436
|
+
this.generateIssueId(),
|
|
437
|
+
v.severity || "moderate",
|
|
438
|
+
`[AI VALIDATED] ${v.original_issue || v.explanation}`,
|
|
439
|
+
v.fix || "See AI analysis",
|
|
440
|
+
v.file || "unknown",
|
|
441
|
+
v.line,
|
|
442
|
+
(v.confidence || 80) / 100,
|
|
443
|
+
void 0,
|
|
444
|
+
false,
|
|
445
|
+
{ category: "ai-validated" }
|
|
446
|
+
));
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (json.additional && Array.isArray(json.additional)) {
|
|
451
|
+
for (const a of json.additional) {
|
|
452
|
+
issues.push(this.createIssue(
|
|
453
|
+
this.generateIssueId(),
|
|
454
|
+
a.severity || "moderate",
|
|
455
|
+
`[AI FOUND] ${a.issue || a.explanation}`,
|
|
456
|
+
a.fix || "See AI analysis",
|
|
457
|
+
a.file || "unknown",
|
|
458
|
+
a.line,
|
|
459
|
+
0.85,
|
|
460
|
+
// AI-found issues have good confidence
|
|
461
|
+
void 0,
|
|
462
|
+
false,
|
|
463
|
+
{ category: "ai-found" }
|
|
464
|
+
));
|
|
465
|
+
}
|
|
321
466
|
}
|
|
322
|
-
}
|
|
467
|
+
} catch (error) {
|
|
468
|
+
}
|
|
469
|
+
return issues;
|
|
323
470
|
}
|
|
324
471
|
/**
|
|
325
|
-
*
|
|
472
|
+
* Check if a file is relevant for this agent's analysis
|
|
473
|
+
* Subclasses should override for domain-specific checks
|
|
474
|
+
*/
|
|
475
|
+
checkFileRelevance(_file, _content) {
|
|
476
|
+
return {
|
|
477
|
+
isRelevant: true,
|
|
478
|
+
reason: "Default analysis",
|
|
479
|
+
priority: "low",
|
|
480
|
+
indicators: []
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Merge and deduplicate issues from AI and pattern analysis
|
|
326
485
|
*/
|
|
327
486
|
mergeIssues(aiIssues, legacyIssues) {
|
|
328
487
|
const merged = [...aiIssues];
|
|
@@ -400,7 +559,7 @@ For each issue found, provide:
|
|
|
400
559
|
// src/agents/agent-smith.ts
|
|
401
560
|
import { readFile, writeFile, mkdir, rm } from "fs/promises";
|
|
402
561
|
import { existsSync } from "fs";
|
|
403
|
-
import { join, dirname, basename
|
|
562
|
+
import { join, dirname, basename } from "path";
|
|
404
563
|
import { createHash } from "crypto";
|
|
405
564
|
var MEMORY_LIMITS = {
|
|
406
565
|
MAX_LOCATIONS_PER_ISSUE: 5,
|
|
@@ -645,6 +804,13 @@ var AgentSmithAgent = class extends BaseAgent {
|
|
|
645
804
|
shouldActivate(_context) {
|
|
646
805
|
return false;
|
|
647
806
|
}
|
|
807
|
+
/**
|
|
808
|
+
* Override analyzeWithAI to skip the base class AI analysis.
|
|
809
|
+
* Agent Smith has its own sub-agent swarm - we don't want placeholder issues.
|
|
810
|
+
*/
|
|
811
|
+
async analyzeWithAI(files, context) {
|
|
812
|
+
return this.analyzeFiles(files, context);
|
|
813
|
+
}
|
|
648
814
|
// No override needed — base class returns 0 when shouldActivate is false
|
|
649
815
|
async analyzeFiles(files, context) {
|
|
650
816
|
const issues = [];
|
|
@@ -966,11 +1132,11 @@ Found in ${result.occurrences.length} files, ${result.totalCount} total instance
|
|
|
966
1132
|
await this.updateMemory(hash, result.pattern, result.type, file, instances.length);
|
|
967
1133
|
const severity = this.determineSeverity(instances.length, inevitabilityScore);
|
|
968
1134
|
const smithNote = this.getPhilosophicalNote(result.type, instances.length);
|
|
969
|
-
const locationsStr = instances.map((i) => `${
|
|
1135
|
+
const locationsStr = instances.map((i) => `${basename(i.file)}:${i.line}`).slice(0, 5).join(", ");
|
|
970
1136
|
issues.push(this.createSmithIssue(
|
|
971
1137
|
this.generateSmithIssueId(),
|
|
972
1138
|
severity,
|
|
973
|
-
`\u{1F574}\uFE0F ${config.description} \u2014 ${instances.length} instance${instances.length > 1 ? "s" : ""} in ${
|
|
1139
|
+
`\u{1F574}\uFE0F ${config.description} \u2014 ${instances.length} instance${instances.length > 1 ? "s" : ""} in ${basename(file)}
|
|
974
1140
|
|
|
975
1141
|
${smithNote}
|
|
976
1142
|
|
|
@@ -1542,8 +1708,11 @@ Files scanned: ${files.length}
|
|
|
1542
1708
|
|
|
1543
1709
|
export {
|
|
1544
1710
|
ProgressReporter,
|
|
1711
|
+
isAIAvailable,
|
|
1712
|
+
runAIAnalysis,
|
|
1713
|
+
getAIStatusMessage,
|
|
1545
1714
|
BaseAgent,
|
|
1546
1715
|
SUB_AGENT_PATTERNS,
|
|
1547
1716
|
AgentSmithAgent
|
|
1548
1717
|
};
|
|
1549
|
-
//# sourceMappingURL=chunk-
|
|
1718
|
+
//# sourceMappingURL=chunk-3AUDJWEF.js.map
|