mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
feat: make enhance prompt button optional through experimental setting
- Add SHOW_ENHANCE_PROMPT_BUTTON experiment ID - Update ChatTextArea to conditionally render button based on experiment - Add translation keys for the new experimental setting - Update tests to handle the new experiment configuration - Default the setting to enabled to maintain current behavior Fixes #6207
This commit is contained in:
parent
d62a260576
commit
0e1c968fba
6 changed files with 127 additions and 45 deletions
|
|
@ -6,7 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
|
|||
* ExperimentId
|
||||
*/
|
||||
|
||||
export const experimentIds = ["powerSteering", "multiFileApplyDiff"] as const
|
||||
export const experimentIds = ["powerSteering", "multiFileApplyDiff", "showEnhancePromptButton"] as const
|
||||
|
||||
export const experimentIdsSchema = z.enum(experimentIds)
|
||||
|
||||
|
|
@ -19,6 +19,7 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
|
|||
export const experimentsSchema = z.object({
|
||||
powerSteering: z.boolean().optional(),
|
||||
multiFileApplyDiff: z.boolean().optional(),
|
||||
showEnhancePromptButton: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export type Experiments = z.infer<typeof experimentsSchema>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type { AssertEqual, Equals, Keys, Values, ExperimentId, Experiments } fro
|
|||
export const EXPERIMENT_IDS = {
|
||||
MULTI_FILE_APPLY_DIFF: "multiFileApplyDiff",
|
||||
POWER_STEERING: "powerSteering",
|
||||
SHOW_ENHANCE_PROMPT_BUTTON: "showEnhancePromptButton",
|
||||
} as const satisfies Record<string, ExperimentId>
|
||||
|
||||
type _AssertExperimentIds = AssertEqual<Equals<ExperimentId, Values<typeof EXPERIMENT_IDS>>>
|
||||
|
|
@ -16,6 +17,7 @@ interface ExperimentConfig {
|
|||
export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
|
||||
MULTI_FILE_APPLY_DIFF: { enabled: false },
|
||||
POWER_STEERING: { enabled: false },
|
||||
SHOW_ENHANCE_PROMPT_BUTTON: { enabled: true },
|
||||
}
|
||||
|
||||
export const experimentDefault = Object.fromEntries(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { ExtensionMessage } from "@roo/ExtensionMessage"
|
|||
import { vscode } from "@/utils/vscode"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { useAppTranslation } from "@/i18n/TranslationContext"
|
||||
import { EXPERIMENT_IDS, experiments } from "@roo/experiments"
|
||||
import {
|
||||
ContextMenuOptionType,
|
||||
getContextMenuOptions,
|
||||
|
|
@ -86,6 +87,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
togglePinnedApiConfig,
|
||||
taskHistory,
|
||||
clineMessages,
|
||||
experiments: experimentsConfig,
|
||||
} = useExtensionState()
|
||||
|
||||
// Find the ID and display text for the currently selected API configuration
|
||||
|
|
@ -1109,29 +1111,31 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
onScroll={() => updateHighlights()}
|
||||
/>
|
||||
|
||||
<div className="absolute top-1 right-1 z-30">
|
||||
<StandardTooltip content={t("chat:enhancePrompt")}>
|
||||
<button
|
||||
aria-label={t("chat:enhancePrompt")}
|
||||
disabled={sendingDisabled}
|
||||
onClick={!sendingDisabled ? handleEnhancePrompt : undefined}
|
||||
className={cn(
|
||||
"relative inline-flex items-center justify-center",
|
||||
"bg-transparent border-none p-1.5",
|
||||
"rounded-md min-w-[28px] min-h-[28px]",
|
||||
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
|
||||
"transition-all duration-150",
|
||||
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
!sendingDisabled && "cursor-pointer",
|
||||
sendingDisabled &&
|
||||
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
|
||||
)}>
|
||||
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
|
||||
</button>
|
||||
</StandardTooltip>
|
||||
</div>
|
||||
{experiments.isEnabled(experimentsConfig, EXPERIMENT_IDS.SHOW_ENHANCE_PROMPT_BUTTON) && (
|
||||
<div className="absolute top-1 right-1 z-30">
|
||||
<StandardTooltip content={t("chat:enhancePrompt")}>
|
||||
<button
|
||||
aria-label={t("chat:enhancePrompt")}
|
||||
disabled={sendingDisabled}
|
||||
onClick={!sendingDisabled ? handleEnhancePrompt : undefined}
|
||||
className={cn(
|
||||
"relative inline-flex items-center justify-center",
|
||||
"bg-transparent border-none p-1.5",
|
||||
"rounded-md min-w-[28px] min-h-[28px]",
|
||||
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
|
||||
"transition-all duration-150",
|
||||
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
|
||||
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
|
||||
"active:bg-[rgba(255,255,255,0.1)]",
|
||||
!sendingDisabled && "cursor-pointer",
|
||||
sendingDisabled &&
|
||||
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
|
||||
)}>
|
||||
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
|
||||
</button>
|
||||
</StandardTooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isEditMode && (
|
||||
<div className="absolute bottom-1 right-1 z-30">
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ describe("ChatTextArea", () => {
|
|||
},
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -83,11 +86,50 @@ describe("ChatTextArea", () => {
|
|||
openedTabs: [],
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
render(<ChatTextArea {...defaultProps} sendingDisabled={true} />)
|
||||
const enhanceButton = getEnhancePromptButton()
|
||||
expect(enhanceButton).toHaveClass("cursor-not-allowed")
|
||||
})
|
||||
|
||||
it("should not be visible when experiment is disabled", () => {
|
||||
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
|
||||
filePaths: [],
|
||||
openedTabs: [],
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: false,
|
||||
},
|
||||
})
|
||||
render(<ChatTextArea {...defaultProps} />)
|
||||
|
||||
// The button should not exist in the DOM
|
||||
const enhanceButton = screen.queryByRole("button", {
|
||||
name: (_, element) => {
|
||||
return element.querySelector(".lucide-wand-sparkles") !== null
|
||||
},
|
||||
})
|
||||
expect(enhanceButton).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("should be visible when experiment is enabled", () => {
|
||||
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
|
||||
filePaths: [],
|
||||
openedTabs: [],
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
render(<ChatTextArea {...defaultProps} />)
|
||||
const enhanceButton = getEnhancePromptButton()
|
||||
expect(enhanceButton).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("handleEnhancePrompt", () => {
|
||||
|
|
@ -103,6 +145,9 @@ describe("ChatTextArea", () => {
|
|||
apiConfiguration,
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
render(<ChatTextArea {...defaultProps} inputValue="Test prompt" />)
|
||||
|
|
@ -125,6 +170,9 @@ describe("ChatTextArea", () => {
|
|||
},
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
render(<ChatTextArea {...defaultProps} inputValue="" />)
|
||||
|
|
@ -147,6 +195,9 @@ describe("ChatTextArea", () => {
|
|||
},
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
render(<ChatTextArea {...defaultProps} inputValue="Test prompt" />)
|
||||
|
|
@ -174,6 +225,9 @@ describe("ChatTextArea", () => {
|
|||
},
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
rerender(<ChatTextArea {...defaultProps} />)
|
||||
|
|
@ -275,6 +329,9 @@ describe("ChatTextArea", () => {
|
|||
filePaths: [],
|
||||
openedTabs: [],
|
||||
cwd: mockCwd,
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
mockConvertToMentionPath.mockClear()
|
||||
})
|
||||
|
|
@ -506,6 +563,9 @@ describe("ChatTextArea", () => {
|
|||
taskHistory: [],
|
||||
clineMessages: mockClineMessages,
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -659,6 +719,9 @@ describe("ChatTextArea", () => {
|
|||
taskHistory: [],
|
||||
clineMessages: mixedClineMessages,
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
const setInputValue = vi.fn()
|
||||
|
|
@ -687,6 +750,9 @@ describe("ChatTextArea", () => {
|
|||
taskHistory: [],
|
||||
clineMessages: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
const setInputValue = vi.fn()
|
||||
|
|
@ -718,6 +784,9 @@ describe("ChatTextArea", () => {
|
|||
taskHistory: [],
|
||||
clineMessages: clineMessagesWithEmpty,
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
const setInputValue = vi.fn()
|
||||
|
|
@ -752,6 +821,9 @@ describe("ChatTextArea", () => {
|
|||
taskHistory: mockTaskHistory,
|
||||
clineMessages: [], // No conversation messages
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
const setInputValue = vi.fn()
|
||||
|
|
@ -789,6 +861,9 @@ describe("ChatTextArea", () => {
|
|||
],
|
||||
clineMessages: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
rerender(<ChatTextArea {...defaultProps} setInputValue={setInputValue} inputValue="" />)
|
||||
|
|
@ -812,6 +887,9 @@ describe("ChatTextArea", () => {
|
|||
{ type: "say", say: "user_feedback", text: "Message 2", ts: 2000 },
|
||||
],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
setInputValue.mockClear()
|
||||
|
|
@ -929,6 +1007,9 @@ describe("ChatTextArea", () => {
|
|||
cwd: "/test/workspace",
|
||||
customModes: [],
|
||||
customModePrompts: {},
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
render(<ChatTextArea {...defaultProps} isEditMode={true} />)
|
||||
|
|
@ -953,6 +1034,9 @@ describe("ChatTextArea", () => {
|
|||
openedTabs: [],
|
||||
taskHistory: [],
|
||||
cwd: "/test/workspace",
|
||||
experiments: {
|
||||
showEnhancePromptButton: true,
|
||||
},
|
||||
})
|
||||
|
||||
render(<ChatTextArea {...defaultProps} isEditMode={false} />)
|
||||
|
|
|
|||
|
|
@ -39,29 +39,16 @@ export const ExperimentalSettings = ({
|
|||
{Object.entries(experimentConfigsMap)
|
||||
.filter(([key]) => key in EXPERIMENT_IDS)
|
||||
.map((config) => {
|
||||
if (config[0] === "MULTI_FILE_APPLY_DIFF") {
|
||||
return (
|
||||
<ExperimentalFeature
|
||||
key={config[0]}
|
||||
experimentKey={config[0]}
|
||||
enabled={experiments[EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF] ?? false}
|
||||
onChange={(enabled) =>
|
||||
setExperimentEnabled(EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF, enabled)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
const experimentKey = config[0] as keyof typeof EXPERIMENT_IDS
|
||||
const experimentId = EXPERIMENT_IDS[experimentKey]
|
||||
const defaultEnabled = experimentConfigsMap[experimentKey].enabled
|
||||
|
||||
return (
|
||||
<ExperimentalFeature
|
||||
key={config[0]}
|
||||
experimentKey={config[0]}
|
||||
enabled={experiments[EXPERIMENT_IDS[config[0] as keyof typeof EXPERIMENT_IDS]] ?? false}
|
||||
onChange={(enabled) =>
|
||||
setExperimentEnabled(
|
||||
EXPERIMENT_IDS[config[0] as keyof typeof EXPERIMENT_IDS],
|
||||
enabled,
|
||||
)
|
||||
}
|
||||
key={experimentKey}
|
||||
experimentKey={experimentKey}
|
||||
enabled={experiments[experimentId] ?? defaultEnabled}
|
||||
onChange={(enabled) => setExperimentEnabled(experimentId, enabled)}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -648,6 +648,10 @@
|
|||
"MULTI_FILE_APPLY_DIFF": {
|
||||
"name": "Enable concurrent file edits",
|
||||
"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."
|
||||
},
|
||||
"SHOW_ENHANCE_PROMPT_BUTTON": {
|
||||
"name": "Show enhance prompt button",
|
||||
"description": "When enabled, displays the enhance prompt button in the chat input area. This button allows you to improve your prompts using AI assistance."
|
||||
}
|
||||
},
|
||||
"promptCaching": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue