Skip to content

Commit 99aed8d

Browse files
committed
refactor: move experimentalPreventFocusDisruption to experiments system
- Remove experimentalPreventFocusDisruption from VSCode settings - Add PREVENT_FOCUS_DISRUPTION to experiments system - Update DiffViewProvider to use experiments instead of VSCode config - Update Task.ts to pass experiments to DiffViewProvider - Add localization entries for the new experiment - Update tests to use the experiments system This change moves the experimental setting from VSCode configuration to the plugin's experimental settings system as requested.
1 parent bdcee80 commit 99aed8d

File tree

10 files changed

+60
-40
lines changed

10 files changed

+60
-40
lines changed

packages/types/src/experiment.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
66
* ExperimentId
77
*/
88

9-
export const experimentIds = ["powerSteering", "multiFileApplyDiff"] as const
9+
export const experimentIds = ["powerSteering", "multiFileApplyDiff", "preventFocusDisruption"] as const
1010

1111
export const experimentIdsSchema = z.enum(experimentIds)
1212

@@ -19,6 +19,7 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
1919
export const experimentsSchema = z.object({
2020
powerSteering: z.boolean().optional(),
2121
multiFileApplyDiff: z.boolean().optional(),
22+
preventFocusDisruption: z.boolean().optional(),
2223
})
2324

2425
export type Experiments = z.infer<typeof experimentsSchema>

src/core/task/Task.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ export class Task extends EventEmitter<ClineEvents> {
288288
if (isMultiFileApplyDiffEnabled) {
289289
this.diffStrategy = new MultiFileSearchReplaceDiffStrategy(this.fuzzyMatchThreshold)
290290
}
291+
292+
// Update DiffViewProvider with experiments
293+
this.diffViewProvider.setExperiments(state.experiments ?? {})
291294
})
292295
}
293296

src/integrations/editor/DiffViewProvider.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { ClineSayTool } from "../../shared/ExtensionMessage"
1414
import { Task } from "../../core/task/Task"
1515
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
1616
import { Package } from "../../shared/package"
17+
import { EXPERIMENT_IDS, experiments as Experiments } from "../../shared/experiments"
18+
import type { Experiments as ExperimentsType } from "@roo-code/types"
1719

1820
import { DecorationController } from "./DecorationController"
1921

@@ -37,8 +39,18 @@ export class DiffViewProvider {
3739
private activeLineController?: DecorationController
3840
private streamedLines: string[] = []
3941
private preDiagnostics: [vscode.Uri, vscode.Diagnostic[]][] = []
42+
private experiments?: ExperimentsType
4043

41-
constructor(private cwd: string) {}
44+
constructor(
45+
private cwd: string,
46+
experiments?: ExperimentsType,
47+
) {
48+
this.experiments = experiments
49+
}
50+
51+
public setExperiments(experiments: ExperimentsType) {
52+
this.experiments = experiments
53+
}
4254

4355
async open(relPath: string): Promise<void> {
4456
this.relPath = relPath
@@ -203,9 +215,9 @@ export class DiffViewProvider {
203215
}
204216

205217
// Check if the experimental setting is enabled
206-
const preventFocusDisruption = vscode.workspace
207-
.getConfiguration(Package.name)
208-
.get<boolean>("experimentalPreventFocusDisruption", false)
218+
const preventFocusDisruption = this.experiments
219+
? Experiments.isEnabled(this.experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)
220+
: false
209221

210222
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
211223
preview: false,
@@ -401,9 +413,9 @@ export class DiffViewProvider {
401413

402414
if (this.documentWasOpen) {
403415
// Check if the experimental setting is enabled
404-
const preventFocusDisruption = vscode.workspace
405-
.getConfiguration(Package.name)
406-
.get<boolean>("experimentalPreventFocusDisruption", false)
416+
const preventFocusDisruption = this.experiments
417+
? Experiments.isEnabled(this.experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)
418+
: false
407419

408420
await vscode.window.showTextDocument(vscode.Uri.file(absolutePath), {
409421
preview: false,
@@ -462,9 +474,9 @@ export class DiffViewProvider {
462474
const uri = vscode.Uri.file(path.resolve(this.cwd, this.relPath))
463475

464476
// Check if the experimental setting is enabled
465-
const preventFocusDisruption = vscode.workspace
466-
.getConfiguration(Package.name)
467-
.get<boolean>("experimentalPreventFocusDisruption", false)
477+
const preventFocusDisruption = this.experiments
478+
? Experiments.isEnabled(this.experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)
479+
: false
468480

469481
// If this diff editor is already open (ie if a previous write file was
470482
// interrupted) then we should activate that instead of opening a new

src/integrations/editor/__tests__/DiffViewProvider.spec.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { DiffViewProvider, DIFF_VIEW_URI_SCHEME, DIFF_VIEW_LABEL_CHANGES } from
22
import * as vscode from "vscode"
33
import * as path from "path"
44
import delay from "delay"
5+
import { EXPERIMENT_IDS } from "../../../shared/experiments"
56

67
// Mock delay
78
vi.mock("delay", () => ({
@@ -425,10 +426,11 @@ describe("DiffViewProvider", () => {
425426

426427
describe("experimentalPreventFocusDisruption setting", () => {
427428
it("should preserve focus when experimentalPreventFocusDisruption is enabled", async () => {
428-
// Mock the configuration to return true for experimentalPreventFocusDisruption
429-
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
430-
get: vi.fn().mockReturnValue(true),
431-
} as any)
429+
// Create a new DiffViewProvider with experiments enabled
430+
const experiments = {
431+
[EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION]: true,
432+
}
433+
diffViewProvider = new DiffViewProvider(mockCwd, experiments)
432434

433435
// Setup mock editor
434436
const mockEditor = {
@@ -482,10 +484,11 @@ describe("DiffViewProvider", () => {
482484
})
483485

484486
it("should not preserve focus when experimentalPreventFocusDisruption is disabled", async () => {
485-
// Mock the configuration to return false for experimentalPreventFocusDisruption
486-
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
487-
get: vi.fn().mockReturnValue(false),
488-
} as any)
487+
// Create a new DiffViewProvider with experiments disabled
488+
const experiments = {
489+
[EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION]: false,
490+
}
491+
diffViewProvider = new DiffViewProvider(mockCwd, experiments)
489492

490493
// Setup mock editor
491494
const mockEditor = {
@@ -539,10 +542,11 @@ describe("DiffViewProvider", () => {
539542
})
540543

541544
it("should preserve focus in saveChanges when experimentalPreventFocusDisruption is enabled", async () => {
542-
// Mock the configuration to return true
543-
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
544-
get: vi.fn().mockReturnValue(true),
545-
} as any)
545+
// Create a new DiffViewProvider with experiments enabled
546+
const experiments = {
547+
[EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION]: true,
548+
}
549+
diffViewProvider = new DiffViewProvider(mockCwd, experiments)
546550

547551
// Setup for saveChanges
548552
;(diffViewProvider as any).relPath = "test.ts"
@@ -571,10 +575,11 @@ describe("DiffViewProvider", () => {
571575
})
572576

573577
it("should preserve focus in revertChanges when experimentalPreventFocusDisruption is enabled", async () => {
574-
// Mock the configuration to return true
575-
vi.mocked(vscode.workspace.getConfiguration).mockReturnValue({
576-
get: vi.fn().mockReturnValue(true),
577-
} as any)
578+
// Create a new DiffViewProvider with experiments enabled
579+
const experiments = {
580+
[EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION]: true,
581+
}
582+
diffViewProvider = new DiffViewProvider(mockCwd, experiments)
578583

579584
// Setup for revertChanges
580585
;(diffViewProvider as any).relPath = "test.ts"

src/package.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,6 @@
386386
"type": "string",
387387
"default": "",
388388
"description": "%settings.autoImportSettingsPath.description%"
389-
},
390-
"roo-cline.experimentalPreventFocusDisruption": {
391-
"type": "boolean",
392-
"default": false,
393-
"description": "%settings.experimentalPreventFocusDisruption.description%"
394389
}
395390
}
396391
}

src/package.nls.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,5 @@
3636
"settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)",
3737
"settings.customStoragePath.description": "Custom storage path. Leave empty to use the default location. Supports absolute paths (e.g. 'D:\\RooCodeStorage')",
3838
"settings.enableCodeActions.description": "Enable Roo Code quick fixes",
39-
"settings.autoImportSettingsPath.description": "Path to a RooCode configuration file to automatically import on extension startup. Supports absolute paths and paths relative to the home directory (e.g. '~/Documents/roo-code-settings.json'). Leave empty to disable auto-import.",
40-
"settings.experimentalPreventFocusDisruption.description": "(Experimental) Prevent file edits from stealing focus. When enabled, diff views and file edits will not disrupt your current work. Files will update in the background without forcing you to switch context."
39+
"settings.autoImportSettingsPath.description": "Path to a RooCode configuration file to automatically import on extension startup. Supports absolute paths and paths relative to the home directory (e.g. '~/Documents/roo-code-settings.json'). Leave empty to disable auto-import."
4140
}

src/shared/__tests__/experiments.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe("experiments", () => {
2828
const experiments: Record<ExperimentId, boolean> = {
2929
powerSteering: false,
3030
multiFileApplyDiff: false,
31+
preventFocusDisruption: false,
3132
}
3233
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(false)
3334
})
@@ -36,6 +37,7 @@ describe("experiments", () => {
3637
const experiments: Record<ExperimentId, boolean> = {
3738
powerSteering: true,
3839
multiFileApplyDiff: false,
40+
preventFocusDisruption: false,
3941
}
4042
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(true)
4143
})
@@ -44,6 +46,7 @@ describe("experiments", () => {
4446
const experiments: Record<ExperimentId, boolean> = {
4547
powerSteering: false,
4648
multiFileApplyDiff: false,
49+
preventFocusDisruption: false,
4750
}
4851
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.POWER_STEERING)).toBe(false)
4952
})

src/shared/experiments.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { AssertEqual, Equals, Keys, Values, ExperimentId, Experiments } fro
33
export const EXPERIMENT_IDS = {
44
MULTI_FILE_APPLY_DIFF: "multiFileApplyDiff",
55
POWER_STEERING: "powerSteering",
6+
PREVENT_FOCUS_DISRUPTION: "preventFocusDisruption",
67
} as const satisfies Record<string, ExperimentId>
78

89
type _AssertExperimentIds = AssertEqual<Equals<ExperimentId, Values<typeof EXPERIMENT_IDS>>>
@@ -16,6 +17,7 @@ interface ExperimentConfig {
1617
export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
1718
MULTI_FILE_APPLY_DIFF: { enabled: false },
1819
POWER_STEERING: { enabled: false },
20+
PREVENT_FOCUS_DISRUPTION: { enabled: false },
1921
}
2022

2123
export const experimentDefault = Object.fromEntries(

webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,8 @@ describe("mergeExtensionState", () => {
222222
apiConfiguration: { modelMaxThinkingTokens: 456, modelTemperature: 0.3 },
223223
experiments: {
224224
powerSteering: true,
225-
marketplace: false,
226-
disableCompletionCommand: false,
227-
concurrentFileReads: true,
228225
multiFileApplyDiff: true,
226+
preventFocusDisruption: false,
229227
} as Record<ExperimentId, boolean>,
230228
}
231229

@@ -238,10 +236,8 @@ describe("mergeExtensionState", () => {
238236

239237
expect(result.experiments).toEqual({
240238
powerSteering: true,
241-
marketplace: false,
242-
disableCompletionCommand: false,
243-
concurrentFileReads: true,
244239
multiFileApplyDiff: true,
240+
preventFocusDisruption: false,
245241
})
246242
})
247243
})

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,10 @@
618618
"MULTI_FILE_APPLY_DIFF": {
619619
"name": "Enable concurrent file edits",
620620
"description": "When enabled, Roo can edit multiple files in a single request. When disabled, Roo must edit files one at a time. Disabling this can help when working with less capable models or when you want more control over file modifications."
621+
},
622+
"PREVENT_FOCUS_DISRUPTION": {
623+
"name": "Prevent focus disruption on file edits",
624+
"description": "When enabled, file edits will not automatically switch focus to the edited file. This helps maintain your current workflow when Roo makes changes to multiple files."
621625
}
622626
},
623627
"promptCaching": {

0 commit comments

Comments
 (0)