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.
- package/.cr-aia.yml +23 -0
- package/.crignore +0 -0
- package/dist/index.js +27 -0
- package/package.json +85 -0
- package/src/analysis/FindingsExtractor.ts +431 -0
- package/src/analysis/ai-detection/analyzers/BaseAnalyzer.ts +267 -0
- package/src/analysis/ai-detection/analyzers/DocumentationAnalyzer.ts +622 -0
- package/src/analysis/ai-detection/analyzers/GitHistoryAnalyzer.ts +430 -0
- package/src/analysis/ai-detection/core/AIDetectionEngine.ts +467 -0
- package/src/analysis/ai-detection/types/DetectionTypes.ts +406 -0
- package/src/analysis/ai-detection/utils/SubmissionConverter.ts +390 -0
- package/src/analysis/context/ReviewContext.ts +378 -0
- package/src/analysis/context/index.ts +7 -0
- package/src/analysis/index.ts +8 -0
- package/src/analysis/tokens/TokenAnalysisFormatter.ts +154 -0
- package/src/analysis/tokens/TokenAnalyzer.ts +747 -0
- package/src/analysis/tokens/index.ts +8 -0
- package/src/clients/base/abstractClient.ts +190 -0
- package/src/clients/base/httpClient.ts +160 -0
- package/src/clients/base/index.ts +12 -0
- package/src/clients/base/modelDetection.ts +107 -0
- package/src/clients/base/responseProcessor.ts +586 -0
- package/src/clients/factory/clientFactory.ts +55 -0
- package/src/clients/factory/index.ts +8 -0
- package/src/clients/implementations/index.ts +8 -0
- package/src/clients/implementations/openRouterClient.ts +411 -0
- package/src/clients/openRouterClient.ts +863 -0
- package/src/clients/openRouterClientWrapper.ts +44 -0
- package/src/clients/utils/directoryStructure.ts +52 -0
- package/src/clients/utils/index.ts +11 -0
- package/src/clients/utils/languageDetection.ts +44 -0
- package/src/clients/utils/promptFormatter.ts +105 -0
- package/src/clients/utils/promptLoader.ts +53 -0
- package/src/clients/utils/tokenCounter.ts +297 -0
- package/src/core/ApiClientSelector.ts +37 -0
- package/src/core/ConfigurationService.ts +591 -0
- package/src/core/ConsolidationService.ts +423 -0
- package/src/core/InteractiveDisplayManager.ts +81 -0
- package/src/core/OutputManager.ts +275 -0
- package/src/core/ReviewGenerator.ts +140 -0
- package/src/core/fileDiscovery.ts +237 -0
- package/src/core/handlers/EstimationHandler.ts +104 -0
- package/src/core/handlers/FileProcessingHandler.ts +204 -0
- package/src/core/handlers/OutputHandler.ts +125 -0
- package/src/core/handlers/ReviewExecutor.ts +104 -0
- package/src/core/reviewOrchestrator.ts +333 -0
- package/src/core/utils/ModelInfoUtils.ts +56 -0
- package/src/formatters/outputFormatter.ts +62 -0
- package/src/formatters/utils/IssueFormatters.ts +83 -0
- package/src/formatters/utils/JsonFormatter.ts +77 -0
- package/src/formatters/utils/MarkdownFormatters.ts +609 -0
- package/src/formatters/utils/MetadataFormatter.ts +269 -0
- package/src/formatters/utils/ModelInfoExtractor.ts +115 -0
- package/src/index.ts +27 -0
- package/src/plugins/PluginInterface.ts +50 -0
- package/src/plugins/PluginManager.ts +126 -0
- package/src/prompts/PromptManager.ts +69 -0
- package/src/prompts/cache/PromptCache.ts +50 -0
- package/src/prompts/promptText/common/variables/css-frameworks.json +33 -0
- package/src/prompts/promptText/common/variables/framework-versions.json +45 -0
- package/src/prompts/promptText/frameworks/react/comprehensive.hbs +19 -0
- package/src/prompts/promptText/languages/css/comprehensive.hbs +18 -0
- package/src/prompts/promptText/languages/generic/comprehensive.hbs +20 -0
- package/src/prompts/promptText/languages/html/comprehensive.hbs +18 -0
- package/src/prompts/promptText/languages/javascript/comprehensive.hbs +18 -0
- package/src/prompts/promptText/languages/python/comprehensive.hbs +18 -0
- package/src/prompts/promptText/languages/typescript/comprehensive.hbs +18 -0
- package/src/runtime/auth/service.ts +58 -0
- package/src/runtime/auth/session.ts +103 -0
- package/src/runtime/auth/types.ts +11 -0
- package/src/runtime/cliEntry.ts +196 -0
- package/src/runtime/errors.ts +13 -0
- package/src/runtime/fileCollector.ts +188 -0
- package/src/runtime/manifest.ts +64 -0
- package/src/runtime/openrouterProxy.ts +45 -0
- package/src/runtime/proxyConfig.ts +94 -0
- package/src/runtime/proxyEnvironment.ts +71 -0
- package/src/runtime/reportMerge.ts +102 -0
- package/src/runtime/reporting/markdownReportBuilder.ts +138 -0
- package/src/runtime/reporting/reportDataCollector.ts +234 -0
- package/src/runtime/reporting/summaryGenerator.ts +86 -0
- package/src/runtime/reviewPipeline.ts +155 -0
- package/src/runtime/runAiCodeReview.ts +153 -0
- package/src/runtime/runtimeConfig.ts +5 -0
- package/src/runtime/ui/Layout.tsx +57 -0
- package/src/runtime/ui/RuntimeApp.tsx +150 -0
- package/src/runtime/ui/inkModules.ts +73 -0
- package/src/runtime/ui/screens/AuthScreen.tsx +128 -0
- package/src/runtime/ui/screens/ModeSelection.tsx +52 -0
- package/src/runtime/ui/screens/ProgressScreen.tsx +55 -0
- package/src/runtime/ui/screens/ResultsScreen.tsx +76 -0
- package/src/strategies/ArchitecturalReviewStrategy.ts +54 -0
- package/src/strategies/CodingTestReviewStrategy.ts +920 -0
- package/src/strategies/ConsolidatedReviewStrategy.ts +59 -0
- package/src/strategies/ExtractPatternsReviewStrategy.ts +64 -0
- package/src/strategies/MultiPassReviewStrategy.ts +785 -0
- package/src/strategies/ReviewStrategy.ts +64 -0
- package/src/strategies/StrategyFactory.ts +79 -0
- package/src/strategies/index.ts +14 -0
- package/src/tokenizers/baseTokenizer.ts +61 -0
- package/src/tokenizers/gptTokenizer.ts +27 -0
- package/src/tokenizers/index.ts +8 -0
- package/src/types/apiResponses.ts +40 -0
- package/src/types/cli.ts +24 -0
- package/src/types/common.ts +39 -0
- package/src/types/configuration.ts +201 -0
- package/src/types/handlebars.d.ts +5 -0
- package/src/types/patch.d.ts +25 -0
- package/src/types/review.ts +294 -0
- package/src/types/reviewContext.d.ts +65 -0
- package/src/types/reviewSchema.ts +181 -0
- package/src/types/structuredReview.ts +167 -0
- package/src/types/tokenAnalysis.ts +56 -0
- package/src/utils/FileReader.ts +93 -0
- package/src/utils/FileWriter.ts +76 -0
- package/src/utils/PathGenerator.ts +97 -0
- package/src/utils/api/apiUtils.ts +14 -0
- package/src/utils/api/index.ts +1 -0
- package/src/utils/apiErrorHandler.ts +287 -0
- package/src/utils/ciDataCollector.ts +252 -0
- package/src/utils/codingTestConfigLoader.ts +466 -0
- package/src/utils/dependencies/aiDependencyAnalyzer.ts +454 -0
- package/src/utils/detection/frameworkDetector.ts +879 -0
- package/src/utils/detection/index.ts +10 -0
- package/src/utils/detection/projectTypeDetector.ts +518 -0
- package/src/utils/diagramGenerator.ts +206 -0
- package/src/utils/errorLogger.ts +60 -0
- package/src/utils/estimationUtils.ts +407 -0
- package/src/utils/fileFilters.ts +373 -0
- package/src/utils/fileSystem.ts +57 -0
- package/src/utils/index.ts +36 -0
- package/src/utils/logger.ts +240 -0
- package/src/utils/pathValidator.ts +98 -0
- package/src/utils/priorityFilter.ts +59 -0
- package/src/utils/projectDocs.ts +189 -0
- package/src/utils/promptPaths.ts +29 -0
- package/src/utils/promptTemplateManager.ts +157 -0
- package/src/utils/review/consolidateReview.ts +553 -0
- package/src/utils/review/fixDisplay.ts +100 -0
- package/src/utils/review/fixImplementation.ts +61 -0
- package/src/utils/review/index.ts +36 -0
- package/src/utils/review/interactiveProcessing.ts +294 -0
- package/src/utils/review/progressTracker.ts +296 -0
- package/src/utils/review/reviewExtraction.ts +382 -0
- package/src/utils/review/types.ts +46 -0
- package/src/utils/reviewActionHandler.ts +18 -0
- package/src/utils/reviewParser.ts +253 -0
- package/src/utils/sanitizer.ts +238 -0
- package/src/utils/smartFileSelector.ts +255 -0
- package/src/utils/templateLoader.ts +514 -0
- package/src/utils/treeGenerator.ts +153 -0
- package/tsconfig.build.json +14 -0
- 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
|
+
};
|