vantaverse-ai-reviewer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +129 -0
  2. package/bin/cli.js +12 -0
  3. package/dist/ai/agent.d.ts +54 -0
  4. package/dist/ai/agent.d.ts.map +1 -0
  5. package/dist/ai/agent.js +141 -0
  6. package/dist/ai/agent.js.map +1 -0
  7. package/dist/ai/gemini-client.d.ts +37 -0
  8. package/dist/ai/gemini-client.d.ts.map +1 -0
  9. package/dist/ai/gemini-client.js +75 -0
  10. package/dist/ai/gemini-client.js.map +1 -0
  11. package/dist/ai/prompts.d.ts +25 -0
  12. package/dist/ai/prompts.d.ts.map +1 -0
  13. package/dist/ai/prompts.js +176 -0
  14. package/dist/ai/prompts.js.map +1 -0
  15. package/dist/auth/token-manager.d.ts +33 -0
  16. package/dist/auth/token-manager.d.ts.map +1 -0
  17. package/dist/auth/token-manager.js +97 -0
  18. package/dist/auth/token-manager.js.map +1 -0
  19. package/dist/commands/config.d.ts +12 -0
  20. package/dist/commands/config.d.ts.map +1 -0
  21. package/dist/commands/config.js +84 -0
  22. package/dist/commands/config.js.map +1 -0
  23. package/dist/commands/scan.d.ts +14 -0
  24. package/dist/commands/scan.d.ts.map +1 -0
  25. package/dist/commands/scan.js +110 -0
  26. package/dist/commands/scan.js.map +1 -0
  27. package/dist/core/executor.d.ts +33 -0
  28. package/dist/core/executor.d.ts.map +1 -0
  29. package/dist/core/executor.js +149 -0
  30. package/dist/core/executor.js.map +1 -0
  31. package/dist/core/framework-detector.d.ts +20 -0
  32. package/dist/core/framework-detector.d.ts.map +1 -0
  33. package/dist/core/framework-detector.js +155 -0
  34. package/dist/core/framework-detector.js.map +1 -0
  35. package/dist/core/scanner.d.ts +34 -0
  36. package/dist/core/scanner.d.ts.map +1 -0
  37. package/dist/core/scanner.js +172 -0
  38. package/dist/core/scanner.js.map +1 -0
  39. package/dist/core/security.d.ts +40 -0
  40. package/dist/core/security.d.ts.map +1 -0
  41. package/dist/core/security.js +118 -0
  42. package/dist/core/security.js.map +1 -0
  43. package/dist/index.d.ts +5 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +40 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/reporters/markdown.d.ts +25 -0
  48. package/dist/reporters/markdown.d.ts.map +1 -0
  49. package/dist/reporters/markdown.js +135 -0
  50. package/dist/reporters/markdown.js.map +1 -0
  51. package/dist/utils/logger.d.ts +50 -0
  52. package/dist/utils/logger.d.ts.map +1 -0
  53. package/dist/utils/logger.js +94 -0
  54. package/dist/utils/logger.js.map +1 -0
  55. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # ๐Ÿค– AI Code Reviewer
2
+
3
+ > AI-powered code review CLI - analyze your codebase with Gemini AI
4
+
5
+ [![npm version](https://badge.fury.io/js/%40anthropic%2Fai-reviewer.svg)](https://badge.fury.io/js/%40anthropic%2Fai-reviewer)
6
+
7
+ ## Features
8
+
9
+ - ๐Ÿ” **Intelligent Scanning** - Auto-detects framework (Next.js, React, Vue, Django, etc.)
10
+ - ๐Ÿ”’ **Security Analysis** - Finds vulnerabilities, XSS, injection flaws
11
+ - โ™ฟ **Accessibility Audit** - WCAG compliance checks
12
+ - ๐Ÿงน **Code Quality** - Identifies code smells, complexity issues
13
+ - ๐Ÿงช **Test Suggestions** - Recommends test cases
14
+ - ๐Ÿ“Š **Detailed Reports** - Markdown reports with actionable insights
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Run directly with npx (no install needed)
20
+ npx @anthropic/ai-reviewer
21
+
22
+ # Or install globally
23
+ npm install -g @anthropic/ai-reviewer
24
+ ai-reviewer scan
25
+ ```
26
+
27
+ On first run, you'll be prompted for your **Gemini API key**.
28
+ Get one free at: https://aistudio.google.com/apikey
29
+
30
+ ## Usage
31
+
32
+ ### Analyze Current Directory
33
+
34
+ ```bash
35
+ # Basic scan
36
+ ai-reviewer scan
37
+
38
+ # With options
39
+ ai-reviewer scan --output custom-report.md --verbose
40
+
41
+ # Include JSON output
42
+ ai-reviewer scan --json
43
+
44
+ # Select specific analysis types
45
+ ai-reviewer scan --types security,codeQuality
46
+ ```
47
+
48
+ ### Manage Configuration
49
+
50
+ ```bash
51
+ # Show current config
52
+ ai-reviewer config
53
+
54
+ # Update API token
55
+ ai-reviewer config --action token
56
+
57
+ # Reset all settings
58
+ ai-reviewer config --action reset
59
+ ```
60
+
61
+ ## Analysis Types
62
+
63
+ | Type | Description |
64
+ |------|-------------|
65
+ | `overview` | High-level project assessment |
66
+ | `security` | Security vulnerabilities and risks |
67
+ | `codeQuality` | Code smells, complexity, maintainability |
68
+ | `accessibility` | WCAG compliance, screen reader support |
69
+ | `uiux` | User experience issues, loading states |
70
+ | `testing` | Suggested test cases and coverage |
71
+
72
+ ## Output
73
+
74
+ The tool generates `AI_REVIEW_REPORT.md` in your project root:
75
+
76
+ ```md
77
+ # ๐Ÿค– AI Code Review Report
78
+
79
+ ## ๐Ÿ“Š Project Information
80
+ | Property | Value |
81
+ |----------|-------|
82
+ | Framework | Next.js |
83
+ | Files Scanned | 42 |
84
+ ...
85
+
86
+ ## ๐Ÿ”’ Security Analysis
87
+ [AI-generated security findings]
88
+
89
+ ## ๐Ÿ”ง Code Quality Review
90
+ [AI-generated quality analysis]
91
+ ...
92
+ ```
93
+
94
+ ## Security
95
+
96
+ - โœ… **Sandboxed** - Only reads files within the target repository
97
+ - โœ… **No arbitrary execution** - Uses whitelisted commands only
98
+ - โœ… **Secure storage** - API tokens encrypted locally
99
+ - โœ… **Privacy first** - Code sent only to Gemini API for analysis
100
+
101
+ ## Supported Frameworks
102
+
103
+ - Next.js / React
104
+ - Vue.js / Nuxt
105
+ - Angular
106
+ - Svelte / SvelteKit
107
+ - Vite projects
108
+ - Django / Flask
109
+ - Express / NestJS
110
+ - Generic Node.js projects
111
+
112
+ ## Development
113
+
114
+ ```bash
115
+ # Clone and install
116
+ git clone https://github.com/your-username/ai-reviewer-package
117
+ cd ai-reviewer-package
118
+ npm install
119
+
120
+ # Build
121
+ npm run build
122
+
123
+ # Run locally
124
+ node bin/cli.js scan
125
+ ```
126
+
127
+ ## License
128
+
129
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AI Reviewer CLI Entry Point
5
+ * This file is the npx entry point - it bootstraps the CLI
6
+ */
7
+
8
+ import('../dist/index.js').catch((err) => {
9
+ console.error('Failed to start AI Reviewer:', err.message);
10
+ console.error('Run "npm run build" first if developing locally.');
11
+ process.exit(1);
12
+ });
@@ -0,0 +1,54 @@
1
+ /**
2
+ * AI Agent - Orchestrates the analysis pipeline
3
+ */
4
+ import type { GeminiClient } from './gemini-client.js';
5
+ import type { ScanResult } from '../core/scanner.js';
6
+ import type { FrameworkInfo } from '../core/framework-detector.js';
7
+ import { type PromptType } from './prompts.js';
8
+ export interface AgentConfig {
9
+ repoRoot: string;
10
+ framework: FrameworkInfo;
11
+ analysisTypes: PromptType[];
12
+ maxFilesPerBatch: number;
13
+ maxCharsPerBatch: number;
14
+ }
15
+ export interface AnalysisSection {
16
+ type: PromptType;
17
+ title: string;
18
+ content: string;
19
+ tokensUsed: number;
20
+ filesAnalyzed: string[];
21
+ }
22
+ export interface AgentResult {
23
+ sections: AnalysisSection[];
24
+ context: Record<string, string>;
25
+ typeErrors: string[];
26
+ lintIssues: string[];
27
+ totalTokens: number;
28
+ duration: number;
29
+ }
30
+ /**
31
+ * AI Agent that orchestrates analysis
32
+ */
33
+ export declare class AIAgent {
34
+ private client;
35
+ private config;
36
+ constructor(client: GeminiClient, config: AgentConfig);
37
+ /**
38
+ * Run the full analysis pipeline
39
+ */
40
+ analyze(scanResult: ScanResult): Promise<AgentResult>;
41
+ /**
42
+ * Run a single analysis type
43
+ */
44
+ private runAnalysis;
45
+ /**
46
+ * Categorize files for each analysis type
47
+ */
48
+ private categorizeFilesForAnalysis;
49
+ }
50
+ /**
51
+ * Create a new AI agent
52
+ */
53
+ export declare function createAgent(client: GeminiClient, config: Partial<AgentConfig> & Pick<AgentConfig, 'repoRoot' | 'framework'>): AIAgent;
54
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/ai/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAIlF,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,aAAa,CAAC;IACzB,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAWD;;GAEG;AACH,qBAAa,OAAO;IAChB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW;IAKrD;;OAEG;IACG,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IA4C3D;;OAEG;YACW,WAAW;IA6CzB;;OAEG;IACH,OAAO,CAAC,0BAA0B;CAgCrC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG,OAAO,CASrI"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * AI Agent - Orchestrates the analysis pipeline
3
+ */
4
+ import { getPrompt, createContextualPrompt } from './prompts.js';
5
+ import { safeReadFile } from '../core/security.js';
6
+ import { gatherRepoContext, runTypeCheck, runLint } from '../core/executor.js';
7
+ const SECTION_TITLES = {
8
+ security: '๐Ÿ”’ Security Analysis',
9
+ codeQuality: '๐Ÿ”ง Code Quality Review',
10
+ accessibility: 'โ™ฟ Accessibility Audit',
11
+ uiux: '๐ŸŽจ UI/UX Analysis',
12
+ testing: '๐Ÿงช Testing Recommendations',
13
+ overview: '๐Ÿ“‹ Project Overview'
14
+ };
15
+ /**
16
+ * AI Agent that orchestrates analysis
17
+ */
18
+ export class AIAgent {
19
+ client;
20
+ config;
21
+ constructor(client, config) {
22
+ this.client = client;
23
+ this.config = config;
24
+ }
25
+ /**
26
+ * Run the full analysis pipeline
27
+ */
28
+ async analyze(scanResult) {
29
+ const startTime = Date.now();
30
+ const sections = [];
31
+ let totalTokens = 0;
32
+ // Gather repository context using dynamic commands
33
+ const context = await gatherRepoContext(this.config.repoRoot);
34
+ // Run type checking if TypeScript project
35
+ const typeErrors = await runTypeCheck(this.config.repoRoot);
36
+ if (typeErrors.length > 0) {
37
+ context['type_errors'] = `${typeErrors.length} TypeScript errors found`;
38
+ }
39
+ // Run linting
40
+ const lintIssues = await runLint(this.config.repoRoot);
41
+ if (lintIssues.length > 0) {
42
+ context['lint_issues'] = `${lintIssues.length} lint issues found`;
43
+ }
44
+ // Determine which files to analyze for each type
45
+ const filesByType = this.categorizeFilesForAnalysis(scanResult);
46
+ // Run each analysis type
47
+ for (const analysisType of this.config.analysisTypes) {
48
+ const files = filesByType[analysisType] || scanResult.files.slice(0, 20);
49
+ if (files.length === 0)
50
+ continue;
51
+ const section = await this.runAnalysis(analysisType, files, context);
52
+ sections.push(section);
53
+ totalTokens += section.tokensUsed;
54
+ }
55
+ return {
56
+ sections,
57
+ context,
58
+ typeErrors,
59
+ lintIssues,
60
+ totalTokens,
61
+ duration: Date.now() - startTime
62
+ };
63
+ }
64
+ /**
65
+ * Run a single analysis type
66
+ */
67
+ async runAnalysis(type, files, context) {
68
+ // Read file contents
69
+ const fileContents = new Map();
70
+ let totalChars = 0;
71
+ for (const file of files) {
72
+ if (totalChars >= this.config.maxCharsPerBatch)
73
+ break;
74
+ try {
75
+ const content = await safeReadFile(file.path, this.config.repoRoot, 100 * 1024 // 100KB max per file
76
+ );
77
+ if (totalChars + content.length <= this.config.maxCharsPerBatch) {
78
+ fileContents.set(file.relativePath, content);
79
+ totalChars += content.length;
80
+ }
81
+ }
82
+ catch {
83
+ // Skip files that can't be read
84
+ }
85
+ }
86
+ // Build contextual prompt
87
+ const basePrompt = getPrompt(type);
88
+ const frameworkHints = this.config.framework.description;
89
+ const prompt = createContextualPrompt(basePrompt, frameworkHints, context);
90
+ // Run analysis
91
+ const result = await this.client.analyzeMultiple(prompt, fileContents, '');
92
+ return {
93
+ type,
94
+ title: SECTION_TITLES[type],
95
+ content: result.content,
96
+ tokensUsed: result.tokensUsed,
97
+ filesAnalyzed: Array.from(fileContents.keys())
98
+ };
99
+ }
100
+ /**
101
+ * Categorize files for each analysis type
102
+ */
103
+ categorizeFilesForAnalysis(scanResult) {
104
+ return {
105
+ security: [
106
+ ...scanResult.byCategory.api,
107
+ ...scanResult.byCategory.utility.filter(f => f.relativePath.includes('auth') ||
108
+ f.relativePath.includes('security') ||
109
+ f.relativePath.includes('middleware'))
110
+ ].slice(0, 15),
111
+ codeQuality: [
112
+ ...scanResult.byCategory.utility,
113
+ ...scanResult.byCategory.api,
114
+ ...scanResult.byCategory.other
115
+ ].slice(0, 20),
116
+ accessibility: [
117
+ ...scanResult.byCategory.component,
118
+ ...scanResult.byCategory.page
119
+ ].slice(0, 15),
120
+ uiux: [
121
+ ...scanResult.byCategory.component,
122
+ ...scanResult.byCategory.page
123
+ ].slice(0, 15),
124
+ testing: scanResult.files.slice(0, 15),
125
+ overview: scanResult.files.slice(0, 25)
126
+ };
127
+ }
128
+ }
129
+ /**
130
+ * Create a new AI agent
131
+ */
132
+ export function createAgent(client, config) {
133
+ const fullConfig = {
134
+ analysisTypes: ['overview', 'security', 'codeQuality', 'accessibility'],
135
+ maxFilesPerBatch: 20,
136
+ maxCharsPerBatch: 50000,
137
+ ...config
138
+ };
139
+ return new AIAgent(client, fullConfig);
140
+ }
141
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/ai/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAmB,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AA2B/E,MAAM,cAAc,GAA+B;IAC/C,QAAQ,EAAE,sBAAsB;IAChC,WAAW,EAAE,wBAAwB;IACrC,aAAa,EAAE,uBAAuB;IACtC,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,4BAA4B;IACrC,QAAQ,EAAE,qBAAqB;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,OAAO;IACR,MAAM,CAAe;IACrB,MAAM,CAAc;IAE5B,YAAY,MAAoB,EAAE,MAAmB;QACjD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAsB;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,mDAAmD;QACnD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE9D,0CAA0C;QAC1C,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,aAAa,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,0BAA0B,CAAC;QAC5E,CAAC;QAED,cAAc;QACd,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,aAAa,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,oBAAoB,CAAC;QACtE,CAAC;QAED,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC;QAEhE,yBAAyB;QACzB,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAEzE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEjC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACrE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC;QACtC,CAAC;QAED,OAAO;YACH,QAAQ;YACR,OAAO;YACP,UAAU;YACV,UAAU;YACV,WAAW;YACX,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACnC,CAAC;IACN,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW,CACrB,IAAgB,EAChB,KAAoB,EACpB,OAA+B;QAE/B,qBAAqB;QACrB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC/C,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB;gBAAE,MAAM;YAEtD,IAAI,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,YAAY,CAC9B,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,GAAG,GAAG,IAAI,CAAC,qBAAqB;iBACnC,CAAC;gBAEF,IAAI,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;oBAC9D,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;oBAC7C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;gBACjC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACL,gCAAgC;YACpC,CAAC;QACL,CAAC;QAED,0BAA0B;QAC1B,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC;QACzD,MAAM,MAAM,GAAG,sBAAsB,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAE3E,eAAe;QACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAE3E,OAAO;YACH,IAAI;YACJ,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC;YAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;SACjD,CAAC;IACN,CAAC;IAED;;OAEG;IACK,0BAA0B,CAAC,UAAsB;QACrD,OAAO;YACH,QAAQ,EAAE;gBACN,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG;gBAC5B,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACxC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAC/B,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;oBACnC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,CACxC;aACJ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAEd,WAAW,EAAE;gBACT,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO;gBAChC,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG;gBAC5B,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK;aACjC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAEd,aAAa,EAAE;gBACX,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS;gBAClC,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI;aAChC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAEd,IAAI,EAAE;gBACF,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS;gBAClC,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI;aAChC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAEd,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAEtC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SAC1C,CAAC;IACN,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAoB,EAAE,MAA0E;IACxH,MAAM,UAAU,GAAgB;QAC5B,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,CAAC;QACvE,gBAAgB,EAAE,EAAE;QACpB,gBAAgB,EAAE,KAAK;QACvB,GAAG,MAAM;KACZ,CAAC;IAEF,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Gemini AI Client - Wrapper for Google's Generative AI SDK
3
+ */
4
+ export interface AnalysisResult {
5
+ content: string;
6
+ tokensUsed: number;
7
+ }
8
+ export declare class GeminiClient {
9
+ private model;
10
+ private modelName;
11
+ constructor(apiKey: string, modelName?: string);
12
+ /**
13
+ * Validate the API key by making a simple request
14
+ */
15
+ validateKey(): Promise<boolean>;
16
+ /**
17
+ * Analyze code with a specific prompt
18
+ */
19
+ analyze(prompt: string, code: string, context?: string): Promise<AnalysisResult>;
20
+ /**
21
+ * Analyze multiple files in a batch
22
+ */
23
+ analyzeMultiple(prompt: string, files: Map<string, string>, context?: string): Promise<AnalysisResult>;
24
+ /**
25
+ * Build the full prompt with instruction, code, and context
26
+ */
27
+ private buildPrompt;
28
+ /**
29
+ * Get model info
30
+ */
31
+ getModelName(): string;
32
+ }
33
+ /**
34
+ * Create a new Gemini client
35
+ */
36
+ export declare function createGeminiClient(apiKey: string, model?: string): GeminiClient;
37
+ //# sourceMappingURL=gemini-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-client.d.ts","sourceRoot":"","sources":["../../src/ai/gemini-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAA2B;IAMlE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgBtF;;OAEG;IACG,eAAe,CACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC;IAQ1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACH,YAAY,IAAI,MAAM;CAGzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,CAE/E"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Gemini AI Client - Wrapper for Google's Generative AI SDK
3
+ */
4
+ import { GoogleGenerativeAI } from '@google/generative-ai';
5
+ export class GeminiClient {
6
+ model;
7
+ modelName;
8
+ constructor(apiKey, modelName = 'gemini-1.5-flash') {
9
+ const genAI = new GoogleGenerativeAI(apiKey);
10
+ this.model = genAI.getGenerativeModel({ model: modelName });
11
+ this.modelName = modelName;
12
+ }
13
+ /**
14
+ * Validate the API key by making a simple request
15
+ */
16
+ async validateKey() {
17
+ try {
18
+ const result = await this.model.generateContent('Say "ok" if you can hear me.');
19
+ return !!result.response.text();
20
+ }
21
+ catch (error) {
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Analyze code with a specific prompt
27
+ */
28
+ async analyze(prompt, code, context) {
29
+ const fullPrompt = this.buildPrompt(prompt, code, context);
30
+ try {
31
+ const result = await this.model.generateContent(fullPrompt);
32
+ const response = result.response;
33
+ return {
34
+ content: response.text(),
35
+ tokensUsed: response.usageMetadata?.totalTokenCount || 0
36
+ };
37
+ }
38
+ catch (error) {
39
+ throw new Error(`Gemini API error: ${error instanceof Error ? error.message : 'Unknown error'}`);
40
+ }
41
+ }
42
+ /**
43
+ * Analyze multiple files in a batch
44
+ */
45
+ async analyzeMultiple(prompt, files, context) {
46
+ const filesContent = Array.from(files.entries())
47
+ .map(([path, content]) => `### File: ${path}\n\`\`\`\n${content}\n\`\`\``)
48
+ .join('\n\n');
49
+ return this.analyze(prompt, filesContent, context);
50
+ }
51
+ /**
52
+ * Build the full prompt with instruction, code, and context
53
+ */
54
+ buildPrompt(instruction, code, context) {
55
+ let prompt = instruction + '\n\n';
56
+ if (context) {
57
+ prompt += `## Context\n${context}\n\n`;
58
+ }
59
+ prompt += `## Code to Analyze\n${code}`;
60
+ return prompt;
61
+ }
62
+ /**
63
+ * Get model info
64
+ */
65
+ getModelName() {
66
+ return this.modelName;
67
+ }
68
+ }
69
+ /**
70
+ * Create a new Gemini client
71
+ */
72
+ export function createGeminiClient(apiKey, model) {
73
+ return new GeminiClient(apiKey, model);
74
+ }
75
+ //# sourceMappingURL=gemini-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-client.js","sourceRoot":"","sources":["../../src/ai/gemini-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAmB,MAAM,uBAAuB,CAAC;AAO5E,MAAM,OAAO,YAAY;IACb,KAAK,CAAkB;IACvB,SAAS,CAAS;IAE1B,YAAY,MAAc,EAAE,YAAoB,kBAAkB;QAC9D,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACb,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,8BAA8B,CAAC,CAAC;YAChF,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,IAAY,EAAE,OAAgB;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAE3D,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;YAEjC,OAAO;gBACH,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;gBACxB,UAAU,EAAE,QAAQ,CAAC,aAAa,EAAE,eAAe,IAAI,CAAC;aAC3D,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACrG,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CACjB,MAAc,EACd,KAA0B,EAC1B,OAAgB;QAEhB,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;aAC3C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,aAAa,IAAI,aAAa,OAAO,UAAU,CAAC;aACzE,IAAI,CAAC,MAAM,CAAC,CAAC;QAElB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,WAAmB,EAAE,IAAY,EAAE,OAAgB;QACnE,IAAI,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;QAElC,IAAI,OAAO,EAAE,CAAC;YACV,MAAM,IAAI,eAAe,OAAO,MAAM,CAAC;QAC3C,CAAC;QAED,MAAM,IAAI,uBAAuB,IAAI,EAAE,CAAC;QAExC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,YAAY;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAc;IAC7D,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * AI Prompts - Structured prompts for different analysis types
3
+ */
4
+ export declare const PROMPTS: {
5
+ security: string;
6
+ codeQuality: string;
7
+ accessibility: string;
8
+ uiux: string;
9
+ testing: string;
10
+ overview: string;
11
+ };
12
+ export type PromptType = keyof typeof PROMPTS;
13
+ /**
14
+ * Get a prompt by type
15
+ */
16
+ export declare function getPrompt(type: PromptType): string;
17
+ /**
18
+ * Get all available prompt types
19
+ */
20
+ export declare function getPromptTypes(): PromptType[];
21
+ /**
22
+ * Create a custom prompt with framework context
23
+ */
24
+ export declare function createContextualPrompt(basePrompt: string, frameworkHints: string, repoContext: Record<string, string>): string;
25
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/ai/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,OAAO;;;;;;;CAkJnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAC;AAE9C;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAE7C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAClC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,MAAM,CAiBR"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * AI Prompts - Structured prompts for different analysis types
3
+ */
4
+ export const PROMPTS = {
5
+ security: `You are a security expert reviewing code for vulnerabilities.
6
+
7
+ Analyze the provided code and identify:
8
+ 1. **Critical vulnerabilities** (SQL injection, XSS, CSRF, auth bypass)
9
+ 2. **Data exposure risks** (sensitive data logging, hardcoded secrets)
10
+ 3. **Input validation issues** (missing sanitization, type coercion)
11
+ 4. **Authentication/Authorization flaws**
12
+ 5. **Dependency risks** (if package info provided)
13
+
14
+ Format your response as:
15
+ ## ๐Ÿ”ด Critical Issues
16
+ - [issue with file:line reference]
17
+
18
+ ## ๐ŸŸ  Medium Issues
19
+ - [issue with file:line reference]
20
+
21
+ ## ๐ŸŸก Low Issues
22
+ - [issue with file:line reference]
23
+
24
+ ## โœ… Security Recommendations
25
+ - [specific actionable recommendations]
26
+
27
+ If no issues found, state "No security issues detected" and explain what was checked.`,
28
+ codeQuality: `You are a senior software engineer reviewing code quality.
29
+
30
+ Analyze the provided code for:
31
+ 1. **Code smells** (long methods, deep nesting, god objects)
32
+ 2. **DRY violations** (repeated code patterns)
33
+ 3. **Naming issues** (unclear variable/function names)
34
+ 4. **Complexity issues** (cyclomatic complexity, cognitive load)
35
+ 5. **Error handling** (missing try/catch, swallowed errors)
36
+ 6. **Performance concerns** (N+1 queries, memory leaks, unnecessary re-renders)
37
+
38
+ Format your response as:
39
+ ## ๐Ÿ”ง Code Quality Issues
40
+ ### [File Name]
41
+ - **Line X**: [issue description]
42
+ - Suggestion: [how to fix]
43
+
44
+ ## ๐Ÿ“Š Metrics Summary
45
+ - Complexity: [Low/Medium/High]
46
+ - Maintainability: [Good/Fair/Poor]
47
+
48
+ ## โœจ Refactoring Suggestions
49
+ - [specific improvements]`,
50
+ accessibility: `You are an accessibility expert (WCAG 2.1 AA certified).
51
+
52
+ Analyze the provided UI code for accessibility issues:
53
+ 1. **Missing ARIA labels** (buttons, links, form fields)
54
+ 2. **Color contrast issues** (text on backgrounds)
55
+ 3. **Keyboard navigation** (focus management, tab order)
56
+ 4. **Screen reader compatibility** (semantic HTML, alt text)
57
+ 5. **Form accessibility** (labels, error messages, required fields)
58
+ 6. **Motion/animation concerns** (respects prefers-reduced-motion)
59
+
60
+ Format your response as:
61
+ ## โ™ฟ Accessibility Issues
62
+ ### Critical (WCAG A violations)
63
+ - [issue with element reference]
64
+
65
+ ### Important (WCAG AA violations)
66
+ - [issue with element reference]
67
+
68
+ ### Best Practices
69
+ - [recommendations]
70
+
71
+ ## ๐Ÿ“ Suggested Fixes
72
+ - [specific code changes]`,
73
+ uiux: `You are a UX designer and frontend expert.
74
+
75
+ Review the UI/component code for:
76
+ 1. **User experience issues** (confusing flows, missing feedback)
77
+ 2. **Loading states** (spinners, skeletons, optimistic updates)
78
+ 3. **Error states** (error boundaries, user-friendly messages)
79
+ 4. **Empty states** (no data scenarios)
80
+ 5. **Responsive design** (mobile considerations)
81
+ 6. **Interaction patterns** (hover states, click feedback)
82
+
83
+ Format your response as:
84
+ ## ๐ŸŽจ UX Issues Found
85
+ - [issue with component reference]
86
+
87
+ ## ๐Ÿ’ก UX Improvements
88
+ - [specific suggestions]
89
+
90
+ ## ๐Ÿงช Suggested Test Cases
91
+ - [user scenarios to test]`,
92
+ testing: `You are a QA engineer and testing expert.
93
+
94
+ Analyze the code and suggest:
95
+ 1. **Unit test cases** (functions and methods to test)
96
+ 2. **Integration test cases** (component interactions)
97
+ 3. **Edge cases** (boundary conditions, null checks)
98
+ 4. **Error scenarios** (network failures, invalid inputs)
99
+ 5. **User flow tests** (E2E scenarios)
100
+
101
+ Format your response as:
102
+ ## ๐Ÿงช Recommended Test Cases
103
+
104
+ ### Unit Tests
105
+ #### [Function/Component Name]
106
+ - Test case: [description]
107
+ - Input: [example]
108
+ - Expected: [result]
109
+
110
+ ### Integration Tests
111
+ - [scenario description]
112
+
113
+ ### Edge Cases
114
+ - [boundary conditions to test]
115
+
116
+ ### E2E Scenarios
117
+ - [user flow to test]`,
118
+ overview: `You are a technical lead performing a comprehensive code review.
119
+
120
+ Provide a high-level analysis covering:
121
+ 1. **Architecture assessment** (structure, patterns used)
122
+ 2. **Code organization** (file structure, separation of concerns)
123
+ 3. **Best practices adherence** (framework conventions, industry standards)
124
+ 4. **Technical debt** (areas needing refactoring)
125
+ 5. **Documentation needs** (missing comments, unclear logic)
126
+
127
+ Format your response as:
128
+ ## ๐Ÿ“‹ Project Overview
129
+
130
+ ### Architecture
131
+ [assessment of overall structure]
132
+
133
+ ### Strengths
134
+ - [positive observations]
135
+
136
+ ### Areas for Improvement
137
+ - [specific concerns]
138
+
139
+ ### Priority Actions
140
+ 1. [most important fix]
141
+ 2. [second priority]
142
+ 3. [third priority]
143
+
144
+ ### Overall Health Score: [1-10]/10`
145
+ };
146
+ /**
147
+ * Get a prompt by type
148
+ */
149
+ export function getPrompt(type) {
150
+ return PROMPTS[type];
151
+ }
152
+ /**
153
+ * Get all available prompt types
154
+ */
155
+ export function getPromptTypes() {
156
+ return Object.keys(PROMPTS);
157
+ }
158
+ /**
159
+ * Create a custom prompt with framework context
160
+ */
161
+ export function createContextualPrompt(basePrompt, frameworkHints, repoContext) {
162
+ let contextSection = '';
163
+ if (frameworkHints) {
164
+ contextSection += `\n### Framework Notes\n${frameworkHints}\n`;
165
+ }
166
+ if (Object.keys(repoContext).length > 0) {
167
+ contextSection += '\n### Repository Context\n';
168
+ for (const [key, value] of Object.entries(repoContext)) {
169
+ if (value) {
170
+ contextSection += `- ${key}: ${value}\n`;
171
+ }
172
+ }
173
+ }
174
+ return basePrompt + contextSection;
175
+ }
176
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/ai/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG;IACnB,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;sFAsBwE;IAElF,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;0BAqBS;IAEtB,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;0BAsBO;IAEtB,IAAI,EAAE;;;;;;;;;;;;;;;;;;2BAkBiB;IAEvB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;sBAyBS;IAElB,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;oCA0BsB;CACnC,CAAC;AAIF;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAgB;IACtC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAiB,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAClC,UAAkB,EAClB,cAAsB,EACtB,WAAmC;IAEnC,IAAI,cAAc,GAAG,EAAE,CAAC;IAExB,IAAI,cAAc,EAAE,CAAC;QACjB,cAAc,IAAI,0BAA0B,cAAc,IAAI,CAAC;IACnE,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,cAAc,IAAI,4BAA4B,CAAC;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACrD,IAAI,KAAK,EAAE,CAAC;gBACR,cAAc,IAAI,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC;YAC7C,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,UAAU,GAAG,cAAc,CAAC;AACvC,CAAC"}