From a679c95412a76d63f809d2f9f5aa5fd621e50d29 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Fri, 14 Mar 2025 09:45:31 -0400 Subject: [PATCH] Create new context management section in settings --- .../components/settings/AdvancedSettings.tsx | 75 +------------- .../settings/ContextManagementSettings.tsx | 99 +++++++++++++++++++ .../src/components/settings/SettingsView.tsx | 17 +++- .../ContextManagementSettings.test.tsx | 58 +++++++++++ 4 files changed, 172 insertions(+), 77 deletions(-) create mode 100644 webview-ui/src/components/settings/ContextManagementSettings.tsx create mode 100644 webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx diff --git a/webview-ui/src/components/settings/AdvancedSettings.tsx b/webview-ui/src/components/settings/AdvancedSettings.tsx index c04f28f88e..e25366331e 100644 --- a/webview-ui/src/components/settings/AdvancedSettings.tsx +++ b/webview-ui/src/components/settings/AdvancedSettings.tsx @@ -13,29 +13,16 @@ import { Section } from "./Section" type AdvancedSettingsProps = HTMLAttributes & { rateLimitSeconds: number - terminalOutputLineLimit?: number - maxOpenTabsContext: number diffEnabled?: boolean fuzzyMatchThreshold?: number - showRooIgnoredFiles?: boolean - setCachedStateField: SetCachedStateField< - | "rateLimitSeconds" - | "terminalOutputLineLimit" - | "maxOpenTabsContext" - | "diffEnabled" - | "fuzzyMatchThreshold" - | "showRooIgnoredFiles" - > + setCachedStateField: SetCachedStateField<"rateLimitSeconds" | "diffEnabled" | "fuzzyMatchThreshold"> experiments: Record setExperimentEnabled: SetExperimentEnabled } export const AdvancedSettings = ({ rateLimitSeconds, - terminalOutputLineLimit, - maxOpenTabsContext, diffEnabled, fuzzyMatchThreshold, - showRooIgnoredFiles, setCachedStateField, experiments, setExperimentEnabled, @@ -71,52 +58,6 @@ export const AdvancedSettings = ({

Minimum time between API requests.

-
-
- Terminal output limit -
- - setCachedStateField("terminalOutputLineLimit", parseInt(e.target.value)) - } - className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background" - /> - {terminalOutputLineLimit ?? 500} -
-
-

- Maximum number of lines to include in terminal output when executing commands. When exceeded - lines will be removed from the middle, saving tokens. -

-
- -
-
- Open tabs context limit -
- setCachedStateField("maxOpenTabsContext", parseInt(e.target.value))} - className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background" - /> - {maxOpenTabsContext ?? 20} -
-
-

- Maximum number of VSCode open tabs to include in context. Higher values provide more context but - increase token usage. -

-
-
)}
- -
- { - setCachedStateField("showRooIgnoredFiles", e.target.checked) - }}> - Show .rooignore'd files in lists and searches - -

- When enabled, files matching patterns in .rooignore will be shown in lists with a lock symbol. - When disabled, these files will be completely hidden from file lists and searches. -

-
) diff --git a/webview-ui/src/components/settings/ContextManagementSettings.tsx b/webview-ui/src/components/settings/ContextManagementSettings.tsx new file mode 100644 index 0000000000..f8563071f2 --- /dev/null +++ b/webview-ui/src/components/settings/ContextManagementSettings.tsx @@ -0,0 +1,99 @@ +import { HTMLAttributes } from "react" +import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react" +import { Database } from "lucide-react" + +import { cn } from "@/lib/utils" + +import { SetCachedStateField } from "./types" +import { sliderLabelStyle } from "./styles" +import { SectionHeader } from "./SectionHeader" +import { Section } from "./Section" + +type ContextManagementSettingsProps = HTMLAttributes & { + terminalOutputLineLimit?: number + maxOpenTabsContext: number + showRooIgnoredFiles?: boolean + setCachedStateField: SetCachedStateField<"terminalOutputLineLimit" | "maxOpenTabsContext" | "showRooIgnoredFiles"> +} + +export const ContextManagementSettings = ({ + terminalOutputLineLimit, + maxOpenTabsContext, + showRooIgnoredFiles, + setCachedStateField, + className, + ...props +}: ContextManagementSettingsProps) => { + return ( +
+ +
+ +
Context Management
+
+
+ +
+
+
+ Terminal output limit +
+ + setCachedStateField("terminalOutputLineLimit", parseInt(e.target.value)) + } + className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background" + /> + {terminalOutputLineLimit ?? 500} +
+
+

+ Maximum number of lines to include in terminal output when executing commands. When exceeded + lines will be removed from the middle, saving tokens. +

+
+ +
+
+ Open tabs context limit +
+ setCachedStateField("maxOpenTabsContext", parseInt(e.target.value))} + className="h-2 focus:outline-0 w-4/5 accent-vscode-button-background" + /> + {maxOpenTabsContext ?? 20} +
+
+

+ Maximum number of VSCode open tabs to include in context. Higher values provide more context but + increase token usage. +

+
+ +
+ { + setCachedStateField("showRooIgnoredFiles", e.target.checked) + }}> + Show .rooignore'd files in lists and searches + +

+ When enabled, files matching patterns in .rooignore will be shown in lists with a lock symbol. + When disabled, these files will be completely hidden from file lists and searches. +

+
+
+
+ ) +} diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index d49ed2d03a..c267acfee1 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -11,6 +11,7 @@ import { AlertTriangle, } from "lucide-react" +import { Database } from "lucide-react" import { ExperimentId } from "../../../../src/shared/experiments" import { TelemetrySetting } from "../../../../src/shared/TelemetrySetting" import { ApiConfiguration } from "../../../../src/shared/api" @@ -39,6 +40,7 @@ import { AutoApproveSettings } from "./AutoApproveSettings" import { BrowserSettings } from "./BrowserSettings" import { CheckpointSettings } from "./CheckpointSettings" import { NotificationSettings } from "./NotificationSettings" +import { ContextManagementSettings } from "./ContextManagementSettings" import { AdvancedSettings } from "./AdvancedSettings" import { SettingsFooter } from "./SettingsFooter" import { Section } from "./Section" @@ -230,6 +232,7 @@ const SettingsView = forwardRef(({ onDone }, const browserRef = useRef(null) const checkpointRef = useRef(null) const notificationsRef = useRef(null) + const contextRef = useRef(null) const advancedRef = useRef(null) const experimentalRef = useRef(null) @@ -242,6 +245,7 @@ const SettingsView = forwardRef(({ onDone }, { id: "browser", icon: SquareMousePointer, ref: browserRef }, { id: "checkpoint", icon: GitBranch, ref: checkpointRef }, { id: "notifications", icon: Bell, ref: notificationsRef }, + { id: "context", icon: Database, ref: contextRef }, { id: "advanced", icon: Cog, ref: advancedRef }, { id: "experimental", icon: FlaskConical, ref: experimentalRef }, ], @@ -255,6 +259,7 @@ const SettingsView = forwardRef(({ onDone }, { ref: browserRef, id: "browser" }, { ref: checkpointRef, id: "checkpoint" }, { ref: notificationsRef, id: "notifications" }, + { ref: contextRef, id: "context" }, { ref: advancedRef, id: "advanced" }, { ref: experimentalRef, id: "experimental" }, ] @@ -401,14 +406,20 @@ const SettingsView = forwardRef(({ onDone }, /> +
+ +
+
{ + const defaultProps = { + terminalOutputLineLimit: 500, + maxOpenTabsContext: 20, + showRooIgnoredFiles: false, + setCachedStateField: jest.fn(), + } + + beforeEach(() => { + jest.clearAllMocks() + }) + + it("renders all controls", () => { + render() + + // Terminal output limit + expect(screen.getByText("Terminal output limit")).toBeInTheDocument() + expect(screen.getByRole("slider", { name: /Terminal output limit/i })).toHaveValue("500") + + // Open tabs context limit + expect(screen.getByText("Open tabs context limit")).toBeInTheDocument() + expect(screen.getByRole("slider", { name: /Open tabs context limit/i })).toHaveValue("20") + + // Show .rooignore'd files + expect(screen.getByText("Show .rooignore'd files in lists and searches")).toBeInTheDocument() + expect(screen.getByRole("checkbox")).not.toBeChecked() + }) + + it("updates terminal output limit", () => { + render() + + const slider = screen.getByRole("slider", { name: /Terminal output limit/i }) + fireEvent.change(slider, { target: { value: "1000" } }) + + expect(defaultProps.setCachedStateField).toHaveBeenCalledWith("terminalOutputLineLimit", 1000) + }) + + it("updates open tabs context limit", () => { + render() + + const slider = screen.getByRole("slider", { name: /Open tabs context limit/i }) + fireEvent.change(slider, { target: { value: "50" } }) + + expect(defaultProps.setCachedStateField).toHaveBeenCalledWith("maxOpenTabsContext", 50) + }) + + it("updates show rooignored files setting", () => { + render() + + const checkbox = screen.getByRole("checkbox") + fireEvent.click(checkbox) + + expect(defaultProps.setCachedStateField).toHaveBeenCalledWith("showRooIgnoredFiles", true) + }) +})