@gitsense/gsc-utils 0.2.25 → 0.2.28
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/README.md +380 -62
- package/dist/gsc-utils.cjs.js +2290 -326
- package/dist/gsc-utils.esm.js +2290 -326
- package/package.json +1 -1
- package/src/AnalyzerUtils/cloner.js +149 -0
- package/src/AnalyzerUtils/constants.js +1 -1
- package/src/AnalyzerUtils/defaultPromptLoader.js +10 -10
- package/src/AnalyzerUtils/discovery.js +48 -39
- package/src/AnalyzerUtils/index.js +13 -7
- package/src/AnalyzerUtils/instructionLoader.js +6 -6
- package/src/AnalyzerUtils/jsonParser.js +35 -0
- package/src/AnalyzerUtils/management.js +6 -6
- package/src/AnalyzerUtils/saver.js +5 -5
- package/src/AnalyzerUtils/schemaLoader.js +194 -26
- package/src/AnalyzerUtils/updater.js +187 -0
- package/src/CodeBlockUtils/blockProcessor.js +14 -32
- package/src/CodeBlockUtils/index.js +7 -6
- package/src/CodeBlockUtils/lineageTracer.js +95 -0
- package/src/CompactChatUtils/CompactedMessageUtils.js +224 -0
- package/src/CompactChatUtils/README.md +321 -0
- package/src/CompactChatUtils/ReferenceMessageUtils.js +143 -0
- package/src/CompactChatUtils/index.js +40 -0
- package/src/ContextUtils.js +40 -4
- package/src/DomUtils.js +102 -14
- package/src/FormatterUtils.js +1 -1
- package/src/GSToolBlockUtils.js +66 -1
- package/src/GitSenseChatUtils.js +58 -5
- package/src/LLMUtils.js +1 -1
- package/src/MarkdownUtils.js +4 -1
- package/src/MessageUtils.js +1 -1
- package/src/MetaRawResultUtils.js +244 -0
- package/src/PatchUtils/constants.js +9 -3
- package/src/PatchUtils/patchParser.js +60 -36
- package/src/PatchUtils/patchVerifier/detectAndFixOverlappingHunks.js +1 -1
- package/src/PatchUtils/patchVerifier/detectAndFixRedundantChanges.js +1 -1
- package/src/PatchUtils/patchVerifier/verifyAndCorrectHunkHeaders.js +1 -1
- package/src/SVGUtils.js +137 -2
- package/src/SharedUtils/stringUtils.js +303 -0
- package/src/CodeBlockUtils/blockProcessor.js.rej +0 -8
package/dist/gsc-utils.cjs.js
CHANGED
|
@@ -45,8 +45,8 @@ function getAugmentedNamespace(n) {
|
|
|
45
45
|
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0)
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
|
-
const fs$
|
|
49
|
-
const path$
|
|
48
|
+
const fs$9 = require$$0;
|
|
49
|
+
const path$7 = require$$1;
|
|
50
50
|
const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -80,12 +80,12 @@ function unescapeCodeBlocks(content) {
|
|
|
80
80
|
* @returns {Array} An array of message objects with role and content properties
|
|
81
81
|
*/
|
|
82
82
|
function getChatTemplateMessages$1(dirname, messageType) {
|
|
83
|
-
const messagesDir = messageType ? path$
|
|
83
|
+
const messagesDir = messageType ? path$7.join(dirname, messageType) : dirname;
|
|
84
84
|
const messages = [];
|
|
85
85
|
|
|
86
86
|
try {
|
|
87
87
|
// Read all files in the directory
|
|
88
|
-
const files = fs$
|
|
88
|
+
const files = fs$9.readdirSync(messagesDir);
|
|
89
89
|
|
|
90
90
|
// Sort files numerically (1.md, 2.md, etc.)
|
|
91
91
|
const sortedFiles = files.sort((a, b) => {
|
|
@@ -96,9 +96,9 @@ function getChatTemplateMessages$1(dirname, messageType) {
|
|
|
96
96
|
|
|
97
97
|
// Process each file
|
|
98
98
|
for (const file of sortedFiles) {
|
|
99
|
-
if (path$
|
|
100
|
-
const filePath = path$
|
|
101
|
-
const fileContent = fs$
|
|
99
|
+
if (path$7.extname(file) === '.md') {
|
|
100
|
+
const filePath = path$7.join(messagesDir, file);
|
|
101
|
+
const fileContent = fs$9.readFileSync(filePath, 'utf8');
|
|
102
102
|
|
|
103
103
|
// Split by triple newline to separate metadata from content
|
|
104
104
|
const parts = fileContent.split('\n\n\n');
|
|
@@ -398,7 +398,7 @@ function getMessageContentType$1(messageContent) {
|
|
|
398
398
|
return 'regular'; // Handle non-string input gracefully
|
|
399
399
|
}
|
|
400
400
|
const trimmedContent = messageContent.trimStart(); // Check from the beginning, ignoring leading whitespace
|
|
401
|
-
if (trimmedContent.startsWith('## FILE CONTENT')) {
|
|
401
|
+
if (trimmedContent.startsWith('## FILE CONTENT') || trimmedContent.startsWith('## REFERENCE FILE CONTENT')) {
|
|
402
402
|
return 'file-content-context';
|
|
403
403
|
} else if (trimmedContent.startsWith('## OVERVIEW')) {
|
|
404
404
|
return 'overview-context';
|
|
@@ -619,7 +619,7 @@ function getChatMessages$1(chat, model) {
|
|
|
619
619
|
return getMessagesBeforeId$1(model || chat.main_model, chat.messages[0], null);
|
|
620
620
|
}
|
|
621
621
|
|
|
622
|
-
var ChatUtils$
|
|
622
|
+
var ChatUtils$2 = {
|
|
623
623
|
isAskChat,
|
|
624
624
|
isNewAnalyzerChat,
|
|
625
625
|
isAnalyzeChat,
|
|
@@ -691,7 +691,7 @@ const COMMENT_STYLES$3 = {
|
|
|
691
691
|
'vbscript': { type: 'apostrophe' }
|
|
692
692
|
};
|
|
693
693
|
|
|
694
|
-
var constants$
|
|
694
|
+
var constants$3 = {
|
|
695
695
|
COMMENT_STYLES: COMMENT_STYLES$3
|
|
696
696
|
};
|
|
697
697
|
|
|
@@ -710,7 +710,7 @@ var constants$2 = {
|
|
|
710
710
|
* Generates a valid RFC 4122 UUID v4
|
|
711
711
|
* @returns {string} A valid UUID v4
|
|
712
712
|
*/
|
|
713
|
-
function generateUUID$
|
|
713
|
+
function generateUUID$2() {
|
|
714
714
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
715
715
|
const r = Math.random() * 16 | 0;
|
|
716
716
|
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
@@ -729,7 +729,7 @@ function validateUUID$4(uuid) {
|
|
|
729
729
|
if (!uuidPattern.test(uuid)) {
|
|
730
730
|
return {
|
|
731
731
|
"Block-UUID": "INVALID UUID",
|
|
732
|
-
"Correct Block-UUID": generateUUID$
|
|
732
|
+
"Correct Block-UUID": generateUUID$2()
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
735
|
|
|
@@ -739,7 +739,7 @@ function validateUUID$4(uuid) {
|
|
|
739
739
|
}
|
|
740
740
|
|
|
741
741
|
var uuidUtils = {
|
|
742
|
-
generateUUID: generateUUID$
|
|
742
|
+
generateUUID: generateUUID$2,
|
|
743
743
|
validateUUID: validateUUID$4
|
|
744
744
|
};
|
|
745
745
|
|
|
@@ -871,7 +871,7 @@ var lineNumberFormatter = {
|
|
|
871
871
|
*/
|
|
872
872
|
|
|
873
873
|
// Dependencies from other modules within CodeBlockUtils
|
|
874
|
-
const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$
|
|
874
|
+
const { COMMENT_STYLES: COMMENT_STYLES$2 } = constants$3;
|
|
875
875
|
const { removeLineNumbers: removeLineNumbers$9 } = lineNumberFormatter; // Assuming this utility exists
|
|
876
876
|
const { validateUUID: validateUUID$3 } = uuidUtils; // Assuming uuidUtils.js is in the same directory
|
|
877
877
|
|
|
@@ -1540,24 +1540,63 @@ function isValidVersion$1(version) {
|
|
|
1540
1540
|
var versionUtils = {
|
|
1541
1541
|
isValidVersion: isValidVersion$1};
|
|
1542
1542
|
|
|
1543
|
+
/**
|
|
1544
|
+
* Component: PatchUtils Constants
|
|
1545
|
+
* Block-UUID: c6747054-2c8b-461f-910d-0fd725d9a350
|
|
1546
|
+
* Parent-UUID: 32adc00e-7509-4219-8e40-6c1319371db9
|
|
1547
|
+
* Version: 2.1.0
|
|
1548
|
+
* Description: Contains shared constants and regular expressions used by the enhanced patch utilities.
|
|
1549
|
+
* Language: JavaScript
|
|
1550
|
+
* Created-at: 2025-05-14T16:55:00.000Z
|
|
1551
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Claude 3.7 Sonnet (v2.0.0), Qwen 3 Coder 480B - Cerebras (v2.1.0)
|
|
1552
|
+
*/
|
|
1553
|
+
|
|
1554
|
+
// Traditional patch markers
|
|
1555
|
+
const PATCH_START_MARKER$1 = '# --- PATCH START MARKER ---';
|
|
1556
|
+
const PATCH_END_MARKER$1 = '# --- PATCH END MARKER ---';
|
|
1557
|
+
|
|
1558
|
+
// Abbreviated patch markers
|
|
1559
|
+
const ABBREVIATED_PATCH_START_MARKER$1 = '# --- ABBREVIATED PATCH START MARKER ---';
|
|
1560
|
+
const ABBREVIATED_PATCH_END_MARKER$1 = '# --- ABBREVIATED PATCH END MARKER ---';
|
|
1561
|
+
|
|
1562
|
+
// Patch metadata header
|
|
1563
|
+
const PATCH_METADATA_HEADER$1 = '# Patch Metadata';
|
|
1564
|
+
|
|
1565
|
+
// Diff file headers
|
|
1566
|
+
const ORIGINAL_FILE_HEADER$1 = '--- Original';
|
|
1567
|
+
const MODIFIED_FILE_HEADER$1 = '+++ Modified';
|
|
1568
|
+
|
|
1569
|
+
var constants$2 = {
|
|
1570
|
+
PATCH_START_MARKER: PATCH_START_MARKER$1,
|
|
1571
|
+
PATCH_END_MARKER: PATCH_END_MARKER$1,
|
|
1572
|
+
ABBREVIATED_PATCH_START_MARKER: ABBREVIATED_PATCH_START_MARKER$1,
|
|
1573
|
+
ABBREVIATED_PATCH_END_MARKER: ABBREVIATED_PATCH_END_MARKER$1,
|
|
1574
|
+
PATCH_METADATA_HEADER: PATCH_METADATA_HEADER$1,
|
|
1575
|
+
ORIGINAL_FILE_HEADER: ORIGINAL_FILE_HEADER$1,
|
|
1576
|
+
MODIFIED_FILE_HEADER: MODIFIED_FILE_HEADER$1
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1543
1579
|
/**
|
|
1544
1580
|
* Component: PatchUtils Parser
|
|
1545
1581
|
* Block-UUID: ce634df9-ff99-482a-a261-56ab34a2546e
|
|
1546
1582
|
* Parent-UUID: fcc85ec1-0146-40bf-a937-6f7928258cbf
|
|
1547
|
-
* Version: 1.
|
|
1548
|
-
* Description: Handles parsing, validation, extraction, and detection of traditional unified diff patches. Extracts metadata and raw diff content.
|
|
1583
|
+
* Version: 1.2.0
|
|
1584
|
+
* Description: Handles parsing, validation, extraction, and detection of traditional unified diff patches and abbreviated patches. Extracts metadata and raw diff content.
|
|
1549
1585
|
* Language: JavaScript
|
|
1550
1586
|
* Created-at: 2025-04-18T02:59:04.322Z
|
|
1551
|
-
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0)
|
|
1587
|
+
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0)
|
|
1552
1588
|
*/
|
|
1553
1589
|
|
|
1554
1590
|
const { isValidVersion } = versionUtils; // Assuming SharedUtils is one level up
|
|
1591
|
+
const { PATCH_START_MARKER, PATCH_END_MARKER, PATCH_METADATA_HEADER,
|
|
1592
|
+
ORIGINAL_FILE_HEADER, MODIFIED_FILE_HEADER, ABBREVIATED_PATCH_START_MARKER,
|
|
1593
|
+
ABBREVIATED_PATCH_END_MARKER } = constants$2;
|
|
1555
1594
|
|
|
1556
1595
|
/**
|
|
1557
1596
|
* Determines the type of patch format used based on markers.
|
|
1558
|
-
*
|
|
1597
|
+
* Looks for traditional unified diff markers or abbreviated patch markers.
|
|
1559
1598
|
* @param {string} patchText - The patch text
|
|
1560
|
-
* @returns {string} 'traditional', or 'unknown'
|
|
1599
|
+
* @returns {string} 'traditional', 'abbreviated', or 'unknown'
|
|
1561
1600
|
*/
|
|
1562
1601
|
function determinePatchFormat$1(patchText) {
|
|
1563
1602
|
if (!patchText || typeof patchText !== 'string') {
|
|
@@ -1565,29 +1604,33 @@ function determinePatchFormat$1(patchText) {
|
|
|
1565
1604
|
}
|
|
1566
1605
|
|
|
1567
1606
|
// Check for required metadata header first
|
|
1568
|
-
if (!patchText.includes(
|
|
1607
|
+
if (!patchText.includes(PATCH_METADATA_HEADER)) {
|
|
1569
1608
|
return 'unknown'; // Must have metadata header
|
|
1570
1609
|
}
|
|
1571
1610
|
|
|
1572
1611
|
// Check for traditional unified diff markers *after* potential metadata and start marker
|
|
1573
1612
|
// Look for ---, +++, @@ after the start marker
|
|
1574
|
-
const
|
|
1575
|
-
if (
|
|
1576
|
-
|
|
1577
|
-
}
|
|
1613
|
+
const traditionalStartMarkerIndex = patchText.indexOf(PATCH_START_MARKER);
|
|
1614
|
+
if (traditionalStartMarkerIndex !== -1) {
|
|
1615
|
+
const contentAfterMarker = patchText.substring(traditionalStartMarkerIndex);
|
|
1578
1616
|
|
|
1579
|
-
|
|
1617
|
+
// Use regex for more reliable detection within the content part
|
|
1618
|
+
const traditionalMarkers = /^\s*--- Original\s*\n\s*\+\+\+ Modified\s*\n\s*@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/m;
|
|
1580
1619
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1620
|
+
if (traditionalMarkers.test(contentAfterMarker)) {
|
|
1621
|
+
return 'traditional';
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1583
1624
|
|
|
1584
|
-
|
|
1585
|
-
|
|
1625
|
+
// Check for abbreviated patch markers
|
|
1626
|
+
const abbreviatedStartMarkerIndex = patchText.indexOf(ABBREVIATED_PATCH_START_MARKER);
|
|
1627
|
+
if (abbreviatedStartMarkerIndex !== -1) {
|
|
1628
|
+
return 'abbreviated';
|
|
1586
1629
|
}
|
|
1587
1630
|
|
|
1588
1631
|
// Removed check for obsolete '@=' context marker
|
|
1589
1632
|
|
|
1590
|
-
return 'unknown'; // Format doesn't match expected
|
|
1633
|
+
return 'unknown'; // Format doesn't match expected structures after markers
|
|
1591
1634
|
}
|
|
1592
1635
|
|
|
1593
1636
|
/**
|
|
@@ -1608,7 +1651,8 @@ function extractPatchMetadata$1(patchText) {
|
|
|
1608
1651
|
const trimmedLine = line.trim();
|
|
1609
1652
|
|
|
1610
1653
|
// Stop processing metadata if we hit content markers or the start marker
|
|
1611
|
-
if (trimmedLine ===
|
|
1654
|
+
if (trimmedLine === PATCH_START_MARKER ||
|
|
1655
|
+
trimmedLine === ABBREVIATED_PATCH_START_MARKER ||
|
|
1612
1656
|
line.startsWith('--- ') || // Standard diff header start
|
|
1613
1657
|
line.startsWith('+++ ') || // Standard diff header start
|
|
1614
1658
|
line.startsWith('@@ ')) // Standard diff hunk header start
|
|
@@ -1630,7 +1674,7 @@ function extractPatchMetadata$1(patchText) {
|
|
|
1630
1674
|
}
|
|
1631
1675
|
}
|
|
1632
1676
|
// Allow lines that are just comments (e.g., # Description continued)
|
|
1633
|
-
} else if (trimmedLine !== '' && !trimmedLine.startsWith(
|
|
1677
|
+
} else if (trimmedLine !== '' && !trimmedLine.startsWith(PATCH_METADATA_HEADER)) {
|
|
1634
1678
|
break;
|
|
1635
1679
|
}
|
|
1636
1680
|
}
|
|
@@ -1671,11 +1715,11 @@ function validatePatchMetadata$1(metadata) {
|
|
|
1671
1715
|
}
|
|
1672
1716
|
|
|
1673
1717
|
// Validate UUIDs are not the template string
|
|
1674
|
-
if (metadata['Source-Block-UUID'] === '
|
|
1675
|
-
errors.push('Source-Block-UUID contains placeholder value "
|
|
1718
|
+
if (metadata['Source-Block-UUID'] === '{{GS-UUID}}') {
|
|
1719
|
+
errors.push('Source-Block-UUID contains placeholder value "{{GS-UUID}}".');
|
|
1676
1720
|
}
|
|
1677
|
-
if (metadata['Target-Block-UUID'] === '
|
|
1678
|
-
errors.push('Target-Block-UUID contains placeholder value "
|
|
1721
|
+
if (metadata['Target-Block-UUID'] === '{{GS-UUID}}') {
|
|
1722
|
+
errors.push('Target-Block-UUID contains placeholder value "{{GS-UUID}}".');
|
|
1679
1723
|
}
|
|
1680
1724
|
|
|
1681
1725
|
return errors;
|
|
@@ -1688,23 +1732,34 @@ function validatePatchMetadata$1(metadata) {
|
|
|
1688
1732
|
* @param {string} format - Expected format (should be 'traditional').
|
|
1689
1733
|
* @returns {string} Raw unified diff content, or empty string if not found/invalid.
|
|
1690
1734
|
*/
|
|
1691
|
-
function extractPatchContent$1(patchText, format) {
|
|
1692
|
-
if (!patchText
|
|
1735
|
+
function extractPatchContent$1(patchText, format = 'traditional') {
|
|
1736
|
+
if (!patchText) {
|
|
1693
1737
|
return "";
|
|
1694
1738
|
}
|
|
1695
1739
|
|
|
1696
1740
|
const lines = patchText.split('\n');
|
|
1697
|
-
|
|
1698
1741
|
let contentLines = [];
|
|
1699
1742
|
let inContentBlock = false;
|
|
1743
|
+
let startMarker, endMarker;
|
|
1744
|
+
|
|
1745
|
+
// Determine which markers to look for based on format
|
|
1746
|
+
if (format === 'traditional') {
|
|
1747
|
+
startMarker = PATCH_START_MARKER;
|
|
1748
|
+
endMarker = PATCH_END_MARKER;
|
|
1749
|
+
} else if (format === 'abbreviated') {
|
|
1750
|
+
startMarker = ABBREVIATED_PATCH_START_MARKER;
|
|
1751
|
+
endMarker = ABBREVIATED_PATCH_END_MARKER;
|
|
1752
|
+
} else {
|
|
1753
|
+
return ""; // Unsupported format
|
|
1754
|
+
}
|
|
1700
1755
|
|
|
1701
1756
|
for (const line of lines) {
|
|
1702
|
-
if (line.trim() ===
|
|
1757
|
+
if (line.trim() === startMarker) {
|
|
1703
1758
|
inContentBlock = true;
|
|
1704
1759
|
continue; // Skip the marker line itself
|
|
1705
1760
|
}
|
|
1706
1761
|
|
|
1707
|
-
if (line.trim() ===
|
|
1762
|
+
if (line.trim() === endMarker) {
|
|
1708
1763
|
inContentBlock = false;
|
|
1709
1764
|
break; // Stop processing once end marker is found
|
|
1710
1765
|
}
|
|
@@ -1743,23 +1798,25 @@ function detectPatch(messageText) {
|
|
|
1743
1798
|
}
|
|
1744
1799
|
|
|
1745
1800
|
// Find the first code block that contains patch metadata
|
|
1746
|
-
// Regex looks for ``` optionally followed by
|
|
1747
|
-
const codeBlockRegex = /```(
|
|
1801
|
+
// Regex looks for ``` optionally followed by language hint
|
|
1802
|
+
const codeBlockRegex = /```([a-zA-Z0-9#+_-]*)?\s*\n([\s\S]*?)```/g;
|
|
1748
1803
|
let match;
|
|
1749
1804
|
while ((match = codeBlockRegex.exec(messageText)) !== null) {
|
|
1750
|
-
const
|
|
1805
|
+
const language = match[1] || '';
|
|
1806
|
+
const blockContent = match[2];
|
|
1751
1807
|
if (isPatchBlock$1(blockContent)) { // Use isPatchBlock for check
|
|
1752
1808
|
const metadata = extractPatchMetadata$1(blockContent); // Use extractPatchMetadata
|
|
1753
1809
|
// Basic validation: Check for essential UUIDs
|
|
1754
1810
|
if (metadata['Source-Block-UUID'] && metadata['Target-Block-UUID'] &&
|
|
1755
|
-
metadata['Source-Block-UUID'] !== '
|
|
1756
|
-
metadata['Target-Block-UUID'] !== '
|
|
1811
|
+
metadata['Source-Block-UUID'] !== '{{GS-UUID}}' && // Check placeholders
|
|
1812
|
+
metadata['Target-Block-UUID'] !== '{{GS-UUID}}')
|
|
1757
1813
|
{
|
|
1758
1814
|
return {
|
|
1759
1815
|
patchText: blockContent, // Return the content inside the fence
|
|
1760
1816
|
metadata,
|
|
1761
1817
|
sourceBlockUUID: metadata['Source-Block-UUID'],
|
|
1762
1818
|
targetBlockUUID: metadata['Target-Block-UUID'],
|
|
1819
|
+
language: language,
|
|
1763
1820
|
startIndex: match.index, // Store block position if needed
|
|
1764
1821
|
endIndex: match.index + match[0].length
|
|
1765
1822
|
};
|
|
@@ -1781,25 +1838,28 @@ function findAllPatches(messageText) {
|
|
|
1781
1838
|
}
|
|
1782
1839
|
|
|
1783
1840
|
const patches = [];
|
|
1784
|
-
|
|
1841
|
+
// Find code blocks with any language identifier
|
|
1842
|
+
const codeBlockRegex = /```([a-zA-Z0-9#+_-]*)?\s*\n([\s\S]*?)```/g;
|
|
1785
1843
|
|
|
1786
1844
|
let match;
|
|
1787
1845
|
while ((match = codeBlockRegex.exec(messageText)) !== null) {
|
|
1788
|
-
const
|
|
1846
|
+
const language = match[1] || '';
|
|
1847
|
+
const blockContent = match[2];
|
|
1789
1848
|
|
|
1790
1849
|
if (isPatchBlock$1(blockContent)) {
|
|
1791
1850
|
const metadata = extractPatchMetadata$1(blockContent);
|
|
1792
1851
|
|
|
1793
1852
|
// Basic validation: Check for essential UUIDs and non-placeholder values
|
|
1794
1853
|
if (metadata['Source-Block-UUID'] && metadata['Target-Block-UUID'] &&
|
|
1795
|
-
metadata['Source-Block-UUID'] !== '
|
|
1796
|
-
metadata['Target-Block-UUID'] !== '
|
|
1854
|
+
metadata['Source-Block-UUID'] !== '{{GS-UUID}}' &&
|
|
1855
|
+
metadata['Target-Block-UUID'] !== '{{GS-UUID}}')
|
|
1797
1856
|
{
|
|
1798
1857
|
patches.push({
|
|
1799
1858
|
patchText: blockContent,
|
|
1800
1859
|
metadata,
|
|
1801
1860
|
sourceBlockUUID: metadata['Source-Block-UUID'],
|
|
1802
1861
|
targetBlockUUID: metadata['Target-Block-UUID'],
|
|
1862
|
+
language: language,
|
|
1803
1863
|
startIndex: match.index,
|
|
1804
1864
|
endIndex: match.index + match[0].length
|
|
1805
1865
|
});
|
|
@@ -2267,7 +2327,7 @@ var verifyAndCorrectLineNumbers_1 = {
|
|
|
2267
2327
|
|
|
2268
2328
|
/**
|
|
2269
2329
|
* Component: PatchUtils Verify and Correct Hunk Headers
|
|
2270
|
-
* Block-UUID:
|
|
2330
|
+
* Block-UUID: 013f7f2d-0077-4cec-bd22-3bf2fc81f222
|
|
2271
2331
|
* Parent-UUID: 2308ed72-91ff-48ba-bc80-310c23c01ff1
|
|
2272
2332
|
* Version: 1.0.0
|
|
2273
2333
|
* Description: Verifies and corrects the hunk headers within a patch based on the line number prefixes in the content lines.
|
|
@@ -2466,7 +2526,7 @@ var verifyAndCorrectHunkHeaders_1 = {
|
|
|
2466
2526
|
|
|
2467
2527
|
/**
|
|
2468
2528
|
* Component: PatchUtils Detect and Fix Redundant Changes
|
|
2469
|
-
* Block-UUID:
|
|
2529
|
+
* Block-UUID: bb354364-b497-412c-9570-b39355da8153
|
|
2470
2530
|
* Parent-UUID: 2308ed72-91ff-48ba-bc80-310c23c01ff1
|
|
2471
2531
|
* Version: 1.0.0
|
|
2472
2532
|
* Description: Detects and optionally fixes redundant changes in a patch where content is deleted and re-added identically.
|
|
@@ -2869,7 +2929,7 @@ var detectAndFixRedundantChanges_1 = {
|
|
|
2869
2929
|
|
|
2870
2930
|
/**
|
|
2871
2931
|
* Component: PatchUtils Detect and Fix Overlapping Hunks
|
|
2872
|
-
* Block-UUID:
|
|
2932
|
+
* Block-UUID: 7324dab8-24ae-4a42-9dc3-766e69104ef6
|
|
2873
2933
|
* Parent-UUID: 2308ed72-91ff-48ba-bc80-310c23c01ff1
|
|
2874
2934
|
* Version: 1.0.0
|
|
2875
2935
|
* Description: Detects and optionally fixes overlapping hunks in a patch file by merging them.
|
|
@@ -8746,6 +8806,8 @@ var PatchUtils$2 = {
|
|
|
8746
8806
|
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
8747
8807
|
*/
|
|
8748
8808
|
|
|
8809
|
+
const GS_TOOL_BLOCK_TYPE = 'gs-tool';
|
|
8810
|
+
|
|
8749
8811
|
/**
|
|
8750
8812
|
* Checks if a given code block content represents a GitSense Chat Tool Block.
|
|
8751
8813
|
* It verifies if the first non-empty line starts with "# GitSense Chat Tool".
|
|
@@ -8764,6 +8826,65 @@ function isToolBlock$1(content) {
|
|
|
8764
8826
|
return false;
|
|
8765
8827
|
}
|
|
8766
8828
|
|
|
8829
|
+
|
|
8830
|
+
// TODO: Add JSDocs
|
|
8831
|
+
function getToolBlocksByTool(content, tool, CodeBlockUtils) {
|
|
8832
|
+
const { blocks, warnings } = CodeBlockUtils.extractCodeBlocks(content, { silent: true });
|
|
8833
|
+
|
|
8834
|
+
return blocks.filter((block, index) => {
|
|
8835
|
+
if (block.type !== GS_TOOL_BLOCK_TYPE)
|
|
8836
|
+
return;
|
|
8837
|
+
|
|
8838
|
+
try {
|
|
8839
|
+
const data = parseToolBlock$1(block.content);
|
|
8840
|
+
|
|
8841
|
+
if (data.tool === tool) {
|
|
8842
|
+
block.index = index;
|
|
8843
|
+
return block;
|
|
8844
|
+
}
|
|
8845
|
+
} catch(error) {
|
|
8846
|
+
// FIXME: We need a more elegant way to identify examples.
|
|
8847
|
+
if (!content.includes(/Internal INTEGER IDs/)) {
|
|
8848
|
+
console.warn(`Invalid tool block JSON: ${error.message}`);
|
|
8849
|
+
}
|
|
8850
|
+
}
|
|
8851
|
+
});
|
|
8852
|
+
}
|
|
8853
|
+
|
|
8854
|
+
// TODO: Add JSDocs
|
|
8855
|
+
function getToolBlockElemsByTool(dom, tool) {
|
|
8856
|
+
const elems = dom.querySelectorAll('pre');
|
|
8857
|
+
const toolBockElems = [];
|
|
8858
|
+
|
|
8859
|
+
for ( let i = 0; i < elems.length; i++ ) {
|
|
8860
|
+
const elem = elems[i];
|
|
8861
|
+
let content = elem.textContent;
|
|
8862
|
+
|
|
8863
|
+
// We need to strip out the first two lines since this is not part of the actual code
|
|
8864
|
+
// block. These two lines are designed to make it easy to identify the language
|
|
8865
|
+
content = content.split('\n').slice(2).join('\n');
|
|
8866
|
+
|
|
8867
|
+
if (!isToolBlock$1(content))
|
|
8868
|
+
continue;
|
|
8869
|
+
|
|
8870
|
+
try {
|
|
8871
|
+
const data = parseToolBlock$1(content, { silent: true });
|
|
8872
|
+
|
|
8873
|
+
if (data.tool === tool)
|
|
8874
|
+
toolBockElems.push(elem);
|
|
8875
|
+
} catch(error) {
|
|
8876
|
+
// FIXME: We need a more elegant way to identify examples.
|
|
8877
|
+
if (!content.match(/Internal INTEGER IDs/)) {
|
|
8878
|
+
console.warn("getToolBlockElemsByTool: ",error.message);
|
|
8879
|
+
}
|
|
8880
|
+
continue;
|
|
8881
|
+
}
|
|
8882
|
+
}
|
|
8883
|
+
|
|
8884
|
+
return toolBockElems;
|
|
8885
|
+
}
|
|
8886
|
+
|
|
8887
|
+
|
|
8767
8888
|
/**
|
|
8768
8889
|
* Parses the content of a GitSense Chat Tool Block to extract the JSON payload.
|
|
8769
8890
|
* It strips the marker line and any subsequent lines starting with '#' (comments)
|
|
@@ -8872,7 +8993,7 @@ function replaceToolBlock(markdownContent, toolName, newToolData, CodeBlockUtils
|
|
|
8872
8993
|
// 2. Iterate through the processed blocks to find the target GitSense Chat Tool Block
|
|
8873
8994
|
for (let i = 0; i < blocks.length; i++) {
|
|
8874
8995
|
const block = blocks[i];
|
|
8875
|
-
if (block.type ===
|
|
8996
|
+
if (block.type === GS_TOOL_BLOCK_TYPE && block.toolData && block.toolData.tool === toolName) {
|
|
8876
8997
|
targetBlockIndex = i;
|
|
8877
8998
|
break; // Found the first matching tool block
|
|
8878
8999
|
}
|
|
@@ -9006,11 +9127,15 @@ function detectAndFormatUnfencedToolBlock(messageContent) {
|
|
|
9006
9127
|
};
|
|
9007
9128
|
}
|
|
9008
9129
|
|
|
9130
|
+
|
|
9131
|
+
|
|
9009
9132
|
var GSToolBlockUtils$3 = {
|
|
9010
9133
|
isToolBlock: isToolBlock$1,
|
|
9011
9134
|
parseToolBlock: parseToolBlock$1,
|
|
9012
9135
|
formatToolBlock,
|
|
9013
9136
|
replaceToolBlock,
|
|
9137
|
+
getToolBlocksByTool,
|
|
9138
|
+
getToolBlockElemsByTool,
|
|
9014
9139
|
detectAndFormatUnfencedToolBlock,
|
|
9015
9140
|
};
|
|
9016
9141
|
|
|
@@ -9310,16 +9435,16 @@ var JsonUtils$2 = {
|
|
|
9310
9435
|
* Component: CodeBlockUtils Block Processor
|
|
9311
9436
|
* Block-UUID: 1d8a559b-4f7a-4b0b-9e0a-13786f94a74e
|
|
9312
9437
|
* Parent-UUID: 082abf8b-079f-4c95-8464-0e66c0de45eb
|
|
9313
|
-
* Version: 1.
|
|
9438
|
+
* Version: 1.5.0
|
|
9314
9439
|
* Description: Processes the content of identified code blocks, parsing headers or patch details, and provides utilities like fixing UUIDs within blocks.
|
|
9315
9440
|
* Language: JavaScript
|
|
9316
9441
|
* Created-at: 2025-07-21T00:33:22.312Z
|
|
9317
|
-
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Pro (v1.2.0), Gemini 2.5 Flash Thinking (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0)
|
|
9442
|
+
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Pro (v1.2.0), Gemini 2.5 Flash Thinking (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0), Qwen 3 Coder 480B - Cerebras (v1.5.0)
|
|
9318
9443
|
*/
|
|
9319
9444
|
|
|
9320
9445
|
const { findAllCodeFences: findAllCodeFences$3, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$3 } = blockExtractor;
|
|
9321
9446
|
const { parseHeader: parseHeader$2 } = headerUtils;
|
|
9322
|
-
const { validateUUID: validateUUID$2
|
|
9447
|
+
const { validateUUID: validateUUID$2 } = uuidUtils;
|
|
9323
9448
|
const AnalysisBlockUtils$2 = AnalysisBlockUtils$3;
|
|
9324
9449
|
const PatchUtils$1 = PatchUtils$2;
|
|
9325
9450
|
const GSToolBlockUtils$2 = GSToolBlockUtils$3;
|
|
@@ -9435,7 +9560,7 @@ function processBlockContent(content, language, position, incomplete, options =
|
|
|
9435
9560
|
if (PatchUtils$1.isPatchBlock(content)) {
|
|
9436
9561
|
const patchFormat = PatchUtils$1.determinePatchFormat(content);
|
|
9437
9562
|
const metadata = PatchUtils$1.extractPatchMetadata(content); // Extract metadata regardless of validation
|
|
9438
|
-
const patchContent = PatchUtils$1.extractPatchContent(content); // Extract raw patch content
|
|
9563
|
+
const patchContent = PatchUtils$1.extractPatchContent(content, patchFormat); // Extract raw patch content
|
|
9439
9564
|
|
|
9440
9565
|
let patchValidationResult = { valid: true, errors: [], patches: null }; // Default valid state
|
|
9441
9566
|
|
|
@@ -9452,36 +9577,16 @@ function processBlockContent(content, language, position, incomplete, options =
|
|
|
9452
9577
|
// For now, just warn, but return the extracted (potentially invalid) metadata.
|
|
9453
9578
|
}
|
|
9454
9579
|
|
|
9455
|
-
//
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
if (!patches || patches.length === 0) {
|
|
9460
|
-
patchValidationResult = { valid: false, errors: ['No valid context patch content found.'], patches: null };
|
|
9461
|
-
warnings.push({
|
|
9462
|
-
position: position,
|
|
9463
|
-
type: 'patch_content_error',
|
|
9464
|
-
message: 'No valid context patch content found.',
|
|
9465
|
-
content: content,
|
|
9466
|
-
});
|
|
9467
|
-
} else {
|
|
9468
|
-
// Basic validation passed (structure was parsable)
|
|
9469
|
-
patchValidationResult = { valid: true, errors: [], patches: patches };
|
|
9470
|
-
}
|
|
9471
|
-
} catch (error) {
|
|
9472
|
-
patchValidationResult = { valid: false, errors: [error.message], patches: null };
|
|
9473
|
-
warnings.push({
|
|
9474
|
-
position: position,
|
|
9475
|
-
type: 'patch_parse_error',
|
|
9476
|
-
message: `Error parsing context patch: ${error.message}`,
|
|
9477
|
-
content: content,
|
|
9478
|
-
});
|
|
9479
|
-
}
|
|
9580
|
+
// Determine the correct language for the block
|
|
9581
|
+
let blockLanguage = language; // Default to the fence language
|
|
9582
|
+
if (patchFormat === 'traditional') {
|
|
9583
|
+
blockLanguage = 'diff'; // Enforce 'diff' for traditional patches
|
|
9480
9584
|
}
|
|
9585
|
+
// For abbreviated patches, keep the original language (e.g., 'javascript', 'python')
|
|
9481
9586
|
|
|
9482
9587
|
return {
|
|
9483
9588
|
type: 'patch',
|
|
9484
|
-
language:
|
|
9589
|
+
language: blockLanguage, // Use determined language
|
|
9485
9590
|
content: content, // Full original content within fences
|
|
9486
9591
|
position: position,
|
|
9487
9592
|
incomplete: incomplete,
|
|
@@ -9675,8 +9780,10 @@ function processBlockContents(text, completeBlocks, incompleteBlocks, options) {
|
|
|
9675
9780
|
* @returns {Object} { blocks: Array, warnings: Array, hasIncompleteBlocks: boolean, lastIncompleteBlock: Object|null }
|
|
9676
9781
|
*/
|
|
9677
9782
|
function processCodeBlocks$5(text, options = { silent: false, validatePatches: false }) {
|
|
9678
|
-
if (typeof text !== "string") {
|
|
9679
|
-
|
|
9783
|
+
if (typeof text !== "string") {
|
|
9784
|
+
if (text != null )
|
|
9785
|
+
console.warn("Warning: Input must be a string.");
|
|
9786
|
+
|
|
9680
9787
|
return {
|
|
9681
9788
|
blocks: [],
|
|
9682
9789
|
warnings: [{ type: 'invalid_input', message: 'Input must be a string.' }],
|
|
@@ -10597,19 +10704,114 @@ var updateCodeBlock_1 = {
|
|
|
10597
10704
|
updateCodeBlockInMessage: updateCodeBlockInMessage$1,
|
|
10598
10705
|
deleteCodeBlockByIndex: deleteCodeBlockByIndex$2};
|
|
10599
10706
|
|
|
10707
|
+
/**
|
|
10708
|
+
* Component: CodeBlockUtils Lineage Tracer
|
|
10709
|
+
* Block-UUID: 13b08cce-6fd1-4ec9-a915-240714ee89b9
|
|
10710
|
+
* Parent-UUID: df1a629b-2cc0-4677-b410-3172ee0e0f9f
|
|
10711
|
+
* Version: 1.1.0
|
|
10712
|
+
* Description: Provides a utility function to trace the full lineage (patch-based and parent-based) of code blocks within a chat, including loop detection.
|
|
10713
|
+
* Language: JavaScript
|
|
10714
|
+
* Created-at: 2025-10-23T01:28:10.456Z
|
|
10715
|
+
* Authors: Qwen 3 Coder 480B - Cerebras (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.1.0)
|
|
10716
|
+
*/
|
|
10717
|
+
|
|
10718
|
+
/**
|
|
10719
|
+
* Traces the full lineage of a code block or patch identified by a UUID.
|
|
10720
|
+
* The lineage includes the block itself and all its ancestors, tracing backwards
|
|
10721
|
+
* first through patch relationships (Source-Block-UUID -> Target-Block-UUID)
|
|
10722
|
+
* and then through Parent-UUID relationships.
|
|
10723
|
+
* Loop detection is included to prevent infinite tracing.
|
|
10724
|
+
*
|
|
10725
|
+
* @param {string} uuid - The UUID of the target code block or patch.
|
|
10726
|
+
* @param {Map<string, object>} blockMap - A map where keys are UUIDs (for code blocks)
|
|
10727
|
+
* or patch UUIDs (source:target) and values
|
|
10728
|
+
* are the corresponding block objects.
|
|
10729
|
+
* Block objects are expected to have
|
|
10730
|
+
* properties like `isPatch`, `metadata`, and `header`.
|
|
10731
|
+
* @returns {Array<object>} An array of block objects representing the lineage.
|
|
10732
|
+
* The first element is the block for the provided `uuid`.
|
|
10733
|
+
* Subsequent elements are its ancestors.
|
|
10734
|
+
* Returns an empty array if the initial uuid is not found.
|
|
10735
|
+
* If a loop is detected, the last element will have a property `loopDetected: true`.
|
|
10736
|
+
*/
|
|
10737
|
+
function getLineage$2(uuid, blockMap) {
|
|
10738
|
+
if (!uuid || !blockMap) {
|
|
10739
|
+
return [];
|
|
10740
|
+
}
|
|
10741
|
+
|
|
10742
|
+
const lineage = [];
|
|
10743
|
+
const visitedUuids = new Set();
|
|
10744
|
+
let currentUuid = uuid;
|
|
10745
|
+
|
|
10746
|
+
while (currentUuid) {
|
|
10747
|
+
// --- Loop Detection ---
|
|
10748
|
+
if (visitedUuids.has(currentUuid)) {
|
|
10749
|
+
// Add a marker or the block itself to indicate the loop
|
|
10750
|
+
const loopBlock = blockMap.get(currentUuid) || { uuid: currentUuid, loopDetected: true, type: 'loop-marker' };
|
|
10751
|
+
loopBlock.loopDetected = true; // Ensure the property is set
|
|
10752
|
+
lineage.push(loopBlock);
|
|
10753
|
+
break; // Stop the trace
|
|
10754
|
+
}
|
|
10755
|
+
visitedUuids.add(currentUuid);
|
|
10756
|
+
|
|
10757
|
+
// --- 1. Try to find the block directly by its UUID ---
|
|
10758
|
+
let block = blockMap.get(currentUuid);
|
|
10759
|
+
|
|
10760
|
+
// --- 2. If not found directly, search patch keys ---
|
|
10761
|
+
if (!block) {
|
|
10762
|
+
for (const [key, value] of blockMap) {
|
|
10763
|
+
// Check if the map key is a patch key (contains ':') and ends with our target UUID
|
|
10764
|
+
if (key.includes(':') && key.endsWith(`:${currentUuid}`)) {
|
|
10765
|
+
block = value;
|
|
10766
|
+
break;
|
|
10767
|
+
}
|
|
10768
|
+
}
|
|
10769
|
+
}
|
|
10770
|
+
|
|
10771
|
+
// --- 3. If a block was found, add it to the lineage ---
|
|
10772
|
+
if (block) {
|
|
10773
|
+
lineage.push(block);
|
|
10774
|
+
|
|
10775
|
+
let nextUuid = null;
|
|
10776
|
+
|
|
10777
|
+
// --- 3a. If it's a patch, move to its source UUID ---
|
|
10778
|
+
if (block.isPatch && block.metadata && block.metadata['Source-Block-UUID']) {
|
|
10779
|
+
nextUuid = block.metadata['Source-Block-UUID'];
|
|
10780
|
+
}
|
|
10781
|
+
// --- 3b. If it's a code block, move to its Parent-UUID (if valid) ---
|
|
10782
|
+
else if (!block.isPatch && block.header && block.header['Parent-UUID'] && block.header['Parent-UUID'] !== 'N/A') {
|
|
10783
|
+
nextUuid = block.header['Parent-UUID'];
|
|
10784
|
+
}
|
|
10785
|
+
// If it's a code block with Parent-UUID: 0c104865-260a-4942-8cb6-93bebf40c450
|
|
10786
|
+
|
|
10787
|
+
currentUuid = nextUuid;
|
|
10788
|
+
} else {
|
|
10789
|
+
// If no block is found for currentUuid, the lineage is incomplete.
|
|
10790
|
+
// We could add a placeholder here if needed, but for now, we just stop.
|
|
10791
|
+
currentUuid = null;
|
|
10792
|
+
}
|
|
10793
|
+
}
|
|
10794
|
+
|
|
10795
|
+
return lineage;
|
|
10796
|
+
}
|
|
10797
|
+
|
|
10798
|
+
var lineageTracer = {
|
|
10799
|
+
getLineage: getLineage$2
|
|
10800
|
+
};
|
|
10801
|
+
|
|
10600
10802
|
/**
|
|
10601
10803
|
* Component: CodeBlockUtils Index
|
|
10602
|
-
* Block-UUID:
|
|
10603
|
-
* Parent-UUID:
|
|
10604
|
-
* Version: 1.
|
|
10804
|
+
* Block-UUID: 98684aa5-d597-41b6-a7fd-cc16482aafdc
|
|
10805
|
+
* Parent-UUID: 7e9d3f8a-1b2c-4d5e-8f9a-0123456789ab
|
|
10806
|
+
* Version: 1.5.0
|
|
10605
10807
|
* Description: Aggregates and exports all utilities related to code block processing from the CodeBlockUtils module. Serves as the main entry point for this module.
|
|
10606
10808
|
* Language: JavaScript
|
|
10607
10809
|
* Created-at: 2025-04-15T16:02:20.217Z
|
|
10608
|
-
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Claude 3.7 Sonnet (v1.2.0), Gemini 2.5 Pro (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0)
|
|
10810
|
+
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Pro (v1.1.0), Claude 3.7 Sonnet (v1.2.0), Gemini 2.5 Pro (v1.3.0), Gemini 2.5 Flash Thinking (v1.4.0), Qwen 3 Coder 480B - Cerebras (v1.5.0)
|
|
10609
10811
|
*/
|
|
10610
10812
|
|
|
10611
10813
|
// Import from individual utility files
|
|
10612
|
-
const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$
|
|
10814
|
+
const { COMMENT_STYLES: COMMENT_STYLES$1 } = constants$3;
|
|
10613
10815
|
const { generateUUID: generateUUID$1, validateUUID: validateUUID$1 } = uuidUtils;
|
|
10614
10816
|
const { isValidISOTimestamp: isValidISOTimestamp$1, parseHeader: parseHeader$1, getHeaderLineCount } = headerUtils;
|
|
10615
10817
|
const { findAllCodeFences: findAllCodeFences$1, matchFencesAndExtractBlocks: matchFencesAndExtractBlocks$1, extractCodeBlocksWithUUIDs, findCodeBlockByUUID } = blockExtractor;
|
|
@@ -10621,9 +10823,10 @@ const { parseCodeBlocks: parseCommentDelimitedBlocks$1 } = headerParser;
|
|
|
10621
10823
|
const { removeCodeBlockMarkers: removeCodeBlockMarkers$1 } = markerRemover;
|
|
10622
10824
|
const { updateCodeBlockByIndex: updateCodeBlockByIndex$1, updateCodeBlockByUUID, updateCodeBlock, updateCodeBlockInMessage, deleteCodeBlockByIndex: deleteCodeBlockByIndex$1 } = updateCodeBlock_1;
|
|
10623
10825
|
const { formatWithLineNumbers: formatWithLineNumbers$1, formatBlockWithLineNumbers: formatBlockWithLineNumbers$1, formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1, removeLineNumbers: removeLineNumbers$1 } = lineNumberFormatter;
|
|
10826
|
+
const { getLineage: getLineage$1 } = lineageTracer;
|
|
10624
10827
|
|
|
10625
10828
|
// Export all imported items
|
|
10626
|
-
var CodeBlockUtils$
|
|
10829
|
+
var CodeBlockUtils$7 = {
|
|
10627
10830
|
// Constants
|
|
10628
10831
|
COMMENT_STYLES: COMMENT_STYLES$1,
|
|
10629
10832
|
|
|
@@ -10675,22 +10878,23 @@ var CodeBlockUtils$5 = {
|
|
|
10675
10878
|
// Line Number Formatting Utilities
|
|
10676
10879
|
formatWithLineNumbers: formatWithLineNumbers$1,
|
|
10677
10880
|
formatBlockWithLineNumbers: formatBlockWithLineNumbers$1,
|
|
10678
|
-
formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1,
|
|
10881
|
+
formatBlocksWithLineNumbers: formatBlocksWithLineNumbers$1,
|
|
10882
|
+
getLineage: getLineage$1,
|
|
10679
10883
|
removeLineNumbers: removeLineNumbers$1,
|
|
10680
10884
|
};
|
|
10681
10885
|
|
|
10682
10886
|
/*
|
|
10683
10887
|
* Component: ContextUtils
|
|
10684
|
-
* Block-UUID:
|
|
10685
|
-
* Parent-UUID:
|
|
10686
|
-
* Version: 1.
|
|
10888
|
+
* Block-UUID: 534c348d-a11f-4de6-ad15-f33068d51fb8
|
|
10889
|
+
* Parent-UUID: a0b71292-b1cc-401a-8ce2-544a047b0fef
|
|
10890
|
+
* Version: 1.4.0
|
|
10687
10891
|
* Description: Provides utility functions for parsing context message sections to extract file details and code blocks, and for formatting content for LLM context.
|
|
10688
10892
|
* Language: JavaScript
|
|
10689
10893
|
* Created-at: 2025-05-09T01:36:20.107Z
|
|
10690
|
-
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0), Qwen 3 Coder 480B - Cerebras (v1.3.0)
|
|
10894
|
+
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0), Qwen 3 Coder 480B - Cerebras (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0)
|
|
10691
10895
|
*/
|
|
10692
10896
|
|
|
10693
|
-
const CodeBlockUtils$
|
|
10897
|
+
const CodeBlockUtils$6 = CodeBlockUtils$7;
|
|
10694
10898
|
const MessageUtils$2 = MessageUtils$3;
|
|
10695
10899
|
|
|
10696
10900
|
/**
|
|
@@ -10757,6 +10961,41 @@ function _createContextSummary(items, contentType) {
|
|
|
10757
10961
|
return summary + "\n";
|
|
10758
10962
|
}
|
|
10759
10963
|
|
|
10964
|
+
/**
|
|
10965
|
+
* Extracts all context files from a given chat object.
|
|
10966
|
+
* Iterates through chat messages, identifies context loader outputs,
|
|
10967
|
+
* and parses them into individual file objects.
|
|
10968
|
+
*
|
|
10969
|
+
* @param {object} chat - The GitSense chat object.
|
|
10970
|
+
* @returns {Array<object>} An array of parsed context file objects.
|
|
10971
|
+
* Returns an empty array if no context files are found or on error.
|
|
10972
|
+
*/
|
|
10973
|
+
function getContextFiles$1(chat) {
|
|
10974
|
+
const ChatUtils = ChatUtils$2;
|
|
10975
|
+
const contextFiles = [];
|
|
10976
|
+
const messages = ChatUtils.getChatMessages(chat);
|
|
10977
|
+
|
|
10978
|
+
if (!Array.isArray(messages)) {
|
|
10979
|
+
console.warn("getContextFiles: Provided chat object does not contain a valid messages array.");
|
|
10980
|
+
return contextFiles;
|
|
10981
|
+
}
|
|
10982
|
+
|
|
10983
|
+
messages.forEach(message => {
|
|
10984
|
+
// Check if the message content is a context message
|
|
10985
|
+
if (MessageUtils$2.isContextMessage(message.message)) {
|
|
10986
|
+
try {
|
|
10987
|
+
// Extract all context sections from the message content
|
|
10988
|
+
const extractedFiles = extractContextSections$1(message.message);
|
|
10989
|
+
contextFiles.push(...extractedFiles);
|
|
10990
|
+
} catch (error) {
|
|
10991
|
+
console.warn(`getContextFiles: Failed to extract context sections from message ID ${message.id}:`, error);
|
|
10992
|
+
}
|
|
10993
|
+
}
|
|
10994
|
+
});
|
|
10995
|
+
|
|
10996
|
+
return contextFiles;
|
|
10997
|
+
}
|
|
10998
|
+
|
|
10760
10999
|
/**
|
|
10761
11000
|
* Escapes backticks in code blocks to prevent premature termination of LLM-generated code blocks.
|
|
10762
11001
|
* @param {string} content - The content string to escape.
|
|
@@ -10829,7 +11068,7 @@ function parseContextSection$1(sectionText) {
|
|
|
10829
11068
|
}
|
|
10830
11069
|
});
|
|
10831
11070
|
|
|
10832
|
-
const { blocks, warnings } = CodeBlockUtils$
|
|
11071
|
+
const { blocks, warnings } = CodeBlockUtils$6.extractCodeBlocks(sectionText, { silent: true });
|
|
10833
11072
|
const codeBlocks = blocks.filter(block => block.type === 'code');
|
|
10834
11073
|
|
|
10835
11074
|
if (codeBlocks.length === 0) {
|
|
@@ -11031,6 +11270,7 @@ function formatContextContent$1(items, contentType, contentOption) {
|
|
|
11031
11270
|
var ContextUtils$2 = {
|
|
11032
11271
|
parseContextSection: parseContextSection$1,
|
|
11033
11272
|
extractContextSections: extractContextSections$1,
|
|
11273
|
+
getContextFiles: getContextFiles$1,
|
|
11034
11274
|
extractContextItemsOverviewTableRows: extractContextItemsOverviewTableRows$1,
|
|
11035
11275
|
formatContextContent: formatContextContent$1,
|
|
11036
11276
|
};
|
|
@@ -11088,7 +11328,7 @@ var contextMapper = {
|
|
|
11088
11328
|
|
|
11089
11329
|
/*
|
|
11090
11330
|
* Component: AnalyzerUtils Constants
|
|
11091
|
-
* Block-UUID:
|
|
11331
|
+
* Block-UUID: fec5dcc4-a1d0-4ef7-8828-3e44a75892c4
|
|
11092
11332
|
* Parent-UUID: N/A
|
|
11093
11333
|
* Version: 1.0.0
|
|
11094
11334
|
* Description: Defines constants specific to the AnalyzerUtils module.
|
|
@@ -11114,7 +11354,7 @@ var constants = {
|
|
|
11114
11354
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11115
11355
|
*/
|
|
11116
11356
|
|
|
11117
|
-
const CodeBlockUtils$
|
|
11357
|
+
const CodeBlockUtils$5 = CodeBlockUtils$7;
|
|
11118
11358
|
const GSToolBlockUtils$1 = GSToolBlockUtils$3;
|
|
11119
11359
|
const JsonUtils$1 = JsonUtils$2;
|
|
11120
11360
|
const { ANALYZE_HEADER_PREFIX } = constants;
|
|
@@ -11131,7 +11371,7 @@ const { ANALYZE_HEADER_PREFIX } = constants;
|
|
|
11131
11371
|
*/
|
|
11132
11372
|
function processLLMAnalysisResponse$2(messageContent, stoppedStreaming) {
|
|
11133
11373
|
const silent = { silent: true };
|
|
11134
|
-
const { blocks, warnings } = CodeBlockUtils$
|
|
11374
|
+
const { blocks, warnings } = CodeBlockUtils$5.extractCodeBlocks(messageContent, silent);
|
|
11135
11375
|
|
|
11136
11376
|
const analysisBlocks = [];
|
|
11137
11377
|
const analysisMetadataBlocks = [];
|
|
@@ -11316,7 +11556,7 @@ var dataValidator = {
|
|
|
11316
11556
|
|
|
11317
11557
|
/*
|
|
11318
11558
|
* Component: AnalyzerUtils Instruction Loader
|
|
11319
|
-
* Block-UUID:
|
|
11559
|
+
* Block-UUID: 3ecd422e-1dd8-482d-ae3f-90a5eae3ae44
|
|
11320
11560
|
* Parent-UUID: N/A
|
|
11321
11561
|
* Version: 1.0.0
|
|
11322
11562
|
* Description: Provides utility functions for loading raw analyzer instruction content.
|
|
@@ -11325,19 +11565,19 @@ var dataValidator = {
|
|
|
11325
11565
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11326
11566
|
*/
|
|
11327
11567
|
|
|
11328
|
-
const fs$
|
|
11329
|
-
const path$
|
|
11568
|
+
const fs$8 = require$$0.promises;
|
|
11569
|
+
const path$6 = require$$1;
|
|
11330
11570
|
|
|
11331
11571
|
/**
|
|
11332
11572
|
* Retrieves the raw Markdown content of the analyzer's '1.md' instruction file.
|
|
11333
11573
|
*
|
|
11334
|
-
* @param {string}
|
|
11574
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
11335
11575
|
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11336
11576
|
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content of the '1.md' file, or null if not found/invalid.
|
|
11337
11577
|
*/
|
|
11338
|
-
async function getAnalyzerInstructionsContent$3(
|
|
11339
|
-
if (typeof
|
|
11340
|
-
console.error('Error:
|
|
11578
|
+
async function getAnalyzerInstructionsContent$3(analyzersBasePath, analyzerId) {
|
|
11579
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
11580
|
+
console.error('Error: analyzersBasePath is required.');
|
|
11341
11581
|
return null;
|
|
11342
11582
|
}
|
|
11343
11583
|
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
@@ -11352,10 +11592,10 @@ async function getAnalyzerInstructionsContent$3(analyzeMessagesBasePath, analyze
|
|
|
11352
11592
|
}
|
|
11353
11593
|
const [analyzerName, contentType, instructionsType] = parts;
|
|
11354
11594
|
|
|
11355
|
-
const instructionsFilePath = path$
|
|
11595
|
+
const instructionsFilePath = path$6.join(analyzersBasePath, analyzerName, contentType, instructionsType, '1.md');
|
|
11356
11596
|
|
|
11357
11597
|
try {
|
|
11358
|
-
const fileContent = await fs$
|
|
11598
|
+
const fileContent = await fs$8.readFile(instructionsFilePath, 'utf8');
|
|
11359
11599
|
const parts = fileContent.split('\n\n\n');
|
|
11360
11600
|
parts.shift();
|
|
11361
11601
|
return parts.join('\n\n\n');
|
|
@@ -11375,20 +11615,56 @@ var instructionLoader = {
|
|
|
11375
11615
|
};
|
|
11376
11616
|
|
|
11377
11617
|
/*
|
|
11618
|
+
* Component: AnalyzerUtils JSON Parser
|
|
11619
|
+
* Block-UUID: 4dd21efd-3ad3-43e1-adf0-d52d7c560970
|
|
11620
|
+
* Version: 1.0.0
|
|
11621
|
+
* Description: Provides utility functions for pre-processing JSON content from analyzer instructions.
|
|
11622
|
+
* Language: JavaScript
|
|
11623
|
+
* Created-at: 2025-11-23T05:38:15.725Z
|
|
11624
|
+
* Authors: GLM-4.6 (v1.0.0)
|
|
11625
|
+
*/
|
|
11626
|
+
|
|
11627
|
+
/**
|
|
11628
|
+
* Pre-processes JSON content to quote unquoted template strings before parsing.
|
|
11629
|
+
* This handles cases where {{SYSTEM: ...}} and {{ANALYZER: ...}} placeholders
|
|
11630
|
+
* are not properly quoted in the JSON.
|
|
11631
|
+
*
|
|
11632
|
+
* @param {string} jsonString - The raw JSON string content.
|
|
11633
|
+
* @returns {string} The processed JSON string with template strings quoted.
|
|
11634
|
+
*/
|
|
11635
|
+
function preprocessJsonForValidation$5(jsonString) {
|
|
11636
|
+
// Find all unquoted template strings and quote them with proper escaping
|
|
11637
|
+
// This regex looks for template strings that aren't already quoted
|
|
11638
|
+
return jsonString.replace(
|
|
11639
|
+
/(?<!")(\{\{(SYSTEM|ANALYZER):[^}]+\}\})(?!")/g,
|
|
11640
|
+
(match, template) => {
|
|
11641
|
+
// Escape any double quotes within the template string
|
|
11642
|
+
const escapedTemplate = template.replace(/"/g, '\\"');
|
|
11643
|
+
return `"${escapedTemplate}"`;
|
|
11644
|
+
}
|
|
11645
|
+
);
|
|
11646
|
+
}
|
|
11647
|
+
|
|
11648
|
+
var jsonParser = {
|
|
11649
|
+
preprocessJsonForValidation: preprocessJsonForValidation$5
|
|
11650
|
+
};
|
|
11651
|
+
|
|
11652
|
+
/**
|
|
11378
11653
|
* Component: AnalyzerUtils Discovery
|
|
11379
|
-
* Block-UUID:
|
|
11380
|
-
* Parent-UUID:
|
|
11381
|
-
* Version: 1.1
|
|
11382
|
-
* Description: Provides utility functions for discovering available analyzers.
|
|
11654
|
+
* Block-UUID: 26a7df9b-ef29-4dcd-aab2-9cdc3a11133c
|
|
11655
|
+
* Parent-UUID: aa999515-84fb-43f6-91a7-cf79248d7286
|
|
11656
|
+
* Version: 1.3.1
|
|
11657
|
+
* Description: Provides utility functions for discovering available analyzers. Updated to include version and tags in analyzer objects.
|
|
11383
11658
|
* Language: JavaScript
|
|
11384
|
-
* Created-at: 2025-
|
|
11385
|
-
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
11659
|
+
* Created-at: 2025-11-27T14:45:30.978Z
|
|
11660
|
+
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0), GLM-4.6 (v1.2.1), GLM-4.6 (v1.3.0), GLM-4.6 (v1.3.1)
|
|
11386
11661
|
*/
|
|
11387
11662
|
|
|
11388
|
-
const fs$
|
|
11389
|
-
const path$
|
|
11663
|
+
const fs$7 = require$$0.promises;
|
|
11664
|
+
const path$5 = require$$1;
|
|
11390
11665
|
const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$2 } = instructionLoader;
|
|
11391
|
-
const
|
|
11666
|
+
const { preprocessJsonForValidation: preprocessJsonForValidation$4 } = jsonParser;
|
|
11667
|
+
const CodeBlockUtils$4 = CodeBlockUtils$7;
|
|
11392
11668
|
|
|
11393
11669
|
/**
|
|
11394
11670
|
* Reads and parses the config.json file in a directory.
|
|
@@ -11396,10 +11672,10 @@ const CodeBlockUtils$2 = CodeBlockUtils$5;
|
|
|
11396
11672
|
* @returns {Promise<object|null>} A promise that resolves to the parsed config object
|
|
11397
11673
|
* or null if the file doesn't exist or is invalid.
|
|
11398
11674
|
*/
|
|
11399
|
-
async function readConfig$
|
|
11400
|
-
const configPath = path$
|
|
11675
|
+
async function readConfig$2(dirPath) {
|
|
11676
|
+
const configPath = path$5.join(dirPath, 'config.json');
|
|
11401
11677
|
try {
|
|
11402
|
-
const fileContent = await fs$
|
|
11678
|
+
const fileContent = await fs$7.readFile(configPath, 'utf8');
|
|
11403
11679
|
return JSON.parse(fileContent);
|
|
11404
11680
|
} catch (error) {
|
|
11405
11681
|
if (error.code !== 'ENOENT') {
|
|
@@ -11411,12 +11687,12 @@ async function readConfig$1(dirPath) {
|
|
|
11411
11687
|
}
|
|
11412
11688
|
|
|
11413
11689
|
/**
|
|
11414
|
-
* Checks if a directory name is valid
|
|
11690
|
+
* Checks if a directory name is valid
|
|
11415
11691
|
* Allowed: a-z, A-Z, 0-9, dash (-), underscore (_). Cannot start with underscore or contain dots.
|
|
11416
11692
|
* @param {string} name - The directory name to check.
|
|
11417
11693
|
* @returns {boolean} True if the name is valid, false otherwise.
|
|
11418
11694
|
*/
|
|
11419
|
-
function isValidDirName(name) {
|
|
11695
|
+
function isValidDirName$2(name) {
|
|
11420
11696
|
// Exclude names starting with underscore or containing dots
|
|
11421
11697
|
if (name.startsWith('_') || name.includes('.')) {
|
|
11422
11698
|
return false;
|
|
@@ -11429,51 +11705,53 @@ function isValidDirName(name) {
|
|
|
11429
11705
|
* Discovers and lists all available analyzers by traversing the directory structure.
|
|
11430
11706
|
* An analyzer is considered valid if a '1.md' file exists in the instructions directory.
|
|
11431
11707
|
*
|
|
11432
|
-
* @param {string}
|
|
11708
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers (e.g., 'analyzers/analyzer-1').
|
|
11433
11709
|
* @param {object} [options={}] - Optional configuration.
|
|
11434
|
-
* @
|
|
11435
|
-
* @returns {Promise<Array<{id: string, label: string, name: string, protected: boolean, description?: string}>>} A promise that resolves to an array of analyzer objects.
|
|
11710
|
+
* @returns {Promise<Array<{id: string, label: string, name: string, protected: boolean, description?: string, version?: string, tags?: Array<string>}>>} A promise that resolves to an array of analyzer objects.
|
|
11436
11711
|
*/
|
|
11437
|
-
async function getAnalyzers$
|
|
11438
|
-
const { includeDescription = false } = options;
|
|
11712
|
+
async function getAnalyzers$3(analyzersBasePath, options = {}) {
|
|
11439
11713
|
const analyzers = [];
|
|
11714
|
+
const demoAnalyzerPattern = /^demo-.+-\w{6}$/;
|
|
11440
11715
|
|
|
11441
11716
|
try {
|
|
11442
|
-
const analyzerEntries = await fs$
|
|
11717
|
+
const analyzerEntries = await fs$7.readdir(analyzersBasePath, { withFileTypes: true });
|
|
11443
11718
|
|
|
11444
11719
|
for (const analyzerEntry of analyzerEntries) {
|
|
11445
|
-
if (analyzerEntry.isDirectory() && isValidDirName(analyzerEntry.name)) {
|
|
11720
|
+
if (analyzerEntry.isDirectory() && isValidDirName$2(analyzerEntry.name)) {
|
|
11446
11721
|
const analyzerName = analyzerEntry.name;
|
|
11447
|
-
const analyzerPath = path$
|
|
11448
|
-
const analyzerConfig = await readConfig$
|
|
11722
|
+
const analyzerPath = path$5.join(analyzersBasePath, analyzerName);
|
|
11723
|
+
const analyzerConfig = await readConfig$2(analyzerPath);
|
|
11449
11724
|
const analyzerLabel = analyzerConfig?.label || analyzerName;
|
|
11450
11725
|
|
|
11451
|
-
const contentEntries = await fs$
|
|
11726
|
+
const contentEntries = await fs$7.readdir(analyzerPath, { withFileTypes: true });
|
|
11452
11727
|
|
|
11453
11728
|
for (const contentEntry of contentEntries) {
|
|
11454
|
-
if (contentEntry.isDirectory() && isValidDirName(contentEntry.name)) {
|
|
11729
|
+
if (contentEntry.isDirectory() && isValidDirName$2(contentEntry.name)) {
|
|
11455
11730
|
const contentType = contentEntry.name;
|
|
11456
|
-
const contentPath = path$
|
|
11457
|
-
const contentConfig = await readConfig$
|
|
11731
|
+
const contentPath = path$5.join(analyzerPath, contentType);
|
|
11732
|
+
const contentConfig = await readConfig$2(contentPath);
|
|
11458
11733
|
const contentLabel = contentConfig?.label || contentType;
|
|
11459
11734
|
|
|
11460
|
-
const instructionsEntries = await fs$
|
|
11735
|
+
const instructionsEntries = await fs$7.readdir(contentPath, { withFileTypes: true });
|
|
11461
11736
|
|
|
11462
11737
|
for (const instructionsEntry of instructionsEntries) {
|
|
11463
|
-
if (instructionsEntry.isDirectory() && isValidDirName(instructionsEntry.name)) {
|
|
11738
|
+
if (instructionsEntry.isDirectory() && isValidDirName$2(instructionsEntry.name)) {
|
|
11464
11739
|
const instructionsType = instructionsEntry.name;
|
|
11465
|
-
const instructionsPath = path$
|
|
11466
|
-
const instructionsConfig = await readConfig$
|
|
11740
|
+
const instructionsPath = path$5.join(contentPath, instructionsType);
|
|
11741
|
+
const instructionsConfig = await readConfig$2(instructionsPath);
|
|
11467
11742
|
const instructionsLabel = instructionsConfig?.label || instructionsType;
|
|
11468
11743
|
|
|
11744
|
+
// Construct the analyzer ID and label
|
|
11745
|
+
const analyzerId = `${analyzerName}::${contentType}::${instructionsType}`;
|
|
11746
|
+
|
|
11469
11747
|
// Check for the existence of 1.md to confirm a valid analyzer configuration
|
|
11470
|
-
const instructionsFilePath = path$
|
|
11748
|
+
const instructionsFilePath = path$5.join(instructionsPath, '1.md');
|
|
11471
11749
|
try {
|
|
11472
|
-
await fs$
|
|
11750
|
+
await fs$7.access(instructionsFilePath); // Check if file exists and is accessible
|
|
11473
11751
|
|
|
11474
11752
|
// If analyzerName starts with 'tutorial-', check its last modified time.
|
|
11475
|
-
if (analyzerName.startsWith('tutorial-')) {
|
|
11476
|
-
const stats = await fs$
|
|
11753
|
+
if (analyzerName.startsWith('tutorial-') || demoAnalyzerPattern.test(analyzerName)) {
|
|
11754
|
+
const stats = await fs$7.stat(instructionsFilePath);
|
|
11477
11755
|
const lastModified = stats.mtime.getTime(); // Get timestamp in milliseconds
|
|
11478
11756
|
const sixtyMinutesAgo = Date.now() - (60 * 60 * 1000); // Current time - 60 minutes in ms
|
|
11479
11757
|
|
|
@@ -11482,37 +11760,43 @@ async function getAnalyzers$2(analyzeMessagesBasePath, options = {}) {
|
|
|
11482
11760
|
continue;
|
|
11483
11761
|
}
|
|
11484
11762
|
}
|
|
11485
|
-
//
|
|
11486
|
-
const
|
|
11487
|
-
const analyzerFullLabel = `${analyzerLabel} (${contentLabel} - ${instructionsLabel})`;
|
|
11763
|
+
// TODO: Decide if we should show the contentLabel and instructionsLabel. For now we will ignore them.
|
|
11764
|
+
const analyzerFullLabel = `${analyzerLabel}`; // (${contentLabel} - ${instructionsLabel})`;
|
|
11488
11765
|
|
|
11766
|
+
// Extract description, version, and tags from the JSON block in 1.md
|
|
11489
11767
|
let description = null;
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11768
|
+
let version = null;
|
|
11769
|
+
let tags = [];
|
|
11770
|
+
let label = null;
|
|
11771
|
+
let requires_reference_files = null;
|
|
11772
|
+
|
|
11773
|
+
try {
|
|
11774
|
+
const content = await getAnalyzerInstructionsContent$2(analyzersBasePath, analyzerId);
|
|
11775
|
+
const { blocks, warnings } = CodeBlockUtils$4.extractCodeBlocks(content, { silent: true });
|
|
11776
|
+
const jsonBlock = blocks.find(block => block.language === 'json');
|
|
11777
|
+
|
|
11778
|
+
if (jsonBlock && jsonBlock.content) {
|
|
11779
|
+
const preprocessedContent = preprocessJsonForValidation$4(jsonBlock.content);
|
|
11780
|
+
const json = JSON.parse(preprocessedContent);
|
|
11781
|
+
description = json.description || null;
|
|
11782
|
+
label = json.label || null;
|
|
11783
|
+
requires_reference_files = json.requires_reference_files || false;
|
|
11784
|
+
version = json.version || null;
|
|
11785
|
+
tags = Array.isArray(json.tags) ? json.tags : [];
|
|
11507
11786
|
}
|
|
11787
|
+
} catch (descError) {
|
|
11788
|
+
console.warn(`Warning: Could not load metadata for ${analyzerId}: ${descError.message}`);
|
|
11508
11789
|
}
|
|
11509
11790
|
|
|
11510
11791
|
analyzers.push({
|
|
11511
11792
|
id: analyzerId,
|
|
11512
|
-
label: analyzerFullLabel,
|
|
11513
11793
|
name: analyzerName,
|
|
11794
|
+
description,
|
|
11795
|
+
label: label || analyzerFullLabel,
|
|
11796
|
+
requires_reference_files,
|
|
11514
11797
|
protected: analyzerConfig?.protected || false,
|
|
11515
|
-
|
|
11798
|
+
version,
|
|
11799
|
+
tags
|
|
11516
11800
|
});
|
|
11517
11801
|
} catch (error) {
|
|
11518
11802
|
// If 1.md doesn't exist, this is not a complete analyzer configuration, skip.
|
|
@@ -11527,7 +11811,7 @@ async function getAnalyzers$2(analyzeMessagesBasePath, options = {}) {
|
|
|
11527
11811
|
}
|
|
11528
11812
|
}
|
|
11529
11813
|
} catch (error) {
|
|
11530
|
-
console.error(`Error traversing
|
|
11814
|
+
console.error(`Error traversing analyzers directory ${analyzersBasePath}: ${error.message}`);
|
|
11531
11815
|
// Depending on requirements, you might want to throw the error or return an empty array
|
|
11532
11816
|
throw error; // Re-throw to indicate failure
|
|
11533
11817
|
}
|
|
@@ -11536,8 +11820,10 @@ async function getAnalyzers$2(analyzeMessagesBasePath, options = {}) {
|
|
|
11536
11820
|
}
|
|
11537
11821
|
|
|
11538
11822
|
var discovery = {
|
|
11539
|
-
getAnalyzers: getAnalyzers$
|
|
11540
|
-
readConfig: readConfig$
|
|
11823
|
+
getAnalyzers: getAnalyzers$3,
|
|
11824
|
+
readConfig: readConfig$2,
|
|
11825
|
+
isValidDirName: isValidDirName$2,
|
|
11826
|
+
};
|
|
11541
11827
|
|
|
11542
11828
|
/**
|
|
11543
11829
|
* Component: Analyzer Saver Utility
|
|
@@ -11550,8 +11836,8 @@ var discovery = {
|
|
|
11550
11836
|
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash Thinking (v1.1.0)
|
|
11551
11837
|
*/
|
|
11552
11838
|
|
|
11553
|
-
const fs$
|
|
11554
|
-
const path$
|
|
11839
|
+
const fs$6 = require$$0.promises;
|
|
11840
|
+
const path$4 = require$$1;
|
|
11555
11841
|
|
|
11556
11842
|
/**
|
|
11557
11843
|
* Saves or updates an analyzer configuration.
|
|
@@ -11561,19 +11847,19 @@ const path$3 = require$$1;
|
|
|
11561
11847
|
* if necessary, saves the instructions to '1.md'. Optionally, it can
|
|
11562
11848
|
* ensure config.json files exist with labels derived from directory names.
|
|
11563
11849
|
*
|
|
11564
|
-
* @param {string}
|
|
11850
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers (e.g., 'analyzers/analyzer-1').
|
|
11565
11851
|
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11566
11852
|
* @param {string} instructionsContent - The full content of the analyzer instructions message to be saved in '1.md'.
|
|
11567
11853
|
* @param {object} [options={}] - Optional configuration options.
|
|
11568
11854
|
* @param {boolean} [options.ensureConfigs=false] - If true, ensures config.json files exist in the analyzer, content, and instructions directories. Defaults to false.
|
|
11569
11855
|
* @returns {Promise<{success: boolean, message?: string}>} A promise that resolves with a result object.
|
|
11570
11856
|
*/
|
|
11571
|
-
async function saveConfiguration$
|
|
11857
|
+
async function saveConfiguration$2(analyzersBasePath, analyzerId, instructionsContent, options = {}) {
|
|
11572
11858
|
const { ensureConfigs = false } = options;
|
|
11573
11859
|
|
|
11574
11860
|
// 1. Validate inputs
|
|
11575
|
-
if (typeof
|
|
11576
|
-
return { success: false, message: '
|
|
11861
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
11862
|
+
return { success: false, message: 'analyzersBasePath is required.' };
|
|
11577
11863
|
}
|
|
11578
11864
|
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11579
11865
|
return { success: false, message: 'analyzerId is required.' };
|
|
@@ -11606,18 +11892,18 @@ async function saveConfiguration$1(analyzeMessagesBasePath, analyzerId, instruct
|
|
|
11606
11892
|
}
|
|
11607
11893
|
|
|
11608
11894
|
// 3. Construct directory paths
|
|
11609
|
-
const analyzerDir = path$
|
|
11610
|
-
const contentDir = path$
|
|
11611
|
-
const instructionsDir = path$
|
|
11612
|
-
const instructionsFilePath = path$
|
|
11895
|
+
const analyzerDir = path$4.join(analyzersBasePath, analyzerName);
|
|
11896
|
+
const contentDir = path$4.join(analyzerDir, contentType);
|
|
11897
|
+
const instructionsDir = path$4.join(contentDir, instructionsType);
|
|
11898
|
+
const instructionsFilePath = path$4.join(instructionsDir, '1.md');
|
|
11613
11899
|
|
|
11614
11900
|
try {
|
|
11615
11901
|
// 4. Create directories recursively
|
|
11616
|
-
await fs$
|
|
11902
|
+
await fs$6.mkdir(instructionsDir, { recursive: true });
|
|
11617
11903
|
|
|
11618
11904
|
// 5. Save instructions content to 1.md
|
|
11619
11905
|
const finalContent = `; role: assistant\n\n\n${instructionsContent}`;
|
|
11620
|
-
await fs$
|
|
11906
|
+
await fs$6.writeFile(instructionsFilePath, finalContent, 'utf8');
|
|
11621
11907
|
|
|
11622
11908
|
// 6. Optionally create/Update config.json files
|
|
11623
11909
|
if (ensureConfigs) {
|
|
@@ -11643,11 +11929,11 @@ async function saveConfiguration$1(analyzeMessagesBasePath, analyzerId, instruct
|
|
|
11643
11929
|
* @param {string} label - The label to ensure is in the config.json.
|
|
11644
11930
|
*/
|
|
11645
11931
|
async function ensureConfigJson(dirPath, label) {
|
|
11646
|
-
const configPath = path$
|
|
11932
|
+
const configPath = path$4.join(dirPath, 'config.json');
|
|
11647
11933
|
let config = {};
|
|
11648
11934
|
|
|
11649
11935
|
try {
|
|
11650
|
-
const fileContent = await fs$
|
|
11936
|
+
const fileContent = await fs$6.readFile(configPath, 'utf8');
|
|
11651
11937
|
config = JSON.parse(fileContent);
|
|
11652
11938
|
} catch (error) {
|
|
11653
11939
|
// If file doesn't exist or parsing fails, start with an empty config
|
|
@@ -11664,28 +11950,103 @@ async function ensureConfigJson(dirPath, label) {
|
|
|
11664
11950
|
}
|
|
11665
11951
|
|
|
11666
11952
|
// Write the updated config back to the file
|
|
11667
|
-
await fs$
|
|
11953
|
+
await fs$6.writeFile(configPath, JSON.stringify(config, null, 4), 'utf8');
|
|
11668
11954
|
}
|
|
11669
11955
|
|
|
11670
11956
|
|
|
11671
11957
|
var saver = {
|
|
11672
|
-
saveConfiguration: saveConfiguration$
|
|
11958
|
+
saveConfiguration: saveConfiguration$2,
|
|
11673
11959
|
};
|
|
11674
11960
|
|
|
11675
|
-
|
|
11961
|
+
/**
|
|
11676
11962
|
* Component: AnalyzerUtils Schema Loader
|
|
11677
|
-
* Block-UUID:
|
|
11678
|
-
* Parent-UUID:
|
|
11679
|
-
* Version: 1.
|
|
11963
|
+
* Block-UUID: bf25c501-f9e1-4e5b-ad22-9ed24ba50787
|
|
11964
|
+
* Parent-UUID: 66208fdc-2c80-4264-8500-06d5f4db103a
|
|
11965
|
+
* Version: 1.4.1
|
|
11680
11966
|
* Description: Provides utility functions for retrieving and deducing JSON schemas for analyzers.
|
|
11681
11967
|
* Language: JavaScript
|
|
11682
|
-
* Created-at: 2025-
|
|
11683
|
-
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11968
|
+
* Created-at: 2025-11-23T05:40:43.016Z
|
|
11969
|
+
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Pro (v1.1.0), Claude Haiku 4.5 (v1.2.0), Claude Haiku 4.5 (v1.3.0), Qwen 3 Coder 480B - Cerebras (v1.4.0), GLM-4.6 (v1.4.1)
|
|
11684
11970
|
*/
|
|
11685
11971
|
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11972
|
+
/**
|
|
11973
|
+
* Parses the 'Custom Metadata Definitions' block from the markdown content.
|
|
11974
|
+
* Handles both formats:
|
|
11975
|
+
* - With backticks: * `fieldName` (type): description
|
|
11976
|
+
* - Without backticks: * fieldName (type): description
|
|
11977
|
+
*
|
|
11978
|
+
* @param {string} markdownContent - The full content of the 1.md file.
|
|
11979
|
+
* @returns {Map<string, {type: string, description: string}>} A map from field name to its type and description.
|
|
11980
|
+
*/
|
|
11981
|
+
function parseMetadataDefinitions(markdownContent) {
|
|
11982
|
+
const definitions = new Map();
|
|
11983
|
+
|
|
11984
|
+
// Match the "### Custom Metadata Definitions" section until the next code block or section
|
|
11985
|
+
const sectionRegex = /### Custom Metadata Definitions\s*([\s\S]*?)(?=```|\n##|\n---)/;
|
|
11986
|
+
const match = markdownContent.match(sectionRegex);
|
|
11987
|
+
|
|
11988
|
+
if (!match || !match[1]) {
|
|
11989
|
+
return definitions;
|
|
11990
|
+
}
|
|
11991
|
+
|
|
11992
|
+
const definitionBlock = match[1];
|
|
11993
|
+
|
|
11994
|
+
// Regex to match both formats:
|
|
11995
|
+
// Format 1: * `fieldName` (type): description
|
|
11996
|
+
// Format 2: * fieldName (type): description
|
|
11997
|
+
// Capture groups:
|
|
11998
|
+
// Group 1: backtick-wrapped field name (if present)
|
|
11999
|
+
// Group 2: non-backtick field name (if present)
|
|
12000
|
+
// Group 3: field type
|
|
12001
|
+
// Group 4: description
|
|
12002
|
+
const lineRegex = /^\s*\*\s+(?:`([^`]+)`|([a-zA-Z0-9_-]+))\s+\(([^)]+)\):\s*(.+)/gm;
|
|
12003
|
+
|
|
12004
|
+
let lineMatch;
|
|
12005
|
+
while ((lineMatch = lineRegex.exec(definitionBlock)) !== null) {
|
|
12006
|
+
// Extract field name from either group 1 (backtick-wrapped) or group 2 (plain)
|
|
12007
|
+
const fieldName = (lineMatch[1] || lineMatch[2]).trim();
|
|
12008
|
+
const fieldType = lineMatch[3].trim();
|
|
12009
|
+
const description = lineMatch[4].trim();
|
|
12010
|
+
|
|
12011
|
+
if (fieldName && fieldType && description) {
|
|
12012
|
+
definitions.set(fieldName, { type: fieldType, description });
|
|
12013
|
+
}
|
|
12014
|
+
}
|
|
12015
|
+
|
|
12016
|
+
return definitions;
|
|
12017
|
+
}
|
|
12018
|
+
|
|
12019
|
+
const fs$5 = require$$0.promises;
|
|
12020
|
+
const path$3 = require$$1;
|
|
12021
|
+
const CodeBlockUtils$3 = CodeBlockUtils$7;
|
|
12022
|
+
const { preprocessJsonForValidation: preprocessJsonForValidation$3 } = jsonParser;
|
|
12023
|
+
|
|
12024
|
+
/**
|
|
12025
|
+
* Maps a simple type string (from the definitions block) to a JSON schema type object.
|
|
12026
|
+
* @param {string} simpleType - The type string (e.g., "number", "array of strings").
|
|
12027
|
+
* @returns {object} A JSON schema type definition.
|
|
12028
|
+
*/
|
|
12029
|
+
function mapSimpleTypeToSchema(simpleType) {
|
|
12030
|
+
const lowerType = simpleType.toLowerCase().trim();
|
|
12031
|
+
switch (lowerType) {
|
|
12032
|
+
case 'string':
|
|
12033
|
+
return { type: 'string' };
|
|
12034
|
+
case 'number':
|
|
12035
|
+
case 'integer':
|
|
12036
|
+
return { type: 'number' };
|
|
12037
|
+
case 'boolean':
|
|
12038
|
+
return { type: 'boolean' };
|
|
12039
|
+
case 'array of strings':
|
|
12040
|
+
return { type: 'array', items: { type: 'string' } };
|
|
12041
|
+
case 'date':
|
|
12042
|
+
return { type: 'string', format: 'date' };
|
|
12043
|
+
case 'datetime':
|
|
12044
|
+
case 'iso 8601 timestamp':
|
|
12045
|
+
return { type: 'string', format: 'date-time' };
|
|
12046
|
+
default:
|
|
12047
|
+
return { type: 'string' }; // Default to string for unknown types
|
|
12048
|
+
}
|
|
12049
|
+
}
|
|
11689
12050
|
|
|
11690
12051
|
/**
|
|
11691
12052
|
* Deduces the JSON schema type and format/items from a string value pattern.
|
|
@@ -11698,6 +12059,15 @@ const CodeBlockUtils$1 = CodeBlockUtils$5;
|
|
|
11698
12059
|
*/
|
|
11699
12060
|
function deduceSchemaType(value, fieldName) {
|
|
11700
12061
|
const defaultSchema = { type: 'string' }; // Default fallback
|
|
12062
|
+
|
|
12063
|
+
// Handle new placeholder format {{SYSTEM: ...}} and {{ANALYZER: ...}}
|
|
12064
|
+
// These are valid placeholders and should not generate warnings
|
|
12065
|
+
if (typeof value === 'string') {
|
|
12066
|
+
const trimmedValue = value.trim();
|
|
12067
|
+
if (trimmedValue.startsWith('{{SYSTEM:') || trimmedValue.startsWith('{{ANALYZER:')) {
|
|
12068
|
+
return defaultSchema; // Return default string schema for system/analyzer placeholders
|
|
12069
|
+
}
|
|
12070
|
+
}
|
|
11701
12071
|
|
|
11702
12072
|
if (typeof value !== 'string') {
|
|
11703
12073
|
const jsType = typeof value;
|
|
@@ -11709,35 +12079,35 @@ function deduceSchemaType(value, fieldName) {
|
|
|
11709
12079
|
}
|
|
11710
12080
|
|
|
11711
12081
|
const trimmedValue = value.trim();
|
|
11712
|
-
|
|
12082
|
+
|
|
11713
12083
|
if (/^\[string:.*\]$/.test(trimmedValue) || (/^\[[^:]+\]$/.test(trimmedValue) && !/^\[(number|datetime|date|<string>):.*\]$/.test(trimmedValue))) {
|
|
11714
12084
|
return { type: 'string' };
|
|
11715
12085
|
}
|
|
11716
|
-
|
|
12086
|
+
|
|
11717
12087
|
if (/^\[number:.*\]$/.test(trimmedValue)) {
|
|
11718
12088
|
return { type: 'number' };
|
|
11719
12089
|
}
|
|
11720
|
-
|
|
12090
|
+
|
|
11721
12091
|
if (/^\[boolean:.*\]$/.test(trimmedValue)) {
|
|
11722
12092
|
return { type: 'boolean' };
|
|
11723
12093
|
}
|
|
11724
|
-
|
|
12094
|
+
|
|
11725
12095
|
if (/^\[date-*time:.*\]$/.test(trimmedValue)) {
|
|
11726
12096
|
return { type: 'string', format: 'date-time' };
|
|
11727
12097
|
}
|
|
11728
|
-
|
|
12098
|
+
|
|
11729
12099
|
if (/^\[date:.*\]$/.test(trimmedValue)) {
|
|
11730
12100
|
return { type: 'string', format: 'date' };
|
|
11731
12101
|
}
|
|
11732
|
-
|
|
12102
|
+
|
|
11733
12103
|
if (/^\[<string>:.*\]$/.test(trimmedValue) || trimmedValue.toLowerCase().includes('array of strings')) {
|
|
11734
12104
|
return { type: 'array', items: { type: 'string' } };
|
|
11735
12105
|
}
|
|
11736
|
-
|
|
12106
|
+
|
|
11737
12107
|
if (trimmedValue.toLowerCase().includes("output 'true' or 'false'") || trimmedValue.toLowerCase().includes("determine if") && (trimmedValue.toLowerCase().includes("true") || trimmedValue.toLowerCase().includes("false"))) {
|
|
11738
12108
|
return { type: 'boolean' };
|
|
11739
12109
|
}
|
|
11740
|
-
|
|
12110
|
+
|
|
11741
12111
|
console.warn(`Warning: Unknown metadata value pattern for field "${fieldName}". Defaulting to type 'string'. Value: "${value}"`);
|
|
11742
12112
|
return defaultSchema;
|
|
11743
12113
|
}
|
|
@@ -11748,14 +12118,14 @@ function deduceSchemaType(value, fieldName) {
|
|
|
11748
12118
|
* Reads the corresponding '1.md' file, extracts the JSON block,
|
|
11749
12119
|
* and deduces schema types from the string values.
|
|
11750
12120
|
*
|
|
11751
|
-
* @param {string}
|
|
12121
|
+
* @param {string} analyzersBasePath - The absolute or relative path to the base directory containing the analyzer message files (e.g., 'messages/analyze').
|
|
11752
12122
|
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11753
12123
|
* @returns {Promise<object|null>} A promise that resolves with the JSON schema object or null if the analyzer ID is invalid or the schema cannot be retrieved/parsed.
|
|
11754
12124
|
* @throws {Error} If the 1.md file is found but does not contain exactly one JSON code block.
|
|
11755
12125
|
*/
|
|
11756
|
-
async function getAnalyzerSchema$2(
|
|
11757
|
-
if (typeof
|
|
11758
|
-
console.error('Error:
|
|
12126
|
+
async function getAnalyzerSchema$2(analyzersBasePath, analyzerId) {
|
|
12127
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12128
|
+
console.error('Error: analyzersBasePath is required.');
|
|
11759
12129
|
return null;
|
|
11760
12130
|
}
|
|
11761
12131
|
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
@@ -11770,11 +12140,14 @@ async function getAnalyzerSchema$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11770
12140
|
}
|
|
11771
12141
|
const [analyzerName, contentType, instructionsType] = parts;
|
|
11772
12142
|
|
|
11773
|
-
const instructionsFilePath = path$
|
|
12143
|
+
const instructionsFilePath = path$3.join(analyzersBasePath, analyzerName, contentType, instructionsType, '1.md');
|
|
11774
12144
|
|
|
11775
12145
|
try {
|
|
11776
|
-
const fileContent = await fs$
|
|
11777
|
-
|
|
12146
|
+
const fileContent = await fs$5.readFile(instructionsFilePath, 'utf8');
|
|
12147
|
+
// New: Parse the structured definitions block first
|
|
12148
|
+
const definedFields = parseMetadataDefinitions(fileContent);
|
|
12149
|
+
|
|
12150
|
+
const { blocks } = CodeBlockUtils$3.extractCodeBlocks(fileContent, { silent: true });
|
|
11778
12151
|
const jsonBlocks = blocks.filter(block => block.type === 'code' && block.language === 'json');
|
|
11779
12152
|
|
|
11780
12153
|
if (jsonBlocks.length !== 1) {
|
|
@@ -11782,19 +12155,24 @@ async function getAnalyzerSchema$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11782
12155
|
}
|
|
11783
12156
|
|
|
11784
12157
|
const jsonBlockContent = jsonBlocks[0].content;
|
|
12158
|
+
const preprocessedContent = preprocessJsonForValidation$3(jsonBlockContent);
|
|
11785
12159
|
let rawJson = null;
|
|
11786
12160
|
try {
|
|
11787
|
-
rawJson = JSON.parse(
|
|
12161
|
+
rawJson = JSON.parse(preprocessedContent);
|
|
11788
12162
|
} catch (parseError) {
|
|
11789
12163
|
console.error(`Error parsing JSON content from ${instructionsFilePath}: ${parseError.message}`);
|
|
11790
12164
|
return null;
|
|
11791
12165
|
}
|
|
11792
12166
|
|
|
12167
|
+
const startOfInstructions = fileContent.indexOf('# Analyze ');
|
|
12168
|
+
|
|
11793
12169
|
const schema = {
|
|
11794
12170
|
type: 'object',
|
|
11795
12171
|
description: rawJson.description,
|
|
12172
|
+
version: rawJson.version,
|
|
11796
12173
|
properties: {},
|
|
11797
|
-
required: []
|
|
12174
|
+
required: [],
|
|
12175
|
+
instructions: fileContent.slice(startOfInstructions),
|
|
11798
12176
|
};
|
|
11799
12177
|
|
|
11800
12178
|
const metadataProperties = rawJson?.extracted_metadata;
|
|
@@ -11802,9 +12180,20 @@ async function getAnalyzerSchema$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11802
12180
|
if (metadataProperties && typeof metadataProperties === 'object') {
|
|
11803
12181
|
for (const fieldName in metadataProperties) {
|
|
11804
12182
|
if (Object.hasOwnProperty.call(metadataProperties, fieldName)) {
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
12183
|
+
let fieldSchema;
|
|
12184
|
+
let description;
|
|
12185
|
+
|
|
12186
|
+
if (definedFields.has(fieldName)) {
|
|
12187
|
+
// Priority 1: Use the explicit definition
|
|
12188
|
+
const definition = definedFields.get(fieldName);
|
|
12189
|
+
fieldSchema = mapSimpleTypeToSchema(definition.type);
|
|
12190
|
+
description = definition.description;
|
|
12191
|
+
} else {
|
|
12192
|
+
// Priority 2: Fallback for system fields or backward compatibility
|
|
12193
|
+
const rawValue = metadataProperties[fieldName];
|
|
12194
|
+
fieldSchema = deduceSchemaType(rawValue, fieldName);
|
|
12195
|
+
description = rawValue.match(/^\[\w+: ([^\]]+)\]/)?.[1] || '';
|
|
12196
|
+
}
|
|
11808
12197
|
|
|
11809
12198
|
schema.properties[fieldName] = {
|
|
11810
12199
|
...fieldSchema,
|
|
@@ -11818,7 +12207,6 @@ async function getAnalyzerSchema$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11818
12207
|
}
|
|
11819
12208
|
|
|
11820
12209
|
return schema;
|
|
11821
|
-
|
|
11822
12210
|
} catch (error) {
|
|
11823
12211
|
if (error.code === 'ENOENT') {
|
|
11824
12212
|
console.warn(`Analyzer instructions file not found: ${instructionsFilePath}`);
|
|
@@ -11835,7 +12223,7 @@ var schemaLoader = {
|
|
|
11835
12223
|
|
|
11836
12224
|
/*
|
|
11837
12225
|
* Component: AnalyzerUtils Management
|
|
11838
|
-
* Block-UUID:
|
|
12226
|
+
* Block-UUID: 6241f381-512b-48a7-b70e-6b45683831fe
|
|
11839
12227
|
* Parent-UUID: N/A
|
|
11840
12228
|
* Version: 1.0.0
|
|
11841
12229
|
* Description: Provides utility functions for managing (deleting) analyzer configurations.
|
|
@@ -11844,9 +12232,9 @@ var schemaLoader = {
|
|
|
11844
12232
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11845
12233
|
*/
|
|
11846
12234
|
|
|
11847
|
-
const fs$
|
|
11848
|
-
const path$
|
|
11849
|
-
const { readConfig } = discovery; // Import helper from discovery
|
|
12235
|
+
const fs$4 = require$$0.promises;
|
|
12236
|
+
const path$2 = require$$1;
|
|
12237
|
+
const { readConfig: readConfig$1 } = discovery; // Import helper from discovery
|
|
11850
12238
|
|
|
11851
12239
|
/**
|
|
11852
12240
|
* Checks if a directory is empty or only contains a config.json.
|
|
@@ -11855,7 +12243,7 @@ const { readConfig } = discovery; // Import helper from discovery
|
|
|
11855
12243
|
*/
|
|
11856
12244
|
async function isDirectoryEmpty(dirPath) {
|
|
11857
12245
|
try {
|
|
11858
|
-
const files = await fs$
|
|
12246
|
+
const files = await fs$4.readdir(dirPath);
|
|
11859
12247
|
return files.length === 0 || (files.length === 1 && files[0] === 'config.json');
|
|
11860
12248
|
} catch (error) {
|
|
11861
12249
|
if (error.code === 'ENOENT') {
|
|
@@ -11868,13 +12256,13 @@ async function isDirectoryEmpty(dirPath) {
|
|
|
11868
12256
|
/**
|
|
11869
12257
|
* Deletes a specific analyzer configuration and intelligently cleans up empty directories.
|
|
11870
12258
|
*
|
|
11871
|
-
* @param {string}
|
|
12259
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers (e.g., 'analyzers/analyzer-1').
|
|
11872
12260
|
* @param {string} analyzerId - The unique ID of the analyzer to delete (format: 'analyzer_name::content_type::instructions_type').
|
|
11873
12261
|
* @returns {Promise<{success: boolean, message: string}>} A promise that resolves with a result object indicating success or failure.
|
|
11874
12262
|
*/
|
|
11875
|
-
async function deleteAnalyzer$2(
|
|
11876
|
-
if (typeof
|
|
11877
|
-
return { success: false, message: '
|
|
12263
|
+
async function deleteAnalyzer$2(analyzersBasePath, analyzerId) {
|
|
12264
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12265
|
+
return { success: false, message: 'analyzersBasePath is required.' };
|
|
11878
12266
|
}
|
|
11879
12267
|
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11880
12268
|
return { success: false, message: 'analyzerId is required.' };
|
|
@@ -11886,31 +12274,31 @@ async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11886
12274
|
}
|
|
11887
12275
|
const [analyzerName, contentType, instructionsType] = parts;
|
|
11888
12276
|
|
|
11889
|
-
const analyzerDir = path$
|
|
11890
|
-
const contentDir = path$
|
|
11891
|
-
const instructionsDir = path$
|
|
11892
|
-
const instructionsFilePath = path$
|
|
12277
|
+
const analyzerDir = path$2.join(analyzersBasePath, analyzerName);
|
|
12278
|
+
const contentDir = path$2.join(analyzerDir, contentType);
|
|
12279
|
+
const instructionsDir = path$2.join(contentDir, instructionsType);
|
|
12280
|
+
const instructionsFilePath = path$2.join(instructionsDir, '1.md');
|
|
11893
12281
|
|
|
11894
12282
|
try {
|
|
11895
12283
|
// 1. Check for protection at all levels
|
|
11896
|
-
const analyzerConfig = await readConfig(analyzerDir);
|
|
12284
|
+
const analyzerConfig = await readConfig$1(analyzerDir);
|
|
11897
12285
|
if (analyzerConfig?.protected) {
|
|
11898
12286
|
return { success: false, message: `Analyzer '${analyzerName}' is protected and cannot be deleted.` };
|
|
11899
12287
|
}
|
|
11900
12288
|
|
|
11901
|
-
const contentConfig = await readConfig(contentDir);
|
|
12289
|
+
const contentConfig = await readConfig$1(contentDir);
|
|
11902
12290
|
if (contentConfig?.protected) {
|
|
11903
12291
|
return { success: false, message: `Content type '${contentType}' for analyzer '${analyzerName}' is protected and cannot be deleted.` };
|
|
11904
12292
|
}
|
|
11905
12293
|
|
|
11906
|
-
const instructionsConfig = await readConfig(instructionsDir);
|
|
12294
|
+
const instructionsConfig = await readConfig$1(instructionsDir);
|
|
11907
12295
|
if (instructionsConfig?.protected) {
|
|
11908
12296
|
return { success: false, message: `Instructions type '${instructionsType}' for content type '${contentType}' is protected and cannot be deleted.` };
|
|
11909
12297
|
}
|
|
11910
12298
|
|
|
11911
12299
|
// 2. Delete the 1.md file
|
|
11912
12300
|
try {
|
|
11913
|
-
await fs$
|
|
12301
|
+
await fs$4.unlink(instructionsFilePath);
|
|
11914
12302
|
} catch (error) {
|
|
11915
12303
|
if (error.code === 'ENOENT') {
|
|
11916
12304
|
return { success: false, message: `Analyzer instructions file not found: ${instructionsFilePath}. It may have already been deleted.` };
|
|
@@ -11924,7 +12312,7 @@ async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11924
12312
|
// Check and delete instructions directory
|
|
11925
12313
|
if (await isDirectoryEmpty(instructionsDir)) {
|
|
11926
12314
|
try {
|
|
11927
|
-
await fs$
|
|
12315
|
+
await fs$4.rmdir(instructionsDir);
|
|
11928
12316
|
deletedDirs.push(instructionsDir);
|
|
11929
12317
|
} catch (error) {
|
|
11930
12318
|
console.warn(`Warning: Could not remove empty instructions directory ${instructionsDir}: ${error.message}`);
|
|
@@ -11934,7 +12322,7 @@ async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11934
12322
|
// Check and delete content directory
|
|
11935
12323
|
if (await isDirectoryEmpty(contentDir)) {
|
|
11936
12324
|
try {
|
|
11937
|
-
await fs$
|
|
12325
|
+
await fs$4.rmdir(contentDir);
|
|
11938
12326
|
deletedDirs.push(contentDir);
|
|
11939
12327
|
} catch (error) {
|
|
11940
12328
|
console.warn(`Warning: Could not remove empty content directory ${contentDir}: ${error.message}`);
|
|
@@ -11944,7 +12332,7 @@ async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11944
12332
|
// Check and delete analyzer directory
|
|
11945
12333
|
if (await isDirectoryEmpty(analyzerDir)) {
|
|
11946
12334
|
try {
|
|
11947
|
-
await fs$
|
|
12335
|
+
await fs$4.rmdir(analyzerDir);
|
|
11948
12336
|
deletedDirs.push(analyzerDir);
|
|
11949
12337
|
} catch (error) {
|
|
11950
12338
|
console.warn(`Warning: Could not remove empty analyzer directory ${analyzerDir}: ${error.message}`);
|
|
@@ -11960,7 +12348,9 @@ async function deleteAnalyzer$2(analyzeMessagesBasePath, analyzerId) {
|
|
|
11960
12348
|
}
|
|
11961
12349
|
|
|
11962
12350
|
var management = {
|
|
11963
|
-
deleteAnalyzer: deleteAnalyzer$2
|
|
12351
|
+
deleteAnalyzer: deleteAnalyzer$2,
|
|
12352
|
+
isDirectoryEmpty,
|
|
12353
|
+
};
|
|
11964
12354
|
|
|
11965
12355
|
/*
|
|
11966
12356
|
* Component: AnalyzerUtils Default Prompt Loader
|
|
@@ -11973,25 +12363,25 @@ var management = {
|
|
|
11973
12363
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
11974
12364
|
*/
|
|
11975
12365
|
|
|
11976
|
-
const fs$
|
|
11977
|
-
const path = require$$1;
|
|
12366
|
+
const fs$3 = require$$0.promises;
|
|
12367
|
+
const path$1 = require$$1;
|
|
11978
12368
|
|
|
11979
12369
|
/**
|
|
11980
12370
|
* Retrieves the raw Markdown content of the shared system message ('_shared/system/1.md').
|
|
11981
12371
|
*
|
|
11982
|
-
* @param {string}
|
|
12372
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers (e.g., 'analyzers/analyzer-1').
|
|
11983
12373
|
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content, or null if not found/invalid.
|
|
11984
12374
|
*/
|
|
11985
|
-
async function getSystemMessageContent$2(
|
|
11986
|
-
if (typeof
|
|
11987
|
-
console.error('Error:
|
|
12375
|
+
async function getSystemMessageContent$2(analyzersBasePath) {
|
|
12376
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12377
|
+
console.error('Error: analyzersBasePath is required for getSystemMessageContent.');
|
|
11988
12378
|
return null;
|
|
11989
12379
|
}
|
|
11990
12380
|
|
|
11991
|
-
const systemMessageFilePath = path.join(
|
|
12381
|
+
const systemMessageFilePath = path$1.join(analyzersBasePath, '_shared', 'system', '1.md');
|
|
11992
12382
|
|
|
11993
12383
|
try {
|
|
11994
|
-
const fileContent = await fs$
|
|
12384
|
+
const fileContent = await fs$3.readFile(systemMessageFilePath, 'utf8');
|
|
11995
12385
|
const parts = fileContent.split('\n\n\n');
|
|
11996
12386
|
parts.shift();
|
|
11997
12387
|
return parts.join('\n\n\n');
|
|
@@ -12009,19 +12399,19 @@ async function getSystemMessageContent$2(analyzeMessagesBasePath) {
|
|
|
12009
12399
|
/**
|
|
12010
12400
|
* Retrieves the raw Markdown content of the shared start message ('_shared/start/1.md').
|
|
12011
12401
|
*
|
|
12012
|
-
* @param {string}
|
|
12402
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers (e.g., 'analyzers/analyzer-1').
|
|
12013
12403
|
* @returns {Promise<string|null>} A promise that resolves with the full Markdown content, or null if not found/invalid.
|
|
12014
12404
|
*/
|
|
12015
|
-
async function getStartMessageContent$2(
|
|
12016
|
-
if (typeof
|
|
12017
|
-
console.error('Error:
|
|
12405
|
+
async function getStartMessageContent$2(analyzersBasePath) {
|
|
12406
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12407
|
+
console.error('Error: analyzersBasePath is required for getStartMessageContent.');
|
|
12018
12408
|
return null;
|
|
12019
12409
|
}
|
|
12020
12410
|
|
|
12021
|
-
const startMessageFilePath = path.join(
|
|
12411
|
+
const startMessageFilePath = path$1.join(analyzersBasePath, '_shared', 'start', '1.md');
|
|
12022
12412
|
|
|
12023
12413
|
try {
|
|
12024
|
-
const fileContent = await fs$
|
|
12414
|
+
const fileContent = await fs$3.readFile(startMessageFilePath, 'utf8');
|
|
12025
12415
|
const parts = fileContent.split('\n\n\n');
|
|
12026
12416
|
parts.shift();
|
|
12027
12417
|
return parts.join('\n\n\n');
|
|
@@ -12042,60 +12432,401 @@ var defaultPromptLoader = {
|
|
|
12042
12432
|
};
|
|
12043
12433
|
|
|
12044
12434
|
/*
|
|
12045
|
-
* Component: AnalyzerUtils
|
|
12046
|
-
* Block-UUID:
|
|
12047
|
-
* Parent-UUID: N/A
|
|
12048
|
-
* Version: 1.2.0
|
|
12049
|
-
* Description: Aggregates and exports all utility functions from the AnalyzerUtils module.
|
|
12050
|
-
* Language: JavaScript
|
|
12051
|
-
* Created-at: 2025-08-28T15:56:40.319Z
|
|
12052
|
-
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0), Gemini 2.5 Flash (v1.2.0)
|
|
12053
|
-
*/
|
|
12054
|
-
|
|
12055
|
-
const { buildChatIdToPathMap: buildChatIdToPathMap$1 } = contextMapper;
|
|
12056
|
-
const { processLLMAnalysisResponse: processLLMAnalysisResponse$1 } = responseProcessor;
|
|
12057
|
-
const { validateLLMAnalysisData: validateLLMAnalysisData$1 } = dataValidator;
|
|
12058
|
-
const { getAnalyzers: getAnalyzers$1 } = discovery;
|
|
12059
|
-
const { saveConfiguration } = saver;
|
|
12060
|
-
const { getAnalyzerSchema: getAnalyzerSchema$1 } = schemaLoader;
|
|
12061
|
-
const { deleteAnalyzer: deleteAnalyzer$1 } = management;
|
|
12062
|
-
const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1 } = instructionLoader;
|
|
12063
|
-
const { getSystemMessageContent: getSystemMessageContent$1, getStartMessageContent: getStartMessageContent$1 } = defaultPromptLoader; // NEW: Import default prompt loaders
|
|
12064
|
-
|
|
12065
|
-
var AnalyzerUtils$1 = {
|
|
12066
|
-
buildChatIdToPathMap: buildChatIdToPathMap$1,
|
|
12067
|
-
processLLMAnalysisResponse: processLLMAnalysisResponse$1,
|
|
12068
|
-
validateLLMAnalysisData: validateLLMAnalysisData$1,
|
|
12069
|
-
getAnalyzers: getAnalyzers$1,
|
|
12070
|
-
getAnalyzerSchema: getAnalyzerSchema$1,
|
|
12071
|
-
deleteAnalyzer: deleteAnalyzer$1,
|
|
12072
|
-
getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1,
|
|
12073
|
-
saveConfiguration,
|
|
12074
|
-
getSystemMessageContent: getSystemMessageContent$1,
|
|
12075
|
-
getStartMessageContent: getStartMessageContent$1
|
|
12076
|
-
};
|
|
12077
|
-
|
|
12078
|
-
/**
|
|
12079
|
-
* Component: LLMUtils
|
|
12080
|
-
* Block-UUID: a3106054-42f1-474f-96f3-182d66eb19a0
|
|
12435
|
+
* Component: AnalyzerUtils Updater
|
|
12436
|
+
* Block-UUID: aee32ada-81d8-4d44-b0a3-5613ba166d1e
|
|
12081
12437
|
* Parent-UUID: N/A
|
|
12082
12438
|
* Version: 1.0.0
|
|
12083
|
-
* Description: Provides utility functions
|
|
12439
|
+
* Description: Provides utility functions for updating analyzer configurations, including renaming and metadata updates.
|
|
12084
12440
|
* Language: JavaScript
|
|
12085
|
-
* Created-at: 2025-
|
|
12086
|
-
* Authors:
|
|
12441
|
+
* Created-at: 2025-12-25T19:55:00.000Z
|
|
12442
|
+
* Authors: GLM-4.6 (v1.0.0)
|
|
12087
12443
|
*/
|
|
12088
12444
|
|
|
12445
|
+
const fs$2 = require$$0.promises;
|
|
12446
|
+
const path = require$$1;
|
|
12447
|
+
const CodeBlockUtils$2 = CodeBlockUtils$7;
|
|
12448
|
+
const { preprocessJsonForValidation: preprocessJsonForValidation$2 } = jsonParser;
|
|
12449
|
+
const { isValidDirName: isValidDirName$1 } = discovery;
|
|
12450
|
+
const { readConfig } = discovery;
|
|
12451
|
+
|
|
12089
12452
|
/**
|
|
12090
|
-
*
|
|
12091
|
-
* This is a basic estimation using the common heuristic of ~4 characters per token.
|
|
12092
|
-
* Actual token count can vary significantly based on the specific tokenizer used by an LLM.
|
|
12453
|
+
* Updates an analyzer configuration, including renaming the analyzer if needed.
|
|
12093
12454
|
*
|
|
12094
|
-
* @param {string}
|
|
12095
|
-
* @
|
|
12455
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers.
|
|
12456
|
+
* @param {string} analyzerId - The current unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
12457
|
+
* @param {object} updates - The updates to apply to the analyzer.
|
|
12458
|
+
* @param {string} [updates.name] - The new analyzer name (for renaming the directory).
|
|
12459
|
+
* @param {string} [updates.label] - The new label for the analyzer.
|
|
12460
|
+
* @param {string} [updates.description] - The new description for the analyzer.
|
|
12461
|
+
* @param {string} [updates.version] - The new version for the analyzer.
|
|
12462
|
+
* @param {Array<string>} [updates.tags] - The new tags for the analyzer.
|
|
12463
|
+
* @returns {Promise<{success: boolean, message: string, newAnalyzerId?: string}>} A promise that resolves with a result object.
|
|
12096
12464
|
*/
|
|
12097
|
-
function
|
|
12098
|
-
|
|
12465
|
+
async function updateAnalyzer$1(analyzersBasePath, analyzerId, updates) {
|
|
12466
|
+
// 1. Validate inputs
|
|
12467
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12468
|
+
return { success: false, message: 'analyzersBasePath is required.' };
|
|
12469
|
+
}
|
|
12470
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
12471
|
+
return { success: false, message: 'analyzerId is required.' };
|
|
12472
|
+
}
|
|
12473
|
+
if (!updates || typeof updates !== 'object') {
|
|
12474
|
+
return { success: false, message: 'updates object is required.' };
|
|
12475
|
+
}
|
|
12476
|
+
|
|
12477
|
+
// 2.0 Parse current analyzerId
|
|
12478
|
+
const parts = analyzerId.split('::');
|
|
12479
|
+
if (parts.length !== 3) {
|
|
12480
|
+
return { success: false, message: `Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.` };
|
|
12481
|
+
}
|
|
12482
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
12483
|
+
|
|
12484
|
+
// 2.1 Unset name if it has been provided but is the same as the analyzerName
|
|
12485
|
+
if (updates.name && analyzerName === updates.name) {
|
|
12486
|
+
delete updates.name;
|
|
12487
|
+
}
|
|
12488
|
+
|
|
12489
|
+
// 3. Validate new name if provided
|
|
12490
|
+
if (updates.name && !isValidDirName$1(updates.name)) {
|
|
12491
|
+
return { success: false, message: `Invalid analyzer name '${updates.name}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
12492
|
+
}
|
|
12493
|
+
|
|
12494
|
+
// 4. Check if analyzer is protected
|
|
12495
|
+
const analyzerDir = path.join(analyzersBasePath, analyzerName);
|
|
12496
|
+
const analyzerConfig = await readConfig(analyzerDir);
|
|
12497
|
+
if (analyzerConfig?.protected) {
|
|
12498
|
+
return { success: false, message: `Analyzer '${analyzerName}' is protected and cannot be updated.` };
|
|
12499
|
+
}
|
|
12500
|
+
|
|
12501
|
+
// 5. Get current instructions content
|
|
12502
|
+
const instructionsFilePath = path.join(analyzerDir, contentType, instructionsType, '1.md');
|
|
12503
|
+
let instructionsContent;
|
|
12504
|
+
try {
|
|
12505
|
+
instructionsContent = await fs$2.readFile(instructionsFilePath, 'utf8');
|
|
12506
|
+
} catch (error) {
|
|
12507
|
+
return { success: false, message: `Failed to read analyzer instructions: ${error.message}` };
|
|
12508
|
+
}
|
|
12509
|
+
|
|
12510
|
+
// 6. Extract and update JSON block
|
|
12511
|
+
const { blocks } = CodeBlockUtils$2.extractCodeBlocks(instructionsContent, { silent: true });
|
|
12512
|
+
const jsonBlock = blocks.find(block => block.language === 'json');
|
|
12513
|
+
|
|
12514
|
+
if (!jsonBlock) {
|
|
12515
|
+
return { success: false, message: 'No JSON block found in analyzer instructions.' };
|
|
12516
|
+
}
|
|
12517
|
+
|
|
12518
|
+
let jsonData;
|
|
12519
|
+
try {
|
|
12520
|
+
const preprocessedContent = preprocessJsonForValidation$2(jsonBlock.content);
|
|
12521
|
+
jsonData = JSON.parse(preprocessedContent);
|
|
12522
|
+
} catch (error) {
|
|
12523
|
+
return { success: false, message: `Failed to parse JSON block: ${error.message}` };
|
|
12524
|
+
}
|
|
12525
|
+
|
|
12526
|
+
// 7. Update JSON data with provided values
|
|
12527
|
+
if (updates.label !== undefined) jsonData.label = updates.label;
|
|
12528
|
+
if (updates.description !== undefined) jsonData.description = updates.description;
|
|
12529
|
+
if (updates.version !== undefined) jsonData.version = updates.version;
|
|
12530
|
+
if (updates.tags !== undefined) jsonData.tags = updates.tags;
|
|
12531
|
+
|
|
12532
|
+
// 8. Rebuild the instructions content with updated JSON
|
|
12533
|
+
const updatedJsonContent = JSON.stringify(jsonData, null, 2);
|
|
12534
|
+
const updatedInstructionsContent = instructionsContent.replace(
|
|
12535
|
+
jsonBlock.content,
|
|
12536
|
+
updatedJsonContent
|
|
12537
|
+
);
|
|
12538
|
+
|
|
12539
|
+
// 9. Handle directory renaming if needed
|
|
12540
|
+
let newAnalyzerId = analyzerId;
|
|
12541
|
+
if (updates.name && updates.name !== analyzerName) {
|
|
12542
|
+
// Create new directory structure
|
|
12543
|
+
const newAnalyzerDir = path.join(analyzersBasePath, updates.name);
|
|
12544
|
+
const newContentDir = path.join(newAnalyzerDir, contentType);
|
|
12545
|
+
const newInstructionsDir = path.join(newContentDir, instructionsType);
|
|
12546
|
+
const newInstructionsFilePath = path.join(newInstructionsDir, '1.md');
|
|
12547
|
+
|
|
12548
|
+
try {
|
|
12549
|
+
// Create new directories
|
|
12550
|
+
await fs$2.mkdir(newInstructionsDir, { recursive: true });
|
|
12551
|
+
|
|
12552
|
+
// Copy config.json if it exists
|
|
12553
|
+
const configPath = path.join(analyzerDir, 'config.json');
|
|
12554
|
+
const newConfigPath = path.join(newAnalyzerDir, 'config.json');
|
|
12555
|
+
try {
|
|
12556
|
+
const configContent = await fs$2.readFile(configPath, 'utf8');
|
|
12557
|
+
await fs$2.writeFile(newConfigPath, configContent, 'utf8');
|
|
12558
|
+
} catch (error) {
|
|
12559
|
+
// Config file might not exist, that's okay
|
|
12560
|
+
}
|
|
12561
|
+
|
|
12562
|
+
// Copy content config.json if it exists
|
|
12563
|
+
const contentConfigPath = path.join(analyzerDir, contentType, 'config.json');
|
|
12564
|
+
const newContentConfigPath = path.join(newContentDir, 'config.json');
|
|
12565
|
+
try {
|
|
12566
|
+
const contentConfigContent = await fs$2.readFile(contentConfigPath, 'utf8');
|
|
12567
|
+
await fs$2.writeFile(newContentConfigPath, contentConfigContent, 'utf8');
|
|
12568
|
+
} catch (error) {
|
|
12569
|
+
// Config file might not exist, that's okay
|
|
12570
|
+
}
|
|
12571
|
+
|
|
12572
|
+
// Copy instructions config.json if it exists
|
|
12573
|
+
const instructionsConfigPath = path.join(analyzerDir, contentType, instructionsType, 'config.json');
|
|
12574
|
+
const newInstructionsConfigPath = path.join(newInstructionsDir, 'config.json');
|
|
12575
|
+
try {
|
|
12576
|
+
const instructionsConfigContent = await fs$2.readFile(instructionsConfigPath, 'utf8');
|
|
12577
|
+
await fs$2.writeFile(newInstructionsConfigPath, instructionsConfigContent, 'utf8');
|
|
12578
|
+
} catch (error) {
|
|
12579
|
+
// Config file might not exist, that's okay
|
|
12580
|
+
}
|
|
12581
|
+
|
|
12582
|
+
// Write updated instructions to new location
|
|
12583
|
+
const finalContent = `; role: assistant\n\n\n${updatedInstructionsContent}`;
|
|
12584
|
+
await fs$2.writeFile(newInstructionsFilePath, finalContent, 'utf8');
|
|
12585
|
+
|
|
12586
|
+
// Update the analyzer ID
|
|
12587
|
+
newAnalyzerId = `${updates.name}::${contentType}::${instructionsType}`;
|
|
12588
|
+
|
|
12589
|
+
// Delete old analyzer directory (will be done after successful save)
|
|
12590
|
+
} catch (error) {
|
|
12591
|
+
return { success: false, message: `Failed to create new analyzer directory: ${error.message}` };
|
|
12592
|
+
}
|
|
12593
|
+
} else {
|
|
12594
|
+
// Just update the existing file
|
|
12595
|
+
const finalContent = `; role: assistant\n\n\n${updatedInstructionsContent}`;
|
|
12596
|
+
await fs$2.writeFile(instructionsFilePath, finalContent, 'utf8');
|
|
12597
|
+
}
|
|
12598
|
+
|
|
12599
|
+
// 10. Clean up old directory if renamed
|
|
12600
|
+
if (updates.name && updates.name !== analyzerName) {
|
|
12601
|
+
try {
|
|
12602
|
+
// Use the deleteAnalyzer function to clean up the old directory
|
|
12603
|
+
const { deleteAnalyzer } = management;
|
|
12604
|
+
await deleteAnalyzer(analyzersBasePath, analyzerId);
|
|
12605
|
+
} catch (error) {
|
|
12606
|
+
console.warn(`Warning: Could not clean up old analyzer directory: ${error.message}`);
|
|
12607
|
+
}
|
|
12608
|
+
}
|
|
12609
|
+
|
|
12610
|
+
return {
|
|
12611
|
+
success: true,
|
|
12612
|
+
message: `Analyzer '${analyzerId}' updated successfully.`,
|
|
12613
|
+
newAnalyzerId
|
|
12614
|
+
};
|
|
12615
|
+
}
|
|
12616
|
+
|
|
12617
|
+
var updater = {
|
|
12618
|
+
updateAnalyzer: updateAnalyzer$1
|
|
12619
|
+
};
|
|
12620
|
+
|
|
12621
|
+
/*
|
|
12622
|
+
* Component: AnalyzerUtils Cloner
|
|
12623
|
+
* Block-UUID: 56b8c9f4-97ce-406c-a598-22a838ebefda
|
|
12624
|
+
* Parent-UUID: N/A
|
|
12625
|
+
* Version: 1.0.0
|
|
12626
|
+
* Description: Provides utility functions for cloning analyzer configurations.
|
|
12627
|
+
* Language: JavaScript
|
|
12628
|
+
* Created-at: 2025-12-26T16:59:39.782Z
|
|
12629
|
+
* Authors: GLM-4.6 (v1.0.0)
|
|
12630
|
+
*/
|
|
12631
|
+
|
|
12632
|
+
require$$0.promises;
|
|
12633
|
+
const CodeBlockUtils$1 = CodeBlockUtils$7;
|
|
12634
|
+
const { preprocessJsonForValidation: preprocessJsonForValidation$1 } = jsonParser;
|
|
12635
|
+
const { isValidDirName } = discovery;
|
|
12636
|
+
const { saveConfiguration: saveConfiguration$1 } = saver;
|
|
12637
|
+
const { getAnalyzers: getAnalyzers$2 } = discovery;
|
|
12638
|
+
|
|
12639
|
+
/**
|
|
12640
|
+
* Clones an existing analyzer with a new name.
|
|
12641
|
+
*
|
|
12642
|
+
* @param {string} analyzersBasePath - The absolute path to the base directory containing the analyzers.
|
|
12643
|
+
* @param {string} originalAnalyzerId - The ID of the analyzer to clone (format: 'analyzer_name::content_type::instructions_type').
|
|
12644
|
+
* @param {string} newAnalyzerName - The new name for the cloned analyzer.
|
|
12645
|
+
* @param {object} [options={}] - Optional configuration options.
|
|
12646
|
+
* @param {string} [options.label] - The new label for the cloned analyzer (optional, defaults to newAnalyzerName).
|
|
12647
|
+
* @param {string} [options.description] - The new description for the cloned analyzer (optional, keeps original if not provided).
|
|
12648
|
+
* @returns {Promise<{success: boolean, message: string, newAnalyzerId?: string}>} A promise that resolves with a result object.
|
|
12649
|
+
*/
|
|
12650
|
+
async function cloneAnalyzer$1(analyzersBasePath, originalAnalyzerId, newAnalyzerName, options = {}) {
|
|
12651
|
+
// 1. Validate inputs
|
|
12652
|
+
if (typeof analyzersBasePath !== 'string' || analyzersBasePath.trim() === '') {
|
|
12653
|
+
return { success: false, message: 'analyzersBasePath is required.' };
|
|
12654
|
+
}
|
|
12655
|
+
if (typeof originalAnalyzerId !== 'string' || originalAnalyzerId.trim() === '') {
|
|
12656
|
+
return { success: false, message: 'originalAnalyzerId is required.' };
|
|
12657
|
+
}
|
|
12658
|
+
if (typeof newAnalyzerName !== 'string' || newAnalyzerName.trim() === '') {
|
|
12659
|
+
return { success: false, message: 'newAnalyzerName is required.' };
|
|
12660
|
+
}
|
|
12661
|
+
|
|
12662
|
+
// 2. Parse original analyzerId
|
|
12663
|
+
const parts = originalAnalyzerId.split('::');
|
|
12664
|
+
if (parts.length !== 3) {
|
|
12665
|
+
return { success: false, message: `Invalid originalAnalyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${originalAnalyzerId}'.` };
|
|
12666
|
+
}
|
|
12667
|
+
const [originalAnalyzerName, contentType, instructionsType] = parts;
|
|
12668
|
+
|
|
12669
|
+
// 3. Validate new analyzer name
|
|
12670
|
+
if (!isValidDirName(newAnalyzerName)) {
|
|
12671
|
+
return { success: false, message: `Invalid analyzer name '${newAnalyzerName}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
12672
|
+
}
|
|
12673
|
+
|
|
12674
|
+
// 4. Check if new analyzer name already exists
|
|
12675
|
+
try {
|
|
12676
|
+
const existingAnalyzers = await getAnalyzers$2(analyzersBasePath);
|
|
12677
|
+
const nameExists = existingAnalyzers.some(analyzer => analyzer.name === newAnalyzerName);
|
|
12678
|
+
if (nameExists) {
|
|
12679
|
+
return { success: false, message: `An analyzer with name '${newAnalyzerName}' already exists. Please choose a different name.` };
|
|
12680
|
+
}
|
|
12681
|
+
} catch (error) {
|
|
12682
|
+
return { success: false, message: `Failed to check for existing analyzers: ${error.message}` };
|
|
12683
|
+
}
|
|
12684
|
+
|
|
12685
|
+
// 5. Get original analyzer's instructions content
|
|
12686
|
+
const { getAnalyzerInstructionsContent } = instructionLoader;
|
|
12687
|
+
let instructionsContent;
|
|
12688
|
+
try {
|
|
12689
|
+
instructionsContent = await getAnalyzerInstructionsContent(analyzersBasePath, originalAnalyzerId);
|
|
12690
|
+
if (!instructionsContent) {
|
|
12691
|
+
return { success: false, message: `Could not find original analyzer '${originalAnalyzerId}'.` };
|
|
12692
|
+
}
|
|
12693
|
+
} catch (error) {
|
|
12694
|
+
return { success: false, message: `Failed to read original analyzer instructions: ${error.message}` };
|
|
12695
|
+
}
|
|
12696
|
+
|
|
12697
|
+
// 6. Extract and update JSON block
|
|
12698
|
+
const { blocks } = CodeBlockUtils$1.extractCodeBlocks(instructionsContent, { silent: true });
|
|
12699
|
+
const jsonBlocks = blocks.filter((block, index) => {
|
|
12700
|
+
if (block.language === 'json') {
|
|
12701
|
+
block.index = index;
|
|
12702
|
+
return block;
|
|
12703
|
+
}
|
|
12704
|
+
});
|
|
12705
|
+
const jsonBlock = jsonBlocks[jsonBlocks.length - 1];
|
|
12706
|
+
|
|
12707
|
+
if (!jsonBlock) {
|
|
12708
|
+
return { success: false, message: 'No JSON block found in original analyzer instructions.' };
|
|
12709
|
+
}
|
|
12710
|
+
|
|
12711
|
+
let jsonData;
|
|
12712
|
+
try {
|
|
12713
|
+
const preprocessedContent = preprocessJsonForValidation$1(jsonBlock.content);
|
|
12714
|
+
jsonData = JSON.parse(preprocessedContent);
|
|
12715
|
+
} catch (error) {
|
|
12716
|
+
return { success: false, message: `Failed to parse JSON block: ${error.message}` };
|
|
12717
|
+
}
|
|
12718
|
+
|
|
12719
|
+
// 7. Update JSON data with new values
|
|
12720
|
+
if (options.label !== undefined) {
|
|
12721
|
+
jsonData.label = options.label;
|
|
12722
|
+
}
|
|
12723
|
+
if (options.description !== undefined) {
|
|
12724
|
+
jsonData.description = options.description;
|
|
12725
|
+
}
|
|
12726
|
+
// Reset version for cloned analyzer
|
|
12727
|
+
jsonData.version = '1.0.0';
|
|
12728
|
+
|
|
12729
|
+
// 8. Rebuild the instructions content with updated JSON
|
|
12730
|
+
let updatedInstructionsContent = CodeBlockUtils$1.updateCodeBlockByIndex(
|
|
12731
|
+
instructionsContent,
|
|
12732
|
+
jsonBlock.index,
|
|
12733
|
+
JSON.stringify(jsonData, null, 2),
|
|
12734
|
+
'json'
|
|
12735
|
+
);
|
|
12736
|
+
|
|
12737
|
+
// 9. Create the new analyzer ID
|
|
12738
|
+
const newAnalyzerId = `${newAnalyzerName}::${contentType}::${instructionsType}`;
|
|
12739
|
+
|
|
12740
|
+
// 10. Update the analyzer id in the instructions
|
|
12741
|
+
updatedInstructionsContent = updatedInstructionsContent.replaceAll(originalAnalyzerId, newAnalyzerId);
|
|
12742
|
+
|
|
12743
|
+
// 11. Save the new analyzer
|
|
12744
|
+
try {
|
|
12745
|
+
const saveResult = await saveConfiguration$1(
|
|
12746
|
+
analyzersBasePath,
|
|
12747
|
+
newAnalyzerId,
|
|
12748
|
+
updatedInstructionsContent
|
|
12749
|
+
);
|
|
12750
|
+
|
|
12751
|
+
if (saveResult.success) {
|
|
12752
|
+
return {
|
|
12753
|
+
success: true,
|
|
12754
|
+
message: `Analyzer '${originalAnalyzerName}' cloned successfully as '${newAnalyzerName}'.`,
|
|
12755
|
+
newAnalyzerId
|
|
12756
|
+
};
|
|
12757
|
+
} else {
|
|
12758
|
+
return { success: false, error: saveResult.message };
|
|
12759
|
+
}
|
|
12760
|
+
} catch (error) {
|
|
12761
|
+
return { success: false, message: `Failed to save cloned analyzer: ${error.message}` };
|
|
12762
|
+
}
|
|
12763
|
+
}
|
|
12764
|
+
|
|
12765
|
+
var cloner = {
|
|
12766
|
+
cloneAnalyzer: cloneAnalyzer$1
|
|
12767
|
+
};
|
|
12768
|
+
|
|
12769
|
+
/*
|
|
12770
|
+
* Component: AnalyzerUtils Index
|
|
12771
|
+
* Block-UUID: 780e17b0-0c1e-4d77-bf6e-302951b341bf
|
|
12772
|
+
* Parent-UUID: b403b6a1-230b-4247-8cd6-2a3d068f4bbf
|
|
12773
|
+
* Version: 1.5.0
|
|
12774
|
+
* Description: Aggregates and exports all utility functions from the AnalyzerUtils module. Added cloneAnalyzer method.
|
|
12775
|
+
* Language: JavaScript
|
|
12776
|
+
* Created-at: 2025-08-28T15:56:40.319Z
|
|
12777
|
+
* Authors: Gemini 2.5 Flash (v1.0.0), Gemini 2.5 Flash (v1.1.0), Gemini 2.5 Flash (v1.2.0), GLM-4.6 (v1.3.0), GLM-4.6 (v1.4.0), GLM-4.6 (v1.5.0)
|
|
12778
|
+
*/
|
|
12779
|
+
|
|
12780
|
+
const { buildChatIdToPathMap: buildChatIdToPathMap$1 } = contextMapper;
|
|
12781
|
+
const { processLLMAnalysisResponse: processLLMAnalysisResponse$1 } = responseProcessor;
|
|
12782
|
+
const { validateLLMAnalysisData: validateLLMAnalysisData$1 } = dataValidator;
|
|
12783
|
+
const { getAnalyzers: getAnalyzers$1 } = discovery;
|
|
12784
|
+
const { saveConfiguration } = saver;
|
|
12785
|
+
const { getAnalyzerSchema: getAnalyzerSchema$1 } = schemaLoader;
|
|
12786
|
+
const { deleteAnalyzer: deleteAnalyzer$1 } = management;
|
|
12787
|
+
const { getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1 } = instructionLoader;
|
|
12788
|
+
const { getSystemMessageContent: getSystemMessageContent$1, getStartMessageContent: getStartMessageContent$1 } = defaultPromptLoader;
|
|
12789
|
+
const { preprocessJsonForValidation } = jsonParser;
|
|
12790
|
+
const { updateAnalyzer } = updater;
|
|
12791
|
+
const { cloneAnalyzer } = cloner;
|
|
12792
|
+
|
|
12793
|
+
var AnalyzerUtils$1 = {
|
|
12794
|
+
buildChatIdToPathMap: buildChatIdToPathMap$1,
|
|
12795
|
+
processLLMAnalysisResponse: processLLMAnalysisResponse$1,
|
|
12796
|
+
validateLLMAnalysisData: validateLLMAnalysisData$1,
|
|
12797
|
+
getAnalyzers: getAnalyzers$1,
|
|
12798
|
+
getAnalyzerSchema: getAnalyzerSchema$1,
|
|
12799
|
+
deleteAnalyzer: deleteAnalyzer$1,
|
|
12800
|
+
getAnalyzerInstructionsContent: getAnalyzerInstructionsContent$1,
|
|
12801
|
+
saveConfiguration,
|
|
12802
|
+
getSystemMessageContent: getSystemMessageContent$1,
|
|
12803
|
+
getStartMessageContent: getStartMessageContent$1,
|
|
12804
|
+
preprocessJsonForValidation,
|
|
12805
|
+
updateAnalyzer,
|
|
12806
|
+
cloneAnalyzer
|
|
12807
|
+
};
|
|
12808
|
+
|
|
12809
|
+
/**
|
|
12810
|
+
* Component: LLMUtils
|
|
12811
|
+
* Block-UUID: b8536c11-ed0b-4538-b3ff-35da94e67012
|
|
12812
|
+
* Parent-UUID: N/A
|
|
12813
|
+
* Version: 1.0.0
|
|
12814
|
+
* Description: Provides utility functions related to Large Language Model interactions, such as token estimation.
|
|
12815
|
+
* Language: JavaScript
|
|
12816
|
+
* Created-at: 2025-04-22T17:16:00.590Z
|
|
12817
|
+
* Authors: Gemini 2.5 Pro (v1.0.0)
|
|
12818
|
+
*/
|
|
12819
|
+
|
|
12820
|
+
/**
|
|
12821
|
+
* Estimates the number of tokens in a given text string.
|
|
12822
|
+
* This is a basic estimation using the common heuristic of ~4 characters per token.
|
|
12823
|
+
* Actual token count can vary significantly based on the specific tokenizer used by an LLM.
|
|
12824
|
+
*
|
|
12825
|
+
* @param {string} text - The text to estimate tokens for.
|
|
12826
|
+
* @returns {number} An estimated token count. Returns 0 if input is not a non-empty string.
|
|
12827
|
+
*/
|
|
12828
|
+
function estimateTokens$1(text) {
|
|
12829
|
+
if (typeof text !== 'string' || text.length === 0) {
|
|
12099
12830
|
return 0;
|
|
12100
12831
|
}
|
|
12101
12832
|
// Basic heuristic: average token length is around 4 characters
|
|
@@ -12221,7 +12952,7 @@ var DateUtils$1 = {
|
|
|
12221
12952
|
|
|
12222
12953
|
/**
|
|
12223
12954
|
* Component: Formatter Utilities
|
|
12224
|
-
* Block-UUID:
|
|
12955
|
+
* Block-UUID: 8512c809-87b0-4f90-af9d-b3dca204c4de
|
|
12225
12956
|
* Parent-UUID: 9c07d12f-5a05-4402-99d2-85d872d7b2f7
|
|
12226
12957
|
* Version: 1.0.0
|
|
12227
12958
|
* Description: Utility functions for formatting content in GitSense Chat
|
|
@@ -12276,13 +13007,13 @@ var FormatterUtils$1 = {
|
|
|
12276
13007
|
|
|
12277
13008
|
/**
|
|
12278
13009
|
* Component: DomUtils Helper Functions
|
|
12279
|
-
* Block-UUID:
|
|
12280
|
-
* Parent-UUID:
|
|
12281
|
-
* Version: 1.1
|
|
13010
|
+
* Block-UUID: 9a8e8e8e-8b15-4346-bbfa-740e6a5d2d79
|
|
13011
|
+
* Parent-UUID: 8a528728-ce54-4445-946d-1743fb4b16be
|
|
13012
|
+
* Version: 1.3.1
|
|
12282
13013
|
* Description: Provides helper functions for creating and manipulating DOM elements.
|
|
12283
13014
|
* Language: JavaScript
|
|
12284
|
-
* Created-at: 2025-
|
|
12285
|
-
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash (v1.1.0)
|
|
13015
|
+
* Created-at: 2025-12-14T04:18:40.180Z
|
|
13016
|
+
* Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash (v1.1.0), Qwen 3 Coder 480B - Cerebras (v1.2.0), GLM-4.6 (v1.2.1), GLM-4.6 (v1.3.0), GLM-4.6 (v1.3.1)
|
|
12286
13017
|
*/
|
|
12287
13018
|
|
|
12288
13019
|
function createElement(type, params) {
|
|
@@ -12294,6 +13025,7 @@ function createElement(type, params) {
|
|
|
12294
13025
|
let {
|
|
12295
13026
|
id,
|
|
12296
13027
|
ariaLabel,
|
|
13028
|
+
xmlns,
|
|
12297
13029
|
role,
|
|
12298
13030
|
html,
|
|
12299
13031
|
text,
|
|
@@ -12316,11 +13048,15 @@ function createElement(type, params) {
|
|
|
12316
13048
|
"data-message-role": dmr,
|
|
12317
13049
|
attrs = {},
|
|
12318
13050
|
dataset,
|
|
13051
|
+
rows
|
|
12319
13052
|
} = params;
|
|
12320
13053
|
|
|
12321
13054
|
// Set standard attributes
|
|
12322
13055
|
if (id != null) elem.id = id;
|
|
12323
13056
|
if (ariaLabel) elem.setAttribute("aria-label", ariaLabel);
|
|
13057
|
+
if (xmlns) elem.setAttribute("xmlns", xmlns);
|
|
13058
|
+
if (params.viewBox) elem.setAttribute("viewBox", params.viewBox);
|
|
13059
|
+
if (params.fill) elem.setAttribute("fill", params.fill);
|
|
12324
13060
|
if (role) elem.setAttribute("role", role);
|
|
12325
13061
|
if (placeholder) elem.setAttribute("placeholder", placeholder);
|
|
12326
13062
|
if (cls || className) elem.setAttribute("class", cls || className);
|
|
@@ -12328,6 +13064,9 @@ function createElement(type, params) {
|
|
|
12328
13064
|
if (title != null) elem.setAttribute("title", title);
|
|
12329
13065
|
if (inputType) elem.setAttribute("type", inputType);
|
|
12330
13066
|
if (name != null) elem.setAttribute("name", name);
|
|
13067
|
+
if (params.width) elem.setAttribute("width", params.width);
|
|
13068
|
+
if (params.height) elem.setAttribute("height", params.height);
|
|
13069
|
+
if (params.stroke) elem.setAttribute("stroke", params.stroke);
|
|
12331
13070
|
if (value != null) elem.value = value;
|
|
12332
13071
|
if (checked != null && checked) elem.checked = true; // Use property for checked
|
|
12333
13072
|
if (selected != null && selected) elem.selected = true; // Use property for selected
|
|
@@ -12335,13 +13074,21 @@ function createElement(type, params) {
|
|
|
12335
13074
|
if (dmi != null) elem.setAttribute("data-message-id", dmi);
|
|
12336
13075
|
if (dmr != null) elem.setAttribute("data-message-role", dmr);
|
|
12337
13076
|
if (_for != null ) elem.setAttribute("for", _for);
|
|
13077
|
+
if (params.strokeWidth) elem.setAttribute("stroke-width", params.strokeWidth);
|
|
13078
|
+
if (params.strokeLinecap) elem.setAttribute("stroke-linecap", params.strokeLinecap);
|
|
13079
|
+
if (params.strokeLinejoin) elem.setAttribute("stroke-linejoin", params.strokeLinejoin);
|
|
12338
13080
|
if (colSpan != null) elem.colSpan = colSpan;
|
|
13081
|
+
if (rows) elem.setAttribute("rows", params.rows);
|
|
12339
13082
|
|
|
12340
13083
|
// Set content
|
|
12341
13084
|
if (html != null) {
|
|
12342
13085
|
if (typeof html === "object" && html instanceof Node) { // Ensure html is a Node
|
|
12343
13086
|
elem.appendChild(html);
|
|
12344
13087
|
} else if (typeof html === "string") {
|
|
13088
|
+
// For SVG elements, use innerHTML to support path elements
|
|
13089
|
+
if (type === 'svg' && params.innerHTML) {
|
|
13090
|
+
elem.innerHTML = params.innerHTML;
|
|
13091
|
+
}
|
|
12345
13092
|
elem.innerHTML = html;
|
|
12346
13093
|
}
|
|
12347
13094
|
} else if (text != null) {
|
|
@@ -12367,12 +13114,12 @@ function createElement(type, params) {
|
|
|
12367
13114
|
});
|
|
12368
13115
|
}
|
|
12369
13116
|
|
|
12370
|
-
//
|
|
13117
|
+
// Set additional attributes from attrs object
|
|
12371
13118
|
if (attrs && typeof attrs === 'object') {
|
|
12372
13119
|
for (const [key, value] of Object.entries(attrs)) {
|
|
12373
13120
|
if (value !== undefined && value !== null) {
|
|
12374
13121
|
// Skip if already set by standard properties or handled directly
|
|
12375
|
-
if (!['id', 'class', 'role', 'aria-label', 'title', 'style', '
|
|
13122
|
+
if (!['id', 'class', 'role', 'aria-label', 'title', 'style', 'selected', 'disabled', 'value', 'name', 'type', 'for'].includes(key) && !key.startsWith('data-')) {
|
|
12376
13123
|
elem.setAttribute(key, value);
|
|
12377
13124
|
}
|
|
12378
13125
|
}
|
|
@@ -12485,14 +13232,17 @@ const h$1 = {
|
|
|
12485
13232
|
},
|
|
12486
13233
|
createLink: (params) => {
|
|
12487
13234
|
const link = createElement("a", params);
|
|
12488
|
-
|
|
12489
|
-
if (params?.
|
|
13235
|
+
if (params?.href) link.href = params.href;
|
|
13236
|
+
if (params?.target) link.target = params.target;
|
|
12490
13237
|
return link;
|
|
12491
13238
|
},
|
|
12492
13239
|
createNav: (params) => {
|
|
12493
13240
|
return createElement("nav", params);
|
|
12494
13241
|
},
|
|
12495
|
-
|
|
13242
|
+
createOl: (params) => {
|
|
13243
|
+
return createElement("ol", params);
|
|
13244
|
+
},
|
|
13245
|
+
createOL: (params) => {
|
|
12496
13246
|
return createElement("ol", params);
|
|
12497
13247
|
},
|
|
12498
13248
|
createOption: (params) => { // Added
|
|
@@ -12508,13 +13258,49 @@ const h$1 = {
|
|
|
12508
13258
|
createPre: (params) => {
|
|
12509
13259
|
return createElement("pre", params);
|
|
12510
13260
|
},
|
|
12511
|
-
createSelect: (params) => {
|
|
12512
|
-
//
|
|
12513
|
-
|
|
13261
|
+
createSelect: (params) => {
|
|
13262
|
+
// Extract value before creating the select element
|
|
13263
|
+
const { value, ...selectParams } = params || {};
|
|
13264
|
+
|
|
13265
|
+
// Create select element without the value initially
|
|
13266
|
+
const select = createElement("select", selectParams);
|
|
13267
|
+
|
|
13268
|
+
// Handle options array if provided
|
|
13269
|
+
if (params && params.options && Array.isArray(params.options)) {
|
|
13270
|
+
params.options.forEach(option => {
|
|
13271
|
+
if (option && typeof option === 'object') {
|
|
13272
|
+
// Check if this option should be selected based on the value
|
|
13273
|
+
const isSelected = (value !== undefined && value !== null) &&
|
|
13274
|
+
(option.value === value ||
|
|
13275
|
+
(value === '' && option.value === '') ||
|
|
13276
|
+
(value === null && option.value === null));
|
|
13277
|
+
|
|
13278
|
+
const optionElement = createElement("option", {
|
|
13279
|
+
value: option.value,
|
|
13280
|
+
text: option.text,
|
|
13281
|
+
selected: isSelected || option.selected
|
|
13282
|
+
});
|
|
13283
|
+
select.appendChild(optionElement);
|
|
13284
|
+
}
|
|
13285
|
+
});
|
|
13286
|
+
}
|
|
13287
|
+
|
|
13288
|
+
// Set the value after options are added to ensure proper selection
|
|
13289
|
+
if (value !== undefined && value !== null) {
|
|
13290
|
+
select.value = value;
|
|
13291
|
+
}
|
|
13292
|
+
|
|
13293
|
+
return select;
|
|
12514
13294
|
},
|
|
12515
13295
|
createSpan: (params) => {
|
|
12516
13296
|
return createElement("span", params);
|
|
12517
13297
|
},
|
|
13298
|
+
createSvg: (params) => {
|
|
13299
|
+
// Create SVG element with xmlns attribute
|
|
13300
|
+
const svgParams = { ...params, xmlns: "http://www.w3.org/2000/svg" };
|
|
13301
|
+
const svg = createElement("svg", svgParams);
|
|
13302
|
+
return svg;
|
|
13303
|
+
},
|
|
12518
13304
|
createStrong: (params) => { // Added
|
|
12519
13305
|
return createElement("strong", params);
|
|
12520
13306
|
},
|
|
@@ -12527,6 +13313,10 @@ const h$1 = {
|
|
|
12527
13313
|
createText: (text) => {
|
|
12528
13314
|
return document.createTextNode(text);
|
|
12529
13315
|
},
|
|
13316
|
+
createTextarea: (params) => {
|
|
13317
|
+
const textArea = createElement("textarea", params);
|
|
13318
|
+
return textArea;
|
|
13319
|
+
},
|
|
12530
13320
|
createTextArea: (params) => {
|
|
12531
13321
|
const textArea = createElement("textarea", params);
|
|
12532
13322
|
return textArea;
|
|
@@ -12725,6 +13515,35 @@ const h$1 = {
|
|
|
12725
13515
|
})
|
|
12726
13516
|
.join('');
|
|
12727
13517
|
},
|
|
13518
|
+
|
|
13519
|
+
/**
|
|
13520
|
+
* Injects CSS styles into the document head.
|
|
13521
|
+
* @param {string} cssString - The CSS string to inject.
|
|
13522
|
+
* @param {string} [id] - Optional ID for the style element to prevent duplicates.
|
|
13523
|
+
* @returns {HTMLStyleElement} The created or existing style element.
|
|
13524
|
+
*/
|
|
13525
|
+
injectStyles: (cssString, id) => {
|
|
13526
|
+
// If an ID is provided, check if styles with this ID already exist
|
|
13527
|
+
if (id) {
|
|
13528
|
+
const existingStyle = document.getElementById(id);
|
|
13529
|
+
if (existingStyle) {
|
|
13530
|
+
// Styles already injected, return the existing element
|
|
13531
|
+
return existingStyle;
|
|
13532
|
+
}
|
|
13533
|
+
}
|
|
13534
|
+
|
|
13535
|
+
// Create a new style element
|
|
13536
|
+
const styleElement = document.createElement('style');
|
|
13537
|
+
if (id) {
|
|
13538
|
+
styleElement.id = id;
|
|
13539
|
+
}
|
|
13540
|
+
styleElement.textContent = cssString;
|
|
13541
|
+
|
|
13542
|
+
// Append to the document head
|
|
13543
|
+
document.head.appendChild(styleElement);
|
|
13544
|
+
|
|
13545
|
+
return styleElement;
|
|
13546
|
+
},
|
|
12728
13547
|
|
|
12729
13548
|
/**
|
|
12730
13549
|
* Calculates the distance between an element's edge and the viewport's corresponding edge
|
|
@@ -22357,7 +23176,10 @@ function createMarkdownRenderer$1(hljs, hstyle = {}, nhstyle = {}) {
|
|
|
22357
23176
|
// Create the inner code element with the highlighted content
|
|
22358
23177
|
// and the language label prepended.
|
|
22359
23178
|
const codeElement = h.createCode({
|
|
22360
|
-
html: `<span class='gs-chat-lang'>${lang}</span>\n\n${highlightedCode}
|
|
23179
|
+
html: `<span class='gs-chat-lang'>${lang}</span>\n\n${highlightedCode}`,
|
|
23180
|
+
style: {
|
|
23181
|
+
fontSize: '13px'
|
|
23182
|
+
}
|
|
22361
23183
|
});
|
|
22362
23184
|
|
|
22363
23185
|
// Wrap the code element in a pre tag with styling
|
|
@@ -22758,7 +23580,7 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
22758
23580
|
* @returns {Element} SVG element
|
|
22759
23581
|
*/
|
|
22760
23582
|
static archive(params) {
|
|
22761
|
-
const xml = `<svg xmlns=
|
|
23583
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M0 2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75v1.5A1.75 1.75 0 0 1 14.25 6H1.75A1.75 1.75 0 0 1 0 4.25ZM1.75 7a.75.75 0 0 1 .75.75v5.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-5.5a.75.75 0 0 1 1.5 0v5.5A1.75 1.75 0 0 1 13.25 15H2.75A1.75 1.75 0 0 1 1 13.25v-5.5A.75.75 0 0 1 1.75 7Zm0-4.5a.25.25 0 0 0-.25.25v1.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-1.5a.25.25 0 0 0-.25-.25ZM6.25 8h3.5a.75.75 0 0 1 0 1.5h-3.5a.75.75 0 0 1 0-1.5Z"></path></svg>`;
|
|
22762
23584
|
return this.create(xml, params);
|
|
22763
23585
|
}
|
|
22764
23586
|
|
|
@@ -23084,6 +23906,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23084
23906
|
return this.create(xml, params);
|
|
23085
23907
|
}
|
|
23086
23908
|
|
|
23909
|
+
/**
|
|
23910
|
+
* Generate commentDiscussions24 SVG icon
|
|
23911
|
+
* @param {Object} params - Configuration parameters
|
|
23912
|
+
* @returns {Element} SVG element
|
|
23913
|
+
*/
|
|
23914
|
+
static commentDiscussions24(params) {
|
|
23915
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path></svg>`;
|
|
23916
|
+
return this.create(xml, params);
|
|
23917
|
+
}
|
|
23918
|
+
|
|
23087
23919
|
/**
|
|
23088
23920
|
* Generate commit SVG icon
|
|
23089
23921
|
* @param {Object} params - Configuration parameters
|
|
@@ -23094,6 +23926,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23094
23926
|
return this.create(xml, params);
|
|
23095
23927
|
}
|
|
23096
23928
|
|
|
23929
|
+
/**
|
|
23930
|
+
* Generate commit SVG icon
|
|
23931
|
+
* @param {Object} params - Configuration parameters
|
|
23932
|
+
* @returns {Element} SVG element
|
|
23933
|
+
*/
|
|
23934
|
+
static compose24(params) {
|
|
23935
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M1 21.25V4a1.75 1.75 0 0 1 1.75-1.75h7.51a.75.75 0 0 1 0 1.5H2.75A.25.25 0 0 0 2.5 4v17.25a.25.25 0 0 0 .25.25H20a.25.25 0 0 0 .25-.25V13a.75.75 0 0 1 1.5 0v8.25c0 .464-.184.909-.513 1.237A1.746 1.746 0 0 1 20 23H2.75A1.75 1.75 0 0 1 1 21.25Z"></path><path d="M19.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.25.929a.751.751 0 0 1-.928-.927l.929-3.25c.082-.287.235-.547.445-.758l8.61-8.61Zm-7.55 9.67a.241.241 0 0 0-.063.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064L19.19 6.25l-1.44-1.44Zm8.964-8.61a.245.245 0 0 0-.177-.073.245.245 0 0 0-.177.073L18.811 3.75l1.439 1.44 1.263-1.263a.245.245 0 0 0 .073-.177.245.245 0 0 0-.073-.177Z"></path></svg>`;
|
|
23936
|
+
return this.create(xml, params);
|
|
23937
|
+
}
|
|
23938
|
+
|
|
23097
23939
|
/**
|
|
23098
23940
|
* Generate container SVG icon
|
|
23099
23941
|
* @param {Object} params - Configuration parameters
|
|
@@ -23124,6 +23966,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23124
23966
|
return this.create(xml, params);
|
|
23125
23967
|
}
|
|
23126
23968
|
|
|
23969
|
+
/**
|
|
23970
|
+
* Generate crosshairs SVG icon
|
|
23971
|
+
* @param {Object} params - Configuration parameters
|
|
23972
|
+
* @returns {Element} SVG element
|
|
23973
|
+
*/
|
|
23974
|
+
static crosshairs(params) {
|
|
23975
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M14 8A6 6 0 1 1 2 8a6 6 0 0 1 12 0Zm-1.5 0a4.5 4.5 0 1 0-9 0 4.5 4.5 0 0 0 9 0Z"></path><path d="M5 7.25a.75.75 0 0 1 0 1.5H1a.75.75 0 0 1 0-1.5Zm3-7a.75.75 0 0 1 .75.75v4a.75.75 0 0 1-1.5 0V1A.75.75 0 0 1 8 .25Zm7 7a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1 0-1.5Zm-7 3a.75.75 0 0 1 .75.75v4a.75.75 0 0 1-1.5 0v-4a.75.75 0 0 1 .75-.75Z"></path></svg>`;
|
|
23976
|
+
return this.create(xml, params);
|
|
23977
|
+
}
|
|
23978
|
+
|
|
23127
23979
|
/**
|
|
23128
23980
|
* Generate deepSeek SVG icon
|
|
23129
23981
|
* @param {Object} params - Configuration parameters
|
|
@@ -23165,6 +24017,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23165
24017
|
return this.create(xml, params);
|
|
23166
24018
|
}
|
|
23167
24019
|
|
|
24020
|
+
/**
|
|
24021
|
+
* Generate dropZone SVG icon
|
|
24022
|
+
* @param {Object} params - Configuration parameters
|
|
24023
|
+
* @returns {Element} SVG element
|
|
24024
|
+
*/
|
|
24025
|
+
static dropZone(params) {
|
|
24026
|
+
const xml = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='64' height='64'><path d="M7 18C4.23858 18 2 15.7614 2 13C2 10.2386 4.23858 8 7 8C7.55228 8 8 8.44772 8 9C8 9.55228 7.55228 10 7 10C5.34315 10 4 11.3431 4 13C4 14.6569 5.34315 16 7 16H17C18.6569 16 20 14.6569 20 13C20 11.3431 18.6569 10 17 10C16.4477 10 16 9.55228 16 9C16 8.44772 16.4477 8 17 8C19.7614 8 22 10.2386 22 13C22 15.7614 19.7614 18 17 18H7Z" fill="currentColor"/><path d="M12 2L12 14M12 14L9 11M12 14L15 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
24027
|
+
return this.create(xml, params);
|
|
24028
|
+
}
|
|
24029
|
+
|
|
23168
24030
|
/**
|
|
23169
24031
|
* Generate dot SVG icon
|
|
23170
24032
|
* @param {Object} params - Configuration parameters
|
|
@@ -23205,6 +24067,26 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23205
24067
|
return this.create(xml, params);
|
|
23206
24068
|
}
|
|
23207
24069
|
|
|
24070
|
+
/**
|
|
24071
|
+
* Generate eye SVG icon
|
|
24072
|
+
* @param {Object} params - Configuration parameters
|
|
24073
|
+
* @returns {Element} SVG element
|
|
24074
|
+
*/
|
|
24075
|
+
static eye(params) {
|
|
24076
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M8 2c1.981 0 3.671.992 4.933 2.078 1.27 1.091 2.187 2.345 2.637 3.023a1.62 1.62 0 0 1 0 1.798c-.45.678-1.367 1.932-2.637 3.023C11.67 13.008 9.981 14 8 14c-1.981 0-3.671-.992-4.933-2.078C1.797 10.83.88 9.576.43 8.898a1.62 1.62 0 0 1 0-1.798c.45-.677 1.367-1.931 2.637-3.022C4.33 2.992 6.019 2 8 2ZM1.679 7.932a.12.12 0 0 0 0 .136c.411.622 1.241 1.75 2.366 2.717C5.176 11.758 6.527 12.5 8 12.5c1.473 0 2.825-.742 3.955-1.715 1.124-.967 1.954-2.096 2.366-2.717a.12.12 0 0 0 0-.136c-.412-.621-1.242-1.75-2.366-2.717C10.824 4.242 9.473 3.5 8 3.5c-1.473 0-2.825.742-3.955 1.715-1.124.967-1.954 2.096-2.366 2.717ZM8 10a2 2 0 1 1-.001-3.999A2 2 0 0 1 8 10Z"></path></svg>`;
|
|
24077
|
+
return this.create(xml, params);
|
|
24078
|
+
}
|
|
24079
|
+
|
|
24080
|
+
/**
|
|
24081
|
+
* Generate eye closed SVG icon
|
|
24082
|
+
* @param {Object} params - Configuration parameters
|
|
24083
|
+
* @returns {Element} SVG element
|
|
24084
|
+
*/
|
|
24085
|
+
static eyeClosed(params) {
|
|
24086
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M.143 2.31a.75.75 0 0 1 1.047-.167l14.5 10.5a.75.75 0 1 1-.88 1.214l-2.248-1.628C11.346 13.19 9.792 14 8 14c-1.981 0-3.67-.992-4.933-2.078C1.797 10.832.88 9.577.43 8.9a1.619 1.619 0 0 1 0-1.797c.353-.533.995-1.42 1.868-2.305L.31 3.357A.75.75 0 0 1 .143 2.31Zm1.536 5.622A.12.12 0 0 0 1.657 8c0 .021.006.045.022.068.412.621 1.242 1.75 2.366 2.717C5.175 11.758 6.527 12.5 8 12.5c1.195 0 2.31-.488 3.29-1.191L9.063 9.695A2 2 0 0 1 6.058 7.52L3.529 5.688a14.207 14.207 0 0 0-1.85 2.244ZM8 3.5c-.516 0-1.017.09-1.499.251a.75.75 0 1 1-.473-1.423A6.207 6.207 0 0 1 8 2c1.981 0 3.67.992 4.933 2.078 1.27 1.091 2.187 2.345 2.637 3.023a1.62 1.62 0 0 1 0 1.798c-.11.166-.248.365-.41.587a.75.75 0 1 1-1.21-.887c.148-.201.272-.382.371-.53a.119.119 0 0 0 0-.137c-.412-.621-1.242-1.75-2.366-2.717C10.825 4.242 9.473 3.5 8 3.5Z"></path></svg>`;
|
|
24087
|
+
return this.create(xml, params);
|
|
24088
|
+
}
|
|
24089
|
+
|
|
23208
24090
|
/**
|
|
23209
24091
|
* Generate file SVG icon
|
|
23210
24092
|
* @param {Object} params - Configuration parameters
|
|
@@ -23497,6 +24379,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23497
24379
|
return this.create(xml, params);
|
|
23498
24380
|
}
|
|
23499
24381
|
|
|
24382
|
+
/**
|
|
24383
|
+
* Generate lock SVG icon
|
|
24384
|
+
* @param {Object} params - Configuration parameters
|
|
24385
|
+
* @returns {Element} SVG element
|
|
24386
|
+
*/
|
|
24387
|
+
static lock(params) {
|
|
24388
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>`;
|
|
24389
|
+
return this.create(xml, params);
|
|
24390
|
+
}
|
|
24391
|
+
|
|
23500
24392
|
/**
|
|
23501
24393
|
* Generate lightBulb SVG icon
|
|
23502
24394
|
* @param {Object} params - Configuration parameters
|
|
@@ -23550,17 +24442,27 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23550
24442
|
}
|
|
23551
24443
|
|
|
23552
24444
|
/**
|
|
23553
|
-
* Generate
|
|
24445
|
+
* Generate moveToEnd SVG icon
|
|
23554
24446
|
* @param {Object} params - Configuration parameters
|
|
23555
24447
|
* @returns {Element} SVG element
|
|
23556
24448
|
*/
|
|
23557
|
-
static
|
|
23558
|
-
const xml = `<svg xmlns=
|
|
24449
|
+
static moveToEnd(params) {
|
|
24450
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="m10.78 8.53-3.75 3.75a.749.749 0 1 1-1.06-1.06l2.469-2.47H1.75a.75.75 0 0 1 0-1.5h6.689L5.97 4.78a.749.749 0 1 1 1.06-1.06l3.75 3.75a.749.749 0 0 1 0 1.06ZM13 12.25v-8.5a.75.75 0 0 1 1.5 0v8.5a.75.75 0 0 1-1.5 0Z"></path></svg>`;
|
|
23559
24451
|
return this.create(xml, params);
|
|
23560
24452
|
}
|
|
23561
24453
|
|
|
23562
24454
|
/**
|
|
23563
|
-
* Generate
|
|
24455
|
+
* Generate northStar SVG icon
|
|
24456
|
+
* @param {Object} params - Configuration parameters
|
|
24457
|
+
* @returns {Element} SVG element
|
|
24458
|
+
*/
|
|
24459
|
+
static northStar(params) {
|
|
24460
|
+
const xml = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'><path d='M8.5.75a.75.75 0 00-1.5 0v5.19L4.391 3.33a.75.75 0 10-1.06 1.061L5.939 7H.75a.75.75 0 000 1.5h5.19l-2.61 2.609a.75.75 0 101.061 1.06L7 9.561v5.189a.75.75 0 001.5 0V9.56l2.609 2.61a.75.75 0 101.06-1.061L9.561 8.5h5.189a.75.75 0 000-1.5H9.56l2.61-2.609a.75.75 0 00-1.061-1.06L8.5 5.939V.75z'></path></svg>`;
|
|
24461
|
+
return this.create(xml, params);
|
|
24462
|
+
}
|
|
24463
|
+
|
|
24464
|
+
/**
|
|
24465
|
+
* Generate note SVG icon
|
|
23564
24466
|
* @param {Object} params - Configuration parameters
|
|
23565
24467
|
* @returns {Element} SVG element
|
|
23566
24468
|
*/
|
|
@@ -23569,6 +24471,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23569
24471
|
return this.create(xml, params);
|
|
23570
24472
|
}
|
|
23571
24473
|
|
|
24474
|
+
/**
|
|
24475
|
+
* Generate note24 SVG icon
|
|
24476
|
+
* @param {Object} params - Configuration parameters
|
|
24477
|
+
* @returns {Element} SVG element
|
|
24478
|
+
*/
|
|
24479
|
+
static note24(params) {
|
|
24480
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 4.75C0 3.784.784 3 1.75 3h20.5c.966 0 1.75.784 1.75 1.75v14.5A1.75 1.75 0 0 1 22.25 21H1.75A1.75 1.75 0 0 1 0 19.25Zm1.75-.25a.25.25 0 0 0-.25.25v14.5c0 .138.112.25.25.25h20.5a.25.25 0 0 0 .25-.25V4.75a.25.25 0 0 0-.25-.25Z"></path><path d="M5 8.75A.75.75 0 0 1 5.75 8h11.5a.75.75 0 0 1 0 1.5H5.75A.75.75 0 0 1 5 8.75Zm0 4a.75.75 0 0 1 .75-.75h5.5a.75.75 0 0 1 0 1.5h-5.5a.75.75 0 0 1-.75-.75Z"></path></svg>`;
|
|
24481
|
+
return this.create(xml, params);
|
|
24482
|
+
}
|
|
24483
|
+
|
|
23572
24484
|
/**
|
|
23573
24485
|
* Generate openAI SVG icon
|
|
23574
24486
|
* @param {Object} params - Configuration parameters
|
|
@@ -23635,7 +24547,17 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23635
24547
|
* @returns {Element} SVG element
|
|
23636
24548
|
*/
|
|
23637
24549
|
static pin(params) {
|
|
23638
|
-
const xml = `<svg xmlns=
|
|
24550
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="m11.294.984 3.722 3.722a1.75 1.75 0 0 1-.504 2.826l-1.327.613a3.089 3.089 0 0 0-1.707 2.084l-.584 2.454c-.317 1.332-1.972 1.8-2.94.832L5.75 11.311 1.78 15.28a.749.749 0 1 1-1.06-1.06l3.969-3.97-2.204-2.204c-.968-.968-.5-2.623.832-2.94l2.454-.584a3.08 3.08 0 0 0 2.084-1.707l.613-1.327a1.75 1.75 0 0 1 2.826-.504ZM6.283 9.723l2.732 2.731a.25.25 0 0 0 .42-.119l.584-2.454a4.586 4.586 0 0 1 2.537-3.098l1.328-.613a.25.25 0 0 0 .072-.404l-3.722-3.722a.25.25 0 0 0-.404.072l-.613 1.328a4.584 4.584 0 0 1-3.098 2.537l-2.454.584a.25.25 0 0 0-.119.42l2.731 2.732Z"></path></svg>`;
|
|
24551
|
+
return this.create(xml, params);
|
|
24552
|
+
}
|
|
24553
|
+
|
|
24554
|
+
/**
|
|
24555
|
+
* Generate pin24 SVG icon
|
|
24556
|
+
* @param {Object} params - Configuration parameters
|
|
24557
|
+
* @returns {Element} SVG element
|
|
24558
|
+
*/
|
|
24559
|
+
static pin24(params) {
|
|
24560
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="m16.114 1.553 6.333 6.333a1.75 1.75 0 0 1-.603 2.869l-1.63.633a5.67 5.67 0 0 0-3.395 3.725l-1.131 3.959a1.75 1.75 0 0 1-2.92.757L9 16.061l-5.595 5.594a.749.749 0 1 1-1.06-1.06L7.939 15l-3.768-3.768a1.75 1.75 0 0 1 .757-2.92l3.959-1.131a5.666 5.666 0 0 0 3.725-3.395l.633-1.63a1.75 1.75 0 0 1 2.869-.603ZM5.232 10.171l8.597 8.597a.25.25 0 0 0 .417-.108l1.131-3.959A7.17 7.17 0 0 1 19.67 9.99l1.63-.634a.25.25 0 0 0 .086-.409l-6.333-6.333a.25.25 0 0 0-.409.086l-.634 1.63a7.17 7.17 0 0 1-4.711 4.293L5.34 9.754a.25.25 0 0 0-.108.417Z"></path></svg>`;
|
|
23639
24561
|
return this.create(xml, params);
|
|
23640
24562
|
}
|
|
23641
24563
|
|
|
@@ -23751,6 +24673,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23751
24673
|
return this.create(xml, params);
|
|
23752
24674
|
}
|
|
23753
24675
|
|
|
24676
|
+
/**
|
|
24677
|
+
* Generate sparkle SVG icon
|
|
24678
|
+
* @param {Object} params - Configuration parameters
|
|
24679
|
+
* @returns {Element} SVG element
|
|
24680
|
+
*/
|
|
24681
|
+
static sparkle(params) {
|
|
24682
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M7.198.57c.275-.752 1.34-.752 1.615 0l.849 2.317a5.819 5.819 0 0 0 3.462 3.463l2.317.848c.753.275.753 1.34 0 1.615l-2.317.849a5.815 5.815 0 0 0-3.462 3.462l-.849 2.317c-.275.753-1.34.753-1.615 0l-.848-2.317a5.819 5.819 0 0 0-3.463-3.462L.57 8.813c-.752-.275-.752-1.34 0-1.615l2.317-.848A5.823 5.823 0 0 0 6.35 2.887L7.198.57Zm.562 2.833A7.323 7.323 0 0 1 3.403 7.76l-.673.246.673.246a7.324 7.324 0 0 1 4.357 4.356l.246.673.246-.673a7.322 7.322 0 0 1 4.356-4.356l.673-.246-.673-.246a7.324 7.324 0 0 1-4.356-4.357l-.246-.673-.246.673Z"></path></svg>`;
|
|
24683
|
+
return this.create(xml, params);
|
|
24684
|
+
}
|
|
24685
|
+
|
|
23754
24686
|
/**
|
|
23755
24687
|
* Generate square SVG icon
|
|
23756
24688
|
* @param {Object} params - Configuration parameters
|
|
@@ -23761,6 +24693,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
23761
24693
|
return this.create(xml, params);
|
|
23762
24694
|
}
|
|
23763
24695
|
|
|
24696
|
+
/**
|
|
24697
|
+
* Generate squarCircle SVG icon
|
|
24698
|
+
* @param {Object} params - Configuration parameters
|
|
24699
|
+
* @returns {Element} SVG element
|
|
24700
|
+
*/
|
|
24701
|
+
static squareCircle(params) {
|
|
24702
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16Zm0-1.5a6.5 6.5 0 1 0 0-13 6.5 6.5 0 0 0 0 13Z"></path><path d="M5 5.75A.75.75 0 0 1 5.75 5h4.5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1-.75-.75Z"></path></svg>`;
|
|
24703
|
+
return this.create(xml, params);
|
|
24704
|
+
}
|
|
24705
|
+
|
|
23764
24706
|
/**
|
|
23765
24707
|
* Generate stack SVG icon
|
|
23766
24708
|
* @param {Object} params - Configuration parameters
|
|
@@ -24051,6 +24993,16 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
24051
24993
|
return this.create(xml, params);
|
|
24052
24994
|
}
|
|
24053
24995
|
|
|
24996
|
+
/**
|
|
24997
|
+
* Generate verticalEllipsis SVG icon
|
|
24998
|
+
* @param {Object} params - Configuration parameters
|
|
24999
|
+
* @returns {Element} SVG element
|
|
25000
|
+
*/
|
|
25001
|
+
static verticalEllipsis(params) {
|
|
25002
|
+
const xml = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16' transform='rotate(90)'><path d='M8 9a1.5 1.5 0 100-3 1.5 1.5 0 000 3zM1.5 9a1.5 1.5 0 100-3 1.5 1.5 0 000 3zm13 0a1.5 1.5 0 100-3 1.5 1.5 0 000 3z'></path></svg>`;
|
|
25003
|
+
return this.create(xml, params);
|
|
25004
|
+
}
|
|
25005
|
+
|
|
24054
25006
|
/**
|
|
24055
25007
|
* Generate x SVG icon
|
|
24056
25008
|
* @param {Object} params - Configuration parameters
|
|
@@ -24080,10 +25032,318 @@ let SVGUtils$1 = class SVGUtils {
|
|
|
24080
25032
|
const xml = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='16' height='16'><path fill-rule='evenodd' d='M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z'></path></svg>`;
|
|
24081
25033
|
return this.create(xml, params);
|
|
24082
25034
|
}
|
|
25035
|
+
|
|
25036
|
+
static zai(params) {
|
|
25037
|
+
const xml = `<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em"><title>Z.ai</title><path d="M12.105 2L9.927 4.953H.653L2.83 2h9.276zM23.254 19.048L21.078 22h-9.242l2.174-2.952h9.244zM24 2L9.264 22H0L14.736 2H24z"/></svg>`;
|
|
25038
|
+
return this.create(xml, params);
|
|
25039
|
+
}
|
|
24083
25040
|
};
|
|
24084
25041
|
|
|
24085
25042
|
var SVGUtils_1 = SVGUtils$1;
|
|
24086
25043
|
|
|
25044
|
+
/*
|
|
25045
|
+
* Component: StringUtils
|
|
25046
|
+
* Block-UUID: 7069f2b4-f0b3-4dcd-9eae-5cecaddcdd66
|
|
25047
|
+
* Version: 1.0.0
|
|
25048
|
+
* Description: A collection of utility functions for common string manipulation and processing tasks within GitSense Chat.
|
|
25049
|
+
* Language: JavaScript
|
|
25050
|
+
* Created-at: 2025-10-30T22:06:47.000Z
|
|
25051
|
+
* Authors: Qwen 3 Coder 480B - Cerebras (v1.0.0)
|
|
25052
|
+
*/
|
|
25053
|
+
|
|
25054
|
+
/**
|
|
25055
|
+
* Splits a string into an array of substrings based on a delimiter, up to a specified limit.
|
|
25056
|
+
* This mimics behavior similar to Python's `str.split(sep, maxsplit)` or Java's `String.split(regex, limit)`.
|
|
25057
|
+
*
|
|
25058
|
+
* @param {string} text - The string to split.
|
|
25059
|
+
* @param {string|RegExp} delimiter - The delimiter to split the string by.
|
|
25060
|
+
* @param {number} [limit=Infinity] - The maximum number of parts to return. The final part will contain the remainder of the string.
|
|
25061
|
+
* @returns {string[]} An array of substrings.
|
|
25062
|
+
*/
|
|
25063
|
+
function splitWithLimit$1(text, delimiter, limit = Infinity) {
|
|
25064
|
+
if (limit === 0) {
|
|
25065
|
+
return [];
|
|
25066
|
+
}
|
|
25067
|
+
if (limit === 1) {
|
|
25068
|
+
return [text];
|
|
25069
|
+
}
|
|
25070
|
+
|
|
25071
|
+
const parts = [];
|
|
25072
|
+
let remainingText = text;
|
|
25073
|
+
let count = 0;
|
|
25074
|
+
|
|
25075
|
+
// Handle RegExp delimiter
|
|
25076
|
+
if (delimiter instanceof RegExp) {
|
|
25077
|
+
// For RegExp, we need to manually find matches and slice the string
|
|
25078
|
+
// This is a simplified approach and might not cover all edge cases of global regex matching
|
|
25079
|
+
// especially with capture groups or zero-width matches.
|
|
25080
|
+
const flags = delimiter.flags.includes('g') ? delimiter.flags : delimiter.flags + 'g';
|
|
25081
|
+
const globalDelimiter = new RegExp(delimiter.source, flags);
|
|
25082
|
+
let match;
|
|
25083
|
+
let lastIndex = 0;
|
|
25084
|
+
let matchCount = 0;
|
|
25085
|
+
|
|
25086
|
+
// We need (limit - 1) matches to create `limit` parts
|
|
25087
|
+
while ((match = globalDelimiter.exec(remainingText)) !== null && matchCount < limit - 1) {
|
|
25088
|
+
// Add the part before the match
|
|
25089
|
+
parts.push(remainingText.substring(lastIndex, match.index));
|
|
25090
|
+
// Add the matched delimiter part itself if it's non-empty (important for zero-width matches)
|
|
25091
|
+
// This part is tricky; typically, the delimiter itself is not part of the returned array.
|
|
25092
|
+
// The logic below follows the standard split behavior where the delimiter is not included.
|
|
25093
|
+
lastIndex = match.index + match[0].length;
|
|
25094
|
+
matchCount++;
|
|
25095
|
+
// Avoid infinite loop for zero-length matches
|
|
25096
|
+
if (match.index === globalDelimiter.lastIndex) {
|
|
25097
|
+
globalDelimiter.lastIndex++;
|
|
25098
|
+
}
|
|
25099
|
+
}
|
|
25100
|
+
// Add the final part
|
|
25101
|
+
parts.push(remainingText.substring(lastIndex));
|
|
25102
|
+
} else {
|
|
25103
|
+
// Handle string delimiter
|
|
25104
|
+
const delimLength = delimiter.length;
|
|
25105
|
+
if (delimLength === 0) {
|
|
25106
|
+
// If delimiter is an empty string, split by characters
|
|
25107
|
+
// This is consistent with JS String.split('')
|
|
25108
|
+
return text.split('').slice(0, limit);
|
|
25109
|
+
}
|
|
25110
|
+
let index;
|
|
25111
|
+
while (count < limit - 1 && (index = remainingText.indexOf(delimiter)) !== -1) {
|
|
25112
|
+
parts.push(remainingText.substring(0, index));
|
|
25113
|
+
remainingText = remainingText.substring(index + delimLength);
|
|
25114
|
+
count++;
|
|
25115
|
+
}
|
|
25116
|
+
// Add the final part (the rest of the string)
|
|
25117
|
+
parts.push(remainingText);
|
|
25118
|
+
}
|
|
25119
|
+
|
|
25120
|
+
return parts;
|
|
25121
|
+
}
|
|
25122
|
+
|
|
25123
|
+
/**
|
|
25124
|
+
* Capitalizes the first character of a string.
|
|
25125
|
+
*
|
|
25126
|
+
* @param {string} text - The string to capitalize.
|
|
25127
|
+
* @returns {string} The string with its first character capitalized.
|
|
25128
|
+
*/
|
|
25129
|
+
function capitalize$1(text) {
|
|
25130
|
+
if (!text || typeof text !== 'string') {
|
|
25131
|
+
return text;
|
|
25132
|
+
}
|
|
25133
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
25134
|
+
}
|
|
25135
|
+
|
|
25136
|
+
/**
|
|
25137
|
+
* Converts a string to title case (capitalizing the first letter of each word).
|
|
25138
|
+
* Words are sequences of characters separated by space, tab, or newline.
|
|
25139
|
+
*
|
|
25140
|
+
* @param {string} text - The string to convert.
|
|
25141
|
+
* @returns {string} The string in title case.
|
|
25142
|
+
*/
|
|
25143
|
+
function titleCase$1(text) {
|
|
25144
|
+
if (!text || typeof text !== 'string') {
|
|
25145
|
+
return text;
|
|
25146
|
+
}
|
|
25147
|
+
// Split by one or more whitespace characters
|
|
25148
|
+
return text.split(/\s+/).map(word => capitalize$1(word)).join(' ');
|
|
25149
|
+
}
|
|
25150
|
+
|
|
25151
|
+
/**
|
|
25152
|
+
* Converts a string to camelCase.
|
|
25153
|
+
*
|
|
25154
|
+
* @param {string} text - The string to convert.
|
|
25155
|
+
* @returns {string} The string in camelCase.
|
|
25156
|
+
*/
|
|
25157
|
+
function camelCase$1(text) {
|
|
25158
|
+
if (!text || typeof text !== 'string') {
|
|
25159
|
+
return text;
|
|
25160
|
+
}
|
|
25161
|
+
return text
|
|
25162
|
+
.split(/\W+/) // Split on non-word characters
|
|
25163
|
+
.map((word, index) => {
|
|
25164
|
+
if (index === 0) {
|
|
25165
|
+
// First word is lowercase
|
|
25166
|
+
return word.toLowerCase();
|
|
25167
|
+
}
|
|
25168
|
+
// Subsequent words have their first letter capitalized
|
|
25169
|
+
return capitalize$1(word.toLowerCase());
|
|
25170
|
+
})
|
|
25171
|
+
.join('');
|
|
25172
|
+
}
|
|
25173
|
+
|
|
25174
|
+
/**
|
|
25175
|
+
* Converts a string to PascalCase.
|
|
25176
|
+
*
|
|
25177
|
+
* @param {string} text - The string to convert.
|
|
25178
|
+
* @returns {string} The string in PascalCase.
|
|
25179
|
+
*/
|
|
25180
|
+
function pascalCase$1(text) {
|
|
25181
|
+
if (!text || typeof text !== 'string') {
|
|
25182
|
+
return text;
|
|
25183
|
+
}
|
|
25184
|
+
return text
|
|
25185
|
+
.split(/\W+/) // Split on non-word characters
|
|
25186
|
+
.map(word => capitalize$1(word.toLowerCase()))
|
|
25187
|
+
.join('');
|
|
25188
|
+
}
|
|
25189
|
+
|
|
25190
|
+
/**
|
|
25191
|
+
* Converts a string to kebab-case.
|
|
25192
|
+
*
|
|
25193
|
+
* @param {string} text - The string to convert.
|
|
25194
|
+
* @returns {string} The string in kebab-case.
|
|
25195
|
+
*/
|
|
25196
|
+
function kebabCase$1(text) {
|
|
25197
|
+
if (!text || typeof text !== 'string') {
|
|
25198
|
+
return text;
|
|
25199
|
+
}
|
|
25200
|
+
return text
|
|
25201
|
+
.split(/\W+/) // Split on non-word characters
|
|
25202
|
+
.map(word => word.toLowerCase())
|
|
25203
|
+
.filter(word => word.length > 0) // Remove empty strings from split
|
|
25204
|
+
.join('-');
|
|
25205
|
+
}
|
|
25206
|
+
|
|
25207
|
+
/**
|
|
25208
|
+
* Converts a string to snake_case.
|
|
25209
|
+
*
|
|
25210
|
+
* @param {string} text - The string to convert.
|
|
25211
|
+
* @returns {string} The string in snake_case.
|
|
25212
|
+
*/
|
|
25213
|
+
function snakeCase$1(text) {
|
|
25214
|
+
if (!text || typeof text !== 'string') {
|
|
25215
|
+
return text;
|
|
25216
|
+
}
|
|
25217
|
+
return text
|
|
25218
|
+
.split(/\W+/) // Split on non-word characters
|
|
25219
|
+
.map(word => word.toLowerCase())
|
|
25220
|
+
.filter(word => word.length > 0) // Remove empty strings from split
|
|
25221
|
+
.join('_');
|
|
25222
|
+
}
|
|
25223
|
+
|
|
25224
|
+
/**
|
|
25225
|
+
* Converts a string to CONSTANT_CASE.
|
|
25226
|
+
*
|
|
25227
|
+
* @param {string} text - The string to convert.
|
|
25228
|
+
* @returns {string} The string in CONSTANT_CASE.
|
|
25229
|
+
*/
|
|
25230
|
+
function constantCase$1(text) {
|
|
25231
|
+
if (!text || typeof text !== 'string') {
|
|
25232
|
+
return text;
|
|
25233
|
+
}
|
|
25234
|
+
return text
|
|
25235
|
+
.split(/\W+/) // Split on non-word characters
|
|
25236
|
+
.map(word => word.toUpperCase())
|
|
25237
|
+
.filter(word => word.length > 0) // Remove empty strings from split
|
|
25238
|
+
.join('_');
|
|
25239
|
+
}
|
|
25240
|
+
|
|
25241
|
+
/**
|
|
25242
|
+
* Trims leading and trailing whitespace and normalizes internal whitespace
|
|
25243
|
+
* (replacing sequences of whitespace characters with a single space).
|
|
25244
|
+
*
|
|
25245
|
+
* @param {string} text - The string to trim and normalize.
|
|
25246
|
+
* @returns {string} The trimmed and normalized string.
|
|
25247
|
+
*/
|
|
25248
|
+
function trimWhitespace$1(text) {
|
|
25249
|
+
if (!text || typeof text !== 'string') {
|
|
25250
|
+
return text;
|
|
25251
|
+
}
|
|
25252
|
+
return text.trim().replace(/\s+/g, ' ');
|
|
25253
|
+
}
|
|
25254
|
+
|
|
25255
|
+
/**
|
|
25256
|
+
* Truncates a string to a specified maximum length and appends a suffix if truncated.
|
|
25257
|
+
*
|
|
25258
|
+
* @param {string} text - The string to truncate.
|
|
25259
|
+
* @param {number} maxLength - The maximum length of the string.
|
|
25260
|
+
* @param {string} [suffix='...'] - The suffix to append if the string is truncated.
|
|
25261
|
+
* @returns {string} The truncated string with suffix, or the original string if not truncated.
|
|
25262
|
+
*/
|
|
25263
|
+
function truncate$1(text, maxLength, suffix = '...') {
|
|
25264
|
+
if (!text || typeof text !== 'string' || maxLength <= 0) {
|
|
25265
|
+
return '';
|
|
25266
|
+
}
|
|
25267
|
+
if (text.length <= maxLength) {
|
|
25268
|
+
return text;
|
|
25269
|
+
}
|
|
25270
|
+
// Ensure we don't cut the suffix itself if maxLength is very small
|
|
25271
|
+
const suffixLength = suffix.length;
|
|
25272
|
+
if (maxLength <= suffixLength) {
|
|
25273
|
+
// If max length is less than or equal to suffix, return a truncated suffix
|
|
25274
|
+
// This is a bit of an edge case, but handles it gracefully.
|
|
25275
|
+
return suffix.substring(0, maxLength);
|
|
25276
|
+
}
|
|
25277
|
+
return text.substring(0, maxLength - suffixLength) + suffix;
|
|
25278
|
+
}
|
|
25279
|
+
|
|
25280
|
+
/**
|
|
25281
|
+
* Escapes HTML characters in a string to prevent them from being interpreted as HTML.
|
|
25282
|
+
*
|
|
25283
|
+
* @param {string} text - The string to escape.
|
|
25284
|
+
* @returns {string} The escaped string.
|
|
25285
|
+
*/
|
|
25286
|
+
function escapeHtml(text) {
|
|
25287
|
+
if (!text || typeof text !== 'string') {
|
|
25288
|
+
return text;
|
|
25289
|
+
}
|
|
25290
|
+
const htmlEscapes = {
|
|
25291
|
+
'&': '&',
|
|
25292
|
+
'<': '<',
|
|
25293
|
+
'>': '>',
|
|
25294
|
+
'"': '"',
|
|
25295
|
+
"'": ''',
|
|
25296
|
+
};
|
|
25297
|
+
return text.replace(/[&<>"']/g, match => htmlEscapes[match]);
|
|
25298
|
+
}
|
|
25299
|
+
|
|
25300
|
+
/**
|
|
25301
|
+
* Removes HTML tags from a string.
|
|
25302
|
+
*
|
|
25303
|
+
* @param {string} text - The string to strip tags from.
|
|
25304
|
+
* @returns {string} The string without HTML tags.
|
|
25305
|
+
*/
|
|
25306
|
+
function stripHtml(text) {
|
|
25307
|
+
if (!text || typeof text !== 'string') {
|
|
25308
|
+
return text;
|
|
25309
|
+
}
|
|
25310
|
+
return text.replace(/<[^>]*>/g, '');
|
|
25311
|
+
}
|
|
25312
|
+
|
|
25313
|
+
/**
|
|
25314
|
+
* Performs a basic check to see if a string looks like a valid email address.
|
|
25315
|
+
* This is a simple validation and should not be used for robust security checks.
|
|
25316
|
+
*
|
|
25317
|
+
* @param {string} email - The email string to validate.
|
|
25318
|
+
* @returns {boolean} True if the string looks like a valid email, false otherwise.
|
|
25319
|
+
*/
|
|
25320
|
+
function isValidEmail(email) {
|
|
25321
|
+
if (!email || typeof email !== 'string') {
|
|
25322
|
+
return false;
|
|
25323
|
+
}
|
|
25324
|
+
// A basic regex for email validation. Note: Fully validating email addresses
|
|
25325
|
+
// is extremely complex. This covers common cases.
|
|
25326
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
25327
|
+
return emailRegex.test(email);
|
|
25328
|
+
}
|
|
25329
|
+
|
|
25330
|
+
|
|
25331
|
+
var stringUtils = {
|
|
25332
|
+
splitWithLimit: splitWithLimit$1,
|
|
25333
|
+
capitalize: capitalize$1,
|
|
25334
|
+
titleCase: titleCase$1,
|
|
25335
|
+
camelCase: camelCase$1,
|
|
25336
|
+
kebabCase: kebabCase$1,
|
|
25337
|
+
snakeCase: snakeCase$1,
|
|
25338
|
+
constantCase: constantCase$1,
|
|
25339
|
+
pascalCase: pascalCase$1,
|
|
25340
|
+
trimWhitespace: trimWhitespace$1,
|
|
25341
|
+
truncate: truncate$1,
|
|
25342
|
+
escapeHtml,
|
|
25343
|
+
stripHtml,
|
|
25344
|
+
isValidEmail,
|
|
25345
|
+
};
|
|
25346
|
+
|
|
24087
25347
|
/*
|
|
24088
25348
|
* Component: Language Name Utils
|
|
24089
25349
|
* Block-UUID: 313abeab-2bb3-49d1-8693-e9e88aa97113
|
|
@@ -24255,19 +25515,670 @@ var LanguageNameUtils$1 = {
|
|
|
24255
25515
|
getLanguageNameMap
|
|
24256
25516
|
};
|
|
24257
25517
|
|
|
25518
|
+
/**
|
|
25519
|
+
* Component: MetaRawResultUtils
|
|
25520
|
+
* Block-UUID: 8a4d235b-a9d3-44b8-9c08-47b3678ba1c0
|
|
25521
|
+
* Parent-UUID: N/A
|
|
25522
|
+
* Version: 1.0.0
|
|
25523
|
+
* Description: Utility for parsing and extracting mappings from meta-raw-result messages
|
|
25524
|
+
* Language: JavaScript
|
|
25525
|
+
* Created-at: 2025-11-15T19:15:00.000Z
|
|
25526
|
+
* Authors: GLM-4.6 (v1.0.0)
|
|
25527
|
+
*/
|
|
25528
|
+
|
|
25529
|
+
const ChatUtils$1 = ChatUtils$2;
|
|
25530
|
+
|
|
25531
|
+
/**
|
|
25532
|
+
* Extracts and parses all meta-raw-result messages from a chat
|
|
25533
|
+
* @param {Object} chat - The chat object containing messages
|
|
25534
|
+
* @param {string} model - The model name (optional, for message filtering)
|
|
25535
|
+
* @returns {Map<number, Object>} Map of chatId to file metadata
|
|
25536
|
+
*/
|
|
25537
|
+
function extractMetaRawResultMappings$1(chat, model = null) {
|
|
25538
|
+
const mappings = new Map();
|
|
25539
|
+
|
|
25540
|
+
try {
|
|
25541
|
+
// Get all messages from the chat
|
|
25542
|
+
const allMessages = ChatUtils$1.getChatMessages(chat, model);
|
|
25543
|
+
|
|
25544
|
+
// Filter for meta-raw-result messages
|
|
25545
|
+
const metaRawMessages = allMessages.filter(msg => isMetaRawResultMessage$1(msg));
|
|
25546
|
+
|
|
25547
|
+
// Parse each meta-raw-result message
|
|
25548
|
+
for (const message of metaRawMessages) {
|
|
25549
|
+
const messageMappings = parseMetaRawResultContent$1(message.message);
|
|
25550
|
+
|
|
25551
|
+
// Merge mappings into the main map
|
|
25552
|
+
for (const [chatId, fileInfo] of messageMappings) {
|
|
25553
|
+
mappings.set(chatId, fileInfo);
|
|
25554
|
+
}
|
|
25555
|
+
}
|
|
25556
|
+
|
|
25557
|
+
return mappings;
|
|
25558
|
+
} catch (error) {
|
|
25559
|
+
console.error('Error extracting meta-raw-result mappings:', error);
|
|
25560
|
+
return mappings;
|
|
25561
|
+
}
|
|
25562
|
+
}
|
|
25563
|
+
|
|
25564
|
+
/**
|
|
25565
|
+
* Validates if a message is a meta-raw-result message
|
|
25566
|
+
* @param {Object} message - The message object to validate
|
|
25567
|
+
* @returns {boolean} True if message is meta-raw-result type
|
|
25568
|
+
*/
|
|
25569
|
+
function isMetaRawResultMessage$1(message) {
|
|
25570
|
+
if (!message || !message.message) {
|
|
25571
|
+
return false;
|
|
25572
|
+
}
|
|
25573
|
+
|
|
25574
|
+
// Check if message type is meta-raw-result
|
|
25575
|
+
if (message.type === 'meta-raw-result') {
|
|
25576
|
+
return true;
|
|
25577
|
+
}
|
|
25578
|
+
|
|
25579
|
+
return false;
|
|
25580
|
+
}
|
|
25581
|
+
|
|
25582
|
+
/**
|
|
25583
|
+
* Parses a single meta-raw-result message content
|
|
25584
|
+
* @param {string} messageContent - The message content to parse
|
|
25585
|
+
* @returns {Map<number, Object>} Map of chatId to file metadata
|
|
25586
|
+
*/
|
|
25587
|
+
function parseMetaRawResultContent$1(messageContent) {
|
|
25588
|
+
const mappings = new Map();
|
|
25589
|
+
|
|
25590
|
+
try {
|
|
25591
|
+
// Split content into lines
|
|
25592
|
+
const lines = messageContent.split('\n');
|
|
25593
|
+
|
|
25594
|
+
// Find the data section
|
|
25595
|
+
let dataSectionStart = -1;
|
|
25596
|
+
for (let i = 0; i < lines.length; i++) {
|
|
25597
|
+
if (lines[i].trimStart().startsWith('## Data ')) {
|
|
25598
|
+
dataSectionStart = i;
|
|
25599
|
+
break;
|
|
25600
|
+
}
|
|
25601
|
+
}
|
|
25602
|
+
|
|
25603
|
+
if (dataSectionStart === -1) {
|
|
25604
|
+
return mappings; // No data section found
|
|
25605
|
+
}
|
|
25606
|
+
|
|
25607
|
+
// Find the table header (line with |)
|
|
25608
|
+
let headerLine = -1;
|
|
25609
|
+
for (let i = dataSectionStart; i < lines.length; i++) {
|
|
25610
|
+
if (lines[i].includes('|') && lines[i].includes('Chat ID')) {
|
|
25611
|
+
headerLine = i;
|
|
25612
|
+
break;
|
|
25613
|
+
}
|
|
25614
|
+
}
|
|
25615
|
+
|
|
25616
|
+
if (headerLine === -1) {
|
|
25617
|
+
return mappings; // No table header found
|
|
25618
|
+
}
|
|
25619
|
+
|
|
25620
|
+
// Find the separator line (|---|---|...)
|
|
25621
|
+
let separatorLine = -1;
|
|
25622
|
+
for (let i = headerLine + 1; i < lines.length; i++) {
|
|
25623
|
+
if (lines[i].match(/^\|[\s\-\|]*\|$/)) {
|
|
25624
|
+
separatorLine = i;
|
|
25625
|
+
break;
|
|
25626
|
+
}
|
|
25627
|
+
}
|
|
25628
|
+
|
|
25629
|
+
if (separatorLine === -1) {
|
|
25630
|
+
return mappings; // No separator found
|
|
25631
|
+
}
|
|
25632
|
+
|
|
25633
|
+
// Parse data rows (everything after the separator)
|
|
25634
|
+
for (let i = separatorLine + 1; i < lines.length; i++) {
|
|
25635
|
+
const line = lines[i].trim();
|
|
25636
|
+
|
|
25637
|
+
// Skip empty lines or separator lines
|
|
25638
|
+
if (!line || line.match(/^\|[\s\-\|]*\|$/) || !line.includes('|')) {
|
|
25639
|
+
continue;
|
|
25640
|
+
}
|
|
25641
|
+
|
|
25642
|
+
// Parse the table row
|
|
25643
|
+
const fileInfo = parseTableRow$1(line);
|
|
25644
|
+
if (fileInfo && fileInfo.id) {
|
|
25645
|
+
mappings.set(fileInfo.id, fileInfo);
|
|
25646
|
+
}
|
|
25647
|
+
}
|
|
25648
|
+
|
|
25649
|
+
return mappings;
|
|
25650
|
+
} catch (error) {
|
|
25651
|
+
console.error('Error parsing meta-raw-result content:', error);
|
|
25652
|
+
return mappings;
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
|
|
25656
|
+
/**
|
|
25657
|
+
* Parses a single table row from meta-raw-result content
|
|
25658
|
+
* @param {string} rowLine - The table row line to parse
|
|
25659
|
+
* @returns {Object|null} Parsed file information object or null if parsing failed
|
|
25660
|
+
*/
|
|
25661
|
+
function parseTableRow$1(rowLine) {
|
|
25662
|
+
try {
|
|
25663
|
+
// Split the row by | and clean up
|
|
25664
|
+
const cells = rowLine.split('|').map(cell => cell.trim()).filter(cell => cell);
|
|
25665
|
+
|
|
25666
|
+
if (cells.length < 6) {
|
|
25667
|
+
return null; // Not enough columns
|
|
25668
|
+
}
|
|
25669
|
+
|
|
25670
|
+
// Extract basic information from the table cells
|
|
25671
|
+
const repo = cells[0];
|
|
25672
|
+
const branch = cells[1];
|
|
25673
|
+
const filePath = cells[2];
|
|
25674
|
+
const language = cells[3];
|
|
25675
|
+
const chatId = parseInt(cells[4], 10);
|
|
25676
|
+
|
|
25677
|
+
// Parse file path to extract name and path
|
|
25678
|
+
const pathParts = filePath.split('/');
|
|
25679
|
+
const name = pathParts[pathParts.length - 1];
|
|
25680
|
+
const path = filePath;
|
|
25681
|
+
|
|
25682
|
+
// Create full path
|
|
25683
|
+
const fullPath = `${repo}/${path}`;
|
|
25684
|
+
|
|
25685
|
+
return {
|
|
25686
|
+
id: chatId,
|
|
25687
|
+
name: name,
|
|
25688
|
+
path: path,
|
|
25689
|
+
repo: repo,
|
|
25690
|
+
branch: branch,
|
|
25691
|
+
language: language,
|
|
25692
|
+
fullPath: fullPath
|
|
25693
|
+
};
|
|
25694
|
+
} catch (error) {
|
|
25695
|
+
console.error('Error parsing table row:', error);
|
|
25696
|
+
return null;
|
|
25697
|
+
}
|
|
25698
|
+
}
|
|
25699
|
+
|
|
25700
|
+
/**
|
|
25701
|
+
* Parses size string to bytes
|
|
25702
|
+
* @param {string} sizeStr - Size string (e.g., "1.2 KB", "500 B")
|
|
25703
|
+
* @returns {number} Size in bytes
|
|
25704
|
+
*/
|
|
25705
|
+
function parseSize$1(sizeStr) {
|
|
25706
|
+
if (!sizeStr || sizeStr === 'N/A') {
|
|
25707
|
+
return 0;
|
|
25708
|
+
}
|
|
25709
|
+
|
|
25710
|
+
const match = sizeStr.match(/^([\d.]+)\s*(B|KB|MB|GB)?$/i);
|
|
25711
|
+
if (!match) {
|
|
25712
|
+
return 0;
|
|
25713
|
+
}
|
|
25714
|
+
|
|
25715
|
+
const value = parseFloat(match[1]);
|
|
25716
|
+
const unit = (match[2] || 'B').toUpperCase();
|
|
25717
|
+
|
|
25718
|
+
switch (unit) {
|
|
25719
|
+
case 'B': return Math.round(value);
|
|
25720
|
+
case 'KB': return Math.round(value * 1024);
|
|
25721
|
+
case 'MB': return Math.round(value * 1024 * 1024);
|
|
25722
|
+
case 'GB': return Math.round(value * 1024 * 1024 * 1024);
|
|
25723
|
+
default: return 0;
|
|
25724
|
+
}
|
|
25725
|
+
}
|
|
25726
|
+
|
|
25727
|
+
/**
|
|
25728
|
+
* Parses tokens string to number
|
|
25729
|
+
* @param {string} tokensStr - Tokens string (e.g., "1.2k", "500")
|
|
25730
|
+
* @returns {number} Token count
|
|
25731
|
+
*/
|
|
25732
|
+
function parseTokens$1(tokensStr) {
|
|
25733
|
+
if (!tokensStr || tokensStr === 'N/A') {
|
|
25734
|
+
return 0;
|
|
25735
|
+
}
|
|
25736
|
+
|
|
25737
|
+
const match = tokensStr.match(/^([\d.]+)(k|m|b)?$/i);
|
|
25738
|
+
if (!match) {
|
|
25739
|
+
return 0;
|
|
25740
|
+
}
|
|
25741
|
+
|
|
25742
|
+
const value = parseFloat(match[1]);
|
|
25743
|
+
const suffix = (match[2] || '').toLowerCase();
|
|
25744
|
+
|
|
25745
|
+
switch (suffix) {
|
|
25746
|
+
case 'k': return Math.round(value * 1000);
|
|
25747
|
+
case 'm': return Math.round(value * 1000000);
|
|
25748
|
+
case 'b': return Math.round(value * 1000000000);
|
|
25749
|
+
default: return Math.round(value);
|
|
25750
|
+
}
|
|
25751
|
+
}
|
|
25752
|
+
|
|
25753
|
+
var MetaRawResultUtils$1 = {
|
|
25754
|
+
extractMetaRawResultMappings: extractMetaRawResultMappings$1,
|
|
25755
|
+
isMetaRawResultMessage: isMetaRawResultMessage$1,
|
|
25756
|
+
parseMetaRawResultContent: parseMetaRawResultContent$1,
|
|
25757
|
+
parseTableRow: parseTableRow$1,
|
|
25758
|
+
parseSize: parseSize$1,
|
|
25759
|
+
parseTokens: parseTokens$1
|
|
25760
|
+
};
|
|
25761
|
+
|
|
25762
|
+
/**
|
|
25763
|
+
* Component: ReferenceMessageUtils
|
|
25764
|
+
* Block-UUID: 2870551a-4311-4d64-9491-c9cc62f276e8
|
|
25765
|
+
* Parent-UUID: N/A
|
|
25766
|
+
* Description: Utility for parsing reference messages in the compact message workflow, extracting session data, metadata, and message sections.
|
|
25767
|
+
* Language: JavaScript
|
|
25768
|
+
* Created-at: 2025-12-07T00:08:42.573Z
|
|
25769
|
+
* Authors: GLM-4.6 (v1.0.0)
|
|
25770
|
+
*/
|
|
25771
|
+
|
|
25772
|
+
let ReferenceMessageUtils$1 = class ReferenceMessageUtils {
|
|
25773
|
+
/**
|
|
25774
|
+
* Extracts all data from a reference message including session data, metadata, and message sections
|
|
25775
|
+
* @param {string} referenceMessage - The reference message content to parse
|
|
25776
|
+
* @returns {Object} Parsed data with messages to compact and keep, metadata, and session information
|
|
25777
|
+
*/
|
|
25778
|
+
static extractReferenceMessageData(referenceMessage) {
|
|
25779
|
+
if (!referenceMessage) {
|
|
25780
|
+
return {
|
|
25781
|
+
messagesToCompact: [],
|
|
25782
|
+
messagesToKeep: [],
|
|
25783
|
+
originalChatUuid: null,
|
|
25784
|
+
validationHash: null,
|
|
25785
|
+
sessionId: null,
|
|
25786
|
+
range: null,
|
|
25787
|
+
from: null,
|
|
25788
|
+
to: null
|
|
25789
|
+
};
|
|
25790
|
+
}
|
|
25791
|
+
|
|
25792
|
+
// Extract Original Chat UUID
|
|
25793
|
+
const originalChatUuidMatch = referenceMessage.match(/Original Chat UUID:\s*([a-f0-9-]+)/i);
|
|
25794
|
+
const originalChatUuid = originalChatUuidMatch ? originalChatUuidMatch[1] : null;
|
|
25795
|
+
|
|
25796
|
+
// Extract Validation Hash
|
|
25797
|
+
const validationHashMatch = referenceMessage.match(/Validation Hash:\s*([a-f0-9]+)/i);
|
|
25798
|
+
const validationHash = validationHashMatch ? validationHashMatch[1] : null;
|
|
25799
|
+
|
|
25800
|
+
// Extract Session ID
|
|
25801
|
+
const sessionIdMatch = referenceMessage.match(/Session ID:\s*(\d+)/i);
|
|
25802
|
+
const sessionId = sessionIdMatch ? sessionIdMatch[1] : null;
|
|
25803
|
+
|
|
25804
|
+
// Extract Range
|
|
25805
|
+
const rangeMatch = referenceMessage.match(/Range:\s*(\d+-\d+)/i);
|
|
25806
|
+
const range = rangeMatch ? rangeMatch[1] : null;
|
|
25807
|
+
|
|
25808
|
+
// Extract From and To values
|
|
25809
|
+
const fromMatch = referenceMessage.match(/From:\s*(\d+)/i);
|
|
25810
|
+
const from = fromMatch ? parseInt(fromMatch[1], 10) : null;
|
|
25811
|
+
|
|
25812
|
+
const toMatch = referenceMessage.match(/To:\s*(\d+)/i);
|
|
25813
|
+
const to = toMatch ? parseInt(toMatch[1], 10) : null;
|
|
25814
|
+
|
|
25815
|
+
// If range is not found but from and to are available, construct the range
|
|
25816
|
+
if (!range && from !== null && to !== null) {
|
|
25817
|
+
range = `${from}-${to}`;
|
|
25818
|
+
}
|
|
25819
|
+
|
|
25820
|
+
// Extract Messages to Compact section
|
|
25821
|
+
const compactSectionMatch = referenceMessage.match(/# Messages to Compact\n([\s\S]*?)(?=\n# |\n$|$)/);
|
|
25822
|
+
const compactSection = compactSectionMatch ? compactSectionMatch[1] : '';
|
|
25823
|
+
|
|
25824
|
+
// Extract Messages to Keep section
|
|
25825
|
+
const keepSectionMatch = referenceMessage.match(/# Messages to Keep \(Context\)\n([\s\S]*?)(?=\n# |\n$|$)/);
|
|
25826
|
+
const keepSection = keepSectionMatch ? keepSectionMatch[1] : '';
|
|
25827
|
+
|
|
25828
|
+
// Parse messages from each section
|
|
25829
|
+
const messagesToCompact = this.parseMessageSection(compactSection);
|
|
25830
|
+
const messagesToKeep = this.parseMessageSection(keepSection);
|
|
25831
|
+
|
|
25832
|
+
return {
|
|
25833
|
+
messagesToCompact,
|
|
25834
|
+
messagesToKeep,
|
|
25835
|
+
originalChatUuid,
|
|
25836
|
+
validationHash,
|
|
25837
|
+
sessionId,
|
|
25838
|
+
range,
|
|
25839
|
+
from,
|
|
25840
|
+
to
|
|
25841
|
+
};
|
|
25842
|
+
}
|
|
25843
|
+
|
|
25844
|
+
/**
|
|
25845
|
+
* Parses a message section to extract individual messages
|
|
25846
|
+
* @param {string} section - The section content to parse
|
|
25847
|
+
* @returns {Array} Array of parsed message objects
|
|
25848
|
+
*/
|
|
25849
|
+
static parseMessageSection(section) {
|
|
25850
|
+
if (!section) return [];
|
|
25851
|
+
|
|
25852
|
+
const messages = [];
|
|
25853
|
+
const messageRegex = /<(\w+) message number (\d+)>\n([\s\S]*?)\n<\/\1 message number \2>/g;
|
|
25854
|
+
let match;
|
|
25855
|
+
|
|
25856
|
+
while ((match = messageRegex.exec(section)) !== null) {
|
|
25857
|
+
const [, role, positionStr, content] = match;
|
|
25858
|
+
const position = parseInt(positionStr, 10);
|
|
25859
|
+
|
|
25860
|
+
messages.push({
|
|
25861
|
+
role,
|
|
25862
|
+
position,
|
|
25863
|
+
content: content.trim()
|
|
25864
|
+
});
|
|
25865
|
+
}
|
|
25866
|
+
|
|
25867
|
+
return messages;
|
|
25868
|
+
}
|
|
25869
|
+
|
|
25870
|
+
/**
|
|
25871
|
+
* Extracts just the metadata from a reference message without the message sections
|
|
25872
|
+
* @param {string} referenceMessage - The reference message content to parse
|
|
25873
|
+
* @returns {Object} Metadata object with original chat UUID, validation hash, session ID, and range information
|
|
25874
|
+
*/
|
|
25875
|
+
static extractReferenceMessageMetadata(referenceMessage) {
|
|
25876
|
+
const data = this.extractReferenceMessageData(referenceMessage);
|
|
25877
|
+
|
|
25878
|
+
return {
|
|
25879
|
+
originalChatUuid: data.originalChatUuid,
|
|
25880
|
+
validationHash: data.validationHash,
|
|
25881
|
+
sessionId: data.sessionId,
|
|
25882
|
+
range: data.range,
|
|
25883
|
+
from: data.from,
|
|
25884
|
+
to: data.to
|
|
25885
|
+
};
|
|
25886
|
+
}
|
|
25887
|
+
|
|
25888
|
+
/**
|
|
25889
|
+
* Checks if a message is a reference message
|
|
25890
|
+
* @param {string} message - The message content to check
|
|
25891
|
+
* @returns {boolean} True if the message is a reference message
|
|
25892
|
+
*/
|
|
25893
|
+
static isReferenceMessage(message) {
|
|
25894
|
+
if (!message) return false;
|
|
25895
|
+
|
|
25896
|
+
// Check for key indicators of a reference message
|
|
25897
|
+
return message.includes('# Compact Messages Reference') &&
|
|
25898
|
+
message.includes('Original Chat UUID:') &&
|
|
25899
|
+
message.includes('Session ID:');
|
|
25900
|
+
}
|
|
25901
|
+
};
|
|
25902
|
+
|
|
25903
|
+
var ReferenceMessageUtils_1 = { ReferenceMessageUtils: ReferenceMessageUtils$1 };
|
|
25904
|
+
|
|
25905
|
+
/**
|
|
25906
|
+
* Component: CompactedMessageUtils
|
|
25907
|
+
* Block-UUID: b4111118-ec11-49d6-9a6e-402ca0b6df5b
|
|
25908
|
+
* Parent-UUID: N/A
|
|
25909
|
+
* Version: 1.0.1
|
|
25910
|
+
* Description: Utility for formatting, parsing, and validating compacted messages with standardized metadata headers.
|
|
25911
|
+
* Language: JavaScript
|
|
25912
|
+
* Created-at: 2025-12-07T00:09:15.842Z
|
|
25913
|
+
* Authors: GLM-4.6 (v1.0.0), GLM-4.6 (v1.0.1)
|
|
25914
|
+
*/
|
|
25915
|
+
|
|
25916
|
+
let CompactedMessageUtils$1 = class CompactedMessageUtils {
|
|
25917
|
+
/**
|
|
25918
|
+
* Formats a compacted message with standardized metadata headers
|
|
25919
|
+
* @param {string} content - The compacted message content
|
|
25920
|
+
* @param {string} originalChatUuid - UUID of the original chat
|
|
25921
|
+
* @param {string} messageRange - Message range that was compacted (e.g., "3-6")
|
|
25922
|
+
* @param {Object} options - Additional options
|
|
25923
|
+
* @param {Date} options.compactedAt - Custom timestamp for when the message was compacted
|
|
25924
|
+
* @returns {string} Formatted compacted message with metadata
|
|
25925
|
+
*/
|
|
25926
|
+
static formatCompactedMessage(content, originalChatUuid, messageRange, options = {}) {
|
|
25927
|
+
if (!content) {
|
|
25928
|
+
throw new Error('Content is required for formatting a compacted message');
|
|
25929
|
+
}
|
|
25930
|
+
|
|
25931
|
+
if (!originalChatUuid) {
|
|
25932
|
+
throw new Error('Original chat UUID is required for formatting a compacted message');
|
|
25933
|
+
}
|
|
25934
|
+
|
|
25935
|
+
if (!messageRange) {
|
|
25936
|
+
throw new Error('Message range is required for formatting a compacted message');
|
|
25937
|
+
}
|
|
25938
|
+
|
|
25939
|
+
// Use provided timestamp or generate current one
|
|
25940
|
+
const compactedAt = options.compactedAt || new Date().toISOString();
|
|
25941
|
+
|
|
25942
|
+
return `## Compacted Message
|
|
25943
|
+
|
|
25944
|
+
- **Original Chat:** [${originalChatUuid}](/?chat=${originalChatUuid})
|
|
25945
|
+
- **Message Range:** ${messageRange}
|
|
25946
|
+
- **Compacted At:** ${compactedAt}
|
|
25947
|
+
|
|
25948
|
+
${content}`;
|
|
25949
|
+
}
|
|
25950
|
+
|
|
25951
|
+
/**
|
|
25952
|
+
* Extracts metadata from a compacted message
|
|
25953
|
+
* @param {string} compactedMessage - The compacted message to parse
|
|
25954
|
+
* @returns {Object|null} Metadata object or null if format is invalid
|
|
25955
|
+
*/
|
|
25956
|
+
static extractCompactedMessageMetadata(compactedMessage) {
|
|
25957
|
+
if (!this.isCompactedMessage(compactedMessage)) {
|
|
25958
|
+
return null;
|
|
25959
|
+
}
|
|
25960
|
+
|
|
25961
|
+
// Extract Original Chat UUID
|
|
25962
|
+
const originalChatMatch = compactedMessage.match(/\*\*Original Chat:\*\*\s*([a-f0-9-]+)/i);
|
|
25963
|
+
const originalChatUuid = originalChatMatch ? originalChatMatch[1] : null;
|
|
25964
|
+
|
|
25965
|
+
// Extract Message Range
|
|
25966
|
+
const rangeMatch = compactedMessage.match(/\*\*Message Range:\*\*\s*(\d+-\d+)/i);
|
|
25967
|
+
const messageRange = rangeMatch ? rangeMatch[1] : null;
|
|
25968
|
+
|
|
25969
|
+
// Extract Compacted At timestamp
|
|
25970
|
+
const compactedAtMatch = compactedMessage.match(/\*\*Compacted At:\*\*\s*([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z)/i);
|
|
25971
|
+
const compactedAt = compactedAtMatch ? compactedAtMatch[1] : null;
|
|
25972
|
+
|
|
25973
|
+
return {
|
|
25974
|
+
originalChatUuid,
|
|
25975
|
+
messageRange,
|
|
25976
|
+
compactedAt
|
|
25977
|
+
};
|
|
25978
|
+
}
|
|
25979
|
+
|
|
25980
|
+
/**
|
|
25981
|
+
* Extracts just the content portion from a compacted message (without metadata)
|
|
25982
|
+
* @param {string} compactedMessage - The compacted message to parse
|
|
25983
|
+
* @returns {string|null} Content portion or null if format is invalid
|
|
25984
|
+
*/
|
|
25985
|
+
static extractCompactedMessageContent(compactedMessage) {
|
|
25986
|
+
if (!this.isCompactedMessage(compactedMessage)) {
|
|
25987
|
+
return null;
|
|
25988
|
+
}
|
|
25989
|
+
|
|
25990
|
+
// Find the start and end boundaries
|
|
25991
|
+
const startMarker = "## Compacted Message";
|
|
25992
|
+
const endMarker = "## End Compacted Message";
|
|
25993
|
+
|
|
25994
|
+
const startIndex = compactedMessage.indexOf(startMarker);
|
|
25995
|
+
const endIndex = compactedMessage.indexOf(endMarker);
|
|
25996
|
+
|
|
25997
|
+
// If start marker is not found, return null
|
|
25998
|
+
if (startIndex === -1) {
|
|
25999
|
+
return null;
|
|
26000
|
+
}
|
|
26001
|
+
|
|
26002
|
+
// If end marker is not found, extract everything after start marker
|
|
26003
|
+
if (endIndex === -1) {
|
|
26004
|
+
return compactedMessage.substring(startIndex + startMarker.length).trim();
|
|
26005
|
+
}
|
|
26006
|
+
|
|
26007
|
+
// Extract content between the markers
|
|
26008
|
+
const contentStart = startIndex + startMarker.length;
|
|
26009
|
+
return compactedMessage.substring(contentStart, endIndex).trim();
|
|
26010
|
+
}
|
|
26011
|
+
|
|
26012
|
+
/**
|
|
26013
|
+
* Validates that a compacted message follows the expected format
|
|
26014
|
+
* @param {string} compactedMessage - The compacted message to validate
|
|
26015
|
+
* @returns {Object} Validation result with isValid flag and any errors/warnings
|
|
26016
|
+
*/
|
|
26017
|
+
static validateCompactedMessageFormat(compactedMessage) {
|
|
26018
|
+
const result = {
|
|
26019
|
+
isValid: true,
|
|
26020
|
+
errors: [],
|
|
26021
|
+
warnings: []
|
|
26022
|
+
};
|
|
26023
|
+
|
|
26024
|
+
if (!compactedMessage) {
|
|
26025
|
+
result.isValid = false;
|
|
26026
|
+
result.errors.push('Compacted message is empty or null');
|
|
26027
|
+
return result;
|
|
26028
|
+
}
|
|
26029
|
+
|
|
26030
|
+
// Check for required header
|
|
26031
|
+
if (!compactedMessage.includes('## Compacted Message')) {
|
|
26032
|
+
result.isValid = false;
|
|
26033
|
+
result.errors.push('Missing required "## Compacted Message" header');
|
|
26034
|
+
}
|
|
26035
|
+
|
|
26036
|
+
// Check for required metadata fields
|
|
26037
|
+
const metadata = this.extractCompactedMessageMetadata(compactedMessage);
|
|
26038
|
+
|
|
26039
|
+
if (!metadata) {
|
|
26040
|
+
result.isValid = false;
|
|
26041
|
+
result.errors.push('Could not extract metadata from compacted message');
|
|
26042
|
+
return result;
|
|
26043
|
+
}
|
|
26044
|
+
|
|
26045
|
+
if (!metadata.originalChatUuid) {
|
|
26046
|
+
result.isValid = false;
|
|
26047
|
+
result.errors.push('Missing or invalid Original Chat UUID');
|
|
26048
|
+
}
|
|
26049
|
+
|
|
26050
|
+
if (!metadata.messageRange) {
|
|
26051
|
+
result.isValid = false;
|
|
26052
|
+
result.errors.push('Missing or invalid Message Range');
|
|
26053
|
+
}
|
|
26054
|
+
|
|
26055
|
+
if (!metadata.compactedAt) {
|
|
26056
|
+
result.warnings.push('Missing or invalid Compacted At timestamp');
|
|
26057
|
+
}
|
|
26058
|
+
|
|
26059
|
+
// Validate UUID format
|
|
26060
|
+
if (metadata.originalChatUuid && !this.isValidUUID(metadata.originalChatUuid)) {
|
|
26061
|
+
result.isValid = false;
|
|
26062
|
+
result.errors.push('Original Chat UUID is not in valid UUID format');
|
|
26063
|
+
}
|
|
26064
|
+
|
|
26065
|
+
// Validate message range format
|
|
26066
|
+
if (metadata.messageRange && !this.isValidMessageRange(metadata.messageRange)) {
|
|
26067
|
+
result.isValid = false;
|
|
26068
|
+
result.errors.push('Message Range is not in valid format (expected "X-Y")');
|
|
26069
|
+
}
|
|
26070
|
+
|
|
26071
|
+
// Validate timestamp format
|
|
26072
|
+
if (metadata.compactedAt && !this.isValidISOTimestamp(metadata.compactedAt)) {
|
|
26073
|
+
result.warnings.push('Compacted At timestamp is not in valid ISO 8601 format');
|
|
26074
|
+
}
|
|
26075
|
+
|
|
26076
|
+
return result;
|
|
26077
|
+
}
|
|
26078
|
+
|
|
26079
|
+
/**
|
|
26080
|
+
* Checks if a message is a compacted message
|
|
26081
|
+
* @param {string} message - The message content to check
|
|
26082
|
+
* @returns {boolean} True if the message is a compacted message
|
|
26083
|
+
*/
|
|
26084
|
+
static isCompactedMessage(message) {
|
|
26085
|
+
if (!message) return false;
|
|
26086
|
+
|
|
26087
|
+
// Check for the compacted message header
|
|
26088
|
+
return message.includes('## Compacted Message');
|
|
26089
|
+
}
|
|
26090
|
+
|
|
26091
|
+
/**
|
|
26092
|
+
* Validates if a string is a valid UUID v4
|
|
26093
|
+
* @param {string} uuid - The UUID string to validate
|
|
26094
|
+
* @returns {boolean} True if valid UUID v4
|
|
26095
|
+
*/
|
|
26096
|
+
static isValidUUID(uuid) {
|
|
26097
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
26098
|
+
return uuidRegex.test(uuid);
|
|
26099
|
+
}
|
|
26100
|
+
|
|
26101
|
+
/**
|
|
26102
|
+
* Validates if a string is a valid message range (e.g., "3-6")
|
|
26103
|
+
* @param {string} range - The range string to validate
|
|
26104
|
+
* @returns {boolean} True if valid range format
|
|
26105
|
+
*/
|
|
26106
|
+
static isValidMessageRange(range) {
|
|
26107
|
+
const rangeRegex = /^\d+-\d+$/;
|
|
26108
|
+
if (!rangeRegex.test(range)) return false;
|
|
26109
|
+
|
|
26110
|
+
const [from, to] = range.split('-').map(Number);
|
|
26111
|
+
return !isNaN(from) && !isNaN(to) && from <= to;
|
|
26112
|
+
}
|
|
26113
|
+
|
|
26114
|
+
/**
|
|
26115
|
+
* Validates if a string is a valid ISO 8601 timestamp
|
|
26116
|
+
* @param {string} timestamp - The timestamp string to validate
|
|
26117
|
+
* @returns {boolean} True if valid ISO 8601 timestamp
|
|
26118
|
+
*/
|
|
26119
|
+
static isValidISOTimestamp(timestamp) {
|
|
26120
|
+
if (!timestamp) return false;
|
|
26121
|
+
|
|
26122
|
+
const date = new Date(timestamp);
|
|
26123
|
+
return !isNaN(date.getTime()) && timestamp === date.toISOString();
|
|
26124
|
+
}
|
|
26125
|
+
};
|
|
26126
|
+
|
|
26127
|
+
var CompactedMessageUtils_1 = { CompactedMessageUtils: CompactedMessageUtils$1 };
|
|
26128
|
+
|
|
26129
|
+
/**
|
|
26130
|
+
* Component: CompactChatUtils Index
|
|
26131
|
+
* Block-UUID: cd0a6091-edb6-4e92-9439-63dd8f6a6796
|
|
26132
|
+
* Parent-UUID: 5ffa0338-b4fb-4968-908c-f23a26d4923b
|
|
26133
|
+
* Version: 2.0.0
|
|
26134
|
+
* Description: Entry point for CompactChatUtils that exports both ReferenceMessageUtils and CompactedMessageUtils methods directly for easier access.
|
|
26135
|
+
* Language: JavaScript
|
|
26136
|
+
* Created-at: 2025-12-07T00:10:05.123Z
|
|
26137
|
+
* Authors: GLM-4.6 (v1.0.0), GLM-4.6 (v2.0.0)
|
|
26138
|
+
*/
|
|
26139
|
+
|
|
26140
|
+
const { ReferenceMessageUtils } = ReferenceMessageUtils_1;
|
|
26141
|
+
const { CompactedMessageUtils } = CompactedMessageUtils_1;
|
|
26142
|
+
|
|
26143
|
+
/**
|
|
26144
|
+
* CompactChatUtils provides utilities for working with compacted messages in GitSense Chat.
|
|
26145
|
+
* It includes functionality for parsing reference messages and formatting/parsing compacted messages.
|
|
26146
|
+
*/
|
|
26147
|
+
var CompactChatUtils$1 = {
|
|
26148
|
+
// Export the classes for those who want to access them directly
|
|
26149
|
+
ReferenceMessageUtils,
|
|
26150
|
+
CompactedMessageUtils,
|
|
26151
|
+
|
|
26152
|
+
// Export all methods from ReferenceMessageUtils directly
|
|
26153
|
+
extractReferenceMessageData: ReferenceMessageUtils.extractReferenceMessageData,
|
|
26154
|
+
parseMessageSection: ReferenceMessageUtils.parseMessageSection,
|
|
26155
|
+
extractReferenceMessageMetadata: ReferenceMessageUtils.extractReferenceMessageMetadata,
|
|
26156
|
+
isReferenceMessage: ReferenceMessageUtils.isReferenceMessage,
|
|
26157
|
+
|
|
26158
|
+
// Export all methods from CompactedMessageUtils directly
|
|
26159
|
+
formatCompactedMessage: CompactedMessageUtils.formatCompactedMessage,
|
|
26160
|
+
extractCompactedMessageMetadata: CompactedMessageUtils.extractCompactedMessageMetadata,
|
|
26161
|
+
extractCompactedMessageContent: CompactedMessageUtils.extractCompactedMessageContent,
|
|
26162
|
+
validateCompactedMessageFormat: CompactedMessageUtils.validateCompactedMessageFormat,
|
|
26163
|
+
isCompactedMessage: CompactedMessageUtils.isCompactedMessage,
|
|
26164
|
+
isValidUUID: CompactedMessageUtils.isValidUUID,
|
|
26165
|
+
isValidMessageRange: CompactedMessageUtils.isValidMessageRange,
|
|
26166
|
+
isValidISOTimestamp: CompactedMessageUtils.isValidISOTimestamp
|
|
26167
|
+
};
|
|
26168
|
+
|
|
24258
26169
|
/*
|
|
24259
26170
|
* Component: GitSenseChatUtils
|
|
24260
|
-
* Block-UUID:
|
|
24261
|
-
* Parent-UUID:
|
|
24262
|
-
* Version: 2.
|
|
24263
|
-
* 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, EnvUtils, and
|
|
26171
|
+
* Block-UUID: c1b6c4d3-7959-4eb6-8022-6cd7aa59240d
|
|
26172
|
+
* Parent-UUID: 1793b3a8-4881-4306-bfdf-673eef503679
|
|
26173
|
+
* Version: 2.7.0
|
|
26174
|
+
* 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, EnvUtils, ObjectUtils, MetaRawResultUtils, and CompactChatUtils.
|
|
24264
26175
|
* Language: JavaScript
|
|
24265
26176
|
* Created-at: 2025-10-17T17:13:04.663Z
|
|
24266
|
-
* 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), Qwen 3 Coder 480B - Cerebras (v2.1.5), Qwen 3 Coder 480B - Cerebras (v2.2.0), Qwen 3 Coder 480B - Cerebras (v2.2.1), Claude Haiku 4.5 (v2.3.0), Qwen 3 Coder 480B - Cerebras (v2.4.0)
|
|
26177
|
+
* 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), Qwen 3 Coder 480B - Cerebras (v2.1.5), Qwen 3 Coder 480B - Cerebras (v2.2.0), Qwen 3 Coder 480B - Cerebras (v2.2.1), Claude Haiku 4.5 (v2.3.0), Qwen 3 Coder 480B - Cerebras (v2.4.0), Qwen 3 Coder 480B - Cerebras (v2.5.0), GLM-4.6 (v2.6.0), GLM-4.6 (v2.7.0)
|
|
24267
26178
|
*/
|
|
24268
26179
|
|
|
24269
|
-
const ChatUtils = ChatUtils$
|
|
24270
|
-
const CodeBlockUtils = CodeBlockUtils$
|
|
26180
|
+
const ChatUtils = ChatUtils$2;
|
|
26181
|
+
const CodeBlockUtils = CodeBlockUtils$7;
|
|
24271
26182
|
const ContextUtils = ContextUtils$2;
|
|
24272
26183
|
const MessageUtils = MessageUtils$3;
|
|
24273
26184
|
const AnalysisBlockUtils = AnalysisBlockUtils$3;
|
|
@@ -24284,7 +26195,10 @@ const EnvUtils = EnvUtils$1;
|
|
|
24284
26195
|
const DomUtils = DomUtils$1;
|
|
24285
26196
|
const ObjectUtils = ObjectUtils$1;
|
|
24286
26197
|
const SVGUtils = SVGUtils_1;
|
|
26198
|
+
const StringUtils = stringUtils;
|
|
24287
26199
|
const LanguageNameUtils = LanguageNameUtils$1;
|
|
26200
|
+
const MetaRawResultUtils = MetaRawResultUtils$1;
|
|
26201
|
+
const CompactChatUtils = CompactChatUtils$1;
|
|
24288
26202
|
|
|
24289
26203
|
const {
|
|
24290
26204
|
normalizeLanguageName,
|
|
@@ -24370,6 +26284,7 @@ const {
|
|
|
24370
26284
|
removeCodeBlockMarkers,
|
|
24371
26285
|
updateCodeBlockByIndex,
|
|
24372
26286
|
deleteCodeBlockByIndex,
|
|
26287
|
+
getLineage,
|
|
24373
26288
|
} = CodeBlockUtils;
|
|
24374
26289
|
|
|
24375
26290
|
const {
|
|
@@ -24415,6 +26330,7 @@ const {
|
|
|
24415
26330
|
parseContextSection,
|
|
24416
26331
|
extractContextSections,
|
|
24417
26332
|
extractContextItemsOverviewTableRows,
|
|
26333
|
+
getContextFiles,
|
|
24418
26334
|
formatContextContent,
|
|
24419
26335
|
} = ContextUtils;
|
|
24420
26336
|
|
|
@@ -24422,6 +26338,28 @@ const {
|
|
|
24422
26338
|
trimObjectStrings
|
|
24423
26339
|
} = ObjectUtils;
|
|
24424
26340
|
|
|
26341
|
+
const {
|
|
26342
|
+
splitWithLimit,
|
|
26343
|
+
capitalize,
|
|
26344
|
+
titleCase,
|
|
26345
|
+
camelCase,
|
|
26346
|
+
kebabCase,
|
|
26347
|
+
snakeCase,
|
|
26348
|
+
constantCase,
|
|
26349
|
+
pascalCase,
|
|
26350
|
+
trimWhitespace,
|
|
26351
|
+
truncate,
|
|
26352
|
+
} = StringUtils;
|
|
26353
|
+
|
|
26354
|
+
const {
|
|
26355
|
+
extractMetaRawResultMappings,
|
|
26356
|
+
isMetaRawResultMessage,
|
|
26357
|
+
parseMetaRawResultContent,
|
|
26358
|
+
parseTableRow,
|
|
26359
|
+
parseSize,
|
|
26360
|
+
parseTokens
|
|
26361
|
+
} = MetaRawResultUtils;
|
|
26362
|
+
|
|
24425
26363
|
|
|
24426
26364
|
/**
|
|
24427
26365
|
* GitSenseChatUtils class provides a unified interface to code block and patch utilities.
|
|
@@ -24662,7 +26600,12 @@ var GitSenseChatUtils_1 = {
|
|
|
24662
26600
|
EnvUtils,
|
|
24663
26601
|
DomUtils,
|
|
24664
26602
|
ObjectUtils,
|
|
26603
|
+
StringUtils,
|
|
24665
26604
|
SVGUtils,
|
|
26605
|
+
MetaRawResultUtils,
|
|
26606
|
+
CompactChatUtils,
|
|
26607
|
+
ReferenceMessageUtils: CompactChatUtils.ReferenceMessageUtils,
|
|
26608
|
+
CompactedMessageUtils: CompactChatUtils.CompactedMessageUtils,
|
|
24666
26609
|
|
|
24667
26610
|
// --- Individual Function Exports (sourced correctly) ---
|
|
24668
26611
|
|
|
@@ -24755,6 +26698,18 @@ var GitSenseChatUtils_1 = {
|
|
|
24755
26698
|
// Object Utils
|
|
24756
26699
|
trimObjectStrings,
|
|
24757
26700
|
|
|
26701
|
+
// String Utils
|
|
26702
|
+
splitWithLimit,
|
|
26703
|
+
capitalize,
|
|
26704
|
+
titleCase,
|
|
26705
|
+
camelCase,
|
|
26706
|
+
kebabCase,
|
|
26707
|
+
snakeCase,
|
|
26708
|
+
constantCase,
|
|
26709
|
+
pascalCase,
|
|
26710
|
+
trimWhitespace,
|
|
26711
|
+
truncate,
|
|
26712
|
+
|
|
24758
26713
|
// Markdown Utils
|
|
24759
26714
|
createMarkdownRenderer,
|
|
24760
26715
|
removeSignature,
|
|
@@ -24774,10 +26729,19 @@ var GitSenseChatUtils_1 = {
|
|
|
24774
26729
|
getApiKey,
|
|
24775
26730
|
|
|
24776
26731
|
// Context Utils
|
|
26732
|
+
getContextFiles,
|
|
24777
26733
|
parseContextSection,
|
|
24778
26734
|
extractContextSections,
|
|
24779
26735
|
extractContextItemsOverviewTableRows,
|
|
24780
26736
|
formatContextContent,
|
|
26737
|
+
|
|
26738
|
+
// MetaRawResult Utils
|
|
26739
|
+
extractMetaRawResultMappings,
|
|
26740
|
+
isMetaRawResultMessage,
|
|
26741
|
+
parseMetaRawResultContent,
|
|
26742
|
+
parseTableRow,
|
|
26743
|
+
parseSize,
|
|
26744
|
+
parseTokens,
|
|
24781
26745
|
};
|
|
24782
26746
|
|
|
24783
26747
|
var GitSenseChatUtils$1 = /*@__PURE__*/getDefaultExportFromCjs(GitSenseChatUtils_1);
|