mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-22 13:21:07 -05:00
feat: implement experimental features system
- Add experiments.ts to manage experimental features - Refactor experimental diff strategy into experiments system - Add UI components for managing experimental features - Add tests for experimental tools - Update system prompts to handle experiments
This commit is contained in:
@@ -108,7 +108,7 @@ export interface ExtensionState {
|
||||
mode: Mode
|
||||
modeApiConfigs?: Record<Mode, string>
|
||||
enhancementApiConfigId?: string
|
||||
experimentalDiffStrategy?: boolean
|
||||
experiments: Record<string, boolean> // Map of experiment IDs to their enabled state
|
||||
autoApprovalEnabled?: boolean
|
||||
customModes: ModeConfig[]
|
||||
toolRequirements?: Record<string, boolean> // Map of tool names to their requirements (e.g. {"apply_diff": true} if diffEnabled)
|
||||
|
||||
@@ -75,7 +75,7 @@ export interface WebviewMessage {
|
||||
| "getSystemPrompt"
|
||||
| "systemPrompt"
|
||||
| "enhancementApiConfigId"
|
||||
| "experimentalDiffStrategy"
|
||||
| "updateExperimental"
|
||||
| "autoApprovalEnabled"
|
||||
| "updateCustomMode"
|
||||
| "deleteCustomMode"
|
||||
|
||||
@@ -14,6 +14,12 @@ describe("isToolAllowedForMode", () => {
|
||||
roleDefinition: "You are a CSS editor",
|
||||
groups: ["read", ["edit", { fileRegex: "\\.css$" }], "browser"],
|
||||
},
|
||||
{
|
||||
slug: "test-exp-mode",
|
||||
name: "Test Exp Mode",
|
||||
roleDefinition: "You are an experimental tester",
|
||||
groups: ["read", "edit", "browser"],
|
||||
},
|
||||
]
|
||||
|
||||
it("allows always available tools", () => {
|
||||
@@ -240,6 +246,87 @@ describe("isToolAllowedForMode", () => {
|
||||
|
||||
expect(isToolAllowedForMode("write_to_file", "markdown-editor", customModes, toolRequirements)).toBe(false)
|
||||
})
|
||||
|
||||
describe("experimental tools", () => {
|
||||
it("disables tools when experiment is disabled", () => {
|
||||
const experiments = {
|
||||
search_and_replace: false,
|
||||
insert_code_block: false,
|
||||
}
|
||||
|
||||
expect(
|
||||
isToolAllowedForMode(
|
||||
"search_and_replace",
|
||||
"test-exp-mode",
|
||||
customModes,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
),
|
||||
).toBe(false)
|
||||
|
||||
expect(
|
||||
isToolAllowedForMode(
|
||||
"insert_code_block",
|
||||
"test-exp-mode",
|
||||
customModes,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
),
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it("allows tools when experiment is enabled", () => {
|
||||
const experiments = {
|
||||
search_and_replace: true,
|
||||
insert_code_block: true,
|
||||
}
|
||||
|
||||
expect(
|
||||
isToolAllowedForMode(
|
||||
"search_and_replace",
|
||||
"test-exp-mode",
|
||||
customModes,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
),
|
||||
).toBe(true)
|
||||
|
||||
expect(
|
||||
isToolAllowedForMode(
|
||||
"insert_code_block",
|
||||
"test-exp-mode",
|
||||
customModes,
|
||||
undefined,
|
||||
undefined,
|
||||
experiments,
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("allows non-experimental tools when experiments are disabled", () => {
|
||||
const experiments = {
|
||||
search_and_replace: false,
|
||||
insert_code_block: false,
|
||||
}
|
||||
|
||||
expect(
|
||||
isToolAllowedForMode("read_file", "markdown-editor", customModes, undefined, undefined, experiments),
|
||||
).toBe(true)
|
||||
expect(
|
||||
isToolAllowedForMode(
|
||||
"write_to_file",
|
||||
"markdown-editor",
|
||||
customModes,
|
||||
undefined,
|
||||
{ path: "test.md" },
|
||||
experiments,
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("FileRestrictionError", () => {
|
||||
|
||||
63
src/shared/experiments.ts
Normal file
63
src/shared/experiments.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
export interface ExperimentConfig {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export const EXPERIMENT_IDS = {
|
||||
DIFF_STRATEGY: "experimentalDiffStrategy",
|
||||
SEARCH_AND_REPLACE: "search_and_replace",
|
||||
INSERT_BLOCK: "insert_code_block",
|
||||
} as const
|
||||
|
||||
export type ExperimentId = keyof typeof EXPERIMENT_IDS
|
||||
|
||||
export const experimentConfigsMap: Record<ExperimentId, ExperimentConfig> = {
|
||||
DIFF_STRATEGY: {
|
||||
id: EXPERIMENT_IDS.DIFF_STRATEGY,
|
||||
name: "Use experimental unified diff strategy",
|
||||
description:
|
||||
"Enable the experimental unified diff strategy. This strategy might reduce the number of retries caused by model errors but may cause unexpected behavior or incorrect edits. Only enable if you understand the risks and are willing to carefully review all changes.",
|
||||
enabled: false,
|
||||
},
|
||||
SEARCH_AND_REPLACE: {
|
||||
id: EXPERIMENT_IDS.SEARCH_AND_REPLACE,
|
||||
name: "Use experimental search and replace tool",
|
||||
description:
|
||||
"Enable the experimental Search and Replace tool. This tool allows Roo to search and replace term. Can be run multiple search and replace in sequence at once request.",
|
||||
enabled: false,
|
||||
},
|
||||
INSERT_BLOCK: {
|
||||
id: EXPERIMENT_IDS.INSERT_BLOCK,
|
||||
name: "Use experimental insert block tool",
|
||||
|
||||
description:
|
||||
"Enable the experimental insert block tool. This tool allows Roo to insert code blocks into files. Can be insert multiple blocks at once.",
|
||||
enabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Keep the array version for backward compatibility
|
||||
export const experimentConfigs = Object.values(experimentConfigsMap)
|
||||
export const experimentDefault = Object.fromEntries(
|
||||
Object.entries(experimentConfigsMap).map(([_, config]) => [config.id, config.enabled]),
|
||||
)
|
||||
|
||||
export const experiments = {
|
||||
get: (id: ExperimentId): ExperimentConfig | undefined => {
|
||||
return experimentConfigsMap[id]
|
||||
},
|
||||
isEnabled: (experimentsConfig: Record<string, boolean>, id: string): boolean => {
|
||||
return experimentsConfig[id] ?? experimentDefault[id]
|
||||
},
|
||||
} as const
|
||||
|
||||
// Expose experiment details for UI - pre-compute from map for better performance
|
||||
export const experimentLabels = Object.fromEntries(
|
||||
Object.values(experimentConfigsMap).map((config) => [config.id, config.name]),
|
||||
) as Record<string, string>
|
||||
|
||||
export const experimentDescriptions = Object.fromEntries(
|
||||
Object.values(experimentConfigsMap).map((config) => [config.id, config.description]),
|
||||
) as Record<string, string>
|
||||
@@ -160,12 +160,19 @@ export function isToolAllowedForMode(
|
||||
customModes: ModeConfig[],
|
||||
toolRequirements?: Record<string, boolean>,
|
||||
toolParams?: Record<string, any>, // All tool parameters
|
||||
experiments?: Record<string, boolean>,
|
||||
): boolean {
|
||||
// Always allow these tools
|
||||
if (ALWAYS_AVAILABLE_TOOLS.includes(tool as any)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (experiments && tool in experiments) {
|
||||
if (!experiments[tool]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Check tool requirements if any exist
|
||||
if (toolRequirements && tool in toolRequirements) {
|
||||
if (!toolRequirements[tool]) {
|
||||
|
||||
Reference in New Issue
Block a user