codecritique 1.2.4 → 2.0.1
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/README.md +3 -3
- package/package.json +22 -20
- package/src/content-retrieval.js +38 -26
- package/src/custom-documents.js +29 -14
- package/src/feedback-loader.js +19 -8
- package/src/index.js +95 -45
- package/src/llm.js +7 -3
- package/src/project-analyzer.js +56 -31
- package/src/project-analyzer.test.js +8 -0
- package/src/rag-analyzer.js +70 -34
- package/src/rag-analyzer.test.js +3 -1
- package/src/rag-review.js +14 -7
- package/src/zero-shot-classifier-open.js +16 -7
package/src/rag-analyzer.js
CHANGED
|
@@ -55,7 +55,8 @@ async function ensureSemanticSimilarityInitialized() {
|
|
|
55
55
|
// Initialize semantic similarity using the shared embeddings system
|
|
56
56
|
await initializeSemanticSimilarity();
|
|
57
57
|
semanticSimilarityInitialized = true;
|
|
58
|
-
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
59
60
|
console.warn(chalk.yellow(`⚠️ Could not initialize semantic similarity: ${error.message}`));
|
|
60
61
|
// Continue without semantic similarity - word-based fallback will be used
|
|
61
62
|
}
|
|
@@ -228,7 +229,8 @@ async function getProjectSummary(projectPath, options = {}) {
|
|
|
228
229
|
}
|
|
229
230
|
|
|
230
231
|
return summary;
|
|
231
|
-
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
232
234
|
console.error(chalk.red(`Error retrieving project summary: ${error.message}`));
|
|
233
235
|
return null;
|
|
234
236
|
}
|
|
@@ -240,7 +242,9 @@ async function getProjectSummary(projectPath, options = {}) {
|
|
|
240
242
|
* @returns {string} Formatted context string
|
|
241
243
|
*/
|
|
242
244
|
function formatProjectSummaryForLLM(summary) {
|
|
243
|
-
if (!summary)
|
|
245
|
+
if (!summary) {
|
|
246
|
+
return '';
|
|
247
|
+
}
|
|
244
248
|
|
|
245
249
|
let context = `\n## PROJECT ARCHITECTURE CONTEXT\n\n`;
|
|
246
250
|
|
|
@@ -456,7 +460,8 @@ async function runAnalysis(filePath, options = {}) {
|
|
|
456
460
|
// For PR reviews, always read the full file content for context awareness
|
|
457
461
|
fullFileContent = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : null;
|
|
458
462
|
verboseLog(options, chalk.blue(`Analyzing diff only for ${path.basename(filePath)}`));
|
|
459
|
-
}
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
460
465
|
content = fs.readFileSync(filePath, 'utf8');
|
|
461
466
|
fullFileContent = content;
|
|
462
467
|
verboseLog(options, chalk.blue(`Analyzing full file ${path.basename(filePath)}`));
|
|
@@ -503,7 +508,8 @@ async function runAnalysis(filePath, options = {}) {
|
|
|
503
508
|
verboseLog(options, chalk.magenta(` [${i + 1}] Path: ${g.path} ${g.headingText ? `(Heading: "${g.headingText}")` : ''}`));
|
|
504
509
|
verboseLog(options, chalk.gray(` Content: ${g.content.substring(0, 100).replace(/\\n/g, ' ')}...`));
|
|
505
510
|
});
|
|
506
|
-
}
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
507
513
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
508
514
|
}
|
|
509
515
|
|
|
@@ -513,7 +519,8 @@ async function runAnalysis(filePath, options = {}) {
|
|
|
513
519
|
verboseLog(options, chalk.magenta(` [${i + 1}] Path: ${ex.path} (Similarity: ${ex.similarity?.toFixed(3) || 'N/A'})`));
|
|
514
520
|
verboseLog(options, chalk.gray(` Content: ${ex.content.substring(0, 100).replace(/\\n/g, ' ')}...`));
|
|
515
521
|
});
|
|
516
|
-
}
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
517
524
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
518
525
|
}
|
|
519
526
|
|
|
@@ -524,7 +531,8 @@ async function runAnalysis(filePath, options = {}) {
|
|
|
524
531
|
verboseLog(options, chalk.magenta(` Similarity: ${chunk.similarity?.toFixed(3) || 'N/A'}`));
|
|
525
532
|
verboseLog(options, chalk.gray(` Content: ${chunk.content.substring(0, 100).replace(/\\n/g, ' ')}...`));
|
|
526
533
|
});
|
|
527
|
-
}
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
528
536
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
529
537
|
}
|
|
530
538
|
verboseLog(options, chalk.magenta('---------------------------------'));
|
|
@@ -593,7 +601,8 @@ async function runAnalysis(filePath, options = {}) {
|
|
|
593
601
|
...(filteredResults.metadata || {}),
|
|
594
602
|
},
|
|
595
603
|
};
|
|
596
|
-
}
|
|
604
|
+
}
|
|
605
|
+
catch (error) {
|
|
597
606
|
console.error(chalk.red(`Error analyzing file: ${error.message}`));
|
|
598
607
|
return {
|
|
599
608
|
success: false,
|
|
@@ -745,7 +754,8 @@ async function callLLMForAnalysis(context, options = {}) {
|
|
|
745
754
|
|
|
746
755
|
if (options.isHolisticPRReview) {
|
|
747
756
|
prompt = generateHolisticPRAnalysisPrompt(context);
|
|
748
|
-
}
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
749
759
|
prompt = options.isTestFile ? generateTestFileAnalysisPrompt(context) : generateAnalysisPrompt(context);
|
|
750
760
|
}
|
|
751
761
|
|
|
@@ -781,7 +791,8 @@ async function callLLMForAnalysis(context, options = {}) {
|
|
|
781
791
|
|
|
782
792
|
verboseLog(options, chalk.green('Successfully parsed LLM response with expected structure'));
|
|
783
793
|
return analysisResponse;
|
|
784
|
-
}
|
|
794
|
+
}
|
|
795
|
+
catch (error) {
|
|
785
796
|
console.error(chalk.red(`Error calling LLM for analysis: ${error.message}`));
|
|
786
797
|
console.error(error.stack);
|
|
787
798
|
throw error;
|
|
@@ -945,7 +956,8 @@ async function sendPromptToLLM(promptConfig, llmOptions) {
|
|
|
945
956
|
});
|
|
946
957
|
|
|
947
958
|
return response;
|
|
948
|
-
}
|
|
959
|
+
}
|
|
960
|
+
catch (error) {
|
|
949
961
|
console.error(chalk.red(`Error in LLM call: ${error.message}`));
|
|
950
962
|
throw error;
|
|
951
963
|
}
|
|
@@ -1013,10 +1025,12 @@ Similar code patterns and issues identified by human reviewers in past PRs
|
|
|
1013
1025
|
prHistorySection += `Only report issues that EXACTLY match historical patterns with SPECIFIC code fixes.\n\n`;
|
|
1014
1026
|
|
|
1015
1027
|
verboseLog(context.options, chalk.blue(`PR History section preview: ${prHistorySection.substring(0, 200)}...`));
|
|
1016
|
-
}
|
|
1028
|
+
}
|
|
1029
|
+
else {
|
|
1017
1030
|
verboseLog(context.options, chalk.yellow(`❌ No PR comments section found in context`));
|
|
1018
1031
|
}
|
|
1019
|
-
}
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1020
1034
|
verboseLog(context.options, chalk.yellow(`❌ No context sections available for PR comments`));
|
|
1021
1035
|
}
|
|
1022
1036
|
|
|
@@ -1476,7 +1490,8 @@ async function getPRCommentContext(filePath, options = {}) {
|
|
|
1476
1490
|
fileContent = fs.readFileSync(filePath, 'utf8');
|
|
1477
1491
|
const maxEmbeddingLength = 8000; // Keep consistent with original truncation
|
|
1478
1492
|
contentForSearch = fileContent.length > maxEmbeddingLength ? fileContent.substring(0, maxEmbeddingLength) : fileContent;
|
|
1479
|
-
}
|
|
1493
|
+
}
|
|
1494
|
+
catch (readError) {
|
|
1480
1495
|
debug(`[getPRCommentContext] Could not read file ${filePath}: ${readError.message}`);
|
|
1481
1496
|
return {
|
|
1482
1497
|
success: false,
|
|
@@ -1486,11 +1501,13 @@ async function getPRCommentContext(filePath, options = {}) {
|
|
|
1486
1501
|
summary: 'Failed to read file for context analysis',
|
|
1487
1502
|
};
|
|
1488
1503
|
}
|
|
1489
|
-
}
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1490
1506
|
// Fallback to original behavior if no pre-computed embedding provided
|
|
1491
1507
|
try {
|
|
1492
1508
|
fileContent = fs.readFileSync(filePath, 'utf8');
|
|
1493
|
-
}
|
|
1509
|
+
}
|
|
1510
|
+
catch (readError) {
|
|
1494
1511
|
debug(`[getPRCommentContext] Could not read file ${filePath}: ${readError.message}`);
|
|
1495
1512
|
return {
|
|
1496
1513
|
success: false,
|
|
@@ -1537,7 +1554,8 @@ async function getPRCommentContext(filePath, options = {}) {
|
|
|
1537
1554
|
);
|
|
1538
1555
|
});
|
|
1539
1556
|
}
|
|
1540
|
-
}
|
|
1557
|
+
}
|
|
1558
|
+
catch (dbError) {
|
|
1541
1559
|
console.warn(chalk.yellow(`⚠️ Hybrid search failed: ${dbError.message}`));
|
|
1542
1560
|
debug(`[getPRCommentContext] Hybrid search failed: ${dbError.message}`);
|
|
1543
1561
|
// No fallback needed - if hybrid search fails, we just return empty results
|
|
@@ -1568,7 +1586,8 @@ async function getPRCommentContext(filePath, options = {}) {
|
|
|
1568
1586
|
relevantComments.length > 0 && relevantComments[0].similarity_score !== 0.5 ? 'semantic_embedding' : 'file_path_fallback',
|
|
1569
1587
|
},
|
|
1570
1588
|
};
|
|
1571
|
-
}
|
|
1589
|
+
}
|
|
1590
|
+
catch (error) {
|
|
1572
1591
|
debug(`[getPRCommentContext] Error getting PR comment context: ${error.message}`);
|
|
1573
1592
|
return {
|
|
1574
1593
|
success: false,
|
|
@@ -1737,7 +1756,8 @@ async function performHolisticPRAnalysis(options) {
|
|
|
1737
1756
|
);
|
|
1738
1757
|
verboseLog(options, chalk.gray(` Content: ${g.content.substring(0, 100).replace(/\n/g, ' ')}...`));
|
|
1739
1758
|
});
|
|
1740
|
-
}
|
|
1759
|
+
}
|
|
1760
|
+
else {
|
|
1741
1761
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
1742
1762
|
}
|
|
1743
1763
|
|
|
@@ -1747,7 +1767,8 @@ async function performHolisticPRAnalysis(options) {
|
|
|
1747
1767
|
verboseLog(options, chalk.magenta(` [${i + 1}] Path: ${ex.path} (Similarity: ${ex.similarity?.toFixed(3) || 'N/A'})`));
|
|
1748
1768
|
verboseLog(options, chalk.gray(` Content: ${ex.content.substring(0, 100).replace(/\\n/g, ' ')}...`));
|
|
1749
1769
|
});
|
|
1750
|
-
}
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1751
1772
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
1752
1773
|
}
|
|
1753
1774
|
|
|
@@ -1763,7 +1784,8 @@ async function performHolisticPRAnalysis(options) {
|
|
|
1763
1784
|
verboseLog(options, chalk.gray(` File: ${comment.filePath}`));
|
|
1764
1785
|
verboseLog(options, chalk.gray(` Comment: ${comment.body.substring(0, 100).replace(/\n/g, ' ')}...`));
|
|
1765
1786
|
});
|
|
1766
|
-
}
|
|
1787
|
+
}
|
|
1788
|
+
else {
|
|
1767
1789
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
1768
1790
|
}
|
|
1769
1791
|
|
|
@@ -1774,7 +1796,8 @@ async function performHolisticPRAnalysis(options) {
|
|
|
1774
1796
|
verboseLog(options, chalk.gray(` Similarity: ${chunk.similarity?.toFixed(3) || 'N/A'}`));
|
|
1775
1797
|
verboseLog(options, chalk.gray(` Content: ${chunk.content.substring(0, 100).replace(/\n/g, ' ')}...`));
|
|
1776
1798
|
});
|
|
1777
|
-
}
|
|
1799
|
+
}
|
|
1800
|
+
else {
|
|
1778
1801
|
verboseLog(options, chalk.magenta(' (None)'));
|
|
1779
1802
|
}
|
|
1780
1803
|
verboseLog(options, chalk.magenta('--- Sending Holistic PR Analysis Prompt to LLM ---'));
|
|
@@ -1821,7 +1844,8 @@ async function performHolisticPRAnalysis(options) {
|
|
|
1821
1844
|
},
|
|
1822
1845
|
},
|
|
1823
1846
|
};
|
|
1824
|
-
}
|
|
1847
|
+
}
|
|
1848
|
+
catch (error) {
|
|
1825
1849
|
console.error(chalk.red(`Error in holistic PR analysis: ${error.message}`));
|
|
1826
1850
|
return {
|
|
1827
1851
|
success: false,
|
|
@@ -1852,7 +1876,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
1852
1876
|
// Note: This may be called concurrently. `initializeTables` should be idempotent.
|
|
1853
1877
|
try {
|
|
1854
1878
|
await embeddingsSystem.initialize();
|
|
1855
|
-
}
|
|
1879
|
+
}
|
|
1880
|
+
catch (initError) {
|
|
1856
1881
|
console.warn(chalk.yellow(`Database initialization warning: ${initError.message}`));
|
|
1857
1882
|
}
|
|
1858
1883
|
|
|
@@ -1932,7 +1957,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
1932
1957
|
verboseLog(options, chalk.cyan('📄 Custom documents not yet processed for this project, processing now...'));
|
|
1933
1958
|
// Process custom documents into chunks (only if not already processed)
|
|
1934
1959
|
processedChunks = await embeddingsSystem.processCustomDocumentsInMemory(options.customDocs, projectPath);
|
|
1935
|
-
}
|
|
1960
|
+
}
|
|
1961
|
+
else {
|
|
1936
1962
|
verboseLog(options, chalk.green(`📄 Reusing ${processedChunks.length} already processed custom document chunks`));
|
|
1937
1963
|
}
|
|
1938
1964
|
|
|
@@ -1961,7 +1987,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
1961
1987
|
|
|
1962
1988
|
return relevantChunks;
|
|
1963
1989
|
}
|
|
1964
|
-
}
|
|
1990
|
+
}
|
|
1991
|
+
catch (error) {
|
|
1965
1992
|
console.error(chalk.red(`Error processing custom documents: ${error.message}`));
|
|
1966
1993
|
}
|
|
1967
1994
|
|
|
@@ -1973,7 +2000,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
1973
2000
|
try {
|
|
1974
2001
|
// Use the statically imported function
|
|
1975
2002
|
return await embeddingsSystem.getExistingCustomDocumentChunks(projectPath);
|
|
1976
|
-
}
|
|
2003
|
+
}
|
|
2004
|
+
catch {
|
|
1977
2005
|
verboseLog(options, chalk.gray('No existing custom document chunks found, will process from scratch'));
|
|
1978
2006
|
return [];
|
|
1979
2007
|
}
|
|
@@ -1982,7 +2010,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
1982
2010
|
const withContextFallback = async (promise, fallbackValue, label) => {
|
|
1983
2011
|
try {
|
|
1984
2012
|
return await promise;
|
|
1985
|
-
}
|
|
2013
|
+
}
|
|
2014
|
+
catch (error) {
|
|
1986
2015
|
console.warn(chalk.yellow(`${label} failed: ${error.message}`));
|
|
1987
2016
|
return fallbackValue;
|
|
1988
2017
|
}
|
|
@@ -2055,11 +2084,14 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
2055
2084
|
if (isGenericDocument(docPath, docH1)) {
|
|
2056
2085
|
candidateDocFullContext = getGenericDocumentContext(docPath, docH1);
|
|
2057
2086
|
debug(`[FAST-PATH] Using pre-computed context for generic document in RAG: ${docPath}`);
|
|
2058
|
-
}
|
|
2087
|
+
}
|
|
2088
|
+
else {
|
|
2059
2089
|
candidateDocFullContext = await inferContextFromDocumentContent(docPath, docH1, docChunks, language);
|
|
2060
2090
|
}
|
|
2061
2091
|
const relevantChunksForDoc = docChunks.filter((c) => c.similarity >= RELEVANT_CHUNK_THRESHOLD);
|
|
2062
|
-
if (relevantChunksForDoc.length === 0)
|
|
2092
|
+
if (relevantChunksForDoc.length === 0) {
|
|
2093
|
+
continue;
|
|
2094
|
+
}
|
|
2063
2095
|
|
|
2064
2096
|
const maxChunkScoreInDoc = Math.max(...relevantChunksForDoc.map((c) => c.similarity));
|
|
2065
2097
|
const avgChunkScoreInDoc = relevantChunksForDoc.reduce((sum, c) => sum + c.similarity, 0) / relevantChunksForDoc.length;
|
|
@@ -2080,7 +2112,8 @@ async function getContextForFile(filePath, content, options = {}) {
|
|
|
2080
2112
|
break;
|
|
2081
2113
|
}
|
|
2082
2114
|
}
|
|
2083
|
-
}
|
|
2115
|
+
}
|
|
2116
|
+
else if (reviewedSnippetContext.area !== 'GeneralJS_TS') {
|
|
2084
2117
|
docLevelContextMatchScore -= 0.2;
|
|
2085
2118
|
}
|
|
2086
2119
|
}
|
|
@@ -2205,13 +2238,15 @@ async function gatherUnifiedContextForPR(prFiles, options = {}) {
|
|
|
2205
2238
|
if (!processedChunks || processedChunks.length === 0) {
|
|
2206
2239
|
verboseLog(options, chalk.cyan('📄 Custom documents not yet processed for this project, processing now...'));
|
|
2207
2240
|
processedChunks = await embeddingsSystem.processCustomDocumentsInMemory(options.customDocs, projectPath);
|
|
2208
|
-
}
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2209
2243
|
verboseLog(options, chalk.green(`📄 Reusing ${processedChunks.length} already processed custom document chunks`));
|
|
2210
2244
|
}
|
|
2211
2245
|
|
|
2212
2246
|
globalCustomDocChunks = processedChunks;
|
|
2213
2247
|
verboseLog(options, chalk.green(`📄 Custom documents processed: ${globalCustomDocChunks.length} chunks available for PR analysis`));
|
|
2214
|
-
}
|
|
2248
|
+
}
|
|
2249
|
+
catch (error) {
|
|
2215
2250
|
console.error(chalk.red(`Error processing custom documents for PR: ${error.message}`));
|
|
2216
2251
|
}
|
|
2217
2252
|
}
|
|
@@ -2231,7 +2266,8 @@ async function gatherUnifiedContextForPR(prFiles, options = {}) {
|
|
|
2231
2266
|
...context,
|
|
2232
2267
|
filePath,
|
|
2233
2268
|
};
|
|
2234
|
-
}
|
|
2269
|
+
}
|
|
2270
|
+
catch (error) {
|
|
2235
2271
|
console.error(chalk.red(`Error gathering context for file ${file.filePath}: ${error.message}`));
|
|
2236
2272
|
return null; // Return null on error for this file
|
|
2237
2273
|
}
|
package/src/rag-analyzer.test.js
CHANGED
|
@@ -942,7 +942,9 @@ describe('rag-analyzer', () => {
|
|
|
942
942
|
describe('gatherUnifiedContextForPR error handling', () => {
|
|
943
943
|
it('should handle file context gathering errors', async () => {
|
|
944
944
|
fs.readFileSync.mockImplementation((path) => {
|
|
945
|
-
if (path.includes('error-file'))
|
|
945
|
+
if (path.includes('error-file')) {
|
|
946
|
+
throw new Error('Read error');
|
|
947
|
+
}
|
|
946
948
|
return 'const x = 1;';
|
|
947
949
|
});
|
|
948
950
|
const prFiles = [
|
package/src/rag-review.js
CHANGED
|
@@ -73,7 +73,8 @@ async function reviewFile(filePath, options = {}) {
|
|
|
73
73
|
|
|
74
74
|
// If analysis failed, return the error
|
|
75
75
|
return analyzeResult;
|
|
76
|
-
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
77
78
|
console.error(chalk.red(`Error reviewing file ${filePath}:`), error.message);
|
|
78
79
|
return {
|
|
79
80
|
success: false,
|
|
@@ -143,7 +144,8 @@ async function reviewFiles(filePaths, options = {}) {
|
|
|
143
144
|
results: validResults, // Return array of individual file results
|
|
144
145
|
message: finalMessage,
|
|
145
146
|
};
|
|
146
|
-
}
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
147
149
|
console.error(chalk.red(`Error reviewing multiple files: ${error.message}`));
|
|
148
150
|
console.error(error.stack);
|
|
149
151
|
return {
|
|
@@ -186,7 +188,8 @@ async function reviewPullRequest(changedFilePaths, options = {}) {
|
|
|
186
188
|
|
|
187
189
|
// Use enhanced PR review with cross-file context
|
|
188
190
|
return await reviewPullRequestWithCrossFileContext(filesToReview, options);
|
|
189
|
-
}
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
190
193
|
console.error(chalk.red(`Error reviewing pull request files: ${error.message}`));
|
|
191
194
|
console.error(error.stack);
|
|
192
195
|
return {
|
|
@@ -263,7 +266,8 @@ async function reviewPullRequestWithCrossFileContext(filesToReview, options = {}
|
|
|
263
266
|
baseBranch,
|
|
264
267
|
targetBranch,
|
|
265
268
|
});
|
|
266
|
-
}
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
267
271
|
console.warn(chalk.yellow(`Error processing file ${filePath}: ${error.message}`));
|
|
268
272
|
}
|
|
269
273
|
}
|
|
@@ -429,7 +433,8 @@ async function reviewPullRequestWithCrossFileContext(filesToReview, options = {}
|
|
|
429
433
|
},
|
|
430
434
|
},
|
|
431
435
|
};
|
|
432
|
-
}
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
433
438
|
console.error(chalk.red(`Error in holistic PR review: ${error.message}`));
|
|
434
439
|
|
|
435
440
|
// Fallback to individual file review if holistic review fails
|
|
@@ -469,7 +474,8 @@ async function reviewPullRequestWithCrossFileContext(filesToReview, options = {}
|
|
|
469
474
|
|
|
470
475
|
const result = await runAnalysis(file.filePath, enhancedOptions);
|
|
471
476
|
return result;
|
|
472
|
-
}
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
473
479
|
console.error(chalk.red(`Error reviewing ${file.filePath}: ${error.message}`));
|
|
474
480
|
return {
|
|
475
481
|
filePath: file.filePath,
|
|
@@ -496,7 +502,8 @@ async function reviewPullRequestWithCrossFileContext(filesToReview, options = {}
|
|
|
496
502
|
},
|
|
497
503
|
};
|
|
498
504
|
}
|
|
499
|
-
}
|
|
505
|
+
}
|
|
506
|
+
catch (error) {
|
|
500
507
|
console.error(chalk.red(`Error in enhanced PR review: ${error.message}`));
|
|
501
508
|
return {
|
|
502
509
|
success: false,
|
|
@@ -105,7 +105,9 @@ class OpenZeroShotClassifier {
|
|
|
105
105
|
*/
|
|
106
106
|
async initialize() {
|
|
107
107
|
// If already initialized, return immediately
|
|
108
|
-
if (this.isInitialized)
|
|
108
|
+
if (this.isInitialized) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
109
111
|
|
|
110
112
|
// If currently initializing, wait for the existing initialization
|
|
111
113
|
if (this.initializationPromise) {
|
|
@@ -117,7 +119,8 @@ class OpenZeroShotClassifier {
|
|
|
117
119
|
|
|
118
120
|
try {
|
|
119
121
|
await this.initializationPromise;
|
|
120
|
-
}
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
121
124
|
// Clean up the promise after initialization (success or failure)
|
|
122
125
|
this.initializationPromise = null;
|
|
123
126
|
}
|
|
@@ -133,7 +136,8 @@ class OpenZeroShotClassifier {
|
|
|
133
136
|
|
|
134
137
|
this.isInitialized = true;
|
|
135
138
|
verboseLog({}, '✓ Open-ended zero-shot classifier initialized successfully');
|
|
136
|
-
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
137
141
|
console.error('Error initializing classifier:', error);
|
|
138
142
|
this.isInitialized = false;
|
|
139
143
|
throw error;
|
|
@@ -174,7 +178,8 @@ class OpenZeroShotClassifier {
|
|
|
174
178
|
for (const value of Object.values(obj)) {
|
|
175
179
|
if (Array.isArray(value)) {
|
|
176
180
|
value.forEach((tech) => techs.add(tech.toLowerCase()));
|
|
177
|
-
}
|
|
181
|
+
}
|
|
182
|
+
else if (typeof value === 'object') {
|
|
178
183
|
addTechsFromObject(value);
|
|
179
184
|
}
|
|
180
185
|
}
|
|
@@ -234,7 +239,9 @@ class OpenZeroShotClassifier {
|
|
|
234
239
|
const word = words[i].replace(/[.,;:!?'"()[\]{}]/g, '');
|
|
235
240
|
|
|
236
241
|
// Skip if it's a common word
|
|
237
|
-
if (this.commonWords.has(word.toLowerCase()))
|
|
242
|
+
if (this.commonWords.has(word.toLowerCase())) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
238
245
|
|
|
239
246
|
// Check if word is capitalized and not at sentence start
|
|
240
247
|
if (i > 0 && /^[A-Z][a-zA-Z]+/.test(word) && word.length > 2 && word.length < 20) {
|
|
@@ -302,7 +309,8 @@ class OpenZeroShotClassifier {
|
|
|
302
309
|
|
|
303
310
|
this.cache.set(cacheKey, classifications);
|
|
304
311
|
return classifications;
|
|
305
|
-
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
306
314
|
console.error('Error in technology classification:', error);
|
|
307
315
|
return [];
|
|
308
316
|
}
|
|
@@ -368,7 +376,8 @@ class OpenZeroShotClassifier {
|
|
|
368
376
|
|
|
369
377
|
this.cache.set(cacheKey, classifications);
|
|
370
378
|
return classifications;
|
|
371
|
-
}
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
372
381
|
console.error('Error in domain classification:', error);
|
|
373
382
|
return [];
|
|
374
383
|
}
|