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,98 @@
1
+ /**
2
+ * @fileoverview Path validation utilities.
3
+ *
4
+ * This module provides utilities for validating file and directory paths,
5
+ * ensuring they are safe to use and exist on the file system.
6
+ */
7
+
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+
11
+ /**
12
+ * Check if a path is within the current directory or its subdirectories
13
+ * @param targetPath Path to check
14
+ * @returns True if the path is within the current directory, false otherwise
15
+ */
16
+ export function isPathWithinCwd(targetPath: string): boolean {
17
+ const resolvedPath = path.resolve(targetPath);
18
+ const resolvedCwd = path.resolve(process.cwd());
19
+
20
+ return resolvedPath.startsWith(resolvedCwd);
21
+ }
22
+
23
+ /**
24
+ * Check if a path exists
25
+ * @param targetPath Path to check
26
+ * @returns True if the path exists, false otherwise
27
+ */
28
+ export function pathExists(targetPath: string): boolean {
29
+ try {
30
+ fs.accessSync(targetPath);
31
+ return true;
32
+ } catch (_error) {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Check if a path is a directory
39
+ * @param targetPath Path to check
40
+ * @returns True if the path is a directory, false otherwise
41
+ */
42
+ export function isDirectory(targetPath: string): boolean {
43
+ try {
44
+ return fs.statSync(targetPath).isDirectory();
45
+ } catch (_error) {
46
+ return false;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Check if a path is a file
52
+ * @param targetPath Path to check
53
+ * @returns True if the path is a file, false otherwise
54
+ */
55
+ export function isFile(targetPath: string): boolean {
56
+ try {
57
+ return fs.statSync(targetPath).isFile();
58
+ } catch (_error) {
59
+ return false;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Validate a target path for security and existence
65
+ * @param targetPath Path to validate
66
+ * @returns Object with validation results
67
+ */
68
+ export function validateTargetPath(targetPath: string): {
69
+ isValid: boolean;
70
+ isDir: boolean;
71
+ error?: string;
72
+ } {
73
+ // Check if the path is within the current directory
74
+ if (!isPathWithinCwd(targetPath)) {
75
+ return {
76
+ isValid: false,
77
+ isDir: false,
78
+ error: `Path must be within the current directory: ${process.cwd()}`,
79
+ };
80
+ }
81
+
82
+ // Check if the path exists
83
+ if (!pathExists(targetPath)) {
84
+ return {
85
+ isValid: false,
86
+ isDir: false,
87
+ error: `Path does not exist: ${targetPath}`,
88
+ };
89
+ }
90
+
91
+ // Check if the path is a directory or file
92
+ const isDir = isDirectory(targetPath);
93
+
94
+ return {
95
+ isValid: true,
96
+ isDir,
97
+ };
98
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview Utility functions for handling priority filters.
3
+ *
4
+ * This module provides utility functions for working with priority filters
5
+ * in interactive mode, including extracting priority filters from command line
6
+ * arguments and review options.
7
+ */
8
+
9
+ import type { ReviewOptions } from '../types/review';
10
+ import type { PriorityFilter } from '../types/common';
11
+
12
+ /**
13
+ * Get the priority filter from command line arguments or options
14
+ *
15
+ * This function extracts the priority filter from either:
16
+ * 1. The options object (if the interactive property is a string)
17
+ * 2. The command line arguments (if --interactive or -i is followed by a priority filter)
18
+ *
19
+ * Priority filters determine which issues to display in interactive mode:
20
+ * - 'h': High priority issues only
21
+ * - 'm': Medium and high priority issues
22
+ * - 'l': Low, medium, and high priority issues
23
+ * - 'a': All issues (including informational)
24
+ *
25
+ * @param options Review options that may contain the priority filter
26
+ * @returns The priority filter (h, m, l, or a) or undefined if not specified
27
+ * @example
28
+ * // With options object
29
+ * const filter = getPriorityFilterFromArgs({ interactive: 'h' });
30
+ * // filter === 'h'
31
+ *
32
+ * // With command line arguments (if process.argv includes '--interactive h')
33
+ * const filter = getPriorityFilterFromArgs();
34
+ * // filter === 'h'
35
+ */
36
+ export function getPriorityFilterFromArgs(options?: ReviewOptions): PriorityFilter | undefined {
37
+ // First check if the interactive option is a string (priority filter)
38
+ if (
39
+ options &&
40
+ typeof options.interactive === 'string' &&
41
+ ['h', 'm', 'l', 'a'].includes(options.interactive)
42
+ ) {
43
+ return options.interactive as PriorityFilter;
44
+ }
45
+
46
+ // Otherwise check if there's a priority filter argument after --interactive
47
+ const args = process.argv;
48
+ const interactiveIndex = args.findIndex((arg) => arg === '--interactive' || arg === '-i');
49
+
50
+ if (interactiveIndex !== -1 && interactiveIndex < args.length - 1) {
51
+ const nextArg = args[interactiveIndex + 1];
52
+ // Check if the next argument is a priority filter and not another option
53
+ if (['h', 'm', 'l', 'a'].includes(nextArg) && !nextArg.startsWith('-')) {
54
+ return nextArg as PriorityFilter;
55
+ }
56
+ }
57
+
58
+ return undefined;
59
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @fileoverview Utilities for reading and processing project documentation.
3
+ *
4
+ * This module provides functionality for reading and processing project documentation
5
+ * files like README.md, PROJECT.md, and PROGRESS.md. These files provide important
6
+ * context for code reviews, helping the AI model understand the project's purpose,
7
+ * structure, and current state.
8
+ */
9
+
10
+ import fs from 'node:fs/promises';
11
+ import path from 'node:path';
12
+ import { fileExists } from './fileSystem';
13
+ import logger from './logger';
14
+
15
+ /**
16
+ * Project documentation interface
17
+ */
18
+ export interface ProjectDocs {
19
+ readme?: string;
20
+ project?: string;
21
+ progress?: string;
22
+ contributing?: string;
23
+ architecture?: string;
24
+ custom?: Record<string, string>;
25
+ metadata?: Record<string, string>;
26
+ }
27
+
28
+ /**
29
+ * Maximum size for documentation files (in characters)
30
+ * This helps prevent token limit issues
31
+ */
32
+ const MAX_DOC_SIZE = 50000;
33
+
34
+ /**
35
+ * Read a documentation file if it exists
36
+ * @param filePath File path
37
+ * @returns File content or undefined if the file doesn't exist
38
+ */
39
+ async function readDocFile(filePath: string): Promise<string | undefined> {
40
+ try {
41
+ if (await fileExists(filePath)) {
42
+ const content = await fs.readFile(filePath, 'utf-8');
43
+
44
+ // Truncate if too large
45
+ if (content.length > MAX_DOC_SIZE) {
46
+ logger.warn(
47
+ `Documentation file ${filePath} is too large, truncating to ${MAX_DOC_SIZE} characters.`,
48
+ );
49
+ return `${content.substring(0, MAX_DOC_SIZE)}\n\n[Content truncated due to size]`;
50
+ }
51
+
52
+ return content;
53
+ }
54
+ } catch (error) {
55
+ logger.warn(`Error reading documentation file ${filePath}:`, error);
56
+ }
57
+
58
+ return undefined;
59
+ }
60
+
61
+ /**
62
+ * Read project documentation files
63
+ * @param projectDir Project directory
64
+ * @returns Project documentation
65
+ */
66
+ export async function readProjectDocs(projectDir: string): Promise<ProjectDocs> {
67
+ const docs: ProjectDocs = {
68
+ custom: {},
69
+ };
70
+
71
+ // Read standard documentation files
72
+ docs.readme = await readDocFile(path.join(projectDir, 'README.md'));
73
+ docs.project = await readDocFile(path.join(projectDir, 'PROJECT.md'));
74
+ docs.progress = await readDocFile(path.join(projectDir, 'PROGRESS.md'));
75
+ docs.contributing = await readDocFile(path.join(projectDir, 'CONTRIBUTING.md'));
76
+ docs.architecture = await readDocFile(path.join(projectDir, 'ARCHITECTURE.md'));
77
+
78
+ // Read custom documentation files from the docs directory
79
+ try {
80
+ const docsDir = path.join(projectDir, 'docs');
81
+ if (await fileExists(docsDir)) {
82
+ const files = await fs.readdir(docsDir);
83
+
84
+ for (const file of files) {
85
+ if (file.endsWith('.md')) {
86
+ const filePath = path.join(docsDir, file);
87
+ const content = await readDocFile(filePath);
88
+
89
+ if (content) {
90
+ docs.custom![file] = content;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ } catch (error) {
96
+ logger.warn('Error reading docs directory:', error);
97
+ }
98
+
99
+ return docs;
100
+ }
101
+
102
+ /**
103
+ * Add metadata to project documentation
104
+ * @param docs Project documentation object
105
+ * @param key Metadata key
106
+ * @param value Metadata value
107
+ * @returns Project documentation with added metadata
108
+ */
109
+ export function addMetadataToProjectDocs(
110
+ docs: ProjectDocs,
111
+ key: string,
112
+ value: string,
113
+ ): ProjectDocs {
114
+ if (!docs.metadata) {
115
+ docs.metadata = {};
116
+ }
117
+ docs.metadata[key] = value;
118
+ return docs;
119
+ }
120
+
121
+ /**
122
+ * Format project documentation for inclusion in prompts
123
+ * @param docs Project documentation
124
+ * @returns Formatted documentation string
125
+ */
126
+ export function formatProjectDocs(docs: ProjectDocs): string {
127
+ const sections: string[] = [];
128
+
129
+ if (docs.readme) {
130
+ sections.push(`# README.md\n\n${docs.readme}`);
131
+ }
132
+
133
+ if (docs.project) {
134
+ sections.push(`# PROJECT.md\n\n${docs.project}`);
135
+ }
136
+
137
+ if (docs.architecture) {
138
+ sections.push(`# ARCHITECTURE.md\n\n${docs.architecture}`);
139
+ }
140
+
141
+ if (docs.progress) {
142
+ sections.push(`# PROGRESS.md\n\n${docs.progress}`);
143
+ }
144
+
145
+ if (docs.contributing) {
146
+ sections.push(`# CONTRIBUTING.md\n\n${docs.contributing}`);
147
+ }
148
+
149
+ // Add custom documentation files
150
+ if (docs.custom) {
151
+ for (const [file, content] of Object.entries(docs.custom)) {
152
+ sections.push(`# docs/${file}\n\n${content}`);
153
+ }
154
+ }
155
+
156
+ // Add metadata if present
157
+ if (docs.metadata) {
158
+ for (const [key, content] of Object.entries(docs.metadata)) {
159
+ // Format the metadata section
160
+ const title = key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1');
161
+ sections.push(`# ${title}\n\n${content}`);
162
+ }
163
+ }
164
+
165
+ if (sections.length === 0) {
166
+ return '';
167
+ }
168
+
169
+ return `## Project Documentation\n\n${sections.join('\n\n---\n\n')}`;
170
+ }
171
+
172
+ /**
173
+ * Add project documentation to a prompt
174
+ * @param prompt The prompt to add documentation to
175
+ * @param docs Project documentation object
176
+ * @returns The prompt with documentation added
177
+ */
178
+ export function addProjectDocsToPrompt(prompt: string, docs: ProjectDocs): string {
179
+ const docsText = formatProjectDocs(docs);
180
+ if (docsText) {
181
+ // Try to replace a placeholder if it exists
182
+ if (prompt.includes('{{PROJECT_DOCS}}')) {
183
+ return prompt.replace('{{PROJECT_DOCS}}', docsText);
184
+ }
185
+ // Otherwise, append to the end
186
+ return `${prompt}\n\n${docsText}`;
187
+ }
188
+ return prompt;
189
+ }
@@ -0,0 +1,29 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ /**
5
+ * Resolve the directory that contains the compiled prompt templates.
6
+ * The location varies depending on whether we're running from source,
7
+ * the compiled dist output, or an older workspace layout.
8
+ */
9
+ export function resolvePromptTemplatesDir(): string {
10
+ const candidates = [
11
+ // When running via ts-node from the src tree
12
+ path.resolve(__dirname, '..', 'prompts', 'promptText'),
13
+ // When running compiled code while keeping src in the package
14
+ path.resolve(__dirname, '..', '..', 'src', 'prompts', 'promptText'),
15
+ // When executing directly from the repo root
16
+ path.resolve(process.cwd(), 'src', 'prompts', 'promptText'),
17
+ // Legacy location used before the prompts lived under src/
18
+ path.resolve(process.cwd(), 'promptText'),
19
+ ];
20
+
21
+ for (const candidate of candidates) {
22
+ if (fs.existsSync(candidate)) {
23
+ return candidate;
24
+ }
25
+ }
26
+
27
+ // Fall back to the first option so callers always receive a deterministic path.
28
+ return candidates[0];
29
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Prompt Template Manager
3
+ *
4
+ * This utility provides an interface between the bundledPrompts system
5
+ * and the new Handlebars template system, enabling a smooth migration.
6
+ */
7
+
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+ import type { ReviewType } from '../types/review';
11
+ import logger from './logger';
12
+ import { listAvailableTemplates, loadPromptTemplate } from './templateLoader';
13
+ import { resolvePromptTemplatesDir } from './promptPaths';
14
+
15
+ /**
16
+ * Maps framework identifiers from the API to template directory names
17
+ */
18
+ const frameworkMapping: Record<string, string> = {
19
+ react: 'react',
20
+ angular: 'angular',
21
+ vue: 'vue',
22
+ 'next.js': 'nextjs',
23
+ nextjs: 'nextjs',
24
+ django: 'django',
25
+ flask: 'flask',
26
+ fastapi: 'fastapi',
27
+ pyramid: 'pyramid',
28
+ laravel: 'laravel',
29
+ flutter: 'flutter',
30
+ };
31
+
32
+ /**
33
+ * Maps language identifiers from the API to template directory names
34
+ */
35
+ const languageMapping: Record<string, string> = {
36
+ typescript: 'typescript',
37
+ javascript: 'javascript',
38
+ js: 'javascript',
39
+ python: 'python',
40
+ html: 'html',
41
+ css: 'css',
42
+ php: 'php',
43
+ ruby: 'ruby',
44
+ dart: 'dart',
45
+ };
46
+
47
+ /**
48
+ * Maps ReviewType enum to template file names
49
+ */
50
+ const reviewTypeMapping: Record<string, string> = {
51
+ architectural: 'architectural-review',
52
+ 'best-practices': 'best-practices',
53
+ 'quick-fixes': 'quick-fixes-review',
54
+ security: 'security-review',
55
+ performance: 'performance-review',
56
+ 'unused-code': 'unused-code-review',
57
+ 'code-tracing-unused-code': 'code-tracing-unused-code-review',
58
+ 'focused-unused-code': 'focused-unused-code-review',
59
+ 'improved-unused-code': 'improved-unused-code-review',
60
+ consolidated: 'consolidated-review',
61
+ // Add mapping for improved quick fixes
62
+ 'improved-quick-fixes': 'improved-quick-fixes-review',
63
+ evaluation: 'evaluation',
64
+ 'extract-patterns': 'extract-patterns-review',
65
+ 'coding-test': 'coding-test',
66
+ // Contemporary development patterns
67
+ 'ai-integration': 'ai-integration-review',
68
+ 'cloud-native': 'cloud-native-review',
69
+ 'developer-experience': 'developer-experience-review',
70
+ comprehensive: 'comprehensive',
71
+ };
72
+
73
+ /**
74
+ * Get prompt template for the specified review type, language, and framework
75
+ *
76
+ * @param reviewType The type of review to get a prompt for
77
+ * @param language The programming language (optional)
78
+ * @param framework The framework (optional)
79
+ * @returns The prompt template string or undefined if not found
80
+ */
81
+ export function getPromptTemplate(
82
+ reviewType: ReviewType | string,
83
+ language?: string,
84
+ framework?: string,
85
+ ): string | undefined {
86
+ // Convert ReviewType enum to string if needed
87
+ const reviewTypeStr =
88
+ typeof reviewType === 'string' ? reviewType : String(reviewType).toLowerCase();
89
+
90
+ // Map review type to template file name
91
+ const templateName = reviewTypeMapping[reviewTypeStr];
92
+ if (!templateName) {
93
+ logger.error(`No template mapping found for review type: ${reviewTypeStr}`);
94
+ return undefined;
95
+ }
96
+
97
+ // Map language and framework to template directory names
98
+ const mappedLanguage = language ? languageMapping[language.toLowerCase()] : undefined;
99
+ const mappedFramework = framework ? frameworkMapping[framework.toLowerCase()] : undefined;
100
+
101
+ // Try to load the template
102
+ const template = loadPromptTemplate(templateName, mappedLanguage, mappedFramework);
103
+
104
+ return template || undefined;
105
+ }
106
+
107
+ /**
108
+ * Check if templates directory exists and is properly structured
109
+ *
110
+ * @returns true if templates are available, false otherwise
111
+ */
112
+ export function checkTemplatesAvailability(): boolean {
113
+ const templatesDir = resolvePromptTemplatesDir();
114
+
115
+ if (!fs.existsSync(templatesDir)) {
116
+ logger.warn('Templates directory not found. Using bundled prompts instead.');
117
+ return false;
118
+ }
119
+
120
+ // Check for essential directories
121
+ const requiredDirs = ['common', 'frameworks', 'languages'];
122
+ for (const dir of requiredDirs) {
123
+ if (!fs.existsSync(path.join(templatesDir, dir))) {
124
+ logger.warn(
125
+ `Required templates subdirectory '${dir}' not found. Using bundled prompts instead.`,
126
+ );
127
+ return false;
128
+ }
129
+ }
130
+
131
+ // Check for common variables
132
+ const variablesDir = path.join(templatesDir, 'common', 'variables');
133
+ if (
134
+ !fs.existsSync(variablesDir) ||
135
+ !fs.existsSync(path.join(variablesDir, 'framework-versions.json'))
136
+ ) {
137
+ logger.warn('Framework variables data not found. Using bundled prompts instead.');
138
+ return false;
139
+ }
140
+
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * Get a list of supported frameworks and languages
146
+ *
147
+ * @returns Object containing arrays of supported frameworks, languages, and review types
148
+ */
149
+ export function getSupportedTemplates(): Record<string, string[]> {
150
+ return listAvailableTemplates();
151
+ }
152
+
153
+ export default {
154
+ getPromptTemplate,
155
+ checkTemplatesAvailability,
156
+ getSupportedTemplates,
157
+ };