Skip to content

Commit 648c6e7

Browse files
authored
Move diff editing config to provider settings (#2655)
* Move diff editing config to provider settings * Fix tests
1 parent a3b2ebc commit 648c6e7

File tree

11 files changed

+179
-98
lines changed

11 files changed

+179
-98
lines changed

src/core/config/ProviderSettingsManager.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const providerProfilesSchema = z.object({
1616
migrations: z
1717
.object({
1818
rateLimitSecondsMigrated: z.boolean().optional(),
19+
diffSettingsMigrated: z.boolean().optional(),
1920
})
2021
.optional(),
2122
})
@@ -36,6 +37,7 @@ export class ProviderSettingsManager {
3637
modeApiConfigs: this.defaultModeApiConfigs,
3738
migrations: {
3839
rateLimitSecondsMigrated: true, // Mark as migrated on fresh installs
40+
diffSettingsMigrated: true, // Mark as migrated on fresh installs
3941
},
4042
}
4143

@@ -85,7 +87,10 @@ export class ProviderSettingsManager {
8587

8688
// Ensure migrations field exists
8789
if (!providerProfiles.migrations) {
88-
providerProfiles.migrations = { rateLimitSecondsMigrated: false } // Initialize with default values
90+
providerProfiles.migrations = {
91+
rateLimitSecondsMigrated: false,
92+
diffSettingsMigrated: false,
93+
} // Initialize with default values
8994
isDirty = true
9095
}
9196

@@ -95,6 +100,12 @@ export class ProviderSettingsManager {
95100
isDirty = true
96101
}
97102

103+
if (!providerProfiles.migrations.diffSettingsMigrated) {
104+
await this.migrateDiffSettings(providerProfiles)
105+
providerProfiles.migrations.diffSettingsMigrated = true
106+
isDirty = true
107+
}
108+
98109
if (isDirty) {
99110
await this.store(providerProfiles)
100111
}
@@ -129,6 +140,41 @@ export class ProviderSettingsManager {
129140
}
130141
}
131142

143+
private async migrateDiffSettings(providerProfiles: ProviderProfiles) {
144+
try {
145+
let diffEnabled: boolean | undefined
146+
let fuzzyMatchThreshold: number | undefined
147+
148+
try {
149+
diffEnabled = await this.context.globalState.get<boolean>("diffEnabled")
150+
fuzzyMatchThreshold = await this.context.globalState.get<number>("fuzzyMatchThreshold")
151+
} catch (error) {
152+
console.error("[MigrateDiffSettings] Error getting global diff settings:", error)
153+
}
154+
155+
if (diffEnabled === undefined) {
156+
// Failed to get the existing value, use the default.
157+
diffEnabled = true
158+
}
159+
160+
if (fuzzyMatchThreshold === undefined) {
161+
// Failed to get the existing value, use the default.
162+
fuzzyMatchThreshold = 1.0
163+
}
164+
165+
for (const [name, apiConfig] of Object.entries(providerProfiles.apiConfigs)) {
166+
if (apiConfig.diffEnabled === undefined) {
167+
apiConfig.diffEnabled = diffEnabled
168+
}
169+
if (apiConfig.fuzzyMatchThreshold === undefined) {
170+
apiConfig.fuzzyMatchThreshold = fuzzyMatchThreshold
171+
}
172+
}
173+
} catch (error) {
174+
console.error(`[MigrateDiffSettings] Failed to migrate diff settings:`, error)
175+
}
176+
}
177+
132178
/**
133179
* List all available configs with metadata.
134180
*/

src/core/config/__tests__/ProviderSettingsManager.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,21 @@ describe("ProviderSettingsManager", () => {
4141
expect(mockSecrets.store).not.toHaveBeenCalled()
4242
})
4343

44-
it("should not initialize config if it exists", async () => {
44+
it("should not initialize config if it exists and migrations are complete", async () => {
4545
mockSecrets.get.mockResolvedValue(
4646
JSON.stringify({
4747
currentApiConfigName: "default",
4848
apiConfigs: {
4949
default: {
5050
config: {},
5151
id: "default",
52+
diffEnabled: true,
53+
fuzzyMatchThreshold: 1.0,
5254
},
5355
},
5456
migrations: {
5557
rateLimitSecondsMigrated: true,
58+
diffSettingsMigrated: true,
5659
},
5760
}),
5861
)
@@ -75,14 +78,19 @@ describe("ProviderSettingsManager", () => {
7578
apiProvider: "anthropic",
7679
},
7780
},
81+
migrations: {
82+
rateLimitSecondsMigrated: true,
83+
diffSettingsMigrated: true,
84+
},
7885
}),
7986
)
8087

8188
await providerSettingsManager.initialize()
8289

8390
// Should have written the config with new IDs
8491
expect(mockSecrets.store).toHaveBeenCalled()
85-
const storedConfig = JSON.parse(mockSecrets.store.mock.calls[0][1])
92+
const calls = mockSecrets.store.mock.calls
93+
const storedConfig = JSON.parse(calls[calls.length - 1][1]) // Get the latest call
8694
expect(storedConfig.apiConfigs.default.id).toBeTruthy()
8795
expect(storedConfig.apiConfigs.test.id).toBeTruthy()
8896
})

src/exports/roo-code.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ type ProviderSettings = {
182182
modelTemperature?: (number | null) | undefined
183183
reasoningEffort?: ("low" | "medium" | "high") | undefined
184184
rateLimitSeconds?: number | undefined
185+
diffEnabled?: boolean | undefined
186+
fuzzyMatchThreshold?: number | undefined
185187
fakeAi?: unknown | undefined
186188
}
187189

src/exports/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ type ProviderSettings = {
183183
modelTemperature?: (number | null) | undefined
184184
reasoningEffort?: ("low" | "medium" | "high") | undefined
185185
rateLimitSeconds?: number | undefined
186+
diffEnabled?: boolean | undefined
187+
fuzzyMatchThreshold?: number | undefined
186188
fakeAi?: unknown | undefined
187189
}
188190

src/schemas/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ export const providerSettingsSchema = z.object({
401401
modelTemperature: z.number().nullish(),
402402
reasoningEffort: reasoningEffortsSchema.optional(),
403403
rateLimitSeconds: z.number().optional(),
404+
diffEnabled: z.boolean().optional(),
405+
fuzzyMatchThreshold: z.number().optional(),
404406
// Fake AI
405407
fakeAi: z.unknown().optional(),
406408
})
@@ -490,6 +492,8 @@ const providerSettingsRecord: ProviderSettingsRecord = {
490492
modelTemperature: undefined,
491493
reasoningEffort: undefined,
492494
rateLimitSeconds: undefined,
495+
diffEnabled: undefined,
496+
fuzzyMatchThreshold: undefined,
493497
// Fake AI
494498
fakeAi: undefined,
495499
}

webview-ui/src/components/settings/AdvancedSettings.tsx

Lines changed: 0 additions & 75 deletions
This file was deleted.

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { ModelInfoView } from "./ModelInfoView"
5353
import { ModelPicker } from "./ModelPicker"
5454
import { TemperatureControl } from "./TemperatureControl"
5555
import { RateLimitSecondsControl } from "./RateLimitSecondsControl"
56+
import { DiffSettingsControl } from "./DiffSettingsControl"
5657
import { ApiErrorMessage } from "./ApiErrorMessage"
5758
import { ThinkingBudget } from "./ThinkingBudget"
5859
import { R1FormatSetting } from "./R1FormatSetting"
@@ -1681,6 +1682,11 @@ const ApiOptions = ({
16811682

16821683
{!fromWelcomeView && (
16831684
<>
1685+
<DiffSettingsControl
1686+
diffEnabled={apiConfiguration.diffEnabled}
1687+
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
1688+
onChange={(field, value) => setApiConfigurationField(field, value)}
1689+
/>
16841690
<TemperatureControl
16851691
value={apiConfiguration?.modelTemperature}
16861692
onChange={handleInputChange("modelTemperature", noTransform)}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React, { useCallback } from "react"
2+
import { Slider } from "@/components/ui"
3+
import { useAppTranslation } from "@/i18n/TranslationContext"
4+
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
5+
6+
interface DiffSettingsControlProps {
7+
diffEnabled?: boolean
8+
fuzzyMatchThreshold?: number
9+
onChange: (field: "diffEnabled" | "fuzzyMatchThreshold", value: any) => void
10+
}
11+
12+
export const DiffSettingsControl: React.FC<DiffSettingsControlProps> = ({
13+
diffEnabled = true,
14+
fuzzyMatchThreshold = 1.0,
15+
onChange,
16+
}) => {
17+
const { t } = useAppTranslation()
18+
19+
const handleDiffEnabledChange = useCallback(
20+
(e: any) => {
21+
onChange("diffEnabled", e.target.checked)
22+
},
23+
[onChange],
24+
)
25+
26+
const handleThresholdChange = useCallback(
27+
(newValue: number[]) => {
28+
onChange("fuzzyMatchThreshold", newValue[0])
29+
},
30+
[onChange],
31+
)
32+
33+
return (
34+
<div className="flex flex-col gap-1">
35+
<div>
36+
<VSCodeCheckbox checked={diffEnabled} onChange={handleDiffEnabledChange}>
37+
<span className="font-medium">{t("settings:advanced.diff.label")}</span>
38+
</VSCodeCheckbox>
39+
<div className="text-vscode-descriptionForeground text-sm">
40+
{t("settings:advanced.diff.description")}
41+
</div>
42+
</div>
43+
44+
{diffEnabled && (
45+
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
46+
<div>
47+
<label className="block font-medium mb-1">
48+
{t("settings:advanced.diff.matchPrecision.label")}
49+
</label>
50+
<div className="flex items-center gap-2">
51+
<Slider
52+
min={0.8}
53+
max={1}
54+
step={0.005}
55+
value={[fuzzyMatchThreshold]}
56+
onValueChange={handleThresholdChange}
57+
/>
58+
<span className="w-10">{Math.round(fuzzyMatchThreshold * 100)}%</span>
59+
</div>
60+
<div className="text-vscode-descriptionForeground text-sm mt-1">
61+
{t("settings:advanced.diff.matchPrecision.description")}
62+
</div>
63+
</div>
64+
</div>
65+
)}
66+
</div>
67+
)
68+
}

webview-ui/src/components/settings/ExperimentalSettings.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import { Section } from "./Section"
1212
import { ExperimentalFeature } from "./ExperimentalFeature"
1313

1414
type ExperimentalSettingsProps = HTMLAttributes<HTMLDivElement> & {
15-
setCachedStateField: SetCachedStateField<
16-
"terminalOutputLineLimit" | "maxOpenTabsContext" | "diffEnabled" | "fuzzyMatchThreshold"
17-
>
15+
setCachedStateField: SetCachedStateField<"terminalOutputLineLimit" | "maxOpenTabsContext">
1816
experiments: Record<ExperimentId, boolean>
1917
setExperimentEnabled: SetExperimentEnabled
2018
}

0 commit comments

Comments
 (0)