@gitsense/gsc-utils 0.2.24 → 0.2.27

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.
Files changed (40) hide show
  1. package/README.md +380 -62
  2. package/dist/gsc-utils.cjs.js +14270 -523
  3. package/dist/gsc-utils.esm.js +14270 -523
  4. package/package.json +1 -1
  5. package/src/AnalyzerUtils/cloner.js +149 -0
  6. package/src/AnalyzerUtils/constants.js +1 -1
  7. package/src/AnalyzerUtils/defaultPromptLoader.js +10 -10
  8. package/src/AnalyzerUtils/discovery.js +48 -39
  9. package/src/AnalyzerUtils/index.js +13 -7
  10. package/src/AnalyzerUtils/instructionLoader.js +6 -6
  11. package/src/AnalyzerUtils/jsonParser.js +35 -0
  12. package/src/AnalyzerUtils/management.js +6 -6
  13. package/src/AnalyzerUtils/saver.js +5 -5
  14. package/src/AnalyzerUtils/schemaLoader.js +194 -26
  15. package/src/AnalyzerUtils/updater.js +187 -0
  16. package/src/CodeBlockUtils/blockProcessor.js +14 -32
  17. package/src/CodeBlockUtils/constants.js +8 -4
  18. package/src/CodeBlockUtils/headerUtils.js +19 -3
  19. package/src/CodeBlockUtils/index.js +7 -6
  20. package/src/CodeBlockUtils/lineageTracer.js +95 -0
  21. package/src/CompactChatUtils/CompactedMessageUtils.js +224 -0
  22. package/src/CompactChatUtils/README.md +321 -0
  23. package/src/CompactChatUtils/ReferenceMessageUtils.js +143 -0
  24. package/src/CompactChatUtils/index.js +40 -0
  25. package/src/ContextUtils.js +41 -5
  26. package/src/DomUtils.js +559 -0
  27. package/src/GSToolBlockUtils.js +66 -1
  28. package/src/GitSenseChatUtils.js +108 -16
  29. package/src/LanguageNameUtils.js +171 -0
  30. package/src/MarkdownUtils.js +127 -0
  31. package/src/MessageUtils.js +1 -1
  32. package/src/MetaRawResultUtils.js +244 -0
  33. package/src/ObjectUtils.js +54 -0
  34. package/src/PatchUtils/constants.js +9 -3
  35. package/src/PatchUtils/patchParser.js +60 -37
  36. package/src/PatchUtils/patchProcessor.js +8 -5
  37. package/src/PatchUtils/patchVerifier/detectAndFixOverlappingHunks.js +1 -1
  38. package/src/SVGUtils.js +1467 -0
  39. package/src/SharedUtils/stringUtils.js +303 -0
  40. package/src/CodeBlockUtils/blockProcessor.js.rej +0 -8
@@ -2,11 +2,11 @@
2
2
  * Component: CodeBlockUtils Header Utilities
3
3
  * Block-UUID: 2565f708-feec-4b59-88fd-984084410fd4
4
4
  * Parent-UUID: 01147ddf-320f-498a-a744-198d42a9d2ee
5
- * Version: 1.2.0
5
+ * Version: 1.2.1
6
6
  * Description: Provides utility functions for parsing metadata headers from code blocks, validating timestamps, and calculating header line counts.
7
7
  * Language: JavaScript
8
8
  * Created-at: 2025-07-21T00:23:28.169Z
9
- * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash Thinking (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0)
9
+ * Authors: Gemini 2.5 Pro (v1.0.0), Gemini 2.5 Flash Thinking (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0), Qwen 3 Coder 480B - Cerebras (v1.2.1)
10
10
  */
11
11
 
12
12
 
@@ -113,6 +113,22 @@ function parseHeader(header, language) {
113
113
  .map(line => line.replace(/^\s*'\s?/, ''))
114
114
  .join('\n');
115
115
  break;
116
+
117
+ // --- New Case for HTML/XML/Markdown Comments ---
118
+ case 'html':
119
+ // Remove opening <!-- and closing --> tags.
120
+ // The regex handles cases where the tags might be on the same line as content
121
+ // or on their own lines.
122
+ cleanHeader = header.replace(/^<!--\s*/, '')
123
+ .replace(/\s*-->$/, '')
124
+ .split('\n')
125
+ // Remove leading whitespace and potential dashes (common in HTML comments)
126
+ // This is a heuristic, as HTML comments don't typically have line prefixes.
127
+ // It's included to be robust against minor formatting variations.
128
+ .map(line => line.replace(/^\s*(-|\*)\s?/, ''))
129
+ .join('\n');
130
+ break;
131
+ // --- End of New Case ---
116
132
 
117
133
  case 'unknown':
118
134
  // Attempt basic detection if language wasn't found in COMMENT_STYLES
@@ -170,7 +186,7 @@ function parseHeader(header, language) {
170
186
  const requiredFields = [
171
187
  'Component',
172
188
  'Block-UUID',
173
- 'Version', // Keep Version as string here, handle parsing elsewhere if needed
189
+ 'Version',
174
190
  'Language',
175
191
  'Created-at',
176
192
  'Authors'
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Component: CodeBlockUtils Index
3
- * Block-UUID: 7e9d3f8a-1b2c-4d5e-8f9a-0123456789ab
4
- * Parent-UUID: a3b9c8d1-e0f2-4a1b-8c7d-5e6f0a9b1c2d
5
- * Version: 1.4.0
3
+ * Block-UUID: 98684aa5-d597-41b6-a7fd-cc16482aafdc
4
+ * Parent-UUID: 7e9d3f8a-1b2c-4d5e-8f9a-0123456789ab
5
+ * Version: 1.5.0
6
6
  * Description: Aggregates and exports all utilities related to code block processing from the CodeBlockUtils module. Serves as the main entry point for this module.
7
7
  * Language: JavaScript
8
8
  * Created-at: 2025-04-15T16:02:20.217Z
9
- * 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)
9
+ * 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)
10
10
  */
11
11
 
12
12
 
@@ -23,6 +23,7 @@ const { parseCodeBlocks: parseCommentDelimitedBlocks } = require('./headerParser
23
23
  const { removeCodeBlockMarkers } = require('./markerRemover');
24
24
  const { updateCodeBlockByIndex, updateCodeBlockByUUID, updateCodeBlock, updateCodeBlockInMessage, deleteCodeBlockByIndex } = require('./updateCodeBlock');
25
25
  const { formatWithLineNumbers, formatBlockWithLineNumbers, formatBlocksWithLineNumbers, removeLineNumbers } = require('./lineNumberFormatter');
26
+ const { getLineage } = require('./lineageTracer');
26
27
 
27
28
  // Export all imported items
28
29
  module.exports = {
@@ -77,7 +78,7 @@ module.exports = {
77
78
  // Line Number Formatting Utilities
78
79
  formatWithLineNumbers,
79
80
  formatBlockWithLineNumbers,
80
- formatBlocksWithLineNumbers,
81
+ formatBlocksWithLineNumbers,
82
+ getLineage,
81
83
  removeLineNumbers,
82
84
  };
83
-
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Component: CodeBlockUtils Lineage Tracer
3
+ * Block-UUID: 13b08cce-6fd1-4ec9-a915-240714ee89b9
4
+ * Parent-UUID: df1a629b-2cc0-4677-b410-3172ee0e0f9f
5
+ * Version: 1.1.0
6
+ * Description: Provides a utility function to trace the full lineage (patch-based and parent-based) of code blocks within a chat, including loop detection.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-10-23T01:28:10.456Z
9
+ * Authors: Qwen 3 Coder 480B - Cerebras (v1.0.0), Qwen 3 Coder 480B - Cerebras (v1.1.0)
10
+ */
11
+
12
+
13
+ /**
14
+ * Traces the full lineage of a code block or patch identified by a UUID.
15
+ * The lineage includes the block itself and all its ancestors, tracing backwards
16
+ * first through patch relationships (Source-Block-UUID -> Target-Block-UUID)
17
+ * and then through Parent-UUID relationships.
18
+ * Loop detection is included to prevent infinite tracing.
19
+ *
20
+ * @param {string} uuid - The UUID of the target code block or patch.
21
+ * @param {Map<string, object>} blockMap - A map where keys are UUIDs (for code blocks)
22
+ * or patch UUIDs (source:target) and values
23
+ * are the corresponding block objects.
24
+ * Block objects are expected to have
25
+ * properties like `isPatch`, `metadata`, and `header`.
26
+ * @returns {Array<object>} An array of block objects representing the lineage.
27
+ * The first element is the block for the provided `uuid`.
28
+ * Subsequent elements are its ancestors.
29
+ * Returns an empty array if the initial uuid is not found.
30
+ * If a loop is detected, the last element will have a property `loopDetected: true`.
31
+ */
32
+ function getLineage(uuid, blockMap) {
33
+ if (!uuid || !blockMap) {
34
+ return [];
35
+ }
36
+
37
+ const lineage = [];
38
+ const visitedUuids = new Set();
39
+ let currentUuid = uuid;
40
+
41
+ while (currentUuid) {
42
+ // --- Loop Detection ---
43
+ if (visitedUuids.has(currentUuid)) {
44
+ // Add a marker or the block itself to indicate the loop
45
+ const loopBlock = blockMap.get(currentUuid) || { uuid: currentUuid, loopDetected: true, type: 'loop-marker' };
46
+ loopBlock.loopDetected = true; // Ensure the property is set
47
+ lineage.push(loopBlock);
48
+ break; // Stop the trace
49
+ }
50
+ visitedUuids.add(currentUuid);
51
+
52
+ // --- 1. Try to find the block directly by its UUID ---
53
+ let block = blockMap.get(currentUuid);
54
+
55
+ // --- 2. If not found directly, search patch keys ---
56
+ if (!block) {
57
+ for (const [key, value] of blockMap) {
58
+ // Check if the map key is a patch key (contains ':') and ends with our target UUID
59
+ if (key.includes(':') && key.endsWith(`:${currentUuid}`)) {
60
+ block = value;
61
+ break;
62
+ }
63
+ }
64
+ }
65
+
66
+ // --- 3. If a block was found, add it to the lineage ---
67
+ if (block) {
68
+ lineage.push(block);
69
+
70
+ let nextUuid = null;
71
+
72
+ // --- 3a. If it's a patch, move to its source UUID ---
73
+ if (block.isPatch && block.metadata && block.metadata['Source-Block-UUID']) {
74
+ nextUuid = block.metadata['Source-Block-UUID'];
75
+ }
76
+ // --- 3b. If it's a code block, move to its Parent-UUID (if valid) ---
77
+ else if (!block.isPatch && block.header && block.header['Parent-UUID'] && block.header['Parent-UUID'] !== 'N/A') {
78
+ nextUuid = block.header['Parent-UUID'];
79
+ }
80
+ // If it's a code block with Parent-UUID: 0c104865-260a-4942-8cb6-93bebf40c450
81
+
82
+ currentUuid = nextUuid;
83
+ } else {
84
+ // If no block is found for currentUuid, the lineage is incomplete.
85
+ // We could add a placeholder here if needed, but for now, we just stop.
86
+ currentUuid = null;
87
+ }
88
+ }
89
+
90
+ return lineage;
91
+ }
92
+
93
+ module.exports = {
94
+ getLineage
95
+ };
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Component: CompactedMessageUtils
3
+ * Block-UUID: b4111118-ec11-49d6-9a6e-402ca0b6df5b
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.1
6
+ * Description: Utility for formatting, parsing, and validating compacted messages with standardized metadata headers.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-12-07T00:09:15.842Z
9
+ * Authors: GLM-4.6 (v1.0.0), GLM-4.6 (v1.0.1)
10
+ */
11
+
12
+
13
+ class CompactedMessageUtils {
14
+ /**
15
+ * Formats a compacted message with standardized metadata headers
16
+ * @param {string} content - The compacted message content
17
+ * @param {string} originalChatUuid - UUID of the original chat
18
+ * @param {string} messageRange - Message range that was compacted (e.g., "3-6")
19
+ * @param {Object} options - Additional options
20
+ * @param {Date} options.compactedAt - Custom timestamp for when the message was compacted
21
+ * @returns {string} Formatted compacted message with metadata
22
+ */
23
+ static formatCompactedMessage(content, originalChatUuid, messageRange, options = {}) {
24
+ if (!content) {
25
+ throw new Error('Content is required for formatting a compacted message');
26
+ }
27
+
28
+ if (!originalChatUuid) {
29
+ throw new Error('Original chat UUID is required for formatting a compacted message');
30
+ }
31
+
32
+ if (!messageRange) {
33
+ throw new Error('Message range is required for formatting a compacted message');
34
+ }
35
+
36
+ // Use provided timestamp or generate current one
37
+ const compactedAt = options.compactedAt || new Date().toISOString();
38
+
39
+ return `## Compacted Message
40
+
41
+ - **Original Chat:** [${originalChatUuid}](/?chat=${originalChatUuid})
42
+ - **Message Range:** ${messageRange}
43
+ - **Compacted At:** ${compactedAt}
44
+
45
+ ${content}`;
46
+ }
47
+
48
+ /**
49
+ * Extracts metadata from a compacted message
50
+ * @param {string} compactedMessage - The compacted message to parse
51
+ * @returns {Object|null} Metadata object or null if format is invalid
52
+ */
53
+ static extractCompactedMessageMetadata(compactedMessage) {
54
+ if (!this.isCompactedMessage(compactedMessage)) {
55
+ return null;
56
+ }
57
+
58
+ // Extract Original Chat UUID
59
+ const originalChatMatch = compactedMessage.match(/\*\*Original Chat:\*\*\s*([a-f0-9-]+)/i);
60
+ const originalChatUuid = originalChatMatch ? originalChatMatch[1] : null;
61
+
62
+ // Extract Message Range
63
+ const rangeMatch = compactedMessage.match(/\*\*Message Range:\*\*\s*(\d+-\d+)/i);
64
+ const messageRange = rangeMatch ? rangeMatch[1] : null;
65
+
66
+ // Extract Compacted At timestamp
67
+ 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);
68
+ const compactedAt = compactedAtMatch ? compactedAtMatch[1] : null;
69
+
70
+ return {
71
+ originalChatUuid,
72
+ messageRange,
73
+ compactedAt
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Extracts just the content portion from a compacted message (without metadata)
79
+ * @param {string} compactedMessage - The compacted message to parse
80
+ * @returns {string|null} Content portion or null if format is invalid
81
+ */
82
+ static extractCompactedMessageContent(compactedMessage) {
83
+ if (!this.isCompactedMessage(compactedMessage)) {
84
+ return null;
85
+ }
86
+
87
+ // Find the start and end boundaries
88
+ const startMarker = "## Compacted Message";
89
+ const endMarker = "## End Compacted Message";
90
+
91
+ const startIndex = compactedMessage.indexOf(startMarker);
92
+ const endIndex = compactedMessage.indexOf(endMarker);
93
+
94
+ // If start marker is not found, return null
95
+ if (startIndex === -1) {
96
+ return null;
97
+ }
98
+
99
+ // If end marker is not found, extract everything after start marker
100
+ if (endIndex === -1) {
101
+ return compactedMessage.substring(startIndex + startMarker.length).trim();
102
+ }
103
+
104
+ // Extract content between the markers
105
+ const contentStart = startIndex + startMarker.length;
106
+ return compactedMessage.substring(contentStart, endIndex).trim();
107
+ }
108
+
109
+ /**
110
+ * Validates that a compacted message follows the expected format
111
+ * @param {string} compactedMessage - The compacted message to validate
112
+ * @returns {Object} Validation result with isValid flag and any errors/warnings
113
+ */
114
+ static validateCompactedMessageFormat(compactedMessage) {
115
+ const result = {
116
+ isValid: true,
117
+ errors: [],
118
+ warnings: []
119
+ };
120
+
121
+ if (!compactedMessage) {
122
+ result.isValid = false;
123
+ result.errors.push('Compacted message is empty or null');
124
+ return result;
125
+ }
126
+
127
+ // Check for required header
128
+ if (!compactedMessage.includes('## Compacted Message')) {
129
+ result.isValid = false;
130
+ result.errors.push('Missing required "## Compacted Message" header');
131
+ }
132
+
133
+ // Check for required metadata fields
134
+ const metadata = this.extractCompactedMessageMetadata(compactedMessage);
135
+
136
+ if (!metadata) {
137
+ result.isValid = false;
138
+ result.errors.push('Could not extract metadata from compacted message');
139
+ return result;
140
+ }
141
+
142
+ if (!metadata.originalChatUuid) {
143
+ result.isValid = false;
144
+ result.errors.push('Missing or invalid Original Chat UUID');
145
+ }
146
+
147
+ if (!metadata.messageRange) {
148
+ result.isValid = false;
149
+ result.errors.push('Missing or invalid Message Range');
150
+ }
151
+
152
+ if (!metadata.compactedAt) {
153
+ result.warnings.push('Missing or invalid Compacted At timestamp');
154
+ }
155
+
156
+ // Validate UUID format
157
+ if (metadata.originalChatUuid && !this.isValidUUID(metadata.originalChatUuid)) {
158
+ result.isValid = false;
159
+ result.errors.push('Original Chat UUID is not in valid UUID format');
160
+ }
161
+
162
+ // Validate message range format
163
+ if (metadata.messageRange && !this.isValidMessageRange(metadata.messageRange)) {
164
+ result.isValid = false;
165
+ result.errors.push('Message Range is not in valid format (expected "X-Y")');
166
+ }
167
+
168
+ // Validate timestamp format
169
+ if (metadata.compactedAt && !this.isValidISOTimestamp(metadata.compactedAt)) {
170
+ result.warnings.push('Compacted At timestamp is not in valid ISO 8601 format');
171
+ }
172
+
173
+ return result;
174
+ }
175
+
176
+ /**
177
+ * Checks if a message is a compacted message
178
+ * @param {string} message - The message content to check
179
+ * @returns {boolean} True if the message is a compacted message
180
+ */
181
+ static isCompactedMessage(message) {
182
+ if (!message) return false;
183
+
184
+ // Check for the compacted message header
185
+ return message.includes('## Compacted Message');
186
+ }
187
+
188
+ /**
189
+ * Validates if a string is a valid UUID v4
190
+ * @param {string} uuid - The UUID string to validate
191
+ * @returns {boolean} True if valid UUID v4
192
+ */
193
+ static isValidUUID(uuid) {
194
+ 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;
195
+ return uuidRegex.test(uuid);
196
+ }
197
+
198
+ /**
199
+ * Validates if a string is a valid message range (e.g., "3-6")
200
+ * @param {string} range - The range string to validate
201
+ * @returns {boolean} True if valid range format
202
+ */
203
+ static isValidMessageRange(range) {
204
+ const rangeRegex = /^\d+-\d+$/;
205
+ if (!rangeRegex.test(range)) return false;
206
+
207
+ const [from, to] = range.split('-').map(Number);
208
+ return !isNaN(from) && !isNaN(to) && from <= to;
209
+ }
210
+
211
+ /**
212
+ * Validates if a string is a valid ISO 8601 timestamp
213
+ * @param {string} timestamp - The timestamp string to validate
214
+ * @returns {boolean} True if valid ISO 8601 timestamp
215
+ */
216
+ static isValidISOTimestamp(timestamp) {
217
+ if (!timestamp) return false;
218
+
219
+ const date = new Date(timestamp);
220
+ return !isNaN(date.getTime()) && timestamp === date.toISOString();
221
+ }
222
+ }
223
+
224
+ module.exports = { CompactedMessageUtils };