Skip to content

Commit 0f1054e

Browse files
authored
feat(experiments): register PARALLEL_TOOL_EXECUTION flag (internal-only) (#678)
* feat(experiments): register PARALLEL_TOOL_EXECUTION flag (internal-only) * test(ExperimentalSettings): increasing coverage
1 parent b6baa32 commit 0f1054e

5 files changed

Lines changed: 70 additions & 1 deletion

File tree

packages/types/src/experiment.ts

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

9-
export const experimentIds = ["preventFocusDisruption", "imageGeneration", "runSlashCommand", "customTools"] as const
9+
export const experimentIds = [
10+
"preventFocusDisruption",
11+
"imageGeneration",
12+
"runSlashCommand",
13+
"customTools",
14+
"parallelToolExecution",
15+
] as const
1016

1117
export const experimentIdsSchema = z.enum(experimentIds)
1218

@@ -21,6 +27,7 @@ export const experimentsSchema = z.object({
2127
imageGeneration: z.boolean().optional(),
2228
runSlashCommand: z.boolean().optional(),
2329
customTools: z.boolean().optional(),
30+
parallelToolExecution: z.boolean().optional(),
2431
})
2532

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

src/shared/__tests__/experiments.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ describe("experiments", () => {
2121
imageGeneration: false,
2222
runSlashCommand: false,
2323
customTools: false,
24+
parallelToolExecution: false,
2425
}
2526
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(false)
2627
})
@@ -31,6 +32,7 @@ describe("experiments", () => {
3132
imageGeneration: false,
3233
runSlashCommand: false,
3334
customTools: false,
35+
parallelToolExecution: false,
3436
}
3537
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(true)
3638
})
@@ -41,8 +43,27 @@ describe("experiments", () => {
4143
imageGeneration: false,
4244
runSlashCommand: false,
4345
customTools: false,
46+
parallelToolExecution: false,
4447
}
4548
expect(Experiments.isEnabled(experiments, EXPERIMENT_IDS.PREVENT_FOCUS_DISRUPTION)).toBe(false)
4649
})
4750
})
51+
52+
describe("PARALLEL_TOOL_EXECUTION", () => {
53+
it("is configured correctly", () => {
54+
expect(EXPERIMENT_IDS.PARALLEL_TOOL_EXECUTION).toBe("parallelToolExecution")
55+
expect(experimentConfigsMap.PARALLEL_TOOL_EXECUTION).toMatchObject({
56+
enabled: false,
57+
showInSettings: false,
58+
})
59+
})
60+
61+
it("returns false by default", () => {
62+
expect(Experiments.isEnabled({}, "parallelToolExecution")).toBe(false)
63+
})
64+
65+
it("returns true when enabled", () => {
66+
expect(Experiments.isEnabled({ parallelToolExecution: true }, "parallelToolExecution")).toBe(true)
67+
})
68+
})
4869
})

src/shared/experiments.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const EXPERIMENT_IDS = {
55
IMAGE_GENERATION: "imageGeneration",
66
RUN_SLASH_COMMAND: "runSlashCommand",
77
CUSTOM_TOOLS: "customTools",
8+
PARALLEL_TOOL_EXECUTION: "parallelToolExecution",
89
} as const satisfies Record<string, ExperimentId>
910

1011
type _AssertExperimentIds = AssertEqual<Equals<ExperimentId, Values<typeof EXPERIMENT_IDS>>>
@@ -13,13 +14,17 @@ type ExperimentKey = Keys<typeof EXPERIMENT_IDS>
1314

1415
interface ExperimentConfig {
1516
enabled: boolean
17+
/** Defaults to true; set to false to hide from the Settings panel. */
18+
showInSettings?: boolean
1619
}
1720

1821
export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
1922
PREVENT_FOCUS_DISRUPTION: { enabled: false },
2023
IMAGE_GENERATION: { enabled: false },
2124
RUN_SLASH_COMMAND: { enabled: false },
2225
CUSTOM_TOOLS: { enabled: false },
26+
// TODO: add i18n keys (settings:experimental.PARALLEL_TOOL_EXECUTION.name/.description) in the same PR that sets showInSettings: true
27+
PARALLEL_TOOL_EXECUTION: { enabled: false, showInSettings: false },
2328
}
2429

2530
export const experimentDefault = Object.fromEntries(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const ExperimentalSettings = ({
5151
<Section>
5252
{Object.entries(experimentConfigsMap)
5353
.filter(([key]) => key in EXPERIMENT_IDS)
54+
.filter(([, config]) => config.showInSettings !== false)
5455
.map((config) => {
5556
// Use the same translation key pattern as ExperimentalFeature
5657
const experimentKey = config[0]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { render, screen } from "@testing-library/react"
2+
3+
import { experimentDefault } from "@roo/experiments"
4+
5+
import { ExperimentalSettings } from "../ExperimentalSettings"
6+
7+
vi.mock("@src/i18n/TranslationContext", () => ({
8+
useAppTranslation: () => ({
9+
t: (key: string) => key,
10+
}),
11+
}))
12+
13+
describe("ExperimentalSettings", () => {
14+
const defaultProps = {
15+
experiments: experimentDefault,
16+
setExperimentEnabled: vi.fn(),
17+
setImageGenerationProvider: vi.fn(),
18+
setOpenRouterImageApiKey: vi.fn(),
19+
setImageGenerationSelectedModel: vi.fn(),
20+
}
21+
22+
beforeEach(() => {
23+
vi.clearAllMocks()
24+
})
25+
26+
it("does not render internal-only experiment flags", () => {
27+
render(<ExperimentalSettings {...defaultProps} />)
28+
29+
expect(screen.getByText("settings:experimental.PREVENT_FOCUS_DISRUPTION.name")).toBeInTheDocument()
30+
expect(screen.getByText("settings:experimental.RUN_SLASH_COMMAND.name")).toBeInTheDocument()
31+
expect(screen.getByText("settings:experimental.IMAGE_GENERATION.name")).toBeInTheDocument()
32+
expect(screen.getByText("settings:experimental.CUSTOM_TOOLS.name")).toBeInTheDocument()
33+
expect(screen.queryByText("settings:experimental.PARALLEL_TOOL_EXECUTION.name")).not.toBeInTheDocument()
34+
})
35+
})

0 commit comments

Comments
 (0)