@gitsense/gsc-utils 0.2.8 → 0.2.10
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.
- package/dist/gsc-utils.cjs.js +182 -15
- package/dist/gsc-utils.esm.js +182 -15
- package/package.json +1 -1
- package/src/ContextUtils.js +163 -5
- package/src/GitSenseChatUtils.js +14 -4
package/dist/gsc-utils.cjs.js
CHANGED
|
@@ -10455,26 +10455,108 @@ var CodeBlockUtils$4 = {
|
|
|
10455
10455
|
removeLineNumbers: removeLineNumbers$1,
|
|
10456
10456
|
};
|
|
10457
10457
|
|
|
10458
|
-
|
|
10458
|
+
/*
|
|
10459
10459
|
* Component: ContextUtils
|
|
10460
10460
|
* Block-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
10461
10461
|
* Parent-UUID: N/A
|
|
10462
|
-
* Version: 1.
|
|
10463
|
-
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks.
|
|
10462
|
+
* Version: 1.1.0
|
|
10463
|
+
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
10464
10464
|
* Language: JavaScript
|
|
10465
10465
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
10466
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0)
|
|
10466
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10467
10467
|
*/
|
|
10468
10468
|
|
|
10469
10469
|
const CodeBlockUtils$3 = CodeBlockUtils$4;
|
|
10470
10470
|
const MessageUtils$2 = MessageUtils$3;
|
|
10471
10471
|
|
|
10472
|
+
/**
|
|
10473
|
+
* Formats bytes into human-readable string (KB, MB, GB)
|
|
10474
|
+
* @param {number} bytes - Number of bytes
|
|
10475
|
+
* @returns {string} Formatted size string
|
|
10476
|
+
*/
|
|
10477
|
+
function _formatBytes(bytes) {
|
|
10478
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
|
|
10479
|
+
if (bytes === 0) return '0 bytes';
|
|
10480
|
+
|
|
10481
|
+
const k = 1024;
|
|
10482
|
+
const sizes = ['bytes', 'KB', 'MB', 'GB'];
|
|
10483
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
10484
|
+
|
|
10485
|
+
// Special case for bytes (no decimal)
|
|
10486
|
+
if (i === 0) return `${bytes} ${sizes[i]}`;
|
|
10487
|
+
|
|
10488
|
+
const value = bytes / Math.pow(k, i);
|
|
10489
|
+
// Show no decimal if whole number
|
|
10490
|
+
const decimalPlaces = value % 1 === 0 ? 0 : 1;
|
|
10491
|
+
return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
|
|
10492
|
+
}
|
|
10493
|
+
|
|
10494
|
+
/**
|
|
10495
|
+
* Creates a summary of items for human readers
|
|
10496
|
+
* @param {Array} items - Array of loaded items
|
|
10497
|
+
* @param {string} contentType - Content type
|
|
10498
|
+
* @returns {string} Human-readable summary
|
|
10499
|
+
*/
|
|
10500
|
+
function _createContextSummary(items, contentType) {
|
|
10501
|
+
if (items.length === 0) return '';
|
|
10502
|
+
|
|
10503
|
+
// Group by files and trees
|
|
10504
|
+
const files = items.filter(item => item.metadata?.type === 'git-blob');
|
|
10505
|
+
const trees = items.filter(item => item.metadata?.type === 'git-tree' || item.metadata?.type === 'git-ref');
|
|
10506
|
+
|
|
10507
|
+
// Calculate total size and tokens
|
|
10508
|
+
const totalSize = items.reduce((sum, item) => sum + (item.size || 0), 0);
|
|
10509
|
+
const totalTokens = items.reduce((sum, item) => sum + (item.tokenCount || 0), 0);
|
|
10510
|
+
|
|
10511
|
+
let summary = contentType === 'file content'
|
|
10512
|
+
? `\n**Summary:** ${items.length} file${items.length === 1 ? '' : 's'} (${_formatBytes(totalSize)}, ${totalTokens.toLocaleString()} tokens)\n\n`
|
|
10513
|
+
: `\n**Summary:** ${files.length} file${files.length === 1 ? '' : 's'} - ${trees.length} tree${trees.length === 1 ? '' : 's'}\n\n`;
|
|
10514
|
+
|
|
10515
|
+
// Add brief description of first X files
|
|
10516
|
+
const maxFiles = 10;
|
|
10517
|
+
const displayItems = items.slice(0, maxFiles);
|
|
10518
|
+
if (displayItems.length > 0) {
|
|
10519
|
+
displayItems.forEach(item => {
|
|
10520
|
+
if (item.tokenCount) {
|
|
10521
|
+
summary += `- ${item.name} - ${_formatBytes(item.size)}, ${item.tokenCount.toLocaleString()} tokens\n`;
|
|
10522
|
+
} else {
|
|
10523
|
+
summary += `- ${item.name} - Not analyzed\n`;
|
|
10524
|
+
}
|
|
10525
|
+
});
|
|
10526
|
+
|
|
10527
|
+
// Add note if there are more files
|
|
10528
|
+
if (items.length > maxFiles) {
|
|
10529
|
+
summary += `- ... and ${items.length - maxFiles} more\n`;
|
|
10530
|
+
}
|
|
10531
|
+
}
|
|
10532
|
+
|
|
10533
|
+
return summary + "\n";
|
|
10534
|
+
}
|
|
10535
|
+
|
|
10536
|
+
/**
|
|
10537
|
+
* Escapes backticks in code blocks to prevent premature termination of LLM-generated code blocks.
|
|
10538
|
+
* @param {string} content - The content string to escape.
|
|
10539
|
+
* @returns {{escapedContent: string, escapedLineNums: Array<number>}} Object with escaped content and line numbers of escaped lines.
|
|
10540
|
+
*/
|
|
10541
|
+
function _escapeCodeBlocks(content) {
|
|
10542
|
+
const escapedLineNums = [];
|
|
10543
|
+
const escapedLines = content.replace(/\n$/, '').split('\n').map((line, i) => {
|
|
10544
|
+
if (line.trimStart().startsWith('```')) {
|
|
10545
|
+
line = '\\' + line.trimStart();
|
|
10546
|
+
escapedLineNums.push(i + 1);
|
|
10547
|
+
}
|
|
10548
|
+
return line;
|
|
10549
|
+
});
|
|
10550
|
+
return { escapedContent: escapedLines.join('\n'), escapedLineNums };
|
|
10551
|
+
}
|
|
10552
|
+
|
|
10553
|
+
|
|
10472
10554
|
/**
|
|
10473
10555
|
* Parses context details from a context message section.
|
|
10474
10556
|
* @param {string} sectionText - The text content of a single context section (starting from the file header).
|
|
10475
10557
|
* @returns {Object|null} An object with file details (name, path, meta, content) or null if parsing fails.
|
|
10476
10558
|
*/
|
|
10477
|
-
function parseContextSection(sectionText) {
|
|
10559
|
+
function parseContextSection$1(sectionText) {
|
|
10478
10560
|
const contextSection = {
|
|
10479
10561
|
name: 'Unknown File',
|
|
10480
10562
|
content: null,
|
|
@@ -10550,7 +10632,7 @@ function parseContextSection(sectionText) {
|
|
|
10550
10632
|
* @returns {Array<Object>} An array of parsed context section objects.
|
|
10551
10633
|
* @throws {Error} If the message content is not a valid context message.
|
|
10552
10634
|
*/
|
|
10553
|
-
function extractContextSections(messageContent) {
|
|
10635
|
+
function extractContextSections$1(messageContent) {
|
|
10554
10636
|
// Use the utility function to validate the message type
|
|
10555
10637
|
if (!MessageUtils$2.isContextMessage(messageContent)) {
|
|
10556
10638
|
throw new Error("Invalid message type: Content is not a context message.");
|
|
@@ -10564,7 +10646,7 @@ function extractContextSections(messageContent) {
|
|
|
10564
10646
|
|
|
10565
10647
|
// Process sections starting from the first potential path delimiter.
|
|
10566
10648
|
for (let i = 0; i < sections.length; i++) {
|
|
10567
|
-
const contextSection = parseContextSection(sections[i]);
|
|
10649
|
+
const contextSection = parseContextSection$1(sections[i]);
|
|
10568
10650
|
|
|
10569
10651
|
if (contextSection) {
|
|
10570
10652
|
contextSections.push(contextSection);
|
|
@@ -10579,7 +10661,7 @@ function extractContextSections(messageContent) {
|
|
|
10579
10661
|
return contextSections;
|
|
10580
10662
|
}
|
|
10581
10663
|
|
|
10582
|
-
function extractContextItemsOverviewTableRows(messageContent) {
|
|
10664
|
+
function extractContextItemsOverviewTableRows$1(messageContent) {
|
|
10583
10665
|
const lines = messageContent.trim().split('\n');
|
|
10584
10666
|
const startIndex = lines.findIndex(line => line.startsWith('---Start of Overview Items---')) + 4;
|
|
10585
10667
|
|
|
@@ -10629,10 +10711,85 @@ function extractContextItemsOverviewTableRows(messageContent) {
|
|
|
10629
10711
|
return rows;
|
|
10630
10712
|
}
|
|
10631
10713
|
|
|
10714
|
+
/**
|
|
10715
|
+
* Formats content for context based on content type.
|
|
10716
|
+
* This function is adapted from the original `formatContentForContext` in `formatterUtils.js`.
|
|
10717
|
+
*
|
|
10718
|
+
* @param {Array<Object>} items - Array of loaded items, each with `chatId`, `name`, `content`, `meta`, `repo` (from chatsApi.getBlobDetailsByChatIds).
|
|
10719
|
+
* @param {string} contentType - Type of content ('file content' or 'overview'). For batch analysis, always 'file content'.
|
|
10720
|
+
* @param {string} contentOption - Option for the content type. For batch analysis, always 'imported'.
|
|
10721
|
+
* @returns {string} Formatted text for context.
|
|
10722
|
+
*/
|
|
10723
|
+
function formatContextContent$1(items, contentType, contentOption) {
|
|
10724
|
+
if (items.length === 0) {
|
|
10725
|
+
return 'No content loaded';
|
|
10726
|
+
}
|
|
10727
|
+
|
|
10728
|
+
let result = '';
|
|
10729
|
+
|
|
10730
|
+
// Header based on content type
|
|
10731
|
+
if (contentType === 'overview') {
|
|
10732
|
+
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
10733
|
+
} else {
|
|
10734
|
+
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
10735
|
+
}
|
|
10736
|
+
|
|
10737
|
+
// Summary of items
|
|
10738
|
+
result += _createContextSummary(items, contentType);
|
|
10739
|
+
result += "\n---Start of Context---\n\n";
|
|
10740
|
+
|
|
10741
|
+
items.forEach((item, index) => {
|
|
10742
|
+
// Ensure item has necessary properties, especially meta and repo
|
|
10743
|
+
const itemMeta = item.meta || {};
|
|
10744
|
+
const itemRepo = item.repo || {};
|
|
10745
|
+
|
|
10746
|
+
result += "#### `"+item.name+"`\n";
|
|
10747
|
+
|
|
10748
|
+
const { escapedContent, escapedLineNums } = _escapeCodeBlocks(item.content);
|
|
10749
|
+
|
|
10750
|
+
// Always include metadata for batch analysis context
|
|
10751
|
+
result +=
|
|
10752
|
+
`- Repo: ${itemRepo.fullName || 'N/A'}\n`+
|
|
10753
|
+
`- Path: ${item.path || 'N/A'}\n`;
|
|
10754
|
+
|
|
10755
|
+
// Size and Tokens are specific to 'file content'
|
|
10756
|
+
if (contentType === 'file content') {
|
|
10757
|
+
result += `- Size: ${_formatBytes(item.size)}\n`;
|
|
10758
|
+
result += `- Tokens: ${item.tokenCount || 'N/A'}\n`;
|
|
10759
|
+
} else {
|
|
10760
|
+
const type = item.type || 'unknown';
|
|
10761
|
+
result += `- Type: ${type === 'git-blob' ? 'file' : type === 'git-tree' || type === 'git-ref' ? 'directory' : type }\n`;
|
|
10762
|
+
result += `- Tokens: ${itemMeta.tokens?.analysis?.[contentOption.toLowerCase()]?.estimate || 'N/A'}\n`;
|
|
10763
|
+
}
|
|
10764
|
+
|
|
10765
|
+
result += `- Chat ID: ${item.chatId}\n`;
|
|
10766
|
+
|
|
10767
|
+
if (escapedLineNums.length) {
|
|
10768
|
+
result += `- Escaped Lines: ${escapedLineNums.join(',')}\n`;
|
|
10769
|
+
}
|
|
10770
|
+
|
|
10771
|
+
result += '\n';
|
|
10772
|
+
|
|
10773
|
+
// The original formatterUtils had a special summary handling.
|
|
10774
|
+
// For batch analysis, we want the full file content.
|
|
10775
|
+
// The `if (!escapedContent.includes('Component: New Analyzer Chat') && escapedContent.match(summary))`
|
|
10776
|
+
// logic is specific to the frontend's overview builder and should not be applied here.
|
|
10777
|
+
result += "```"+(itemMeta.highlight || '')+"\n"+escapedContent+"\n```";
|
|
10778
|
+
|
|
10779
|
+
if (index !== items.length - 1) {
|
|
10780
|
+
result += '\n---End of Item---\n';
|
|
10781
|
+
}
|
|
10782
|
+
});
|
|
10783
|
+
|
|
10784
|
+
return result;
|
|
10785
|
+
}
|
|
10786
|
+
|
|
10787
|
+
|
|
10632
10788
|
var ContextUtils$2 = {
|
|
10633
|
-
parseContextSection,
|
|
10634
|
-
extractContextSections,
|
|
10635
|
-
extractContextItemsOverviewTableRows
|
|
10789
|
+
parseContextSection: parseContextSection$1,
|
|
10790
|
+
extractContextSections: extractContextSections$1,
|
|
10791
|
+
extractContextItemsOverviewTableRows: extractContextItemsOverviewTableRows$1,
|
|
10792
|
+
formatContextContent: formatContextContent$1,
|
|
10636
10793
|
};
|
|
10637
10794
|
|
|
10638
10795
|
/*
|
|
@@ -11849,11 +12006,11 @@ var EnvUtils$1 = {
|
|
|
11849
12006
|
* Component: GitSenseChatUtils
|
|
11850
12007
|
* Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
|
|
11851
12008
|
* Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
|
|
11852
|
-
* Version: 2.1.
|
|
12009
|
+
* Version: 2.1.4
|
|
11853
12010
|
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils and EnvUtils.
|
|
11854
12011
|
* Language: JavaScript
|
|
11855
12012
|
* Created-at: 2025-04-15T16:04:26.780Z
|
|
11856
|
-
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3)
|
|
12013
|
+
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4)
|
|
11857
12014
|
*/
|
|
11858
12015
|
|
|
11859
12016
|
const ChatUtils = ChatUtils$1;
|
|
@@ -11970,6 +12127,13 @@ const {
|
|
|
11970
12127
|
getApiKey
|
|
11971
12128
|
} = EnvUtils;
|
|
11972
12129
|
|
|
12130
|
+
const {
|
|
12131
|
+
parseContextSection,
|
|
12132
|
+
extractContextSections,
|
|
12133
|
+
extractContextItemsOverviewTableRows,
|
|
12134
|
+
formatContextContent,
|
|
12135
|
+
} = ContextUtils;
|
|
12136
|
+
|
|
11973
12137
|
|
|
11974
12138
|
/**
|
|
11975
12139
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
@@ -12280,8 +12444,11 @@ var GitSenseChatUtils_1 = {
|
|
|
12280
12444
|
loadEnv,
|
|
12281
12445
|
getApiKey,
|
|
12282
12446
|
|
|
12283
|
-
//
|
|
12284
|
-
|
|
12447
|
+
// Context Utils
|
|
12448
|
+
parseContextSection,
|
|
12449
|
+
extractContextSections,
|
|
12450
|
+
extractContextItemsOverviewTableRows,
|
|
12451
|
+
formatContextContent,
|
|
12285
12452
|
};
|
|
12286
12453
|
|
|
12287
12454
|
var GitSenseChatUtils$1 = /*@__PURE__*/getDefaultExportFromCjs(GitSenseChatUtils_1);
|
package/dist/gsc-utils.esm.js
CHANGED
|
@@ -10453,26 +10453,108 @@ var CodeBlockUtils$4 = {
|
|
|
10453
10453
|
removeLineNumbers: removeLineNumbers$1,
|
|
10454
10454
|
};
|
|
10455
10455
|
|
|
10456
|
-
|
|
10456
|
+
/*
|
|
10457
10457
|
* Component: ContextUtils
|
|
10458
10458
|
* Block-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
10459
10459
|
* Parent-UUID: N/A
|
|
10460
|
-
* Version: 1.
|
|
10461
|
-
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks.
|
|
10460
|
+
* Version: 1.1.0
|
|
10461
|
+
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
10462
10462
|
* Language: JavaScript
|
|
10463
10463
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
10464
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0)
|
|
10464
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10465
10465
|
*/
|
|
10466
10466
|
|
|
10467
10467
|
const CodeBlockUtils$3 = CodeBlockUtils$4;
|
|
10468
10468
|
const MessageUtils$2 = MessageUtils$3;
|
|
10469
10469
|
|
|
10470
|
+
/**
|
|
10471
|
+
* Formats bytes into human-readable string (KB, MB, GB)
|
|
10472
|
+
* @param {number} bytes - Number of bytes
|
|
10473
|
+
* @returns {string} Formatted size string
|
|
10474
|
+
*/
|
|
10475
|
+
function _formatBytes(bytes) {
|
|
10476
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
|
|
10477
|
+
if (bytes === 0) return '0 bytes';
|
|
10478
|
+
|
|
10479
|
+
const k = 1024;
|
|
10480
|
+
const sizes = ['bytes', 'KB', 'MB', 'GB'];
|
|
10481
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
10482
|
+
|
|
10483
|
+
// Special case for bytes (no decimal)
|
|
10484
|
+
if (i === 0) return `${bytes} ${sizes[i]}`;
|
|
10485
|
+
|
|
10486
|
+
const value = bytes / Math.pow(k, i);
|
|
10487
|
+
// Show no decimal if whole number
|
|
10488
|
+
const decimalPlaces = value % 1 === 0 ? 0 : 1;
|
|
10489
|
+
return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
|
|
10490
|
+
}
|
|
10491
|
+
|
|
10492
|
+
/**
|
|
10493
|
+
* Creates a summary of items for human readers
|
|
10494
|
+
* @param {Array} items - Array of loaded items
|
|
10495
|
+
* @param {string} contentType - Content type
|
|
10496
|
+
* @returns {string} Human-readable summary
|
|
10497
|
+
*/
|
|
10498
|
+
function _createContextSummary(items, contentType) {
|
|
10499
|
+
if (items.length === 0) return '';
|
|
10500
|
+
|
|
10501
|
+
// Group by files and trees
|
|
10502
|
+
const files = items.filter(item => item.metadata?.type === 'git-blob');
|
|
10503
|
+
const trees = items.filter(item => item.metadata?.type === 'git-tree' || item.metadata?.type === 'git-ref');
|
|
10504
|
+
|
|
10505
|
+
// Calculate total size and tokens
|
|
10506
|
+
const totalSize = items.reduce((sum, item) => sum + (item.size || 0), 0);
|
|
10507
|
+
const totalTokens = items.reduce((sum, item) => sum + (item.tokenCount || 0), 0);
|
|
10508
|
+
|
|
10509
|
+
let summary = contentType === 'file content'
|
|
10510
|
+
? `\n**Summary:** ${items.length} file${items.length === 1 ? '' : 's'} (${_formatBytes(totalSize)}, ${totalTokens.toLocaleString()} tokens)\n\n`
|
|
10511
|
+
: `\n**Summary:** ${files.length} file${files.length === 1 ? '' : 's'} - ${trees.length} tree${trees.length === 1 ? '' : 's'}\n\n`;
|
|
10512
|
+
|
|
10513
|
+
// Add brief description of first X files
|
|
10514
|
+
const maxFiles = 10;
|
|
10515
|
+
const displayItems = items.slice(0, maxFiles);
|
|
10516
|
+
if (displayItems.length > 0) {
|
|
10517
|
+
displayItems.forEach(item => {
|
|
10518
|
+
if (item.tokenCount) {
|
|
10519
|
+
summary += `- ${item.name} - ${_formatBytes(item.size)}, ${item.tokenCount.toLocaleString()} tokens\n`;
|
|
10520
|
+
} else {
|
|
10521
|
+
summary += `- ${item.name} - Not analyzed\n`;
|
|
10522
|
+
}
|
|
10523
|
+
});
|
|
10524
|
+
|
|
10525
|
+
// Add note if there are more files
|
|
10526
|
+
if (items.length > maxFiles) {
|
|
10527
|
+
summary += `- ... and ${items.length - maxFiles} more\n`;
|
|
10528
|
+
}
|
|
10529
|
+
}
|
|
10530
|
+
|
|
10531
|
+
return summary + "\n";
|
|
10532
|
+
}
|
|
10533
|
+
|
|
10534
|
+
/**
|
|
10535
|
+
* Escapes backticks in code blocks to prevent premature termination of LLM-generated code blocks.
|
|
10536
|
+
* @param {string} content - The content string to escape.
|
|
10537
|
+
* @returns {{escapedContent: string, escapedLineNums: Array<number>}} Object with escaped content and line numbers of escaped lines.
|
|
10538
|
+
*/
|
|
10539
|
+
function _escapeCodeBlocks(content) {
|
|
10540
|
+
const escapedLineNums = [];
|
|
10541
|
+
const escapedLines = content.replace(/\n$/, '').split('\n').map((line, i) => {
|
|
10542
|
+
if (line.trimStart().startsWith('```')) {
|
|
10543
|
+
line = '\\' + line.trimStart();
|
|
10544
|
+
escapedLineNums.push(i + 1);
|
|
10545
|
+
}
|
|
10546
|
+
return line;
|
|
10547
|
+
});
|
|
10548
|
+
return { escapedContent: escapedLines.join('\n'), escapedLineNums };
|
|
10549
|
+
}
|
|
10550
|
+
|
|
10551
|
+
|
|
10470
10552
|
/**
|
|
10471
10553
|
* Parses context details from a context message section.
|
|
10472
10554
|
* @param {string} sectionText - The text content of a single context section (starting from the file header).
|
|
10473
10555
|
* @returns {Object|null} An object with file details (name, path, meta, content) or null if parsing fails.
|
|
10474
10556
|
*/
|
|
10475
|
-
function parseContextSection(sectionText) {
|
|
10557
|
+
function parseContextSection$1(sectionText) {
|
|
10476
10558
|
const contextSection = {
|
|
10477
10559
|
name: 'Unknown File',
|
|
10478
10560
|
content: null,
|
|
@@ -10548,7 +10630,7 @@ function parseContextSection(sectionText) {
|
|
|
10548
10630
|
* @returns {Array<Object>} An array of parsed context section objects.
|
|
10549
10631
|
* @throws {Error} If the message content is not a valid context message.
|
|
10550
10632
|
*/
|
|
10551
|
-
function extractContextSections(messageContent) {
|
|
10633
|
+
function extractContextSections$1(messageContent) {
|
|
10552
10634
|
// Use the utility function to validate the message type
|
|
10553
10635
|
if (!MessageUtils$2.isContextMessage(messageContent)) {
|
|
10554
10636
|
throw new Error("Invalid message type: Content is not a context message.");
|
|
@@ -10562,7 +10644,7 @@ function extractContextSections(messageContent) {
|
|
|
10562
10644
|
|
|
10563
10645
|
// Process sections starting from the first potential path delimiter.
|
|
10564
10646
|
for (let i = 0; i < sections.length; i++) {
|
|
10565
|
-
const contextSection = parseContextSection(sections[i]);
|
|
10647
|
+
const contextSection = parseContextSection$1(sections[i]);
|
|
10566
10648
|
|
|
10567
10649
|
if (contextSection) {
|
|
10568
10650
|
contextSections.push(contextSection);
|
|
@@ -10577,7 +10659,7 @@ function extractContextSections(messageContent) {
|
|
|
10577
10659
|
return contextSections;
|
|
10578
10660
|
}
|
|
10579
10661
|
|
|
10580
|
-
function extractContextItemsOverviewTableRows(messageContent) {
|
|
10662
|
+
function extractContextItemsOverviewTableRows$1(messageContent) {
|
|
10581
10663
|
const lines = messageContent.trim().split('\n');
|
|
10582
10664
|
const startIndex = lines.findIndex(line => line.startsWith('---Start of Overview Items---')) + 4;
|
|
10583
10665
|
|
|
@@ -10627,10 +10709,85 @@ function extractContextItemsOverviewTableRows(messageContent) {
|
|
|
10627
10709
|
return rows;
|
|
10628
10710
|
}
|
|
10629
10711
|
|
|
10712
|
+
/**
|
|
10713
|
+
* Formats content for context based on content type.
|
|
10714
|
+
* This function is adapted from the original `formatContentForContext` in `formatterUtils.js`.
|
|
10715
|
+
*
|
|
10716
|
+
* @param {Array<Object>} items - Array of loaded items, each with `chatId`, `name`, `content`, `meta`, `repo` (from chatsApi.getBlobDetailsByChatIds).
|
|
10717
|
+
* @param {string} contentType - Type of content ('file content' or 'overview'). For batch analysis, always 'file content'.
|
|
10718
|
+
* @param {string} contentOption - Option for the content type. For batch analysis, always 'imported'.
|
|
10719
|
+
* @returns {string} Formatted text for context.
|
|
10720
|
+
*/
|
|
10721
|
+
function formatContextContent$1(items, contentType, contentOption) {
|
|
10722
|
+
if (items.length === 0) {
|
|
10723
|
+
return 'No content loaded';
|
|
10724
|
+
}
|
|
10725
|
+
|
|
10726
|
+
let result = '';
|
|
10727
|
+
|
|
10728
|
+
// Header based on content type
|
|
10729
|
+
if (contentType === 'overview') {
|
|
10730
|
+
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
10731
|
+
} else {
|
|
10732
|
+
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
10733
|
+
}
|
|
10734
|
+
|
|
10735
|
+
// Summary of items
|
|
10736
|
+
result += _createContextSummary(items, contentType);
|
|
10737
|
+
result += "\n---Start of Context---\n\n";
|
|
10738
|
+
|
|
10739
|
+
items.forEach((item, index) => {
|
|
10740
|
+
// Ensure item has necessary properties, especially meta and repo
|
|
10741
|
+
const itemMeta = item.meta || {};
|
|
10742
|
+
const itemRepo = item.repo || {};
|
|
10743
|
+
|
|
10744
|
+
result += "#### `"+item.name+"`\n";
|
|
10745
|
+
|
|
10746
|
+
const { escapedContent, escapedLineNums } = _escapeCodeBlocks(item.content);
|
|
10747
|
+
|
|
10748
|
+
// Always include metadata for batch analysis context
|
|
10749
|
+
result +=
|
|
10750
|
+
`- Repo: ${itemRepo.fullName || 'N/A'}\n`+
|
|
10751
|
+
`- Path: ${item.path || 'N/A'}\n`;
|
|
10752
|
+
|
|
10753
|
+
// Size and Tokens are specific to 'file content'
|
|
10754
|
+
if (contentType === 'file content') {
|
|
10755
|
+
result += `- Size: ${_formatBytes(item.size)}\n`;
|
|
10756
|
+
result += `- Tokens: ${item.tokenCount || 'N/A'}\n`;
|
|
10757
|
+
} else {
|
|
10758
|
+
const type = item.type || 'unknown';
|
|
10759
|
+
result += `- Type: ${type === 'git-blob' ? 'file' : type === 'git-tree' || type === 'git-ref' ? 'directory' : type }\n`;
|
|
10760
|
+
result += `- Tokens: ${itemMeta.tokens?.analysis?.[contentOption.toLowerCase()]?.estimate || 'N/A'}\n`;
|
|
10761
|
+
}
|
|
10762
|
+
|
|
10763
|
+
result += `- Chat ID: ${item.chatId}\n`;
|
|
10764
|
+
|
|
10765
|
+
if (escapedLineNums.length) {
|
|
10766
|
+
result += `- Escaped Lines: ${escapedLineNums.join(',')}\n`;
|
|
10767
|
+
}
|
|
10768
|
+
|
|
10769
|
+
result += '\n';
|
|
10770
|
+
|
|
10771
|
+
// The original formatterUtils had a special summary handling.
|
|
10772
|
+
// For batch analysis, we want the full file content.
|
|
10773
|
+
// The `if (!escapedContent.includes('Component: New Analyzer Chat') && escapedContent.match(summary))`
|
|
10774
|
+
// logic is specific to the frontend's overview builder and should not be applied here.
|
|
10775
|
+
result += "```"+(itemMeta.highlight || '')+"\n"+escapedContent+"\n```";
|
|
10776
|
+
|
|
10777
|
+
if (index !== items.length - 1) {
|
|
10778
|
+
result += '\n---End of Item---\n';
|
|
10779
|
+
}
|
|
10780
|
+
});
|
|
10781
|
+
|
|
10782
|
+
return result;
|
|
10783
|
+
}
|
|
10784
|
+
|
|
10785
|
+
|
|
10630
10786
|
var ContextUtils$2 = {
|
|
10631
|
-
parseContextSection,
|
|
10632
|
-
extractContextSections,
|
|
10633
|
-
extractContextItemsOverviewTableRows
|
|
10787
|
+
parseContextSection: parseContextSection$1,
|
|
10788
|
+
extractContextSections: extractContextSections$1,
|
|
10789
|
+
extractContextItemsOverviewTableRows: extractContextItemsOverviewTableRows$1,
|
|
10790
|
+
formatContextContent: formatContextContent$1,
|
|
10634
10791
|
};
|
|
10635
10792
|
|
|
10636
10793
|
/*
|
|
@@ -11847,11 +12004,11 @@ var EnvUtils$1 = {
|
|
|
11847
12004
|
* Component: GitSenseChatUtils
|
|
11848
12005
|
* Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
|
|
11849
12006
|
* Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
|
|
11850
|
-
* Version: 2.1.
|
|
12007
|
+
* Version: 2.1.4
|
|
11851
12008
|
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils and EnvUtils.
|
|
11852
12009
|
* Language: JavaScript
|
|
11853
12010
|
* Created-at: 2025-04-15T16:04:26.780Z
|
|
11854
|
-
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3)
|
|
12011
|
+
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4)
|
|
11855
12012
|
*/
|
|
11856
12013
|
|
|
11857
12014
|
const ChatUtils = ChatUtils$1;
|
|
@@ -11968,6 +12125,13 @@ const {
|
|
|
11968
12125
|
getApiKey
|
|
11969
12126
|
} = EnvUtils;
|
|
11970
12127
|
|
|
12128
|
+
const {
|
|
12129
|
+
parseContextSection,
|
|
12130
|
+
extractContextSections,
|
|
12131
|
+
extractContextItemsOverviewTableRows,
|
|
12132
|
+
formatContextContent,
|
|
12133
|
+
} = ContextUtils;
|
|
12134
|
+
|
|
11971
12135
|
|
|
11972
12136
|
/**
|
|
11973
12137
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
@@ -12278,8 +12442,11 @@ var GitSenseChatUtils_1 = {
|
|
|
12278
12442
|
loadEnv,
|
|
12279
12443
|
getApiKey,
|
|
12280
12444
|
|
|
12281
|
-
//
|
|
12282
|
-
|
|
12445
|
+
// Context Utils
|
|
12446
|
+
parseContextSection,
|
|
12447
|
+
extractContextSections,
|
|
12448
|
+
extractContextItemsOverviewTableRows,
|
|
12449
|
+
formatContextContent,
|
|
12283
12450
|
};
|
|
12284
12451
|
|
|
12285
12452
|
var GitSenseChatUtils$1 = /*@__PURE__*/getDefaultExportFromCjs(GitSenseChatUtils_1);
|
package/package.json
CHANGED
package/src/ContextUtils.js
CHANGED
|
@@ -1,18 +1,100 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
2
|
* Component: ContextUtils
|
|
3
3
|
* Block-UUID: c199efe3-003c-4226-af3c-d460392a6569
|
|
4
4
|
* Parent-UUID: N/A
|
|
5
|
-
* Version: 1.
|
|
6
|
-
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks.
|
|
5
|
+
* Version: 1.1.0
|
|
6
|
+
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
7
7
|
* Language: JavaScript
|
|
8
8
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
9
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0)
|
|
9
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
const CodeBlockUtils = require('./CodeBlockUtils');
|
|
14
14
|
const MessageUtils = require('./MessageUtils');
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Formats bytes into human-readable string (KB, MB, GB)
|
|
18
|
+
* @param {number} bytes - Number of bytes
|
|
19
|
+
* @returns {string} Formatted size string
|
|
20
|
+
*/
|
|
21
|
+
function _formatBytes(bytes) {
|
|
22
|
+
if (typeof bytes !== 'number' || isNaN(bytes)) return '0 bytes';
|
|
23
|
+
if (bytes === 0) return '0 bytes';
|
|
24
|
+
|
|
25
|
+
const k = 1024;
|
|
26
|
+
const sizes = ['bytes', 'KB', 'MB', 'GB'];
|
|
27
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
28
|
+
|
|
29
|
+
// Special case for bytes (no decimal)
|
|
30
|
+
if (i === 0) return `${bytes} ${sizes[i]}`;
|
|
31
|
+
|
|
32
|
+
const value = bytes / Math.pow(k, i);
|
|
33
|
+
// Show no decimal if whole number
|
|
34
|
+
const decimalPlaces = value % 1 === 0 ? 0 : 1;
|
|
35
|
+
return `${value.toFixed(decimalPlaces)} ${sizes[i]}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a summary of items for human readers
|
|
40
|
+
* @param {Array} items - Array of loaded items
|
|
41
|
+
* @param {string} contentType - Content type
|
|
42
|
+
* @returns {string} Human-readable summary
|
|
43
|
+
*/
|
|
44
|
+
function _createContextSummary(items, contentType) {
|
|
45
|
+
if (items.length === 0) return '';
|
|
46
|
+
|
|
47
|
+
// Group by files and trees
|
|
48
|
+
const files = items.filter(item => item.metadata?.type === 'git-blob');
|
|
49
|
+
const trees = items.filter(item => item.metadata?.type === 'git-tree' || item.metadata?.type === 'git-ref');
|
|
50
|
+
|
|
51
|
+
// Calculate total size and tokens
|
|
52
|
+
const totalSize = items.reduce((sum, item) => sum + (item.size || 0), 0);
|
|
53
|
+
const totalTokens = items.reduce((sum, item) => sum + (item.tokenCount || 0), 0);
|
|
54
|
+
|
|
55
|
+
let summary = contentType === 'file content'
|
|
56
|
+
? `\n**Summary:** ${items.length} file${items.length === 1 ? '' : 's'} (${_formatBytes(totalSize)}, ${totalTokens.toLocaleString()} tokens)\n\n`
|
|
57
|
+
: `\n**Summary:** ${files.length} file${files.length === 1 ? '' : 's'} - ${trees.length} tree${trees.length === 1 ? '' : 's'}\n\n`;
|
|
58
|
+
|
|
59
|
+
// Add brief description of first X files
|
|
60
|
+
const maxFiles = 10;
|
|
61
|
+
const displayItems = items.slice(0, maxFiles);
|
|
62
|
+
if (displayItems.length > 0) {
|
|
63
|
+
displayItems.forEach(item => {
|
|
64
|
+
if (item.tokenCount) {
|
|
65
|
+
summary += `- ${item.name} - ${_formatBytes(item.size)}, ${item.tokenCount.toLocaleString()} tokens\n`;
|
|
66
|
+
} else {
|
|
67
|
+
summary += `- ${item.name} - Not analyzed\n`;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Add note if there are more files
|
|
72
|
+
if (items.length > maxFiles) {
|
|
73
|
+
summary += `- ... and ${items.length - maxFiles} more\n`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return summary + "\n";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Escapes backticks in code blocks to prevent premature termination of LLM-generated code blocks.
|
|
82
|
+
* @param {string} content - The content string to escape.
|
|
83
|
+
* @returns {{escapedContent: string, escapedLineNums: Array<number>}} Object with escaped content and line numbers of escaped lines.
|
|
84
|
+
*/
|
|
85
|
+
function _escapeCodeBlocks(content) {
|
|
86
|
+
const escapedLineNums = [];
|
|
87
|
+
const escapedLines = content.replace(/\n$/, '').split('\n').map((line, i) => {
|
|
88
|
+
if (line.trimStart().startsWith('```')) {
|
|
89
|
+
line = '\\' + line.trimStart();
|
|
90
|
+
escapedLineNums.push(i + 1);
|
|
91
|
+
}
|
|
92
|
+
return line;
|
|
93
|
+
});
|
|
94
|
+
return { escapedContent: escapedLines.join('\n'), escapedLineNums };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
16
98
|
/**
|
|
17
99
|
* Parses context details from a context message section.
|
|
18
100
|
* @param {string} sectionText - The text content of a single context section (starting from the file header).
|
|
@@ -173,8 +255,84 @@ function extractContextItemsOverviewTableRows(messageContent) {
|
|
|
173
255
|
return rows;
|
|
174
256
|
}
|
|
175
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Formats content for context based on content type.
|
|
260
|
+
* This function is adapted from the original `formatContentForContext` in `formatterUtils.js`.
|
|
261
|
+
*
|
|
262
|
+
* @param {Array<Object>} items - Array of loaded items, each with `chatId`, `name`, `content`, `meta`, `repo` (from chatsApi.getBlobDetailsByChatIds).
|
|
263
|
+
* @param {string} contentType - Type of content ('file content' or 'overview'). For batch analysis, always 'file content'.
|
|
264
|
+
* @param {string} contentOption - Option for the content type. For batch analysis, always 'imported'.
|
|
265
|
+
* @returns {string} Formatted text for context.
|
|
266
|
+
*/
|
|
267
|
+
function formatContextContent(items, contentType, contentOption) {
|
|
268
|
+
if (items.length === 0) {
|
|
269
|
+
return 'No content loaded';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let result = '';
|
|
273
|
+
|
|
274
|
+
// Header based on content type
|
|
275
|
+
if (contentType === 'overview') {
|
|
276
|
+
const label = contentOption === "long" ? "comprehensive" : "short";
|
|
277
|
+
result += `## OVERVIEW - ${contentOption.toUpperCase()}\n`;
|
|
278
|
+
} else {
|
|
279
|
+
result += `## FILE CONTENT - ${contentOption.toUpperCase()}\n`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Summary of items
|
|
283
|
+
result += _createContextSummary(items, contentType);
|
|
284
|
+
result += "\n---Start of Context---\n\n";
|
|
285
|
+
|
|
286
|
+
items.forEach((item, index) => {
|
|
287
|
+
// Ensure item has necessary properties, especially meta and repo
|
|
288
|
+
const itemMeta = item.meta || {};
|
|
289
|
+
const itemRepo = item.repo || {};
|
|
290
|
+
|
|
291
|
+
result += "#### `"+item.name+"`\n";
|
|
292
|
+
|
|
293
|
+
const { escapedContent, escapedLineNums } = _escapeCodeBlocks(item.content);
|
|
294
|
+
|
|
295
|
+
// Always include metadata for batch analysis context
|
|
296
|
+
result +=
|
|
297
|
+
`- Repo: ${itemRepo.fullName || 'N/A'}\n`+
|
|
298
|
+
`- Path: ${item.path || 'N/A'}\n`;
|
|
299
|
+
|
|
300
|
+
// Size and Tokens are specific to 'file content'
|
|
301
|
+
if (contentType === 'file content') {
|
|
302
|
+
result += `- Size: ${_formatBytes(item.size)}\n`;
|
|
303
|
+
result += `- Tokens: ${item.tokenCount || 'N/A'}\n`;
|
|
304
|
+
} else {
|
|
305
|
+
const type = item.type || 'unknown';
|
|
306
|
+
result += `- Type: ${type === 'git-blob' ? 'file' : type === 'git-tree' || type === 'git-ref' ? 'directory' : type }\n`;
|
|
307
|
+
result += `- Tokens: ${itemMeta.tokens?.analysis?.[contentOption.toLowerCase()]?.estimate || 'N/A'}\n`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
result += `- Chat ID: ${item.chatId}\n`;
|
|
311
|
+
|
|
312
|
+
if (escapedLineNums.length) {
|
|
313
|
+
result += `- Escaped Lines: ${escapedLineNums.join(',')}\n`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
result += '\n';
|
|
317
|
+
|
|
318
|
+
// The original formatterUtils had a special summary handling.
|
|
319
|
+
// For batch analysis, we want the full file content.
|
|
320
|
+
// The `if (!escapedContent.includes('Component: New Analyzer Chat') && escapedContent.match(summary))`
|
|
321
|
+
// logic is specific to the frontend's overview builder and should not be applied here.
|
|
322
|
+
result += "```"+(itemMeta.highlight || '')+"\n"+escapedContent+"\n```";
|
|
323
|
+
|
|
324
|
+
if (index !== items.length - 1) {
|
|
325
|
+
result += '\n---End of Item---\n';
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
176
333
|
module.exports = {
|
|
177
334
|
parseContextSection,
|
|
178
335
|
extractContextSections,
|
|
179
|
-
extractContextItemsOverviewTableRows
|
|
336
|
+
extractContextItemsOverviewTableRows,
|
|
337
|
+
formatContextContent,
|
|
180
338
|
};
|
package/src/GitSenseChatUtils.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Component: GitSenseChatUtils
|
|
3
3
|
* Block-UUID: 5e8d1a9c-0b3f-4e1a-8c7d-9f0b2e1d3a4b
|
|
4
4
|
* Parent-UUID: 7a9b1c8e-f1a4-4b2d-9e8f-6f7a0b1c2d3f
|
|
5
|
-
* Version: 2.1.
|
|
5
|
+
* Version: 2.1.4
|
|
6
6
|
* Description: Interface class for GitSense Chat utilities providing a unified API for code block parsing (markdown), extraction, and patch operations. Integrates functionalities from CodeBlockUtils and PatchUtils modules, and now includes ConfigUtils and EnvUtils.
|
|
7
7
|
* Language: JavaScript
|
|
8
8
|
* Created-at: 2025-04-15T16:04:26.780Z
|
|
9
|
-
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3)
|
|
9
|
+
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v2.0.0), Gemini 2.5 Pro (v2.1.0), Gemini 2.5 Pro (v2.1.1), Gemini 2.5 Flash (v2.1.2), Gemini 2.5 Flash (v2.1.3), Gemini 2.5 Flash (v2.1.4)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
|
|
@@ -124,6 +124,13 @@ const {
|
|
|
124
124
|
getApiKey
|
|
125
125
|
} = EnvUtils;
|
|
126
126
|
|
|
127
|
+
const {
|
|
128
|
+
parseContextSection,
|
|
129
|
+
extractContextSections,
|
|
130
|
+
extractContextItemsOverviewTableRows,
|
|
131
|
+
formatContextContent,
|
|
132
|
+
} = ContextUtils;
|
|
133
|
+
|
|
127
134
|
|
|
128
135
|
/**
|
|
129
136
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
@@ -434,6 +441,9 @@ module.exports = {
|
|
|
434
441
|
loadEnv,
|
|
435
442
|
getApiKey,
|
|
436
443
|
|
|
437
|
-
//
|
|
438
|
-
|
|
444
|
+
// Context Utils
|
|
445
|
+
parseContextSection,
|
|
446
|
+
extractContextSections,
|
|
447
|
+
extractContextItemsOverviewTableRows,
|
|
448
|
+
formatContextContent,
|
|
439
449
|
};
|