mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
726 lines
24 KiB
TypeScript
726 lines
24 KiB
TypeScript
import { VSCodeButton, VSCodeCheckbox, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
|
import { memo, useEffect, useState } from "react"
|
|
import { useExtensionState } from "../../context/ExtensionStateContext"
|
|
import { validateApiConfiguration, validateModelId } from "../../utils/validate"
|
|
import { vscode } from "../../utils/vscode"
|
|
import ApiOptions from "./ApiOptions"
|
|
import ExperimentalFeature from "./ExperimentalFeature"
|
|
import { EXPERIMENT_IDS, experimentConfigsMap } from "../../../../src/shared/experiments"
|
|
import ApiConfigManager from "./ApiConfigManager"
|
|
import { Dropdown } from "vscrui"
|
|
import type { DropdownOption } from "vscrui"
|
|
|
|
type SettingsViewProps = {
|
|
onDone: () => void
|
|
}
|
|
|
|
const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|
const {
|
|
apiConfiguration,
|
|
version,
|
|
alwaysAllowReadOnly,
|
|
setAlwaysAllowReadOnly,
|
|
alwaysAllowWrite,
|
|
setAlwaysAllowWrite,
|
|
alwaysAllowExecute,
|
|
setAlwaysAllowExecute,
|
|
alwaysAllowBrowser,
|
|
setAlwaysAllowBrowser,
|
|
alwaysAllowMcp,
|
|
setAlwaysAllowMcp,
|
|
soundEnabled,
|
|
setSoundEnabled,
|
|
soundVolume,
|
|
setSoundVolume,
|
|
diffEnabled,
|
|
setDiffEnabled,
|
|
browserViewportSize,
|
|
setBrowserViewportSize,
|
|
openRouterModels,
|
|
glamaModels,
|
|
setAllowedCommands,
|
|
allowedCommands,
|
|
fuzzyMatchThreshold,
|
|
setFuzzyMatchThreshold,
|
|
writeDelayMs,
|
|
setWriteDelayMs,
|
|
screenshotQuality,
|
|
setScreenshotQuality,
|
|
terminalOutputLineLimit,
|
|
setTerminalOutputLineLimit,
|
|
mcpEnabled,
|
|
alwaysApproveResubmit,
|
|
setAlwaysApproveResubmit,
|
|
requestDelaySeconds,
|
|
setRequestDelaySeconds,
|
|
currentApiConfigName,
|
|
listApiConfigMeta,
|
|
experiments,
|
|
setExperimentEnabled,
|
|
alwaysAllowModeSwitch,
|
|
setAlwaysAllowModeSwitch,
|
|
} = useExtensionState()
|
|
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
|
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
|
const [commandInput, setCommandInput] = useState("")
|
|
|
|
const handleSubmit = () => {
|
|
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
|
const modelIdValidationResult = validateModelId(apiConfiguration, glamaModels, openRouterModels)
|
|
|
|
setApiErrorMessage(apiValidationResult)
|
|
setModelIdErrorMessage(modelIdValidationResult)
|
|
if (!apiValidationResult && !modelIdValidationResult) {
|
|
vscode.postMessage({
|
|
type: "apiConfiguration",
|
|
apiConfiguration,
|
|
})
|
|
vscode.postMessage({ type: "alwaysAllowReadOnly", bool: alwaysAllowReadOnly })
|
|
vscode.postMessage({ type: "alwaysAllowWrite", bool: alwaysAllowWrite })
|
|
vscode.postMessage({ type: "alwaysAllowExecute", bool: alwaysAllowExecute })
|
|
vscode.postMessage({ type: "alwaysAllowBrowser", bool: alwaysAllowBrowser })
|
|
vscode.postMessage({ type: "alwaysAllowMcp", bool: alwaysAllowMcp })
|
|
vscode.postMessage({ type: "allowedCommands", commands: allowedCommands ?? [] })
|
|
vscode.postMessage({ type: "soundEnabled", bool: soundEnabled })
|
|
vscode.postMessage({ type: "soundVolume", value: soundVolume })
|
|
vscode.postMessage({ type: "diffEnabled", bool: diffEnabled })
|
|
vscode.postMessage({ type: "browserViewportSize", text: browserViewportSize })
|
|
vscode.postMessage({ type: "fuzzyMatchThreshold", value: fuzzyMatchThreshold ?? 1.0 })
|
|
vscode.postMessage({ type: "writeDelayMs", value: writeDelayMs })
|
|
vscode.postMessage({ type: "screenshotQuality", value: screenshotQuality ?? 75 })
|
|
vscode.postMessage({ type: "terminalOutputLineLimit", value: terminalOutputLineLimit ?? 500 })
|
|
vscode.postMessage({ type: "mcpEnabled", bool: mcpEnabled })
|
|
vscode.postMessage({ type: "alwaysApproveResubmit", bool: alwaysApproveResubmit })
|
|
vscode.postMessage({ type: "requestDelaySeconds", value: requestDelaySeconds })
|
|
vscode.postMessage({ type: "currentApiConfigName", text: currentApiConfigName })
|
|
vscode.postMessage({
|
|
type: "upsertApiConfiguration",
|
|
text: currentApiConfigName,
|
|
apiConfiguration,
|
|
})
|
|
|
|
vscode.postMessage({
|
|
type: "updateExperimental",
|
|
values: experiments,
|
|
})
|
|
|
|
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch })
|
|
onDone()
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
setApiErrorMessage(undefined)
|
|
setModelIdErrorMessage(undefined)
|
|
}, [apiConfiguration])
|
|
|
|
// Initial validation on mount
|
|
useEffect(() => {
|
|
const apiValidationResult = validateApiConfiguration(apiConfiguration)
|
|
const modelIdValidationResult = validateModelId(apiConfiguration, glamaModels, openRouterModels)
|
|
setApiErrorMessage(apiValidationResult)
|
|
setModelIdErrorMessage(modelIdValidationResult)
|
|
}, [apiConfiguration, glamaModels, openRouterModels])
|
|
|
|
const handleResetState = () => {
|
|
vscode.postMessage({ type: "resetState" })
|
|
}
|
|
|
|
const handleAddCommand = () => {
|
|
const currentCommands = allowedCommands ?? []
|
|
if (commandInput && !currentCommands.includes(commandInput)) {
|
|
const newCommands = [...currentCommands, commandInput]
|
|
setAllowedCommands(newCommands)
|
|
setCommandInput("")
|
|
vscode.postMessage({
|
|
type: "allowedCommands",
|
|
commands: newCommands,
|
|
})
|
|
}
|
|
}
|
|
|
|
const sliderLabelStyle = {
|
|
minWidth: "45px",
|
|
textAlign: "right" as const,
|
|
lineHeight: "20px",
|
|
paddingBottom: "2px",
|
|
}
|
|
|
|
const sliderStyle = {
|
|
flexGrow: 1,
|
|
maxWidth: "80%",
|
|
accentColor: "var(--vscode-button-background)",
|
|
height: "2px",
|
|
}
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
position: "fixed",
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
padding: "10px 0px 0px 20px",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
overflow: "hidden",
|
|
}}>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
marginBottom: "17px",
|
|
paddingRight: 17,
|
|
}}>
|
|
<h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>Settings</h3>
|
|
<VSCodeButton onClick={handleSubmit}>Done</VSCodeButton>
|
|
</div>
|
|
<div
|
|
style={{ flexGrow: 1, overflowY: "scroll", paddingRight: 8, display: "flex", flexDirection: "column" }}>
|
|
<div style={{ marginBottom: 40 }}>
|
|
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Provider Settings</h3>
|
|
<div style={{ marginBottom: 15 }}>
|
|
<ApiConfigManager
|
|
currentApiConfigName={currentApiConfigName}
|
|
listApiConfigMeta={listApiConfigMeta}
|
|
onSelectConfig={(configName: string) => {
|
|
vscode.postMessage({
|
|
type: "loadApiConfiguration",
|
|
text: configName,
|
|
})
|
|
}}
|
|
onDeleteConfig={(configName: string) => {
|
|
vscode.postMessage({
|
|
type: "deleteApiConfiguration",
|
|
text: configName,
|
|
})
|
|
}}
|
|
onRenameConfig={(oldName: string, newName: string) => {
|
|
vscode.postMessage({
|
|
type: "renameApiConfiguration",
|
|
values: { oldName, newName },
|
|
apiConfiguration,
|
|
})
|
|
}}
|
|
onUpsertConfig={(configName: string) => {
|
|
vscode.postMessage({
|
|
type: "upsertApiConfiguration",
|
|
text: configName,
|
|
apiConfiguration,
|
|
})
|
|
}}
|
|
/>
|
|
<ApiOptions apiErrorMessage={apiErrorMessage} modelIdErrorMessage={modelIdErrorMessage} />
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 40 }}>
|
|
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Auto-Approve Settings</h3>
|
|
<p style={{ fontSize: "12px", marginBottom: 15, color: "var(--vscode-descriptionForeground)" }}>
|
|
The following settings allow Roo to automatically perform operations without requiring approval.
|
|
Enable these settings only if you fully trust the AI and understand the associated security
|
|
risks.
|
|
</p>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowReadOnly}
|
|
onChange={(e: any) => setAlwaysAllowReadOnly(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve read-only operations</span>
|
|
</VSCodeCheckbox>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
When enabled, Roo will automatically view directory contents and read files without
|
|
requiring you to click the Approve button.
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowWrite}
|
|
onChange={(e: any) => setAlwaysAllowWrite(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve write operations</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Automatically create and edit files without requiring approval
|
|
</p>
|
|
{alwaysAllowWrite && (
|
|
<div
|
|
style={{
|
|
marginTop: 10,
|
|
paddingLeft: 10,
|
|
borderLeft: "2px solid var(--vscode-button-background)",
|
|
}}>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="5000"
|
|
step="100"
|
|
value={writeDelayMs}
|
|
onChange={(e) => setWriteDelayMs(parseInt(e.target.value))}
|
|
style={{
|
|
flex: 1,
|
|
accentColor: "var(--vscode-button-background)",
|
|
height: "2px",
|
|
}}
|
|
/>
|
|
<span style={{ minWidth: "45px", textAlign: "left" }}>{writeDelayMs}ms</span>
|
|
</div>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
Delay after writes to allow diagnostics to detect potential problems
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowBrowser}
|
|
onChange={(e: any) => setAlwaysAllowBrowser(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve browser actions</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Automatically perform browser actions without requiring approval
|
|
<br />
|
|
Note: Only applies when the model supports computer use
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysApproveResubmit}
|
|
onChange={(e: any) => setAlwaysApproveResubmit(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always retry failed API requests</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Automatically retry failed API requests when server returns an error response
|
|
</p>
|
|
{alwaysApproveResubmit && (
|
|
<div
|
|
style={{
|
|
marginTop: 10,
|
|
paddingLeft: 10,
|
|
borderLeft: "2px solid var(--vscode-button-background)",
|
|
}}>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
|
<input
|
|
type="range"
|
|
min="5"
|
|
max="100"
|
|
step="1"
|
|
value={requestDelaySeconds}
|
|
onChange={(e) => setRequestDelaySeconds(parseInt(e.target.value))}
|
|
style={{
|
|
flex: 1,
|
|
accentColor: "var(--vscode-button-background)",
|
|
height: "2px",
|
|
}}
|
|
/>
|
|
<span style={{ minWidth: "45px", textAlign: "left" }}>{requestDelaySeconds}s</span>
|
|
</div>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
Delay before retrying the request
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 5 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowMcp}
|
|
onChange={(e: any) => setAlwaysAllowMcp(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve MCP tools</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Enable auto-approval of individual MCP tools in the MCP Servers view (requires both this
|
|
setting and the tool's individual "Always allow" checkbox)
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowModeSwitch}
|
|
onChange={(e: any) => setAlwaysAllowModeSwitch(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve mode switching & task creation</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Automatically switch between different AI modes and create new tasks without requiring
|
|
approval
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={alwaysAllowExecute}
|
|
onChange={(e: any) => setAlwaysAllowExecute(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Always approve allowed execute operations</span>
|
|
</VSCodeCheckbox>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Automatically execute allowed terminal commands without requiring approval
|
|
</p>
|
|
|
|
{alwaysAllowExecute && (
|
|
<div
|
|
style={{
|
|
marginTop: 10,
|
|
paddingLeft: 10,
|
|
borderLeft: "2px solid var(--vscode-button-background)",
|
|
}}>
|
|
<span style={{ fontWeight: "500" }}>Allowed Auto-Execute Commands</span>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
Command prefixes that can be auto-executed when "Always approve execute operations"
|
|
is enabled.
|
|
</p>
|
|
|
|
<div style={{ display: "flex", gap: "5px", marginTop: "10px" }}>
|
|
<VSCodeTextField
|
|
value={commandInput}
|
|
onInput={(e: any) => setCommandInput(e.target.value)}
|
|
onKeyDown={(e: any) => {
|
|
if (e.key === "Enter") {
|
|
e.preventDefault()
|
|
handleAddCommand()
|
|
}
|
|
}}
|
|
placeholder="Enter command prefix (e.g., 'git ')"
|
|
style={{ flexGrow: 1 }}
|
|
/>
|
|
<VSCodeButton onClick={handleAddCommand}>Add</VSCodeButton>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
marginTop: "10px",
|
|
display: "flex",
|
|
flexWrap: "wrap",
|
|
gap: "5px",
|
|
}}>
|
|
{(allowedCommands ?? []).map((cmd, index) => (
|
|
<div
|
|
key={index}
|
|
style={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: "5px",
|
|
backgroundColor: "var(--vscode-button-secondaryBackground)",
|
|
padding: "2px 6px",
|
|
borderRadius: "4px",
|
|
border: "1px solid var(--vscode-button-secondaryBorder)",
|
|
height: "24px",
|
|
}}>
|
|
<span>{cmd}</span>
|
|
<VSCodeButton
|
|
appearance="icon"
|
|
style={{
|
|
padding: 0,
|
|
margin: 0,
|
|
height: "20px",
|
|
width: "20px",
|
|
minWidth: "20px",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
color: "var(--vscode-button-foreground)",
|
|
}}
|
|
onClick={() => {
|
|
const newCommands = (allowedCommands ?? []).filter(
|
|
(_, i) => i !== index,
|
|
)
|
|
setAllowedCommands(newCommands)
|
|
vscode.postMessage({
|
|
type: "allowedCommands",
|
|
commands: newCommands,
|
|
})
|
|
}}>
|
|
<span className="codicon codicon-close" />
|
|
</VSCodeButton>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<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) => {
|
|
setBrowserViewportSize((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}
|
|
onChange={(e) => setScreenshotQuality(parseInt(e.target.value))}
|
|
style={{
|
|
...sliderStyle,
|
|
}}
|
|
/>
|
|
<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>
|
|
|
|
<div style={{ marginBottom: 40 }}>
|
|
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Notification Settings</h3>
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox checked={soundEnabled} onChange={(e: any) => setSoundEnabled(e.target.checked)}>
|
|
<span style={{ fontWeight: "500" }}>Enable sound effects</span>
|
|
</VSCodeCheckbox>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
When enabled, Roo will play sound effects for notifications and events.
|
|
</p>
|
|
</div>
|
|
{soundEnabled && (
|
|
<div
|
|
style={{
|
|
marginLeft: 0,
|
|
paddingLeft: 10,
|
|
borderLeft: "2px solid var(--vscode-button-background)",
|
|
}}>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
|
|
<span style={{ fontWeight: "500", minWidth: "100px" }}>Volume</span>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="1"
|
|
step="0.01"
|
|
value={soundVolume ?? 0.5}
|
|
onChange={(e) => setSoundVolume(parseFloat(e.target.value))}
|
|
style={{
|
|
flexGrow: 1,
|
|
accentColor: "var(--vscode-button-background)",
|
|
height: "2px",
|
|
}}
|
|
aria-label="Volume"
|
|
/>
|
|
<span style={{ minWidth: "35px", textAlign: "left" }}>
|
|
{((soundVolume ?? 0.5) * 100).toFixed(0)}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 40 }}>
|
|
<h3 style={{ color: "var(--vscode-foreground)", margin: "0 0 15px 0" }}>Advanced Settings</h3>
|
|
<div style={{ marginBottom: 15 }}>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
|
|
<span style={{ fontWeight: "500" }}>Terminal output limit</span>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
|
|
<input
|
|
type="range"
|
|
min="100"
|
|
max="5000"
|
|
step="100"
|
|
value={terminalOutputLineLimit ?? 500}
|
|
onChange={(e) => setTerminalOutputLineLimit(parseInt(e.target.value))}
|
|
style={{ ...sliderStyle }}
|
|
/>
|
|
<span style={{ ...sliderLabelStyle }}>{terminalOutputLineLimit ?? 500}</span>
|
|
</div>
|
|
</div>
|
|
<p style={{ fontSize: "12px", marginTop: "5px", color: "var(--vscode-descriptionForeground)" }}>
|
|
Maximum number of lines to include in terminal output when executing commands. When exceeded
|
|
lines will be removed from the middle, saving tokens.
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: 15 }}>
|
|
<VSCodeCheckbox
|
|
checked={diffEnabled}
|
|
onChange={(e: any) => {
|
|
setDiffEnabled(e.target.checked)
|
|
if (!e.target.checked) {
|
|
// Reset experimental strategy when diffs are disabled
|
|
setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, false)
|
|
}
|
|
}}>
|
|
<span style={{ fontWeight: "500" }}>Enable editing through diffs</span>
|
|
</VSCodeCheckbox>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
When enabled, Roo will be able to edit files more quickly and will automatically reject
|
|
truncated full-file writes. Works best with the latest Claude 3.5 Sonnet model.
|
|
</p>
|
|
|
|
{diffEnabled && (
|
|
<div style={{ marginTop: 10 }}>
|
|
<ExperimentalFeature
|
|
key={EXPERIMENT_IDS.DIFF_STRATEGY}
|
|
{...experimentConfigsMap.DIFF_STRATEGY}
|
|
enabled={experiments[EXPERIMENT_IDS.DIFF_STRATEGY] ?? false}
|
|
onChange={(enabled) => setExperimentEnabled(EXPERIMENT_IDS.DIFF_STRATEGY, enabled)}
|
|
/>
|
|
<div
|
|
style={{ display: "flex", flexDirection: "column", gap: "5px", marginTop: "15px" }}>
|
|
<span style={{ fontWeight: "500" }}>Match precision</span>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
|
|
<input
|
|
type="range"
|
|
min="0.8"
|
|
max="1"
|
|
step="0.005"
|
|
value={fuzzyMatchThreshold ?? 1.0}
|
|
onChange={(e) => {
|
|
setFuzzyMatchThreshold(parseFloat(e.target.value))
|
|
}}
|
|
style={{
|
|
...sliderStyle,
|
|
}}
|
|
/>
|
|
<span style={{ ...sliderLabelStyle }}>
|
|
{Math.round((fuzzyMatchThreshold || 1) * 100)}%
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
This slider controls how precisely code sections must match when applying diffs.
|
|
Lower values allow more flexible matching but increase the risk of incorrect
|
|
replacements. Use values below 100% with extreme caution.
|
|
</p>
|
|
</div>
|
|
)}
|
|
{Object.entries(experimentConfigsMap)
|
|
.filter((config) => config[0] !== "DIFF_STRATEGY")
|
|
.map((config) => (
|
|
<ExperimentalFeature
|
|
key={config[0]}
|
|
{...config[1]}
|
|
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,
|
|
)
|
|
}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
textAlign: "center",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
fontSize: "12px",
|
|
lineHeight: "1.2",
|
|
marginTop: "auto",
|
|
padding: "10px 8px 15px 0px",
|
|
}}>
|
|
<p style={{ wordWrap: "break-word", margin: 0, padding: 0 }}>
|
|
If you have any questions or feedback, feel free to open an issue at{" "}
|
|
<VSCodeLink href="https://github.com/RooVetGit/Roo-Code" style={{ display: "inline" }}>
|
|
github.com/RooVetGit/Roo-Code
|
|
</VSCodeLink>{" "}
|
|
or join{" "}
|
|
<VSCodeLink href="https://www.reddit.com/r/RooCode/" style={{ display: "inline" }}>
|
|
reddit.com/r/RooCode
|
|
</VSCodeLink>
|
|
</p>
|
|
<p style={{ fontStyle: "italic", margin: "10px 0 0 0", padding: 0, marginBottom: 100 }}>
|
|
v{version}
|
|
</p>
|
|
|
|
<p
|
|
style={{
|
|
fontSize: "12px",
|
|
marginTop: "5px",
|
|
color: "var(--vscode-descriptionForeground)",
|
|
}}>
|
|
This will reset all global state and secret storage in the extension.
|
|
</p>
|
|
|
|
<VSCodeButton
|
|
onClick={handleResetState}
|
|
appearance="secondary"
|
|
style={{ marginTop: "5px", width: "auto" }}>
|
|
Reset State
|
|
</VSCodeButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default memo(SettingsView)
|