@gitsense/gsc-utils 0.2.3 → 0.2.4

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,7 +18,7 @@ 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;
21
+ const fs$2 = require$$0;
22
22
  const path = require$$1;
23
23
  const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
24
24
 
@@ -58,7 +58,7 @@ function getChatTemplateMessages$1(dirname, messageType) {
58
58
 
59
59
  try {
60
60
  // Read all files in the directory
61
- const files = fs.readdirSync(messagesDir);
61
+ const files = fs$2.readdirSync(messagesDir);
62
62
 
63
63
  // Sort files numerically (1.md, 2.md, etc.)
64
64
  const sortedFiles = files.sort((a, b) => {
@@ -71,7 +71,7 @@ function getChatTemplateMessages$1(dirname, messageType) {
71
71
  for (const file of sortedFiles) {
72
72
  if (path.extname(file) === '.md') {
73
73
  const filePath = path.join(messagesDir, file);
74
- const fileContent = fs.readFileSync(filePath, 'utf8');
74
+ const fileContent = fs$2.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}
@@ -10966,15 +10966,188 @@ var LLMUtils$1 = {
10966
10966
  estimateTokens: estimateTokens$1,
10967
10967
  };
10968
10968
 
10969
+ /*
10970
+ * Component: Config Utilities
10971
+ * Block-UUID: 89016e46-9898-42f0-bef4-564e442cfaf3
10972
+ * Parent-UUID: N/A
10973
+ * Version: 1.0.0
10974
+ * Description: Provides utility functions for loading and accessing application configuration from data/chats.json.
10975
+ * Language: JavaScript
10976
+ * Created-at: 2025-08-28T17:46:26.948Z
10977
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10978
+ */
10979
+
10980
+ const fs$1 = require$$0.promises;
10981
+
10982
+ /**
10983
+ * Loads and parses the application configuration from the specified JSON file.
10984
+ *
10985
+ * @param {string} filePath - The absolute path to the data/chats.json file.
10986
+ * @returns {Promise<Object>} A promise that resolves with the parsed configuration object.
10987
+ * @throws {Error} If the file cannot be read or parsed.
10988
+ */
10989
+ async function loadConfig$1(filePath) {
10990
+ try {
10991
+ const fileContent = await fs$1.readFile(filePath, 'utf8');
10992
+ return JSON.parse(fileContent);
10993
+ } catch (error) {
10994
+ if (error.code === 'ENOENT') {
10995
+ throw new Error(`Configuration file not found at: ${filePath}`);
10996
+ }
10997
+ throw new Error(`Failed to load or parse configuration from ${filePath}: ${error.message}`);
10998
+ }
10999
+ }
11000
+
11001
+ /**
11002
+ * Retrieves the configuration details for a specific LLM provider.
11003
+ *
11004
+ * @param {Object} config - The loaded configuration object.
11005
+ * @param {string} providerName - The name of the LLM provider (e.g., "Google", "Anthropic").
11006
+ * @returns {Object|null} The provider's configuration object or null if not found.
11007
+ */
11008
+ function getProviderConfig$1(config, providerName) {
11009
+ if (!config || !config.providers || !Array.isArray(config.providers)) {
11010
+ return null;
11011
+ }
11012
+ return config.providers.find(p => p.name === providerName) || null;
11013
+ }
11014
+
11015
+ /**
11016
+ * Finds the specific modelId and other details for a given user-friendly modelName and providerName.
11017
+ *
11018
+ * @param {Object} config - The loaded configuration object.
11019
+ * @param {string} modelName - The user-friendly name of the model (e.g., "Gemini 2.5 Flash").
11020
+ * @param {string} providerName - The name of the provider associated with that model.
11021
+ * @returns {Object|null} An object containing modelId, maxOutputTokens, and other provider-specific model details, or null if not found.
11022
+ */
11023
+ function getModelProviderDetails$1(config, modelName, providerName) {
11024
+ if (!config || !config.models || !Array.isArray(config.models)) {
11025
+ return null;
11026
+ }
11027
+
11028
+ const modelEntry = config.models.find(m => m.name === modelName);
11029
+ if (!modelEntry || !modelEntry.providers || !Array.isArray(modelEntry.providers)) {
11030
+ return null;
11031
+ }
11032
+
11033
+ return modelEntry.providers.find(p => p.name === providerName) || null;
11034
+ }
11035
+
11036
+ /**
11037
+ * Retrieves the environment variable name (e.g., "GEMINI_API_KEY") for the API key of a specific provider.
11038
+ *
11039
+ * @param {Object} config - The loaded configuration object.
11040
+ * @param {string} providerName - The name of the LLM provider.
11041
+ * @returns {string|null} The name of the environment variable that holds the API key, or null if not found.
11042
+ */
11043
+ function getApiKeyName$1(config, providerName) {
11044
+ const providerConfig = getProviderConfig$1(config, providerName);
11045
+ return providerConfig ? providerConfig.apiKeyName : null;
11046
+ }
11047
+
11048
+ var ConfigUtils$1 = {
11049
+ loadConfig: loadConfig$1,
11050
+ getProviderConfig: getProviderConfig$1,
11051
+ getModelProviderDetails: getModelProviderDetails$1,
11052
+ getApiKeyName: getApiKeyName$1
11053
+ };
11054
+
11055
+ /*
11056
+ * Component: Environment Utilities
11057
+ * Block-UUID: a4f78a41-3054-45f1-a839-778a3bd598f2
11058
+ * Parent-UUID: N/A
11059
+ * Version: 1.0.0
11060
+ * Description: Provides utility functions for loading and accessing environment variables from a .env file.
11061
+ * Language: JavaScript
11062
+ * Created-at: 2025-08-28T17:46:26.948Z
11063
+ * Authors: Gemini 2.5 Flash (v1.0.0)
11064
+ */
11065
+
11066
+ const fs = require$$0.promises;
11067
+
11068
+ // Simple .env parser, as dotenv is not explicitly a dependency
11069
+ // This handles basic KEY=VALUE pairs, ignores comments and empty lines.
11070
+ async function parseEnvFile(filePath) {
11071
+ const env = {};
11072
+ try {
11073
+ const fileContent = await fs.readFile(filePath, 'utf8');
11074
+ fileContent.split('\n').forEach(line => {
11075
+ const trimmedLine = line.trim();
11076
+ if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) {
11077
+ return; // Skip empty lines and comments
11078
+ }
11079
+ const parts = trimmedLine.split('=');
11080
+ if (parts.length >= 2) {
11081
+ const key = parts[0].trim();
11082
+ const value = parts.slice(1).join('=').trim(); // Handle values with '='
11083
+ env[key] = value;
11084
+ }
11085
+ });
11086
+ } catch (error) {
11087
+ if (error.code === 'ENOENT') {
11088
+ console.warn(`EnvUtils: .env file not found at ${filePath}. Proceeding without loading.`);
11089
+ } else {
11090
+ throw new Error(`EnvUtils: Failed to read or parse .env file at ${filePath}: ${error.message}`);
11091
+ }
11092
+ }
11093
+ return env;
11094
+ }
11095
+
10969
11096
  /**
11097
+ * Loads environment variables from the specified .env file path into process.env.
11098
+ * This function will only load the .env file once per process.
11099
+ *
11100
+ * @param {string} filePath - The absolute path to the .env file.
11101
+ * @returns {Promise<void>} A promise that resolves when the .env file has been processed.
11102
+ * @throws {Error} If the file exists but cannot be read or parsed.
11103
+ */
11104
+ let envLoaded = false;
11105
+ async function loadEnv$1(filePath) {
11106
+ if (envLoaded) {
11107
+ return; // Only load once
11108
+ }
11109
+
11110
+ const envVars = await parseEnvFile(filePath);
11111
+ for (const key in envVars) {
11112
+ if (Object.hasOwnProperty.call(envVars, key)) {
11113
+ // Only set if not already set in process.env (e.g., by system environment)
11114
+ if (process.env[key] === undefined) {
11115
+ process.env[key] = envVars[key];
11116
+ }
11117
+ }
11118
+ }
11119
+ envLoaded = true;
11120
+ }
11121
+
11122
+ /**
11123
+ * Retrieves the value of a specific API key from process.env.
11124
+ * Assumes loadEnv has been called previously.
11125
+ *
11126
+ * @param {string} keyName - The name of the environment variable holding the API key (e.g., "GEMINI_API_KEY").
11127
+ * @returns {string|null} The API key string, or null if the environment variable is not set.
11128
+ */
11129
+ function getApiKey$1(keyName) {
11130
+ if (typeof keyName !== 'string' || keyName.trim() === '') {
11131
+ console.warn('EnvUtils: Attempted to get API key with an invalid keyName.');
11132
+ return null;
11133
+ }
11134
+ return process.env[keyName] || null;
11135
+ }
11136
+
11137
+ var EnvUtils$1 = {
11138
+ loadEnv: loadEnv$1,
11139
+ getApiKey: getApiKey$1
11140
+ };
11141
+
11142
+ /*
10970
11143
  * Component: GitSenseChatUtils
10971
11144
  * Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
10972
11145
  * 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.
11146
+ * Version: 2.1.2
11147
+ * 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
11148
  * Language: JavaScript
10976
11149
  * 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)
11150
+ * 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)
10978
11151
  */
10979
11152
 
10980
11153
  const ChatUtils = ChatUtils$1;
@@ -10987,13 +11160,15 @@ const PatchUtils = PatchUtils$2;
10987
11160
  const GSToolBlockUtils = GSToolBlockUtils$3;
10988
11161
  const LLMUtils = LLMUtils$1;
10989
11162
  const JsonUtils = JsonUtils$2;
11163
+ const ConfigUtils = ConfigUtils$1;
11164
+ const EnvUtils = EnvUtils$1;
10990
11165
 
10991
11166
  const {
10992
11167
  estimateTokens
10993
11168
  } = LLMUtils;
10994
11169
 
10995
- const {
10996
- detectJsonComments
11170
+ const {
11171
+ detectJsonComments
10997
11172
  } = JsonUtils;
10998
11173
 
10999
11174
  const {
@@ -11059,11 +11234,24 @@ const {
11059
11234
  verifyAndCorrectLineNumbers,
11060
11235
  } = PatchUtils;
11061
11236
 
11062
- const {
11237
+ const {
11063
11238
  isToolBlock,
11064
11239
  parseToolBlock
11065
11240
  } = GSToolBlockUtils;
11066
11241
 
11242
+ const {
11243
+ loadConfig,
11244
+ getProviderConfig,
11245
+ getModelProviderDetails,
11246
+ getApiKeyName
11247
+ } = ConfigUtils;
11248
+
11249
+ const {
11250
+ loadEnv,
11251
+ getApiKey
11252
+ } = EnvUtils;
11253
+
11254
+
11067
11255
  /**
11068
11256
  * GitSenseChatUtils class provides a unified interface to code block and patch utilities.
11069
11257
  * Focuses on markdown code block extraction and processing.
@@ -11208,8 +11396,8 @@ class GitSenseChatUtils {
11208
11396
  extractDiffContent(patchText) {
11209
11397
  // Uses function from PatchUtils (assuming it's named extractPatchContent or similar)
11210
11398
  // If PatchUtils.extractDiffContent exists, use it. Otherwise, use extractPatchContent.
11211
- return PatchUtils.extractDiffContent
11212
- ? PatchUtils.extractDiffContent(patchText)
11399
+ return PatchUtils.extractDiffContent
11400
+ ? PatchUtils.extractDiffContent(patchText)
11213
11401
  : PatchUtils.extractPatchContent(patchText);
11214
11402
  }
11215
11403
 
@@ -11284,6 +11472,8 @@ var GitSenseChatUtils_1 = {
11284
11472
  ChatUtils,
11285
11473
  GSToolBlockUtils,
11286
11474
  JsonUtils,
11475
+ ConfigUtils,
11476
+ EnvUtils,
11287
11477
 
11288
11478
  // --- Individual Function Exports (sourced correctly) ---
11289
11479
 
@@ -11316,14 +11506,14 @@ var GitSenseChatUtils_1 = {
11316
11506
  formatBlockWithLineNumbers,
11317
11507
  formatBlocksWithLineNumbers,
11318
11508
  removeLineNumbers,
11319
-
11509
+
11320
11510
  // Other Utilities (from CodeBlockUtils)
11321
11511
  removeCodeBlockMarkers,
11322
11512
  parseCommentDelimitedBlocks,
11323
11513
  updateCodeBlockByIndex,
11324
11514
  deleteCodeBlockByIndex,
11325
11515
 
11326
- // Analysis Block Utilities
11516
+ // Analysis Block Utilities
11327
11517
  isOverviewBlock,
11328
11518
  getOverviewType,
11329
11519
  parseOverviewMetadata,
@@ -11335,7 +11525,7 @@ var GitSenseChatUtils_1 = {
11335
11525
  validateLLMAnalysisData: AnalyzerUtils.validateLLMAnalysisData,
11336
11526
 
11337
11527
  // ChatUtils
11338
- getChatMessages,
11528
+ getChatMessages,
11339
11529
 
11340
11530
  // Message Utils
11341
11531
  getChatTemplateMessages,
@@ -11355,6 +11545,16 @@ var GitSenseChatUtils_1 = {
11355
11545
  isToolBlock,
11356
11546
  parseToolBlock,
11357
11547
 
11548
+ // Config Utils
11549
+ loadConfig,
11550
+ getProviderConfig,
11551
+ getModelProviderDetails,
11552
+ getApiKeyName,
11553
+
11554
+ // EnvUtils
11555
+ loadEnv,
11556
+ getApiKey,
11557
+
11358
11558
  // Note: Internal helpers like findAllCodeFences, matchFencesAndExtractBlocks are
11359
11559
  // typically not exported directly from the facade but are available via CodeBlockUtils object.
11360
11560
  };
@@ -16,7 +16,7 @@ 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;
19
+ const fs$2 = require$$0;
20
20
  const path = require$$1;
21
21
  const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
22
22
 
@@ -56,7 +56,7 @@ function getChatTemplateMessages$1(dirname, messageType) {
56
56
 
57
57
  try {
58
58
  // Read all files in the directory
59
- const files = fs.readdirSync(messagesDir);
59
+ const files = fs$2.readdirSync(messagesDir);
60
60
 
61
61
  // Sort files numerically (1.md, 2.md, etc.)
62
62
  const sortedFiles = files.sort((a, b) => {
@@ -69,7 +69,7 @@ function getChatTemplateMessages$1(dirname, messageType) {
69
69
  for (const file of sortedFiles) {
70
70
  if (path.extname(file) === '.md') {
71
71
  const filePath = path.join(messagesDir, file);
72
- const fileContent = fs.readFileSync(filePath, 'utf8');
72
+ const fileContent = fs$2.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}
@@ -10964,15 +10964,188 @@ var LLMUtils$1 = {
10964
10964
  estimateTokens: estimateTokens$1,
10965
10965
  };
10966
10966
 
10967
+ /*
10968
+ * Component: Config Utilities
10969
+ * Block-UUID: 89016e46-9898-42f0-bef4-564e442cfaf3
10970
+ * Parent-UUID: N/A
10971
+ * Version: 1.0.0
10972
+ * Description: Provides utility functions for loading and accessing application configuration from data/chats.json.
10973
+ * Language: JavaScript
10974
+ * Created-at: 2025-08-28T17:46:26.948Z
10975
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10976
+ */
10977
+
10978
+ const fs$1 = require$$0.promises;
10979
+
10980
+ /**
10981
+ * Loads and parses the application configuration from the specified JSON file.
10982
+ *
10983
+ * @param {string} filePath - The absolute path to the data/chats.json file.
10984
+ * @returns {Promise<Object>} A promise that resolves with the parsed configuration object.
10985
+ * @throws {Error} If the file cannot be read or parsed.
10986
+ */
10987
+ async function loadConfig$1(filePath) {
10988
+ try {
10989
+ const fileContent = await fs$1.readFile(filePath, 'utf8');
10990
+ return JSON.parse(fileContent);
10991
+ } catch (error) {
10992
+ if (error.code === 'ENOENT') {
10993
+ throw new Error(`Configuration file not found at: ${filePath}`);
10994
+ }
10995
+ throw new Error(`Failed to load or parse configuration from ${filePath}: ${error.message}`);
10996
+ }
10997
+ }
10998
+
10999
+ /**
11000
+ * Retrieves the configuration details for a specific LLM provider.
11001
+ *
11002
+ * @param {Object} config - The loaded configuration object.
11003
+ * @param {string} providerName - The name of the LLM provider (e.g., "Google", "Anthropic").
11004
+ * @returns {Object|null} The provider's configuration object or null if not found.
11005
+ */
11006
+ function getProviderConfig$1(config, providerName) {
11007
+ if (!config || !config.providers || !Array.isArray(config.providers)) {
11008
+ return null;
11009
+ }
11010
+ return config.providers.find(p => p.name === providerName) || null;
11011
+ }
11012
+
11013
+ /**
11014
+ * Finds the specific modelId and other details for a given user-friendly modelName and providerName.
11015
+ *
11016
+ * @param {Object} config - The loaded configuration object.
11017
+ * @param {string} modelName - The user-friendly name of the model (e.g., "Gemini 2.5 Flash").
11018
+ * @param {string} providerName - The name of the provider associated with that model.
11019
+ * @returns {Object|null} An object containing modelId, maxOutputTokens, and other provider-specific model details, or null if not found.
11020
+ */
11021
+ function getModelProviderDetails$1(config, modelName, providerName) {
11022
+ if (!config || !config.models || !Array.isArray(config.models)) {
11023
+ return null;
11024
+ }
11025
+
11026
+ const modelEntry = config.models.find(m => m.name === modelName);
11027
+ if (!modelEntry || !modelEntry.providers || !Array.isArray(modelEntry.providers)) {
11028
+ return null;
11029
+ }
11030
+
11031
+ return modelEntry.providers.find(p => p.name === providerName) || null;
11032
+ }
11033
+
11034
+ /**
11035
+ * Retrieves the environment variable name (e.g., "GEMINI_API_KEY") for the API key of a specific provider.
11036
+ *
11037
+ * @param {Object} config - The loaded configuration object.
11038
+ * @param {string} providerName - The name of the LLM provider.
11039
+ * @returns {string|null} The name of the environment variable that holds the API key, or null if not found.
11040
+ */
11041
+ function getApiKeyName$1(config, providerName) {
11042
+ const providerConfig = getProviderConfig$1(config, providerName);
11043
+ return providerConfig ? providerConfig.apiKeyName : null;
11044
+ }
11045
+
11046
+ var ConfigUtils$1 = {
11047
+ loadConfig: loadConfig$1,
11048
+ getProviderConfig: getProviderConfig$1,
11049
+ getModelProviderDetails: getModelProviderDetails$1,
11050
+ getApiKeyName: getApiKeyName$1
11051
+ };
11052
+
11053
+ /*
11054
+ * Component: Environment Utilities
11055
+ * Block-UUID: a4f78a41-3054-45f1-a839-778a3bd598f2
11056
+ * Parent-UUID: N/A
11057
+ * Version: 1.0.0
11058
+ * Description: Provides utility functions for loading and accessing environment variables from a .env file.
11059
+ * Language: JavaScript
11060
+ * Created-at: 2025-08-28T17:46:26.948Z
11061
+ * Authors: Gemini 2.5 Flash (v1.0.0)
11062
+ */
11063
+
11064
+ const fs = require$$0.promises;
11065
+
11066
+ // Simple .env parser, as dotenv is not explicitly a dependency
11067
+ // This handles basic KEY=VALUE pairs, ignores comments and empty lines.
11068
+ async function parseEnvFile(filePath) {
11069
+ const env = {};
11070
+ try {
11071
+ const fileContent = await fs.readFile(filePath, 'utf8');
11072
+ fileContent.split('\n').forEach(line => {
11073
+ const trimmedLine = line.trim();
11074
+ if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) {
11075
+ return; // Skip empty lines and comments
11076
+ }
11077
+ const parts = trimmedLine.split('=');
11078
+ if (parts.length >= 2) {
11079
+ const key = parts[0].trim();
11080
+ const value = parts.slice(1).join('=').trim(); // Handle values with '='
11081
+ env[key] = value;
11082
+ }
11083
+ });
11084
+ } catch (error) {
11085
+ if (error.code === 'ENOENT') {
11086
+ console.warn(`EnvUtils: .env file not found at ${filePath}. Proceeding without loading.`);
11087
+ } else {
11088
+ throw new Error(`EnvUtils: Failed to read or parse .env file at ${filePath}: ${error.message}`);
11089
+ }
11090
+ }
11091
+ return env;
11092
+ }
11093
+
10967
11094
  /**
11095
+ * Loads environment variables from the specified .env file path into process.env.
11096
+ * This function will only load the .env file once per process.
11097
+ *
11098
+ * @param {string} filePath - The absolute path to the .env file.
11099
+ * @returns {Promise<void>} A promise that resolves when the .env file has been processed.
11100
+ * @throws {Error} If the file exists but cannot be read or parsed.
11101
+ */
11102
+ let envLoaded = false;
11103
+ async function loadEnv$1(filePath) {
11104
+ if (envLoaded) {
11105
+ return; // Only load once
11106
+ }
11107
+
11108
+ const envVars = await parseEnvFile(filePath);
11109
+ for (const key in envVars) {
11110
+ if (Object.hasOwnProperty.call(envVars, key)) {
11111
+ // Only set if not already set in process.env (e.g., by system environment)
11112
+ if (process.env[key] === undefined) {
11113
+ process.env[key] = envVars[key];
11114
+ }
11115
+ }
11116
+ }
11117
+ envLoaded = true;
11118
+ }
11119
+
11120
+ /**
11121
+ * Retrieves the value of a specific API key from process.env.
11122
+ * Assumes loadEnv has been called previously.
11123
+ *
11124
+ * @param {string} keyName - The name of the environment variable holding the API key (e.g., "GEMINI_API_KEY").
11125
+ * @returns {string|null} The API key string, or null if the environment variable is not set.
11126
+ */
11127
+ function getApiKey$1(keyName) {
11128
+ if (typeof keyName !== 'string' || keyName.trim() === '') {
11129
+ console.warn('EnvUtils: Attempted to get API key with an invalid keyName.');
11130
+ return null;
11131
+ }
11132
+ return process.env[keyName] || null;
11133
+ }
11134
+
11135
+ var EnvUtils$1 = {
11136
+ loadEnv: loadEnv$1,
11137
+ getApiKey: getApiKey$1
11138
+ };
11139
+
11140
+ /*
10968
11141
  * Component: GitSenseChatUtils
10969
11142
  * Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
10970
11143
  * Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
10971
- * Version: 2.1.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.
11144
+ * Version: 2.1.2
11145
+ * 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
11146
  * Language: JavaScript
10974
11147
  * 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)
11148
+ * 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)
10976
11149
  */
10977
11150
 
10978
11151
  const ChatUtils = ChatUtils$1;
@@ -10985,13 +11158,15 @@ const PatchUtils = PatchUtils$2;
10985
11158
  const GSToolBlockUtils = GSToolBlockUtils$3;
10986
11159
  const LLMUtils = LLMUtils$1;
10987
11160
  const JsonUtils = JsonUtils$2;
11161
+ const ConfigUtils = ConfigUtils$1;
11162
+ const EnvUtils = EnvUtils$1;
10988
11163
 
10989
11164
  const {
10990
11165
  estimateTokens
10991
11166
  } = LLMUtils;
10992
11167
 
10993
- const {
10994
- detectJsonComments
11168
+ const {
11169
+ detectJsonComments
10995
11170
  } = JsonUtils;
10996
11171
 
10997
11172
  const {
@@ -11057,11 +11232,24 @@ const {
11057
11232
  verifyAndCorrectLineNumbers,
11058
11233
  } = PatchUtils;
11059
11234
 
11060
- const {
11235
+ const {
11061
11236
  isToolBlock,
11062
11237
  parseToolBlock
11063
11238
  } = GSToolBlockUtils;
11064
11239
 
11240
+ const {
11241
+ loadConfig,
11242
+ getProviderConfig,
11243
+ getModelProviderDetails,
11244
+ getApiKeyName
11245
+ } = ConfigUtils;
11246
+
11247
+ const {
11248
+ loadEnv,
11249
+ getApiKey
11250
+ } = EnvUtils;
11251
+
11252
+
11065
11253
  /**
11066
11254
  * GitSenseChatUtils class provides a unified interface to code block and patch utilities.
11067
11255
  * Focuses on markdown code block extraction and processing.
@@ -11206,8 +11394,8 @@ class GitSenseChatUtils {
11206
11394
  extractDiffContent(patchText) {
11207
11395
  // Uses function from PatchUtils (assuming it's named extractPatchContent or similar)
11208
11396
  // If PatchUtils.extractDiffContent exists, use it. Otherwise, use extractPatchContent.
11209
- return PatchUtils.extractDiffContent
11210
- ? PatchUtils.extractDiffContent(patchText)
11397
+ return PatchUtils.extractDiffContent
11398
+ ? PatchUtils.extractDiffContent(patchText)
11211
11399
  : PatchUtils.extractPatchContent(patchText);
11212
11400
  }
11213
11401
 
@@ -11282,6 +11470,8 @@ var GitSenseChatUtils_1 = {
11282
11470
  ChatUtils,
11283
11471
  GSToolBlockUtils,
11284
11472
  JsonUtils,
11473
+ ConfigUtils,
11474
+ EnvUtils,
11285
11475
 
11286
11476
  // --- Individual Function Exports (sourced correctly) ---
11287
11477
 
@@ -11314,14 +11504,14 @@ var GitSenseChatUtils_1 = {
11314
11504
  formatBlockWithLineNumbers,
11315
11505
  formatBlocksWithLineNumbers,
11316
11506
  removeLineNumbers,
11317
-
11507
+
11318
11508
  // Other Utilities (from CodeBlockUtils)
11319
11509
  removeCodeBlockMarkers,
11320
11510
  parseCommentDelimitedBlocks,
11321
11511
  updateCodeBlockByIndex,
11322
11512
  deleteCodeBlockByIndex,
11323
11513
 
11324
- // Analysis Block Utilities
11514
+ // Analysis Block Utilities
11325
11515
  isOverviewBlock,
11326
11516
  getOverviewType,
11327
11517
  parseOverviewMetadata,
@@ -11333,7 +11523,7 @@ var GitSenseChatUtils_1 = {
11333
11523
  validateLLMAnalysisData: AnalyzerUtils.validateLLMAnalysisData,
11334
11524
 
11335
11525
  // ChatUtils
11336
- getChatMessages,
11526
+ getChatMessages,
11337
11527
 
11338
11528
  // Message Utils
11339
11529
  getChatTemplateMessages,
@@ -11353,6 +11543,16 @@ var GitSenseChatUtils_1 = {
11353
11543
  isToolBlock,
11354
11544
  parseToolBlock,
11355
11545
 
11546
+ // Config Utils
11547
+ loadConfig,
11548
+ getProviderConfig,
11549
+ getModelProviderDetails,
11550
+ getApiKeyName,
11551
+
11552
+ // EnvUtils
11553
+ loadEnv,
11554
+ getApiKey,
11555
+
11356
11556
  // Note: Internal helpers like findAllCodeFences, matchFencesAndExtractBlocks are
11357
11557
  // typically not exported directly from the facade but are available via CodeBlockUtils object.
11358
11558
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsense/gsc-utils",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Utilities for GitSense Chat (GSC)",
5
5
  "main": "dist/gsc-utils.cjs.js",
6
6
  "module": "dist/gsc-utils.esm.js",
@@ -1,4 +1,4 @@
1
- /**
1
+ /*
2
2
  * Component: CodeBlockUtils Continuation Utilities
3
3
  * Block-UUID: 6fdf5c7d-4def-42a1-bc88-0312f6002cfc
4
4
  * Parent-UUID: 6322afcd-2e5e-425a-9a43-4c72c887f668
@@ -165,8 +165,8 @@ Example of the START of your response:
165
165
  \`\`\`${language}
166
166
  /**
167
167
  * Component: ${componentName}
168
- * Block-UUID: 01147ddf-320f-498a-a744-198d42a9d2ee
169
- * Parent-UUID: e4c0d839-ea17-467d-a0cc-d269d1dbc404
168
+ * Block-UUID: 01147ddf-320f-498a-a744-198d42a9d2ee
169
+ * Parent-UUID: e4c0d839-ea17-467d-a0cc-d269d1dbc404
170
170
  * Version: ${nextVersion}
171
171
  * Description: ${description}
172
172
  * Language: ${language}
@@ -0,0 +1,86 @@
1
+ /*
2
+ * Component: Config Utilities
3
+ * Block-UUID: 89016e46-9898-42f0-bef4-564e442cfaf3
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.0
6
+ * Description: Provides utility functions for loading and accessing application configuration from data/chats.json.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-08-28T17:46:26.948Z
9
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10
+ */
11
+
12
+
13
+ const fs = require('fs').promises;
14
+
15
+ /**
16
+ * Loads and parses the application configuration from the specified JSON file.
17
+ *
18
+ * @param {string} filePath - The absolute path to the data/chats.json file.
19
+ * @returns {Promise<Object>} A promise that resolves with the parsed configuration object.
20
+ * @throws {Error} If the file cannot be read or parsed.
21
+ */
22
+ async function loadConfig(filePath) {
23
+ try {
24
+ const fileContent = await fs.readFile(filePath, 'utf8');
25
+ return JSON.parse(fileContent);
26
+ } catch (error) {
27
+ if (error.code === 'ENOENT') {
28
+ throw new Error(`Configuration file not found at: ${filePath}`);
29
+ }
30
+ throw new Error(`Failed to load or parse configuration from ${filePath}: ${error.message}`);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Retrieves the configuration details for a specific LLM provider.
36
+ *
37
+ * @param {Object} config - The loaded configuration object.
38
+ * @param {string} providerName - The name of the LLM provider (e.g., "Google", "Anthropic").
39
+ * @returns {Object|null} The provider's configuration object or null if not found.
40
+ */
41
+ function getProviderConfig(config, providerName) {
42
+ if (!config || !config.providers || !Array.isArray(config.providers)) {
43
+ return null;
44
+ }
45
+ return config.providers.find(p => p.name === providerName) || null;
46
+ }
47
+
48
+ /**
49
+ * Finds the specific modelId and other details for a given user-friendly modelName and providerName.
50
+ *
51
+ * @param {Object} config - The loaded configuration object.
52
+ * @param {string} modelName - The user-friendly name of the model (e.g., "Gemini 2.5 Flash").
53
+ * @param {string} providerName - The name of the provider associated with that model.
54
+ * @returns {Object|null} An object containing modelId, maxOutputTokens, and other provider-specific model details, or null if not found.
55
+ */
56
+ function getModelProviderDetails(config, modelName, providerName) {
57
+ if (!config || !config.models || !Array.isArray(config.models)) {
58
+ return null;
59
+ }
60
+
61
+ const modelEntry = config.models.find(m => m.name === modelName);
62
+ if (!modelEntry || !modelEntry.providers || !Array.isArray(modelEntry.providers)) {
63
+ return null;
64
+ }
65
+
66
+ return modelEntry.providers.find(p => p.name === providerName) || null;
67
+ }
68
+
69
+ /**
70
+ * Retrieves the environment variable name (e.g., "GEMINI_API_KEY") for the API key of a specific provider.
71
+ *
72
+ * @param {Object} config - The loaded configuration object.
73
+ * @param {string} providerName - The name of the LLM provider.
74
+ * @returns {string|null} The name of the environment variable that holds the API key, or null if not found.
75
+ */
76
+ function getApiKeyName(config, providerName) {
77
+ const providerConfig = getProviderConfig(config, providerName);
78
+ return providerConfig ? providerConfig.apiKeyName : null;
79
+ }
80
+
81
+ module.exports = {
82
+ loadConfig,
83
+ getProviderConfig,
84
+ getModelProviderDetails,
85
+ getApiKeyName
86
+ };
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Component: Environment Utilities
3
+ * Block-UUID: a4f78a41-3054-45f1-a839-778a3bd598f2
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.0
6
+ * Description: Provides utility functions for loading and accessing environment variables from a .env file.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-08-28T17:46:26.948Z
9
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10
+ */
11
+
12
+
13
+ const fs = require('fs').promises;
14
+ const path = require('path');
15
+
16
+ // Simple .env parser, as dotenv is not explicitly a dependency
17
+ // This handles basic KEY=VALUE pairs, ignores comments and empty lines.
18
+ async function parseEnvFile(filePath) {
19
+ const env = {};
20
+ try {
21
+ const fileContent = await fs.readFile(filePath, 'utf8');
22
+ fileContent.split('\n').forEach(line => {
23
+ const trimmedLine = line.trim();
24
+ if (trimmedLine.length === 0 || trimmedLine.startsWith('#')) {
25
+ return; // Skip empty lines and comments
26
+ }
27
+ const parts = trimmedLine.split('=');
28
+ if (parts.length >= 2) {
29
+ const key = parts[0].trim();
30
+ const value = parts.slice(1).join('=').trim(); // Handle values with '='
31
+ env[key] = value;
32
+ }
33
+ });
34
+ } catch (error) {
35
+ if (error.code === 'ENOENT') {
36
+ console.warn(`EnvUtils: .env file not found at ${filePath}. Proceeding without loading.`);
37
+ } else {
38
+ throw new Error(`EnvUtils: Failed to read or parse .env file at ${filePath}: ${error.message}`);
39
+ }
40
+ }
41
+ return env;
42
+ }
43
+
44
+ /**
45
+ * Loads environment variables from the specified .env file path into process.env.
46
+ * This function will only load the .env file once per process.
47
+ *
48
+ * @param {string} filePath - The absolute path to the .env file.
49
+ * @returns {Promise<void>} A promise that resolves when the .env file has been processed.
50
+ * @throws {Error} If the file exists but cannot be read or parsed.
51
+ */
52
+ let envLoaded = false;
53
+ async function loadEnv(filePath) {
54
+ if (envLoaded) {
55
+ return; // Only load once
56
+ }
57
+
58
+ const envVars = await parseEnvFile(filePath);
59
+ for (const key in envVars) {
60
+ if (Object.hasOwnProperty.call(envVars, key)) {
61
+ // Only set if not already set in process.env (e.g., by system environment)
62
+ if (process.env[key] === undefined) {
63
+ process.env[key] = envVars[key];
64
+ }
65
+ }
66
+ }
67
+ envLoaded = true;
68
+ }
69
+
70
+ /**
71
+ * Retrieves the value of a specific API key from process.env.
72
+ * Assumes loadEnv has been called previously.
73
+ *
74
+ * @param {string} keyName - The name of the environment variable holding the API key (e.g., "GEMINI_API_KEY").
75
+ * @returns {string|null} The API key string, or null if the environment variable is not set.
76
+ */
77
+ function getApiKey(keyName) {
78
+ if (typeof keyName !== 'string' || keyName.trim() === '') {
79
+ console.warn('EnvUtils: Attempted to get API key with an invalid keyName.');
80
+ return null;
81
+ }
82
+ return process.env[keyName] || null;
83
+ }
84
+
85
+ module.exports = {
86
+ loadEnv,
87
+ getApiKey
88
+ };
@@ -1,12 +1,12 @@
1
- /**
1
+ /*
2
2
  * Component: GitSenseChatUtils
3
3
  * Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
4
4
  * Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
5
- * Version: 2.1.1
6
- * 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.
5
+ * Version: 2.1.2
6
+ * 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.
7
7
  * Language: JavaScript
8
8
  * Created-at: 2025-04-15T16:04:26.780Z
9
- * 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)
9
+ * 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)
10
10
  */
11
11
 
12
12
 
@@ -20,13 +20,15 @@ const PatchUtils = require('./PatchUtils');
20
20
  const GSToolBlockUtils = require('./GSToolBlockUtils');
21
21
  const LLMUtils = require('./LLMUtils');
22
22
  const JsonUtils = require('./JsonUtils');
23
+ const ConfigUtils = require('./ConfigUtils');
24
+ const EnvUtils = require('./EnvUtils');
23
25
 
24
26
  const {
25
27
  estimateTokens
26
28
  } = LLMUtils;
27
29
 
28
- const {
29
- detectJsonComments
30
+ const {
31
+ detectJsonComments
30
32
  } = JsonUtils;
31
33
 
32
34
  const {
@@ -92,11 +94,24 @@ const {
92
94
  verifyAndCorrectLineNumbers,
93
95
  } = PatchUtils;
94
96
 
95
- const {
97
+ const {
96
98
  isToolBlock,
97
99
  parseToolBlock
98
100
  } = GSToolBlockUtils;
99
101
 
102
+ const {
103
+ loadConfig,
104
+ getProviderConfig,
105
+ getModelProviderDetails,
106
+ getApiKeyName
107
+ } = ConfigUtils;
108
+
109
+ const {
110
+ loadEnv,
111
+ getApiKey
112
+ } = EnvUtils;
113
+
114
+
100
115
  /**
101
116
  * GitSenseChatUtils class provides a unified interface to code block and patch utilities.
102
117
  * Focuses on markdown code block extraction and processing.
@@ -241,8 +256,8 @@ class GitSenseChatUtils {
241
256
  extractDiffContent(patchText) {
242
257
  // Uses function from PatchUtils (assuming it's named extractPatchContent or similar)
243
258
  // If PatchUtils.extractDiffContent exists, use it. Otherwise, use extractPatchContent.
244
- return PatchUtils.extractDiffContent
245
- ? PatchUtils.extractDiffContent(patchText)
259
+ return PatchUtils.extractDiffContent
260
+ ? PatchUtils.extractDiffContent(patchText)
246
261
  : PatchUtils.extractPatchContent(patchText);
247
262
  }
248
263
 
@@ -317,6 +332,8 @@ module.exports = {
317
332
  ChatUtils,
318
333
  GSToolBlockUtils,
319
334
  JsonUtils,
335
+ ConfigUtils,
336
+ EnvUtils,
320
337
 
321
338
  // --- Individual Function Exports (sourced correctly) ---
322
339
 
@@ -349,14 +366,14 @@ module.exports = {
349
366
  formatBlockWithLineNumbers,
350
367
  formatBlocksWithLineNumbers,
351
368
  removeLineNumbers,
352
-
369
+
353
370
  // Other Utilities (from CodeBlockUtils)
354
371
  removeCodeBlockMarkers,
355
372
  parseCommentDelimitedBlocks,
356
373
  updateCodeBlockByIndex,
357
374
  deleteCodeBlockByIndex,
358
375
 
359
- // Analysis Block Utilities
376
+ // Analysis Block Utilities
360
377
  isOverviewBlock,
361
378
  getOverviewType,
362
379
  parseOverviewMetadata,
@@ -368,7 +385,7 @@ module.exports = {
368
385
  validateLLMAnalysisData: AnalyzerUtils.validateLLMAnalysisData,
369
386
 
370
387
  // ChatUtils
371
- getChatMessages,
388
+ getChatMessages,
372
389
 
373
390
  // Message Utils
374
391
  getChatTemplateMessages,
@@ -388,6 +405,16 @@ module.exports = {
388
405
  isToolBlock,
389
406
  parseToolBlock,
390
407
 
408
+ // Config Utils
409
+ loadConfig,
410
+ getProviderConfig,
411
+ getModelProviderDetails,
412
+ getApiKeyName,
413
+
414
+ // EnvUtils
415
+ loadEnv,
416
+ getApiKey,
417
+
391
418
  // Note: Internal helpers like findAllCodeFences, matchFencesAndExtractBlocks are
392
419
  // typically not exported directly from the facade but are available via CodeBlockUtils object.
393
420
  };