Skip to content

Commit 0e1c968

Browse files
committed
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
1 parent d62a260 commit 0e1c968

File tree

6 files changed

+127
-45
lines changed

6 files changed

+127
-45
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", "showEnhancePromptButton"] 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+
showEnhancePromptButton: z.boolean().optional(),
2223
})
2324

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

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+
SHOW_ENHANCE_PROMPT_BUTTON: "showEnhancePromptButton",
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+
SHOW_ENHANCE_PROMPT_BUTTON: { enabled: true },
1921
}
2022

2123
export const experimentDefault = Object.fromEntries(

webview-ui/src/components/chat/ChatTextArea.tsx

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ExtensionMessage } from "@roo/ExtensionMessage"
1010
import { vscode } from "@/utils/vscode"
1111
import { useExtensionState } from "@/context/ExtensionStateContext"
1212
import { useAppTranslation } from "@/i18n/TranslationContext"
13+
import { EXPERIMENT_IDS, experiments } from "@roo/experiments"
1314
import {
1415
ContextMenuOptionType,
1516
getContextMenuOptions,
@@ -86,6 +87,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
8687
togglePinnedApiConfig,
8788
taskHistory,
8889
clineMessages,
90+
experiments: experimentsConfig,
8991
} = useExtensionState()
9092

9193
// Find the ID and display text for the currently selected API configuration
@@ -1109,29 +1111,31 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
11091111
onScroll={() => updateHighlights()}
11101112
/>
11111113

1112-
<div className="absolute top-1 right-1 z-30">
1113-
<StandardTooltip content={t("chat:enhancePrompt")}>
1114-
<button
1115-
aria-label={t("chat:enhancePrompt")}
1116-
disabled={sendingDisabled}
1117-
onClick={!sendingDisabled ? handleEnhancePrompt : undefined}
1118-
className={cn(
1119-
"relative inline-flex items-center justify-center",
1120-
"bg-transparent border-none p-1.5",
1121-
"rounded-md min-w-[28px] min-h-[28px]",
1122-
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
1123-
"transition-all duration-150",
1124-
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
1125-
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
1126-
"active:bg-[rgba(255,255,255,0.1)]",
1127-
!sendingDisabled && "cursor-pointer",
1128-
sendingDisabled &&
1129-
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
1130-
)}>
1131-
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
1132-
</button>
1133-
</StandardTooltip>
1134-
</div>
1114+
{experiments.isEnabled(experimentsConfig, EXPERIMENT_IDS.SHOW_ENHANCE_PROMPT_BUTTON) && (
1115+
<div className="absolute top-1 right-1 z-30">
1116+
<StandardTooltip content={t("chat:enhancePrompt")}>
1117+
<button
1118+
aria-label={t("chat:enhancePrompt")}
1119+
disabled={sendingDisabled}
1120+
onClick={!sendingDisabled ? handleEnhancePrompt : undefined}
1121+
className={cn(
1122+
"relative inline-flex items-center justify-center",
1123+
"bg-transparent border-none p-1.5",
1124+
"rounded-md min-w-[28px] min-h-[28px]",
1125+
"opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground",
1126+
"transition-all duration-150",
1127+
"hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]",
1128+
"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
1129+
"active:bg-[rgba(255,255,255,0.1)]",
1130+
!sendingDisabled && "cursor-pointer",
1131+
sendingDisabled &&
1132+
"opacity-40 cursor-not-allowed grayscale-[30%] hover:bg-transparent hover:border-[rgba(255,255,255,0.08)] active:bg-transparent",
1133+
)}>
1134+
<WandSparkles className={cn("w-4 h-4", isEnhancingPrompt && "animate-spin")} />
1135+
</button>
1136+
</StandardTooltip>
1137+
</div>
1138+
)}
11351139

11361140
{!isEditMode && (
11371141
<div className="absolute bottom-1 right-1 z-30">

webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ describe("ChatTextArea", () => {
7373
},
7474
taskHistory: [],
7575
cwd: "/test/workspace",
76+
experiments: {
77+
showEnhancePromptButton: true,
78+
},
7679
})
7780
})
7881

@@ -83,11 +86,50 @@ describe("ChatTextArea", () => {
8386
openedTabs: [],
8487
taskHistory: [],
8588
cwd: "/test/workspace",
89+
experiments: {
90+
showEnhancePromptButton: true,
91+
},
8692
})
8793
render(<ChatTextArea {...defaultProps} sendingDisabled={true} />)
8894
const enhanceButton = getEnhancePromptButton()
8995
expect(enhanceButton).toHaveClass("cursor-not-allowed")
9096
})
97+
98+
it("should not be visible when experiment is disabled", () => {
99+
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
100+
filePaths: [],
101+
openedTabs: [],
102+
taskHistory: [],
103+
cwd: "/test/workspace",
104+
experiments: {
105+
showEnhancePromptButton: false,
106+
},
107+
})
108+
render(<ChatTextArea {...defaultProps} />)
109+
110+
// The button should not exist in the DOM
111+
const enhanceButton = screen.queryByRole("button", {
112+
name: (_, element) => {
113+
return element.querySelector(".lucide-wand-sparkles") !== null
114+
},
115+
})
116+
expect(enhanceButton).not.toBeInTheDocument()
117+
})
118+
119+
it("should be visible when experiment is enabled", () => {
120+
;(useExtensionState as ReturnType<typeof vi.fn>).mockReturnValue({
121+
filePaths: [],
122+
openedTabs: [],
123+
taskHistory: [],
124+
cwd: "/test/workspace",
125+
experiments: {
126+
showEnhancePromptButton: true,
127+
},
128+
})
129+
render(<ChatTextArea {...defaultProps} />)
130+
const enhanceButton = getEnhancePromptButton()
131+
expect(enhanceButton).toBeInTheDocument()
132+
})
91133
})
92134

93135
describe("handleEnhancePrompt", () => {
@@ -103,6 +145,9 @@ describe("ChatTextArea", () => {
103145
apiConfiguration,
104146
taskHistory: [],
105147
cwd: "/test/workspace",
148+
experiments: {
149+
showEnhancePromptButton: true,
150+
},
106151
})
107152

108153
render(<ChatTextArea {...defaultProps} inputValue="Test prompt" />)
@@ -125,6 +170,9 @@ describe("ChatTextArea", () => {
125170
},
126171
taskHistory: [],
127172
cwd: "/test/workspace",
173+
experiments: {
174+
showEnhancePromptButton: true,
175+
},
128176
})
129177

130178
render(<ChatTextArea {...defaultProps} inputValue="" />)
@@ -147,6 +195,9 @@ describe("ChatTextArea", () => {
147195
},
148196
taskHistory: [],
149197
cwd: "/test/workspace",
198+
experiments: {
199+
showEnhancePromptButton: true,
200+
},
150201
})
151202

152203
render(<ChatTextArea {...defaultProps} inputValue="Test prompt" />)
@@ -174,6 +225,9 @@ describe("ChatTextArea", () => {
174225
},
175226
taskHistory: [],
176227
cwd: "/test/workspace",
228+
experiments: {
229+
showEnhancePromptButton: true,
230+
},
177231
})
178232

179233
rerender(<ChatTextArea {...defaultProps} />)
@@ -275,6 +329,9 @@ describe("ChatTextArea", () => {
275329
filePaths: [],
276330
openedTabs: [],
277331
cwd: mockCwd,
332+
experiments: {
333+
showEnhancePromptButton: true,
334+
},
278335
})
279336
mockConvertToMentionPath.mockClear()
280337
})
@@ -506,6 +563,9 @@ describe("ChatTextArea", () => {
506563
taskHistory: [],
507564
clineMessages: mockClineMessages,
508565
cwd: "/test/workspace",
566+
experiments: {
567+
showEnhancePromptButton: true,
568+
},
509569
})
510570
})
511571

@@ -659,6 +719,9 @@ describe("ChatTextArea", () => {
659719
taskHistory: [],
660720
clineMessages: mixedClineMessages,
661721
cwd: "/test/workspace",
722+
experiments: {
723+
showEnhancePromptButton: true,
724+
},
662725
})
663726

664727
const setInputValue = vi.fn()
@@ -687,6 +750,9 @@ describe("ChatTextArea", () => {
687750
taskHistory: [],
688751
clineMessages: [],
689752
cwd: "/test/workspace",
753+
experiments: {
754+
showEnhancePromptButton: true,
755+
},
690756
})
691757

692758
const setInputValue = vi.fn()
@@ -718,6 +784,9 @@ describe("ChatTextArea", () => {
718784
taskHistory: [],
719785
clineMessages: clineMessagesWithEmpty,
720786
cwd: "/test/workspace",
787+
experiments: {
788+
showEnhancePromptButton: true,
789+
},
721790
})
722791

723792
const setInputValue = vi.fn()
@@ -752,6 +821,9 @@ describe("ChatTextArea", () => {
752821
taskHistory: mockTaskHistory,
753822
clineMessages: [], // No conversation messages
754823
cwd: "/test/workspace",
824+
experiments: {
825+
showEnhancePromptButton: true,
826+
},
755827
})
756828

757829
const setInputValue = vi.fn()
@@ -789,6 +861,9 @@ describe("ChatTextArea", () => {
789861
],
790862
clineMessages: [],
791863
cwd: "/test/workspace",
864+
experiments: {
865+
showEnhancePromptButton: true,
866+
},
792867
})
793868

794869
rerender(<ChatTextArea {...defaultProps} setInputValue={setInputValue} inputValue="" />)
@@ -812,6 +887,9 @@ describe("ChatTextArea", () => {
812887
{ type: "say", say: "user_feedback", text: "Message 2", ts: 2000 },
813888
],
814889
cwd: "/test/workspace",
890+
experiments: {
891+
showEnhancePromptButton: true,
892+
},
815893
})
816894

817895
setInputValue.mockClear()
@@ -929,6 +1007,9 @@ describe("ChatTextArea", () => {
9291007
cwd: "/test/workspace",
9301008
customModes: [],
9311009
customModePrompts: {},
1010+
experiments: {
1011+
showEnhancePromptButton: true,
1012+
},
9321013
})
9331014

9341015
render(<ChatTextArea {...defaultProps} isEditMode={true} />)
@@ -953,6 +1034,9 @@ describe("ChatTextArea", () => {
9531034
openedTabs: [],
9541035
taskHistory: [],
9551036
cwd: "/test/workspace",
1037+
experiments: {
1038+
showEnhancePromptButton: true,
1039+
},
9561040
})
9571041

9581042
render(<ChatTextArea {...defaultProps} isEditMode={false} />)

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

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,16 @@ export const ExperimentalSettings = ({
3939
{Object.entries(experimentConfigsMap)
4040
.filter(([key]) => key in EXPERIMENT_IDS)
4141
.map((config) => {
42-
if (config[0] === "MULTI_FILE_APPLY_DIFF") {
43-
return (
44-
<ExperimentalFeature
45-
key={config[0]}
46-
experimentKey={config[0]}
47-
enabled={experiments[EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF] ?? false}
48-
onChange={(enabled) =>
49-
setExperimentEnabled(EXPERIMENT_IDS.MULTI_FILE_APPLY_DIFF, enabled)
50-
}
51-
/>
52-
)
53-
}
42+
const experimentKey = config[0] as keyof typeof EXPERIMENT_IDS
43+
const experimentId = EXPERIMENT_IDS[experimentKey]
44+
const defaultEnabled = experimentConfigsMap[experimentKey].enabled
45+
5446
return (
5547
<ExperimentalFeature
56-
key={config[0]}
57-
experimentKey={config[0]}
58-
enabled={experiments[EXPERIMENT_IDS[config[0] as keyof typeof EXPERIMENT_IDS]] ?? false}
59-
onChange={(enabled) =>
60-
setExperimentEnabled(
61-
EXPERIMENT_IDS[config[0] as keyof typeof EXPERIMENT_IDS],
62-
enabled,
63-
)
64-
}
48+
key={experimentKey}
49+
experimentKey={experimentKey}
50+
enabled={experiments[experimentId] ?? defaultEnabled}
51+
onChange={(enabled) => setExperimentEnabled(experimentId, enabled)}
6552
/>
6653
)
6754
})}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,10 @@
648648
"MULTI_FILE_APPLY_DIFF": {
649649
"name": "Enable concurrent file edits",
650650
"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."
651+
},
652+
"SHOW_ENHANCE_PROMPT_BUTTON": {
653+
"name": "Show enhance prompt button",
654+
"description": "When enabled, displays the enhance prompt button in the chat input area. This button allows you to improve your prompts using AI assistance."
651655
}
652656
},
653657
"promptCaching": {

0 commit comments

Comments
 (0)