codereview-aia 0.1.2 → 0.1.4

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 (200) hide show
  1. package/dist/analysis/static/wpPhpcsRunner.d.ts +11 -0
  2. package/dist/analysis/static/wpPhpcsRunner.js +219 -0
  3. package/dist/analysis/static/wpPhpcsRunner.js.map +1 -0
  4. package/dist/clients/implementations/openRouterClient.js +2 -2
  5. package/dist/clients/implementations/openRouterClient.js.map +1 -1
  6. package/dist/clients/openRouterClient.js +2 -2
  7. package/dist/clients/openRouterClient.js.map +1 -1
  8. package/dist/clients/utils/promptFormatter.d.ts +3 -2
  9. package/dist/clients/utils/promptFormatter.js +82 -24
  10. package/dist/clients/utils/promptFormatter.js.map +1 -1
  11. package/dist/core/ConfigurationService.d.ts +21 -0
  12. package/dist/core/ConfigurationService.js +39 -0
  13. package/dist/core/ConfigurationService.js.map +1 -1
  14. package/dist/core/handlers/FileProcessingHandler.js +5 -0
  15. package/dist/core/handlers/FileProcessingHandler.js.map +1 -1
  16. package/dist/core/reviewOrchestrator.js +61 -1
  17. package/dist/core/reviewOrchestrator.js.map +1 -1
  18. package/dist/index.d.ts +0 -1
  19. package/dist/index.js +0 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/runtime/cliEntry.js +57 -4
  22. package/dist/runtime/cliEntry.js.map +1 -1
  23. package/dist/runtime/fileCollector.d.ts +10 -1
  24. package/dist/runtime/fileCollector.js +217 -2
  25. package/dist/runtime/fileCollector.js.map +1 -1
  26. package/dist/runtime/reporting/markdownReportBuilder.d.ts +2 -0
  27. package/dist/runtime/reporting/markdownReportBuilder.js +57 -0
  28. package/dist/runtime/reporting/markdownReportBuilder.js.map +1 -1
  29. package/dist/runtime/reviewPipeline.d.ts +22 -3
  30. package/dist/runtime/reviewPipeline.js +46 -7
  31. package/dist/runtime/reviewPipeline.js.map +1 -1
  32. package/dist/runtime/runAiCodeReview.d.ts +19 -1
  33. package/dist/runtime/runAiCodeReview.js +243 -8
  34. package/dist/runtime/runAiCodeReview.js.map +1 -1
  35. package/dist/runtime/ui/RuntimeApp.js +15 -4
  36. package/dist/runtime/ui/RuntimeApp.js.map +1 -1
  37. package/dist/runtime/ui/screens/ProgressScreen.d.ts +6 -1
  38. package/dist/runtime/ui/screens/ProgressScreen.js +28 -2
  39. package/dist/runtime/ui/screens/ProgressScreen.js.map +1 -1
  40. package/dist/runtime/ui/screens/ResultsScreen.js +8 -1
  41. package/dist/runtime/ui/screens/ResultsScreen.js.map +1 -1
  42. package/dist/types/review.d.ts +60 -0
  43. package/dist/utils/detection/frameworkDetector.js +55 -0
  44. package/dist/utils/detection/frameworkDetector.js.map +1 -1
  45. package/dist/utils/promptTemplateManager.js +1 -0
  46. package/dist/utils/promptTemplateManager.js.map +1 -1
  47. package/package.json +13 -10
  48. package/.cr-aia.yml +0 -23
  49. package/.crignore +0 -0
  50. package/src/analysis/FindingsExtractor.ts +0 -431
  51. package/src/analysis/ai-detection/analyzers/BaseAnalyzer.ts +0 -267
  52. package/src/analysis/ai-detection/analyzers/DocumentationAnalyzer.ts +0 -622
  53. package/src/analysis/ai-detection/analyzers/GitHistoryAnalyzer.ts +0 -430
  54. package/src/analysis/ai-detection/core/AIDetectionEngine.ts +0 -467
  55. package/src/analysis/ai-detection/types/DetectionTypes.ts +0 -406
  56. package/src/analysis/ai-detection/utils/SubmissionConverter.ts +0 -390
  57. package/src/analysis/context/ReviewContext.ts +0 -378
  58. package/src/analysis/context/index.ts +0 -7
  59. package/src/analysis/index.ts +0 -8
  60. package/src/analysis/tokens/TokenAnalysisFormatter.ts +0 -154
  61. package/src/analysis/tokens/TokenAnalyzer.ts +0 -747
  62. package/src/analysis/tokens/index.ts +0 -8
  63. package/src/clients/base/abstractClient.ts +0 -190
  64. package/src/clients/base/httpClient.ts +0 -160
  65. package/src/clients/base/index.ts +0 -12
  66. package/src/clients/base/modelDetection.ts +0 -107
  67. package/src/clients/base/responseProcessor.ts +0 -586
  68. package/src/clients/factory/clientFactory.ts +0 -55
  69. package/src/clients/factory/index.ts +0 -8
  70. package/src/clients/implementations/index.ts +0 -8
  71. package/src/clients/implementations/openRouterClient.ts +0 -411
  72. package/src/clients/openRouterClient.ts +0 -863
  73. package/src/clients/openRouterClientWrapper.ts +0 -44
  74. package/src/clients/utils/directoryStructure.ts +0 -52
  75. package/src/clients/utils/index.ts +0 -11
  76. package/src/clients/utils/languageDetection.ts +0 -44
  77. package/src/clients/utils/promptFormatter.ts +0 -105
  78. package/src/clients/utils/promptLoader.ts +0 -53
  79. package/src/clients/utils/tokenCounter.ts +0 -297
  80. package/src/core/ApiClientSelector.ts +0 -37
  81. package/src/core/ConfigurationService.ts +0 -591
  82. package/src/core/ConsolidationService.ts +0 -423
  83. package/src/core/InteractiveDisplayManager.ts +0 -81
  84. package/src/core/OutputManager.ts +0 -275
  85. package/src/core/ReviewGenerator.ts +0 -140
  86. package/src/core/fileDiscovery.ts +0 -237
  87. package/src/core/handlers/EstimationHandler.ts +0 -104
  88. package/src/core/handlers/FileProcessingHandler.ts +0 -204
  89. package/src/core/handlers/OutputHandler.ts +0 -125
  90. package/src/core/handlers/ReviewExecutor.ts +0 -104
  91. package/src/core/reviewOrchestrator.ts +0 -333
  92. package/src/core/utils/ModelInfoUtils.ts +0 -56
  93. package/src/formatters/outputFormatter.ts +0 -62
  94. package/src/formatters/utils/IssueFormatters.ts +0 -83
  95. package/src/formatters/utils/JsonFormatter.ts +0 -77
  96. package/src/formatters/utils/MarkdownFormatters.ts +0 -609
  97. package/src/formatters/utils/MetadataFormatter.ts +0 -269
  98. package/src/formatters/utils/ModelInfoExtractor.ts +0 -115
  99. package/src/index.ts +0 -28
  100. package/src/plugins/PluginInterface.ts +0 -50
  101. package/src/plugins/PluginManager.ts +0 -126
  102. package/src/prompts/PromptManager.ts +0 -69
  103. package/src/prompts/cache/PromptCache.ts +0 -50
  104. package/src/prompts/promptText/common/variables/css-frameworks.json +0 -33
  105. package/src/prompts/promptText/common/variables/framework-versions.json +0 -45
  106. package/src/prompts/promptText/frameworks/react/comprehensive.hbs +0 -19
  107. package/src/prompts/promptText/languages/css/comprehensive.hbs +0 -18
  108. package/src/prompts/promptText/languages/generic/comprehensive.hbs +0 -20
  109. package/src/prompts/promptText/languages/html/comprehensive.hbs +0 -18
  110. package/src/prompts/promptText/languages/javascript/comprehensive.hbs +0 -18
  111. package/src/prompts/promptText/languages/python/comprehensive.hbs +0 -18
  112. package/src/prompts/promptText/languages/typescript/comprehensive.hbs +0 -18
  113. package/src/runtime/auth/service.ts +0 -58
  114. package/src/runtime/auth/session.ts +0 -103
  115. package/src/runtime/auth/types.ts +0 -11
  116. package/src/runtime/cliEntry.ts +0 -196
  117. package/src/runtime/debug/logManager.ts +0 -37
  118. package/src/runtime/errors.ts +0 -13
  119. package/src/runtime/fileCollector.ts +0 -222
  120. package/src/runtime/manifest.ts +0 -64
  121. package/src/runtime/openrouterProxy.ts +0 -45
  122. package/src/runtime/preprod/webCheck.ts +0 -104
  123. package/src/runtime/proxyConfig.ts +0 -94
  124. package/src/runtime/proxyEnvironment.ts +0 -71
  125. package/src/runtime/reportMerge.ts +0 -102
  126. package/src/runtime/reporting/markdownReportBuilder.ts +0 -138
  127. package/src/runtime/reporting/reportDataCollector.ts +0 -234
  128. package/src/runtime/reporting/summaryGenerator.ts +0 -86
  129. package/src/runtime/reviewPipeline.ts +0 -161
  130. package/src/runtime/runAiCodeReview.ts +0 -153
  131. package/src/runtime/runtimeConfig.ts +0 -5
  132. package/src/runtime/ui/Layout.tsx +0 -57
  133. package/src/runtime/ui/RuntimeApp.tsx +0 -233
  134. package/src/runtime/ui/inkModules.ts +0 -73
  135. package/src/runtime/ui/screens/AuthScreen.tsx +0 -128
  136. package/src/runtime/ui/screens/ModeSelection.tsx +0 -185
  137. package/src/runtime/ui/screens/ProgressScreen.tsx +0 -62
  138. package/src/runtime/ui/screens/ResultsScreen.tsx +0 -83
  139. package/src/strategies/ArchitecturalReviewStrategy.ts +0 -54
  140. package/src/strategies/CodingTestReviewStrategy.ts +0 -920
  141. package/src/strategies/ConsolidatedReviewStrategy.ts +0 -59
  142. package/src/strategies/ExtractPatternsReviewStrategy.ts +0 -64
  143. package/src/strategies/MultiPassReviewStrategy.ts +0 -785
  144. package/src/strategies/ReviewStrategy.ts +0 -64
  145. package/src/strategies/StrategyFactory.ts +0 -79
  146. package/src/strategies/index.ts +0 -14
  147. package/src/tokenizers/baseTokenizer.ts +0 -61
  148. package/src/tokenizers/gptTokenizer.ts +0 -27
  149. package/src/tokenizers/index.ts +0 -8
  150. package/src/types/apiResponses.ts +0 -40
  151. package/src/types/cli.ts +0 -24
  152. package/src/types/common.ts +0 -39
  153. package/src/types/configuration.ts +0 -201
  154. package/src/types/handlebars.d.ts +0 -5
  155. package/src/types/patch.d.ts +0 -25
  156. package/src/types/review.ts +0 -294
  157. package/src/types/reviewContext.d.ts +0 -65
  158. package/src/types/reviewSchema.ts +0 -181
  159. package/src/types/structuredReview.ts +0 -167
  160. package/src/types/tokenAnalysis.ts +0 -56
  161. package/src/utils/FileReader.ts +0 -93
  162. package/src/utils/FileWriter.ts +0 -76
  163. package/src/utils/PathGenerator.ts +0 -97
  164. package/src/utils/api/apiUtils.ts +0 -14
  165. package/src/utils/api/index.ts +0 -1
  166. package/src/utils/apiErrorHandler.ts +0 -287
  167. package/src/utils/ciDataCollector.ts +0 -252
  168. package/src/utils/codingTestConfigLoader.ts +0 -466
  169. package/src/utils/dependencies/aiDependencyAnalyzer.ts +0 -454
  170. package/src/utils/detection/frameworkDetector.ts +0 -879
  171. package/src/utils/detection/index.ts +0 -10
  172. package/src/utils/detection/projectTypeDetector.ts +0 -518
  173. package/src/utils/diagramGenerator.ts +0 -206
  174. package/src/utils/errorLogger.ts +0 -60
  175. package/src/utils/estimationUtils.ts +0 -407
  176. package/src/utils/fileFilters.ts +0 -373
  177. package/src/utils/fileSystem.ts +0 -57
  178. package/src/utils/index.ts +0 -36
  179. package/src/utils/logger.ts +0 -290
  180. package/src/utils/pathValidator.ts +0 -98
  181. package/src/utils/priorityFilter.ts +0 -59
  182. package/src/utils/projectDocs.ts +0 -189
  183. package/src/utils/promptPaths.ts +0 -29
  184. package/src/utils/promptTemplateManager.ts +0 -157
  185. package/src/utils/review/consolidateReview.ts +0 -553
  186. package/src/utils/review/fixDisplay.ts +0 -100
  187. package/src/utils/review/fixImplementation.ts +0 -61
  188. package/src/utils/review/index.ts +0 -36
  189. package/src/utils/review/interactiveProcessing.ts +0 -294
  190. package/src/utils/review/progressTracker.ts +0 -296
  191. package/src/utils/review/reviewExtraction.ts +0 -382
  192. package/src/utils/review/types.ts +0 -46
  193. package/src/utils/reviewActionHandler.ts +0 -18
  194. package/src/utils/reviewParser.ts +0 -253
  195. package/src/utils/sanitizer.ts +0 -238
  196. package/src/utils/smartFileSelector.ts +0 -255
  197. package/src/utils/templateLoader.ts +0 -514
  198. package/src/utils/treeGenerator.ts +0 -153
  199. package/tsconfig.build.json +0 -14
  200. package/tsconfig.json +0 -59
@@ -1,56 +0,0 @@
1
- /** Token analysis primitives shared across the CLI. */
2
-
3
- import type { FileInfo } from './review';
4
-
5
- export interface FileTokenAnalysis {
6
- path: string;
7
- relativePath: string | undefined;
8
- tokenCount: number;
9
- sizeInBytes: number;
10
- tokensPerByte: number;
11
- }
12
-
13
- export interface TokenAnalysisResult {
14
- files: FileTokenAnalysis[];
15
- totalTokens: number;
16
- totalSizeInBytes: number;
17
- averageTokensPerByte: number;
18
- fileCount: number;
19
- promptOverheadTokens: number;
20
- estimatedTotalTokens: number;
21
- contextWindowSize: number;
22
- exceedsContextWindow: boolean;
23
- estimatedPassesNeeded: number;
24
- chunkingRecommendation: ChunkingRecommendation;
25
- }
26
-
27
- export interface ChunkingRecommendation {
28
- chunkingRecommended: boolean;
29
- recommendedChunks: FileChunk[];
30
- reason: string;
31
- }
32
-
33
- export interface FileChunk {
34
- files: string[];
35
- estimatedTokenCount: number;
36
- priority: number;
37
- }
38
-
39
- export interface TokenAnalysisOptions {
40
- reviewType: string;
41
- modelName: string;
42
- optimizeForSpeed?: boolean;
43
- additionalPromptOverhead?: number;
44
- contextMaintenanceFactor?: number;
45
- }
46
-
47
- export declare class TokenAnalyzer {
48
- static analyzeFile(file: FileInfo, options: TokenAnalysisOptions): FileTokenAnalysis;
49
- static analyzeFiles(files: FileInfo[], options: TokenAnalysisOptions): TokenAnalysisResult;
50
- }
51
-
52
- export declare function formatTokenAnalysis(
53
- analysis: TokenAnalysisResult,
54
- modelName: string,
55
- includeFiles?: boolean,
56
- ): string;
@@ -1,93 +0,0 @@
1
- /**
2
- * @fileoverview File reading utilities.
3
- *
4
- * This module provides utilities for reading files and directories,
5
- * with error handling and logging.
6
- */
7
-
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
10
- import type { FileInfo } from '../types/review';
11
- import logger from './logger';
12
-
13
- /**
14
- * Read a file and return its content
15
- * @param filePath Path to the file
16
- * @returns Promise resolving to the file content
17
- * @throws Error if the file cannot be read
18
- */
19
- export async function readFile(filePath: string): Promise<string> {
20
- try {
21
- return await fs.readFile(filePath, 'utf-8');
22
- } catch (error) {
23
- logger.error(
24
- `Error reading file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
25
- );
26
- throw error;
27
- }
28
- }
29
-
30
- /**
31
- * Read a file and return its content with file info
32
- * @param filePath Path to the file
33
- * @returns Promise resolving to a FileInfo object
34
- */
35
- export async function readFileWithInfo(filePath: string): Promise<FileInfo> {
36
- try {
37
- const content = await fs.readFile(filePath, 'utf-8');
38
- const extension = path.extname(filePath).slice(1);
39
-
40
- return {
41
- path: filePath,
42
- content,
43
- extension,
44
- };
45
- } catch (error) {
46
- logger.error(
47
- `Error reading file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
48
- );
49
- throw error;
50
- }
51
- }
52
-
53
- /**
54
- * Read multiple files and return their contents with file info
55
- * @param filePaths Array of file paths
56
- * @returns Promise resolving to an array of FileInfo objects
57
- */
58
- export async function readFilesWithInfo(filePaths: string[]): Promise<FileInfo[]> {
59
- const fileInfoPromises = filePaths.map((filePath) => readFileWithInfo(filePath));
60
- return Promise.all(fileInfoPromises);
61
- }
62
-
63
- /**
64
- * Read all files in a directory recursively
65
- * @param dirPath Path to the directory
66
- * @param filter Optional filter function to exclude certain files
67
- * @returns Promise resolving to an array of file paths
68
- */
69
- export async function readFilesInDirectory(
70
- dirPath: string,
71
- filter?: (filePath: string) => boolean,
72
- ): Promise<string[]> {
73
- const result: string[] = [];
74
-
75
- async function processDirectory(currentPath: string) {
76
- const entries = await fs.readdir(currentPath, { withFileTypes: true });
77
-
78
- for (const entry of entries) {
79
- const entryPath = path.join(currentPath, entry.name);
80
-
81
- if (entry.isDirectory()) {
82
- await processDirectory(entryPath);
83
- } else if (entry.isFile()) {
84
- if (!filter || filter(entryPath)) {
85
- result.push(entryPath);
86
- }
87
- }
88
- }
89
- }
90
-
91
- await processDirectory(dirPath);
92
- return result;
93
- }
@@ -1,76 +0,0 @@
1
- /**
2
- * @fileoverview File writing utilities.
3
- *
4
- * This module provides utilities for writing files and creating directories,
5
- * with error handling and logging.
6
- */
7
-
8
- import fs from 'node:fs/promises';
9
- import path from 'node:path';
10
- import logger from './logger';
11
- import { pathExists } from './pathValidator';
12
-
13
- /**
14
- * Create a directory if it doesn't exist
15
- * @param dirPath Path to the directory
16
- * @returns Promise resolving when the directory is created or already exists
17
- */
18
- export async function ensureDirectoryExists(dirPath: string): Promise<void> {
19
- try {
20
- if (!pathExists(dirPath)) {
21
- await fs.mkdir(dirPath, { recursive: true });
22
- logger.debug(`Created directory: ${dirPath}`);
23
- }
24
- } catch (error) {
25
- logger.error(
26
- `Error creating directory ${dirPath}: ${error instanceof Error ? error.message : String(error)}`,
27
- );
28
- throw error;
29
- }
30
- }
31
-
32
- /**
33
- * Write content to a file, creating the directory if needed
34
- * @param filePath Path to the file
35
- * @param content Content to write
36
- * @returns Promise resolving when the file is written
37
- */
38
- export async function writeFile(filePath: string, content: string): Promise<void> {
39
- try {
40
- // Ensure the directory exists
41
- const dirPath = path.dirname(filePath);
42
- await ensureDirectoryExists(dirPath);
43
-
44
- // Write the file
45
- await fs.writeFile(filePath, content);
46
- logger.debug(`Wrote file: ${filePath}`);
47
- } catch (error) {
48
- logger.error(
49
- `Error writing file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
50
- );
51
- throw error;
52
- }
53
- }
54
-
55
- /**
56
- * Append content to a file, creating the file if it doesn't exist
57
- * @param filePath Path to the file
58
- * @param content Content to append
59
- * @returns Promise resolving when the content is appended
60
- */
61
- export async function appendFile(filePath: string, content: string): Promise<void> {
62
- try {
63
- // Ensure the directory exists
64
- const dirPath = path.dirname(filePath);
65
- await ensureDirectoryExists(dirPath);
66
-
67
- // Append to the file
68
- await fs.appendFile(filePath, content);
69
- logger.debug(`Appended to file: ${filePath}`);
70
- } catch (error) {
71
- logger.error(
72
- `Error appending to file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
73
- );
74
- throw error;
75
- }
76
- }
@@ -1,97 +0,0 @@
1
- /**
2
- * @fileoverview Path generation utilities.
3
- *
4
- * This module provides utilities for generating file and directory paths,
5
- * including versioned output paths for review results.
6
- */
7
-
8
- import path from 'node:path';
9
- import { ensureDirectoryExists } from './FileWriter';
10
- import { pathExists } from './pathValidator';
11
-
12
- /**
13
- * Generate a versioned output path for a file
14
- * @param baseDir Base directory for the output
15
- * @param prefix Prefix for the filename
16
- * @param extension File extension (including the dot)
17
- * @param modelName Name of the model used for the review
18
- * @param targetName Name of the target file or directory
19
- * @returns Promise resolving to the generated path
20
- */
21
- export async function generateVersionedOutputPath(
22
- baseDir: string,
23
- prefix: string,
24
- extension: string,
25
- modelName: string,
26
- targetName: string,
27
- ): Promise<string> {
28
- // Ensure the output directory exists
29
- await ensureDirectoryExists(baseDir);
30
-
31
- // Generate a timestamp for the filename
32
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
33
-
34
- // Clean up the model name for use in a filename
35
- const cleanModelName = modelName.replace(/[^a-zA-Z0-9-]/g, '-');
36
-
37
- // Clean up the target name for use in a filename
38
- let cleanTargetName = targetName.replace(/[^a-zA-Z0-9-]/g, '-');
39
-
40
- // Handle special cases for target names
41
- if (targetName === '.' || cleanTargetName === '-' || cleanTargetName === '') {
42
- cleanTargetName = 'current-dir';
43
- }
44
-
45
- // Remove any sequential dashes
46
- cleanTargetName = cleanTargetName.replace(/-+/g, '-').replace(/^-|-$/g, '');
47
-
48
- // Generate the filename
49
- const filename = `${prefix}-${cleanTargetName}-${cleanModelName}-${timestamp}${extension}`;
50
-
51
- // Return the full path
52
- return path.join(baseDir, filename);
53
- }
54
-
55
- /**
56
- * Generate an output path for a file with a unique name
57
- * @param baseDir Base directory for the output
58
- * @param filename Desired filename
59
- * @returns Promise resolving to the generated path
60
- */
61
- export async function generateUniqueOutputPath(baseDir: string, filename: string): Promise<string> {
62
- // Ensure the output directory exists
63
- await ensureDirectoryExists(baseDir);
64
-
65
- // Generate the initial path
66
- let outputPath = path.join(baseDir, filename);
67
-
68
- // If the file already exists, add a number to the filename
69
- if (await pathExists(outputPath)) {
70
- const extension = path.extname(filename);
71
- const nameWithoutExtension = path.basename(filename, extension);
72
- let counter = 1;
73
-
74
- // Try different numbers until we find an available filename
75
- while (await pathExists(outputPath)) {
76
- outputPath = path.join(baseDir, `${nameWithoutExtension}-${counter}${extension}`);
77
- counter++;
78
- }
79
- }
80
-
81
- return outputPath;
82
- }
83
-
84
- /**
85
- * Generate a temporary file path
86
- * @param prefix Prefix for the filename
87
- * @param extension File extension (including the dot)
88
- * @returns Generated temporary file path
89
- */
90
- export function generateTempFilePath(prefix: string, extension: string): string {
91
- const timestamp = Date.now();
92
- const randomPart = Math.floor(Math.random() * 10000);
93
- return path.join(
94
- process.env.TEMP || process.env.TMP || '/tmp',
95
- `${prefix}-${timestamp}-${randomPart}${extension}`,
96
- );
97
- }
@@ -1,14 +0,0 @@
1
- import logger from '../logger';
2
-
3
- export function hasApiKey(provider: string): boolean {
4
- return provider.toLowerCase() === 'openrouter';
5
- }
6
-
7
- export function getApiKeyType(): 'OpenRouter' | null {
8
- logger.debug('getApiKeyType: defaulting to OpenRouter proxy');
9
- return 'OpenRouter';
10
- }
11
-
12
- export function getApiKeyTypeLowerCase(): 'openrouter' | 'none' {
13
- return 'openrouter';
14
- }
@@ -1 +0,0 @@
1
- export * from './apiUtils';
@@ -1,287 +0,0 @@
1
- /**
2
- * @fileoverview API error handling utilities.
3
- *
4
- * This module provides standardized error handling for API calls,
5
- * including custom error classes for different types of API errors,
6
- * utility functions for handling fetch responses, and logging helpers.
7
- */
8
-
9
- import logger from './logger';
10
-
11
- /**
12
- * Base class for API errors
13
- *
14
- * This class extends the standard Error class to provide additional context
15
- * for API-related errors. It includes properties for the HTTP status code
16
- * and additional error details from the API response.
17
- *
18
- * All specific API error types (like AuthenticationError, RateLimitError, etc.)
19
- * extend this base class to provide a consistent error handling interface.
20
- */
21
- export class ApiError extends Error {
22
- constructor(
23
- message: string,
24
- public statusCode?: number,
25
- public details?: unknown,
26
- ) {
27
- super(message);
28
- this.name = 'ApiError';
29
- // Ensure instanceof works correctly in ES5
30
- Object.setPrototypeOf(this, ApiError.prototype);
31
- }
32
- }
33
-
34
- /**
35
- * Error thrown when API rate limits are exceeded
36
- */
37
- export class RateLimitError extends ApiError {
38
- constructor(
39
- message: string,
40
- public retryAfter?: number,
41
- statusCode?: number,
42
- details?: unknown,
43
- ) {
44
- super(message, statusCode, details);
45
- this.name = 'RateLimitError';
46
- // Ensure instanceof works correctly in ES5
47
- Object.setPrototypeOf(this, RateLimitError.prototype);
48
- }
49
- }
50
-
51
- /**
52
- * Error thrown when authentication fails
53
- */
54
- export class AuthenticationError extends ApiError {
55
- constructor(message: string, statusCode?: number, details?: unknown) {
56
- super(message, statusCode, details);
57
- this.name = 'AuthenticationError';
58
- // Ensure instanceof works correctly in ES5
59
- Object.setPrototypeOf(this, AuthenticationError.prototype);
60
- }
61
- }
62
-
63
- /**
64
- * Error thrown when a resource is not found
65
- */
66
- export class NotFoundError extends ApiError {
67
- constructor(message: string, statusCode?: number, details?: unknown) {
68
- super(message, statusCode, details);
69
- this.name = 'NotFoundError';
70
- // Ensure instanceof works correctly in ES5
71
- Object.setPrototypeOf(this, NotFoundError.prototype);
72
- }
73
- }
74
-
75
- /**
76
- * Error thrown when the API returns an invalid response format
77
- */
78
- export class InvalidResponseError extends ApiError {
79
- constructor(message: string, statusCode?: number, details?: unknown) {
80
- super(message, statusCode, details);
81
- this.name = 'InvalidResponseError';
82
- // Ensure instanceof works correctly in ES5
83
- Object.setPrototypeOf(this, InvalidResponseError.prototype);
84
- }
85
- }
86
-
87
- /**
88
- * Error thrown when token limit is exceeded
89
- */
90
- export class TokenLimitError extends ApiError {
91
- constructor(
92
- message: string,
93
- public tokenCount?: number,
94
- public tokenLimit?: number,
95
- statusCode?: number,
96
- details?: unknown,
97
- ) {
98
- super(message, statusCode, details);
99
- this.name = 'TokenLimitError';
100
- // Ensure instanceof works correctly in ES5
101
- Object.setPrototypeOf(this, TokenLimitError.prototype);
102
- }
103
- }
104
-
105
- /**
106
- * Handle a fetch response and throw appropriate errors if needed
107
- *
108
- * This function processes a fetch response and throws appropriate error types
109
- * based on the HTTP status code and response body. It handles common API error
110
- * scenarios like authentication failures, rate limiting, and resource not found.
111
- *
112
- * The function attempts to parse the response body as JSON if possible, or falls
113
- * back to text if not. It then constructs an appropriate error object with
114
- * detailed information about what went wrong.
115
- *
116
- * @param response The fetch response object from an API call
117
- * @param apiName The name of the API being called (for logging and error messages)
118
- * @returns The original response object if the response is ok (status 200-299)
119
- * @throws AuthenticationError for 401/403 status codes (authentication/authorization issues)
120
- * @throws NotFoundError for 404 status codes (resource not found)
121
- * @throws RateLimitError for 429 status codes (rate limit exceeded)
122
- * @throws ApiError for all other error status codes
123
- * @example
124
- * try {
125
- * const response = await fetch('https://api.example.com/data');
126
- * await handleFetchResponse(response, 'ExampleAPI');
127
- * // Process successful response
128
- * } catch (error) {
129
- * // Error is already logged and has the appropriate type
130
- * if (error instanceof RateLimitError) {
131
- * // Handle rate limiting specifically
132
- * }
133
- * }
134
- */
135
- export async function handleFetchResponse(response: Response, apiName: string): Promise<Response> {
136
- if (!response.ok) {
137
- // Try to get the error body
138
- let errorBody: string | object = 'Unknown error';
139
- try {
140
- // Clone the response so we can read it multiple times if needed
141
- // const clonedResponse = response.clone();
142
-
143
- // Log all headers for debugging
144
- console.log(`[DEBUG] ${apiName} API response headers:`);
145
- response.headers.forEach((value: string, name: string) => {
146
- console.log(`[DEBUG] ${name}: ${value}`);
147
- });
148
-
149
- // Try to parse as JSON first
150
- const contentType = response.headers.get('content-type');
151
- console.log(`[DEBUG] Content-Type: ${contentType}`);
152
-
153
- if (contentType?.includes('application/json')) {
154
- errorBody = await response.json();
155
- console.log(`[DEBUG] JSON error body: ${JSON.stringify(errorBody)}`);
156
- } else {
157
- errorBody = await response.text();
158
- console.log(`[DEBUG] Text error body: ${errorBody}`);
159
- }
160
- } catch (e) {
161
- // Log body read errors
162
- console.log(
163
- `[DEBUG] Failed to read error body: ${e instanceof Error ? e.message : String(e)}`,
164
- );
165
- logger.debug(`Failed to read error body: ${e instanceof Error ? e.message : String(e)}`);
166
- }
167
-
168
- // Create appropriate error based on status code
169
- const errorMessage = `${apiName} API error! Status: ${response.status}, Response: ${
170
- typeof errorBody === 'string' ? errorBody : JSON.stringify(errorBody)
171
- }`;
172
-
173
- // Log the error
174
- logger.error(errorMessage);
175
-
176
- // Throw appropriate error based on status code
177
- if (response.status === 401 || response.status === 403) {
178
- throw new AuthenticationError(errorMessage, response.status, errorBody);
179
- }
180
- if (response.status === 404) {
181
- throw new NotFoundError(errorMessage, response.status, errorBody);
182
- }
183
- if (response.status === 429) {
184
- // Check for retry-after header
185
- const retryAfter = response.headers.get('retry-after');
186
- const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : undefined;
187
-
188
- throw new RateLimitError(errorMessage, retryAfterSeconds, response.status, errorBody);
189
- }
190
- throw new ApiError(errorMessage, response.status, errorBody);
191
- }
192
-
193
- return response;
194
- }
195
-
196
- /**
197
- * Safely parse JSON from a response
198
- * @param response The fetch response object
199
- * @param apiName The name of the API being called (for logging)
200
- * @returns The parsed JSON data
201
- * @throws InvalidResponseError if the response cannot be parsed as JSON
202
- */
203
- export async function safeJsonParse<T>(response: Response | any, apiName: string): Promise<T> {
204
- try {
205
- return (await response.json()) as T;
206
- } catch (error) {
207
- const errorMessage = `Failed to parse ${apiName} API response as JSON: ${
208
- error instanceof Error ? error.message : String(error)
209
- }`;
210
- logger.error(errorMessage);
211
- throw new InvalidResponseError(errorMessage);
212
- }
213
- }
214
-
215
- /**
216
- * Log an API error with appropriate context and formatting
217
- *
218
- * This function logs API errors with rich context information to help with debugging
219
- * and troubleshooting. It detects the specific type of error and formats the log
220
- * message accordingly, providing different information based on the error type.
221
- *
222
- * The function handles various error types including:
223
- * - Rate limit errors (with retry information)
224
- * - Authentication errors
225
- * - Resource not found errors
226
- * - Invalid response errors
227
- * - General API errors
228
- * - Unexpected errors
229
- *
230
- * @param error The error object that was thrown
231
- * @param context Object containing context information:
232
- * - apiName: The name of the API service (e.g., 'OpenAI', 'Anthropic')
233
- * - operation: The operation being performed (e.g., 'generating review')
234
- * - url: Optional URL for the request that failed
235
- * @example
236
- * try {
237
- * // API call that might fail
238
- * } catch (error) {
239
- * logApiError(error, {
240
- * apiName: 'OpenAI',
241
- * operation: 'generating code review',
242
- * url: 'https://api.openai.com/v1/chat/completions'
243
- * });
244
- * }
245
- */
246
- export function logApiError(
247
- error: unknown,
248
- context: { operation: string; url?: string; apiName: string },
249
- ): void {
250
- const { operation, url, apiName } = context;
251
-
252
- if (error instanceof RateLimitError) {
253
- logger.warn(
254
- `Rate limit exceeded for ${apiName} API during ${operation}${
255
- url ? ` (${url})` : ''
256
- }. Retry after: ${error.retryAfter || 'unknown'} seconds.`,
257
- );
258
- } else if (error instanceof AuthenticationError) {
259
- logger.error(
260
- `Authentication failed for ${apiName} API during ${operation}${
261
- url ? ` (${url})` : ''
262
- }. Check your API key.`,
263
- );
264
- } else if (error instanceof NotFoundError) {
265
- logger.error(
266
- `Resource not found on ${apiName} API during ${operation}${
267
- url ? ` (${url})` : ''
268
- }. Check your request parameters.`,
269
- );
270
- } else if (error instanceof InvalidResponseError) {
271
- logger.error(
272
- `Invalid response from ${apiName} API during ${operation}${
273
- url ? ` (${url})` : ''
274
- }. The API may have changed or returned an unexpected format.`,
275
- );
276
- } else if (error instanceof ApiError) {
277
- logger.error(
278
- `API error from ${apiName} during ${operation}${url ? ` (${url})` : ''}: ${error.message}`,
279
- );
280
- } else {
281
- logger.error(
282
- `Unexpected error during ${apiName} API ${operation}${
283
- url ? ` (${url})` : ''
284
- }: ${error instanceof Error ? error.message : String(error)}`,
285
- );
286
- }
287
- }