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