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