@gitsense/gsc-utils 0.2.1 → 0.2.2

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.
@@ -450,7 +450,7 @@ function parseAnalyzeMessage(messageContent) {
450
450
  return { id: uniqueAnalyzerId, analyzer, content, instructions };
451
451
  }
452
452
 
453
- var MessageUtils$2 = {
453
+ var MessageUtils$3 = {
454
454
  deleteMessagesByIds: deleteMessagesByIds$1,
455
455
  getChatTemplateMessages: getChatTemplateMessages$1,
456
456
  getMessagesBeforeId: getMessagesBeforeId$2,
@@ -476,7 +476,7 @@ var MessageUtils$2 = {
476
476
  * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0), Gemini 2.5 Flash Thinking (v1.2.1), Gemini 2.5 Flash Thinking (v1.3.0)
477
477
  */
478
478
 
479
- const { getMessagesBeforeId: getMessagesBeforeId$1 } = MessageUtils$2;
479
+ const { getMessagesBeforeId: getMessagesBeforeId$1 } = MessageUtils$3;
480
480
 
481
481
  /**
482
482
  * Internal helper function to determine if a chat session matches a specific pattern.
@@ -656,7 +656,7 @@ const COMMENT_STYLES$3 = {
656
656
  'vbscript': { type: 'apostrophe' }
657
657
  };
658
658
 
659
- var constants$1 = {
659
+ var constants$2 = {
660
660
  COMMENT_STYLES: COMMENT_STYLES$3
661
661
  };
662
662
 
@@ -836,7 +836,7 @@ var lineNumberFormatter = {
836
836
  */
837
837
 
838
838
  // Dependencies from other modules within CodeBlockUtils
839
- const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$1;
839
+ const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$2;
840
840
  const { removeLineNumbers: removeLineNumbers$9 } = lineNumberFormatter; // Assuming this utility exists
841
841
  const { validateUUID: validateUUID$3 } = uuidUtils; // Assuming uuidUtils.js is in the same directory
842
842
 
@@ -1458,7 +1458,7 @@ function validateAnalysisMetadata(metadata) {
1458
1458
  }
1459
1459
 
1460
1460
 
1461
- var AnalysisBlockUtils$2 = {
1461
+ var AnalysisBlockUtils$3 = {
1462
1462
  isAnalysisBlock,
1463
1463
  getAnalysisBlockType,
1464
1464
  parseOverviewMetadata: parseOverviewMetadata$1,
@@ -1791,7 +1791,7 @@ const CONTENT_LINE_REGEX$5 = /^([ +-])\s*[-+]*(\d+):\s?(.*)$/;
1791
1791
  // Captures: 1: old_start, 2: old_count (optional), 3: new_start, 4: new_count (optional)
1792
1792
  const HUNK_HEADER_REGEX$4 = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
1793
1793
 
1794
- var constants = {
1794
+ var constants$1 = {
1795
1795
  CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$5,
1796
1796
  HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$4,
1797
1797
  };
@@ -1808,7 +1808,7 @@ var constants = {
1808
1808
  */
1809
1809
 
1810
1810
  const { removeLineNumbers: removeLineNumbers$8 } = lineNumberFormatter; // Assuming this utility exists
1811
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$4, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$3 } = constants;
1811
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$4, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$3 } = constants$1;
1812
1812
 
1813
1813
 
1814
1814
  /**
@@ -1973,7 +1973,7 @@ var formatAndAddLineNumbers_1 = {
1973
1973
  */
1974
1974
 
1975
1975
  const { removeLineNumbers: removeLineNumbers$7 } = lineNumberFormatter; // Assuming this utility exists
1976
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$3 } = constants;
1976
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$3 } = constants$1;
1977
1977
  const { formatAndAddLineNumbers: formatAndAddLineNumbers$1 } = formatAndAddLineNumbers_1; // Import the helper
1978
1978
 
1979
1979
 
@@ -2226,7 +2226,7 @@ var verifyAndCorrectLineNumbers_1 = {
2226
2226
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2227
2227
  */
2228
2228
 
2229
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$2, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$2 } = constants;
2229
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$2, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$2 } = constants$1;
2230
2230
 
2231
2231
 
2232
2232
  /**
@@ -2425,7 +2425,7 @@ var verifyAndCorrectHunkHeaders_1 = {
2425
2425
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2426
2426
  */
2427
2427
 
2428
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$1, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$1 } = constants;
2428
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$1, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$1 } = constants$1;
2429
2429
 
2430
2430
 
2431
2431
  /**
@@ -2828,7 +2828,7 @@ var detectAndFixRedundantChanges_1 = {
2828
2828
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2829
2829
  */
2830
2830
 
2831
- const { CONTENT_LINE_REGEX, HUNK_HEADER_REGEX } = constants;
2831
+ const { CONTENT_LINE_REGEX, HUNK_HEADER_REGEX } = constants$1;
2832
2832
 
2833
2833
 
2834
2834
  /**
@@ -8782,7 +8782,7 @@ function formatToolBlock(toolData) {
8782
8782
  return `# GitSense Chat Tool\n\n${JSON.stringify(toolData, null, 2)}`;
8783
8783
  }
8784
8784
 
8785
- var GSToolBlockUtils$2 = {
8785
+ var GSToolBlockUtils$3 = {
8786
8786
  isToolBlock: isToolBlock$1,
8787
8787
  parseToolBlock: parseToolBlock$1,
8788
8788
  formatToolBlock
@@ -9076,7 +9076,7 @@ function detectJsonComments$2(jsonString) {
9076
9076
  return comments;
9077
9077
  }
9078
9078
 
9079
- var JsonUtils$1 = {
9079
+ var JsonUtils$2 = {
9080
9080
  detectJsonComments: detectJsonComments$2
9081
9081
  };
9082
9082
 
@@ -9094,12 +9094,12 @@ var JsonUtils$1 = {
9094
9094
  const { findAllCodeFences: findAllCodeFences$3, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$3 } = blockExtractor;
9095
9095
  const { parseHeader: parseHeader$2 } = headerUtils;
9096
9096
  const { validateUUID: validateUUID$2, generateUUID: generateUUID$2 } = uuidUtils;
9097
- const AnalysisBlockUtils$1 = AnalysisBlockUtils$2;
9097
+ const AnalysisBlockUtils$2 = AnalysisBlockUtils$3;
9098
9098
  const PatchUtils$1 = PatchUtils$2;
9099
- const GSToolBlockUtils$1 = GSToolBlockUtils$2;
9099
+ const GSToolBlockUtils$2 = GSToolBlockUtils$3;
9100
9100
  const { extractContinuationInfo: extractContinuationInfo$2 } = continuationUtils;
9101
9101
  const { removeLineNumbers: removeLineNumbers$2 } = lineNumberFormatter;
9102
- const { detectJsonComments: detectJsonComments$1 } = JsonUtils$1;
9102
+ const { detectJsonComments: detectJsonComments$1 } = JsonUtils$2;
9103
9103
 
9104
9104
  /**
9105
9105
  * Processes a single block's content (internal helper)
@@ -9120,12 +9120,12 @@ function processBlockContent(content, language, position, incomplete, options =
9120
9120
  let codeText = content; // Default to all content being code
9121
9121
 
9122
9122
  // Check if this is a GitSense Tool Block *first*
9123
- if (GSToolBlockUtils$1.isToolBlock(content)) {
9123
+ if (GSToolBlockUtils$2.isToolBlock(content)) {
9124
9124
  let ignoreDueToComments = false;
9125
9125
  let toolData = null;
9126
9126
  let toolParseError = null;
9127
9127
  try {
9128
- toolData = GSToolBlockUtils$1.parseToolBlock(content);
9128
+ toolData = GSToolBlockUtils$2.parseToolBlock(content);
9129
9129
  } catch (error) {
9130
9130
  // When chatting about the tool block, the LLM may add
9131
9131
  // add comments in it so let's test for this
@@ -9159,14 +9159,14 @@ function processBlockContent(content, language, position, incomplete, options =
9159
9159
  }
9160
9160
 
9161
9161
  // Check if this is an analysis block *next*
9162
- if (AnalysisBlockUtils$1.isAnalysisBlock(content)) {
9163
- const analysisType = AnalysisBlockUtils$1.getAnalysisBlockType(content);
9164
- const analysisMetadata = AnalysisBlockUtils$1.parseOverviewMetadata(content);
9162
+ if (AnalysisBlockUtils$2.isAnalysisBlock(content)) {
9163
+ const analysisType = AnalysisBlockUtils$2.getAnalysisBlockType(content);
9164
+ const analysisMetadata = AnalysisBlockUtils$2.parseOverviewMetadata(content);
9165
9165
 
9166
9166
  // Validate the metadata if it was successfully parsed
9167
9167
  let validationResult = { isValid: false, errors: ['Failed to parse analysis metadata'] };
9168
9168
  if (analysisMetadata) {
9169
- validationResult = AnalysisBlockUtils$1.validateAnalysisMetadata(analysisMetadata);
9169
+ validationResult = AnalysisBlockUtils$2.validateAnalysisMetadata(analysisMetadata);
9170
9170
 
9171
9171
  if (!validationResult.isValid) {
9172
9172
  warnings.push({
@@ -10383,7 +10383,7 @@ var updateCodeBlock_1 = {
10383
10383
  */
10384
10384
 
10385
10385
  // Import from individual utility files
10386
- const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$1;
10386
+ const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$2;
10387
10387
  const { generateUUID: generateUUID$1, validateUUID: validateUUID$1 } = uuidUtils;
10388
10388
  const { isValidISOTimestamp: isValidISOTimestamp$1, parseHeader: parseHeader$1, getHeaderLineCount } = headerUtils;
10389
10389
  const { findAllCodeFences: findAllCodeFences$1, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$1, extractCodeBlocksWithUUIDs, findCodeBlockByUUID } = blockExtractor;
@@ -10397,7 +10397,7 @@ const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID,
10397
10397
  const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbers: formatBlockWithLineNumbers$1, formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1, removeLineNumbers: removeLineNumbers$1 } = lineNumberFormatter;
10398
10398
 
10399
10399
  // Export all imported items
10400
- var CodeBlockUtils$2 = {
10400
+ var CodeBlockUtils$3 = {
10401
10401
  // Constants
10402
10402
  COMMENT_STYLES: COMMENT_STYLES$1,
10403
10403
 
@@ -10464,8 +10464,8 @@ var CodeBlockUtils$2 = {
10464
10464
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
10465
10465
  */
10466
10466
 
10467
- const CodeBlockUtils$1 = CodeBlockUtils$2;
10468
- const MessageUtils$1 = MessageUtils$2;
10467
+ const CodeBlockUtils$2 = CodeBlockUtils$3;
10468
+ const MessageUtils$2 = MessageUtils$3;
10469
10469
 
10470
10470
  /**
10471
10471
  * Parses context details from a context message section.
@@ -10521,7 +10521,7 @@ function parseContextSection(sectionText) {
10521
10521
  }
10522
10522
  });
10523
10523
 
10524
- const { blocks, warnings } = CodeBlockUtils$1.extractCodeBlocks(sectionText, { silent: true });
10524
+ const { blocks, warnings } = CodeBlockUtils$2.extractCodeBlocks(sectionText, { silent: true });
10525
10525
  const codeBlocks = blocks.filter(block => block.type === 'code');
10526
10526
 
10527
10527
  if (codeBlocks.length === 0) {
@@ -10550,7 +10550,7 @@ function parseContextSection(sectionText) {
10550
10550
  */
10551
10551
  function extractContextSections(messageContent) {
10552
10552
  // Use the utility function to validate the message type
10553
- if (!MessageUtils$1.isContextMessage(messageContent)) {
10553
+ if (!MessageUtils$2.isContextMessage(messageContent)) {
10554
10554
  throw new Error("Invalid message type: Content is not a context message.");
10555
10555
  }
10556
10556
 
@@ -10627,12 +10627,312 @@ function extractContextItemsOverviewTableRows(messageContent) {
10627
10627
  return rows;
10628
10628
  }
10629
10629
 
10630
- var ContextUtils$1 = {
10630
+ var ContextUtils$2 = {
10631
10631
  parseContextSection,
10632
10632
  extractContextSections,
10633
10633
  extractContextItemsOverviewTableRows
10634
10634
  };
10635
10635
 
10636
+ /*
10637
+ * Component: AnalyzerUtils Context Mapper
10638
+ * Block-UUID: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
10639
+ * Parent-UUID: N/A
10640
+ * Version: 1.0.0
10641
+ * Description: Provides utility functions for building a map of chat IDs to file paths from chat context messages.
10642
+ * Language: JavaScript
10643
+ * Created-at: 2025-08-28T15:56:40.319Z
10644
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10645
+ */
10646
+
10647
+ const MessageUtils$1 = MessageUtils$3;
10648
+ const ContextUtils$1 = ContextUtils$2;
10649
+
10650
+ /**
10651
+ * Builds a map of chat IDs to file paths from the context messages within a chat.
10652
+ * This is crucial for validating that the LLM-generated analysis metadata refers to actual files in context.
10653
+ *
10654
+ * @param {Array<Object>} allMessages - An array of all message objects in the chat.
10655
+ * @returns {Map<number, string>} A Map where keys are chat IDs (numbers) and values are file paths (strings).
10656
+ */
10657
+ function buildChatIdToPathMap$1(allMessages) {
10658
+ const chatIdToPathMap = new Map();
10659
+
10660
+ for (const msg of allMessages) {
10661
+ const content = msg.message;
10662
+ if (MessageUtils$1.isContextMessage(content)) {
10663
+ try {
10664
+ const contextSections = ContextUtils$1.extractContextSections(content);
10665
+
10666
+ for (const section of contextSections) {
10667
+ const chatId = section['chat id'];
10668
+ const path = section.path;
10669
+
10670
+ if (chatId && path) {
10671
+ chatIdToPathMap.set(chatId, path);
10672
+ }
10673
+ }
10674
+ } catch (error) {
10675
+ console.warn("AnalyzerUtils/contextMapper: Error parsing context message for map building:", error);
10676
+ // Continue processing other messages
10677
+ }
10678
+ }
10679
+ }
10680
+ return chatIdToPathMap;
10681
+ }
10682
+
10683
+ var contextMapper = {
10684
+ buildChatIdToPathMap: buildChatIdToPathMap$1
10685
+ };
10686
+
10687
+ /*
10688
+ * Component: AnalyzerUtils Constants
10689
+ * Block-UUID: 01b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
10690
+ * Parent-UUID: N/A
10691
+ * Version: 1.0.0
10692
+ * Description: Defines constants specific to the AnalyzerUtils module.
10693
+ * Language: JavaScript
10694
+ * Created-at: 2025-08-28T15:56:40.319Z
10695
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10696
+ */
10697
+
10698
+ const ANALYZE_HEADER_PREFIX$1 = '# GitSense Chat Analysis';
10699
+
10700
+ var constants = {
10701
+ ANALYZE_HEADER_PREFIX: ANALYZE_HEADER_PREFIX$1
10702
+ };
10703
+
10704
+ /*
10705
+ * Component: AnalyzerUtils Response Processor
10706
+ * Block-UUID: 2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d
10707
+ * Parent-UUID: N/A
10708
+ * Version: 1.0.0
10709
+ * Description: Extracts and performs initial validation of analysis and metadata code blocks from raw LLM message content.
10710
+ * Language: JavaScript
10711
+ * Created-at: 2025-08-28T15:56:40.319Z
10712
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10713
+ */
10714
+
10715
+ const CodeBlockUtils$1 = CodeBlockUtils$3;
10716
+ const GSToolBlockUtils$1 = GSToolBlockUtils$3;
10717
+ const JsonUtils$1 = JsonUtils$2;
10718
+ const { ANALYZE_HEADER_PREFIX } = constants;
10719
+
10720
+ /**
10721
+ * Extracts code blocks from the message content, identifies analysis and metadata blocks,
10722
+ * and performs initial validation (block type, metadata presence, JSON format).
10723
+ * This function is adapted from the original `blockProcessing.js` in `gsc-conversation-view`.
10724
+ *
10725
+ * @param {string} messageContent - The full content of the message.
10726
+ * @param {boolean} stoppedStreaming - Flag indicating if the message streaming has stopped.
10727
+ * @returns {{analysisBlocks: Array<Object>, analysisMetadataBlocks: Array<Object|null>, error: string|null}}
10728
+ * An object containing the extracted blocks and any processing error.
10729
+ */
10730
+ function processLLMAnalysisResponse$1(messageContent, stoppedStreaming) {
10731
+ const silent = { silent: true };
10732
+ const { blocks, warnings } = CodeBlockUtils$1.extractCodeBlocks(messageContent, silent);
10733
+
10734
+ const analysisBlocks = [];
10735
+ const analysisMetadataBlocks = [];
10736
+ let error = null;
10737
+
10738
+ for (let i = 0; i < blocks.length; i += 2) {
10739
+ const analysisBlock = blocks[i];
10740
+
10741
+ // Make sure this is an analysis block by checking its content
10742
+ if (!analysisBlock.content.trimStart().startsWith(ANALYZE_HEADER_PREFIX)) {
10743
+ // Also check if it's a GitSense Tool Block, which should be ignored by this analyzer
10744
+ if (GSToolBlockUtils$1.isToolBlock(analysisBlock.content)) {
10745
+ // If it's a tool block, it's not an analysis block, so skip it and don't treat as error
10746
+ // Adjust index to skip this block and its potential "metadata" if it was paired
10747
+ if (blocks[i+1] && blocks[i+1].language === 'json') {
10748
+ i += 1; // Skip the next block too if it's a JSON block (likely tool config)
10749
+ }
10750
+ continue;
10751
+ }
10752
+
10753
+ if (stoppedStreaming) {
10754
+ error = `Analysis block #${i} does not start with the "${ANALYZE_HEADER_PREFIX}" header.`;
10755
+ }
10756
+ // If we are still streaming, we may not have enough information to tell what type
10757
+ // of block this is, so stop looking
10758
+ break;
10759
+ }
10760
+
10761
+ // Add the analysis block (Markdown overview)
10762
+ analysisBlocks.push(analysisBlock);
10763
+
10764
+ // Make sure there is an analysis metadata block (JSON)
10765
+ const analysisMetadataBlock = blocks[i + 1];
10766
+
10767
+ if (!analysisMetadataBlock) {
10768
+ if (stoppedStreaming) {
10769
+ error = `No analysis metadata found for analysis block (index ${i}).`;
10770
+ } else {
10771
+ // Add a null metadata block to let use know we are still streaming
10772
+ analysisMetadataBlocks.push(null);
10773
+ }
10774
+ break;
10775
+ }
10776
+
10777
+ // We found a code block but we don't know if it is valid or not
10778
+ // 1. First make sure the code block is a JSON type
10779
+ // 2. Try to parse the JSON
10780
+ if (analysisMetadataBlock.language !== 'json') {
10781
+ if (stoppedStreaming) {
10782
+ error = `Analysis metadata block for "${analysisBlock.overviewMetadata?.Path || 'Unknown Path'}" has invalid language "${analysisMetadataBlock.language}". Expected "json".`;
10783
+ } else {
10784
+ // Add a null metadata block to let use know we are still streaming
10785
+ analysisMetadataBlocks.push(null);
10786
+ }
10787
+ break;
10788
+ }
10789
+
10790
+ try {
10791
+ // Check for comments within JSON, which would make it invalid for direct parsing
10792
+ const comments = JsonUtils$1.detectJsonComments(analysisMetadataBlock.content);
10793
+ if (comments.length > 0) {
10794
+ error = `The analysis metadata block for "${analysisBlock.overviewMetadata?.Path || 'Unknown Path'}" contains comments, which makes it invalid JSON.`;
10795
+ if (stoppedStreaming || blocks[i + 2]) { // If streaming stopped or not the last block
10796
+ break;
10797
+ } else {
10798
+ analysisMetadataBlocks.push(null); // Add null to keep arrays aligned
10799
+ return { analysisBlocks, analysisMetadataBlocks, error: null };
10800
+ }
10801
+ }
10802
+
10803
+ JSON.parse(analysisMetadataBlock.content.trim());
10804
+ analysisMetadataBlocks.push(analysisMetadataBlock);
10805
+ } catch (err) {
10806
+ const path = analysisBlock.overviewMetadata?.Path || 'Unknown Path';
10807
+ error = `The analysis metadata block for "${path}" contains an invalid JSON: ${err.message}`;
10808
+
10809
+ // If streaming has stopped or if this is not the last block, set error and break.
10810
+ // Remember to increment by two since every second block is the meta block.
10811
+ if (stoppedStreaming || blocks[i + 2]) {
10812
+ break;
10813
+ } else {
10814
+ // Do nothing since the error is most certaintly due to the fact that we are still
10815
+ // streaming the JSON
10816
+ analysisMetadataBlocks.push(null); // Add null to keep arrays aligned
10817
+ return { analysisBlocks, analysisMetadataBlocks, error: null };
10818
+ }
10819
+ }
10820
+ }
10821
+
10822
+ // If streaming stopped and no overview blocks were found, set an error
10823
+ if (stoppedStreaming && analysisBlocks.length === 0) {
10824
+ error = 'Analysis stopped without producing any data.';
10825
+ }
10826
+
10827
+ return { analysisBlocks, analysisMetadataBlocks, error };
10828
+ }
10829
+
10830
+ var responseProcessor = {
10831
+ processLLMAnalysisResponse: processLLMAnalysisResponse$1
10832
+ };
10833
+
10834
+ /*
10835
+ * Component: AnalyzerUtils Data Validator
10836
+ * Block-UUID: 1317cc51-fca0-49b7-9e4b-b3e1a06ab93f
10837
+ * Parent-UUID: N/A
10838
+ * Version: 1.0.0
10839
+ * Description: Validates extracted analysis data against chat context and expected schema.
10840
+ * Language: JavaScript
10841
+ * Created-at: 2025-08-28T15:56:40.319Z
10842
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10843
+ */
10844
+
10845
+ const AnalysisBlockUtils$1 = AnalysisBlockUtils$3;
10846
+
10847
+ /**
10848
+ * Validates the extracted analysis blocks and their metadata.
10849
+ * Checks for valid chat IDs/paths and uses AnalysisBlockUtils for further metadata validation.
10850
+ * This function is adapted from the original `analysisValidation.js` in `gsc-conversation-view`.
10851
+ *
10852
+ * @param {Array<Object>} analysisBlocks - Array of extracted analysis code blocks (Markdown overviews).
10853
+ * @param {Array<Object|null>} analysisMetadataBlocks - Array of extracted analysis metadata blocks (JSON).
10854
+ * @param {Map<number, string>} chatIdToPathMap - Map of chat IDs to file paths from context messages.
10855
+ * @returns {{validAnalysisData: Array<Object>, invalidAnalysisBlocks: Array<string|Object>}}
10856
+ * An object containing arrays of valid analysis data and invalid analysis blocks.
10857
+ */
10858
+ function validateLLMAnalysisData$1(analysisBlocks, analysisMetadataBlocks, chatIdToPathMap) {
10859
+ const validAnalysisData = []; // Store data for the "Save All" button
10860
+ const invalidAnalysisBlocks = []; // Store invalid analysis blocks
10861
+
10862
+ analysisBlocks.forEach((block, index) => {
10863
+ // Ensure metadata is parsed from the block's content for initial checks
10864
+ const overviewMetadata = AnalysisBlockUtils$1.parseOverviewMetadata(block.content);
10865
+ const metadataBlock = analysisMetadataBlocks[index];
10866
+ const isDone = metadataBlock ? true : false; // Check if metadata block was successfully processed
10867
+
10868
+ // Skip if metadata block is missing (still streaming or error)
10869
+ if (!overviewMetadata || !isDone) {
10870
+ // If metadata block is missing but streaming stopped, it's an error handled in responseProcessor
10871
+ // If overviewMetadata is missing, it's an error handled in responseProcessor
10872
+ return;
10873
+ }
10874
+
10875
+ const chatId = overviewMetadata['Chat ID'];
10876
+ const path = overviewMetadata['Path'];
10877
+
10878
+ // Is this a valid chat id and path id? Some LLMs will actually hallucinate this
10879
+ if (!chatId || !path || !chatIdToPathMap.has(chatId)) {
10880
+ invalidAnalysisBlocks.push(`<li>#${chatId || 'N/A'} => ${path || 'N/A'} (Invalid Chat ID or Path)</li>`);
10881
+ return;
10882
+ }
10883
+
10884
+ // Perform detailed metadata validation using AnalysisBlockUtils
10885
+ const validation = AnalysisBlockUtils$1.validateAnalysisMetadata(overviewMetadata);
10886
+
10887
+ if (validation.isValid) {
10888
+ // Prepare data for API call (map keys if necessary)
10889
+ const analysisData = {
10890
+ chatId: overviewMetadata['Chat ID'],
10891
+ // The original analyzeHandler used 'Message ID', 'Repository', 'Summarized At', 'Analyze At',
10892
+ // 'Summary', 'Key Functionality', 'Keywords' from overviewMetadata.
10893
+ // For batch processing, we primarily need chatId, content, and the full JSON metadata.
10894
+ // The other fields can be derived from the full JSON metadata if needed.
10895
+ path: overviewMetadata['Path'],
10896
+ content: block.content, // The full Markdown overview
10897
+ type: AnalysisBlockUtils$1.getAnalysisBlockType(block.content), // e.g., 'tiny-overview::file-content::default'
10898
+ // We know metadataBlock.content is a valid JSON from responseProcessor
10899
+ metadata: JSON.parse(metadataBlock.content) // The full JSON metadata object
10900
+ };
10901
+ validAnalysisData.push(analysisData); // Add to list for saving
10902
+ } else {
10903
+ // Add invalid analysis block with validation details
10904
+ invalidAnalysisBlocks.push({ block, validation });
10905
+ }
10906
+ });
10907
+
10908
+ return { validAnalysisData, invalidAnalysisBlocks };
10909
+ }
10910
+
10911
+ var dataValidator = {
10912
+ validateLLMAnalysisData: validateLLMAnalysisData$1
10913
+ };
10914
+
10915
+ /*
10916
+ * Component: AnalyzerUtils Index
10917
+ * Block-UUID: b403b6a1-230b-4247-8cd6-2a3d068f4bbf
10918
+ * Parent-UUID: N/A
10919
+ * Version: 1.0.0
10920
+ * Description: Aggregates and exports all utility functions from the AnalyzerUtils module.
10921
+ * Language: JavaScript
10922
+ * Created-at: 2025-08-28T15:56:40.319Z
10923
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10924
+ */
10925
+
10926
+ const { buildChatIdToPathMap } = contextMapper;
10927
+ const { processLLMAnalysisResponse } = responseProcessor;
10928
+ const { validateLLMAnalysisData } = dataValidator;
10929
+
10930
+ var AnalyzerUtils$1 = {
10931
+ buildChatIdToPathMap,
10932
+ processLLMAnalysisResponse,
10933
+ validateLLMAnalysisData
10934
+ };
10935
+
10636
10936
  /**
10637
10937
  * Component: LLMUtils
10638
10938
  * Block-UUID: a3106054-42f1-474f-96f3-182d66eb19a0
@@ -10676,14 +10976,15 @@ var LLMUtils$1 = {
10676
10976
  */
10677
10977
 
10678
10978
  const ChatUtils = ChatUtils$1;
10679
- const CodeBlockUtils = CodeBlockUtils$2;
10680
- const ContextUtils = ContextUtils$1;
10681
- const MessageUtils = MessageUtils$2;
10682
- const AnalysisBlockUtils = AnalysisBlockUtils$2;
10979
+ const CodeBlockUtils = CodeBlockUtils$3;
10980
+ const ContextUtils = ContextUtils$2;
10981
+ const MessageUtils = MessageUtils$3;
10982
+ const AnalysisBlockUtils = AnalysisBlockUtils$3;
10983
+ const AnalyzerUtils = AnalyzerUtils$1;
10683
10984
  const PatchUtils = PatchUtils$2;
10684
- const GSToolBlockUtils = GSToolBlockUtils$2;
10985
+ const GSToolBlockUtils = GSToolBlockUtils$3;
10685
10986
  const LLMUtils = LLMUtils$1;
10686
- const JsonUtils = JsonUtils$1;
10987
+ const JsonUtils = JsonUtils$2;
10687
10988
 
10688
10989
  const {
10689
10990
  estimateTokens
@@ -11025,6 +11326,11 @@ var GitSenseChatUtils_1 = {
11025
11326
  parseOverviewMetadata,
11026
11327
  validateOverviewMetadata,
11027
11328
 
11329
+ // Analyzer Utilities
11330
+ buildChatIdToPathMap: AnalyzerUtils.buildChatIdToPathMap,
11331
+ processLLMAnalysisResponse: AnalyzerUtils.processLLMAnalysisResponse,
11332
+ validateLLMAnalysisData: AnalyzerUtils.validateLLMAnalysisData,
11333
+
11028
11334
  // ChatUtils
11029
11335
  getChatMessages,
11030
11336
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsense/gsc-utils",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Utilities for GitSense Chat (GSC)",
5
5
  "main": "dist/gsc-utils.cjs.js",
6
6
  "module": "dist/gsc-utils.esm.js",
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Component: AnalyzerUtils Constants
3
+ * Block-UUID: 01b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.0
6
+ * Description: Defines constants specific to the AnalyzerUtils module.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-08-28T15:56:40.319Z
9
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10
+ */
11
+
12
+
13
+ const ANALYZE_HEADER_PREFIX = '# GitSense Chat Analysis';
14
+
15
+ module.exports = {
16
+ ANALYZE_HEADER_PREFIX
17
+ };
@@ -0,0 +1,51 @@
1
+ /*
2
+ * Component: AnalyzerUtils Context Mapper
3
+ * Block-UUID: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.0
6
+ * Description: Provides utility functions for building a map of chat IDs to file paths from chat context messages.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-08-28T15:56:40.319Z
9
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10
+ */
11
+
12
+
13
+ const MessageUtils = require('../MessageUtils');
14
+ const ContextUtils = require('../ContextUtils');
15
+
16
+ /**
17
+ * Builds a map of chat IDs to file paths from the context messages within a chat.
18
+ * This is crucial for validating that the LLM-generated analysis metadata refers to actual files in context.
19
+ *
20
+ * @param {Array<Object>} allMessages - An array of all message objects in the chat.
21
+ * @returns {Map<number, string>} A Map where keys are chat IDs (numbers) and values are file paths (strings).
22
+ */
23
+ function buildChatIdToPathMap(allMessages) {
24
+ const chatIdToPathMap = new Map();
25
+
26
+ for (const msg of allMessages) {
27
+ const content = msg.message;
28
+ if (MessageUtils.isContextMessage(content)) {
29
+ try {
30
+ const contextSections = ContextUtils.extractContextSections(content);
31
+
32
+ for (const section of contextSections) {
33
+ const chatId = section['chat id'];
34
+ const path = section.path;
35
+
36
+ if (chatId && path) {
37
+ chatIdToPathMap.set(chatId, path);
38
+ }
39
+ }
40
+ } catch (error) {
41
+ console.warn("AnalyzerUtils/contextMapper: Error parsing context message for map building:", error);
42
+ // Continue processing other messages
43
+ }
44
+ }
45
+ }
46
+ return chatIdToPathMap;
47
+ }
48
+
49
+ module.exports = {
50
+ buildChatIdToPathMap
51
+ };