@gitsense/gsc-utils 0.2.0 → 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.
@@ -452,7 +452,7 @@ function parseAnalyzeMessage(messageContent) {
452
452
  return { id: uniqueAnalyzerId, analyzer, content, instructions };
453
453
  }
454
454
 
455
- var MessageUtils$2 = {
455
+ var MessageUtils$3 = {
456
456
  deleteMessagesByIds: deleteMessagesByIds$1,
457
457
  getChatTemplateMessages: getChatTemplateMessages$1,
458
458
  getMessagesBeforeId: getMessagesBeforeId$2,
@@ -478,7 +478,7 @@ var MessageUtils$2 = {
478
478
  * 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)
479
479
  */
480
480
 
481
- const { getMessagesBeforeId: getMessagesBeforeId$1 } = MessageUtils$2;
481
+ const { getMessagesBeforeId: getMessagesBeforeId$1 } = MessageUtils$3;
482
482
 
483
483
  /**
484
484
  * Internal helper function to determine if a chat session matches a specific pattern.
@@ -530,13 +530,21 @@ function isNewAnalyzerChat(chat, model) {
530
530
  /**
531
531
  * Determines if the current chat session appears to be an "Analyze" session.
532
532
  * @param {object} chat - The chat object.
533
- * @param {string} model - Optional model.
534
533
  * @returns {boolean} True if the chat matches the Overview Builder pattern, false otherwise.
535
534
  */
536
- function isAnalyzeChat(chat, model) {
535
+ function isAnalyzeChat(chat) {
537
536
  return chat.type === 'analyze';
538
537
  }
539
538
 
539
+ /**
540
+ * Determines if the current chat session appears to be an "Analyze Builder" session.
541
+ * @param {object} chat - The chat object.
542
+ * @returns {boolean} True if the chat matches the Overview Builder pattern, false otherwise.
543
+ */
544
+ function isAnalyzeBuilderChat(chat) {
545
+ return chat.type === 'analyze-builder';
546
+ }
547
+
540
548
  /**
541
549
  * Determines if the current chat session appears to be an "Ask" session.
542
550
  * @param {object} chat - The chat object.
@@ -588,6 +596,7 @@ var ChatUtils$1 = {
588
596
  isAskChat,
589
597
  isNewAnalyzerChat,
590
598
  isAnalyzeChat,
599
+ isAnalyzeBuilderChat,
591
600
  isPlanChat,
592
601
  isCodeChat,
593
602
  getChatMessages: getChatMessages$1
@@ -649,7 +658,7 @@ const COMMENT_STYLES$3 = {
649
658
  'vbscript': { type: 'apostrophe' }
650
659
  };
651
660
 
652
- var constants$1 = {
661
+ var constants$2 = {
653
662
  COMMENT_STYLES: COMMENT_STYLES$3
654
663
  };
655
664
 
@@ -829,7 +838,7 @@ var lineNumberFormatter = {
829
838
  */
830
839
 
831
840
  // Dependencies from other modules within CodeBlockUtils
832
- const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$1;
841
+ const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$2;
833
842
  const { removeLineNumbers: removeLineNumbers$9 } = lineNumberFormatter; // Assuming this utility exists
834
843
  const { validateUUID: validateUUID$3 } = uuidUtils; // Assuming uuidUtils.js is in the same directory
835
844
 
@@ -1451,7 +1460,7 @@ function validateAnalysisMetadata(metadata) {
1451
1460
  }
1452
1461
 
1453
1462
 
1454
- var AnalysisBlockUtils$2 = {
1463
+ var AnalysisBlockUtils$3 = {
1455
1464
  isAnalysisBlock,
1456
1465
  getAnalysisBlockType,
1457
1466
  parseOverviewMetadata: parseOverviewMetadata$1,
@@ -1784,7 +1793,7 @@ const CONTENT_LINE_REGEX$5 = /^([ +-])\s*[-+]*(\d+):\s?(.*)$/;
1784
1793
  // Captures: 1: old_start, 2: old_count (optional), 3: new_start, 4: new_count (optional)
1785
1794
  const HUNK_HEADER_REGEX$4 = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
1786
1795
 
1787
- var constants = {
1796
+ var constants$1 = {
1788
1797
  CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$5,
1789
1798
  HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$4,
1790
1799
  };
@@ -1801,7 +1810,7 @@ var constants = {
1801
1810
  */
1802
1811
 
1803
1812
  const { removeLineNumbers: removeLineNumbers$8 } = lineNumberFormatter; // Assuming this utility exists
1804
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$4, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$3 } = constants;
1813
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$4, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$3 } = constants$1;
1805
1814
 
1806
1815
 
1807
1816
  /**
@@ -1966,7 +1975,7 @@ var formatAndAddLineNumbers_1 = {
1966
1975
  */
1967
1976
 
1968
1977
  const { removeLineNumbers: removeLineNumbers$7 } = lineNumberFormatter; // Assuming this utility exists
1969
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$3 } = constants;
1978
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$3 } = constants$1;
1970
1979
  const { formatAndAddLineNumbers: formatAndAddLineNumbers$1 } = formatAndAddLineNumbers_1; // Import the helper
1971
1980
 
1972
1981
 
@@ -2219,7 +2228,7 @@ var verifyAndCorrectLineNumbers_1 = {
2219
2228
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2220
2229
  */
2221
2230
 
2222
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$2, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$2 } = constants;
2231
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$2, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$2 } = constants$1;
2223
2232
 
2224
2233
 
2225
2234
  /**
@@ -2418,7 +2427,7 @@ var verifyAndCorrectHunkHeaders_1 = {
2418
2427
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2419
2428
  */
2420
2429
 
2421
- const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$1, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$1 } = constants;
2430
+ const { CONTENT_LINE_REGEX: CONTENT_LINE_REGEX$1, HUNK_HEADER_REGEX: HUNK_HEADER_REGEX$1 } = constants$1;
2422
2431
 
2423
2432
 
2424
2433
  /**
@@ -2821,7 +2830,7 @@ var detectAndFixRedundantChanges_1 = {
2821
2830
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
2822
2831
  */
2823
2832
 
2824
- const { CONTENT_LINE_REGEX, HUNK_HEADER_REGEX } = constants;
2833
+ const { CONTENT_LINE_REGEX, HUNK_HEADER_REGEX } = constants$1;
2825
2834
 
2826
2835
 
2827
2836
  /**
@@ -8775,7 +8784,7 @@ function formatToolBlock(toolData) {
8775
8784
  return `# GitSense Chat Tool\n\n${JSON.stringify(toolData, null, 2)}`;
8776
8785
  }
8777
8786
 
8778
- var GSToolBlockUtils$2 = {
8787
+ var GSToolBlockUtils$3 = {
8779
8788
  isToolBlock: isToolBlock$1,
8780
8789
  parseToolBlock: parseToolBlock$1,
8781
8790
  formatToolBlock
@@ -9069,7 +9078,7 @@ function detectJsonComments$2(jsonString) {
9069
9078
  return comments;
9070
9079
  }
9071
9080
 
9072
- var JsonUtils$1 = {
9081
+ var JsonUtils$2 = {
9073
9082
  detectJsonComments: detectJsonComments$2
9074
9083
  };
9075
9084
 
@@ -9087,12 +9096,12 @@ var JsonUtils$1 = {
9087
9096
  const { findAllCodeFences: findAllCodeFences$3, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$3 } = blockExtractor;
9088
9097
  const { parseHeader: parseHeader$2 } = headerUtils;
9089
9098
  const { validateUUID: validateUUID$2, generateUUID: generateUUID$2 } = uuidUtils;
9090
- const AnalysisBlockUtils$1 = AnalysisBlockUtils$2;
9099
+ const AnalysisBlockUtils$2 = AnalysisBlockUtils$3;
9091
9100
  const PatchUtils$1 = PatchUtils$2;
9092
- const GSToolBlockUtils$1 = GSToolBlockUtils$2;
9101
+ const GSToolBlockUtils$2 = GSToolBlockUtils$3;
9093
9102
  const { extractContinuationInfo: extractContinuationInfo$2 } = continuationUtils;
9094
9103
  const { removeLineNumbers: removeLineNumbers$2 } = lineNumberFormatter;
9095
- const { detectJsonComments: detectJsonComments$1 } = JsonUtils$1;
9104
+ const { detectJsonComments: detectJsonComments$1 } = JsonUtils$2;
9096
9105
 
9097
9106
  /**
9098
9107
  * Processes a single block's content (internal helper)
@@ -9113,12 +9122,12 @@ function processBlockContent(content, language, position, incomplete, options =
9113
9122
  let codeText = content; // Default to all content being code
9114
9123
 
9115
9124
  // Check if this is a GitSense Tool Block *first*
9116
- if (GSToolBlockUtils$1.isToolBlock(content)) {
9125
+ if (GSToolBlockUtils$2.isToolBlock(content)) {
9117
9126
  let ignoreDueToComments = false;
9118
9127
  let toolData = null;
9119
9128
  let toolParseError = null;
9120
9129
  try {
9121
- toolData = GSToolBlockUtils$1.parseToolBlock(content);
9130
+ toolData = GSToolBlockUtils$2.parseToolBlock(content);
9122
9131
  } catch (error) {
9123
9132
  // When chatting about the tool block, the LLM may add
9124
9133
  // add comments in it so let's test for this
@@ -9152,14 +9161,14 @@ function processBlockContent(content, language, position, incomplete, options =
9152
9161
  }
9153
9162
 
9154
9163
  // Check if this is an analysis block *next*
9155
- if (AnalysisBlockUtils$1.isAnalysisBlock(content)) {
9156
- const analysisType = AnalysisBlockUtils$1.getAnalysisBlockType(content);
9157
- const analysisMetadata = AnalysisBlockUtils$1.parseOverviewMetadata(content);
9164
+ if (AnalysisBlockUtils$2.isAnalysisBlock(content)) {
9165
+ const analysisType = AnalysisBlockUtils$2.getAnalysisBlockType(content);
9166
+ const analysisMetadata = AnalysisBlockUtils$2.parseOverviewMetadata(content);
9158
9167
 
9159
9168
  // Validate the metadata if it was successfully parsed
9160
9169
  let validationResult = { isValid: false, errors: ['Failed to parse analysis metadata'] };
9161
9170
  if (analysisMetadata) {
9162
- validationResult = AnalysisBlockUtils$1.validateAnalysisMetadata(analysisMetadata);
9171
+ validationResult = AnalysisBlockUtils$2.validateAnalysisMetadata(analysisMetadata);
9163
9172
 
9164
9173
  if (!validationResult.isValid) {
9165
9174
  warnings.push({
@@ -10376,7 +10385,7 @@ var updateCodeBlock_1 = {
10376
10385
  */
10377
10386
 
10378
10387
  // Import from individual utility files
10379
- const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$1;
10388
+ const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$2;
10380
10389
  const { generateUUID: generateUUID$1, validateUUID: validateUUID$1 } = uuidUtils;
10381
10390
  const { isValidISOTimestamp: isValidISOTimestamp$1, parseHeader: parseHeader$1, getHeaderLineCount } = headerUtils;
10382
10391
  const { findAllCodeFences: findAllCodeFences$1, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$1, extractCodeBlocksWithUUIDs, findCodeBlockByUUID } = blockExtractor;
@@ -10390,7 +10399,7 @@ const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID,
10390
10399
  const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbers: formatBlockWithLineNumbers$1, formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1, removeLineNumbers: removeLineNumbers$1 } = lineNumberFormatter;
10391
10400
 
10392
10401
  // Export all imported items
10393
- var CodeBlockUtils$2 = {
10402
+ var CodeBlockUtils$3 = {
10394
10403
  // Constants
10395
10404
  COMMENT_STYLES: COMMENT_STYLES$1,
10396
10405
 
@@ -10457,8 +10466,8 @@ var CodeBlockUtils$2 = {
10457
10466
  * Authors: Gemini 2.5 Flash Thinking (v1.0.0)
10458
10467
  */
10459
10468
 
10460
- const CodeBlockUtils$1 = CodeBlockUtils$2;
10461
- const MessageUtils$1 = MessageUtils$2;
10469
+ const CodeBlockUtils$2 = CodeBlockUtils$3;
10470
+ const MessageUtils$2 = MessageUtils$3;
10462
10471
 
10463
10472
  /**
10464
10473
  * Parses context details from a context message section.
@@ -10514,7 +10523,7 @@ function parseContextSection(sectionText) {
10514
10523
  }
10515
10524
  });
10516
10525
 
10517
- const { blocks, warnings } = CodeBlockUtils$1.extractCodeBlocks(sectionText, { silent: true });
10526
+ const { blocks, warnings } = CodeBlockUtils$2.extractCodeBlocks(sectionText, { silent: true });
10518
10527
  const codeBlocks = blocks.filter(block => block.type === 'code');
10519
10528
 
10520
10529
  if (codeBlocks.length === 0) {
@@ -10543,7 +10552,7 @@ function parseContextSection(sectionText) {
10543
10552
  */
10544
10553
  function extractContextSections(messageContent) {
10545
10554
  // Use the utility function to validate the message type
10546
- if (!MessageUtils$1.isContextMessage(messageContent)) {
10555
+ if (!MessageUtils$2.isContextMessage(messageContent)) {
10547
10556
  throw new Error("Invalid message type: Content is not a context message.");
10548
10557
  }
10549
10558
 
@@ -10620,12 +10629,312 @@ function extractContextItemsOverviewTableRows(messageContent) {
10620
10629
  return rows;
10621
10630
  }
10622
10631
 
10623
- var ContextUtils$1 = {
10632
+ var ContextUtils$2 = {
10624
10633
  parseContextSection,
10625
10634
  extractContextSections,
10626
10635
  extractContextItemsOverviewTableRows
10627
10636
  };
10628
10637
 
10638
+ /*
10639
+ * Component: AnalyzerUtils Context Mapper
10640
+ * Block-UUID: 1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d
10641
+ * Parent-UUID: N/A
10642
+ * Version: 1.0.0
10643
+ * Description: Provides utility functions for building a map of chat IDs to file paths from chat context messages.
10644
+ * Language: JavaScript
10645
+ * Created-at: 2025-08-28T15:56:40.319Z
10646
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10647
+ */
10648
+
10649
+ const MessageUtils$1 = MessageUtils$3;
10650
+ const ContextUtils$1 = ContextUtils$2;
10651
+
10652
+ /**
10653
+ * Builds a map of chat IDs to file paths from the context messages within a chat.
10654
+ * This is crucial for validating that the LLM-generated analysis metadata refers to actual files in context.
10655
+ *
10656
+ * @param {Array<Object>} allMessages - An array of all message objects in the chat.
10657
+ * @returns {Map<number, string>} A Map where keys are chat IDs (numbers) and values are file paths (strings).
10658
+ */
10659
+ function buildChatIdToPathMap$1(allMessages) {
10660
+ const chatIdToPathMap = new Map();
10661
+
10662
+ for (const msg of allMessages) {
10663
+ const content = msg.message;
10664
+ if (MessageUtils$1.isContextMessage(content)) {
10665
+ try {
10666
+ const contextSections = ContextUtils$1.extractContextSections(content);
10667
+
10668
+ for (const section of contextSections) {
10669
+ const chatId = section['chat id'];
10670
+ const path = section.path;
10671
+
10672
+ if (chatId && path) {
10673
+ chatIdToPathMap.set(chatId, path);
10674
+ }
10675
+ }
10676
+ } catch (error) {
10677
+ console.warn("AnalyzerUtils/contextMapper: Error parsing context message for map building:", error);
10678
+ // Continue processing other messages
10679
+ }
10680
+ }
10681
+ }
10682
+ return chatIdToPathMap;
10683
+ }
10684
+
10685
+ var contextMapper = {
10686
+ buildChatIdToPathMap: buildChatIdToPathMap$1
10687
+ };
10688
+
10689
+ /*
10690
+ * Component: AnalyzerUtils Constants
10691
+ * Block-UUID: 01b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
10692
+ * Parent-UUID: N/A
10693
+ * Version: 1.0.0
10694
+ * Description: Defines constants specific to the AnalyzerUtils module.
10695
+ * Language: JavaScript
10696
+ * Created-at: 2025-08-28T15:56:40.319Z
10697
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10698
+ */
10699
+
10700
+ const ANALYZE_HEADER_PREFIX$1 = '# GitSense Chat Analysis';
10701
+
10702
+ var constants = {
10703
+ ANALYZE_HEADER_PREFIX: ANALYZE_HEADER_PREFIX$1
10704
+ };
10705
+
10706
+ /*
10707
+ * Component: AnalyzerUtils Response Processor
10708
+ * Block-UUID: 2a3b4c5d-6e7f-4a8b-9c0d-1e2f3a4b5c6d
10709
+ * Parent-UUID: N/A
10710
+ * Version: 1.0.0
10711
+ * Description: Extracts and performs initial validation of analysis and metadata code blocks from raw LLM message content.
10712
+ * Language: JavaScript
10713
+ * Created-at: 2025-08-28T15:56:40.319Z
10714
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10715
+ */
10716
+
10717
+ const CodeBlockUtils$1 = CodeBlockUtils$3;
10718
+ const GSToolBlockUtils$1 = GSToolBlockUtils$3;
10719
+ const JsonUtils$1 = JsonUtils$2;
10720
+ const { ANALYZE_HEADER_PREFIX } = constants;
10721
+
10722
+ /**
10723
+ * Extracts code blocks from the message content, identifies analysis and metadata blocks,
10724
+ * and performs initial validation (block type, metadata presence, JSON format).
10725
+ * This function is adapted from the original `blockProcessing.js` in `gsc-conversation-view`.
10726
+ *
10727
+ * @param {string} messageContent - The full content of the message.
10728
+ * @param {boolean} stoppedStreaming - Flag indicating if the message streaming has stopped.
10729
+ * @returns {{analysisBlocks: Array<Object>, analysisMetadataBlocks: Array<Object|null>, error: string|null}}
10730
+ * An object containing the extracted blocks and any processing error.
10731
+ */
10732
+ function processLLMAnalysisResponse$1(messageContent, stoppedStreaming) {
10733
+ const silent = { silent: true };
10734
+ const { blocks, warnings } = CodeBlockUtils$1.extractCodeBlocks(messageContent, silent);
10735
+
10736
+ const analysisBlocks = [];
10737
+ const analysisMetadataBlocks = [];
10738
+ let error = null;
10739
+
10740
+ for (let i = 0; i < blocks.length; i += 2) {
10741
+ const analysisBlock = blocks[i];
10742
+
10743
+ // Make sure this is an analysis block by checking its content
10744
+ if (!analysisBlock.content.trimStart().startsWith(ANALYZE_HEADER_PREFIX)) {
10745
+ // Also check if it's a GitSense Tool Block, which should be ignored by this analyzer
10746
+ if (GSToolBlockUtils$1.isToolBlock(analysisBlock.content)) {
10747
+ // If it's a tool block, it's not an analysis block, so skip it and don't treat as error
10748
+ // Adjust index to skip this block and its potential "metadata" if it was paired
10749
+ if (blocks[i+1] && blocks[i+1].language === 'json') {
10750
+ i += 1; // Skip the next block too if it's a JSON block (likely tool config)
10751
+ }
10752
+ continue;
10753
+ }
10754
+
10755
+ if (stoppedStreaming) {
10756
+ error = `Analysis block #${i} does not start with the "${ANALYZE_HEADER_PREFIX}" header.`;
10757
+ }
10758
+ // If we are still streaming, we may not have enough information to tell what type
10759
+ // of block this is, so stop looking
10760
+ break;
10761
+ }
10762
+
10763
+ // Add the analysis block (Markdown overview)
10764
+ analysisBlocks.push(analysisBlock);
10765
+
10766
+ // Make sure there is an analysis metadata block (JSON)
10767
+ const analysisMetadataBlock = blocks[i + 1];
10768
+
10769
+ if (!analysisMetadataBlock) {
10770
+ if (stoppedStreaming) {
10771
+ error = `No analysis metadata found for analysis block (index ${i}).`;
10772
+ } else {
10773
+ // Add a null metadata block to let use know we are still streaming
10774
+ analysisMetadataBlocks.push(null);
10775
+ }
10776
+ break;
10777
+ }
10778
+
10779
+ // We found a code block but we don't know if it is valid or not
10780
+ // 1. First make sure the code block is a JSON type
10781
+ // 2. Try to parse the JSON
10782
+ if (analysisMetadataBlock.language !== 'json') {
10783
+ if (stoppedStreaming) {
10784
+ error = `Analysis metadata block for "${analysisBlock.overviewMetadata?.Path || 'Unknown Path'}" has invalid language "${analysisMetadataBlock.language}". Expected "json".`;
10785
+ } else {
10786
+ // Add a null metadata block to let use know we are still streaming
10787
+ analysisMetadataBlocks.push(null);
10788
+ }
10789
+ break;
10790
+ }
10791
+
10792
+ try {
10793
+ // Check for comments within JSON, which would make it invalid for direct parsing
10794
+ const comments = JsonUtils$1.detectJsonComments(analysisMetadataBlock.content);
10795
+ if (comments.length > 0) {
10796
+ error = `The analysis metadata block for "${analysisBlock.overviewMetadata?.Path || 'Unknown Path'}" contains comments, which makes it invalid JSON.`;
10797
+ if (stoppedStreaming || blocks[i + 2]) { // If streaming stopped or not the last block
10798
+ break;
10799
+ } else {
10800
+ analysisMetadataBlocks.push(null); // Add null to keep arrays aligned
10801
+ return { analysisBlocks, analysisMetadataBlocks, error: null };
10802
+ }
10803
+ }
10804
+
10805
+ JSON.parse(analysisMetadataBlock.content.trim());
10806
+ analysisMetadataBlocks.push(analysisMetadataBlock);
10807
+ } catch (err) {
10808
+ const path = analysisBlock.overviewMetadata?.Path || 'Unknown Path';
10809
+ error = `The analysis metadata block for "${path}" contains an invalid JSON: ${err.message}`;
10810
+
10811
+ // If streaming has stopped or if this is not the last block, set error and break.
10812
+ // Remember to increment by two since every second block is the meta block.
10813
+ if (stoppedStreaming || blocks[i + 2]) {
10814
+ break;
10815
+ } else {
10816
+ // Do nothing since the error is most certaintly due to the fact that we are still
10817
+ // streaming the JSON
10818
+ analysisMetadataBlocks.push(null); // Add null to keep arrays aligned
10819
+ return { analysisBlocks, analysisMetadataBlocks, error: null };
10820
+ }
10821
+ }
10822
+ }
10823
+
10824
+ // If streaming stopped and no overview blocks were found, set an error
10825
+ if (stoppedStreaming && analysisBlocks.length === 0) {
10826
+ error = 'Analysis stopped without producing any data.';
10827
+ }
10828
+
10829
+ return { analysisBlocks, analysisMetadataBlocks, error };
10830
+ }
10831
+
10832
+ var responseProcessor = {
10833
+ processLLMAnalysisResponse: processLLMAnalysisResponse$1
10834
+ };
10835
+
10836
+ /*
10837
+ * Component: AnalyzerUtils Data Validator
10838
+ * Block-UUID: 1317cc51-fca0-49b7-9e4b-b3e1a06ab93f
10839
+ * Parent-UUID: N/A
10840
+ * Version: 1.0.0
10841
+ * Description: Validates extracted analysis data against chat context and expected schema.
10842
+ * Language: JavaScript
10843
+ * Created-at: 2025-08-28T15:56:40.319Z
10844
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10845
+ */
10846
+
10847
+ const AnalysisBlockUtils$1 = AnalysisBlockUtils$3;
10848
+
10849
+ /**
10850
+ * Validates the extracted analysis blocks and their metadata.
10851
+ * Checks for valid chat IDs/paths and uses AnalysisBlockUtils for further metadata validation.
10852
+ * This function is adapted from the original `analysisValidation.js` in `gsc-conversation-view`.
10853
+ *
10854
+ * @param {Array<Object>} analysisBlocks - Array of extracted analysis code blocks (Markdown overviews).
10855
+ * @param {Array<Object|null>} analysisMetadataBlocks - Array of extracted analysis metadata blocks (JSON).
10856
+ * @param {Map<number, string>} chatIdToPathMap - Map of chat IDs to file paths from context messages.
10857
+ * @returns {{validAnalysisData: Array<Object>, invalidAnalysisBlocks: Array<string|Object>}}
10858
+ * An object containing arrays of valid analysis data and invalid analysis blocks.
10859
+ */
10860
+ function validateLLMAnalysisData$1(analysisBlocks, analysisMetadataBlocks, chatIdToPathMap) {
10861
+ const validAnalysisData = []; // Store data for the "Save All" button
10862
+ const invalidAnalysisBlocks = []; // Store invalid analysis blocks
10863
+
10864
+ analysisBlocks.forEach((block, index) => {
10865
+ // Ensure metadata is parsed from the block's content for initial checks
10866
+ const overviewMetadata = AnalysisBlockUtils$1.parseOverviewMetadata(block.content);
10867
+ const metadataBlock = analysisMetadataBlocks[index];
10868
+ const isDone = metadataBlock ? true : false; // Check if metadata block was successfully processed
10869
+
10870
+ // Skip if metadata block is missing (still streaming or error)
10871
+ if (!overviewMetadata || !isDone) {
10872
+ // If metadata block is missing but streaming stopped, it's an error handled in responseProcessor
10873
+ // If overviewMetadata is missing, it's an error handled in responseProcessor
10874
+ return;
10875
+ }
10876
+
10877
+ const chatId = overviewMetadata['Chat ID'];
10878
+ const path = overviewMetadata['Path'];
10879
+
10880
+ // Is this a valid chat id and path id? Some LLMs will actually hallucinate this
10881
+ if (!chatId || !path || !chatIdToPathMap.has(chatId)) {
10882
+ invalidAnalysisBlocks.push(`<li>#${chatId || 'N/A'} => ${path || 'N/A'} (Invalid Chat ID or Path)</li>`);
10883
+ return;
10884
+ }
10885
+
10886
+ // Perform detailed metadata validation using AnalysisBlockUtils
10887
+ const validation = AnalysisBlockUtils$1.validateAnalysisMetadata(overviewMetadata);
10888
+
10889
+ if (validation.isValid) {
10890
+ // Prepare data for API call (map keys if necessary)
10891
+ const analysisData = {
10892
+ chatId: overviewMetadata['Chat ID'],
10893
+ // The original analyzeHandler used 'Message ID', 'Repository', 'Summarized At', 'Analyze At',
10894
+ // 'Summary', 'Key Functionality', 'Keywords' from overviewMetadata.
10895
+ // For batch processing, we primarily need chatId, content, and the full JSON metadata.
10896
+ // The other fields can be derived from the full JSON metadata if needed.
10897
+ path: overviewMetadata['Path'],
10898
+ content: block.content, // The full Markdown overview
10899
+ type: AnalysisBlockUtils$1.getAnalysisBlockType(block.content), // e.g., 'tiny-overview::file-content::default'
10900
+ // We know metadataBlock.content is a valid JSON from responseProcessor
10901
+ metadata: JSON.parse(metadataBlock.content) // The full JSON metadata object
10902
+ };
10903
+ validAnalysisData.push(analysisData); // Add to list for saving
10904
+ } else {
10905
+ // Add invalid analysis block with validation details
10906
+ invalidAnalysisBlocks.push({ block, validation });
10907
+ }
10908
+ });
10909
+
10910
+ return { validAnalysisData, invalidAnalysisBlocks };
10911
+ }
10912
+
10913
+ var dataValidator = {
10914
+ validateLLMAnalysisData: validateLLMAnalysisData$1
10915
+ };
10916
+
10917
+ /*
10918
+ * Component: AnalyzerUtils Index
10919
+ * Block-UUID: b403b6a1-230b-4247-8cd6-2a3d068f4bbf
10920
+ * Parent-UUID: N/A
10921
+ * Version: 1.0.0
10922
+ * Description: Aggregates and exports all utility functions from the AnalyzerUtils module.
10923
+ * Language: JavaScript
10924
+ * Created-at: 2025-08-28T15:56:40.319Z
10925
+ * Authors: Gemini 2.5 Flash (v1.0.0)
10926
+ */
10927
+
10928
+ const { buildChatIdToPathMap } = contextMapper;
10929
+ const { processLLMAnalysisResponse } = responseProcessor;
10930
+ const { validateLLMAnalysisData } = dataValidator;
10931
+
10932
+ var AnalyzerUtils$1 = {
10933
+ buildChatIdToPathMap,
10934
+ processLLMAnalysisResponse,
10935
+ validateLLMAnalysisData
10936
+ };
10937
+
10629
10938
  /**
10630
10939
  * Component: LLMUtils
10631
10940
  * Block-UUID: a3106054-42f1-474f-96f3-182d66eb19a0
@@ -10669,14 +10978,15 @@ var LLMUtils$1 = {
10669
10978
  */
10670
10979
 
10671
10980
  const ChatUtils = ChatUtils$1;
10672
- const CodeBlockUtils = CodeBlockUtils$2;
10673
- const ContextUtils = ContextUtils$1;
10674
- const MessageUtils = MessageUtils$2;
10675
- const AnalysisBlockUtils = AnalysisBlockUtils$2;
10981
+ const CodeBlockUtils = CodeBlockUtils$3;
10982
+ const ContextUtils = ContextUtils$2;
10983
+ const MessageUtils = MessageUtils$3;
10984
+ const AnalysisBlockUtils = AnalysisBlockUtils$3;
10985
+ const AnalyzerUtils = AnalyzerUtils$1;
10676
10986
  const PatchUtils = PatchUtils$2;
10677
- const GSToolBlockUtils = GSToolBlockUtils$2;
10987
+ const GSToolBlockUtils = GSToolBlockUtils$3;
10678
10988
  const LLMUtils = LLMUtils$1;
10679
- const JsonUtils = JsonUtils$1;
10989
+ const JsonUtils = JsonUtils$2;
10680
10990
 
10681
10991
  const {
10682
10992
  estimateTokens
@@ -11018,6 +11328,11 @@ var GitSenseChatUtils_1 = {
11018
11328
  parseOverviewMetadata,
11019
11329
  validateOverviewMetadata,
11020
11330
 
11331
+ // Analyzer Utilities
11332
+ buildChatIdToPathMap: AnalyzerUtils.buildChatIdToPathMap,
11333
+ processLLMAnalysisResponse: AnalyzerUtils.processLLMAnalysisResponse,
11334
+ validateLLMAnalysisData: AnalyzerUtils.validateLLMAnalysisData,
11335
+
11021
11336
  // ChatUtils
11022
11337
  getChatMessages,
11023
11338