@gitsense/gsc-utils 0.1.0

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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/dist/gitsense-chat-utils.cjs.js +10977 -0
  3. package/dist/gitsense-chat-utils.esm.js +10975 -0
  4. package/dist/gsc-utils.cjs.js +11043 -0
  5. package/dist/gsc-utils.esm.js +11041 -0
  6. package/package.json +37 -0
  7. package/src/AnalysisBlockUtils.js +151 -0
  8. package/src/ChatUtils.js +126 -0
  9. package/src/CodeBlockUtils/blockExtractor.js +277 -0
  10. package/src/CodeBlockUtils/blockProcessor.js +559 -0
  11. package/src/CodeBlockUtils/blockProcessor.js.rej +8 -0
  12. package/src/CodeBlockUtils/constants.js +62 -0
  13. package/src/CodeBlockUtils/continuationUtils.js +191 -0
  14. package/src/CodeBlockUtils/headerParser.js +175 -0
  15. package/src/CodeBlockUtils/headerUtils.js +236 -0
  16. package/src/CodeBlockUtils/index.js +83 -0
  17. package/src/CodeBlockUtils/lineNumberFormatter.js +117 -0
  18. package/src/CodeBlockUtils/markerRemover.js +89 -0
  19. package/src/CodeBlockUtils/patchIntegration.js +38 -0
  20. package/src/CodeBlockUtils/relationshipUtils.js +159 -0
  21. package/src/CodeBlockUtils/updateCodeBlock.js +372 -0
  22. package/src/CodeBlockUtils/uuidUtils.js +48 -0
  23. package/src/ContextUtils.js +180 -0
  24. package/src/GSToolBlockUtils.js +108 -0
  25. package/src/GitSenseChatUtils.js +386 -0
  26. package/src/JsonUtils.js +101 -0
  27. package/src/LLMUtils.js +31 -0
  28. package/src/MessageUtils.js +460 -0
  29. package/src/PatchUtils/constants.js +72 -0
  30. package/src/PatchUtils/diagnosticReporter.js +213 -0
  31. package/src/PatchUtils/enhancedPatchProcessor.js +390 -0
  32. package/src/PatchUtils/fuzzyMatcher.js +252 -0
  33. package/src/PatchUtils/hunkCorrector.js +204 -0
  34. package/src/PatchUtils/hunkValidator.js +305 -0
  35. package/src/PatchUtils/index.js +135 -0
  36. package/src/PatchUtils/patchExtractor.js +175 -0
  37. package/src/PatchUtils/patchHeaderFormatter.js +143 -0
  38. package/src/PatchUtils/patchParser.js +289 -0
  39. package/src/PatchUtils/patchProcessor.js +389 -0
  40. package/src/PatchUtils/patchVerifier/constants.js +23 -0
  41. package/src/PatchUtils/patchVerifier/detectAndFixOverlappingHunks.js +281 -0
  42. package/src/PatchUtils/patchVerifier/detectAndFixRedundantChanges.js +404 -0
  43. package/src/PatchUtils/patchVerifier/formatAndAddLineNumbers.js +165 -0
  44. package/src/PatchUtils/patchVerifier/index.js +25 -0
  45. package/src/PatchUtils/patchVerifier/verifyAndCorrectHunkHeaders.js +202 -0
  46. package/src/PatchUtils/patchVerifier/verifyAndCorrectLineNumbers.js +254 -0
  47. package/src/SharedUtils/timestampUtils.js +41 -0
  48. package/src/SharedUtils/versionUtils.js +58 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Component: CodeBlockUtils Line Number Formatter
3
+ * Block-UUID: 94373ca5-bd2f-487d-81d6-6b654867e972
4
+ * Parent-UUID: e7ff9961-a0cd-4f4b-b80a-65338a2207b0
5
+ * Version: 1.0.0
6
+ * Description: Provides a function to format code content with padded line numbers to aid in patch generation.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-04-18T01:13:55.824Z
9
+ * Authors: Claude 3.7 Sonnet (v1.0.0)
10
+ */
11
+
12
+
13
+ /**
14
+ * Formats code content by adding padded line numbers to each line.
15
+ * The line numbers are formatted with right-aligned padding and a colon separator.
16
+ *
17
+ * @param {string} codeContent - The raw code content to format with line numbers
18
+ * @param {number} [startLine=1] - The line number to start counting from (default: 1)
19
+ * @param {number} [paddingWidth=0] - Fixed padding width. If 0, automatically calculated based on total lines
20
+ * @returns {string} The formatted code with line numbers
21
+ */
22
+ function formatWithLineNumbers(codeContent, startLine = 1, paddingWidth = 0) {
23
+ if (typeof codeContent !== 'string') {
24
+ throw new Error("codeContent must be a string");
25
+ }
26
+
27
+ // Handle empty content
28
+ if (codeContent.trim() === '') {
29
+ return '';
30
+ }
31
+
32
+ // Split the content into lines
33
+ const lines = codeContent.split('\n');
34
+
35
+ // Calculate the width needed for the line numbers if not specified
36
+ const totalLines = lines.length;
37
+ const calculatedWidth = paddingWidth || Math.max(String(startLine + totalLines - 1).length, 3);
38
+
39
+ // Format each line with a padded line number
40
+ return lines.map((line, index) => {
41
+ const lineNumber = startLine + index;
42
+ const paddedNumber = String(lineNumber).padStart(calculatedWidth, ' ');
43
+ return `${paddedNumber}: ${line}`;
44
+ }).join('\n');
45
+ }
46
+
47
+ /**
48
+ * Formats a code block object by adding line numbers to its code content.
49
+ * Only applies to blocks of type 'code', not 'patch'.
50
+ *
51
+ * @param {Object} block - The processed code block object from processBlockContent
52
+ * @param {number} [startLine=1] - The line number to start counting from
53
+ * @param {number} [paddingWidth=0] - Fixed padding width. If 0, automatically calculated
54
+ * @returns {Object} A new block object with formatted content
55
+ */
56
+ function formatBlockWithLineNumbers(block, startLine = 1, paddingWidth = 0) {
57
+ // Create a shallow copy of the block to avoid modifying the original
58
+ const formattedBlock = { ...block };
59
+
60
+ // Only format code blocks, not patch blocks
61
+ if (block.type === 'code' && typeof block.content === 'string') {
62
+ formattedBlock.content = formatWithLineNumbers(block.content, startLine, paddingWidth);
63
+ formattedBlock.hasLineNumbers = true;
64
+ }
65
+
66
+ return formattedBlock;
67
+ }
68
+
69
+ /**
70
+ * Formats all code blocks in a processed blocks array with line numbers.
71
+ *
72
+ * @param {Array} blocks - Array of processed block objects
73
+ * @param {number} [startLine=1] - The line number to start counting from for each block
74
+ * @param {number} [paddingWidth=0] - Fixed padding width. If 0, automatically calculated per block
75
+ * @returns {Array} A new array of blocks with formatted content
76
+ */
77
+ function formatBlocksWithLineNumbers(blocks, startLine = 1, paddingWidth = 0) {
78
+ if (!Array.isArray(blocks)) {
79
+ throw new Error("blocks must be an array");
80
+ }
81
+
82
+ return blocks.map(block => formatBlockWithLineNumbers(block, startLine, paddingWidth));
83
+ }
84
+
85
+ /**
86
+ * Removes line numbers from formatted code content.
87
+ *
88
+ * @param {string} formattedContent - The code content with line numbers
89
+ * @returns {string} The original code content without line numbers
90
+ */
91
+ function removeLineNumbers(formattedContent) {
92
+ if (typeof formattedContent !== 'string') {
93
+ throw new Error("formattedContent must be a string");
94
+ }
95
+
96
+ // Handle empty content
97
+ if (formattedContent.trim() === '') {
98
+ return '';
99
+ }
100
+
101
+ // Regular expression to match the line number pattern
102
+ const lineNumberPattern = /^\s*\d+:\s/;
103
+
104
+ // Split the content into lines and remove the line number prefix from each
105
+ return formattedContent.split('\n')
106
+ .map(line => line.replace(lineNumberPattern, ''))
107
+ .join('\n');
108
+ }
109
+
110
+ // Export the functions
111
+ module.exports = {
112
+ formatWithLineNumbers,
113
+ formatBlockWithLineNumbers,
114
+ formatBlocksWithLineNumbers,
115
+ removeLineNumbers
116
+ };
117
+
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Component: CodeBlockUtils Marker Remover
3
+ * Block-UUID: 40490e16-a9a3-4e93-b36b-5e9469cd2faf
4
+ * Parent-UUID: 6322afcd-2e5e-425a-9a43-4c72c887f668
5
+ * Version: 1.0.0
6
+ * Description: Removes custom '--- CODE BLOCK START ---' and '--- CODE BLOCK COMPLETE ---' markers surrounding markdown code blocks, only when both markers are present for a block.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-04-15T16:01:34.371Z
9
+ * Authors: Gemini 2.5 Pro (v1.0.0)
10
+ */
11
+
12
+
13
+ /**
14
+ * Removes code block start and complete markers from markdown text,
15
+ * but only when both markers are present for a given code block.
16
+ *
17
+ * @param {string} markdownText - The markdown text containing code blocks with markers
18
+ * @returns {string} - The markdown text with complete code block markers removed
19
+ */
20
+ function removeCodeBlockMarkers(markdownText) {
21
+ // Pattern to match a code block with both start and complete markers
22
+ // Ensures robust matching with potential variations in whitespace/newlines
23
+ const pattern = /---\s*CODE BLOCK START\s*---\s*```([\s\S]*?)```\s*---\s*CODE BLOCK COMPLETE\s*---/gs;
24
+
25
+ // Replace all instances where both markers are present
26
+ const result = markdownText.replace(pattern, (match, codeBlockContent) => {
27
+ // Return the standard markdown block without the custom markers
28
+ // Ensure consistent newline handling around the captured content
29
+ return '```' + codeBlockContent.trim() + '\n```';
30
+ });
31
+
32
+ return result;
33
+ }
34
+
35
+ // Example usage (kept commented out)
36
+ /*
37
+ function testRemoveCodeBlockMarkers() {
38
+ const exampleText = `
39
+ # Example Markdown
40
+
41
+ Here's a code block:
42
+
43
+ --- CODE BLOCK START ---
44
+
45
+ \`\`\`javascript
46
+ function hello() {
47
+ console.log("Hello, World!");
48
+ }
49
+ \`\`\`
50
+
51
+ --- CODE BLOCK COMPLETE ---
52
+
53
+ And here's another one:
54
+
55
+ --- CODE BLOCK START ---
56
+ \`\`\`python
57
+ def hello():
58
+ print("Hello, World!")
59
+ \`\`\`
60
+ --- CODE BLOCK COMPLETE ---
61
+
62
+ Here's an incomplete one that won't be modified:
63
+
64
+ --- CODE BLOCK START ---
65
+
66
+ \`\`\`bash
67
+ echo "Hello, World!"
68
+ \`\`\`
69
+
70
+ And some more text.
71
+
72
+ A block without markers:
73
+ \`\`\`text
74
+ Plain text block.
75
+ \`\`\`
76
+ `;
77
+
78
+ const cleanedText = removeCodeBlockMarkers(exampleText);
79
+ console.log("Original Text:\n", exampleText);
80
+ console.log("\nCleaned Text:\n", cleanedText);
81
+ }
82
+
83
+ // Uncomment to run the example
84
+ // testRemoveCodeBlockMarkers();
85
+ */
86
+
87
+ // Export the function for Node.js environments
88
+ // (Removed the check `if (typeof module !== 'undefined' && module.exports)` as it's standard in Node)
89
+ module.exports = { removeCodeBlockMarkers };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Component: CodeBlockUtils Patch Integration
3
+ * Block-UUID: 9f7395ef-e213-4841-a95d-f263e422288a
4
+ * Parent-UUID: 6322afcd-2e5e-425a-9a43-4c72c887f668
5
+ * Version: 1.0.0
6
+ * Description: Provides functions to detect the presence of patch blocks within text content using the core block processing logic.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-04-15T15:58:19.198Z
9
+ * Authors: Gemini 2.5 Pro (v1.0.0)
10
+ */
11
+
12
+
13
+ // Dependency on the core block processor
14
+ const { processCodeBlocks } = require('./blockProcessor');
15
+
16
+ /**
17
+ * Checks if the provided text content contains at least one patch block.
18
+ * @param {string} content - The text content to check.
19
+ * @param {Object} options - Options passed to processCodeBlocks (e.g., silent).
20
+ * @returns {boolean} - True if a patch block is found, false otherwise.
21
+ */
22
+ function containsPatch(content, options = { silent: true }) {
23
+ // Use the core processor to get all blocks
24
+ const { blocks } = processCodeBlocks(content, options);
25
+
26
+ // Check if any processed block is of type 'patch'
27
+ for (let i = 0; i < blocks.length; i++) {
28
+ if (blocks[i].type === 'patch') {
29
+ return true;
30
+ }
31
+ }
32
+
33
+ return false;
34
+ }
35
+
36
+ module.exports = {
37
+ containsPatch
38
+ };
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Component: CodeBlockUtils Relationship Utilities
3
+ * Block-UUID: cde52e7f-97c6-4680-8a81-75459f10dae9
4
+ * Parent-UUID: 6322afcd-2e5e-425a-9a43-4c72c887f668
5
+ * Version: 1.0.0
6
+ * Description: Provides functions to detect relationships between code blocks (parent-child, patches) and extract structural information like file paths or incomplete blocks from text.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-04-15T15:58:56.290Z
9
+ * Authors: Gemini 2.5 Pro (v1.0.0)
10
+ */
11
+
12
+
13
+ // Dependency on the core block processor
14
+ const { processCodeBlocks } = require('./blockProcessor');
15
+
16
+ /**
17
+ * Detects special code block relationships in a message, such as patches or parent-child links.
18
+ * Assumes a 'codeBlockService' object with a 'getBlockInfo(uuid)' method is available in the calling context
19
+ * to verify the existence of parent UUIDs. This dependency might need to be injected or handled differently
20
+ * depending on the application architecture.
21
+ *
22
+ * @param {string} content - The message content.
23
+ * @param {Object} codeBlockService - An object/service instance with a method `getBlockInfo(uuid)`
24
+ * that returns information about a block UUID (or null/undefined if not found).
25
+ * @param {Object} options - Options passed to processCodeBlocks (e.g., silent).
26
+ * @returns {Object} Object containing detection results:
27
+ * { blocks: Array, warnings: Array, containsPatch: boolean, hasParentChildRelationship: boolean, needsControls: boolean }
28
+ */
29
+ function detectCodeBlockRelationships(content, codeBlockService, options = { silent: true }) {
30
+ if (!content || typeof content !== 'string') {
31
+ return {
32
+ blocks: [],
33
+ warnings: [{ type: 'invalid_input', message: 'Input content must be a non-empty string.' }],
34
+ containsPatch: false,
35
+ hasParentChildRelationship: false,
36
+ needsControls: false
37
+ };
38
+ }
39
+ // Ensure codeBlockService and its method exist
40
+ if (!codeBlockService || typeof codeBlockService.getBlockInfo !== 'function') {
41
+ console.warn("Warning: detectCodeBlockRelationships requires a valid codeBlockService with a getBlockInfo method.");
42
+ // Proceed without parent check if service is missing, but relationship detection will be incomplete.
43
+ codeBlockService = { getBlockInfo: () => null }; // Dummy service
44
+ }
45
+
46
+
47
+ // Extract all code blocks using the core processor
48
+ const { blocks, warnings } = processCodeBlocks(content, options);
49
+
50
+ let hasPatch = false;
51
+ let hasParentChildRelationship = false;
52
+
53
+ if (blocks && blocks.length > 0) {
54
+ for (const block of blocks) {
55
+ // Check for patch type
56
+ if (block.type === 'patch') {
57
+ hasPatch = true;
58
+ // Continue checking other blocks for parent-child relationships
59
+ }
60
+ // Check for parent-child relationship in code blocks
61
+ else if (block.type === 'code') {
62
+ const blockUUID = block.header?.['Block-UUID'];
63
+ const parentUUID = block.header?.['Parent-UUID'];
64
+
65
+ // Check if Parent-UUID is valid and not 'N/A'
66
+ if (blockUUID && parentUUID && parentUUID !== 'N/A' && parentUUID !== 'INVALID UUID') {
67
+ // Check if parent exists using the provided service
68
+ try {
69
+ const parentInfo = codeBlockService.getBlockInfo(parentUUID);
70
+ if (parentInfo) {
71
+ hasParentChildRelationship = true;
72
+ // If we find one relationship, we know controls might be needed,
73
+ // but continue checking other blocks in case they also contain patches.
74
+ }
75
+ } catch (serviceError) {
76
+ console.error(`Error calling codeBlockService.getBlockInfo for UUID ${parentUUID}:`, serviceError);
77
+ // Add a warning? For now, just log it.
78
+ warnings.push({
79
+ position: block.position,
80
+ type: 'service_error',
81
+ message: `Error checking parent UUID ${parentUUID}: ${serviceError.message}`
82
+ });
83
+ }
84
+ }
85
+ }
86
+ // If both are found, no need to check further blocks
87
+ if (hasPatch && hasParentChildRelationship) {
88
+ break;
89
+ }
90
+ }
91
+ }
92
+
93
+ // Determine if we need special controls (e.g., apply patch buttons, view parent buttons)
94
+ const needsControls = hasPatch || hasParentChildRelationship;
95
+
96
+ return {
97
+ blocks, // Return the processed blocks as well
98
+ warnings,
99
+ containsPatch: hasPatch,
100
+ hasParentChildRelationship,
101
+ needsControls
102
+ };
103
+ }
104
+
105
+ /**
106
+ * Detects if a message contains an incomplete code block using the core processor.
107
+ * @param {string} content - The message content.
108
+ * @param {Object} options - Options passed to processCodeBlocks (e.g., silent).
109
+ * @returns {Object} Object containing detection results:
110
+ * { hasIncompleteBlocks: boolean, incompleteBlock: Object|null }
111
+ * 'incompleteBlock' is the *last* incomplete block found.
112
+ */
113
+ function detectIncompleteCodeBlock(content, options = { silent: true }) {
114
+ if (!content || typeof content !== 'string') {
115
+ return {
116
+ hasIncompleteBlocks: false,
117
+ incompleteBlock: null
118
+ };
119
+ }
120
+
121
+ // Use the core processor which already identifies incomplete blocks
122
+ const { hasIncompleteBlocks, lastIncompleteBlock } = processCodeBlocks(content, options);
123
+
124
+ return {
125
+ hasIncompleteBlocks,
126
+ incompleteBlock: lastIncompleteBlock // Return the detailed last incomplete block object
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Extracts file paths from specially formatted lines in a message.
132
+ * Assumes paths are marked like: #### File: `path/to/file.ext`
133
+ * @param {string} messageText - The message text.
134
+ * @returns {Array<string>} Array of extracted file paths.
135
+ */
136
+ function extractFilePaths(messageText) {
137
+ if (!messageText || typeof messageText !== 'string') {
138
+ return [];
139
+ }
140
+
141
+ // Regex to find the specific file path format
142
+ const filePathRegex = /^####\s+File:\s+`([^`]+)`/gm; // Use ^ and gm for line-based matching
143
+ const filePaths = [];
144
+ let match;
145
+
146
+ while ((match = filePathRegex.exec(messageText)) !== null) {
147
+ // match[1] contains the captured path inside the backticks
148
+ filePaths.push(match[1]);
149
+ }
150
+
151
+ return filePaths;
152
+ }
153
+
154
+
155
+ module.exports = {
156
+ detectCodeBlockRelationships,
157
+ detectIncompleteCodeBlock,
158
+ extractFilePaths
159
+ };