Skip to content

Commit 60d4b32

Browse files
feat: Update launch configuration and add build task for esbuild; enhance getWeightedThreshold logic and add tests
1 parent 8df5d92 commit 60d4b32

File tree

6 files changed

+90
-38
lines changed

6 files changed

+90
-38
lines changed

.vscode/launch.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
"type": "extensionHost",
1111
"request": "launch",
1212
"runtimeExecutable": "${execPath}",
13-
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
13+
"args": ["--disable-extensions", "--extensionDevelopmentPath=${workspaceFolder}"],
1414
"sourceMaps": true,
1515
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
16-
"preLaunchTask": "${defaultBuildTask}",
16+
"preLaunchTask": "build:esbuild",
1717
"env": {
1818
"NODE_ENV": "development",
1919
"VSCODE_DEBUG_MODE": "true"
@@ -23,7 +23,9 @@
2323
"hidden": false,
2424
"group": "tasks",
2525
"order": 1
26-
}
26+
},
27+
"sourceMapRenames": true,
28+
"trace": true
2729
}
2830
]
2931
}

.vscode/tasks.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@
5959
"group": "watch",
6060
"reveal": "always"
6161
}
62+
},
63+
{
64+
"label": "build:esbuild",
65+
"type": "npm",
66+
"script": "build:esbuild",
67+
"group": {
68+
"kind": "build",
69+
"isDefault": true
70+
},
71+
"problemMatcher": [],
72+
"isBackground": false
6273
}
6374
]
6475
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,13 @@
371371
"@google/genai": "^0.12.0",
372372
"@mistralai/mistralai": "^1.3.6",
373373
"@modelcontextprotocol/sdk": "^1.7.0",
374+
"@tailwindcss/vite": "^4.1.5",
374375
"@types/clone-deep": "^4.0.4",
375376
"@types/pdf-parse": "^1.1.4",
376377
"@types/tmp": "^0.2.6",
377378
"@types/turndown": "^5.0.5",
378379
"@types/vscode": "^1.95.0",
380+
"@vitejs/plugin-react": "^4.4.1",
379381
"@vscode/codicons": "^0.0.36",
380382
"axios": "^1.7.4",
381383
"cheerio": "^1.0.0",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { getWeightedThreshold } from "../multi-search-replace"
2+
3+
describe("getWeightedThreshold", () => {
4+
it("returns 1 for baseThreshold 1.0 and short text", () => {
5+
expect(getWeightedThreshold(1.0, 10)).toBe(1)
6+
})
7+
8+
it("returns 1 for baseThreshold 1.0 and long text", () => {
9+
expect(getWeightedThreshold(1.0, 10000)).toBe(1)
10+
})
11+
12+
it("returns baseThreshold for long text", () => {
13+
expect(getWeightedThreshold(0.95, 1000)).toBe(0.95)
14+
})
15+
16+
it("returns baseThreshold for text length exactly 50", () => {
17+
expect(getWeightedThreshold(0.9, 50)).toBe(0.9)
18+
})
19+
20+
it("returns baseThreshold - 0.1 for short text, but not below 0.8", () => {
21+
expect(getWeightedThreshold(0.9, 10)).toBe(0.8)
22+
expect(getWeightedThreshold(0.85, 10)).toBe(0.8)
23+
expect(getWeightedThreshold(0.95, 10)).toBe(0.85)
24+
})
25+
26+
it("never goes below 0.8 for extreme values", () => {
27+
expect(getWeightedThreshold(0.8, 1)).toBe(0.8)
28+
expect(getWeightedThreshold(0.8, 100000)).toBe(0.8)
29+
})
30+
})

src/core/diff/strategies/multi-search-replace.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,13 @@ function getSimilarity(original: string, search: string): number {
2929
return 1 - dist / maxLength
3030
}
3131

32-
function getWeightedThreshold(baseThreshold: number, textLength: number): number {
33-
const MIN_THRESHOLD_FACTOR = 0.8
34-
const LENGTH_THRESHOLD = 50
35-
const lengthFactor = Math.max(
36-
MIN_THRESHOLD_FACTOR,
37-
1 - (Math.log10(Math.max(textLength, LENGTH_THRESHOLD)) - 2) * 0.1,
38-
)
39-
return Math.max(baseThreshold * lengthFactor, 0.8) // Nunca por debajo de 0.6
32+
export function getWeightedThreshold(baseThreshold: number, textLength: number): number {
33+
if (baseThreshold === 1) return 1
34+
const MIN_THRESHOLD = 0.8
35+
const lengthFactor = 1 - 1 / (1 + Math.log(Math.max(textLength, 2)) / Math.log(10))
36+
const flex = (1 - baseThreshold) * (1 - lengthFactor)
37+
const threshold = Math.max(baseThreshold + flex, MIN_THRESHOLD)
38+
return Math.min(threshold, 1)
4039
}
4140

4241
/**
@@ -361,7 +360,6 @@ Only use a single line of '=======' between search and replacement content, beca
361360
// Detect line ending from original content
362361
const lineEnding = originalContent.includes("\r\n") ? "\r\n" : "\n"
363362
let resultLines = originalContent.split(/\r?\n/)
364-
let delta = 0
365363
let diffResults: DiffResult[] = []
366364
let appliedCount = 0
367365
const replacements = matches
@@ -370,11 +368,20 @@ Only use a single line of '=======' between search and replacement content, beca
370368
searchContent: match[6],
371369
replaceContent: match[7],
372370
}))
373-
.sort((a, b) => a.startLine - b.startLine)
371+
.map((replacement) => {
372+
if (replacement.replaceContent) {
373+
replacement.replaceContent = replacement.replaceContent.replace(
374+
/(^|\n)(\s*)\:start_line\:\s*\d+\s*\n/g,
375+
"$1",
376+
)
377+
}
378+
return replacement
379+
})
380+
.sort((a, b) => b.startLine - a.startLine)
374381

375382
for (const replacement of replacements) {
376383
let { searchContent, replaceContent } = replacement
377-
let startLine = replacement.startLine + (replacement.startLine === 0 ? 0 : delta)
384+
let startLine = replacement.startLine
378385

379386
// First unescape any escaped markers in the content
380387
searchContent = this.unescapeMarkers(searchContent)
@@ -563,7 +570,6 @@ Only use a single line of '=======' between search and replacement content, beca
563570
const beforeMatch = resultLines.slice(0, matchIndex)
564571
const afterMatch = resultLines.slice(matchIndex + searchLines.length)
565572
resultLines = [...beforeMatch, ...indentedReplaceLines, ...afterMatch]
566-
delta = delta - matchedLines.length + replaceLines.length
567573
appliedCount++
568574
}
569575
const finalContent = resultLines.join(lineEnding)

webview-ui/package.json

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,51 +17,52 @@
1717
"clean": "rimraf build"
1818
},
1919
"dependencies": {
20-
"@radix-ui/react-alert-dialog": "^1.1.6",
21-
"@radix-ui/react-checkbox": "^1.1.5",
22-
"@radix-ui/react-collapsible": "^1.1.3",
23-
"@radix-ui/react-dialog": "^1.1.6",
24-
"@radix-ui/react-dropdown-menu": "^2.1.5",
20+
"@radix-ui/react-alert-dialog": "^1.1.13",
21+
"@radix-ui/react-checkbox": "^1.3.1",
22+
"@radix-ui/react-collapsible": "^1.1.10",
23+
"@radix-ui/react-dialog": "^1.1.13",
24+
"@radix-ui/react-dropdown-menu": "^2.1.14",
2525
"@radix-ui/react-icons": "^1.3.2",
26-
"@radix-ui/react-popover": "^1.1.6",
27-
"@radix-ui/react-progress": "^1.1.2",
28-
"@radix-ui/react-select": "^2.1.6",
29-
"@radix-ui/react-separator": "^1.1.2",
30-
"@radix-ui/react-slider": "^1.2.3",
31-
"@radix-ui/react-slot": "^1.1.2",
32-
"@radix-ui/react-tooltip": "^1.1.8",
26+
"@radix-ui/react-popover": "^1.1.13",
27+
"@radix-ui/react-progress": "^1.1.6",
28+
"@radix-ui/react-select": "^2.2.4",
29+
"@radix-ui/react-separator": "^1.1.6",
30+
"@radix-ui/react-slider": "^1.3.4",
31+
"@radix-ui/react-slot": "^1.2.2",
32+
"@radix-ui/react-tooltip": "^1.2.6",
3333
"@tailwindcss/vite": "^4.0.0",
34-
"@tanstack/react-query": "^5.68.0",
34+
"@tanstack/react-query": "^5.75.4",
3535
"@vscode/webview-ui-toolkit": "^1.4.0",
3636
"class-variance-authority": "^0.7.1",
3737
"clsx": "^2.1.1",
38-
"cmdk": "^1.0.0",
39-
"debounce": "^2.1.1",
38+
"cmdk": "^1.1.1",
39+
"debounce": "^2.2.0",
4040
"fast-deep-equal": "^3.1.3",
4141
"fzf": "^0.5.2",
4242
"i18next": "^24.2.2",
4343
"i18next-http-backend": "^3.0.2",
4444
"knuth-shuffle-seeded": "^1.0.6",
4545
"lucide-react": "^0.475.0",
46-
"mermaid": "^11.4.1",
47-
"posthog-js": "^1.227.2",
46+
"mermaid": "^11.6.0",
47+
"posthog-js": "^1.239.1",
4848
"react": "^18.3.1",
4949
"react-dom": "^18.3.1",
50-
"react-i18next": "^15.4.1",
50+
"react-i18next": "^15.5.1",
5151
"react-markdown": "^9.0.3",
5252
"react-remark": "^2.1.0",
53-
"react-textarea-autosize": "^8.5.3",
54-
"react-use": "^17.5.1",
55-
"react-virtuoso": "^4.7.13",
53+
"react-textarea-autosize": "^8.5.9",
54+
"react-use": "^17.6.0",
55+
"react-virtuoso": "^4.12.7",
5656
"rehype-highlight": "^7.0.0",
5757
"remark-gfm": "^4.0.1",
58-
"remove-markdown": "^0.6.0",
58+
"remove-markdown": "^0.6.2",
5959
"shell-quote": "^1.8.2",
6060
"shiki": "^3.2.1",
61-
"styled-components": "^6.1.13",
61+
"styled-components": "^6.1.17",
6262
"tailwind-merge": "^2.6.0",
6363
"tailwindcss": "^4.0.0",
6464
"tailwindcss-animate": "^1.0.7",
65+
"unist-util-visit": "^5.0.0",
6566
"vscrui": "^0.2.2",
6667
"zod": "^3.24.2"
6768
},

0 commit comments

Comments
 (0)