mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
refactor: streamline edit result validation and format code
This commit is contained in:
@@ -66,33 +66,29 @@ export function getDMPSimilarity(original: string, modified: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to validate edit results using hunk information
|
// Helper function to validate edit results using hunk information
|
||||||
export function validateEditResult(hunk: Hunk, result: string, confidenceThreshold: number): number {
|
export function validateEditResult(hunk: Hunk, result: string): number {
|
||||||
const hunkDeepCopy: Hunk = JSON.parse(JSON.stringify(hunk))
|
// Build the expected text from the hunk
|
||||||
|
const expectedText = hunk.changes
|
||||||
|
.filter(change => change.type === "context" || change.type === "add")
|
||||||
|
.map(change => change.indent ? change.indent + change.content : change.content)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
const originalSkeleton = hunkDeepCopy.changes
|
// Calculate similarity between the result and expected text
|
||||||
.filter((change) => change.type === "context" || change.type === "remove")
|
const similarity = getDMPSimilarity(expectedText, result);
|
||||||
.map((change) => change.content)
|
|
||||||
.join("\n")
|
|
||||||
|
|
||||||
const expectedSkeleton = hunkDeepCopy.changes
|
// If the result is unchanged from original, return low confidence
|
||||||
.filter((change) => change.type === "context" || change.type === "add")
|
const originalText = hunk.changes
|
||||||
.map((change) => change.content)
|
.filter(change => change.type === "context" || change.type === "remove")
|
||||||
.join("\n")
|
.map(change => change.indent ? change.indent + change.content : change.content)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
const originalSimilarity = evaluateSimilarity(originalSkeleton, result)
|
const originalSimilarity = getDMPSimilarity(originalText, result);
|
||||||
const expectedSimilarity = evaluateSimilarity(expectedSkeleton, result)
|
if (originalSimilarity > 0.97 && similarity !== 1) {
|
||||||
|
return 0.8 * similarity; // Some confidence since we found the right location
|
||||||
if (originalSimilarity > 0.97 && expectedSimilarity !== 1) {
|
|
||||||
if (originalSimilarity === 1) {
|
|
||||||
return 0.5
|
|
||||||
} else {
|
|
||||||
return 0.8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const multiplier = expectedSimilarity < confidenceThreshold ? expectedSimilarity : 1
|
// For partial matches, scale the confidence but keep it high if we're close
|
||||||
|
return similarity;
|
||||||
return multiplier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to validate context lines against original content
|
// Helper function to validate context lines against original content
|
||||||
@@ -157,7 +153,9 @@ function combineOverlappingMatches(
|
|||||||
const usedIndices = new Set<number>()
|
const usedIndices = new Set<number>()
|
||||||
|
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
if (usedIndices.has(match.windowIndex)) {continue}
|
if (usedIndices.has(match.windowIndex)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Find overlapping matches
|
// Find overlapping matches
|
||||||
const overlapping = matches.filter(
|
const overlapping = matches.filter(
|
||||||
@@ -194,7 +192,12 @@ function combineOverlappingMatches(
|
|||||||
return combinedMatches
|
return combinedMatches
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findExactMatch(searchStr: string, content: string[], startIndex: number = 0, confidenceThreshold: number = 0.97): SearchResult {
|
export function findExactMatch(
|
||||||
|
searchStr: string,
|
||||||
|
content: string[],
|
||||||
|
startIndex: number = 0,
|
||||||
|
confidenceThreshold: number = 0.97
|
||||||
|
): SearchResult {
|
||||||
const searchLines = searchStr.split("\n")
|
const searchLines = searchStr.split("\n")
|
||||||
const windows = createOverlappingWindows(content.slice(startIndex), searchLines.length)
|
const windows = createOverlappingWindows(content.slice(startIndex), searchLines.length)
|
||||||
const matches: (SearchResult & { windowIndex: number })[] = []
|
const matches: (SearchResult & { windowIndex: number })[] = []
|
||||||
@@ -229,7 +232,12 @@ export function findExactMatch(searchStr: string, content: string[], startIndex:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// String similarity strategy
|
// String similarity strategy
|
||||||
export function findSimilarityMatch(searchStr: string, content: string[], startIndex: number = 0, confidenceThreshold: number = 0.97): SearchResult {
|
export function findSimilarityMatch(
|
||||||
|
searchStr: string,
|
||||||
|
content: string[],
|
||||||
|
startIndex: number = 0,
|
||||||
|
confidenceThreshold: number = 0.97
|
||||||
|
): SearchResult {
|
||||||
const searchLines = searchStr.split("\n")
|
const searchLines = searchStr.split("\n")
|
||||||
let bestScore = 0
|
let bestScore = 0
|
||||||
let bestIndex = -1
|
let bestIndex = -1
|
||||||
@@ -257,7 +265,12 @@ export function findSimilarityMatch(searchStr: string, content: string[], startI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Levenshtein strategy
|
// Levenshtein strategy
|
||||||
export function findLevenshteinMatch(searchStr: string, content: string[], startIndex: number = 0, confidenceThreshold: number = 0.97): SearchResult {
|
export function findLevenshteinMatch(
|
||||||
|
searchStr: string,
|
||||||
|
content: string[],
|
||||||
|
startIndex: number = 0,
|
||||||
|
confidenceThreshold: number = 0.97
|
||||||
|
): SearchResult {
|
||||||
const searchLines = searchStr.split("\n")
|
const searchLines = searchStr.split("\n")
|
||||||
const candidates = []
|
const candidates = []
|
||||||
|
|
||||||
@@ -271,7 +284,6 @@ export function findLevenshteinMatch(searchStr: string, content: string[], start
|
|||||||
const similarity = getDMPSimilarity(searchStr, closestMatch)
|
const similarity = getDMPSimilarity(searchStr, closestMatch)
|
||||||
const contextSimilarity = validateContextLines(searchStr, closestMatch, confidenceThreshold)
|
const contextSimilarity = validateContextLines(searchStr, closestMatch, confidenceThreshold)
|
||||||
const confidence = Math.min(similarity, contextSimilarity)
|
const confidence = Math.min(similarity, contextSimilarity)
|
||||||
console.log(searchStr, closestMatch, index, confidence)
|
|
||||||
return {
|
return {
|
||||||
index: confidence === 0 ? -1 : index,
|
index: confidence === 0 ? -1 : index,
|
||||||
confidence: index !== -1 ? confidence : 0,
|
confidence: index !== -1 ? confidence : 0,
|
||||||
@@ -284,99 +296,104 @@ export function findLevenshteinMatch(searchStr: string, content: string[], start
|
|||||||
|
|
||||||
// Helper function to identify anchor lines
|
// Helper function to identify anchor lines
|
||||||
function identifyAnchors(searchStr: string): { first: string | null; last: string | null } {
|
function identifyAnchors(searchStr: string): { first: string | null; last: string | null } {
|
||||||
const searchLines = searchStr.split("\n");
|
const searchLines = searchStr.split("\n")
|
||||||
let first: string | null = null;
|
let first: string | null = null
|
||||||
let last: string | null = null;
|
let last: string | null = null
|
||||||
|
|
||||||
// Find the first non-empty line
|
// Find the first non-empty line
|
||||||
for (const line of searchLines) {
|
for (const line of searchLines) {
|
||||||
if (line.trim()) {
|
if (line.trim()) {
|
||||||
first = line;
|
first = line
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the last non-empty line
|
// Find the last non-empty line
|
||||||
for (let i = searchLines.length - 1; i >= 0; i--) {
|
for (let i = searchLines.length - 1; i >= 0; i--) {
|
||||||
if (searchLines[i].trim()) {
|
if (searchLines[i].trim()) {
|
||||||
last = searchLines[i];
|
last = searchLines[i]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { first, last };
|
return { first, last }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anchor-based search strategy
|
// Anchor-based search strategy
|
||||||
export function findAnchorMatch(searchStr: string, content: string[], startIndex: number = 0, confidenceThreshold: number = 0.97): SearchResult {
|
export function findAnchorMatch(
|
||||||
const searchLines = searchStr.split("\n");
|
searchStr: string,
|
||||||
const { first, last } = identifyAnchors(searchStr);
|
content: string[],
|
||||||
|
startIndex: number = 0,
|
||||||
|
confidenceThreshold: number = 0.97
|
||||||
|
): SearchResult {
|
||||||
|
const searchLines = searchStr.split("\n")
|
||||||
|
const { first, last } = identifyAnchors(searchStr)
|
||||||
|
|
||||||
if (!first || !last) {
|
if (!first || !last) {
|
||||||
return { index: -1, confidence: 0, strategy: "anchor" };
|
return { index: -1, confidence: 0, strategy: "anchor" }
|
||||||
}
|
}
|
||||||
|
|
||||||
let firstIndex = -1;
|
let firstIndex = -1
|
||||||
let lastIndex = -1;
|
let lastIndex = -1
|
||||||
|
|
||||||
// Check if the first anchor is unique
|
// Check if the first anchor is unique
|
||||||
let firstOccurrences = 0;
|
let firstOccurrences = 0
|
||||||
for (const contentLine of content) {
|
for (const contentLine of content) {
|
||||||
if (contentLine === first) {
|
if (contentLine === first) {
|
||||||
firstOccurrences++;
|
firstOccurrences++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstOccurrences !== 1) {
|
if (firstOccurrences !== 1) {
|
||||||
return { index: -1, confidence: 0, strategy: "anchor" };
|
return { index: -1, confidence: 0, strategy: "anchor" }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the first anchor
|
// Find the first anchor
|
||||||
for (let i = startIndex; i < content.length; i++) {
|
for (let i = startIndex; i < content.length; i++) {
|
||||||
if (content[i] === first) {
|
if (content[i] === first) {
|
||||||
firstIndex = i;
|
firstIndex = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the last anchor
|
// Find the last anchor
|
||||||
for (let i = content.length - 1; i >= startIndex; i--) {
|
for (let i = content.length - 1; i >= startIndex; i--) {
|
||||||
if (content[i] === last) {
|
if (content[i] === last) {
|
||||||
lastIndex = i;
|
lastIndex = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstIndex === -1 || lastIndex === -1 || lastIndex <= firstIndex) {
|
if (firstIndex === -1 || lastIndex === -1 || lastIndex <= firstIndex) {
|
||||||
return { index: -1, confidence: 0, strategy: "anchor" };
|
return { index: -1, confidence: 0, strategy: "anchor" }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the context
|
// Validate the context
|
||||||
const expectedContext = searchLines.slice(searchLines.indexOf(first) + 1, searchLines.indexOf(last)).join("\n");
|
const expectedContext = searchLines.slice(searchLines.indexOf(first) + 1, searchLines.indexOf(last)).join("\n")
|
||||||
const actualContext = content.slice(firstIndex + 1, lastIndex).join("\n");
|
const actualContext = content.slice(firstIndex + 1, lastIndex).join("\n")
|
||||||
const contextSimilarity = evaluateSimilarity(expectedContext, actualContext);
|
const contextSimilarity = evaluateSimilarity(expectedContext, actualContext)
|
||||||
|
|
||||||
if (contextSimilarity < getAdaptiveThreshold(content.length, confidenceThreshold)) {
|
if (contextSimilarity < getAdaptiveThreshold(content.length, confidenceThreshold)) {
|
||||||
return { index: -1, confidence: 0, strategy: "anchor" };
|
return { index: -1, confidence: 0, strategy: "anchor" }
|
||||||
}
|
}
|
||||||
|
|
||||||
const confidence = 1;
|
const confidence = 1
|
||||||
|
|
||||||
return {
|
return {
|
||||||
index: firstIndex,
|
index: firstIndex,
|
||||||
confidence: confidence,
|
confidence: confidence,
|
||||||
strategy: "anchor",
|
strategy: "anchor",
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main search function that tries all strategies
|
// Main search function that tries all strategies
|
||||||
export function findBestMatch(searchStr: string, content: string[], startIndex: number = 0, confidenceThreshold: number = 0.97): SearchResult {
|
export function findBestMatch(
|
||||||
const strategies = [
|
searchStr: string,
|
||||||
findExactMatch,
|
content: string[],
|
||||||
findAnchorMatch,
|
startIndex: number = 0,
|
||||||
findSimilarityMatch,
|
confidenceThreshold: number = 0.97
|
||||||
findLevenshteinMatch
|
): SearchResult {
|
||||||
]
|
const strategies = [findExactMatch, findAnchorMatch, findSimilarityMatch, findLevenshteinMatch]
|
||||||
|
|
||||||
let bestResult: SearchResult = { index: -1, confidence: 0, strategy: "none" }
|
let bestResult: SearchResult = { index: -1, confidence: 0, strategy: "none" }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user