@gitsense/gsc-utils 0.2.16 → 0.2.18

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.
@@ -675,7 +675,7 @@ var constants$2 = {
675
675
  * Generates a valid RFC 4122 UUID v4
676
676
  * @returns {string} A valid UUID v4
677
677
  */
678
- function generateUUID$2() {
678
+ function generateUUID$3() {
679
679
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
680
680
  const r = Math.random() * 16 | 0;
681
681
  const v = c === 'x' ? r : (r & 0x3 | 0x8);
@@ -688,13 +688,13 @@ function generateUUID$2() {
688
688
  * @param {string} uuid - The UUID string to validate
689
689
  * @returns {Object} Object containing validation results and replacement UUID if needed
690
690
  */
691
- function validateUUID$3(uuid) {
691
+ function validateUUID$4(uuid) {
692
692
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
693
693
 
694
694
  if (!uuidPattern.test(uuid)) {
695
695
  return {
696
696
  "Block-UUID": "INVALID UUID",
697
- "Correct Block-UUID": generateUUID$2()
697
+ "Correct Block-UUID": generateUUID$3()
698
698
  };
699
699
  }
700
700
 
@@ -704,8 +704,8 @@ function validateUUID$3(uuid) {
704
704
  }
705
705
 
706
706
  var uuidUtils = {
707
- generateUUID: generateUUID$2,
708
- validateUUID: validateUUID$3
707
+ generateUUID: generateUUID$3,
708
+ validateUUID: validateUUID$4
709
709
  };
710
710
 
711
711
  /**
@@ -797,7 +797,7 @@ function formatBlocksWithLineNumbers$2(blocks, startLine = 1, paddingWidth = 0)
797
797
  * @param {string} formattedContent - The code content with line numbers
798
798
  * @returns {string} The original code content without line numbers
799
799
  */
800
- function removeLineNumbers$9(formattedContent) {
800
+ function removeLineNumbers$a(formattedContent) {
801
801
  if (typeof formattedContent !== 'string') {
802
802
  throw new Error("formattedContent must be a string");
803
803
  }
@@ -821,7 +821,7 @@ var lineNumberFormatter = {
821
821
  formatWithLineNumbers: formatWithLineNumbers$2,
822
822
  formatBlockWithLineNumbers: formatBlockWithLineNumbers$2,
823
823
  formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$2,
824
- removeLineNumbers: removeLineNumbers$9
824
+ removeLineNumbers: removeLineNumbers$a
825
825
  };
826
826
 
827
827
  /**
@@ -837,8 +837,8 @@ var lineNumberFormatter = {
837
837
 
838
838
  // Dependencies from other modules within CodeBlockUtils
839
839
  const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$2;
840
- const { removeLineNumbers: removeLineNumbers$8 } = lineNumberFormatter; // Assuming this utility exists
841
- const { validateUUID: validateUUID$2 } = uuidUtils; // Assuming uuidUtils.js is in the same directory
840
+ const { removeLineNumbers: removeLineNumbers$9 } = lineNumberFormatter; // Assuming this utility exists
841
+ const { validateUUID: validateUUID$3 } = uuidUtils; // Assuming uuidUtils.js is in the same directory
842
842
 
843
843
  const MAX_HEADER_LINES = 12; // Maximum allowed non-empty lines for a header
844
844
  /**
@@ -863,7 +863,7 @@ function isValidISOTimestamp$2(timestamp) {
863
863
  * @returns {Object} - The parsed header object.
864
864
  * @throws {Error} If header parsing fails (e.g., missing fields, invalid format).
865
865
  */
866
- function parseHeader$2(header, language) {
866
+ function parseHeader$3(header, language) {
867
867
  const headerObject = {};
868
868
 
869
869
  // Get comment style for the language
@@ -972,7 +972,7 @@ function parseHeader$2(header, language) {
972
972
  // Special handling for Block-UUID and Parent-UUID
973
973
  if (key === "Block-UUID" || key === "Parent-UUID") {
974
974
  if (value !== 'N/A') {
975
- const uuidValidation = validateUUID$2(value); // Use imported function
975
+ const uuidValidation = validateUUID$3(value); // Use imported function
976
976
  if (uuidValidation["Block-UUID"] === "INVALID UUID") {
977
977
  // Store invalid status and the suggested correction
978
978
  headerObject[key] = "INVALID UUID";
@@ -1054,7 +1054,7 @@ function getHeaderLineCount$1(headerText, language) {
1054
1054
 
1055
1055
  var headerUtils = {
1056
1056
  isValidISOTimestamp: isValidISOTimestamp$2,
1057
- parseHeader: parseHeader$2,
1057
+ parseHeader: parseHeader$3,
1058
1058
  getHeaderLineCount: getHeaderLineCount$1 // Export the new function
1059
1059
  };
1060
1060
 
@@ -1074,7 +1074,7 @@ var headerUtils = {
1074
1074
  * @param {string} text - The input text
1075
1075
  * @returns {Object} Object containing arrays of opening and closing fence positions: { openingPositions: Array, closingPositions: Array }
1076
1076
  */
1077
- function findAllCodeFences$2(text) {
1077
+ function findAllCodeFences$4(text) {
1078
1078
  const openingPositions = [];
1079
1079
  const closingPositions = [];
1080
1080
 
@@ -1139,7 +1139,7 @@ function findAllCodeFences$2(text) {
1139
1139
  * @param {Array} closingPositions - Array of closing fence objects { position, length }
1140
1140
  * @returns {Object} Object containing: { completeBlocks: Array, incompleteBlocks: Array, warnings: Array }
1141
1141
  */
1142
- function matchFencesAndExtractBlocks$2(text, openingPositions, closingPositions) {
1142
+ function matchFencesAndExtractBlocks$4(text, openingPositions, closingPositions) {
1143
1143
  const completeBlocks = [];
1144
1144
  const incompleteBlocks = [];
1145
1145
  const warnings = [];
@@ -1298,7 +1298,7 @@ function extractCodeBlocksWithUUIDs$1(messageText) {
1298
1298
  * @param {string} blockUUID - The Block-UUID to find
1299
1299
  * @returns {Object|null} Code block object or null if not found
1300
1300
  */
1301
- function findCodeBlockByUUID$1(messageText, blockUUID) {
1301
+ function findCodeBlockByUUID$2(messageText, blockUUID) {
1302
1302
  if (!messageText || !blockUUID) {
1303
1303
  return null;
1304
1304
  }
@@ -1308,10 +1308,10 @@ function findCodeBlockByUUID$1(messageText, blockUUID) {
1308
1308
  }
1309
1309
 
1310
1310
  var blockExtractor = {
1311
- findAllCodeFences: findAllCodeFences$2,
1312
- matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$2,
1311
+ findAllCodeFences: findAllCodeFences$4,
1312
+ matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$4,
1313
1313
  extractCodeBlocksWithUUIDs: extractCodeBlocksWithUUIDs$1,
1314
- findCodeBlockByUUID: findCodeBlockByUUID$1
1314
+ findCodeBlockByUUID: findCodeBlockByUUID$2
1315
1315
  };
1316
1316
 
1317
1317
  /**
@@ -1458,7 +1458,7 @@ function validateAnalysisMetadata(metadata) {
1458
1458
  }
1459
1459
 
1460
1460
 
1461
- var AnalysisBlockUtils$2 = {
1461
+ var AnalysisBlockUtils$3 = {
1462
1462
  isAnalysisBlock,
1463
1463
  getAnalysisBlockType,
1464
1464
  parseOverviewMetadata: parseOverviewMetadata$1,
@@ -1807,7 +1807,7 @@ var constants$1 = {
1807
1807
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
1808
1808
  */
1809
1809
 
1810
- const { removeLineNumbers: removeLineNumbers$7 } = lineNumberFormatter; // Assuming this utility exists
1810
+ const { removeLineNumbers: removeLineNumbers$8 } = lineNumberFormatter; // Assuming this utility exists
1811
1811
  const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$4, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$3 } = constants$1;
1812
1812
 
1813
1813
 
@@ -1972,7 +1972,7 @@ var formatAndAddLineNumbers_1 = {
1972
1972
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0), Claude 3.7 Sonnet (v1.1.0, v1.2.0)
1973
1973
  */
1974
1974
 
1975
- const { removeLineNumbers: removeLineNumbers$6 } = lineNumberFormatter; // Assuming this utility exists
1975
+ const { removeLineNumbers: removeLineNumbers$7 } = lineNumberFormatter; // Assuming this utility exists
1976
1976
  const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$3 } = constants$1;
1977
1977
  const { formatAndAddLineNumbers: formatAndAddLineNumbers$1 } = formatAndAddLineNumbers_1; // Import the helper
1978
1978
 
@@ -2020,7 +2020,7 @@ function verifyAndCorrectLineNumbers$2(patchText, sourceText, windowSize = 251)
2020
2020
  const formatResult = formatAndAddLineNumbers$1(patchText, sourceText);
2021
2021
  const patchLines = formatResult.formattedPatchText.split('\n');
2022
2022
  // Ensure source is clean (defensive check, though caller should provide clean source)
2023
- const sourceLines = removeLineNumbers$6(sourceText).split('\n');
2023
+ const sourceLines = removeLineNumbers$7(sourceText).split('\n');
2024
2024
  const outputLines = [];
2025
2025
  const errors = [];
2026
2026
  let correctionsMade = formatResult.correctionsMade; // Inherit corrections made by formatter
@@ -6578,7 +6578,7 @@ function escapeHTML(s) {
6578
6578
 
6579
6579
  const parser$1 = patchParser;
6580
6580
  const jsdiff$1 = lib;
6581
- const { removeLineNumbers: removeLineNumbers$5 } = lineNumberFormatter;
6581
+ const { removeLineNumbers: removeLineNumbers$6 } = lineNumberFormatter;
6582
6582
 
6583
6583
  /**
6584
6584
  * Apply patch against source code. Expects traditional unified diff format.
@@ -6620,7 +6620,7 @@ function applyPatch(sourceText, patchText) {
6620
6620
  }
6621
6621
 
6622
6622
  // 1.1. Play it safe and clean sourceText by removing potential line numbers
6623
- sourceText = removeLineNumbers$5(sourceText);
6623
+ sourceText = removeLineNumbers$6(sourceText);
6624
6624
 
6625
6625
  // 2. Extract metadata (optional for applying, but good practice)
6626
6626
  const metadata = parser$1.extractPatchMetadata(patchText);
@@ -6685,8 +6685,8 @@ function createPatch(sourceText, targetCode, metadata = {}, filename = 'Original
6685
6685
 
6686
6686
  try {
6687
6687
  // --- CRITICAL: jsdiff needs CLEAN text ---
6688
- const cleanSource = removeLineNumbers$5(sourceText);
6689
- const cleanTarget = removeLineNumbers$5(targetCode);
6688
+ const cleanSource = removeLineNumbers$6(sourceText);
6689
+ const cleanTarget = removeLineNumbers$6(targetCode);
6690
6690
 
6691
6691
  // --- Generate standard diff ---
6692
6692
  // Provide filenames for standard diff headers (--- filename \n +++ filename)
@@ -7320,7 +7320,7 @@ var fuzzyMatcher$1 = {
7320
7320
  * Authors: Claude 3.7 Sonnet (v1.0.0), Claude 3.5 Sonnet (v1.1.0, v1.2.0), Claude 3.5 Sonnet (v1.3.0), Gemini 2.5 Flash (v1.3.0)
7321
7321
  */
7322
7322
  const { findBestContextMatch: findBestContextMatch$1, findBestMatchWithSlidingWindow: findBestMatchWithSlidingWindow$1 } = fuzzyMatcher$1;
7323
- const { removeLineNumbers: removeLineNumbers$4 } = lineNumberFormatter;
7323
+ const { removeLineNumbers: removeLineNumbers$5 } = lineNumberFormatter;
7324
7324
 
7325
7325
  /**
7326
7326
  * Parses a hunk into its components
@@ -7340,7 +7340,7 @@ function parseHunk(hunkText) {
7340
7340
 
7341
7341
  for (const line of contentLines) {
7342
7342
  // Clean line numbers from the content
7343
- const cleanLine = removeLineNumbers$4(line.substring(1));
7343
+ const cleanLine = removeLineNumbers$5(line.substring(1));
7344
7344
 
7345
7345
  if (line.startsWith(' ')) {
7346
7346
  // Regular context line - add to both context arrays
@@ -7991,7 +7991,7 @@ var diagnosticReporter$1 = {
7991
7991
  * Authors: Claude 3.7 Sonnet (v1.0.0)
7992
7992
  */
7993
7993
 
7994
- const { removeLineNumbers: removeLineNumbers$3 } = lineNumberFormatter;
7994
+ const { removeLineNumbers: removeLineNumbers$4 } = lineNumberFormatter;
7995
7995
 
7996
7996
  /**
7997
7997
  * Extracts individual hunks from a patch
@@ -8098,7 +8098,7 @@ function cleanHunkLineNumbers$1(hunkText) {
8098
8098
 
8099
8099
  if (line.startsWith(' ') || line.startsWith('+') || line.startsWith('-')) {
8100
8100
  const prefix = line[0];
8101
- const content = removeLineNumbers$3(line.substring(1));
8101
+ const content = removeLineNumbers$4(line.substring(1));
8102
8102
  cleanedLines.push(`${prefix}${content}`);
8103
8103
  } else {
8104
8104
  // Non-content line, keep as is
@@ -8167,7 +8167,7 @@ var patchExtractor$1 = {
8167
8167
  */
8168
8168
 
8169
8169
  const jsdiff = lib;
8170
- const { removeLineNumbers: removeLineNumbers$2 } = lineNumberFormatter;
8170
+ const { removeLineNumbers: removeLineNumbers$3 } = lineNumberFormatter;
8171
8171
  const { extractAndCleanHunks, reconstructPatch } = patchExtractor$1;
8172
8172
  const { validateHunk, validateHunks } = hunkValidator$1;
8173
8173
  const { findBestContextMatch, findBestMatchWithSlidingWindow } = fuzzyMatcher$1;
@@ -8220,7 +8220,7 @@ function applyPatchWithDiagnostics(sourceText, patchText) {
8220
8220
  }
8221
8221
 
8222
8222
  // Clean source text (remove any line numbers)
8223
- const cleanSourceText = removeLineNumbers$2(sourceText);
8223
+ const cleanSourceText = removeLineNumbers$3(sourceText);
8224
8224
 
8225
8225
  // First, clean up redundant changes
8226
8226
  const redundantFixResult = detectAndFixRedundantChanges(patchText, true);
@@ -8388,7 +8388,7 @@ function validatePatch(sourceText, patchText) {
8388
8388
  }
8389
8389
 
8390
8390
  // Clean source text
8391
- const cleanSourceText = removeLineNumbers$2(sourceText);
8391
+ const cleanSourceText = removeLineNumbers$3(sourceText);
8392
8392
 
8393
8393
  // Clean up redundant changes
8394
8394
  const redundantFixResult = detectAndFixRedundantChanges(patchText, true);
@@ -8465,7 +8465,7 @@ function applyHunk(sourceText, hunkText) {
8465
8465
  }
8466
8466
 
8467
8467
  // Clean source text
8468
- const cleanSourceText = removeLineNumbers$2(sourceText);
8468
+ const cleanSourceText = removeLineNumbers$3(sourceText);
8469
8469
 
8470
8470
  // Clean hunk line numbers
8471
8471
  const cleanHunk = cleanHunkLineNumbers(hunkText);
@@ -8599,7 +8599,7 @@ const enhancedProcessor = enhancedPatchProcessor;
8599
8599
  */
8600
8600
 
8601
8601
  // Export all modules
8602
- var PatchUtils$1 = {
8602
+ var PatchUtils$2 = {
8603
8603
  // Original exports (for backward compatibility)
8604
8604
  validateAndParseContextPatch: parser.validateAndParseContextPatch,
8605
8605
  determinePatchFormat: parser.determinePatchFormat,
@@ -8680,381 +8680,6 @@ var PatchUtils$1 = {
8680
8680
  applyHunk: enhancedProcessor.applyHunk
8681
8681
  };
8682
8682
 
8683
- /**
8684
- * Component: CodeBlockUtils Update Code Block
8685
- * Block-UUID: 6a7b8c9d-0e1f-42a3-b4c5-d6e7f8a9b0c1
8686
- * Parent-UUID: 5f9c1e3a-7b2d-4e8f-a1d0-9c4b2e1f8a0b
8687
- * Version: 1.4.0
8688
- * Description: Provides functions to update the content of a specific code block within a string, identified by index, UUID, or direct reference.
8689
- * Language: JavaScript
8690
- * Created-at: 2025-04-16T00:56:57.352Z
8691
- * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Pro (v1.2.0), Gemini 2.5 Pro (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0)
8692
- */
8693
-
8694
- var updateCodeBlock_1;
8695
- var hasRequiredUpdateCodeBlock;
8696
-
8697
- function requireUpdateCodeBlock () {
8698
- if (hasRequiredUpdateCodeBlock) return updateCodeBlock_1;
8699
- hasRequiredUpdateCodeBlock = 1;
8700
- // Dependencies from other modules within CodeBlockUtils
8701
- const { findAllCodeFences, matchFencesAndExtractBlocks, findCodeBlockByUUID } = blockExtractor; // Added findCodeBlockByUUID
8702
- const { processCodeBlocks } = requireBlockProcessor(); // To get parsed block info
8703
-
8704
- /**
8705
- * Replaces the content of a code block specified by its index within a message string.
8706
- *
8707
- * @param {string} messageContent - The original message string containing code blocks.
8708
- * @param {number} blockIndex - The 0-based index of the code block to replace.
8709
- * @param {string} newCodeContent - The new raw content (code, potentially including header) to insert into the block.
8710
- * @param {string} [language] - Optional: The language identifier for the updated code block fence. If omitted, the original language is preserved.
8711
- * @returns {string} The message content with the specified code block updated.
8712
- * @throws {Error} If the blockIndex is out of bounds or if block boundaries cannot be determined.
8713
- */
8714
- function updateCodeBlockByIndex(messageContent, blockIndex, newCodeContent, language = undefined) {
8715
- if (typeof messageContent !== 'string') {
8716
- throw new Error("messageContent must be a string.");
8717
- }
8718
- if (typeof blockIndex !== 'number' || blockIndex < 0) {
8719
- throw new Error("blockIndex must be a non-negative number.");
8720
- }
8721
- if (typeof newCodeContent !== 'string') {
8722
- // Allow empty string replacement, but not other types
8723
- throw new Error("newCodeContent must be a string.");
8724
- }
8725
-
8726
- // Step 1: Find all fence positions to get accurate start/end of the full block
8727
- const { openingPositions, closingPositions } = findAllCodeFences(messageContent);
8728
- const { completeBlocks, incompleteBlocks, warnings: extractorWarnings } = matchFencesAndExtractBlocks(
8729
- messageContent, openingPositions, closingPositions
8730
- );
8731
-
8732
- // Combine complete and incomplete for indexing, assuming we might want to update an incomplete one too
8733
- // Note: Replacing content in an incomplete block might be unusual, but technically possible.
8734
- const allBlocks = [...completeBlocks, ...incompleteBlocks];
8735
-
8736
- // Step 2: Validate index
8737
- if (blockIndex >= allBlocks.length) {
8738
- throw new Error(`blockIndex ${blockIndex} is out of bounds. Found ${allBlocks.length} blocks.`);
8739
- }
8740
-
8741
- // Step 3: Get the target block's boundary information
8742
- const targetBlockBoundaries = allBlocks[blockIndex];
8743
- const openingFence = targetBlockBoundaries.opening;
8744
- const closingFence = targetBlockBoundaries.closing; // Will be undefined for incomplete blocks
8745
-
8746
- if (!openingFence) {
8747
- // Should not happen if index is valid, but good practice to check
8748
- throw new Error(`Could not find opening fence for block at index ${blockIndex}.`);
8749
- }
8750
-
8751
- // Determine the exact start and end of the full markdown block
8752
- const blockStartPos = openingFence.position;
8753
- // If the block is incomplete, the end is the end of the messageContent
8754
- const blockEndPos = closingFence
8755
- ? closingFence.position + closingFence.length
8756
- : messageContent.length;
8757
-
8758
- // Step 4: Construct the replacement block string
8759
- const targetLanguage = language !== undefined ? language : (openingFence.language || ''); // Use provided language or original/empty
8760
- const newBlockString = `\`\`\`${targetLanguage}\n${newCodeContent}\n\`\`\``;
8761
-
8762
- // Step 5: Perform the replacement
8763
- const updatedMessageContent =
8764
- messageContent.substring(0, blockStartPos) +
8765
- newBlockString +
8766
- messageContent.substring(blockEndPos);
8767
-
8768
- return updatedMessageContent;
8769
- }
8770
-
8771
- /**
8772
- * Replaces the content of a code block specified by its Block-UUID within a message string.
8773
- *
8774
- * @param {string} messageContent - The original message string containing code blocks.
8775
- * @param {string} blockUUID - The Block-UUID of the code block to replace.
8776
- * @param {string} newCodeContent - The new raw content (code, potentially including header) to insert into the block.
8777
- * @param {string} [language] - Optional: The language identifier for the updated code block fence. If omitted, the original language is preserved.
8778
- * @returns {string} The message content with the specified code block updated.
8779
- * @throws {Error} If no block with the specified UUID is found, or if multiple blocks have the same UUID.
8780
- */
8781
- function updateCodeBlockByUUID(messageContent, blockUUID, newCodeContent, language = undefined) {
8782
- if (typeof messageContent !== 'string') {
8783
- throw new Error("messageContent must be a string.");
8784
- }
8785
- if (typeof blockUUID !== 'string' || !blockUUID) {
8786
- throw new Error("blockUUID must be a non-empty string.");
8787
- }
8788
- if (typeof newCodeContent !== 'string') {
8789
- throw new Error("newCodeContent must be a string.");
8790
- }
8791
-
8792
- // Step 1: Process blocks to get headers and find the target index
8793
- const { blocks: processedBlocks, warnings } = processCodeBlocks(messageContent, { silent: true });
8794
-
8795
- let targetIndex = -1;
8796
-
8797
- for (let i = 0; i < processedBlocks.length; i++) {
8798
- const block = processedBlocks[i];
8799
- let match = false;
8800
-
8801
- // Check standard code blocks by Block-UUID
8802
- if ((block.type === 'code') && block.header && block.header['Block-UUID'] === blockUUID) {
8803
- match = true;
8804
- }
8805
- // Check patch blocks by Target-Block-UUID
8806
- else if (block.type === 'patch' && block.metadata && block.metadata['Target-Block-UUID'] === blockUUID) {
8807
- match = true;
8808
- }
8809
-
8810
- if (match) {
8811
- // If we've already found one, log a warning but still update the first one found.
8812
- if (targetIndex !== -1) {
8813
- console.warn(`Multiple blocks found matching UUID: ${blockUUID} (could be Block-UUID or Target-Block-UUID). Updating the first occurrence.`);
8814
- } else {
8815
- targetIndex = i;
8816
- }
8817
- }
8818
- }
8819
-
8820
- // Step 2: Handle findings
8821
- if (targetIndex === -1) { // Use targetIndex to check if *any* valid match was set
8822
- throw new Error(`No code or patch block found matching UUID: ${blockUUID} (checked Block-UUID and Target-Block-UUID).`);
8823
- }
8824
- // Warning for multiple matches is handled inside the loop now.
8825
-
8826
- // Step 3: Call the index-based function
8827
- // We need the index relative to *all* blocks (complete and incomplete), not just processed ones.
8828
- // Re-extract boundaries to get the correct index mapping.
8829
- const { openingPositions, closingPositions } = findAllCodeFences(messageContent);
8830
- const { completeBlocks, incompleteBlocks } = matchFencesAndExtractBlocks(
8831
- messageContent, openingPositions, closingPositions
8832
- );
8833
- const allBlocks = [...completeBlocks, ...incompleteBlocks];
8834
-
8835
- // Find the index in the combined list that corresponds to the processed block's position
8836
- const targetProcessedBlock = processedBlocks[targetIndex];
8837
- const actualIndex = allBlocks.findIndex(b => b.opening.position === targetProcessedBlock.position);
8838
-
8839
- if (actualIndex === -1) {
8840
- // This indicates a discrepancy between blockProcessor and blockExtractor results, which shouldn't happen.
8841
- throw new Error(`Internal error: Could not map processed block at index ${targetIndex} (matching UUID: ${blockUUID}) back to extracted block boundaries.`);
8842
- }
8843
-
8844
- // Pass the optional language parameter down
8845
- return updateCodeBlockByIndex(messageContent, actualIndex, newCodeContent, language);
8846
- }
8847
-
8848
- /**
8849
- * Updates a code block in message text identified by UUID.
8850
- * (Moved from original PatchUtils)
8851
- * @param {string} messageText - The original message text
8852
- * @param {string} blockUUID - The Block-UUID to update
8853
- * @param {string} newCode - The new code content (raw content, including header if applicable)
8854
- * @param {string} language - The code language for the fence
8855
- * @returns {string} Updated message text
8856
- * @throws {Error} If block not found or parameters missing.
8857
- */
8858
- function updateCodeBlockInMessage(messageText, blockUUID, newCode, language) {
8859
- if (!messageText || !blockUUID || newCode === null || newCode === undefined) { // Allow empty string for newCode
8860
- throw new Error("Missing required parameters for updating code block (messageText, blockUUID, newCode)");
8861
- }
8862
-
8863
- // Use findCodeBlockByUUID from blockExtractor
8864
- const block = findCodeBlockByUUID(messageText, blockUUID);
8865
-
8866
- if (!block) {
8867
- throw new Error(`Code block with UUID ${blockUUID} not found`);
8868
- }
8869
-
8870
- // Construct the new full block string
8871
- const newBlockString = '```' + (language || block.language) + '\n' + newCode + '\n```';
8872
-
8873
- // Replace the old block with the new one using precise indices
8874
- return messageText.substring(0, block.startIndex) +
8875
- newBlockString +
8876
- messageText.substring(block.endIndex);
8877
- }
8878
-
8879
-
8880
- /**
8881
- * Generic router function to update a code block by index or UUID.
8882
- *
8883
- * @param {string} messageContent - The original message string.
8884
- * @param {number|string} identifier - The block index (number) or Block-UUID (string).
8885
- * @param {string} newCodeContent - The new raw content for the block.
8886
- * @param {string} [language] - Optional: The language identifier for the updated code block fence.
8887
- * @returns {string} The updated message content.
8888
- * @throws {Error} If the identifier type is invalid or if the underlying update function fails.
8889
- */
8890
- function updateCodeBlock(messageContent, identifier, newCodeContent, language = undefined) {
8891
- if (typeof identifier === 'number') {
8892
- // Pass language to index-based function
8893
- return updateCodeBlockByIndex(messageContent, identifier, newCodeContent, language);
8894
- } else if (typeof identifier === 'string') {
8895
- // Pass language to UUID-based function
8896
- return updateCodeBlockByUUID(messageContent, identifier, newCodeContent, language);
8897
- } else {
8898
- throw new Error("Invalid identifier type. Must be a number (index) or a string (UUID).");
8899
- }
8900
- }
8901
-
8902
- /**
8903
- * Deletes a code block specified by its index within a message string.
8904
- *
8905
- * @param {string} messageContent - The original message string containing code blocks.
8906
- * @param {number} blockIndex - The 0-based index of the code block to delete.
8907
- * @returns {string} The message content with the specified code block deleted.
8908
- * @throws {Error} If the blockIndex is out of bounds or if block boundaries cannot be determined.
8909
- */
8910
- function deleteCodeBlockByIndex(messageContent, blockIndex) {
8911
- if (typeof messageContent !== 'string') {
8912
- throw new Error("messageContent must be a string.");
8913
- }
8914
- if (typeof blockIndex !== 'number' || blockIndex < 0) {
8915
- throw new Error("blockIndex must be a non-negative number.");
8916
- }
8917
-
8918
- // Step 1: Find all fence positions to get accurate start/end of the full block
8919
- const { openingPositions, closingPositions } = findAllCodeFences(messageContent);
8920
- const { completeBlocks, incompleteBlocks } = matchFencesAndExtractBlocks(
8921
- messageContent, openingPositions, closingPositions
8922
- );
8923
-
8924
- // Combine complete and incomplete for indexing
8925
- const allBlocks = [...completeBlocks, ...incompleteBlocks];
8926
-
8927
- // Step 2: Validate index
8928
- if (blockIndex >= allBlocks.length) {
8929
- throw new Error(`blockIndex ${blockIndex} is out of bounds. Found ${allBlocks.length} blocks.`);
8930
- }
8931
-
8932
- // Step 3: Get the target block's boundary information
8933
- const targetBlockBoundaries = allBlocks[blockIndex];
8934
- const openingFence = targetBlockBoundaries.opening;
8935
- const closingFence = targetBlockBoundaries.closing; // Will be undefined for incomplete blocks
8936
-
8937
- if (!openingFence) {
8938
- // Should not happen if index is valid, but good practice to check
8939
- throw new Error(`Could not find opening fence for block at index ${blockIndex}.`);
8940
- }
8941
-
8942
- // Determine the exact start and end of the full markdown block
8943
- const blockStartPos = openingFence.position;
8944
- // If the block is incomplete, the end is the end of the messageContent
8945
- const blockEndPos = closingFence
8946
- ? closingFence.position + closingFence.length
8947
- : messageContent.length;
8948
-
8949
- // Step 4: Perform the deletion
8950
- const updatedMessageContent =
8951
- messageContent.substring(0, blockStartPos) +
8952
- messageContent.substring(blockEndPos);
8953
-
8954
- return updatedMessageContent;
8955
- }
8956
-
8957
- /**
8958
- * Deletes a code block specified by its Block-UUID within a message string.
8959
- *
8960
- * @param {string} messageContent - The original message string containing code blocks.
8961
- * @param {string} blockUUID - The Block-UUID of the code block to delete.
8962
- * @returns {string} The message content with the specified code block deleted.
8963
- * @throws {Error} If no block with the specified UUID is found, or if multiple blocks have the same UUID.
8964
- */
8965
- function deleteCodeBlockByUUID(messageContent, blockUUID) {
8966
- if (typeof messageContent !== 'string') {
8967
- throw new Error("messageContent must be a string.");
8968
- }
8969
- if (typeof blockUUID !== 'string' || !blockUUID) {
8970
- throw new Error("blockUUID must be a non-empty string.");
8971
- }
8972
-
8973
- // Step 1: Process blocks to get headers and find the target index
8974
- const { blocks: processedBlocks, warnings } = processCodeBlocks(messageContent, { silent: true });
8975
-
8976
- let targetIndex = -1;
8977
-
8978
- for (let i = 0; i < processedBlocks.length; i++) {
8979
- const block = processedBlocks[i];
8980
- let match = false;
8981
-
8982
- // Check standard code blocks by Block-UUID
8983
- if (block.type === 'code' && block.header && block.header['Block-UUID'] === blockUUID) {
8984
- match = true;
8985
- }
8986
- // Check patch blocks by Target-Block-UUID
8987
- else if (block.type === 'patch' && block.metadata && block.metadata['Target-Block-UUID'] === blockUUID) {
8988
- match = true;
8989
- }
8990
-
8991
- if (match) {
8992
- // If we've already found one, log a warning but still target the first one found.
8993
- if (targetIndex !== -1) {
8994
- console.warn(`Multiple blocks found matching UUID: ${blockUUID} (could be Block-UUID or Target-Block-UUID). Deleting the first occurrence.`);
8995
- } else {
8996
- targetIndex = i;
8997
- }
8998
- }
8999
- }
9000
-
9001
- // Step 2: Handle findings
9002
- if (targetIndex === -1) { // Use targetIndex to check if *any* valid match was set
9003
- throw new Error(`No code or patch block found matching UUID: ${blockUUID} (checked Block-UUID and Target-Block-UUID).`);
9004
- }
9005
- // Warning for multiple matches is handled inside the loop now.
9006
-
9007
- // Step 3: Call the index-based function
9008
- // We need the index relative to *all* blocks (complete and incomplete), not just processed ones.
9009
- // Re-extract boundaries to get the correct index mapping.
9010
- const { openingPositions, closingPositions } = findAllCodeFences(messageContent);
9011
- const { completeBlocks, incompleteBlocks } = matchFencesAndExtractBlocks(
9012
- messageContent, openingPositions, closingPositions
9013
- );
9014
- const allBlocks = [...completeBlocks, ...incompleteBlocks];
9015
-
9016
- // Find the index in the combined list that corresponds to the processed block's position
9017
- const targetProcessedBlock = processedBlocks[targetIndex];
9018
- const actualIndex = allBlocks.findIndex(b => b.opening.position === targetProcessedBlock.position);
9019
-
9020
- if (actualIndex === -1) {
9021
- // This indicates a discrepancy between blockProcessor and blockExtractor results, which shouldn't happen.
9022
- throw new Error(`Internal error: Could not map processed block at index ${targetIndex} (matching UUID: ${blockUUID}) back to extracted block boundaries.`);
9023
- }
9024
-
9025
- return deleteCodeBlockByIndex(messageContent, actualIndex);
9026
- }
9027
-
9028
- /**
9029
- * Generic router function to delete a code block by index or UUID.
9030
- *
9031
- * @param {string} messageContent - The original message string.
9032
- * @param {number|string} identifier - The block index (number) or Block-UUID (string).
9033
- * @returns {string} The updated message content.
9034
- * @throws {Error} If the identifier type is invalid or if the underlying delete function fails.
9035
- */
9036
- function deleteCodeBlock(messageContent, identifier) {
9037
- if (typeof identifier === 'number') {
9038
- return deleteCodeBlockByIndex(messageContent, identifier);
9039
- } else if (typeof identifier === 'string') {
9040
- return deleteCodeBlockByUUID(messageContent, identifier);
9041
- } else {
9042
- throw new Error("Invalid identifier type. Must be a number (index) or a string (UUID).");
9043
- }
9044
- }
9045
-
9046
- updateCodeBlock_1 = {
9047
- updateCodeBlockByIndex,
9048
- updateCodeBlockByUUID,
9049
- updateCodeBlock,
9050
- updateCodeBlockInMessage,
9051
- deleteCodeBlockByIndex,
9052
- deleteCodeBlockByUUID,
9053
- deleteCodeBlock,
9054
- };
9055
- return updateCodeBlock_1;
9056
- }
9057
-
9058
8683
  /**
9059
8684
  * Component: GitSense Tool Block Utilities
9060
8685
  * Block-UUID: 8e1f7b4e-7e30-48b4-a7fc-643bf647661f
@@ -9066,170 +8691,164 @@ function requireUpdateCodeBlock () {
9066
8691
  * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash (v1.1.0)
9067
8692
  */
9068
8693
 
9069
- var GSToolBlockUtils$2;
9070
- var hasRequiredGSToolBlockUtils;
9071
-
9072
- function requireGSToolBlockUtils () {
9073
- if (hasRequiredGSToolBlockUtils) return GSToolBlockUtils$2;
9074
- hasRequiredGSToolBlockUtils = 1;
9075
- const { updateCodeBlockByIndex } = requireUpdateCodeBlock();
9076
- const { processCodeBlocks } = requireBlockProcessor();
9077
-
9078
- /**
9079
- * Checks if a given code block content represents a GitSense Chat Tool Block.
9080
- * It verifies if the first non-empty line starts with "# GitSense Chat Tool".
9081
- *
9082
- * @param {string} content - The raw content of the code block (within the fences).
9083
- * @returns {boolean} True if it's a GitSense Chat Tool Block, false otherwise.
9084
- */
9085
- function isToolBlock(content) {
9086
- if (!content || typeof content !== 'string') {
9087
- return false;
9088
- }
8694
+ /**
8695
+ * Checks if a given code block content represents a GitSense Chat Tool Block.
8696
+ * It verifies if the first non-empty line starts with "# GitSense Chat Tool".
8697
+ *
8698
+ * @param {string} content - The raw content of the code block (within the fences).
8699
+ * @returns {boolean} True if it's a GitSense Chat Tool Block, false otherwise.
8700
+ */
8701
+ function isToolBlock$1(content) {
8702
+ if (!content || typeof content !== 'string') {
8703
+ return false;
8704
+ }
9089
8705
 
9090
- if (content.match(/^\s*# GitSense Chat Tool\n\s*{/))
9091
- return true;
8706
+ if (content.match(/^\s*# GitSense Chat Tool\n\s*{/))
8707
+ return true;
9092
8708
 
9093
- return false;
9094
- }
8709
+ return false;
8710
+ }
9095
8711
 
9096
- /**
9097
- * Parses the content of a GitSense Chat Tool Block to extract the JSON payload.
9098
- * It strips the marker line and any subsequent lines starting with '#' (comments)
9099
- * or empty lines before attempting to parse the remaining content as JSON.
9100
- *
9101
- * @param {string} content - The raw content of the code block, verified by isToolBlock.
9102
- * @returns {{ tool: string, config: object, data: object } | null} The parsed JSON object { tool, config, data } or null if parsing fails or format is invalid.
9103
- * @throws {Error} If JSON parsing fails.
9104
- */
9105
- function parseToolBlock(content) {
9106
- if (!isToolBlock(content)) {
9107
- return null; // Should already be verified, but double-check
9108
- }
8712
+ /**
8713
+ * Parses the content of a GitSense Chat Tool Block to extract the JSON payload.
8714
+ * It strips the marker line and any subsequent lines starting with '#' (comments)
8715
+ * or empty lines before attempting to parse the remaining content as JSON.
8716
+ *
8717
+ * @param {string} content - The raw content of the code block, verified by isToolBlock.
8718
+ * @returns {{ tool: string, config: object, data: object } | null} The parsed JSON object { tool, config, data } or null if parsing fails or format is invalid.
8719
+ * @throws {Error} If JSON parsing fails.
8720
+ */
8721
+ function parseToolBlock$1(content) {
8722
+ if (!isToolBlock$1(content)) {
8723
+ return null; // Should already be verified, but double-check
8724
+ }
9109
8725
 
9110
- const lines = content.split('\n');
9111
- const jsonLines = [];
9112
- let markerFound = false;
8726
+ const lines = content.split('\n');
8727
+ const jsonLines = [];
8728
+ let markerFound = false;
9113
8729
 
9114
- for (const line of lines) {
9115
- const trimmedLine = line.trim();
8730
+ for (const line of lines) {
8731
+ const trimmedLine = line.trim();
9116
8732
 
9117
- if (!markerFound) {
9118
- if (trimmedLine.startsWith('# GitSense Chat Tool')) {
9119
- markerFound = true; // Skip the marker line itself
9120
- }
9121
- continue; // Skip lines before the marker (shouldn't be any non-empty ones based on isToolBlock)
9122
- }
8733
+ if (!markerFound) {
8734
+ if (trimmedLine.startsWith('# GitSense Chat Tool')) {
8735
+ markerFound = true; // Skip the marker line itself
8736
+ }
8737
+ continue; // Skip lines before the marker (shouldn't be any non-empty ones based on isToolBlock)
8738
+ }
9123
8739
 
9124
- // After the marker, skip empty lines and comment lines
9125
- if (trimmedLine.length === 0 || /^\s*#/.test(line)) {
9126
- continue;
9127
- }
8740
+ // After the marker, skip empty lines and comment lines
8741
+ if (trimmedLine.length === 0 || /^\s*#/.test(line)) {
8742
+ continue;
8743
+ }
9128
8744
 
9129
- // Keep lines that are part of the JSON
9130
- jsonLines.push(line);
9131
- }
8745
+ // Keep lines that are part of the JSON
8746
+ jsonLines.push(line);
8747
+ }
9132
8748
 
9133
- const jsonString = jsonLines.join('\n');
8749
+ const jsonString = jsonLines.join('\n');
9134
8750
 
9135
- if (!jsonString) {
9136
- // No JSON content found after stripping comments/marker
9137
- throw new Error("No JSON content found in the tool block after stripping marker and comments.");
9138
- }
8751
+ if (!jsonString) {
8752
+ // No JSON content found after stripping comments/marker
8753
+ throw new Error("No JSON content found in the tool block after stripping marker and comments.");
8754
+ }
9139
8755
 
9140
- try {
9141
- const parsed = JSON.parse(jsonString);
8756
+ try {
8757
+ const parsed = JSON.parse(jsonString);
9142
8758
 
9143
- // Basic validation of the parsed structure
9144
- // The properties tool and config are required. Tool cannot be null or undefined but
9145
- // config can't. The reason for requiring config to be declared is to reserve the
9146
- // property name.
9147
- if (typeof parsed !== 'object' || parsed === null) {
9148
- throw new Error("Parsed content is not a valid JSON object.");
9149
- }
9150
- if (typeof parsed.tool !== 'string' || !parsed.tool) {
9151
- throw new Error("Parsed JSON object is missing the required 'tool' string property.");
9152
- }
8759
+ // Basic validation of the parsed structure
8760
+ // The properties tool and config are required. Tool cannot be null or undefined but
8761
+ // config can't. The reason for requiring config to be declared is to reserve the
8762
+ // property name.
8763
+ if (typeof parsed !== 'object' || parsed === null) {
8764
+ throw new Error("Parsed content is not a valid JSON object.");
8765
+ }
8766
+ if (typeof parsed.tool !== 'string' || !parsed.tool) {
8767
+ throw new Error("Parsed JSON object is missing the required 'tool' string property.");
8768
+ }
9153
8769
 
9154
- if (typeof parsed.config === 'undefined') {
9155
- throw new Error("Parsed JSON object is missing the required 'config' property.");
9156
- }
8770
+ if (typeof parsed.config === 'undefined') {
8771
+ throw new Error("Parsed JSON object is missing the required 'config' property.");
8772
+ }
9157
8773
 
9158
- return parsed;
9159
- } catch (error) {
9160
- // Re-throw JSON parsing errors with more context
9161
- throw new Error(`Failed to parse tool block JSON: ${error.message}\nContent after stripping comments:\n${jsonString}`);
9162
- }
9163
- }
8774
+ return parsed;
8775
+ } catch (error) {
8776
+ // Re-throw JSON parsing errors with more context
8777
+ throw new Error(`Failed to parse tool block JSON: ${error.message}\nContent after stripping comments:\n${jsonString}`);
8778
+ }
8779
+ }
9164
8780
 
9165
- /**
9166
- * Formats tool data into a GitSense Chat Tool Block string.
9167
- *
9168
- * @param {object} toolData - The tool data object to format.
9169
- * @returns {string} The formatted GitSense Chat Tool Block string.
9170
- */
9171
- function formatToolBlock(toolData) {
9172
- return `# GitSense Chat Tool\n\n${JSON.stringify(toolData, null, 2)}`;
9173
- }
8781
+ /**
8782
+ * Formats tool data into a GitSense Chat Tool Block string.
8783
+ *
8784
+ * @param {object} toolData - The tool data object to format.
8785
+ * @returns {string} The formatted GitSense Chat Tool Block string.
8786
+ */
8787
+ function formatToolBlock(toolData) {
8788
+ return `# GitSense Chat Tool\n\n${JSON.stringify(toolData, null, 2)}`;
8789
+ }
9174
8790
 
9175
- /**
9176
- * Replaces a specific GitSense Chat Tool Block within a markdown string with updated tool data.
9177
- * This function leverages CodeBlockUtils for robust parsing and updating.
9178
- *
9179
- * @param {string} markdownContent - The original markdown string containing code blocks.
9180
- * @param {string} toolName - The 'tool' property value of the target GitSense Chat Tool Block to replace.
9181
- * @param {Object} newToolData - The new tool data object to insert into the block.
9182
- * @returns {string} The markdown content with the specified tool block updated.
9183
- * @throws {Error} If the target tool block is not found or if CodeBlockUtils encounters an error.
9184
- */
9185
- function replaceToolBlock(markdownContent, toolName, newToolData) {
9186
- if (typeof markdownContent !== 'string' || !toolName || !newToolData) {
9187
- throw new Error("Missing required parameters for replaceToolBlock.");
9188
- }
8791
+ /**
8792
+ * Replaces a specific GitSense Chat Tool Block within a markdown string with updated tool data.
8793
+ * This function leverages CodeBlockUtils for robust parsing and updating.
8794
+ *
8795
+ * @param {string} markdownContent - The original markdown string containing code blocks.
8796
+ * @param {string} toolName - The 'tool' property value of the target GitSense Chat Tool Block to replace.
8797
+ * @param {Object} newToolData - The new tool data object to insert into the block.
8798
+ * @returns {string} The markdown content with the specified tool block updated.
8799
+ * @throws {Error} If the target tool block is not found or if CodeBlockUtils encounters an error.
8800
+ */
8801
+ function replaceToolBlock(markdownContent, toolName, newToolData, processCodeBlocks, updateCodeBlockByIndex) {
8802
+ if (typeof markdownContent !== 'string' || !toolName || !newToolData) {
8803
+ throw new Error("Missing required parameters for replaceToolBlock.");
8804
+ }
9189
8805
 
9190
- // 1. Process the markdown content to find all code blocks
9191
- const { blocks, warnings } = processCodeBlocks(markdownContent, { silent: true });
8806
+ // We can't require them as this will create a circular dependency
8807
+ if (!processCodeBlocks || !updateCodeBlockByIndex) {
8808
+ throw new Error("Missing required dependencies processCodeBlocks and/or updateCodeBlockByIndex.");
8809
+ }
9192
8810
 
9193
- let targetBlockIndex = -1;
8811
+ // 1. Process the markdown content to find all code blocks
8812
+ const { blocks, warnings } = processCodeBlocks(markdownContent, { silent: true });
9194
8813
 
9195
- // 2. Iterate through the processed blocks to find the target GitSense Chat Tool Block
9196
- for (let i = 0; i < blocks.length; i++) {
9197
- const block = blocks[i];
9198
- if (block.type === 'gs-tool' && block.toolData && block.toolData.tool === toolName) {
9199
- targetBlockIndex = i;
9200
- break; // Found the first matching tool block
9201
- }
9202
- }
8814
+ let targetBlockIndex = -1;
9203
8815
 
9204
- if (targetBlockIndex === -1) {
9205
- console.warn(`replaceToolBlock: No GitSense Chat Tool Block with name "${toolName}" found to replace.`);
9206
- return markdownContent; // Return original content if no replacement occurred
9207
- }
8816
+ // 2. Iterate through the processed blocks to find the target GitSense Chat Tool Block
8817
+ for (let i = 0; i < blocks.length; i++) {
8818
+ const block = blocks[i];
8819
+ if (block.type === 'gs-tool' && block.toolData && block.toolData.tool === toolName) {
8820
+ targetBlockIndex = i;
8821
+ break; // Found the first matching tool block
8822
+ }
8823
+ }
9208
8824
 
9209
- // 3. Format the new tool data into the content that goes *inside* the fences
9210
- const newContentBetweenFences = formatToolBlock(newToolData);
8825
+ if (targetBlockIndex === -1) {
8826
+ console.warn(`replaceToolBlock: No GitSense Chat Tool Block with name "${toolName}" found to replace.`);
8827
+ return markdownContent; // Return original content if no replacement occurred
8828
+ }
9211
8829
 
9212
- // 4. Use CodeBlockUtils.updateCodeBlockByIndex to perform the replacement
9213
- // The language for GitSense Tool Blocks is always 'txt'
9214
- const updatedMarkdown = updateCodeBlockByIndex(
9215
- markdownContent,
9216
- targetBlockIndex,
9217
- newContentBetweenFences,
9218
- 'txt'
9219
- );
8830
+ // 3. Format the new tool data into the content that goes *inside* the fences
8831
+ const newContentBetweenFences = formatToolBlock(newToolData);
9220
8832
 
9221
- return updatedMarkdown;
9222
- }
8833
+ // 4. Use CodeBlockUtils.updateCodeBlockByIndex to perform the replacement
8834
+ // The language for GitSense Tool Blocks is always 'txt'
8835
+ const updatedMarkdown = updateCodeBlockByIndex(
8836
+ markdownContent,
8837
+ targetBlockIndex,
8838
+ newContentBetweenFences,
8839
+ 'txt'
8840
+ );
9223
8841
 
9224
- GSToolBlockUtils$2 = {
9225
- isToolBlock,
9226
- parseToolBlock,
9227
- formatToolBlock,
9228
- replaceToolBlock,
9229
- };
9230
- return GSToolBlockUtils$2;
8842
+ return updatedMarkdown;
9231
8843
  }
9232
8844
 
8845
+ var GSToolBlockUtils$3 = {
8846
+ isToolBlock: isToolBlock$1,
8847
+ parseToolBlock: parseToolBlock$1,
8848
+ formatToolBlock,
8849
+ replaceToolBlock,
8850
+ };
8851
+
9233
8852
  /*
9234
8853
  * Component: CodeBlockUtils Continuation Utilities
9235
8854
  * Block-UUID: 6fdf5c7d-4def-42a1-bc88-0312f6002cfc
@@ -9249,7 +8868,7 @@ function requireGSToolBlockUtils () {
9249
8868
  * @param {Object} header - The parsed header object from the incomplete block (if available).
9250
8869
  * @returns {Object} Continuation information { lastLines: Array<string>, blockUUID: string|null, partNumber: number, language: string, metadata: Object }
9251
8870
  */
9252
- function extractContinuationInfo$2(content, partNumber, language, header = {}) {
8871
+ function extractContinuationInfo$3(content, partNumber, language, header = {}) {
9253
8872
  // Extract Block-UUID directly from the parsed header if available and valid
9254
8873
  let blockUUID = (header && header['Block-UUID'] && header['Block-UUID'] !== 'INVALID UUID')
9255
8874
  ? header['Block-UUID']
@@ -9417,7 +9036,7 @@ Contribute code starting from the line immediately following the repeated code b
9417
9036
 
9418
9037
 
9419
9038
  var continuationUtils = {
9420
- extractContinuationInfo: extractContinuationInfo$2,
9039
+ extractContinuationInfo: extractContinuationInfo$3,
9421
9040
  generateContinuationPrompt: generateContinuationPrompt$2
9422
9041
  };
9423
9042
 
@@ -9440,7 +9059,7 @@ var continuationUtils = {
9440
9059
  * @param {string} jsonString The string potentially containing JSON and comments.
9441
9060
  * @returns {string[]} An array of detected comment strings (including their markers).
9442
9061
  */
9443
- function detectJsonComments$1(jsonString) {
9062
+ function detectJsonComments$2(jsonString) {
9444
9063
  const comments = [];
9445
9064
  let inString = false;
9446
9065
  let inBlockComment = false;
@@ -9519,7 +9138,7 @@ function detectJsonComments$1(jsonString) {
9519
9138
  }
9520
9139
 
9521
9140
  var JsonUtils$2 = {
9522
- detectJsonComments: detectJsonComments$1
9141
+ detectJsonComments: detectJsonComments$2
9523
9142
  };
9524
9143
 
9525
9144
  /**
@@ -9533,558 +9152,550 @@ var JsonUtils$2 = {
9533
9152
  * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Pro (v1.2.0), Gemini 2.5 Flash Thinking (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0)
9534
9153
  */
9535
9154
 
9536
- var blockProcessor;
9537
- var hasRequiredBlockProcessor;
9538
-
9539
- function requireBlockProcessor () {
9540
- if (hasRequiredBlockProcessor) return blockProcessor;
9541
- hasRequiredBlockProcessor = 1;
9542
- const { findAllCodeFences, matchFencesAndExtractBlocks } = blockExtractor;
9543
- const { parseHeader } = headerUtils;
9544
- const { validateUUID, generateUUID } = uuidUtils;
9545
- const AnalysisBlockUtils = AnalysisBlockUtils$2;
9546
- const PatchUtils = PatchUtils$1;
9547
- const GSToolBlockUtils = requireGSToolBlockUtils();
9548
- const { extractContinuationInfo } = continuationUtils;
9549
- const { removeLineNumbers } = lineNumberFormatter;
9550
- const { detectJsonComments } = JsonUtils$2;
9551
-
9552
- /**
9553
- * Processes a single block's content (internal helper)
9554
- * @param {string} content - The block content
9555
- * @param {string} language - The language of the block
9556
- * @param {number} position - The position in the original text
9557
- * @param {boolean} incomplete - Whether the block is incomplete
9558
- * @param {Object} options - Processing options (e.g., silent, validatePatches)
9559
- * @returns {Object} Processed block object
9560
- */
9561
- function processBlockContent(content, language, position, incomplete, options = { silent: true, validatePatches: false }) {
9562
- const { silent, validatePatches } = options;
9563
- let warnings = []; // Collect warnings specific to this block
9564
- let header = {};
9565
- let headerText = ''; // Raw header text including comments
9566
- let headerParseError = null;
9567
- let headerDelimiterType = null; // 'triple' or 'double'
9568
- let codeText = content; // Default to all content being code
9569
-
9570
- // Check if this is a GitSense Tool Block *first*
9571
- if (GSToolBlockUtils.isToolBlock(content)) {
9572
- let ignoreDueToComments = false;
9573
- let toolData = null;
9574
- let toolParseError = null;
9575
- try {
9576
- toolData = GSToolBlockUtils.parseToolBlock(content);
9577
- } catch (error) {
9578
- // When chatting about the tool block, the LLM may add
9579
- // add comments in it so let's test for this
9580
- const comments = detectJsonComments(content);
9581
-
9582
- if (comments.length) {
9583
- ignoreDueToComments = true;
9584
- } else {
9585
- toolParseError = error.message;
9586
- warnings.push({
9587
- position: position,
9588
- type: 'gs_tool_block_parse_error',
9589
- message: `Invalid GitSense tool block: ${error.message}`,
9590
- content: content
9591
- });
9592
- }
9593
- }
9155
+ const { findAllCodeFences: findAllCodeFences$3, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$3 } = blockExtractor;
9156
+ const { parseHeader: parseHeader$2 } = headerUtils;
9157
+ const { validateUUID: validateUUID$2, generateUUID: generateUUID$2 } = uuidUtils;
9158
+ const AnalysisBlockUtils$2 = AnalysisBlockUtils$3;
9159
+ const PatchUtils$1 = PatchUtils$2;
9160
+ const GSToolBlockUtils$2 = GSToolBlockUtils$3;
9161
+ const { extractContinuationInfo: extractContinuationInfo$2 } = continuationUtils;
9162
+ const { removeLineNumbers: removeLineNumbers$2 } = lineNumberFormatter;
9163
+ const { detectJsonComments: detectJsonComments$1 } = JsonUtils$2;
9164
+
9165
+ /**
9166
+ * Processes a single block's content (internal helper)
9167
+ * @param {string} content - The block content
9168
+ * @param {string} language - The language of the block
9169
+ * @param {number} position - The position in the original text
9170
+ * @param {boolean} incomplete - Whether the block is incomplete
9171
+ * @param {Object} options - Processing options (e.g., silent, validatePatches)
9172
+ * @returns {Object} Processed block object
9173
+ */
9174
+ function processBlockContent(content, language, position, incomplete, options = { silent: true, validatePatches: false }) {
9175
+ const { silent, validatePatches } = options;
9176
+ let warnings = []; // Collect warnings specific to this block
9177
+ let header = {};
9178
+ let headerText = ''; // Raw header text including comments
9179
+ let headerParseError = null;
9180
+ let headerDelimiterType = null; // 'triple' or 'double'
9181
+ let codeText = content; // Default to all content being code
9182
+
9183
+ // Check if this is a GitSense Tool Block *first*
9184
+ if (GSToolBlockUtils$2.isToolBlock(content)) {
9185
+ let ignoreDueToComments = false;
9186
+ let toolData = null;
9187
+ let toolParseError = null;
9188
+ try {
9189
+ toolData = GSToolBlockUtils$2.parseToolBlock(content);
9190
+ } catch (error) {
9191
+ // When chatting about the tool block, the LLM may add
9192
+ // add comments in it so let's test for this
9193
+ const comments = detectJsonComments$1(content);
9594
9194
 
9595
- if (ignoreDueToComments) ; else {
9596
- return {
9597
- type: 'gs-tool',
9598
- language: language,
9599
- content: content,
9600
- position: position,
9601
- incomplete: incomplete,
9602
- toolData: toolData,
9603
- toolParseError: toolParseError,
9604
- warnings: warnings,
9605
- };
9606
- }
9607
- }
9195
+ if (comments.length) {
9196
+ ignoreDueToComments = true;
9197
+ } else {
9198
+ toolParseError = error.message;
9199
+ warnings.push({
9200
+ position: position,
9201
+ type: 'gs_tool_block_parse_error',
9202
+ message: `Invalid GitSense tool block: ${error.message}`,
9203
+ content: content
9204
+ });
9205
+ }
9206
+ }
9608
9207
 
9609
- // Check if this is an analysis block *next*
9610
- if (AnalysisBlockUtils.isAnalysisBlock(content)) {
9611
- const analysisType = AnalysisBlockUtils.getAnalysisBlockType(content);
9612
- const analysisMetadata = AnalysisBlockUtils.parseOverviewMetadata(content);
9613
-
9614
- // Validate the metadata if it was successfully parsed
9615
- let validationResult = { isValid: false, errors: ['Failed to parse analysis metadata'] };
9616
- if (analysisMetadata) {
9617
- validationResult = AnalysisBlockUtils.validateAnalysisMetadata(analysisMetadata);
9618
-
9619
- if (!validationResult.isValid) {
9620
- warnings.push({
9621
- position: position,
9622
- type: 'analysis_metadata_error',
9623
- message: `Invalid analysis metadata: ${validationResult.errors.join(', ')}`,
9624
- content: content,
9625
- });
9626
- }
9627
- }
9208
+ if (ignoreDueToComments) ; else {
9209
+ return {
9210
+ type: 'gs-tool',
9211
+ language: language,
9212
+ content: content,
9213
+ position: position,
9214
+ incomplete: incomplete,
9215
+ toolData: toolData,
9216
+ toolParseError: toolParseError,
9217
+ warnings: warnings,
9218
+ };
9219
+ }
9220
+ }
9628
9221
 
9629
- return {
9630
- type: analysisType,
9631
- language: language,
9632
- content: content,
9633
- position: position,
9634
- incomplete: incomplete,
9635
- analysisMetadata: analysisMetadata,
9636
- analysisValidation: validationResult,
9637
- warnings: warnings,
9638
- };
9639
- }
9222
+ // Check if this is an analysis block *next*
9223
+ if (AnalysisBlockUtils$2.isAnalysisBlock(content)) {
9224
+ const analysisType = AnalysisBlockUtils$2.getAnalysisBlockType(content);
9225
+ const analysisMetadata = AnalysisBlockUtils$2.parseOverviewMetadata(content);
9640
9226
 
9641
- // Check if this is a gitsense-search-flow block *next*
9642
- if (language === 'gitsense-search-flow') {
9643
- // Future parsing logic for gitsense-search-flow content would go here.
9644
- // For now, we just identify the type and keep the raw content.
9645
- return {
9646
- type: 'gitsense-search-flow',
9647
- language: language,
9648
- content: content, // Keep raw content for now
9649
- position: position,
9650
- incomplete: incomplete,
9651
- // Add parsedData: {} or similar if parsing is implemented later
9652
- warnings: warnings, // Include any warnings collected so far
9653
- };
9654
- }
9227
+ // Validate the metadata if it was successfully parsed
9228
+ let validationResult = { isValid: false, errors: ['Failed to parse analysis metadata'] };
9229
+ if (analysisMetadata) {
9230
+ validationResult = AnalysisBlockUtils$2.validateAnalysisMetadata(analysisMetadata);
9655
9231
 
9656
- // Then check if this is a patch block
9657
- if (PatchUtils.isPatchBlock(content)) {
9658
- const patchFormat = PatchUtils.determinePatchFormat(content);
9659
- const metadata = PatchUtils.extractPatchMetadata(content); // Extract metadata regardless of validation
9660
- const patchContent = PatchUtils.extractPatchContent(content); // Extract raw patch content
9661
-
9662
- let patchValidationResult = { valid: true, errors: [], patches: null }; // Default valid state
9663
-
9664
- // Validate metadata (always useful)
9665
- const errors = PatchUtils.validatePatchMetadata(metadata);
9666
- if (errors.length) {
9667
- warnings.push({
9668
- position: position,
9669
- type: 'patch_metadata_error',
9670
- message: `Invalid patch metadata: ${errors.join(', ')}`,
9671
- content: content,
9672
- });
9673
- // Decide if invalid metadata makes the whole block invalid or just adds a warning
9674
- // For now, just warn, but return the extracted (potentially invalid) metadata.
9675
- }
9232
+ if (!validationResult.isValid) {
9233
+ warnings.push({
9234
+ position: position,
9235
+ type: 'analysis_metadata_error',
9236
+ message: `Invalid analysis metadata: ${validationResult.errors.join(', ')}`,
9237
+ content: content,
9238
+ });
9239
+ }
9240
+ }
9676
9241
 
9677
- // Optionally validate context patch structure if requested
9678
- if (patchFormat === 'context' && validatePatches) {
9679
- try {
9680
- const patches = PatchUtils.extractContextPatches(content);
9681
- if (!patches || patches.length === 0) {
9682
- patchValidationResult = { valid: false, errors: ['No valid context patch content found.'], patches: null };
9683
- warnings.push({
9684
- position: position,
9685
- type: 'patch_content_error',
9686
- message: 'No valid context patch content found.',
9687
- content: content,
9688
- });
9689
- } else {
9690
- // Basic validation passed (structure was parsable)
9691
- patchValidationResult = { valid: true, errors: [], patches: patches };
9692
- }
9693
- } catch (error) {
9694
- patchValidationResult = { valid: false, errors: [error.message], patches: null };
9695
- warnings.push({
9696
- position: position,
9697
- type: 'patch_parse_error',
9698
- message: `Error parsing context patch: ${error.message}`,
9699
- content: content,
9700
- });
9701
- }
9702
- }
9242
+ return {
9243
+ type: analysisType,
9244
+ language: language,
9245
+ content: content,
9246
+ position: position,
9247
+ incomplete: incomplete,
9248
+ analysisMetadata: analysisMetadata,
9249
+ analysisValidation: validationResult,
9250
+ warnings: warnings,
9251
+ };
9252
+ }
9703
9253
 
9704
- return {
9705
- type: 'patch',
9706
- language: language === 'diff' ? 'diff' : language, // Use 'diff' if specified, else keep original
9707
- content: content, // Full original content within fences
9708
- position: position,
9709
- incomplete: incomplete,
9710
- metadata: metadata,
9711
- patch: patchContent, // Raw patch content after metadata
9712
- patchFormat: patchFormat,
9713
- patchValidation: validatePatches ? patchValidationResult : undefined, // Include validation only if requested
9714
- warnings: warnings,
9715
- };
9716
- } else {
9717
- // For non-patch blocks, remove display line numbers before processing content
9718
- content = removeLineNumbers(content); // This is the "cleaned" content
9719
- }
9254
+ // Check if this is a gitsense-search-flow block *next*
9255
+ if (language === 'gitsense-search-flow') {
9256
+ // Future parsing logic for gitsense-search-flow content would go here.
9257
+ // For now, we just identify the type and keep the raw content.
9258
+ return {
9259
+ type: 'gitsense-search-flow',
9260
+ language: language,
9261
+ content: content, // Keep raw content for now
9262
+ position: position,
9263
+ incomplete: incomplete,
9264
+ // Add parsedData: {} or similar if parsing is implemented later
9265
+ warnings: warnings, // Include any warnings collected so far
9266
+ };
9267
+ }
9720
9268
 
9721
- // --- Process as a regular code block ---
9722
- // Attempt 1: Look for triple newline separator (our standard)
9723
- const tripleNewlineSeparator = '\n\n\n';
9724
- const tripleNewlineIndex = content.indexOf(tripleNewlineSeparator);
9725
-
9726
- if (tripleNewlineIndex !== -1) {
9727
- const potentialHeaderText = content.substring(0, tripleNewlineIndex); // No trim here
9728
-
9729
- try {
9730
- header = parseHeader(potentialHeaderText, language);
9731
- headerText = potentialHeaderText;
9732
- codeText = content.substring(tripleNewlineIndex + tripleNewlineSeparator.length);
9733
- headerDelimiterType = 'triple';
9734
- } catch (error) {
9735
- // If parsing fails, it's not a valid header, log warning and try double newline
9736
- headerParseError = error.message;
9737
- warnings.push({
9738
- position: position,
9739
- type: 'header_parse_error',
9740
- message: `Invalid header (triple newline attempt): ${error.message}. Attempting double newline.`,
9741
- content: potentialHeaderText // Show the problematic header text
9742
- });
9743
- // Do not set header, headerText, codeText, or headerDelimiterType yet.
9744
- // Fall through to the next attempt.
9745
- }
9746
- }
9269
+ // Then check if this is a patch block
9270
+ if (PatchUtils$1.isPatchBlock(content)) {
9271
+ const patchFormat = PatchUtils$1.determinePatchFormat(content);
9272
+ const metadata = PatchUtils$1.extractPatchMetadata(content); // Extract metadata regardless of validation
9273
+ const patchContent = PatchUtils$1.extractPatchContent(content); // Extract raw patch content
9747
9274
 
9748
- // Attempt 2: Look for double newline separator (fallback)
9749
- // Only if a valid header wasn't found in the triple newline attempt
9750
- if (!headerDelimiterType) {
9751
- const doubleNewlineSeparator = '\n\n';
9752
- const doubleNewlineIndex = content.indexOf(doubleNewlineSeparator);
9753
-
9754
- if (doubleNewlineIndex !== -1) {
9755
- const potentialHeaderText = content.substring(0, doubleNewlineIndex); // No trim here
9756
-
9757
- try {
9758
- header = parseHeader(potentialHeaderText, language);
9759
- headerText = potentialHeaderText;
9760
- codeText = content.substring(doubleNewlineIndex + doubleNewlineSeparator.length);
9761
- headerDelimiterType = 'double';
9762
- } catch (error) {
9763
- // If parsing fails, it's not a valid header, log warning and default to no header
9764
- headerParseError = error.message;
9765
- warnings.push({
9766
- position: position,
9767
- type: 'header_parse_error',
9768
- message: `Invalid header (double newline attempt): ${error.message}. Treating block as code only.`,
9769
- content: potentialHeaderText // Show the problematic header text
9770
- });
9771
- // Fall through to default case (no header)
9772
- }
9773
- }
9774
- }
9275
+ let patchValidationResult = { valid: true, errors: [], patches: null }; // Default valid state
9775
9276
 
9776
- // Default: If no valid header was found after both attempts
9777
- if (!headerDelimiterType && !incomplete) { // Only warn about missing header if the block is complete
9778
- warnings.push({
9779
- position: position,
9780
- type: 'missing_header',
9781
- message: `No distinct header found or parsed as valid. Treating block as code only.`,
9782
- content: content.substring(0, 100) + '...' // Show beginning of content
9783
- });
9784
- }
9277
+ // Validate metadata (always useful)
9278
+ const errors = PatchUtils$1.validatePatchMetadata(metadata);
9279
+ if (errors.length) {
9280
+ warnings.push({
9281
+ position: position,
9282
+ type: 'patch_metadata_error',
9283
+ message: `Invalid patch metadata: ${errors.join(', ')}`,
9284
+ content: content,
9285
+ });
9286
+ // Decide if invalid metadata makes the whole block invalid or just adds a warning
9287
+ // For now, just warn, but return the extracted (potentially invalid) metadata.
9288
+ }
9785
9289
 
9786
- return {
9787
- type: 'code',
9788
- language: language,
9789
- header: header,
9790
- headerText: headerText.trim(), // Include the raw header text if successfully parsed
9791
- content: codeText, // The code part after the header (or full content if no header)
9792
- position: position, // Position of the opening fence
9793
- headerDelimiterType: headerDelimiterType, // 'triple', 'double', or null
9794
- incomplete: incomplete,
9795
- warnings: warnings,
9796
- headerParseError: headerParseError // Include error message if parsing failed
9797
- };
9798
- }
9290
+ // Optionally validate context patch structure if requested
9291
+ if (patchFormat === 'context' && validatePatches) {
9292
+ try {
9293
+ const patches = PatchUtils$1.extractContextPatches(content);
9294
+ if (!patches || patches.length === 0) {
9295
+ patchValidationResult = { valid: false, errors: ['No valid context patch content found.'], patches: null };
9296
+ warnings.push({
9297
+ position: position,
9298
+ type: 'patch_content_error',
9299
+ message: 'No valid context patch content found.',
9300
+ content: content,
9301
+ });
9302
+ } else {
9303
+ // Basic validation passed (structure was parsable)
9304
+ patchValidationResult = { valid: true, errors: [], patches: patches };
9305
+ }
9306
+ } catch (error) {
9307
+ patchValidationResult = { valid: false, errors: [error.message], patches: null };
9308
+ warnings.push({
9309
+ position: position,
9310
+ type: 'patch_parse_error',
9311
+ message: `Error parsing context patch: ${error.message}`,
9312
+ content: content,
9313
+ });
9314
+ }
9315
+ }
9799
9316
 
9317
+ return {
9318
+ type: 'patch',
9319
+ language: language === 'diff' ? 'diff' : language, // Use 'diff' if specified, else keep original
9320
+ content: content, // Full original content within fences
9321
+ position: position,
9322
+ incomplete: incomplete,
9323
+ metadata: metadata,
9324
+ patch: patchContent, // Raw patch content after metadata
9325
+ patchFormat: patchFormat,
9326
+ patchValidation: validatePatches ? patchValidationResult : undefined, // Include validation only if requested
9327
+ warnings: warnings,
9328
+ };
9329
+ } else {
9330
+ // For non-patch blocks, remove display line numbers before processing content
9331
+ content = removeLineNumbers$2(content); // This is the "cleaned" content
9332
+ }
9800
9333
 
9801
- /**
9802
- * Processes the content of complete and incomplete blocks (internal helper)
9803
- * @param {string} text - The input text
9804
- * @param {Array} completeBlocks - Array of complete block objects from extractor
9805
- * @param {Array} incompleteBlocks - Array of incomplete block objects from extractor
9806
- * @param {Object} options - Processing options
9807
- * @returns {Array} Array of processed block objects
9808
- */
9809
- function processBlockContents(text, completeBlocks, incompleteBlocks, options) {
9810
- const processedBlocks = [];
9811
- const allWarnings = []; // Collect warnings from all blocks
9812
-
9813
- // Process complete blocks
9814
- for (const block of completeBlocks) {
9815
- try {
9816
- const startPos = block.opening.position + block.opening.length;
9817
- const endPos = block.closing.position;
9818
- // Get content, including the newlines immediately after opening and before closing fence
9819
- const contentWithNewlines = text.substring(startPos, endPos);
9820
- const content = contentWithNewlines; //.replace(/^\s*\n|\n\s*$/g, '');
9821
-
9822
- const language = block.opening.language;
9823
-
9824
- // Process block content
9825
- const processedBlock = processBlockContent(content, language, block.opening.position, false, options);
9826
- processedBlocks.push(processedBlock);
9827
- if (processedBlock.warnings) {
9828
- allWarnings.push(...processedBlock.warnings);
9829
- }
9830
- } catch (error) {
9831
- // Catch errors during the processing of a single block
9832
- allWarnings.push({
9833
- position: block.opening?.position || -1,
9834
- type: 'block_processing_error',
9835
- message: `Error processing complete block: ${error.message}`,
9836
- content: text.substring(block.opening?.position, block.closing?.position + block.closing?.length) || "Error retrieving block content"
9837
- });
9838
- }
9839
- }
9334
+ // --- Process as a regular code block ---
9335
+ // Attempt 1: Look for triple newline separator (our standard)
9336
+ const tripleNewlineSeparator = '\n\n\n';
9337
+ const tripleNewlineIndex = content.indexOf(tripleNewlineSeparator);
9840
9338
 
9841
- // Process incomplete blocks
9842
- for (const block of incompleteBlocks) {
9843
- try {
9844
- const startPos = block.opening.position + block.opening.length;
9845
- // Get content from opening fence to end of text
9846
- const contentWithNewline = text.substring(startPos);
9847
- // Trim only leading whitespace line
9848
- const content = contentWithNewline.replace(/^\s*\n/, '');
9849
-
9850
- const language = block.opening.language;
9851
-
9852
- // Process block content - it's expected to be incomplete
9853
- const processedBlock = processBlockContent(content, language, block.opening.position, true, options);
9854
-
9855
- // Extract continuation info for incomplete blocks
9856
- // Requires extractContinuationInfo from continuationUtils
9857
- try {
9858
- // Pass the *processed* header info to continuation utils
9859
- let { 'Continuation-Part': partNumber } = processedBlock?.header || {};
9860
- partNumber = partNumber ? parseInt(partNumber) + 1 : 2; // Default to part 2 if not specified
9861
- processedBlock.continuationInfo = extractContinuationInfo(processedBlock.content, partNumber, language, processedBlock.header);
9862
- } catch (continuationError) {
9863
- allWarnings.push({
9864
- position: block.opening?.position || -1,
9865
- type: 'continuation_info_error',
9866
- message: `Error extracting continuation info: ${continuationError.message}`,
9867
- content: content
9868
- });
9869
- }
9870
-
9871
-
9872
- processedBlocks.push(processedBlock);
9873
- if (processedBlock.warnings) {
9874
- allWarnings.push(...processedBlock.warnings);
9875
- }
9876
- } catch (error) {
9877
- // Catch errors during the processing of a single incomplete block
9878
- allWarnings.push({
9879
- position: block.opening?.position || -1,
9880
- type: 'incomplete_block_processing_error',
9881
- message: `Error processing incomplete block: ${error.message}`,
9882
- content: text.substring(block.opening?.position) || "Error retrieving block content"
9883
- });
9884
- }
9885
- }
9339
+ if (tripleNewlineIndex !== -1) {
9340
+ const potentialHeaderText = content.substring(0, tripleNewlineIndex); // No trim here
9886
9341
 
9887
- // Return processed blocks and collected warnings
9888
- // Note: The caller (processCodeBlocks) will handle adding these warnings to its own return object.
9889
- return { processedBlocks, allWarnings };
9890
- }
9342
+ try {
9343
+ header = parseHeader$2(potentialHeaderText, language);
9344
+ headerText = potentialHeaderText;
9345
+ codeText = content.substring(tripleNewlineIndex + tripleNewlineSeparator.length);
9346
+ headerDelimiterType = 'triple';
9347
+ } catch (error) {
9348
+ // If parsing fails, it's not a valid header, log warning and try double newline
9349
+ headerParseError = error.message;
9350
+ warnings.push({
9351
+ position: position,
9352
+ type: 'header_parse_error',
9353
+ message: `Invalid header (triple newline attempt): ${error.message}. Attempting double newline.`,
9354
+ content: potentialHeaderText // Show the problematic header text
9355
+ });
9356
+ // Do not set header, headerText, codeText, or headerDelimiterType yet.
9357
+ // Fall through to the next attempt.
9358
+ }
9359
+ }
9891
9360
 
9361
+ // Attempt 2: Look for double newline separator (fallback)
9362
+ // Only if a valid header wasn't found in the triple newline attempt
9363
+ if (!headerDelimiterType) {
9364
+ const doubleNewlineSeparator = '\n\n';
9365
+ const doubleNewlineIndex = content.indexOf(doubleNewlineSeparator);
9892
9366
 
9893
- /**
9894
- * Core function to process code blocks with shared logic
9895
- * @param {string} text - The input text containing code blocks
9896
- * @param {Object} options - Processing options (e.g., silent, validatePatches)
9897
- * @returns {Object} { blocks: Array, warnings: Array, hasIncompleteBlocks: boolean, lastIncompleteBlock: Object|null }
9898
- */
9899
- function processCodeBlocks(text, options = { silent: false, validatePatches: false }) {
9900
- if (typeof text !== "string") { // Allow empty strings
9901
- console.warn("Warning: Input must be a string.");
9902
- return {
9903
- blocks: [],
9904
- warnings: [{ type: 'invalid_input', message: 'Input must be a string.' }],
9905
- hasIncompleteBlocks: false,
9906
- lastIncompleteBlock: null }
9907
- ;
9908
- }
9367
+ if (doubleNewlineIndex !== -1) {
9368
+ const potentialHeaderText = content.substring(0, doubleNewlineIndex); // No trim here
9909
9369
 
9910
- if (text.trim() === "") {
9911
- return { blocks: [], warnings: [], hasIncompleteBlocks: false, lastIncompleteBlock: null };
9912
- }
9370
+ try {
9371
+ header = parseHeader$2(potentialHeaderText, language);
9372
+ headerText = potentialHeaderText;
9373
+ codeText = content.substring(doubleNewlineIndex + doubleNewlineSeparator.length);
9374
+ headerDelimiterType = 'double';
9375
+ } catch (error) {
9376
+ // If parsing fails, it's not a valid header, log warning and default to no header
9377
+ headerParseError = error.message;
9378
+ warnings.push({
9379
+ position: position,
9380
+ type: 'header_parse_error',
9381
+ message: `Invalid header (double newline attempt): ${error.message}. Treating block as code only.`,
9382
+ content: potentialHeaderText // Show the problematic header text
9383
+ });
9384
+ // Fall through to default case (no header)
9385
+ }
9386
+ }
9387
+ }
9913
9388
 
9914
- // Step 1: Find all fence positions
9915
- const { openingPositions, closingPositions } = findAllCodeFences(text);
9916
-
9917
- // Step 2: Match fences to get potential block boundaries
9918
- const { completeBlocks, incompleteBlocks, warnings: extractorWarnings } = matchFencesAndExtractBlocks(
9919
- text, openingPositions, closingPositions
9920
- );
9921
-
9922
- // Step 3: Process the content of these potential blocks
9923
- const { processedBlocks, allWarnings: processorWarnings } = processBlockContents(
9924
- text, completeBlocks, incompleteBlocks, options
9925
- );
9926
-
9927
- // Combine warnings from extractor and processor
9928
- const allWarnings = [...extractorWarnings, ...processorWarnings];
9929
-
9930
- // Log warnings if not silent
9931
- if (!options.silent && allWarnings.length > 0) {
9932
- console.warn('\nCode Block Processing Warnings:');
9933
- allWarnings.forEach((warning, index) => {
9934
- console.warn(`\nWarning ${index + 1}:`);
9935
- console.warn(`Type: ${warning.type}`);
9936
- console.warn(`Message: ${warning.message}`);
9937
- console.warn(`Position: ${warning.position}`);
9938
- if (warning.content) {
9939
- // Limit logged content length
9940
- const maxLogLength = 200;
9941
- const loggedContent = warning.content.length > maxLogLength
9942
- ? warning.content.substring(0, maxLogLength) + '...'
9943
- : warning.content;
9944
- console.warn(`Content Hint: ${loggedContent}`);
9945
- }
9946
- });
9947
- }
9389
+ // Default: If no valid header was found after both attempts
9390
+ if (!headerDelimiterType && !incomplete) { // Only warn about missing header if the block is complete
9391
+ warnings.push({
9392
+ position: position,
9393
+ type: 'missing_header',
9394
+ message: `No distinct header found or parsed as valid. Treating block as code only.`,
9395
+ content: content.substring(0, 100) + '...' // Show beginning of content
9396
+ });
9397
+ }
9948
9398
 
9949
- const hasIncompleteBlocks = incompleteBlocks.length > 0;
9950
- const lastIncompleteBlock = hasIncompleteBlocks
9951
- ? processedBlocks.find(block => block.incomplete) // Find the corresponding processed block
9952
- : null;
9953
-
9954
- return {
9955
- blocks: processedBlocks,
9956
- warnings: allWarnings,
9957
- hasIncompleteBlocks: hasIncompleteBlocks,
9958
- lastIncompleteBlock: lastIncompleteBlock
9959
- };
9960
- }
9399
+ return {
9400
+ type: 'code',
9401
+ language: language,
9402
+ header: header,
9403
+ headerText: headerText.trim(), // Include the raw header text if successfully parsed
9404
+ content: codeText, // The code part after the header (or full content if no header)
9405
+ position: position, // Position of the opening fence
9406
+ headerDelimiterType: headerDelimiterType, // 'triple', 'double', or null
9407
+ incomplete: incomplete,
9408
+ warnings: warnings,
9409
+ headerParseError: headerParseError // Include error message if parsing failed
9410
+ };
9411
+ }
9961
9412
 
9962
- /**
9963
- * Public API function - maintains backward compatibility for simple extraction.
9964
- * Use processCodeBlocks for more detailed results (warnings, incomplete status).
9965
- * @param {string} text - The input text containing code blocks
9966
- * @param {Object} options - Options for extraction (e.g., { silent: true })
9967
- * @returns {Object} - Object containing extracted blocks and warnings { blocks: Array, warnings: Array }
9968
- */
9969
- function extractCodeBlocks(text, options = { silent: false, validatePatches: false, debug: false }) {
9970
- const { blocks, warnings } = processCodeBlocks(text, options);
9971
- return { blocks, warnings };
9972
- }
9973
9413
 
9414
+ /**
9415
+ * Processes the content of complete and incomplete blocks (internal helper)
9416
+ * @param {string} text - The input text
9417
+ * @param {Array} completeBlocks - Array of complete block objects from extractor
9418
+ * @param {Array} incompleteBlocks - Array of incomplete block objects from extractor
9419
+ * @param {Object} options - Processing options
9420
+ * @returns {Array} Array of processed block objects
9421
+ */
9422
+ function processBlockContents(text, completeBlocks, incompleteBlocks, options) {
9423
+ const processedBlocks = [];
9424
+ const allWarnings = []; // Collect warnings from all blocks
9974
9425
 
9975
- /**
9976
- * Fixes invalid UUIDs in code blocks within text
9977
- * @param {string} text - The input text containing code blocks
9978
- * @returns {Object} - Object containing fixed text and whether changes were made { text: string, modified: boolean }
9979
- */
9980
- function fixTextCodeBlocks(text) {
9981
- if (typeof text !== "string" || text.trim() === "") {
9982
- return {
9983
- text: text,
9984
- modified: false
9985
- };
9986
- }
9426
+ // Process complete blocks
9427
+ for (const block of completeBlocks) {
9428
+ try {
9429
+ const startPos = block.opening.position + block.opening.length;
9430
+ const endPos = block.closing.position;
9431
+ // Get content, including the newlines immediately after opening and before closing fence
9432
+ const contentWithNewlines = text.substring(startPos, endPos);
9433
+ const content = contentWithNewlines; //.replace(/^\s*\n|\n\s*$/g, '');
9434
+
9435
+ const language = block.opening.language;
9436
+
9437
+ // Process block content
9438
+ const processedBlock = processBlockContent(content, language, block.opening.position, false, options);
9439
+ processedBlocks.push(processedBlock);
9440
+ if (processedBlock.warnings) {
9441
+ allWarnings.push(...processedBlock.warnings);
9442
+ }
9443
+ } catch (error) {
9444
+ // Catch errors during the processing of a single block
9445
+ allWarnings.push({
9446
+ position: block.opening?.position || -1,
9447
+ type: 'block_processing_error',
9448
+ message: `Error processing complete block: ${error.message}`,
9449
+ content: text.substring(block.opening?.position, block.closing?.position + block.closing?.length) || "Error retrieving block content"
9450
+ });
9451
+ }
9452
+ }
9987
9453
 
9988
- let modified = false;
9989
- let fixedText = text;
9990
-
9991
- // Regex to match code blocks with their language
9992
- const codeBlockRegex = /```([a-zA-Z-]*)\n([\s\S]*?)\n```/g;
9993
-
9994
- // Store all matches to process in reverse
9995
- const matches = Array.from(text.matchAll(codeBlockRegex));
9996
-
9997
- // Process matches in reverse to maintain correct positions
9998
- for (let i = matches.length - 1; i >= 0; i--) {
9999
- const match = matches[i];
10000
- const fullMatch = match[0];
10001
- const language = match[1];
10002
- const blockContent = match[2];
10003
-
10004
- // Check if this is a patch block or a gitsense-search-flow block (if they contain UUIDs)
10005
- if (PatchUtils.isPatchBlock(blockContent)) {
10006
- // Process patch block UUIDs
10007
- const lines = blockContent.split('\n');
10008
- let blockModified = false;
10009
-
10010
- const newLines = lines.map(line => {
10011
- // Check for UUID fields in patch metadata
10012
- if ((line.includes('# Source-Block-UUID:') || line.includes('# Target-Block-UUID:')) &&
10013
- !line.includes('{{GS-UUID}')) {
10014
-
10015
- const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
10016
-
10017
- // Validate UUID
10018
- const validation = validateUUID(valuePart);
10019
- if (validation["Block-UUID"] === "INVALID UUID") {
10020
- blockModified = true;
10021
- modified = true;
10022
- return `${fieldPart}: ${validation["Correct Block-UUID"]}`;
10023
- }
10024
- }
10025
- return line;
10026
- });
10027
-
10028
- // If this block was modified, replace it in the text
10029
- if (blockModified) {
10030
- const newBlock = `\`\`\`${language}\n${newLines.join('\n')}\n\`\`\``;
10031
- fixedText = fixedText.substring(0, match.index) +
10032
- newBlock +
10033
- fixedText.substring(match.index + fullMatch.length);
10034
- }
10035
- } else {
10036
- // Process regular code block or gitsense-search-flow block for UUIDs
10037
- // Split block content into lines to check for header/UUIDs
10038
- const lines = blockContent.split('\n');
10039
- let blockModified = false;
10040
-
10041
- // Process each line
10042
- const newLines = lines.map(line => {
10043
- // Check for UUID fields
10044
- if (line.includes(' Block-UUID: ') || line.includes(' Parent-UUID: ')) {
10045
- const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
10046
-
10047
- // Skip if N/A or contains unexpected characters
10048
- if (valuePart === 'N/A' || valuePart.match(/\(/)) {
10049
- return line;
10050
- }
10051
- // Validate UUID
10052
- const validation = validateUUID(valuePart);
10053
-
10054
- if (validation["Block-UUID"] === "INVALID UUID") {
10055
- blockModified = true;
10056
- modified = true;
10057
- return `${fieldPart}: ${validation["Correct Block-UUID"]}`;
10058
- }
10059
- }
10060
- return line;
10061
- });
10062
-
10063
- // If this block was modified, replace it in the text
10064
- if (blockModified) {
10065
- const newBlock = `\`\`\`${language}\n${newLines.join('\n')}\n\`\`\``;
10066
- fixedText = fixedText.substring(0, match.index) +
10067
- newBlock +
10068
- fixedText.substring(match.index + fullMatch.length);
10069
- }
10070
- }
10071
- }
9454
+ // Process incomplete blocks
9455
+ for (const block of incompleteBlocks) {
9456
+ try {
9457
+ const startPos = block.opening.position + block.opening.length;
9458
+ // Get content from opening fence to end of text
9459
+ const contentWithNewline = text.substring(startPos);
9460
+ // Trim only leading whitespace line
9461
+ const content = contentWithNewline.replace(/^\s*\n/, '');
10072
9462
 
10073
- return {
10074
- text: fixedText,
10075
- modified: modified
10076
- };
10077
- }
9463
+ const language = block.opening.language;
10078
9464
 
9465
+ // Process block content - it's expected to be incomplete
9466
+ const processedBlock = processBlockContent(content, language, block.opening.position, true, options);
10079
9467
 
10080
- blockProcessor = {
10081
- processCodeBlocks,
10082
- extractCodeBlocks,
10083
- fixTextCodeBlocks,
10084
- };
10085
- return blockProcessor;
9468
+ // Extract continuation info for incomplete blocks
9469
+ // Requires extractContinuationInfo from continuationUtils
9470
+ try {
9471
+ // Pass the *processed* header info to continuation utils
9472
+ let { 'Continuation-Part': partNumber } = processedBlock?.header || {};
9473
+ partNumber = partNumber ? parseInt(partNumber) + 1 : 2; // Default to part 2 if not specified
9474
+ processedBlock.continuationInfo = extractContinuationInfo$2(processedBlock.content, partNumber, language, processedBlock.header);
9475
+ } catch (continuationError) {
9476
+ allWarnings.push({
9477
+ position: block.opening?.position || -1,
9478
+ type: 'continuation_info_error',
9479
+ message: `Error extracting continuation info: ${continuationError.message}`,
9480
+ content: content
9481
+ });
9482
+ }
9483
+
9484
+
9485
+ processedBlocks.push(processedBlock);
9486
+ if (processedBlock.warnings) {
9487
+ allWarnings.push(...processedBlock.warnings);
9488
+ }
9489
+ } catch (error) {
9490
+ // Catch errors during the processing of a single incomplete block
9491
+ allWarnings.push({
9492
+ position: block.opening?.position || -1,
9493
+ type: 'incomplete_block_processing_error',
9494
+ message: `Error processing incomplete block: ${error.message}`,
9495
+ content: text.substring(block.opening?.position) || "Error retrieving block content"
9496
+ });
9497
+ }
9498
+ }
9499
+
9500
+ // Return processed blocks and collected warnings
9501
+ // Note: The caller (processCodeBlocks) will handle adding these warnings to its own return object.
9502
+ return { processedBlocks, allWarnings };
9503
+ }
9504
+
9505
+
9506
+ /**
9507
+ * Core function to process code blocks with shared logic
9508
+ * @param {string} text - The input text containing code blocks
9509
+ * @param {Object} options - Processing options (e.g., silent, validatePatches)
9510
+ * @returns {Object} { blocks: Array, warnings: Array, hasIncompleteBlocks: boolean, lastIncompleteBlock: Object|null }
9511
+ */
9512
+ function processCodeBlocks$5(text, options = { silent: false, validatePatches: false }) {
9513
+ if (typeof text !== "string") { // Allow empty strings
9514
+ console.warn("Warning: Input must be a string.");
9515
+ return {
9516
+ blocks: [],
9517
+ warnings: [{ type: 'invalid_input', message: 'Input must be a string.' }],
9518
+ hasIncompleteBlocks: false,
9519
+ lastIncompleteBlock: null }
9520
+ ;
9521
+ }
9522
+
9523
+ if (text.trim() === "") {
9524
+ return { blocks: [], warnings: [], hasIncompleteBlocks: false, lastIncompleteBlock: null };
9525
+ }
9526
+
9527
+ // Step 1: Find all fence positions
9528
+ const { openingPositions, closingPositions } = findAllCodeFences$3(text);
9529
+
9530
+ // Step 2: Match fences to get potential block boundaries
9531
+ const { completeBlocks, incompleteBlocks, warnings: extractorWarnings } = matchFencesAndExtractBlocks$3(
9532
+ text, openingPositions, closingPositions
9533
+ );
9534
+
9535
+ // Step 3: Process the content of these potential blocks
9536
+ const { processedBlocks, allWarnings: processorWarnings } = processBlockContents(
9537
+ text, completeBlocks, incompleteBlocks, options
9538
+ );
9539
+
9540
+ // Combine warnings from extractor and processor
9541
+ const allWarnings = [...extractorWarnings, ...processorWarnings];
9542
+
9543
+ // Log warnings if not silent
9544
+ if (!options.silent && allWarnings.length > 0) {
9545
+ console.warn('\nCode Block Processing Warnings:');
9546
+ allWarnings.forEach((warning, index) => {
9547
+ console.warn(`\nWarning ${index + 1}:`);
9548
+ console.warn(`Type: ${warning.type}`);
9549
+ console.warn(`Message: ${warning.message}`);
9550
+ console.warn(`Position: ${warning.position}`);
9551
+ if (warning.content) {
9552
+ // Limit logged content length
9553
+ const maxLogLength = 200;
9554
+ const loggedContent = warning.content.length > maxLogLength
9555
+ ? warning.content.substring(0, maxLogLength) + '...'
9556
+ : warning.content;
9557
+ console.warn(`Content Hint: ${loggedContent}`);
9558
+ }
9559
+ });
9560
+ }
9561
+
9562
+ const hasIncompleteBlocks = incompleteBlocks.length > 0;
9563
+ const lastIncompleteBlock = hasIncompleteBlocks
9564
+ ? processedBlocks.find(block => block.incomplete) // Find the corresponding processed block
9565
+ : null;
9566
+
9567
+ return {
9568
+ blocks: processedBlocks,
9569
+ warnings: allWarnings,
9570
+ hasIncompleteBlocks: hasIncompleteBlocks,
9571
+ lastIncompleteBlock: lastIncompleteBlock
9572
+ };
9573
+ }
9574
+
9575
+ /**
9576
+ * Public API function - maintains backward compatibility for simple extraction.
9577
+ * Use processCodeBlocks for more detailed results (warnings, incomplete status).
9578
+ * @param {string} text - The input text containing code blocks
9579
+ * @param {Object} options - Options for extraction (e.g., { silent: true })
9580
+ * @returns {Object} - Object containing extracted blocks and warnings { blocks: Array, warnings: Array }
9581
+ */
9582
+ function extractCodeBlocks$2(text, options = { silent: false, validatePatches: false, debug: false }) {
9583
+ const { blocks, warnings } = processCodeBlocks$5(text, options);
9584
+ return { blocks, warnings };
10086
9585
  }
10087
9586
 
9587
+
9588
+ /**
9589
+ * Fixes invalid UUIDs in code blocks within text
9590
+ * @param {string} text - The input text containing code blocks
9591
+ * @returns {Object} - Object containing fixed text and whether changes were made { text: string, modified: boolean }
9592
+ */
9593
+ function fixTextCodeBlocks$2(text) {
9594
+ if (typeof text !== "string" || text.trim() === "") {
9595
+ return {
9596
+ text: text,
9597
+ modified: false
9598
+ };
9599
+ }
9600
+
9601
+ let modified = false;
9602
+ let fixedText = text;
9603
+
9604
+ // Regex to match code blocks with their language
9605
+ const codeBlockRegex = /```([a-zA-Z-]*)\n([\s\S]*?)\n```/g;
9606
+
9607
+ // Store all matches to process in reverse
9608
+ const matches = Array.from(text.matchAll(codeBlockRegex));
9609
+
9610
+ // Process matches in reverse to maintain correct positions
9611
+ for (let i = matches.length - 1; i >= 0; i--) {
9612
+ const match = matches[i];
9613
+ const fullMatch = match[0];
9614
+ const language = match[1];
9615
+ const blockContent = match[2];
9616
+
9617
+ // Check if this is a patch block or a gitsense-search-flow block (if they contain UUIDs)
9618
+ if (PatchUtils$1.isPatchBlock(blockContent)) {
9619
+ // Process patch block UUIDs
9620
+ const lines = blockContent.split('\n');
9621
+ let blockModified = false;
9622
+
9623
+ const newLines = lines.map(line => {
9624
+ // Check for UUID fields in patch metadata
9625
+ if ((line.includes('# Source-Block-UUID:') || line.includes('# Target-Block-UUID:')) &&
9626
+ !line.includes('{{GS-UUID}')) {
9627
+
9628
+ const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
9629
+
9630
+ // Validate UUID
9631
+ const validation = validateUUID$2(valuePart);
9632
+ if (validation["Block-UUID"] === "INVALID UUID") {
9633
+ blockModified = true;
9634
+ modified = true;
9635
+ return `${fieldPart}: ${validation["Correct Block-UUID"]}`;
9636
+ }
9637
+ }
9638
+ return line;
9639
+ });
9640
+
9641
+ // If this block was modified, replace it in the text
9642
+ if (blockModified) {
9643
+ const newBlock = `\`\`\`${language}\n${newLines.join('\n')}\n\`\`\``;
9644
+ fixedText = fixedText.substring(0, match.index) +
9645
+ newBlock +
9646
+ fixedText.substring(match.index + fullMatch.length);
9647
+ }
9648
+ } else {
9649
+ // Process regular code block or gitsense-search-flow block for UUIDs
9650
+ // Split block content into lines to check for header/UUIDs
9651
+ const lines = blockContent.split('\n');
9652
+ let blockModified = false;
9653
+
9654
+ // Process each line
9655
+ const newLines = lines.map(line => {
9656
+ // Check for UUID fields
9657
+ if (line.includes(' Block-UUID: ') || line.includes(' Parent-UUID: ')) {
9658
+ const [fieldPart, valuePart] = line.split(':').map(p => p.trim());
9659
+
9660
+ // Skip if N/A or contains unexpected characters
9661
+ if (valuePart === 'N/A' || valuePart.match(/\(/)) {
9662
+ return line;
9663
+ }
9664
+ // Validate UUID
9665
+ const validation = validateUUID$2(valuePart);
9666
+
9667
+ if (validation["Block-UUID"] === "INVALID UUID") {
9668
+ blockModified = true;
9669
+ modified = true;
9670
+ return `${fieldPart}: ${validation["Correct Block-UUID"]}`;
9671
+ }
9672
+ }
9673
+ return line;
9674
+ });
9675
+
9676
+ // If this block was modified, replace it in the text
9677
+ if (blockModified) {
9678
+ const newBlock = `\`\`\`${language}\n${newLines.join('\n')}\n\`\`\``;
9679
+ fixedText = fixedText.substring(0, match.index) +
9680
+ newBlock +
9681
+ fixedText.substring(match.index + fullMatch.length);
9682
+ }
9683
+ }
9684
+ }
9685
+
9686
+ return {
9687
+ text: fixedText,
9688
+ modified: modified
9689
+ };
9690
+ }
9691
+
9692
+
9693
+ var blockProcessor = {
9694
+ processCodeBlocks: processCodeBlocks$5,
9695
+ extractCodeBlocks: extractCodeBlocks$2,
9696
+ fixTextCodeBlocks: fixTextCodeBlocks$2,
9697
+ };
9698
+
10088
9699
  /**
10089
9700
  * Component: CodeBlockUtils Patch Integration
10090
9701
  * Block-UUID: 9f7395ef-e213-4841-a95d-f263e422288a
@@ -10097,7 +9708,7 @@ function requireBlockProcessor () {
10097
9708
  */
10098
9709
 
10099
9710
  // Dependency on the core block processor
10100
- const { processCodeBlocks: processCodeBlocks$3 } = requireBlockProcessor();
9711
+ const { processCodeBlocks: processCodeBlocks$4 } = blockProcessor;
10101
9712
 
10102
9713
  /**
10103
9714
  * Checks if the provided text content contains at least one patch block.
@@ -10107,7 +9718,7 @@ const { processCodeBlocks: processCodeBlocks$3 } = requireBlockProcessor();
10107
9718
  */
10108
9719
  function containsPatch$2(content, options = { silent: true }) {
10109
9720
  // Use the core processor to get all blocks
10110
- const { blocks } = processCodeBlocks$3(content, options);
9721
+ const { blocks } = processCodeBlocks$4(content, options);
10111
9722
 
10112
9723
  // Check if any processed block is of type 'patch'
10113
9724
  for (let i = 0; i < blocks.length; i++) {
@@ -10135,7 +9746,7 @@ var patchIntegration = {
10135
9746
  */
10136
9747
 
10137
9748
  // Dependency on the core block processor
10138
- const { processCodeBlocks: processCodeBlocks$2 } = requireBlockProcessor();
9749
+ const { processCodeBlocks: processCodeBlocks$3 } = blockProcessor;
10139
9750
 
10140
9751
  /**
10141
9752
  * Detects special code block relationships in a message, such as patches or parent-child links.
@@ -10169,7 +9780,7 @@ function detectCodeBlockRelationships$2(content, codeBlockService, options = { s
10169
9780
 
10170
9781
 
10171
9782
  // Extract all code blocks using the core processor
10172
- const { blocks, warnings } = processCodeBlocks$2(content, options);
9783
+ const { blocks, warnings } = processCodeBlocks$3(content, options);
10173
9784
 
10174
9785
  let hasPatch = false;
10175
9786
  let hasParentChildRelationship = false;
@@ -10243,7 +9854,7 @@ function detectIncompleteCodeBlock$2(content, options = { silent: true }) {
10243
9854
  }
10244
9855
 
10245
9856
  // Use the core processor which already identifies incomplete blocks
10246
- const { hasIncompleteBlocks, lastIncompleteBlock } = processCodeBlocks$2(content, options);
9857
+ const { hasIncompleteBlocks, lastIncompleteBlock } = processCodeBlocks$3(content, options);
10247
9858
 
10248
9859
  return {
10249
9860
  hasIncompleteBlocks,
@@ -10546,6 +10157,281 @@ Plain text block.
10546
10157
  // (Removed the check `if (typeof module !== 'undefined' && module.exports)` as it's standard in Node)
10547
10158
  var markerRemover = { removeCodeBlockMarkers: removeCodeBlockMarkers$2 };
10548
10159
 
10160
+ /**
10161
+ * Component: CodeBlockUtils Update Code Block
10162
+ * Block-UUID: 6a7b8c9d-0e1f-42a3-b4c5-d6e7f8a9b0c1
10163
+ * Parent-UUID: 5f9c1e3a-7b2d-4e8f-a1d0-9c4b2e1f8a0b
10164
+ * Version: 1.4.0
10165
+ * Description: Provides functions to update the content of a specific code block within a string, identified by index, UUID, or direct reference.
10166
+ * Language: JavaScript
10167
+ * Created-at: 2025-04-16T00:56:57.352Z
10168
+ * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Pro (v1.2.0), Gemini 2.5 Pro (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0)
10169
+ */
10170
+
10171
+ // Dependencies from other modules within CodeBlockUtils
10172
+ const { findAllCodeFences: findAllCodeFences$2, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$2, findCodeBlockByUUID: findCodeBlockByUUID$1 } = blockExtractor; // Added findCodeBlockByUUID
10173
+ const { processCodeBlocks: processCodeBlocks$2 } = blockProcessor; // To get parsed block info
10174
+
10175
+ /**
10176
+ * Replaces the content of a code block specified by its index within a message string.
10177
+ *
10178
+ * @param {string} messageContent - The original message string containing code blocks.
10179
+ * @param {number} blockIndex - The 0-based index of the code block to replace.
10180
+ * @param {string} newCodeContent - The new raw content (code, potentially including header) to insert into the block.
10181
+ * @param {string} [language] - Optional: The language identifier for the updated code block fence. If omitted, the original language is preserved.
10182
+ * @returns {string} The message content with the specified code block updated.
10183
+ * @throws {Error} If the blockIndex is out of bounds or if block boundaries cannot be determined.
10184
+ */
10185
+ function updateCodeBlockByIndex$2(messageContent, blockIndex, newCodeContent, language = undefined) {
10186
+ if (typeof messageContent !== 'string') {
10187
+ throw new Error("messageContent must be a string.");
10188
+ }
10189
+ if (typeof blockIndex !== 'number' || blockIndex < 0) {
10190
+ throw new Error("blockIndex must be a non-negative number.");
10191
+ }
10192
+ if (typeof newCodeContent !== 'string') {
10193
+ // Allow empty string replacement, but not other types
10194
+ throw new Error("newCodeContent must be a string.");
10195
+ }
10196
+
10197
+ // Step 1: Find all fence positions to get accurate start/end of the full block
10198
+ const { openingPositions, closingPositions } = findAllCodeFences$2(messageContent);
10199
+ const { completeBlocks, incompleteBlocks, warnings: extractorWarnings } = matchFencesAndExtractBlocks$2(
10200
+ messageContent, openingPositions, closingPositions
10201
+ );
10202
+
10203
+ // Combine complete and incomplete for indexing, assuming we might want to update an incomplete one too
10204
+ // Note: Replacing content in an incomplete block might be unusual, but technically possible.
10205
+ const allBlocks = [...completeBlocks, ...incompleteBlocks];
10206
+
10207
+ // Step 2: Validate index
10208
+ if (blockIndex >= allBlocks.length) {
10209
+ throw new Error(`blockIndex ${blockIndex} is out of bounds. Found ${allBlocks.length} blocks.`);
10210
+ }
10211
+
10212
+ // Step 3: Get the target block's boundary information
10213
+ const targetBlockBoundaries = allBlocks[blockIndex];
10214
+ const openingFence = targetBlockBoundaries.opening;
10215
+ const closingFence = targetBlockBoundaries.closing; // Will be undefined for incomplete blocks
10216
+
10217
+ if (!openingFence) {
10218
+ // Should not happen if index is valid, but good practice to check
10219
+ throw new Error(`Could not find opening fence for block at index ${blockIndex}.`);
10220
+ }
10221
+
10222
+ // Determine the exact start and end of the full markdown block
10223
+ const blockStartPos = openingFence.position;
10224
+ // If the block is incomplete, the end is the end of the messageContent
10225
+ const blockEndPos = closingFence
10226
+ ? closingFence.position + closingFence.length
10227
+ : messageContent.length;
10228
+
10229
+ // Step 4: Construct the replacement block string
10230
+ const targetLanguage = language !== undefined ? language : (openingFence.language || ''); // Use provided language or original/empty
10231
+ const newBlockString = `\`\`\`${targetLanguage}\n${newCodeContent}\n\`\`\``;
10232
+
10233
+ // Step 5: Perform the replacement
10234
+ const updatedMessageContent =
10235
+ messageContent.substring(0, blockStartPos) +
10236
+ newBlockString +
10237
+ messageContent.substring(blockEndPos);
10238
+
10239
+ return updatedMessageContent;
10240
+ }
10241
+
10242
+ /**
10243
+ * Replaces the content of a code block specified by its Block-UUID within a message string.
10244
+ *
10245
+ * @param {string} messageContent - The original message string containing code blocks.
10246
+ * @param {string} blockUUID - The Block-UUID of the code block to replace.
10247
+ * @param {string} newCodeContent - The new raw content (code, potentially including header) to insert into the block.
10248
+ * @param {string} [language] - Optional: The language identifier for the updated code block fence. If omitted, the original language is preserved.
10249
+ * @returns {string} The message content with the specified code block updated.
10250
+ * @throws {Error} If no block with the specified UUID is found, or if multiple blocks have the same UUID.
10251
+ */
10252
+ function updateCodeBlockByUUID$1(messageContent, blockUUID, newCodeContent, language = undefined) {
10253
+ if (typeof messageContent !== 'string') {
10254
+ throw new Error("messageContent must be a string.");
10255
+ }
10256
+ if (typeof blockUUID !== 'string' || !blockUUID) {
10257
+ throw new Error("blockUUID must be a non-empty string.");
10258
+ }
10259
+ if (typeof newCodeContent !== 'string') {
10260
+ throw new Error("newCodeContent must be a string.");
10261
+ }
10262
+
10263
+ // Step 1: Process blocks to get headers and find the target index
10264
+ const { blocks: processedBlocks, warnings } = processCodeBlocks$2(messageContent, { silent: true });
10265
+
10266
+ let targetIndex = -1;
10267
+
10268
+ for (let i = 0; i < processedBlocks.length; i++) {
10269
+ const block = processedBlocks[i];
10270
+ let match = false;
10271
+
10272
+ // Check standard code blocks by Block-UUID
10273
+ if ((block.type === 'code') && block.header && block.header['Block-UUID'] === blockUUID) {
10274
+ match = true;
10275
+ }
10276
+ // Check patch blocks by Target-Block-UUID
10277
+ else if (block.type === 'patch' && block.metadata && block.metadata['Target-Block-UUID'] === blockUUID) {
10278
+ match = true;
10279
+ }
10280
+
10281
+ if (match) {
10282
+ // If we've already found one, log a warning but still update the first one found.
10283
+ if (targetIndex !== -1) {
10284
+ console.warn(`Multiple blocks found matching UUID: ${blockUUID} (could be Block-UUID or Target-Block-UUID). Updating the first occurrence.`);
10285
+ } else {
10286
+ targetIndex = i;
10287
+ }
10288
+ }
10289
+ }
10290
+
10291
+ // Step 2: Handle findings
10292
+ if (targetIndex === -1) { // Use targetIndex to check if *any* valid match was set
10293
+ throw new Error(`No code or patch block found matching UUID: ${blockUUID} (checked Block-UUID and Target-Block-UUID).`);
10294
+ }
10295
+ // Warning for multiple matches is handled inside the loop now.
10296
+
10297
+ // Step 3: Call the index-based function
10298
+ // We need the index relative to *all* blocks (complete and incomplete), not just processed ones.
10299
+ // Re-extract boundaries to get the correct index mapping.
10300
+ const { openingPositions, closingPositions } = findAllCodeFences$2(messageContent);
10301
+ const { completeBlocks, incompleteBlocks } = matchFencesAndExtractBlocks$2(
10302
+ messageContent, openingPositions, closingPositions
10303
+ );
10304
+ const allBlocks = [...completeBlocks, ...incompleteBlocks];
10305
+
10306
+ // Find the index in the combined list that corresponds to the processed block's position
10307
+ const targetProcessedBlock = processedBlocks[targetIndex];
10308
+ const actualIndex = allBlocks.findIndex(b => b.opening.position === targetProcessedBlock.position);
10309
+
10310
+ if (actualIndex === -1) {
10311
+ // This indicates a discrepancy between blockProcessor and blockExtractor results, which shouldn't happen.
10312
+ throw new Error(`Internal error: Could not map processed block at index ${targetIndex} (matching UUID: ${blockUUID}) back to extracted block boundaries.`);
10313
+ }
10314
+
10315
+ // Pass the optional language parameter down
10316
+ return updateCodeBlockByIndex$2(messageContent, actualIndex, newCodeContent, language);
10317
+ }
10318
+
10319
+ /**
10320
+ * Updates a code block in message text identified by UUID.
10321
+ * (Moved from original PatchUtils)
10322
+ * @param {string} messageText - The original message text
10323
+ * @param {string} blockUUID - The Block-UUID to update
10324
+ * @param {string} newCode - The new code content (raw content, including header if applicable)
10325
+ * @param {string} language - The code language for the fence
10326
+ * @returns {string} Updated message text
10327
+ * @throws {Error} If block not found or parameters missing.
10328
+ */
10329
+ function updateCodeBlockInMessage$1(messageText, blockUUID, newCode, language) {
10330
+ if (!messageText || !blockUUID || newCode === null || newCode === undefined) { // Allow empty string for newCode
10331
+ throw new Error("Missing required parameters for updating code block (messageText, blockUUID, newCode)");
10332
+ }
10333
+
10334
+ // Use findCodeBlockByUUID from blockExtractor
10335
+ const block = findCodeBlockByUUID$1(messageText, blockUUID);
10336
+
10337
+ if (!block) {
10338
+ throw new Error(`Code block with UUID ${blockUUID} not found`);
10339
+ }
10340
+
10341
+ // Construct the new full block string
10342
+ const newBlockString = '```' + (language || block.language) + '\n' + newCode + '\n```';
10343
+
10344
+ // Replace the old block with the new one using precise indices
10345
+ return messageText.substring(0, block.startIndex) +
10346
+ newBlockString +
10347
+ messageText.substring(block.endIndex);
10348
+ }
10349
+
10350
+
10351
+ /**
10352
+ * Generic router function to update a code block by index or UUID.
10353
+ *
10354
+ * @param {string} messageContent - The original message string.
10355
+ * @param {number|string} identifier - The block index (number) or Block-UUID (string).
10356
+ * @param {string} newCodeContent - The new raw content for the block.
10357
+ * @param {string} [language] - Optional: The language identifier for the updated code block fence.
10358
+ * @returns {string} The updated message content.
10359
+ * @throws {Error} If the identifier type is invalid or if the underlying update function fails.
10360
+ */
10361
+ function updateCodeBlock$1(messageContent, identifier, newCodeContent, language = undefined) {
10362
+ if (typeof identifier === 'number') {
10363
+ // Pass language to index-based function
10364
+ return updateCodeBlockByIndex$2(messageContent, identifier, newCodeContent, language);
10365
+ } else if (typeof identifier === 'string') {
10366
+ // Pass language to UUID-based function
10367
+ return updateCodeBlockByUUID$1(messageContent, identifier, newCodeContent, language);
10368
+ } else {
10369
+ throw new Error("Invalid identifier type. Must be a number (index) or a string (UUID).");
10370
+ }
10371
+ }
10372
+
10373
+ /**
10374
+ * Deletes a code block specified by its index within a message string.
10375
+ *
10376
+ * @param {string} messageContent - The original message string containing code blocks.
10377
+ * @param {number} blockIndex - The 0-based index of the code block to delete.
10378
+ * @returns {string} The message content with the specified code block deleted.
10379
+ * @throws {Error} If the blockIndex is out of bounds or if block boundaries cannot be determined.
10380
+ */
10381
+ function deleteCodeBlockByIndex$2(messageContent, blockIndex) {
10382
+ if (typeof messageContent !== 'string') {
10383
+ throw new Error("messageContent must be a string.");
10384
+ }
10385
+ if (typeof blockIndex !== 'number' || blockIndex < 0) {
10386
+ throw new Error("blockIndex must be a non-negative number.");
10387
+ }
10388
+
10389
+ // Step 1: Find all fence positions to get accurate start/end of the full block
10390
+ const { openingPositions, closingPositions } = findAllCodeFences$2(messageContent);
10391
+ const { completeBlocks, incompleteBlocks } = matchFencesAndExtractBlocks$2(
10392
+ messageContent, openingPositions, closingPositions
10393
+ );
10394
+
10395
+ // Combine complete and incomplete for indexing
10396
+ const allBlocks = [...completeBlocks, ...incompleteBlocks];
10397
+
10398
+ // Step 2: Validate index
10399
+ if (blockIndex >= allBlocks.length) {
10400
+ throw new Error(`blockIndex ${blockIndex} is out of bounds. Found ${allBlocks.length} blocks.`);
10401
+ }
10402
+
10403
+ // Step 3: Get the target block's boundary information
10404
+ const targetBlockBoundaries = allBlocks[blockIndex];
10405
+ const openingFence = targetBlockBoundaries.opening;
10406
+ const closingFence = targetBlockBoundaries.closing; // Will be undefined for incomplete blocks
10407
+
10408
+ if (!openingFence) {
10409
+ // Should not happen if index is valid, but good practice to check
10410
+ throw new Error(`Could not find opening fence for block at index ${blockIndex}.`);
10411
+ }
10412
+
10413
+ // Determine the exact start and end of the full markdown block
10414
+ const blockStartPos = openingFence.position;
10415
+ // If the block is incomplete, the end is the end of the messageContent
10416
+ const blockEndPos = closingFence
10417
+ ? closingFence.position + closingFence.length
10418
+ : messageContent.length;
10419
+
10420
+ // Step 4: Perform the deletion
10421
+ const updatedMessageContent =
10422
+ messageContent.substring(0, blockStartPos) +
10423
+ messageContent.substring(blockEndPos);
10424
+
10425
+ return updatedMessageContent;
10426
+ }
10427
+
10428
+ var updateCodeBlock_1 = {
10429
+ updateCodeBlockByIndex: updateCodeBlockByIndex$2,
10430
+ updateCodeBlockByUUID: updateCodeBlockByUUID$1,
10431
+ updateCodeBlock: updateCodeBlock$1,
10432
+ updateCodeBlockInMessage: updateCodeBlockInMessage$1,
10433
+ deleteCodeBlockByIndex: deleteCodeBlockByIndex$2};
10434
+
10549
10435
  /**
10550
10436
  * Component: CodeBlockUtils Index
10551
10437
  * Block-UUID: 7e9d3f8a-1b2c-4d5e-8f9a-0123456789ab
@@ -10562,17 +10448,17 @@ const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$2;
10562
10448
  const { generateUUID: generateUUID$1, validateUUID: validateUUID$1 } = uuidUtils;
10563
10449
  const { isValidISOTimestamp: isValidISOTimestamp$1, parseHeader: parseHeader$1, getHeaderLineCount } = headerUtils;
10564
10450
  const { findAllCodeFences: findAllCodeFences$1, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$1, extractCodeBlocksWithUUIDs, findCodeBlockByUUID } = blockExtractor;
10565
- const { processCodeBlocks: processCodeBlocks$1, extractCodeBlocks: extractCodeBlocks$1, fixTextCodeBlocks: fixTextCodeBlocks$1 } = requireBlockProcessor();
10451
+ const { processCodeBlocks: processCodeBlocks$1, extractCodeBlocks: extractCodeBlocks$1, fixTextCodeBlocks: fixTextCodeBlocks$1 } = blockProcessor;
10566
10452
  const { containsPatch: containsPatch$1 } = patchIntegration;
10567
10453
  const { detectCodeBlockRelationships: detectCodeBlockRelationships$1, detectIncompleteCodeBlock: detectIncompleteCodeBlock$1, extractFilePaths: extractFilePaths$1 } = relationshipUtils;
10568
10454
  const { extractContinuationInfo: extractContinuationInfo$1, generateContinuationPrompt: generateContinuationPrompt$1 } = continuationUtils;
10569
10455
  const { parseCodeBlocks: parseCommentDelimitedBlocks$1 } = headerParser;
10570
10456
  const { removeCodeBlockMarkers: removeCodeBlockMarkers$1 } = markerRemover;
10571
- const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID, updateCodeBlock, updateCodeBlockInMessage, deleteCodeBlockByIndex: deleteCodeBlockByIndex$1 } = requireUpdateCodeBlock();
10457
+ const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID, updateCodeBlock, updateCodeBlockInMessage, deleteCodeBlockByIndex: deleteCodeBlockByIndex$1 } = updateCodeBlock_1;
10572
10458
  const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbers: formatBlockWithLineNumbers$1, formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1, removeLineNumbers: removeLineNumbers$1 } = lineNumberFormatter;
10573
10459
 
10574
10460
  // Export all imported items
10575
- var CodeBlockUtils$4 = {
10461
+ var CodeBlockUtils$5 = {
10576
10462
  // Constants
10577
10463
  COMMENT_STYLES: COMMENT_STYLES$1,
10578
10464
 
@@ -10639,7 +10525,7 @@ var CodeBlockUtils$4 = {
10639
10525
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
10640
10526
  */
10641
10527
 
10642
- const CodeBlockUtils$3 = CodeBlockUtils$4;
10528
+ const CodeBlockUtils$4 = CodeBlockUtils$5;
10643
10529
  const MessageUtils$2 = MessageUtils$3;
10644
10530
 
10645
10531
  /**
@@ -10778,7 +10664,7 @@ function parseContextSection$1(sectionText) {
10778
10664
  }
10779
10665
  });
10780
10666
 
10781
- const { blocks, warnings } = CodeBlockUtils$3.extractCodeBlocks(sectionText, { silent: true });
10667
+ const { blocks, warnings } = CodeBlockUtils$4.extractCodeBlocks(sectionText, { silent: true });
10782
10668
  const codeBlocks = blocks.filter(block => block.type === 'code');
10783
10669
 
10784
10670
  if (codeBlocks.length === 0) {
@@ -11044,8 +10930,8 @@ var constants = {
11044
10930
  * Authors: Gemini 2.5 Flash (v1.0.0)
11045
10931
  */
11046
10932
 
11047
- const CodeBlockUtils$2 = CodeBlockUtils$4;
11048
- const GSToolBlockUtils$1 = requireGSToolBlockUtils();
10933
+ const CodeBlockUtils$3 = CodeBlockUtils$5;
10934
+ const GSToolBlockUtils$1 = GSToolBlockUtils$3;
11049
10935
  const JsonUtils$1 = JsonUtils$2;
11050
10936
  const { ANALYZE_HEADER_PREFIX } = constants;
11051
10937
 
@@ -11061,7 +10947,7 @@ const { ANALYZE_HEADER_PREFIX } = constants;
11061
10947
  */
11062
10948
  function processLLMAnalysisResponse$2(messageContent, stoppedStreaming) {
11063
10949
  const silent = { silent: true };
11064
- const { blocks, warnings } = CodeBlockUtils$2.extractCodeBlocks(messageContent, silent);
10950
+ const { blocks, warnings } = CodeBlockUtils$3.extractCodeBlocks(messageContent, silent);
11065
10951
 
11066
10952
  const analysisBlocks = [];
11067
10953
  const analysisMetadataBlocks = [];
@@ -11174,7 +11060,7 @@ var responseProcessor = {
11174
11060
  * Authors: Gemini 2.5 Flash (v1.0.0)
11175
11061
  */
11176
11062
 
11177
- const AnalysisBlockUtils$1 = AnalysisBlockUtils$2;
11063
+ const AnalysisBlockUtils$1 = AnalysisBlockUtils$3;
11178
11064
 
11179
11065
  /**
11180
11066
  * Validates the extracted analysis blocks and their metadata.
@@ -11318,6 +11204,7 @@ var instructionLoader = {
11318
11204
  const fs$6 = require$$0.promises;
11319
11205
  const path$4 = require$$1;
11320
11206
  const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2 } = instructionLoader;
11207
+ const CodeBlockUtils$2 = CodeBlockUtils$5;
11321
11208
 
11322
11209
  /**
11323
11210
  * Reads and parses the config.json file in a directory.
@@ -11415,10 +11302,21 @@ async function getAnalyzers$2(analyzeMessagesBasePath, options = {}) {
11415
11302
  const analyzerId = `${analyzerName}::${contentType}::${instructionsType}`;
11416
11303
  const analyzerFullLabel = `${analyzerLabel} (${contentLabel} - ${instructionsLabel})`;
11417
11304
 
11418
- let descriptionContent = null;
11305
+ let description = null;
11419
11306
  if (includeDescription) {
11420
11307
  try {
11421
- descriptionContent = await getAnalyzerInstructionsContent$2(analyzeMessagesBasePath, analyzerId);
11308
+ const content = await getAnalyzerInstructionsContent$2(analyzeMessagesBasePath, analyzerId);
11309
+ const { blocks, warnings } = CodeBlockUtils$2.extractCodeBlocks(content, { silent: true });
11310
+ const jsonBlock = blocks.find(block => block.language === 'json');
11311
+
11312
+ if (jsonBlock && jsonBlock.content) {
11313
+ try {
11314
+ const json = JSON.parse(jsonBlock.content);
11315
+ description = json.description;
11316
+ } catch(error) {
11317
+ console.warn(`${analyzerId} contains an invalid JSON`);
11318
+ }
11319
+ }
11422
11320
  } catch (descError) {
11423
11321
  console.warn(`Warning: Could not load description for ${analyzerId}: ${descError.message}`);
11424
11322
  descriptionContent = null;
@@ -11430,7 +11328,7 @@ async function getAnalyzers$2(analyzeMessagesBasePath, options = {}) {
11430
11328
  label: analyzerFullLabel,
11431
11329
  name: analyzerName,
11432
11330
  protected: analyzerConfig?.protected || false,
11433
- ...(descriptionContent && { description: descriptionContent })
11331
+ description
11434
11332
  });
11435
11333
  } catch (error) {
11436
11334
  // If 1.md doesn't exist, this is not a complete analyzer configuration, skip.
@@ -11603,7 +11501,7 @@ var saver = {
11603
11501
 
11604
11502
  const fs$4 = require$$0.promises;
11605
11503
  const path$2 = require$$1;
11606
- const CodeBlockUtils$1 = CodeBlockUtils$4;
11504
+ const CodeBlockUtils$1 = CodeBlockUtils$5;
11607
11505
 
11608
11506
  /**
11609
11507
  * Deduces the JSON schema type and format/items from a string value pattern.
@@ -12232,13 +12130,13 @@ var EnvUtils$1 = {
12232
12130
  */
12233
12131
 
12234
12132
  const ChatUtils = ChatUtils$1;
12235
- const CodeBlockUtils = CodeBlockUtils$4;
12133
+ const CodeBlockUtils = CodeBlockUtils$5;
12236
12134
  const ContextUtils = ContextUtils$2;
12237
12135
  const MessageUtils = MessageUtils$3;
12238
- const AnalysisBlockUtils = AnalysisBlockUtils$2;
12136
+ const AnalysisBlockUtils = AnalysisBlockUtils$3;
12239
12137
  const AnalyzerUtils = AnalyzerUtils$1;
12240
- const PatchUtils = PatchUtils$1;
12241
- const GSToolBlockUtils = requireGSToolBlockUtils();
12138
+ const PatchUtils = PatchUtils$2;
12139
+ const GSToolBlockUtils = GSToolBlockUtils$3;
12242
12140
  const LLMUtils = LLMUtils$1;
12243
12141
  const JsonUtils = JsonUtils$2;
12244
12142
  const ConfigUtils = ConfigUtils$1;