@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,213 @@
1
+ /**
2
+ * Component: PatchUtils Diagnostic Reporter
3
+ * Block-UUID: 3a7b9c5d-1e3f-4a2b-8c7d-6e5f4a3b2c1d
4
+ * Parent-UUID: N/A
5
+ * Version: 1.0.0
6
+ * Description: Formats diagnostic information about patch hunks for humans and LLMs.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-05-14T16:50:00.000Z
9
+ * Authors: Claude 3.7 Sonnet (v1.0.0)
10
+ */
11
+
12
+
13
+ /**
14
+ * Generates a human-readable description of a hunk validation result
15
+ * @param {object} hunkResult - The validation result for a single hunk
16
+ * @returns {string} Human-readable description
17
+ */
18
+ function describeHunkResult(hunkResult) {
19
+ if (!hunkResult) {
20
+ return "No hunk result provided";
21
+ }
22
+
23
+ if (hunkResult.valid) {
24
+ return `Hunk #${hunkResult.hunkIndex + 1} VALID: Applied successfully at specified position.`;
25
+ }
26
+
27
+ let description = `Hunk #${hunkResult.hunkIndex + 1} FAILED: `;
28
+
29
+ if (hunkResult.diagnostics) {
30
+ if (!hunkResult.diagnostics.headerValid) {
31
+ description += `Invalid hunk header format. ${hunkResult.diagnostics.headerError}`;
32
+ } else if (hunkResult.diagnostics.method === "direct_failed") {
33
+ description += hunkResult.diagnostics.message || "Failed to apply at specified position.";
34
+ } else {
35
+ description += "Unknown validation error.";
36
+ }
37
+ } else {
38
+ description += "No diagnostic information available.";
39
+ }
40
+
41
+ // Add correction information if available
42
+ if (hunkResult.correction && hunkResult.correction.success) {
43
+ description += `\n - ${hunkResult.correction.explanation}`;
44
+ } else if (hunkResult.correction) {
45
+ description += `\n - Could not generate correction: ${hunkResult.correction.reason}`;
46
+ }
47
+
48
+ return description;
49
+ }
50
+
51
+ /**
52
+ * Generates human-readable diagnostics for all hunks
53
+ * @param {object[]} hunkResults - Array of validation results for all hunks
54
+ * @returns {string} Human-readable diagnostic report
55
+ */
56
+ function generateHumanReadableDiagnostics(hunkResults) {
57
+ if (!Array.isArray(hunkResults) || hunkResults.length === 0) {
58
+ return "No hunk results to report.";
59
+ }
60
+
61
+ const validHunks = hunkResults.filter(result => result.valid);
62
+ const invalidHunks = hunkResults.filter(result => !result.valid);
63
+
64
+ let report = `Patch Validation Report\n`;
65
+ report += `======================\n\n`;
66
+ report += `Summary: ${validHunks.length} of ${hunkResults.length} hunks valid.\n\n`;
67
+
68
+ if (invalidHunks.length > 0) {
69
+ report += `Invalid Hunks:\n`;
70
+ report += invalidHunks.map(result => describeHunkResult(result)).join('\n\n');
71
+ report += `\n\n`;
72
+ }
73
+
74
+ if (validHunks.length > 0) {
75
+ report += `Valid Hunks: ${validHunks.map(result => `#${result.hunkIndex + 1}`).join(', ')}`;
76
+ }
77
+
78
+ return report;
79
+ }
80
+
81
+ /**
82
+ * Formats a hunk result for LLM consumption
83
+ * @param {object} hunkResult - The validation result for a single hunk
84
+ * @returns {object} Structured hunk result for LLM
85
+ */
86
+ function formatHunkResultForLLM(hunkResult) {
87
+ if (!hunkResult) {
88
+ return { error: "No hunk result provided" };
89
+ }
90
+
91
+ const result = {
92
+ hunkIndex: hunkResult.hunkIndex,
93
+ status: hunkResult.valid ? "valid" : "invalid",
94
+ header: hunkResult.hunk?.header || null
95
+ };
96
+
97
+ if (hunkResult.valid) {
98
+ result.message = "Hunk applied successfully at specified position";
99
+ } else {
100
+ result.issueType = hunkResult.diagnostics?.method === "direct_failed"
101
+ ? "context_mismatch"
102
+ : "header_invalid";
103
+
104
+ result.message = hunkResult.diagnostics?.message || "Unknown validation error";
105
+
106
+ if (hunkResult.correction && hunkResult.correction.success) {
107
+ result.correction = {
108
+ correctedHeader: hunkResult.correction.correctedHeader,
109
+ confidence: hunkResult.correction.confidence,
110
+ explanation: hunkResult.correction.explanation
111
+ };
112
+ }
113
+ }
114
+
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * Generates structured feedback for LLMs about patch validation
120
+ * @param {object[]} hunkResults - Array of validation results for all hunks
121
+ * @returns {object} Structured feedback for LLM consumption
122
+ */
123
+ function generateLLMFeedback(hunkResults) {
124
+ if (!Array.isArray(hunkResults) || hunkResults.length === 0) {
125
+ return { error: "No hunk results to report" };
126
+ }
127
+
128
+ const validCount = hunkResults.filter(result => result.valid).length;
129
+
130
+ return {
131
+ summary: {
132
+ totalHunks: hunkResults.length,
133
+ validHunks: validCount,
134
+ invalidHunks: hunkResults.length - validCount,
135
+ overallStatus: validCount === hunkResults.length ? "valid" : "invalid"
136
+ },
137
+ hunks: hunkResults.map(formatHunkResultForLLM)
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Formats a diagnostic summary for the entire patch
143
+ * @param {object} patchResult - The overall patch validation result
144
+ * @returns {object} Formatted diagnostic summary
145
+ */
146
+ function formatDiagnosticSummary(patchResult) {
147
+ if (!patchResult) {
148
+ return { error: "No patch result provided" };
149
+ }
150
+
151
+ const summary = {
152
+ success: patchResult.success,
153
+ hunkCount: patchResult.hunkResults?.length || 0,
154
+ validHunks: patchResult.hunkResults?.filter(h => h.valid)?.length || 0,
155
+ hasCorrections: patchResult.hunkResults?.some(h => h.correction?.success) || false
156
+ };
157
+
158
+ summary.allHunksValid = summary.validHunks === summary.hunkCount;
159
+ summary.allHunksFixable = summary.allHunksValid ||
160
+ (patchResult.hunkResults?.filter(h => !h.valid)
161
+ .every(h => h.correction?.success) || false);
162
+
163
+ if (!summary.allHunksValid) {
164
+ summary.invalidHunkIndices = patchResult.hunkResults
165
+ ?.filter(h => !h.valid)
166
+ .map(h => h.hunkIndex);
167
+ }
168
+
169
+ return summary;
170
+ }
171
+
172
+ /**
173
+ * Generates a concise error message for a failed patch
174
+ * @param {object} patchResult - The overall patch validation result
175
+ * @returns {string} Concise error message
176
+ */
177
+ function generateErrorMessage(patchResult) {
178
+ if (!patchResult) {
179
+ return "Patch validation failed: No result available";
180
+ }
181
+
182
+ if (patchResult.success) {
183
+ return "Patch applied successfully";
184
+ }
185
+
186
+ const summary = formatDiagnosticSummary(patchResult);
187
+
188
+ if (summary.allHunksFixable) {
189
+ return "Patch contains fixable errors in hunk headers";
190
+ }
191
+
192
+ const invalidHunks = patchResult.hunkResults?.filter(h => !h.valid) || [];
193
+
194
+ if (invalidHunks.length === 0) {
195
+ return "Patch validation failed: Unknown error";
196
+ }
197
+
198
+ if (invalidHunks.length === 1) {
199
+ const hunk = invalidHunks[0];
200
+ return `Patch validation failed: Hunk #${hunk.hunkIndex + 1} - ${hunk.diagnostics?.message || "Unknown error"}`;
201
+ }
202
+
203
+ return `Patch validation failed: ${invalidHunks.length} invalid hunks (indices: ${summary.invalidHunkIndices?.join(', ')})`;
204
+ }
205
+
206
+ module.exports = {
207
+ describeHunkResult,
208
+ generateHumanReadableDiagnostics,
209
+ formatHunkResultForLLM,
210
+ generateLLMFeedback,
211
+ formatDiagnosticSummary,
212
+ generateErrorMessage
213
+ };
@@ -0,0 +1,390 @@
1
+ /**
2
+ * Component: PatchUtils Enhanced Processor
3
+ * Block-UUID: 3e9a9106-7f16-4b49-9b38-86d95b413c2a
4
+ * Parent-UUID: 5bfb717c-aaec-462e-a50e-d096aba0d63f
5
+ * Version: 1.2.0
6
+ * Description: Enhanced patch processor with hunk-level validation, diagnostics, and fuzzy matching.
7
+ * Language: JavaScript
8
+ * Created-at: 2025-05-14T18:26:31.210Z
9
+ * Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Flash (v1.1.0), Claude 3.7 Sonnet (v1.2.0)
10
+ */
11
+
12
+
13
+ const jsdiff = require('diff');
14
+ const { removeLineNumbers } = require('../CodeBlockUtils/lineNumberFormatter');
15
+ const { extractAndCleanHunks, reconstructPatch } = require('./patchExtractor');
16
+ const { validateHunk, validateHunks } = require('./hunkValidator');
17
+ const { findBestContextMatch, findBestMatchWithSlidingWindow } = require('./fuzzyMatcher');
18
+ const { generateCorrectedHunk, generateHunkCorrection } = require('./hunkCorrector');
19
+ const { generateHumanReadableDiagnostics, generateLLMFeedback } = require('./diagnosticReporter');
20
+ const { detectAndFixRedundantChanges } = require('./patchVerifier/detectAndFixRedundantChanges');
21
+
22
+ /**
23
+ * @typedef {object} PatchValidationResult
24
+ * @property {boolean} valid - Whether the patch is valid
25
+ * @property {boolean} fixable - Whether invalid hunks can be fixed
26
+ * @property {object[]} hunkResults - Detailed results for each hunk
27
+ * @property {string} humanReadableDiagnostics - Human-readable diagnostic report
28
+ * @property {object} llmFeedback - Structured feedback for LLMs
29
+ */
30
+
31
+ /**
32
+ * @typedef {object} PatchApplicationResult
33
+ * @property {boolean} success - Whether the patch was applied successfully
34
+ * @property {string} patchedText - The resulting text after applying the patch
35
+ * @property {boolean} patchWasCorrected - Whether the patch needed correction
36
+ * @property {string} correctedPatch - The corrected patch if applicable
37
+ * @property {object[]} hunkResults - Detailed results for each hunk
38
+ * @property {string} humanReadableDiagnostics - Human-readable diagnostic report
39
+ * @property {object} llmFeedback - Structured feedback for LLMs
40
+ */
41
+
42
+ /**
43
+ * @typedef {object} HunkValidationResult
44
+ * @property {boolean} valid - Whether the hunk is valid
45
+ * @property {object} hunk - Parsed hunk information
46
+ * @property {object} headerInfo - Parsed header information
47
+ * @property {object} diagnostics - Detailed diagnostic information
48
+ */
49
+
50
+ /**
51
+ * Applies a patch with detailed per-hunk diagnostics
52
+ * @param {string} sourceText - Original source code
53
+ * @param {string} patchText - Patch text from LLM
54
+ * @returns {object} Comprehensive results including diagnostics
55
+ */
56
+ function applyPatchWithDiagnostics(sourceText, patchText) {
57
+ if (!sourceText || !patchText) {
58
+ return {
59
+ success: false,
60
+ error: "Missing source or patch text",
61
+ patchedText: null,
62
+ hunkResults: []
63
+ };
64
+ }
65
+
66
+ // Clean source text (remove any line numbers)
67
+ const cleanSourceText = removeLineNumbers(sourceText);
68
+
69
+ // First, clean up redundant changes
70
+ const redundantFixResult = detectAndFixRedundantChanges(patchText, true);
71
+ const cleanedPatchText = redundantFixResult.correctionsMade
72
+ ? redundantFixResult.correctedPatchText
73
+ : patchText;
74
+
75
+ // Extract hunks from the patch
76
+ const { metadata, hunks } = extractAndCleanHunks(cleanedPatchText);
77
+
78
+ if (hunks.length === 0) {
79
+ return {
80
+ success: false,
81
+ error: "No hunks found in patch",
82
+ patchedText: null,
83
+ hunkResults: []
84
+ };
85
+ }
86
+
87
+ // Validate each hunk
88
+ const hunkResults = validateHunks(cleanSourceText, hunks);
89
+
90
+ // For invalid hunks, try fuzzy matching
91
+ for (let i = 0; i < hunkResults.length; i++) {
92
+ const result = hunkResults[i];
93
+
94
+ if (!result.valid && result.diagnostics?.needsFuzzyMatching) {
95
+ // Try fuzzy matching using the correct context for matching
96
+ const matchResult = findBestMatchWithSlidingWindow(
97
+ result.hunk.contextLinesForMatching, // Use the new array
98
+ cleanSourceText
99
+ );
100
+
101
+ // Generate correction if match found
102
+ if (matchResult.found) {
103
+ const correction = generateHunkCorrection(result, matchResult);
104
+ hunkResults[i].correction = correction;
105
+ hunkResults[i].matchResult = matchResult;
106
+ } else {
107
+ hunkResults[i].correction = {
108
+ success: false,
109
+ reason: matchResult.reason || "No suitable match found"
110
+ };
111
+ hunkResults[i].matchResult = matchResult;
112
+ }
113
+ }
114
+ }
115
+
116
+ // Check if all hunks are valid or fixable
117
+ const allValid = hunkResults.every(result => result.valid);
118
+ const allFixable = hunkResults
119
+ .filter(result => !result.valid)
120
+ .every(result => result.correction && result.correction.success);
121
+
122
+ // If all hunks are valid, apply the patch directly
123
+ if (allValid) {
124
+ try {
125
+ const patchedText = jsdiff.applyPatch(cleanSourceText, patchText);
126
+
127
+ if (patchedText === false) {
128
+ return {
129
+ success: false,
130
+ error: "Failed to apply patch despite all hunks validating individually",
131
+ patchedText: null,
132
+ hunkResults,
133
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
134
+ llmFeedback: generateLLMFeedback(hunkResults)
135
+ };
136
+ }
137
+
138
+ return {
139
+ success: true,
140
+ patchedText,
141
+ hunkResults,
142
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
143
+ llmFeedback: generateLLMFeedback(hunkResults)
144
+ };
145
+ } catch (error) {
146
+ return {
147
+ success: false,
148
+ error: `Error applying patch: ${error.message}`,
149
+ patchedText: null,
150
+ hunkResults,
151
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
152
+ llmFeedback: generateLLMFeedback(hunkResults)
153
+ };
154
+ }
155
+ }
156
+
157
+ // If all invalid hunks are fixable, create a corrected patch and apply it
158
+ if (allFixable) {
159
+ try {
160
+ // Create corrected hunks
161
+ const correctedHunks = hunkResults.map(result => {
162
+ if (result.valid) {
163
+ return hunks[result.hunkIndex];
164
+ } else {
165
+ return result.correction.correctedHunkText;
166
+ }
167
+ });
168
+
169
+ // Reconstruct the patch
170
+ const correctedPatch = reconstructPatch(metadata, correctedHunks);
171
+
172
+ // Apply the corrected patch
173
+ const patchedText = jsdiff.applyPatch(cleanSourceText, correctedPatch.replace(/# --- PATCH (START|END) MARKER ---/g, ''));
174
+
175
+ if (patchedText === false) {
176
+ return {
177
+ success: false,
178
+ error: "Failed to apply corrected patch",
179
+ patchedText: null,
180
+ correctedPatch,
181
+ hunkResults,
182
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
183
+ llmFeedback: generateLLMFeedback(hunkResults)
184
+ };
185
+ }
186
+
187
+ return {
188
+ success: true,
189
+ patchedText,
190
+ correctedPatch,
191
+ hunkResults,
192
+ patchWasCorrected: true,
193
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
194
+ llmFeedback: generateLLMFeedback(hunkResults)
195
+ };
196
+ } catch (error) {
197
+ return {
198
+ success: false,
199
+ error: `Error applying corrected patch: ${error.message}`,
200
+ patchedText: null,
201
+ hunkResults,
202
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
203
+ llmFeedback: generateLLMFeedback(hunkResults)
204
+ };
205
+ }
206
+ }
207
+
208
+ // If we get here, some hunks are invalid and not fixable
209
+ return {
210
+ success: false,
211
+ error: "Some hunks are invalid and could not be fixed",
212
+ patchedText: null,
213
+ hunkResults,
214
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
215
+ llmFeedback: generateLLMFeedback(hunkResults)
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Validates a patch without applying it
221
+ * @param {string} sourceText - Original source code
222
+ * @param {string} patchText - Patch text from LLM
223
+ * @returns {object} Validation results with diagnostics
224
+ */
225
+ function validatePatch(sourceText, patchText) {
226
+ if (!sourceText || !patchText) {
227
+ return {
228
+ valid: false,
229
+ error: "Missing source or patch text",
230
+ hunkResults: []
231
+ };
232
+ }
233
+
234
+ // Clean source text
235
+ const cleanSourceText = removeLineNumbers(sourceText);
236
+
237
+ // Clean up redundant changes
238
+ const redundantFixResult = detectAndFixRedundantChanges(patchText, true);
239
+ const cleanedPatchText = redundantFixResult.correctionsMade
240
+ ? redundantFixResult.correctedPatchText
241
+ : patchText;
242
+
243
+ // Extract hunks
244
+ const { metadata, hunks } = extractAndCleanHunks(cleanedPatchText);
245
+
246
+ if (hunks.length === 0) {
247
+ return {
248
+ valid: false,
249
+ error: "No hunks found in patch",
250
+ hunkResults: []
251
+ };
252
+ }
253
+
254
+ // Validate each hunk
255
+ const hunkResults = validateHunks(cleanSourceText, hunks);
256
+
257
+ // For invalid hunks, try fuzzy matching
258
+ for (let i = 0; i < hunkResults.length; i++) {
259
+ const result = hunkResults[i];
260
+
261
+ if (!result.valid && result.diagnostics?.needsFuzzyMatching) {
262
+ const matchResult = findBestMatchWithSlidingWindow(
263
+ result.hunk.contextLinesForMatching, // Use the new array
264
+ cleanSourceText
265
+ );
266
+
267
+ if (matchResult.found) {
268
+ const correction = generateHunkCorrection(result, matchResult);
269
+ hunkResults[i].correction = correction;
270
+ hunkResults[i].matchResult = matchResult;
271
+ } else {
272
+ hunkResults[i].correction = {
273
+ success: false,
274
+ reason: matchResult.reason || "No suitable match found"
275
+ };
276
+ hunkResults[i].matchResult = matchResult;
277
+ }
278
+ }
279
+ }
280
+
281
+ // Check if all hunks are valid or fixable
282
+ const allValid = hunkResults.every(result => result.valid);
283
+ const allFixable = hunkResults
284
+ .filter(result => !result.valid)
285
+ .every(result => result.correction && result.correction.success);
286
+
287
+ return {
288
+ valid: allValid,
289
+ fixable: !allValid && allFixable,
290
+ hunkResults,
291
+ humanReadableDiagnostics: generateHumanReadableDiagnostics(hunkResults),
292
+ llmFeedback: generateLLMFeedback(hunkResults)
293
+ };
294
+ }
295
+
296
+ /**
297
+ * Applies a single hunk to source code
298
+ * @param {string} sourceText - Original source code
299
+ * @param {string} hunkText - Text of a single hunk
300
+ * @returns {object} Result of applying the hunk
301
+ */
302
+ function applyHunk(sourceText, hunkText) {
303
+ if (!sourceText || !hunkText) {
304
+ return {
305
+ success: false,
306
+ error: "Missing source or hunk text",
307
+ patchedText: null
308
+ };
309
+ }
310
+
311
+ // Clean source text
312
+ const cleanSourceText = removeLineNumbers(sourceText);
313
+
314
+ // Clean hunk line numbers
315
+ const cleanHunk = cleanHunkLineNumbers(hunkText);
316
+
317
+ // Validate the hunk
318
+ const validation = validateHunk(cleanSourceText, cleanHunk);
319
+
320
+ if (validation.valid) {
321
+ return {
322
+ success: true,
323
+ patchedText: validation.appliedText,
324
+ validation
325
+ };
326
+ }
327
+
328
+ // Try fuzzy matching
329
+ const matchResult = findBestMatchWithSlidingWindow(
330
+ validation.hunk.contextLinesForMatching, // Use the new array
331
+ cleanSourceText
332
+ );
333
+
334
+ if (matchResult.found) {
335
+ const correction = generateHunkCorrection(validation, matchResult);
336
+
337
+ if (correction.success) {
338
+ try {
339
+ // Create a minimal patch with just this hunk
340
+ const minimalPatch = `--- Original\n+++ Modified\n${correction.correctedHunkText}`;
341
+
342
+ // Apply the corrected hunk
343
+ const patchedText = jsdiff.applyPatch(cleanSourceText, minimalPatch);
344
+
345
+ if (patchedText === false) {
346
+ return {
347
+ success: false,
348
+ error: "Failed to apply corrected hunk",
349
+ patchedText: null,
350
+ validation,
351
+ correction,
352
+ matchResult
353
+ };
354
+ }
355
+
356
+ return {
357
+ success: true,
358
+ patchedText,
359
+ validation,
360
+ correction,
361
+ matchResult,
362
+ hunkWasCorrected: true
363
+ };
364
+ } catch (error) {
365
+ return {
366
+ success: false,
367
+ error: `Error applying corrected hunk: ${error.message}`,
368
+ patchedText: null,
369
+ validation,
370
+ correction,
371
+ matchResult
372
+ };
373
+ }
374
+ }
375
+ }
376
+
377
+ return {
378
+ success: false,
379
+ error: "Hunk is invalid and could not be fixed",
380
+ patchedText: null,
381
+ validation,
382
+ matchResult: matchResult || null
383
+ };
384
+ }
385
+
386
+ module.exports = {
387
+ applyPatchWithDiagnostics,
388
+ validatePatch,
389
+ applyHunk
390
+ };