codereview-aia 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 (153) hide show
  1. package/.cr-aia.yml +23 -0
  2. package/.crignore +0 -0
  3. package/dist/index.js +27 -0
  4. package/package.json +85 -0
  5. package/src/analysis/FindingsExtractor.ts +431 -0
  6. package/src/analysis/ai-detection/analyzers/BaseAnalyzer.ts +267 -0
  7. package/src/analysis/ai-detection/analyzers/DocumentationAnalyzer.ts +622 -0
  8. package/src/analysis/ai-detection/analyzers/GitHistoryAnalyzer.ts +430 -0
  9. package/src/analysis/ai-detection/core/AIDetectionEngine.ts +467 -0
  10. package/src/analysis/ai-detection/types/DetectionTypes.ts +406 -0
  11. package/src/analysis/ai-detection/utils/SubmissionConverter.ts +390 -0
  12. package/src/analysis/context/ReviewContext.ts +378 -0
  13. package/src/analysis/context/index.ts +7 -0
  14. package/src/analysis/index.ts +8 -0
  15. package/src/analysis/tokens/TokenAnalysisFormatter.ts +154 -0
  16. package/src/analysis/tokens/TokenAnalyzer.ts +747 -0
  17. package/src/analysis/tokens/index.ts +8 -0
  18. package/src/clients/base/abstractClient.ts +190 -0
  19. package/src/clients/base/httpClient.ts +160 -0
  20. package/src/clients/base/index.ts +12 -0
  21. package/src/clients/base/modelDetection.ts +107 -0
  22. package/src/clients/base/responseProcessor.ts +586 -0
  23. package/src/clients/factory/clientFactory.ts +55 -0
  24. package/src/clients/factory/index.ts +8 -0
  25. package/src/clients/implementations/index.ts +8 -0
  26. package/src/clients/implementations/openRouterClient.ts +411 -0
  27. package/src/clients/openRouterClient.ts +863 -0
  28. package/src/clients/openRouterClientWrapper.ts +44 -0
  29. package/src/clients/utils/directoryStructure.ts +52 -0
  30. package/src/clients/utils/index.ts +11 -0
  31. package/src/clients/utils/languageDetection.ts +44 -0
  32. package/src/clients/utils/promptFormatter.ts +105 -0
  33. package/src/clients/utils/promptLoader.ts +53 -0
  34. package/src/clients/utils/tokenCounter.ts +297 -0
  35. package/src/core/ApiClientSelector.ts +37 -0
  36. package/src/core/ConfigurationService.ts +591 -0
  37. package/src/core/ConsolidationService.ts +423 -0
  38. package/src/core/InteractiveDisplayManager.ts +81 -0
  39. package/src/core/OutputManager.ts +275 -0
  40. package/src/core/ReviewGenerator.ts +140 -0
  41. package/src/core/fileDiscovery.ts +237 -0
  42. package/src/core/handlers/EstimationHandler.ts +104 -0
  43. package/src/core/handlers/FileProcessingHandler.ts +204 -0
  44. package/src/core/handlers/OutputHandler.ts +125 -0
  45. package/src/core/handlers/ReviewExecutor.ts +104 -0
  46. package/src/core/reviewOrchestrator.ts +333 -0
  47. package/src/core/utils/ModelInfoUtils.ts +56 -0
  48. package/src/formatters/outputFormatter.ts +62 -0
  49. package/src/formatters/utils/IssueFormatters.ts +83 -0
  50. package/src/formatters/utils/JsonFormatter.ts +77 -0
  51. package/src/formatters/utils/MarkdownFormatters.ts +609 -0
  52. package/src/formatters/utils/MetadataFormatter.ts +269 -0
  53. package/src/formatters/utils/ModelInfoExtractor.ts +115 -0
  54. package/src/index.ts +27 -0
  55. package/src/plugins/PluginInterface.ts +50 -0
  56. package/src/plugins/PluginManager.ts +126 -0
  57. package/src/prompts/PromptManager.ts +69 -0
  58. package/src/prompts/cache/PromptCache.ts +50 -0
  59. package/src/prompts/promptText/common/variables/css-frameworks.json +33 -0
  60. package/src/prompts/promptText/common/variables/framework-versions.json +45 -0
  61. package/src/prompts/promptText/frameworks/react/comprehensive.hbs +19 -0
  62. package/src/prompts/promptText/languages/css/comprehensive.hbs +18 -0
  63. package/src/prompts/promptText/languages/generic/comprehensive.hbs +20 -0
  64. package/src/prompts/promptText/languages/html/comprehensive.hbs +18 -0
  65. package/src/prompts/promptText/languages/javascript/comprehensive.hbs +18 -0
  66. package/src/prompts/promptText/languages/python/comprehensive.hbs +18 -0
  67. package/src/prompts/promptText/languages/typescript/comprehensive.hbs +18 -0
  68. package/src/runtime/auth/service.ts +58 -0
  69. package/src/runtime/auth/session.ts +103 -0
  70. package/src/runtime/auth/types.ts +11 -0
  71. package/src/runtime/cliEntry.ts +196 -0
  72. package/src/runtime/errors.ts +13 -0
  73. package/src/runtime/fileCollector.ts +188 -0
  74. package/src/runtime/manifest.ts +64 -0
  75. package/src/runtime/openrouterProxy.ts +45 -0
  76. package/src/runtime/proxyConfig.ts +94 -0
  77. package/src/runtime/proxyEnvironment.ts +71 -0
  78. package/src/runtime/reportMerge.ts +102 -0
  79. package/src/runtime/reporting/markdownReportBuilder.ts +138 -0
  80. package/src/runtime/reporting/reportDataCollector.ts +234 -0
  81. package/src/runtime/reporting/summaryGenerator.ts +86 -0
  82. package/src/runtime/reviewPipeline.ts +155 -0
  83. package/src/runtime/runAiCodeReview.ts +153 -0
  84. package/src/runtime/runtimeConfig.ts +5 -0
  85. package/src/runtime/ui/Layout.tsx +57 -0
  86. package/src/runtime/ui/RuntimeApp.tsx +150 -0
  87. package/src/runtime/ui/inkModules.ts +73 -0
  88. package/src/runtime/ui/screens/AuthScreen.tsx +128 -0
  89. package/src/runtime/ui/screens/ModeSelection.tsx +52 -0
  90. package/src/runtime/ui/screens/ProgressScreen.tsx +55 -0
  91. package/src/runtime/ui/screens/ResultsScreen.tsx +76 -0
  92. package/src/strategies/ArchitecturalReviewStrategy.ts +54 -0
  93. package/src/strategies/CodingTestReviewStrategy.ts +920 -0
  94. package/src/strategies/ConsolidatedReviewStrategy.ts +59 -0
  95. package/src/strategies/ExtractPatternsReviewStrategy.ts +64 -0
  96. package/src/strategies/MultiPassReviewStrategy.ts +785 -0
  97. package/src/strategies/ReviewStrategy.ts +64 -0
  98. package/src/strategies/StrategyFactory.ts +79 -0
  99. package/src/strategies/index.ts +14 -0
  100. package/src/tokenizers/baseTokenizer.ts +61 -0
  101. package/src/tokenizers/gptTokenizer.ts +27 -0
  102. package/src/tokenizers/index.ts +8 -0
  103. package/src/types/apiResponses.ts +40 -0
  104. package/src/types/cli.ts +24 -0
  105. package/src/types/common.ts +39 -0
  106. package/src/types/configuration.ts +201 -0
  107. package/src/types/handlebars.d.ts +5 -0
  108. package/src/types/patch.d.ts +25 -0
  109. package/src/types/review.ts +294 -0
  110. package/src/types/reviewContext.d.ts +65 -0
  111. package/src/types/reviewSchema.ts +181 -0
  112. package/src/types/structuredReview.ts +167 -0
  113. package/src/types/tokenAnalysis.ts +56 -0
  114. package/src/utils/FileReader.ts +93 -0
  115. package/src/utils/FileWriter.ts +76 -0
  116. package/src/utils/PathGenerator.ts +97 -0
  117. package/src/utils/api/apiUtils.ts +14 -0
  118. package/src/utils/api/index.ts +1 -0
  119. package/src/utils/apiErrorHandler.ts +287 -0
  120. package/src/utils/ciDataCollector.ts +252 -0
  121. package/src/utils/codingTestConfigLoader.ts +466 -0
  122. package/src/utils/dependencies/aiDependencyAnalyzer.ts +454 -0
  123. package/src/utils/detection/frameworkDetector.ts +879 -0
  124. package/src/utils/detection/index.ts +10 -0
  125. package/src/utils/detection/projectTypeDetector.ts +518 -0
  126. package/src/utils/diagramGenerator.ts +206 -0
  127. package/src/utils/errorLogger.ts +60 -0
  128. package/src/utils/estimationUtils.ts +407 -0
  129. package/src/utils/fileFilters.ts +373 -0
  130. package/src/utils/fileSystem.ts +57 -0
  131. package/src/utils/index.ts +36 -0
  132. package/src/utils/logger.ts +240 -0
  133. package/src/utils/pathValidator.ts +98 -0
  134. package/src/utils/priorityFilter.ts +59 -0
  135. package/src/utils/projectDocs.ts +189 -0
  136. package/src/utils/promptPaths.ts +29 -0
  137. package/src/utils/promptTemplateManager.ts +157 -0
  138. package/src/utils/review/consolidateReview.ts +553 -0
  139. package/src/utils/review/fixDisplay.ts +100 -0
  140. package/src/utils/review/fixImplementation.ts +61 -0
  141. package/src/utils/review/index.ts +36 -0
  142. package/src/utils/review/interactiveProcessing.ts +294 -0
  143. package/src/utils/review/progressTracker.ts +296 -0
  144. package/src/utils/review/reviewExtraction.ts +382 -0
  145. package/src/utils/review/types.ts +46 -0
  146. package/src/utils/reviewActionHandler.ts +18 -0
  147. package/src/utils/reviewParser.ts +253 -0
  148. package/src/utils/sanitizer.ts +238 -0
  149. package/src/utils/smartFileSelector.ts +255 -0
  150. package/src/utils/templateLoader.ts +514 -0
  151. package/src/utils/treeGenerator.ts +153 -0
  152. package/tsconfig.build.json +14 -0
  153. package/tsconfig.json +59 -0
@@ -0,0 +1,454 @@
1
+ /**
2
+ * @fileoverview AI-powered dependency analysis for architectural reviews
3
+ *
4
+ * This module provides a dependency analysis approach that uses the AI model
5
+ * itself to analyze the project structure and dependencies, eliminating the
6
+ * need for external tools like dependency-cruiser that can cause installation issues.
7
+ */
8
+
9
+ import { exec } from 'node:child_process';
10
+ import fs from 'node:fs/promises';
11
+ import path from 'node:path';
12
+ import { promisify } from 'node:util';
13
+ // import { getConfig } from '../../utils/config';
14
+ // import { AbstractClient } from '../../clients/base/abstractClient';
15
+ import { ClientFactory } from '../../clients/factory/clientFactory';
16
+ import logger from '../logger';
17
+
18
+ // import { formatProjectDocs } from '../projectDocs';
19
+
20
+ const execAsync = promisify(exec);
21
+
22
+ /**
23
+ * Basic file structure for dependency analysis
24
+ */
25
+ interface FileStructureInfo {
26
+ /** Path to the file */
27
+ path: string;
28
+ /** Type of file based on extension */
29
+ type: string;
30
+ /** Import statements in the file */
31
+ imports?: string[];
32
+ /** Export statements in the file */
33
+ exports?: string[];
34
+ /** Dependencies declared in package.json */
35
+ dependencies?: Record<string, string>;
36
+ /** Dev dependencies declared in package.json */
37
+ devDependencies?: Record<string, string>;
38
+ }
39
+
40
+ /**
41
+ * Sample of files to provide to the AI for analysis
42
+ */
43
+ interface ProjectFileSample {
44
+ /** All package.json files found */
45
+ packageFiles: FileStructureInfo[];
46
+ /** Sample of source files with their imports/exports */
47
+ sourceFiles: FileStructureInfo[];
48
+ /** Total file count in the project */
49
+ totalFileCount: number;
50
+ /** Project structure overview */
51
+ directoryStructure: string;
52
+ }
53
+
54
+ /**
55
+ * Result of the AI-based dependency analysis
56
+ */
57
+ export interface AIDependencyAnalysisResult {
58
+ /** Summary of dependencies in the project */
59
+ dependencySummary: string;
60
+ /** Potential architectural issues identified */
61
+ architecturalIssues: string;
62
+ /** Package.json analysis */
63
+ packageAnalysis: string;
64
+ /** Import/export structure analysis */
65
+ codeStructureAnalysis: string;
66
+ /** Recommendations for dependency management */
67
+ recommendations: string;
68
+ /** Raw AI response for debugging */
69
+ rawResponse?: string;
70
+ }
71
+
72
+ /**
73
+ * Create a dependency analysis section for architectural reviews using AI
74
+ * @param projectPath The path to the project
75
+ * @returns Dependency analysis formatted for inclusion in reviews
76
+ */
77
+ export async function createAIDependencyAnalysis(projectPath: string): Promise<string> {
78
+ logger.info('=========== STARTING AI-POWERED DEPENDENCY ANALYSIS ===========');
79
+ logger.info(`Project path: ${projectPath}`);
80
+
81
+ try {
82
+ // Get project file sample for AI analysis
83
+ const projectSample = await getProjectFileSample(projectPath);
84
+
85
+ // Return empty analysis if no files were found
86
+ if (projectSample.packageFiles.length === 0 && projectSample.sourceFiles.length === 0) {
87
+ logger.warn('No suitable files found for AI dependency analysis');
88
+ return '## Dependency Analysis\n\nNo suitable files were found for dependency analysis.';
89
+ }
90
+
91
+ logger.info(
92
+ `Collected ${projectSample.packageFiles.length} package files and ${projectSample.sourceFiles.length} source files for analysis`,
93
+ );
94
+
95
+ // Generate the dependency analysis using AI
96
+ const analysisResult = await analyzeWithAI(projectSample);
97
+
98
+ // Format the results as markdown
99
+ return formatDependencyAnalysis(analysisResult);
100
+ } catch (error) {
101
+ logger.error(
102
+ `Error in AI dependency analysis: ${error instanceof Error ? error.message : String(error)}`,
103
+ );
104
+ return '## Dependency Analysis\n\n⚠️ Unable to perform AI-powered dependency analysis due to an error.\n\nThe rest of the review is still valid.';
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Use AI to analyze project dependencies
110
+ * @param projectSample Sample of project files for analysis
111
+ * @returns AI-generated dependency analysis
112
+ */
113
+ async function analyzeWithAI(
114
+ projectSample: ProjectFileSample,
115
+ ): Promise<AIDependencyAnalysisResult> {
116
+ try {
117
+ // Initialize an API client based on the selected model
118
+ const client = ClientFactory.createClient();
119
+ await client.initialize();
120
+
121
+ // Prepare a detailed prompt for the AI
122
+ const prompt = createDependencyAnalysisPrompt(projectSample);
123
+
124
+ // Generate the analysis using the AI client
125
+ const analysisResponse = await client.generateReview(
126
+ prompt,
127
+ 'dependency-analysis.md',
128
+ 'architectural',
129
+ {
130
+ readme: '',
131
+ custom: {
132
+ 'DEPENDENCY_ANALYSIS_INSTRUCTIONS.md': getDependencyAnalysisInstructions(),
133
+ },
134
+ },
135
+ {
136
+ type: 'architectural',
137
+ includeTests: false,
138
+ output: 'markdown',
139
+ // @ts-expect-error - temporary property for AI dependency analysis
140
+ isAIDependencyAnalysis: true,
141
+ },
142
+ );
143
+
144
+ // Parse the AI response into structured sections
145
+ return parseDependencyAnalysisResponse(analysisResponse.content);
146
+ } catch (error) {
147
+ logger.error(
148
+ `Error generating AI dependency analysis: ${error instanceof Error ? error.message : String(error)}`,
149
+ );
150
+ throw error;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Create a prompt for dependency analysis
156
+ * @param projectSample Sample of project files
157
+ * @returns Formatted prompt for the AI
158
+ */
159
+ function createDependencyAnalysisPrompt(projectSample: ProjectFileSample): string {
160
+ // Format package files
161
+ const packageFilesSection = projectSample.packageFiles
162
+ .map((pkg) => {
163
+ return `## ${pkg.path}
164
+ \`\`\`json
165
+ "dependencies": ${JSON.stringify(pkg.dependencies || {}, null, 2)},
166
+ "devDependencies": ${JSON.stringify(pkg.devDependencies || {}, null, 2)}
167
+ \`\`\`
168
+ `;
169
+ })
170
+ .join('\n\n');
171
+
172
+ // Format source files with imports
173
+ const sourceFilesSection = projectSample.sourceFiles
174
+ .map((file) => {
175
+ return `## ${file.path} (${file.type})
176
+ ${
177
+ file.imports && file.imports.length > 0
178
+ ? `**Imports:**
179
+ ${file.imports.map((imp) => `- ${imp}`).join('\n')}`
180
+ : 'No imports found.'
181
+ }
182
+
183
+ ${
184
+ file.exports && file.exports.length > 0
185
+ ? `**Exports:**
186
+ ${file.exports.map((exp) => `- ${exp}`).join('\n')}`
187
+ : 'No exports found.'
188
+ }
189
+ `;
190
+ })
191
+ .join('\n\n');
192
+
193
+ // Create the full prompt
194
+ return `# Project Dependency Analysis Request
195
+
196
+ ## Project Overview
197
+ Total Files: ${projectSample.totalFileCount}
198
+ Sample Files Analyzed: ${projectSample.packageFiles.length + projectSample.sourceFiles.length}
199
+
200
+ ## Directory Structure
201
+ \`\`\`
202
+ ${projectSample.directoryStructure}
203
+ \`\`\`
204
+
205
+ ## Package Files
206
+ ${packageFilesSection}
207
+
208
+ ## Source File Sample
209
+ ${sourceFilesSection}
210
+
211
+ Please analyze the project dependencies and structure based on the provided information.`;
212
+ }
213
+
214
+ /**
215
+ * Get detailed instructions for the AI dependency analysis
216
+ * @returns Formatted instructions
217
+ */
218
+ function getDependencyAnalysisInstructions(): string {
219
+ return `# Dependency Analysis Instructions
220
+
221
+ You are tasked with analyzing the project dependencies and structure based on the provided sample of files.
222
+ Focus on identifying potential dependency issues, architectural patterns, and providing recommendations.
223
+
224
+ ## Analysis Requirements
225
+
226
+ 1. **Package Dependencies**:
227
+ - Analyze all package.json files
228
+ - Identify key dependencies and their purposes
229
+ - Detect potential outdated or problematic dependencies
230
+ - Note any unusual dependency patterns
231
+
232
+ 2. **Code Structure**:
233
+ - Analyze import/export patterns in the sample files
234
+ - Identify potential circular dependencies
235
+ - Note any heavily imported modules (potential core components)
236
+ - Analyze coupling between components
237
+
238
+ 3. **Architectural Issues**:
239
+ - Identify potential architectural anti-patterns
240
+ - Note any separation of concerns issues
241
+ - Detect potential dependency management issues
242
+ - Analyze project structure for architectural consistency
243
+
244
+ 4. **Recommendations**:
245
+ - Suggest improvements to dependency management
246
+ - Recommend architectural improvements based on modern practices
247
+ - Provide specific, actionable advice for dependency-related issues
248
+
249
+ ## Response Format
250
+
251
+ Organize your analysis into the following sections:
252
+
253
+ 1. **Dependency Summary**: Overview of the project's dependencies and overall structure.
254
+ 2. **Architectural Issues**: Potential problems in the dependency architecture.
255
+ 3. **Package Analysis**: Detailed analysis of package.json dependencies.
256
+ 4. **Code Structure Analysis**: Analysis of import/export patterns and module relationships.
257
+ 5. **Recommendations**: Specific suggestions for improving dependency management and architecture.
258
+
259
+ Be thorough but concise. Focus on providing actionable insights rather than just descriptions.`;
260
+ }
261
+
262
+ /**
263
+ * Parse the AI response into structured sections
264
+ * @param responseContent AI response content
265
+ * @returns Structured dependency analysis
266
+ */
267
+ function parseDependencyAnalysisResponse(responseContent: string): AIDependencyAnalysisResult {
268
+ // Helper function to extract a section from the response
269
+ const extractSection = (title: string): string => {
270
+ const regex = new RegExp(`## ${title}\\s*([\\s\\S]*?)(?=## |$)`, 'i');
271
+ const match = responseContent.match(regex);
272
+ return match ? match[1].trim() : '';
273
+ };
274
+
275
+ return {
276
+ dependencySummary: extractSection('Dependency Summary'),
277
+ architecturalIssues: extractSection('Architectural Issues'),
278
+ packageAnalysis: extractSection('Package Analysis'),
279
+ codeStructureAnalysis: extractSection('Code Structure Analysis'),
280
+ recommendations: extractSection('Recommendations'),
281
+ rawResponse: responseContent,
282
+ };
283
+ }
284
+
285
+ /**
286
+ * Format the dependency analysis as markdown
287
+ * @param analysis Dependency analysis result
288
+ * @returns Formatted markdown
289
+ */
290
+ function formatDependencyAnalysis(analysis: AIDependencyAnalysisResult): string {
291
+ return `## AI-Powered Dependency Analysis
292
+
293
+ ${analysis.dependencySummary}
294
+
295
+ ### Architectural Issues
296
+
297
+ ${analysis.architecturalIssues}
298
+
299
+ ### Package Analysis
300
+
301
+ ${analysis.packageAnalysis}
302
+
303
+ ### Code Structure Analysis
304
+
305
+ ${analysis.codeStructureAnalysis}
306
+
307
+ ### Recommendations
308
+
309
+ ${analysis.recommendations}
310
+
311
+ ---
312
+
313
+ *Note: This dependency analysis was performed by AI based on a representative sample of the codebase, without requiring additional dependencies.*`;
314
+ }
315
+
316
+ /**
317
+ * Get a representative sample of project files for analysis
318
+ * @param projectPath Path to the project
319
+ * @returns Sample of project files
320
+ */
321
+ async function getProjectFileSample(projectPath: string): Promise<ProjectFileSample> {
322
+ logger.info(`Collecting project file sample from ${projectPath}`);
323
+
324
+ // Initialize the result
325
+ const result: ProjectFileSample = {
326
+ packageFiles: [],
327
+ sourceFiles: [],
328
+ totalFileCount: 0,
329
+ directoryStructure: '',
330
+ };
331
+
332
+ try {
333
+ // Get directory structure using ls
334
+ try {
335
+ const { stdout: dirOutput } = await execAsync(`ls -la ${projectPath}`);
336
+ result.directoryStructure = dirOutput;
337
+ } catch (error) {
338
+ logger.warn(
339
+ `Error getting directory structure: ${error instanceof Error ? error.message : String(error)}`,
340
+ );
341
+ result.directoryStructure = 'Unable to retrieve directory structure';
342
+ }
343
+
344
+ // Find package.json files
345
+ let packageFilePaths: string[] = [];
346
+ try {
347
+ const { stdout: packageFilesOutput } = await execAsync(
348
+ `find ${projectPath} -name "package.json" -not -path "*/node_modules/*" -not -path "*/\\.*/*" | head -5`,
349
+ );
350
+ packageFilePaths = packageFilesOutput.trim().split('\n').filter(Boolean);
351
+ } catch (error) {
352
+ logger.warn(
353
+ `Error finding package.json files: ${error instanceof Error ? error.message : String(error)}`,
354
+ );
355
+ }
356
+
357
+ // Process each package.json file
358
+ for (const filePath of packageFilePaths) {
359
+ try {
360
+ const content = await fs.readFile(filePath, 'utf-8');
361
+ const packageJson = JSON.parse(content);
362
+
363
+ result.packageFiles.push({
364
+ path: path.relative(projectPath, filePath),
365
+ type: 'package.json',
366
+ dependencies: packageJson.dependencies || {},
367
+ devDependencies: packageJson.devDependencies || {},
368
+ });
369
+ } catch (error) {
370
+ logger.warn(
371
+ `Error processing package.json file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
372
+ );
373
+ }
374
+ }
375
+
376
+ // Get total file count (excluding node_modules and hidden directories)
377
+ try {
378
+ const { stdout: totalFilesOutput } = await execAsync(
379
+ `find ${projectPath} -type f -not -path "*/node_modules/*" -not -path "*/\\.*/*" | wc -l`,
380
+ );
381
+ result.totalFileCount = parseInt(totalFilesOutput.trim(), 10);
382
+ } catch (error) {
383
+ logger.warn(
384
+ `Error counting files: ${error instanceof Error ? error.message : String(error)}`,
385
+ );
386
+ result.totalFileCount = 0;
387
+ }
388
+
389
+ // Find source files (JS, TS, etc.)
390
+ let sourceFilePaths: string[] = [];
391
+ try {
392
+ const { stdout: sourceFilesOutput } = await execAsync(
393
+ `find ${projectPath} -type f \\( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \\) -not -path "*/node_modules/*" -not -path "*/\\.*/*" | sort -R | head -20`,
394
+ );
395
+ sourceFilePaths = sourceFilesOutput.trim().split('\n').filter(Boolean);
396
+ } catch (error) {
397
+ logger.warn(
398
+ `Error finding source files: ${error instanceof Error ? error.message : String(error)}`,
399
+ );
400
+ }
401
+
402
+ // Process each source file to extract imports
403
+ for (const filePath of sourceFilePaths) {
404
+ try {
405
+ const content = await fs.readFile(filePath, 'utf-8');
406
+
407
+ // Extract file type from extension
408
+ const fileType = path.extname(filePath).slice(1);
409
+
410
+ // Extract imports using regex
411
+ const importRegex = /import\s+(?:(?:{[^}]*})|(?:[^{}]*?))\s+from\s+['"]([^'"]+)['"]/g;
412
+ const imports: string[] = [];
413
+ let match;
414
+
415
+ while ((match = importRegex.exec(content)) !== null) {
416
+ imports.push(match[1]);
417
+ }
418
+
419
+ // Extract exports using regex
420
+ const exportRegex =
421
+ /export\s+(?:(?:default\s+)?(?:class|function|const|let|var|interface|type|enum)\s+(\w+))/g;
422
+ const exports: string[] = [];
423
+ let exportMatch;
424
+
425
+ while ((exportMatch = exportRegex.exec(content)) !== null) {
426
+ if (exportMatch[1]) {
427
+ exports.push(exportMatch[1]);
428
+ }
429
+ }
430
+
431
+ result.sourceFiles.push({
432
+ path: path.relative(projectPath, filePath),
433
+ type: fileType,
434
+ imports,
435
+ exports,
436
+ });
437
+ } catch (error) {
438
+ logger.warn(
439
+ `Error processing source file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
440
+ );
441
+ }
442
+ }
443
+
444
+ logger.info(
445
+ `Collected ${result.packageFiles.length} package files and ${result.sourceFiles.length} source files`,
446
+ );
447
+ return result;
448
+ } catch (error) {
449
+ logger.error(
450
+ `Error getting project file sample: ${error instanceof Error ? error.message : String(error)}`,
451
+ );
452
+ return result;
453
+ }
454
+ }