@gitsense/gsc-utils 0.2.3 → 0.2.5
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/dist/gsc-utils.cjs.js +752 -45
- package/dist/gsc-utils.esm.js +752 -45
- package/package.json +1 -1
- package/src/AnalyzerUtils/discovery.js +139 -0
- package/src/AnalyzerUtils/index.js +11 -3
- package/src/AnalyzerUtils/instructionLoader.js +58 -0
- package/src/AnalyzerUtils/management.js +131 -0
- package/src/AnalyzerUtils/schemaLoader.js +163 -0
- package/src/CodeBlockUtils/continuationUtils.js +3 -3
- package/src/ConfigUtils.js +86 -0
- package/src/EnvUtils.js +88 -0
- package/src/GitSenseChatUtils.js +57 -16
package/dist/gsc-utils.esm.js
CHANGED
|
@@ -16,8 +16,8 @@ function getDefaultExportFromCjs (x) {
|
|
|
16
16
|
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
const fs = require$$0;
|
|
20
|
-
const path = require$$1;
|
|
19
|
+
const fs$6 = require$$0;
|
|
20
|
+
const path$4 = require$$1;
|
|
21
21
|
const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -51,12 +51,12 @@ function unescapeCodeBlocks(content) {
|
|
|
51
51
|
* @returns {Array} An array of message objects with role and content properties
|
|
52
52
|
*/
|
|
53
53
|
function getChatTemplateMessages$1(dirname, messageType) {
|
|
54
|
-
const messagesDir = path.join(dirname, messageType);
|
|
54
|
+
const messagesDir = path$4.join(dirname, messageType);
|
|
55
55
|
const messages = [];
|
|
56
56
|
|
|
57
57
|
try {
|
|
58
58
|
// Read all files in the directory
|
|
59
|
-
const files = fs.readdirSync(messagesDir);
|
|
59
|
+
const files = fs$6.readdirSync(messagesDir);
|
|
60
60
|
|
|
61
61
|
// Sort files numerically (1.md, 2.md, etc.)
|
|
62
62
|
const sortedFiles = files.sort((a, b) => {
|
|
@@ -67,9 +67,9 @@ function getChatTemplateMessages$1(dirname, messageType) {
|
|
|
67
67
|
|
|
68
68
|
// Process each file
|
|
69
69
|
for (const file of sortedFiles) {
|
|
70
|
-
if (path.extname(file) === '.md') {
|
|
71
|
-
const filePath = path.join(messagesDir, file);
|
|
72
|
-
const fileContent = fs.readFileSync(filePath, 'utf8');
|
|
70
|
+
if (path$4.extname(file) === '.md') {
|
|
71
|
+
const filePath = path$4.join(messagesDir, file);
|
|
72
|
+
const fileContent = fs$6.readFileSync(filePath, 'utf8');
|
|
73
73
|
|
|
74
74
|
// Split by triple newline to separate metadata from content
|
|
75
75
|
const parts = fileContent.split('\n\n\n');
|
|
@@ -8788,7 +8788,7 @@ var GSToolBlockUtils$3 = {
|
|
|
8788
8788
|
formatToolBlock
|
|
8789
8789
|
};
|
|
8790
8790
|
|
|
8791
|
-
|
|
8791
|
+
/*
|
|
8792
8792
|
* Component: CodeBlockUtils Continuation Utilities
|
|
8793
8793
|
* Block-UUID: 6fdf5c7d-4def-42a1-bc88-0312f6002cfc
|
|
8794
8794
|
* Parent-UUID: 6322afcd-2e5e-425a-9a43-4c72c887f668
|
|
@@ -8954,8 +8954,8 @@ Example of the START of your response:
|
|
|
8954
8954
|
\`\`\`${language}
|
|
8955
8955
|
/**
|
|
8956
8956
|
* Component: ${componentName}
|
|
8957
|
-
* Block-UUID: 01147ddf-320f-498a-a744-198d42a9d2ee
|
|
8958
|
-
* Parent-UUID: e4c0d839-ea17-467d-a0cc-d269d1dbc404
|
|
8957
|
+
* Block-UUID: 01147ddf-320f-498a-a744-198d42a9d2ee
|
|
8958
|
+
* Parent-UUID: e4c0d839-ea17-467d-a0cc-d269d1dbc404
|
|
8959
8959
|
* Version: ${nextVersion}
|
|
8960
8960
|
* Description: ${description}
|
|
8961
8961
|
* Language: ${language}
|
|
@@ -10397,7 +10397,7 @@ const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID,
|
|
|
10397
10397
|
const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbers: formatBlockWithLineNumbers$1, formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1, removeLineNumbers: removeLineNumbers$1 } = lineNumberFormatter;
|
|
10398
10398
|
|
|
10399
10399
|
// Export all imported items
|
|
10400
|
-
var CodeBlockUtils$
|
|
10400
|
+
var CodeBlockUtils$4 = {
|
|
10401
10401
|
// Constants
|
|
10402
10402
|
COMMENT_STYLES: COMMENT_STYLES$1,
|
|
10403
10403
|
|
|
@@ -10464,7 +10464,7 @@ var CodeBlockUtils$3 = {
|
|
|
10464
10464
|
* Authors: Gemini 2.5 Flash Thinking (v1.0.0)
|
|
10465
10465
|
*/
|
|
10466
10466
|
|
|
10467
|
-
const CodeBlockUtils$
|
|
10467
|
+
const CodeBlockUtils$3 = CodeBlockUtils$4;
|
|
10468
10468
|
const MessageUtils$2 = MessageUtils$3;
|
|
10469
10469
|
|
|
10470
10470
|
/**
|
|
@@ -10521,7 +10521,7 @@ function parseContextSection(sectionText) {
|
|
|
10521
10521
|
}
|
|
10522
10522
|
});
|
|
10523
10523
|
|
|
10524
|
-
const { blocks, warnings } = CodeBlockUtils$
|
|
10524
|
+
const { blocks, warnings } = CodeBlockUtils$3.extractCodeBlocks(sectionText, { silent: true });
|
|
10525
10525
|
const codeBlocks = blocks.filter(block => block.type === 'code');
|
|
10526
10526
|
|
|
10527
10527
|
if (codeBlocks.length === 0) {
|
|
@@ -10654,7 +10654,7 @@ const ContextUtils$1 = ContextUtils$2;
|
|
|
10654
10654
|
* @param {Array<Object>} allMessages - An array of all message objects in the chat.
|
|
10655
10655
|
* @returns {Map<number, string>} A Map where keys are chat IDs (numbers) and values are file paths (strings).
|
|
10656
10656
|
*/
|
|
10657
|
-
function buildChatIdToPathMap$
|
|
10657
|
+
function buildChatIdToPathMap$2(allMessages) {
|
|
10658
10658
|
const chatIdToPathMap = new Map();
|
|
10659
10659
|
|
|
10660
10660
|
for (const msg of allMessages) {
|
|
@@ -10681,7 +10681,7 @@ function buildChatIdToPathMap$1(allMessages) {
|
|
|
10681
10681
|
}
|
|
10682
10682
|
|
|
10683
10683
|
var contextMapper = {
|
|
10684
|
-
buildChatIdToPathMap: buildChatIdToPathMap$
|
|
10684
|
+
buildChatIdToPathMap: buildChatIdToPathMap$2
|
|
10685
10685
|
};
|
|
10686
10686
|
|
|
10687
10687
|
/*
|
|
@@ -10712,7 +10712,7 @@ var constants = {
|
|
|
10712
10712
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
10713
10713
|
*/
|
|
10714
10714
|
|
|
10715
|
-
const CodeBlockUtils$
|
|
10715
|
+
const CodeBlockUtils$2 = CodeBlockUtils$4;
|
|
10716
10716
|
const GSToolBlockUtils$1 = GSToolBlockUtils$3;
|
|
10717
10717
|
const JsonUtils$1 = JsonUtils$2;
|
|
10718
10718
|
const { ANALYZE_HEADER_PREFIX } = constants;
|
|
@@ -10727,9 +10727,9 @@ const { ANALYZE_HEADER_PREFIX } = constants;
|
|
|
10727
10727
|
* @returns {{analysisBlocks: Array<Object>, analysisMetadataBlocks: Array<Object|null>, error: string|null}}
|
|
10728
10728
|
* An object containing the extracted blocks and any processing error.
|
|
10729
10729
|
*/
|
|
10730
|
-
function processLLMAnalysisResponse$
|
|
10730
|
+
function processLLMAnalysisResponse$2(messageContent, stoppedStreaming) {
|
|
10731
10731
|
const silent = { silent: true };
|
|
10732
|
-
const { blocks, warnings } = CodeBlockUtils$
|
|
10732
|
+
const { blocks, warnings } = CodeBlockUtils$2.extractCodeBlocks(messageContent, silent);
|
|
10733
10733
|
|
|
10734
10734
|
const analysisBlocks = [];
|
|
10735
10735
|
const analysisMetadataBlocks = [];
|
|
@@ -10828,7 +10828,7 @@ function processLLMAnalysisResponse$1(messageContent, stoppedStreaming) {
|
|
|
10828
10828
|
}
|
|
10829
10829
|
|
|
10830
10830
|
var responseProcessor = {
|
|
10831
|
-
processLLMAnalysisResponse: processLLMAnalysisResponse$
|
|
10831
|
+
processLLMAnalysisResponse: processLLMAnalysisResponse$2
|
|
10832
10832
|
};
|
|
10833
10833
|
|
|
10834
10834
|
/*
|
|
@@ -10855,7 +10855,7 @@ const AnalysisBlockUtils$1 = AnalysisBlockUtils$3;
|
|
|
10855
10855
|
* @returns {{validAnalysisData: Array<Object>, invalidAnalysisBlocks: Array<string|Object>}}
|
|
10856
10856
|
* An object containing arrays of valid analysis data and invalid analysis blocks.
|
|
10857
10857
|
*/
|
|
10858
|
-
function validateLLMAnalysisData$
|
|
10858
|
+
function validateLLMAnalysisData$2(analysisBlocks, analysisMetadataBlocks, chatIdToPathMap) {
|
|
10859
10859
|
const validAnalysisData = []; // Store data for the "Save All" button
|
|
10860
10860
|
const invalidAnalysisBlocks = []; // Store invalid analysis blocks
|
|
10861
10861
|
|
|
@@ -10909,28 +10909,521 @@ function validateLLMAnalysisData$1(analysisBlocks, analysisMetadataBlocks, chatI
|
|
|
10909
10909
|
}
|
|
10910
10910
|
|
|
10911
10911
|
var dataValidator = {
|
|
10912
|
-
validateLLMAnalysisData: validateLLMAnalysisData$
|
|
10912
|
+
validateLLMAnalysisData: validateLLMAnalysisData$2
|
|
10913
|
+
};
|
|
10914
|
+
|
|
10915
|
+
/*
|
|
10916
|
+
* Component: AnalyzerUtils Discovery
|
|
10917
|
+
* Block-UUID: 0b1c2d3e-4f5a-6b7c-8d9e-0f1a2b3c4d5f
|
|
10918
|
+
* Parent-UUID: N/A
|
|
10919
|
+
* Version: 1.0.0
|
|
10920
|
+
* Description: Provides utility functions for discovering available analyzers.
|
|
10921
|
+
* Language: JavaScript
|
|
10922
|
+
* Created-at: 2025-08-28T23:48:00.000Z
|
|
10923
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
10924
|
+
*/
|
|
10925
|
+
|
|
10926
|
+
const fs$5 = require$$0.promises;
|
|
10927
|
+
const path$3 = require$$1;
|
|
10928
|
+
|
|
10929
|
+
/**
|
|
10930
|
+
* Reads and parses the config.json file in a directory.
|
|
10931
|
+
* @param {string} dirPath - The path to the directory.
|
|
10932
|
+
* @returns {Promise<object|null>} A promise that resolves to the parsed config object
|
|
10933
|
+
* or null if the file doesn't exist or is invalid.
|
|
10934
|
+
*/
|
|
10935
|
+
async function readConfig$1(dirPath) {
|
|
10936
|
+
const configPath = path$3.join(dirPath, 'config.json');
|
|
10937
|
+
try {
|
|
10938
|
+
const fileContent = await fs$5.readFile(configPath, 'utf8');
|
|
10939
|
+
return JSON.parse(fileContent);
|
|
10940
|
+
} catch (error) {
|
|
10941
|
+
if (error.code !== 'ENOENT') {
|
|
10942
|
+
// Log a warning if config.json exists but is malformed
|
|
10943
|
+
console.warn(`Warning: Failed to parse config.json in ${dirPath}: ${error.message}`);
|
|
10944
|
+
}
|
|
10945
|
+
return null; // Return null if file not found or parsing failed
|
|
10946
|
+
}
|
|
10947
|
+
}
|
|
10948
|
+
|
|
10949
|
+
/**
|
|
10950
|
+
* Checks if a directory name is valid based on the rules in messages/analyze/README.md.
|
|
10951
|
+
* Allowed: a-z, A-Z, 0-9, dash (-), underscore (_). Cannot start with underscore or contain dots.
|
|
10952
|
+
* @param {string} name - The directory name to check.
|
|
10953
|
+
* @returns {boolean} True if the name is valid, false otherwise.
|
|
10954
|
+
*/
|
|
10955
|
+
function isValidDirName(name) {
|
|
10956
|
+
// Exclude names starting with underscore or containing dots
|
|
10957
|
+
if (name.startsWith('_') || name.includes('.')) {
|
|
10958
|
+
return false;
|
|
10959
|
+
}
|
|
10960
|
+
// Check for allowed characters
|
|
10961
|
+
return /^[a-zA-Z0-9_-]+$/.test(name);
|
|
10962
|
+
}
|
|
10963
|
+
|
|
10964
|
+
/**
|
|
10965
|
+
* Discovers and lists all available analyzers by traversing the directory structure.
|
|
10966
|
+
* An analyzer is considered valid if a '1.md' file exists in the instructions directory.
|
|
10967
|
+
*
|
|
10968
|
+
* @param {string} analyzeMessagesBasePath - The absolute or relative path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
10969
|
+
* @returns {Promise<Array<{id: string, label: string}>>} A promise that resolves to an array of analyzer objects.
|
|
10970
|
+
*/
|
|
10971
|
+
async function getAnalyzers$2(analyzeMessagesBasePath) {
|
|
10972
|
+
const analyzers = [];
|
|
10973
|
+
|
|
10974
|
+
try {
|
|
10975
|
+
const analyzerEntries = await fs$5.readdir(analyzeMessagesBasePath, { withFileTypes: true });
|
|
10976
|
+
|
|
10977
|
+
for (const analyzerEntry of analyzerEntries) {
|
|
10978
|
+
if (analyzerEntry.isDirectory() && isValidDirName(analyzerEntry.name)) {
|
|
10979
|
+
const analyzerName = analyzerEntry.name;
|
|
10980
|
+
const analyzerPath = path$3.join(analyzeMessagesBasePath, analyzerName);
|
|
10981
|
+
const analyzerConfig = await readConfig$1(analyzerPath);
|
|
10982
|
+
const analyzerLabel = analyzerConfig?.label || analyzerName;
|
|
10983
|
+
|
|
10984
|
+
const contentEntries = await fs$5.readdir(analyzerPath, { withFileTypes: true });
|
|
10985
|
+
|
|
10986
|
+
for (const contentEntry of contentEntries) {
|
|
10987
|
+
if (contentEntry.isDirectory() && isValidDirName(contentEntry.name)) {
|
|
10988
|
+
const contentType = contentEntry.name;
|
|
10989
|
+
const contentPath = path$3.join(analyzerPath, contentType);
|
|
10990
|
+
const contentConfig = await readConfig$1(contentPath);
|
|
10991
|
+
const contentLabel = contentConfig?.label || contentType;
|
|
10992
|
+
|
|
10993
|
+
const instructionsEntries = await fs$5.readdir(contentPath, { withFileTypes: true });
|
|
10994
|
+
|
|
10995
|
+
for (const instructionsEntry of instructionsEntries) {
|
|
10996
|
+
if (instructionsEntry.isDirectory() && isValidDirName(instructionsEntry.name)) {
|
|
10997
|
+
const instructionsType = instructionsEntry.name;
|
|
10998
|
+
const instructionsPath = path$3.join(contentPath, instructionsType);
|
|
10999
|
+
const instructionsConfig = await readConfig$1(instructionsPath);
|
|
11000
|
+
const instructionsLabel = instructionsConfig?.label || instructionsType;
|
|
11001
|
+
|
|
11002
|
+
// Check for the existence of 1.md to confirm a valid analyzer configuration
|
|
11003
|
+
const instructionsFilePath = path$3.join(instructionsPath, '1.md');
|
|
11004
|
+
try {
|
|
11005
|
+
await fs$5.access(instructionsFilePath); // Check if file exists and is accessible
|
|
11006
|
+
|
|
11007
|
+
// If analyzerName starts with 'tutorial-', check its last modified time.
|
|
11008
|
+
if (analyzerName.startsWith('tutorial-')) {
|
|
11009
|
+
const stats = await fs$5.stat(instructionsFilePath);
|
|
11010
|
+
const lastModified = stats.mtime.getTime(); // Get timestamp in milliseconds
|
|
11011
|
+
const sixtyMinutesAgo = Date.now() - (60 * 60 * 1000); // Current time - 60 minutes in ms
|
|
11012
|
+
|
|
11013
|
+
if (lastModified < sixtyMinutesAgo) {
|
|
11014
|
+
// This tutorial analyzer has expired, skip it.
|
|
11015
|
+
continue;
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
// Construct the analyzer ID and label
|
|
11019
|
+
const analyzerId = `${analyzerName}::${contentType}::${instructionsType}`;
|
|
11020
|
+
const analyzerFullLabel = `${analyzerLabel} (${contentLabel} - ${instructionsLabel})`;
|
|
11021
|
+
|
|
11022
|
+
analyzers.push({
|
|
11023
|
+
id: analyzerId,
|
|
11024
|
+
label: analyzerFullLabel,
|
|
11025
|
+
protected: analyzerConfig?.protected || false
|
|
11026
|
+
});
|
|
11027
|
+
} catch (error) {
|
|
11028
|
+
// If 1.md doesn't exist, this is not a complete analyzer configuration, skip.
|
|
11029
|
+
if (error.code !== 'ENOENT') {
|
|
11030
|
+
console.warn(`Warning: Error accessing 1.md for ${analyzerId}: ${error.message}`);
|
|
11031
|
+
}
|
|
11032
|
+
}
|
|
11033
|
+
}
|
|
11034
|
+
}
|
|
11035
|
+
}
|
|
11036
|
+
}
|
|
11037
|
+
}
|
|
11038
|
+
}
|
|
11039
|
+
} catch (error) {
|
|
11040
|
+
console.error(`Error traversing analyze messages directory ${analyzeMessagesBasePath}: ${error.message}`);
|
|
11041
|
+
// Depending on requirements, you might want to throw the error or return an empty array
|
|
11042
|
+
throw error; // Re-throw to indicate failure
|
|
11043
|
+
}
|
|
11044
|
+
|
|
11045
|
+
return analyzers;
|
|
11046
|
+
}
|
|
11047
|
+
|
|
11048
|
+
var discovery = {
|
|
11049
|
+
getAnalyzers: getAnalyzers$2,
|
|
11050
|
+
readConfig: readConfig$1};
|
|
11051
|
+
|
|
11052
|
+
/*
|
|
11053
|
+
* Component: AnalyzerUtils Schema Loader
|
|
11054
|
+
* Block-UUID: 0c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f
|
|
11055
|
+
* Parent-UUID: N/A
|
|
11056
|
+
* Version: 1.0.0
|
|
11057
|
+
* Description: Provides utility functions for retrieving and deducing JSON schemas for analyzers.
|
|
11058
|
+
* Language: JavaScript
|
|
11059
|
+
* Created-at: 2025-08-28T23:48:00.000Z
|
|
11060
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11061
|
+
*/
|
|
11062
|
+
|
|
11063
|
+
const fs$4 = require$$0.promises;
|
|
11064
|
+
const path$2 = require$$1;
|
|
11065
|
+
const CodeBlockUtils$1 = CodeBlockUtils$4;
|
|
11066
|
+
|
|
11067
|
+
/**
|
|
11068
|
+
* Deduces the JSON schema type and format/items from a string value pattern.
|
|
11069
|
+
* Handles patterns like "[string: ...]", "[number: ...]", "[datetime: ...]", "[<string>: ...]",
|
|
11070
|
+
* and boolean instructions. Defaults to 'string' for unknown patterns.
|
|
11071
|
+
*
|
|
11072
|
+
* @param {any} value - The value from the raw JSON (expected to be a string pattern).
|
|
11073
|
+
* @param {string} fieldName - The name of the field (for logging warnings).
|
|
11074
|
+
* @returns {{type: string, format?: string, items?: object}} An object describing the schema type and format/items.
|
|
11075
|
+
*/
|
|
11076
|
+
function deduceSchemaType(value, fieldName) {
|
|
11077
|
+
const defaultSchema = { type: 'string' }; // Default fallback
|
|
11078
|
+
|
|
11079
|
+
if (typeof value !== 'string') {
|
|
11080
|
+
const jsType = typeof value;
|
|
11081
|
+
if (jsType === 'object' && value !== null) {
|
|
11082
|
+
console.warn(`Warning: Unexpected non-string, non-null object/array value for field "${fieldName}". Defaulting to type 'string'. Value:`, value);
|
|
11083
|
+
return defaultSchema;
|
|
11084
|
+
}
|
|
11085
|
+
return { type: jsType };
|
|
11086
|
+
}
|
|
11087
|
+
|
|
11088
|
+
const trimmedValue = value.trim();
|
|
11089
|
+
|
|
11090
|
+
if (/^\[string:.*\]$/.test(trimmedValue) || (/^\[[^:]+\]$/.test(trimmedValue) && !/^\[(number|datetime|date|<string>):.*\]$/.test(trimmedValue))) {
|
|
11091
|
+
return { type: 'string' };
|
|
11092
|
+
}
|
|
11093
|
+
|
|
11094
|
+
if (/^\[number:.*\]$/.test(trimmedValue)) {
|
|
11095
|
+
return { type: 'number' };
|
|
11096
|
+
}
|
|
11097
|
+
|
|
11098
|
+
if (/^\[boolean:.*\]$/.test(trimmedValue)) {
|
|
11099
|
+
return { type: 'boolean' };
|
|
11100
|
+
}
|
|
11101
|
+
|
|
11102
|
+
if (/^\[date-*time:.*\]$/.test(trimmedValue)) {
|
|
11103
|
+
return { type: 'string', format: 'date-time' };
|
|
11104
|
+
}
|
|
11105
|
+
|
|
11106
|
+
if (/^\[date:.*\]$/.test(trimmedValue)) {
|
|
11107
|
+
return { type: 'string', format: 'date' };
|
|
11108
|
+
}
|
|
11109
|
+
|
|
11110
|
+
if (/^\[<string>:.*\]$/.test(trimmedValue) || trimmedValue.toLowerCase().includes('array of strings')) {
|
|
11111
|
+
return { type: 'array', items: { type: 'string' } };
|
|
11112
|
+
}
|
|
11113
|
+
|
|
11114
|
+
if (trimmedValue.toLowerCase().includes("output 'true' or 'false'") || trimmedValue.toLowerCase().includes("determine if") && (trimmedValue.toLowerCase().includes("true") || trimmedValue.toLowerCase().includes("false"))) {
|
|
11115
|
+
return { type: 'boolean' };
|
|
11116
|
+
}
|
|
11117
|
+
|
|
11118
|
+
console.warn(`Warning: Unknown metadata value pattern for field "${fieldName}". Defaulting to type 'string'. Value: "${value}"`);
|
|
11119
|
+
return defaultSchema;
|
|
11120
|
+
}
|
|
11121
|
+
|
|
11122
|
+
|
|
11123
|
+
/**
|
|
11124
|
+
* Retrieves the JSON schema for a specific analyzer.
|
|
11125
|
+
* Reads the corresponding '1.md' file, extracts the JSON block,
|
|
11126
|
+
* and deduces schema types from the string values.
|
|
11127
|
+
*
|
|
11128
|
+
* @param {string} analyzeMessagesBasePath - The absolute or relative path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
11129
|
+
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11130
|
+
* @returns {Promise<object|null>} A promise that resolves with the JSON schema object or null if the analyzer ID is invalid or the schema cannot be retrieved/parsed.
|
|
11131
|
+
* @throws {Error} If the 1.md file is found but does not contain exactly one JSON code block.
|
|
11132
|
+
*/
|
|
11133
|
+
async function getAnalyzerSchema$2(analyzeMessagesBasePath, analyzerId) {
|
|
11134
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
11135
|
+
console.error('Error: analyzeMessagesBasePath is required.');
|
|
11136
|
+
return null;
|
|
11137
|
+
}
|
|
11138
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11139
|
+
console.error('Error: analyzerId is required.');
|
|
11140
|
+
return null;
|
|
11141
|
+
}
|
|
11142
|
+
|
|
11143
|
+
const parts = analyzerId.split('::');
|
|
11144
|
+
if (parts.length !== 3) {
|
|
11145
|
+
console.error(`Error: Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.`);
|
|
11146
|
+
return null;
|
|
11147
|
+
}
|
|
11148
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
11149
|
+
|
|
11150
|
+
const instructionsFilePath = path$2.join(analyzeMessagesBasePath, analyzerName, contentType, instructionsType, '1.md');
|
|
11151
|
+
|
|
11152
|
+
try {
|
|
11153
|
+
const fileContent = await fs$4.readFile(instructionsFilePath, 'utf8');
|
|
11154
|
+
const { blocks } = CodeBlockUtils$1.extractCodeBlocks(fileContent, { silent: true });
|
|
11155
|
+
const jsonBlocks = blocks.filter(block => block.type === 'code' && block.language === 'json');
|
|
11156
|
+
|
|
11157
|
+
if (jsonBlocks.length !== 1) {
|
|
11158
|
+
throw new Error(`Expected exactly one JSON code block in ${instructionsFilePath}, but found ${jsonBlocks.length}.`);
|
|
11159
|
+
}
|
|
11160
|
+
|
|
11161
|
+
const jsonBlockContent = jsonBlocks[0].content;
|
|
11162
|
+
let rawJson = null;
|
|
11163
|
+
try {
|
|
11164
|
+
rawJson = JSON.parse(jsonBlockContent);
|
|
11165
|
+
} catch (parseError) {
|
|
11166
|
+
console.error(`Error parsing JSON content from ${instructionsFilePath}: ${parseError.message}`);
|
|
11167
|
+
return null;
|
|
11168
|
+
}
|
|
11169
|
+
|
|
11170
|
+
const schema = {
|
|
11171
|
+
type: 'object',
|
|
11172
|
+
description: rawJson.description,
|
|
11173
|
+
properties: {},
|
|
11174
|
+
required: []
|
|
11175
|
+
};
|
|
11176
|
+
|
|
11177
|
+
const metadataProperties = rawJson?.extracted_metadata;
|
|
11178
|
+
|
|
11179
|
+
if (metadataProperties && typeof metadataProperties === 'object') {
|
|
11180
|
+
for (const fieldName in metadataProperties) {
|
|
11181
|
+
if (Object.hasOwnProperty.call(metadataProperties, fieldName)) {
|
|
11182
|
+
const rawValue = metadataProperties[fieldName];
|
|
11183
|
+
const fieldSchema = deduceSchemaType(rawValue, fieldName);
|
|
11184
|
+
const description = rawValue.match(/^\[\w+: ([^\]]+)\]/)?.[1] || '';
|
|
11185
|
+
|
|
11186
|
+
schema.properties[fieldName] = {
|
|
11187
|
+
...fieldSchema,
|
|
11188
|
+
description,
|
|
11189
|
+
title: fieldName.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
|
|
11190
|
+
};
|
|
11191
|
+
}
|
|
11192
|
+
}
|
|
11193
|
+
} else {
|
|
11194
|
+
console.warn(`Warning: Could not find 'extracted_metadata' object in JSON block from ${instructionsFilePath}. Schema will be empty.`);
|
|
11195
|
+
}
|
|
11196
|
+
|
|
11197
|
+
return schema;
|
|
11198
|
+
|
|
11199
|
+
} catch (error) {
|
|
11200
|
+
if (error.code === 'ENOENT') {
|
|
11201
|
+
console.warn(`Analyzer instructions file not found: ${instructionsFilePath}`);
|
|
11202
|
+
return null;
|
|
11203
|
+
} else {
|
|
11204
|
+
console.error(`Error retrieving or processing schema for analyzer ${analyzerId}: ${error.message}`);
|
|
11205
|
+
throw error;
|
|
11206
|
+
}
|
|
11207
|
+
}
|
|
11208
|
+
}
|
|
11209
|
+
|
|
11210
|
+
var schemaLoader = {
|
|
11211
|
+
getAnalyzerSchema: getAnalyzerSchema$2};
|
|
11212
|
+
|
|
11213
|
+
/*
|
|
11214
|
+
* Component: AnalyzerUtils Management
|
|
11215
|
+
* Block-UUID: 0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a
|
|
11216
|
+
* Parent-UUID: N/A
|
|
11217
|
+
* Version: 1.0.0
|
|
11218
|
+
* Description: Provides utility functions for managing (deleting) analyzer configurations.
|
|
11219
|
+
* Language: JavaScript
|
|
11220
|
+
* Created-at: 2025-08-28T23:48:00.000Z
|
|
11221
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11222
|
+
*/
|
|
11223
|
+
|
|
11224
|
+
const fs$3 = require$$0.promises;
|
|
11225
|
+
const path$1 = require$$1;
|
|
11226
|
+
const { readConfig } = discovery; // Import helper from discovery
|
|
11227
|
+
|
|
11228
|
+
/**
|
|
11229
|
+
* Checks if a directory is empty or only contains a config.json.
|
|
11230
|
+
* @param {string} dirPath - The path to the directory.
|
|
11231
|
+
* @returns {Promise<boolean>} True if the directory is empty or only contains config.json, false otherwise.
|
|
11232
|
+
*/
|
|
11233
|
+
async function isDirectoryEmpty(dirPath) {
|
|
11234
|
+
try {
|
|
11235
|
+
const files = await fs$3.readdir(dirPath);
|
|
11236
|
+
return files.length === 0 || (files.length === 1 && files[0] === 'config.json');
|
|
11237
|
+
} catch (error) {
|
|
11238
|
+
if (error.code === 'ENOENT') {
|
|
11239
|
+
return true; // Directory doesn't exist, so it's "empty" for our purpose
|
|
11240
|
+
}
|
|
11241
|
+
throw error; // Re-throw other errors
|
|
11242
|
+
}
|
|
11243
|
+
}
|
|
11244
|
+
|
|
11245
|
+
/**
|
|
11246
|
+
* Deletes a specific analyzer configuration and intelligently cleans up empty directories.
|
|
11247
|
+
*
|
|
11248
|
+
* @param {string} analyzeMessagesBasePath - The absolute or relative path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
11249
|
+
* @param {string} analyzerId - The unique ID of the analyzer to delete (format: 'analyzer_name::content_type::instructions_type').
|
|
11250
|
+
* @returns {Promise<{success: boolean, message: string}>} A promise that resolves with a result object indicating success or failure.
|
|
11251
|
+
*/
|
|
11252
|
+
async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
11253
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
11254
|
+
return { success: false, message: 'analyzeMessagesBasePath is required.' };
|
|
11255
|
+
}
|
|
11256
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11257
|
+
return { success: false, message: 'analyzerId is required.' };
|
|
11258
|
+
}
|
|
11259
|
+
|
|
11260
|
+
const parts = analyzerId.split('::');
|
|
11261
|
+
if (parts.length !== 3) {
|
|
11262
|
+
return { success: false, message: `Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.` };
|
|
11263
|
+
}
|
|
11264
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
11265
|
+
|
|
11266
|
+
const analyzerDir = path$1.join(analyzeMessagesBasePath, analyzerName);
|
|
11267
|
+
const contentDir = path$1.join(analyzerDir, contentType);
|
|
11268
|
+
const instructionsDir = path$1.join(contentDir, instructionsType);
|
|
11269
|
+
const instructionsFilePath = path$1.join(instructionsDir, '1.md');
|
|
11270
|
+
|
|
11271
|
+
try {
|
|
11272
|
+
// 1. Check for protection at all levels
|
|
11273
|
+
const analyzerConfig = await readConfig(analyzerDir);
|
|
11274
|
+
if (analyzerConfig?.protected) {
|
|
11275
|
+
return { success: false, message: `Analyzer '${analyzerName}' is protected and cannot be deleted.` };
|
|
11276
|
+
}
|
|
11277
|
+
|
|
11278
|
+
const contentConfig = await readConfig(contentDir);
|
|
11279
|
+
if (contentConfig?.protected) {
|
|
11280
|
+
return { success: false, message: `Content type '${contentType}' for analyzer '${analyzerName}' is protected and cannot be deleted.` };
|
|
11281
|
+
}
|
|
11282
|
+
|
|
11283
|
+
const instructionsConfig = await readConfig(instructionsDir);
|
|
11284
|
+
if (instructionsConfig?.protected) {
|
|
11285
|
+
return { success: false, message: `Instructions type '${instructionsType}' for content type '${contentType}' is protected and cannot be deleted.` };
|
|
11286
|
+
}
|
|
11287
|
+
|
|
11288
|
+
// 2. Delete the 1.md file
|
|
11289
|
+
try {
|
|
11290
|
+
await fs$3.unlink(instructionsFilePath);
|
|
11291
|
+
} catch (error) {
|
|
11292
|
+
if (error.code === 'ENOENT') {
|
|
11293
|
+
return { success: false, message: `Analyzer instructions file not found: ${instructionsFilePath}. It may have already been deleted.` };
|
|
11294
|
+
}
|
|
11295
|
+
throw error; // Re-throw other errors
|
|
11296
|
+
}
|
|
11297
|
+
|
|
11298
|
+
// 3. Intelligently delete empty directories, cascading upwards
|
|
11299
|
+
let deletedDirs = [];
|
|
11300
|
+
|
|
11301
|
+
// Check and delete instructions directory
|
|
11302
|
+
if (await isDirectoryEmpty(instructionsDir)) {
|
|
11303
|
+
try {
|
|
11304
|
+
await fs$3.rmdir(instructionsDir);
|
|
11305
|
+
deletedDirs.push(instructionsDir);
|
|
11306
|
+
} catch (error) {
|
|
11307
|
+
console.warn(`Warning: Could not remove empty instructions directory ${instructionsDir}: ${error.message}`);
|
|
11308
|
+
}
|
|
11309
|
+
}
|
|
11310
|
+
|
|
11311
|
+
// Check and delete content directory
|
|
11312
|
+
if (await isDirectoryEmpty(contentDir)) {
|
|
11313
|
+
try {
|
|
11314
|
+
await fs$3.rmdir(contentDir);
|
|
11315
|
+
deletedDirs.push(contentDir);
|
|
11316
|
+
} catch (error) {
|
|
11317
|
+
console.warn(`Warning: Could not remove empty content directory ${contentDir}: ${error.message}`);
|
|
11318
|
+
}
|
|
11319
|
+
}
|
|
11320
|
+
|
|
11321
|
+
// Check and delete analyzer directory
|
|
11322
|
+
if (await isDirectoryEmpty(analyzerDir)) {
|
|
11323
|
+
try {
|
|
11324
|
+
await fs$3.rmdir(analyzerDir);
|
|
11325
|
+
deletedDirs.push(analyzerDir);
|
|
11326
|
+
} catch (error) {
|
|
11327
|
+
console.warn(`Warning: Could not remove empty analyzer directory ${analyzerDir}: ${error.message}`);
|
|
11328
|
+
}
|
|
11329
|
+
}
|
|
11330
|
+
|
|
11331
|
+
return { success: true, message: `Analyzer '${analyzerId}' deleted successfully. Cleaned up directories: ${deletedDirs.join(', ') || 'None'}.` };
|
|
11332
|
+
|
|
11333
|
+
} catch (error) {
|
|
11334
|
+
console.error(`Error deleting analyzer '${analyzerId}': ${error.message}`);
|
|
11335
|
+
return { success: false, message: `Failed to delete analyzer: ${error.message}` };
|
|
11336
|
+
}
|
|
11337
|
+
}
|
|
11338
|
+
|
|
11339
|
+
var management = {
|
|
11340
|
+
deleteAnalyzer: deleteAnalyzer$2};
|
|
11341
|
+
|
|
11342
|
+
/*
|
|
11343
|
+
* Component: AnalyzerUtils Instruction Loader
|
|
11344
|
+
* Block-UUID: 0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5e
|
|
11345
|
+
* Parent-UUID: N/A
|
|
11346
|
+
* Version: 1.0.0
|
|
11347
|
+
* Description: Provides utility functions for loading raw analyzer instruction content.
|
|
11348
|
+
* Language: JavaScript
|
|
11349
|
+
* Created-at: 2025-08-28T23:48:00.000Z
|
|
11350
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11351
|
+
*/
|
|
11352
|
+
|
|
11353
|
+
const fs$2 = require$$0.promises;
|
|
11354
|
+
const path = require$$1;
|
|
11355
|
+
|
|
11356
|
+
/**
|
|
11357
|
+
* Retrieves the raw Markdown content of the analyzer's '1.md' instruction file.
|
|
11358
|
+
*
|
|
11359
|
+
* @param {string} analyzeMessagesBasePath - The absolute path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
11360
|
+
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11361
|
+
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content of the '1.md' file, or null if not found/invalid.
|
|
11362
|
+
*/
|
|
11363
|
+
async function getAnalyzerInstructionsContent$2(analyzeMessagesBasePath, analyzerId) {
|
|
11364
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
11365
|
+
console.error('Error: analyzeMessagesBasePath is required.');
|
|
11366
|
+
return null;
|
|
11367
|
+
}
|
|
11368
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11369
|
+
console.error('Error: analyzerId is required.');
|
|
11370
|
+
return null;
|
|
11371
|
+
}
|
|
11372
|
+
|
|
11373
|
+
const parts = analyzerId.split('::');
|
|
11374
|
+
if (parts.length !== 3) {
|
|
11375
|
+
console.error(`Error: Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.`);
|
|
11376
|
+
return null;
|
|
11377
|
+
}
|
|
11378
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
11379
|
+
|
|
11380
|
+
const instructionsFilePath = path.join(analyzeMessagesBasePath, analyzerName, contentType, instructionsType, '1.md');
|
|
11381
|
+
|
|
11382
|
+
try {
|
|
11383
|
+
const fileContent = await fs$2.readFile(instructionsFilePath, 'utf8');
|
|
11384
|
+
return fileContent;
|
|
11385
|
+
} catch (error) {
|
|
11386
|
+
if (error.code === 'ENOENT') {
|
|
11387
|
+
console.warn(`Analyzer instructions file not found: ${instructionsFilePath}`);
|
|
11388
|
+
return null;
|
|
11389
|
+
} else {
|
|
11390
|
+
console.error(`Error reading analyzer instructions file ${instructionsFilePath}: ${error.message}`);
|
|
11391
|
+
throw error;
|
|
11392
|
+
}
|
|
11393
|
+
}
|
|
11394
|
+
}
|
|
11395
|
+
|
|
11396
|
+
var instructionLoader = {
|
|
11397
|
+
getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2
|
|
10913
11398
|
};
|
|
10914
11399
|
|
|
10915
11400
|
/*
|
|
10916
11401
|
* Component: AnalyzerUtils Index
|
|
10917
11402
|
* Block-UUID: b403b6a1-230b-4247-8cd6-2a3d068f4bbf
|
|
10918
11403
|
* Parent-UUID: N/A
|
|
10919
|
-
* Version: 1.
|
|
11404
|
+
* Version: 1.1.0
|
|
10920
11405
|
* Description: Aggregates and exports all utility functions from the AnalyzerUtils module.
|
|
10921
11406
|
* Language: JavaScript
|
|
10922
11407
|
* Created-at: 2025-08-28T15:56:40.319Z
|
|
10923
|
-
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11408
|
+
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10924
11409
|
*/
|
|
10925
11410
|
|
|
10926
|
-
const { buildChatIdToPathMap } = contextMapper;
|
|
10927
|
-
const { processLLMAnalysisResponse } = responseProcessor;
|
|
10928
|
-
const { validateLLMAnalysisData } = dataValidator;
|
|
11411
|
+
const { buildChatIdToPathMap: buildChatIdToPathMap$1 } = contextMapper;
|
|
11412
|
+
const { processLLMAnalysisResponse: processLLMAnalysisResponse$1 } = responseProcessor;
|
|
11413
|
+
const { validateLLMAnalysisData: validateLLMAnalysisData$1 } = dataValidator;
|
|
11414
|
+
const { getAnalyzers: getAnalyzers$1 } = discovery;
|
|
11415
|
+
const { getAnalyzerSchema: getAnalyzerSchema$1 } = schemaLoader;
|
|
11416
|
+
const { deleteAnalyzer: deleteAnalyzer$1 } = management;
|
|
11417
|
+
const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1 } = instructionLoader;
|
|
10929
11418
|
|
|
10930
11419
|
var AnalyzerUtils$1 = {
|
|
10931
|
-
buildChatIdToPathMap,
|
|
10932
|
-
processLLMAnalysisResponse,
|
|
10933
|
-
validateLLMAnalysisData
|
|
11420
|
+
buildChatIdToPathMap: buildChatIdToPathMap$1,
|
|
11421
|
+
processLLMAnalysisResponse: processLLMAnalysisResponse$1,
|
|
11422
|
+
validateLLMAnalysisData: validateLLMAnalysisData$1,
|
|
11423
|
+
getAnalyzers: getAnalyzers$1,
|
|
11424
|
+
getAnalyzerSchema: getAnalyzerSchema$1,
|
|
11425
|
+
deleteAnalyzer: deleteAnalyzer$1,
|
|
11426
|
+
getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1,
|
|
10934
11427
|
};
|
|
10935
11428
|
|
|
10936
11429
|
/**
|
|
@@ -10964,34 +11457,209 @@ var LLMUtils$1 = {
|
|
|
10964
11457
|
estimateTokens: estimateTokens$1,
|
|
10965
11458
|
};
|
|
10966
11459
|
|
|
11460
|
+
/*
|
|
11461
|
+
* Component: Config Utilities
|
|
11462
|
+
* Block-UUID: 89016e46-9898-42f0-bef4-564e442cfaf3
|
|
11463
|
+
* Parent-UUID: N/A
|
|
11464
|
+
* Version: 1.0.0
|
|
11465
|
+
* Description: Provides utility functions for loading and accessing application configuration from data/chats.json.
|
|
11466
|
+
* Language: JavaScript
|
|
11467
|
+
* Created-at: 2025-08-28T17:46:26.948Z
|
|
11468
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11469
|
+
*/
|
|
11470
|
+
|
|
11471
|
+
const fs$1 = require$$0.promises;
|
|
11472
|
+
|
|
11473
|
+
/**
|
|
11474
|
+
* Loads and parses the application configuration from the specified JSON file.
|
|
11475
|
+
*
|
|
11476
|
+
* @param {string} filePath - The absolute path to the data/chats.json file.
|
|
11477
|
+
* @returns {Promise<Object>} A promise that resolves with the parsed configuration object.
|
|
11478
|
+
* @throws {Error} If the file cannot be read or parsed.
|
|
11479
|
+
*/
|
|
11480
|
+
async function loadConfig$1(filePath) {
|
|
11481
|
+
try {
|
|
11482
|
+
const fileContent = await fs$1.readFile(filePath, 'utf8');
|
|
11483
|
+
return JSON.parse(fileContent);
|
|
11484
|
+
} catch (error) {
|
|
11485
|
+
if (error.code === 'ENOENT') {
|
|
11486
|
+
throw new Error(`Configuration file not found at: ${filePath}`);
|
|
11487
|
+
}
|
|
11488
|
+
throw new Error(`Failed to load or parse configuration from ${filePath}: ${error.message}`);
|
|
11489
|
+
}
|
|
11490
|
+
}
|
|
11491
|
+
|
|
10967
11492
|
/**
|
|
11493
|
+
* Retrieves the configuration details for a specific LLM provider.
|
|
11494
|
+
*
|
|
11495
|
+
* @param {Object} config - The loaded configuration object.
|
|
11496
|
+
* @param {string} providerName - The name of the LLM provider (e.g., "Google", "Anthropic").
|
|
11497
|
+
* @returns {Object|null} The provider's configuration object or null if not found.
|
|
11498
|
+
*/
|
|
11499
|
+
function getProviderConfig$1(config, providerName) {
|
|
11500
|
+
if (!config || !config.providers || !Array.isArray(config.providers)) {
|
|
11501
|
+
return null;
|
|
11502
|
+
}
|
|
11503
|
+
return config.providers.find(p => p.name === providerName) || null;
|
|
11504
|
+
}
|
|
11505
|
+
|
|
11506
|
+
/**
|
|
11507
|
+
* Finds the specific modelId and other details for a given user-friendly modelName and providerName.
|
|
11508
|
+
*
|
|
11509
|
+
* @param {Object} config - The loaded configuration object.
|
|
11510
|
+
* @param {string} modelName - The user-friendly name of the model (e.g., "Gemini 2.5 Flash").
|
|
11511
|
+
* @param {string} providerName - The name of the provider associated with that model.
|
|
11512
|
+
* @returns {Object|null} An object containing modelId, maxOutputTokens, and other provider-specific model details, or null if not found.
|
|
11513
|
+
*/
|
|
11514
|
+
function getModelProviderDetails$1(config, modelName, providerName) {
|
|
11515
|
+
if (!config || !config.models || !Array.isArray(config.models)) {
|
|
11516
|
+
return null;
|
|
11517
|
+
}
|
|
11518
|
+
|
|
11519
|
+
const modelEntry = config.models.find(m => m.name === modelName);
|
|
11520
|
+
if (!modelEntry || !modelEntry.providers || !Array.isArray(modelEntry.providers)) {
|
|
11521
|
+
return null;
|
|
11522
|
+
}
|
|
11523
|
+
|
|
11524
|
+
return modelEntry.providers.find(p => p.name === providerName) || null;
|
|
11525
|
+
}
|
|
11526
|
+
|
|
11527
|
+
/**
|
|
11528
|
+
* Retrieves the environment variable name (e.g., "GEMINI_API_KEY") for the API key of a specific provider.
|
|
11529
|
+
*
|
|
11530
|
+
* @param {Object} config - The loaded configuration object.
|
|
11531
|
+
* @param {string} providerName - The name of the LLM provider.
|
|
11532
|
+
* @returns {string|null} The name of the environment variable that holds the API key, or null if not found.
|
|
11533
|
+
*/
|
|
11534
|
+
function getApiKeyName$1(config, providerName) {
|
|
11535
|
+
const providerConfig = getProviderConfig$1(config, providerName);
|
|
11536
|
+
return providerConfig ? providerConfig.apiKeyName : null;
|
|
11537
|
+
}
|
|
11538
|
+
|
|
11539
|
+
var ConfigUtils$1 = {
|
|
11540
|
+
loadConfig: loadConfig$1,
|
|
11541
|
+
getProviderConfig: getProviderConfig$1,
|
|
11542
|
+
getModelProviderDetails: getModelProviderDetails$1,
|
|
11543
|
+
getApiKeyName: getApiKeyName$1
|
|
11544
|
+
};
|
|
11545
|
+
|
|
11546
|
+
/*
|
|
11547
|
+
* Component: Environment Utilities
|
|
11548
|
+
* Block-UUID: a4f78a41-3054-45f1-a839-778a3bd598f2
|
|
11549
|
+
* Parent-UUID: N/A
|
|
11550
|
+
* Version: 1.0.0
|
|
11551
|
+
* Description: Provides utility functions for loading and accessing environment variables from a .env file.
|
|
11552
|
+
* Language: JavaScript
|
|
11553
|
+
* Created-at: 2025-08-28T17:46:26.948Z
|
|
11554
|
+
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11555
|
+
*/
|
|
11556
|
+
|
|
11557
|
+
const fs = require$$0.promises;
|
|
11558
|
+
|
|
11559
|
+
// Simple .env parser, as dotenv is not explicitly a dependency
|
|
11560
|
+
// This handles basic KEY=VALUE pairs, ignores comments and empty lines.
|
|
11561
|
+
async function parseEnvFile(filePath) {
|
|
11562
|
+
const env = {};
|
|
11563
|
+
try {
|
|
11564
|
+
const fileContent = await fs.readFile(filePath, 'utf8');
|
|
11565
|
+
fileContent.split('\n').forEach(line => {
|
|
11566
|
+
const trimmedLine = line.trim();
|
|
11567
|
+
if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) {
|
|
11568
|
+
return; // Skip empty lines and comments
|
|
11569
|
+
}
|
|
11570
|
+
const parts = trimmedLine.split('=');
|
|
11571
|
+
if (parts.length >= 2) {
|
|
11572
|
+
const key = parts[0].trim();
|
|
11573
|
+
const value = parts.slice(1).join('=').trim(); // Handle values with '='
|
|
11574
|
+
env[key] = value;
|
|
11575
|
+
}
|
|
11576
|
+
});
|
|
11577
|
+
} catch (error) {
|
|
11578
|
+
if (error.code === 'ENOENT') {
|
|
11579
|
+
console.warn(`EnvUtils: .env file not found at ${filePath}. Proceeding without loading.`);
|
|
11580
|
+
} else {
|
|
11581
|
+
throw new Error(`EnvUtils: Failed to read or parse .env file at ${filePath}: ${error.message}`);
|
|
11582
|
+
}
|
|
11583
|
+
}
|
|
11584
|
+
return env;
|
|
11585
|
+
}
|
|
11586
|
+
|
|
11587
|
+
/**
|
|
11588
|
+
* Loads environment variables from the specified .env file path into process.env.
|
|
11589
|
+
* This function will only load the .env file once per process.
|
|
11590
|
+
*
|
|
11591
|
+
* @param {string} filePath - The absolute path to the .env file.
|
|
11592
|
+
* @returns {Promise<void>} A promise that resolves when the .env file has been processed.
|
|
11593
|
+
* @throws {Error} If the file exists but cannot be read or parsed.
|
|
11594
|
+
*/
|
|
11595
|
+
let envLoaded = false;
|
|
11596
|
+
async function loadEnv$1(filePath) {
|
|
11597
|
+
if (envLoaded) {
|
|
11598
|
+
return; // Only load once
|
|
11599
|
+
}
|
|
11600
|
+
|
|
11601
|
+
const envVars = await parseEnvFile(filePath);
|
|
11602
|
+
for (const key in envVars) {
|
|
11603
|
+
if (Object.hasOwnProperty.call(envVars, key)) {
|
|
11604
|
+
// Only set if not already set in process.env (e.g., by system environment)
|
|
11605
|
+
if (process.env[key] === undefined) {
|
|
11606
|
+
process.env[key] = envVars[key];
|
|
11607
|
+
}
|
|
11608
|
+
}
|
|
11609
|
+
}
|
|
11610
|
+
envLoaded = true;
|
|
11611
|
+
}
|
|
11612
|
+
|
|
11613
|
+
/**
|
|
11614
|
+
* Retrieves the value of a specific API key from process.env.
|
|
11615
|
+
* Assumes loadEnv has been called previously.
|
|
11616
|
+
*
|
|
11617
|
+
* @param {string} keyName - The name of the environment variable holding the API key (e.g., "GEMINI_API_KEY").
|
|
11618
|
+
* @returns {string|null} The API key string, or null if the environment variable is not set.
|
|
11619
|
+
*/
|
|
11620
|
+
function getApiKey$1(keyName) {
|
|
11621
|
+
if (typeof keyName !== 'string' || keyName.trim() === '') {
|
|
11622
|
+
console.warn('EnvUtils: Attempted to get API key with an invalid keyName.');
|
|
11623
|
+
return null;
|
|
11624
|
+
}
|
|
11625
|
+
return process.env[keyName] || null;
|
|
11626
|
+
}
|
|
11627
|
+
|
|
11628
|
+
var EnvUtils$1 = {
|
|
11629
|
+
loadEnv: loadEnv$1,
|
|
11630
|
+
getApiKey: getApiKey$1
|
|
11631
|
+
};
|
|
11632
|
+
|
|
11633
|
+
/*
|
|
10968
11634
|
* Component: GitSenseChatUtils
|
|
10969
11635
|
* Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
|
|
10970
11636
|
* Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
|
|
10971
|
-
* Version: 2.1.
|
|
10972
|
-
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules.
|
|
11637
|
+
* Version: 2.1.3
|
|
11638
|
+
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils and EnvUtils.
|
|
10973
11639
|
* Language: JavaScript
|
|
10974
11640
|
* Created-at: 2025-04-15T16:04:26.780Z
|
|
10975
|
-
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1)
|
|
11641
|
+
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3)
|
|
10976
11642
|
*/
|
|
10977
11643
|
|
|
10978
11644
|
const ChatUtils = ChatUtils$1;
|
|
10979
|
-
const CodeBlockUtils = CodeBlockUtils$
|
|
11645
|
+
const CodeBlockUtils = CodeBlockUtils$4;
|
|
10980
11646
|
const ContextUtils = ContextUtils$2;
|
|
10981
11647
|
const MessageUtils = MessageUtils$3;
|
|
10982
11648
|
const AnalysisBlockUtils = AnalysisBlockUtils$3;
|
|
10983
|
-
const AnalyzerUtils = AnalyzerUtils$1;
|
|
11649
|
+
const AnalyzerUtils = AnalyzerUtils$1; // Updated import
|
|
10984
11650
|
const PatchUtils = PatchUtils$2;
|
|
10985
11651
|
const GSToolBlockUtils = GSToolBlockUtils$3;
|
|
10986
11652
|
const LLMUtils = LLMUtils$1;
|
|
10987
11653
|
const JsonUtils = JsonUtils$2;
|
|
11654
|
+
const ConfigUtils = ConfigUtils$1;
|
|
11655
|
+
const EnvUtils = EnvUtils$1;
|
|
10988
11656
|
|
|
10989
11657
|
const {
|
|
10990
11658
|
estimateTokens
|
|
10991
11659
|
} = LLMUtils;
|
|
10992
11660
|
|
|
10993
|
-
const {
|
|
10994
|
-
detectJsonComments
|
|
11661
|
+
const {
|
|
11662
|
+
detectJsonComments
|
|
10995
11663
|
} = JsonUtils;
|
|
10996
11664
|
|
|
10997
11665
|
const {
|
|
@@ -11018,6 +11686,16 @@ const {
|
|
|
11018
11686
|
validateOverviewMetadata,
|
|
11019
11687
|
} = AnalysisBlockUtils;
|
|
11020
11688
|
|
|
11689
|
+
const { // Updated AnalyzerUtils destructuring
|
|
11690
|
+
buildChatIdToPathMap,
|
|
11691
|
+
processLLMAnalysisResponse,
|
|
11692
|
+
validateLLMAnalysisData,
|
|
11693
|
+
getAnalyzers,
|
|
11694
|
+
getAnalyzerSchema,
|
|
11695
|
+
deleteAnalyzer,
|
|
11696
|
+
getAnalyzerInstructionsContent,
|
|
11697
|
+
} = AnalyzerUtils;
|
|
11698
|
+
|
|
11021
11699
|
const {
|
|
11022
11700
|
COMMENT_STYLES,
|
|
11023
11701
|
generateUUID,
|
|
@@ -11057,11 +11735,24 @@ const {
|
|
|
11057
11735
|
verifyAndCorrectLineNumbers,
|
|
11058
11736
|
} = PatchUtils;
|
|
11059
11737
|
|
|
11060
|
-
const {
|
|
11738
|
+
const {
|
|
11061
11739
|
isToolBlock,
|
|
11062
11740
|
parseToolBlock
|
|
11063
11741
|
} = GSToolBlockUtils;
|
|
11064
11742
|
|
|
11743
|
+
const {
|
|
11744
|
+
loadConfig,
|
|
11745
|
+
getProviderConfig,
|
|
11746
|
+
getModelProviderDetails,
|
|
11747
|
+
getApiKeyName
|
|
11748
|
+
} = ConfigUtils;
|
|
11749
|
+
|
|
11750
|
+
const {
|
|
11751
|
+
loadEnv,
|
|
11752
|
+
getApiKey
|
|
11753
|
+
} = EnvUtils;
|
|
11754
|
+
|
|
11755
|
+
|
|
11065
11756
|
/**
|
|
11066
11757
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
11067
11758
|
* Focuses on markdown code block extraction and processing.
|
|
@@ -11206,8 +11897,8 @@ class GitSenseChatUtils {
|
|
|
11206
11897
|
extractDiffContent(patchText) {
|
|
11207
11898
|
// Uses function from PatchUtils (assuming it's named extractPatchContent or similar)
|
|
11208
11899
|
// If PatchUtils.extractDiffContent exists, use it. Otherwise, use extractPatchContent.
|
|
11209
|
-
return PatchUtils.extractDiffContent
|
|
11210
|
-
? PatchUtils.extractDiffContent(patchText)
|
|
11900
|
+
return PatchUtils.extractDiffContent
|
|
11901
|
+
? PatchUtils.extractDiffContent(patchText)
|
|
11211
11902
|
: PatchUtils.extractPatchContent(patchText);
|
|
11212
11903
|
}
|
|
11213
11904
|
|
|
@@ -11282,6 +11973,8 @@ var GitSenseChatUtils_1 = {
|
|
|
11282
11973
|
ChatUtils,
|
|
11283
11974
|
GSToolBlockUtils,
|
|
11284
11975
|
JsonUtils,
|
|
11976
|
+
ConfigUtils,
|
|
11977
|
+
EnvUtils,
|
|
11285
11978
|
|
|
11286
11979
|
// --- Individual Function Exports (sourced correctly) ---
|
|
11287
11980
|
|
|
@@ -11314,26 +12007,30 @@ var GitSenseChatUtils_1 = {
|
|
|
11314
12007
|
formatBlockWithLineNumbers,
|
|
11315
12008
|
formatBlocksWithLineNumbers,
|
|
11316
12009
|
removeLineNumbers,
|
|
11317
|
-
|
|
12010
|
+
|
|
11318
12011
|
// Other Utilities (from CodeBlockUtils)
|
|
11319
12012
|
removeCodeBlockMarkers,
|
|
11320
12013
|
parseCommentDelimitedBlocks,
|
|
11321
12014
|
updateCodeBlockByIndex,
|
|
11322
12015
|
deleteCodeBlockByIndex,
|
|
11323
12016
|
|
|
11324
|
-
// Analysis Block Utilities
|
|
12017
|
+
// Analysis Block Utilities
|
|
11325
12018
|
isOverviewBlock,
|
|
11326
12019
|
getOverviewType,
|
|
11327
12020
|
parseOverviewMetadata,
|
|
11328
12021
|
validateOverviewMetadata,
|
|
11329
12022
|
|
|
11330
12023
|
// Analyzer Utilities
|
|
11331
|
-
buildChatIdToPathMap
|
|
11332
|
-
processLLMAnalysisResponse
|
|
11333
|
-
validateLLMAnalysisData
|
|
12024
|
+
buildChatIdToPathMap,
|
|
12025
|
+
processLLMAnalysisResponse,
|
|
12026
|
+
validateLLMAnalysisData,
|
|
12027
|
+
getAnalyzers,
|
|
12028
|
+
getAnalyzerSchema,
|
|
12029
|
+
deleteAnalyzer,
|
|
12030
|
+
getAnalyzerInstructionsContent,
|
|
11334
12031
|
|
|
11335
12032
|
// ChatUtils
|
|
11336
|
-
getChatMessages,
|
|
12033
|
+
getChatMessages,
|
|
11337
12034
|
|
|
11338
12035
|
// Message Utils
|
|
11339
12036
|
getChatTemplateMessages,
|
|
@@ -11353,6 +12050,16 @@ var GitSenseChatUtils_1 = {
|
|
|
11353
12050
|
isToolBlock,
|
|
11354
12051
|
parseToolBlock,
|
|
11355
12052
|
|
|
12053
|
+
// Config Utils
|
|
12054
|
+
loadConfig,
|
|
12055
|
+
getProviderConfig,
|
|
12056
|
+
getModelProviderDetails,
|
|
12057
|
+
getApiKeyName,
|
|
12058
|
+
|
|
12059
|
+
// EnvUtils
|
|
12060
|
+
loadEnv,
|
|
12061
|
+
getApiKey,
|
|
12062
|
+
|
|
11356
12063
|
// Note: Internal helpers like findAllCodeFences, matchFencesAndExtractBlocks are
|
|
11357
12064
|
// typically not exported directly from the facade but are available via CodeBlockUtils object.
|
|
11358
12065
|
};
|