Skip to content

Commit

Permalink
Merge pull request #1331 from RooVetGit/browser_tool_enabled
Browse files Browse the repository at this point in the history
Add a checkbox to enable/disable the browser tool
  • Loading branch information
mrubens authored Mar 3, 2025
2 parents 82b6fe6 + 6b0347e commit bf77f46
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 49 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-candles-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"roo-cline": patch
---

Add a checkbox to disable the browser tool
3 changes: 2 additions & 1 deletion src/core/Cline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ export class Cline {
preferredLanguage,
experiments,
enableMcpServerCreation,
browserToolEnabled,
} = (await this.providerRef.deref()?.getState()) ?? {}
const { customModes } = (await this.providerRef.deref()?.getState()) ?? {}
const systemPrompt = await (async () => {
Expand All @@ -956,7 +957,7 @@ export class Cline {
return SYSTEM_PROMPT(
provider.context,
cwd,
this.api.getModel().info.supportsComputerUse ?? false,
(this.api.getModel().info.supportsComputerUse ?? false) && (browserToolEnabled ?? true),
mcpHub,
this.diffStrategy,
browserViewportSize,
Expand Down
9 changes: 9 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
await this.updateGlobalState("maxOpenTabsContext", tabCount)
await this.postStateToWebview()
break
case "browserToolEnabled":
await this.updateGlobalState("browserToolEnabled", message.bool ?? true)
await this.postStateToWebview()
break
case "enhancementApiConfigId":
await this.updateGlobalState("enhancementApiConfigId", message.text)
await this.postStateToWebview()
Expand Down Expand Up @@ -2022,6 +2026,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
autoApprovalEnabled,
experiments,
maxOpenTabsContext,
browserToolEnabled,
} = await this.getState()

const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get<string[]>("allowedCommands") || []
Expand Down Expand Up @@ -2075,6 +2080,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
mcpServers: this.mcpHub?.getAllServers() ?? [],
maxOpenTabsContext: maxOpenTabsContext ?? 20,
cwd: cwd,
browserToolEnabled: browserToolEnabled ?? true,
}
}

Expand Down Expand Up @@ -2214,6 +2220,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
modelMaxTokens,
modelMaxThinkingTokens,
maxOpenTabsContext,
browserToolEnabled,
] = await Promise.all([
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
this.getGlobalState("apiModelId") as Promise<string | undefined>,
Expand Down Expand Up @@ -2298,6 +2305,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.getGlobalState("modelMaxTokens") as Promise<number | undefined>,
this.getGlobalState("anthropicThinking") as Promise<number | undefined>,
this.getGlobalState("maxOpenTabsContext") as Promise<number | undefined>,
this.getGlobalState("browserToolEnabled") as Promise<boolean | undefined>,
])

let apiProvider: ApiProvider
Expand Down Expand Up @@ -2431,6 +2439,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
customModes,
maxOpenTabsContext: maxOpenTabsContext ?? 20,
openRouterUseMiddleOutTransform: openRouterUseMiddleOutTransform ?? true,
browserToolEnabled: browserToolEnabled ?? true,
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/core/webview/__tests__/ClineProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ describe("ClineProvider", () => {
customModes: [],
experiments: experimentDefault,
maxOpenTabsContext: 20,
browserToolEnabled: true,
}

const message: ExtensionMessage = {
Expand Down Expand Up @@ -591,6 +592,21 @@ describe("ClineProvider", () => {
expect(provider.configManager.setModeConfig).toHaveBeenCalledWith("architect", "new-id")
})

test("handles browserToolEnabled setting", async () => {
await provider.resolveWebviewView(mockWebviewView)
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]

// Test browserToolEnabled
await messageHandler({ type: "browserToolEnabled", bool: true })
expect(mockContext.globalState.update).toHaveBeenCalledWith("browserToolEnabled", true)
expect(mockPostMessage).toHaveBeenCalled()

// Verify state includes browserToolEnabled
const state = await provider.getState()
expect(state).toHaveProperty("browserToolEnabled")
expect(state.browserToolEnabled).toBe(true) // Default value should be true
})

test("handles request delay settings messages", async () => {
await provider.resolveWebviewView(mockWebviewView)
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
Expand Down
2 changes: 2 additions & 0 deletions src/shared/ExtensionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface ExtensionMessage {
| "updateCustomMode"
| "deleteCustomMode"
| "currentCheckpointUpdated"
| "browserToolEnabled"
text?: string
action?:
| "chatButtonClicked"
Expand Down Expand Up @@ -103,6 +104,7 @@ export interface ExtensionState {
alwaysAllowMcp?: boolean
alwaysApproveResubmit?: boolean
alwaysAllowModeSwitch?: boolean
browserToolEnabled?: boolean
requestDelaySeconds: number
rateLimitSeconds: number // Minimum time between successive requests (0 = disabled)
uriScheme?: string
Expand Down
1 change: 1 addition & 0 deletions src/shared/WebviewMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export interface WebviewMessage {
| "checkpointRestore"
| "deleteMcpServer"
| "maxOpenTabsContext"
| "browserToolEnabled"
text?: string
disabled?: boolean
askResponse?: ClineAskResponse
Expand Down
1 change: 1 addition & 0 deletions src/shared/globalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,4 @@ export type GlobalStateKey =
| "anthropicThinking" // TODO: Rename to `modelMaxThinkingTokens`.
| "mistralCodestralUrl"
| "maxOpenTabsContext"
| "browserToolEnabled" // Setting to enable/disable the browser tool
122 changes: 74 additions & 48 deletions webview-ui/src/components/settings/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
alwaysAllowModeSwitch,
alwaysAllowWrite,
alwaysApproveResubmit,
browserToolEnabled,
browserViewportSize,
enableCheckpoints,
diffEnabled,
Expand Down Expand Up @@ -140,6 +141,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
vscode.postMessage({ type: "alwaysAllowBrowser", bool: alwaysAllowBrowser })
vscode.postMessage({ type: "alwaysAllowMcp", bool: alwaysAllowMcp })
vscode.postMessage({ type: "allowedCommands", commands: allowedCommands ?? [] })
vscode.postMessage({ type: "browserToolEnabled", bool: browserToolEnabled })
vscode.postMessage({ type: "soundEnabled", bool: soundEnabled })
vscode.postMessage({ type: "soundVolume", value: soundVolume })
vscode.postMessage({ type: "diffEnabled", bool: diffEnabled })
Expand Down Expand Up @@ -537,59 +539,83 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone },
<div style={{ marginBottom: 40 }}>
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Browser Settings</h3>
<div style={{ marginBottom: 15 }}>
<label style={{ fontWeight: "500", display: "block", marginBottom: 5 }}>Viewport size</label>
<div className="dropdown-container">
<Dropdown
value={browserViewportSize}
onChange={(value: unknown) => {
setCachedStateField("browserViewportSize", (value as DropdownOption).value)
}}
style={{ width: "100%" }}
options={[
{ value: "1280x800", label: "Large Desktop (1280x800)" },
{ value: "900x600", label: "Small Desktop (900x600)" },
{ value: "768x1024", label: "Tablet (768x1024)" },
{ value: "360x640", label: "Mobile (360x640)" },
]}
/>
</div>
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
Select the viewport size for browser interactions. This affects how websites are displayed
and interacted with.
<VSCodeCheckbox
checked={browserToolEnabled}
onChange={(e: any) => setCachedStateField("browserToolEnabled", e.target.checked)}>
<span style={{ fontWeight: "500" }}>Enable browser tool</span>
</VSCodeCheckbox>
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
When enabled, Roo can use a browser to interact with websites when using models that support
computer use.
</p>
</div>
{browserToolEnabled && (
<div
style={{
marginLeft: 0,
paddingLeft: 10,
borderLeft: "2px solid var(--vscode-button-background)",
}}>
<div style={{ marginBottom: 15 }}>
<label style={{ fontWeight: "500", display: "block", marginBottom: 5 }}>
Viewport size
</label>
<div className="dropdown-container">
<Dropdown
value={browserViewportSize}
onChange={(value: unknown) => {
setCachedStateField("browserViewportSize", (value as DropdownOption).value)
}}
style={{ width: "100%" }}
options={[
{ value: "1280x800", label: "Large Desktop (1280x800)" },
{ value: "900x600", label: "Small Desktop (900x600)" },
{ value: "768x1024", label: "Tablet (768x1024)" },
{ value: "360x640", label: "Mobile (360x640)" },
]}
/>
</div>
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
Select the viewport size for browser interactions. This affects how websites are
displayed and interacted with.
</p>
</div>

<div style={{ marginBottom: 15 }}>
<div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
<span style={{ fontWeight: "500" }}>Screenshot quality</span>
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
<input
type="range"
min="1"
max="100"
step="1"
value={screenshotQuality ?? 75}
className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background"
onChange={(e) => setCachedStateField("screenshotQuality", parseInt(e.target.value))}
/>
<span style={{ ...sliderLabelStyle }}>{screenshotQuality ?? 75}%</span>
<div style={{ marginBottom: 15 }}>
<div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
<span style={{ fontWeight: "500" }}>Screenshot quality</span>
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
<input
type="range"
min="1"
max="100"
step="1"
value={screenshotQuality ?? 75}
className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background"
onChange={(e) =>
setCachedStateField("screenshotQuality", parseInt(e.target.value))
}
/>
<span style={{ ...sliderLabelStyle }}>{screenshotQuality ?? 75}%</span>
</div>
</div>
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
Adjust the WebP quality of browser screenshots. Higher values provide clearer
screenshots but increase token usage.
</p>
</div>
</div>
<p
style={{
fontSize: "12px",
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
Adjust the WebP quality of browser screenshots. Higher values provide clearer screenshots
but increase token usage.
</p>
</div>
)}
</div>

<div style={{ marginBottom: 40 }}>
Expand Down
3 changes: 3 additions & 0 deletions webview-ui/src/context/ExtensionStateContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ExtensionStateContextType extends ExtensionState {
setAlwaysAllowBrowser: (value: boolean) => void
setAlwaysAllowMcp: (value: boolean) => void
setAlwaysAllowModeSwitch: (value: boolean) => void
setBrowserToolEnabled: (value: boolean) => void
setShowAnnouncement: (value: boolean) => void
setAllowedCommands: (value: string[]) => void
setSoundEnabled: (value: boolean) => void
Expand Down Expand Up @@ -128,6 +129,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
customModes: [],
maxOpenTabsContext: 20,
cwd: "",
browserToolEnabled: true,
})

const [didHydrateState, setDidHydrateState] = useState(false)
Expand Down Expand Up @@ -265,6 +267,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setAutoApprovalEnabled: (value) => setState((prevState) => ({ ...prevState, autoApprovalEnabled: value })),
setCustomModes: (value) => setState((prevState) => ({ ...prevState, customModes: value })),
setMaxOpenTabsContext: (value) => setState((prevState) => ({ ...prevState, maxOpenTabsContext: value })),
setBrowserToolEnabled: (value) => setState((prevState) => ({ ...prevState, browserToolEnabled: value })),
}

return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>
Expand Down

0 comments on commit bf77f46

Please sign in to comment.