Skip to content

Commit d5457aa

Browse files
hannesrudolphdaniel-lxs
authored andcommitted
fix: address PR #5582 review feedback
- Standardize default max diagnostic messages to 50 across all files - Extract diagnostic settings to centralized constants and helper functions - Add comprehensive documentation for diagnostic settings - Update UI to always show max diagnostic messages slider - Add unit tests for ContextManagementSettings component - Improve code organization and maintainability
1 parent 0325eaa commit d5457aa

File tree

11 files changed

+196
-53
lines changed

11 files changed

+196
-53
lines changed

packages/types/src/global-settings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,15 @@ export const globalSettingsSchema = z.object({
7272
autoCondenseContextPercent: z.number().optional(),
7373
maxConcurrentFileReads: z.number().optional(),
7474

75+
/**
76+
* Whether to include diagnostic messages (errors, warnings) in tool outputs
77+
* @default true
78+
*/
7579
includeDiagnosticMessages: z.boolean().optional(),
80+
/**
81+
* Maximum number of diagnostic messages to include in tool outputs
82+
* @default 50
83+
*/
7684
maxDiagnosticMessages: z.number().optional(),
7785

7886
browserToolEnabled: z.boolean().optional(),
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Constants for diagnostic settings
3+
*/
4+
5+
/**
6+
* Default value for whether to include diagnostic messages in tool outputs
7+
*/
8+
export const DEFAULT_INCLUDE_DIAGNOSTIC_MESSAGES = true
9+
10+
/**
11+
* Default maximum number of diagnostic messages to include in tool outputs
12+
*/
13+
export const DEFAULT_MAX_DIAGNOSTIC_MESSAGES = 50

src/core/tools/applyDiffTool.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { formatResponse } from "../prompts/responses"
1212
import { fileExistsAtPath } from "../../utils/fs"
1313
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
1414
import { unescapeHtmlEntities } from "../../utils/text-normalization"
15+
import { getDiagnosticSettings } from "./helpers/diagnosticSettings"
1516

1617
export async function applyDiffToolLegacy(
1718
cline: Task,
@@ -142,10 +143,8 @@ export async function applyDiffToolLegacy(
142143
cline.consecutiveMistakeCount = 0
143144
cline.consecutiveMistakeCountForApplyDiff.delete(relPath)
144145

145-
// Get diagnostic settings from state
146-
const state = await cline.providerRef?.deref()?.getState()
147-
const includeDiagnosticMessages = state?.includeDiagnosticMessages ?? true
148-
const maxDiagnosticMessages = state?.maxDiagnosticMessages
146+
// Get diagnostic settings
147+
const { includeDiagnosticMessages, maxDiagnosticMessages } = await getDiagnosticSettings(cline)
149148

150149
// Update DiffViewProvider with diagnostic settings
151150
cline.diffViewProvider.updateDiagnosticSettings(includeDiagnosticMessages, maxDiagnosticMessages)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Task } from "../../task/Task"
2+
import {
3+
DEFAULT_INCLUDE_DIAGNOSTIC_MESSAGES,
4+
DEFAULT_MAX_DIAGNOSTIC_MESSAGES,
5+
} from "../../constants/diagnosticSettings"
6+
7+
/**
8+
* Retrieves diagnostic settings from the provider state
9+
* @param cline - The Task instance
10+
* @returns Object containing diagnostic settings with defaults
11+
*/
12+
export async function getDiagnosticSettings(cline: Task): Promise<{
13+
includeDiagnosticMessages: boolean
14+
maxDiagnosticMessages: number
15+
}> {
16+
const state = await cline.providerRef?.deref()?.getState()
17+
18+
return {
19+
includeDiagnosticMessages: state?.includeDiagnosticMessages ?? DEFAULT_INCLUDE_DIAGNOSTIC_MESSAGES,
20+
maxDiagnosticMessages: state?.maxDiagnosticMessages ?? DEFAULT_MAX_DIAGNOSTIC_MESSAGES,
21+
}
22+
}

src/core/tools/insertContentTool.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
1111
import { fileExistsAtPath } from "../../utils/fs"
1212
import { insertGroups } from "../diff/insert-groups"
1313
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
14+
import { getDiagnosticSettings } from "./helpers/diagnosticSettings"
1415

1516
export async function insertContentTool(
1617
cline: Task,
@@ -99,14 +100,11 @@ export async function insertContentTool(
99100
cline.diffViewProvider.editType = fileExists ? "modify" : "create"
100101
cline.diffViewProvider.originalContent = fileContent
101102

102-
// Update diagnostic settings from global state
103-
const state = await cline.providerRef?.deref()?.getState()
104-
if (state) {
105-
cline.diffViewProvider.updateDiagnosticSettings(
106-
state.includeDiagnosticMessages ?? true,
107-
state.maxDiagnosticMessages ?? 5,
108-
)
109-
}
103+
// Get diagnostic settings
104+
const { includeDiagnosticMessages, maxDiagnosticMessages } = await getDiagnosticSettings(cline)
105+
106+
// Update DiffViewProvider with diagnostic settings
107+
cline.diffViewProvider.updateDiagnosticSettings(includeDiagnosticMessages, maxDiagnosticMessages)
110108
const lines = fileExists ? fileContent.split("\n") : []
111109

112110
const updatedContent = insertGroups(lines, [

src/core/tools/searchAndReplaceTool.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { getReadablePath } from "../../utils/path"
1212
import { fileExistsAtPath } from "../../utils/fs"
1313
import { RecordSource } from "../context-tracking/FileContextTrackerTypes"
1414
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
15+
import { getDiagnosticSettings } from "./helpers/diagnosticSettings"
1516

1617
/**
1718
* Tool for performing search and replace operations on files
@@ -191,14 +192,11 @@ export async function searchAndReplaceTool(
191192
cline.diffViewProvider.editType = "modify"
192193
cline.diffViewProvider.originalContent = fileContent
193194

194-
// Update diagnostic settings from global state
195-
const state = await cline.providerRef?.deref()?.getState()
196-
if (state) {
197-
cline.diffViewProvider.updateDiagnosticSettings(
198-
state.includeDiagnosticMessages ?? true,
199-
state.maxDiagnosticMessages ?? 5,
200-
)
201-
}
195+
// Get diagnostic settings
196+
const { includeDiagnosticMessages, maxDiagnosticMessages } = await getDiagnosticSettings(cline)
197+
198+
// Update DiffViewProvider with diagnostic settings
199+
cline.diffViewProvider.updateDiagnosticSettings(includeDiagnosticMessages, maxDiagnosticMessages)
202200

203201
// Generate and validate diff
204202
const diff = formatResponse.createPrettyPatch(validRelPath, fileContent, newContent)

src/core/tools/writeToFileTool.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { isPathOutsideWorkspace } from "../../utils/pathUtils"
1414
import { detectCodeOmission } from "../../integrations/editor/detect-omission"
1515
import { unescapeHtmlEntities } from "../../utils/text-normalization"
1616
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
17+
import { getDiagnosticSettings } from "./helpers/diagnosticSettings"
1718

1819
export async function writeToFileTool(
1920
cline: Task,
@@ -97,10 +98,8 @@ export async function writeToFileTool(
9798
isProtected: isWriteProtected,
9899
}
99100

100-
// Get diagnostic settings from state
101-
const state = await cline.providerRef?.deref()?.getState()
102-
const includeDiagnosticMessages = state?.includeDiagnosticMessages ?? true
103-
const maxDiagnosticMessages = state?.maxDiagnosticMessages
101+
// Get diagnostic settings
102+
const { includeDiagnosticMessages, maxDiagnosticMessages } = await getDiagnosticSettings(cline)
104103

105104
// Update DiffViewProvider with diagnostic settings
106105
cline.diffViewProvider.updateDiagnosticSettings(includeDiagnosticMessages, maxDiagnosticMessages)

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import { WebviewMessage } from "../../shared/WebviewMessage"
7171
import { EMBEDDING_MODEL_PROFILES } from "../../shared/embeddingModels"
7272
import { ProfileValidator } from "../../shared/ProfileValidator"
7373
import { getWorkspaceGitInfo } from "../../utils/git"
74+
import { DEFAULT_INCLUDE_DIAGNOSTIC_MESSAGES, DEFAULT_MAX_DIAGNOSTIC_MESSAGES } from "../constants/diagnosticSettings"
7475

7576
/**
7677
* https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
@@ -1727,8 +1728,8 @@ export class ClineProvider
17271728
},
17281729
profileThresholds: stateValues.profileThresholds ?? {},
17291730
// Add diagnostic message settings
1730-
includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true,
1731-
maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? 5,
1731+
includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? DEFAULT_INCLUDE_DIAGNOSTIC_MESSAGES,
1732+
maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? DEFAULT_MAX_DIAGNOSTIC_MESSAGES,
17321733
}
17331734
}
17341735

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

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -217,27 +217,25 @@ export const ContextManagementSettings = ({
217217
</div>
218218
</div>
219219

220-
{includeDiagnosticMessages && (
221-
<div>
222-
<span className="block font-medium mb-1">
223-
{t("settings:contextManagement.diagnostics.maxMessages.label")}
224-
</span>
225-
<div className="flex items-center gap-2">
226-
<Slider
227-
min={1}
228-
max={100}
229-
step={1}
230-
value={[maxDiagnosticMessages ?? 50]}
231-
onValueChange={([value]) => setCachedStateField("maxDiagnosticMessages", value)}
232-
data-testid="max-diagnostic-messages-slider"
233-
/>
234-
<span className="w-10">{maxDiagnosticMessages ?? 50}</span>
235-
</div>
236-
<div className="text-vscode-descriptionForeground text-sm mt-1">
237-
{t("settings:contextManagement.diagnostics.maxMessages.description")}
238-
</div>
220+
<div>
221+
<span className="block font-medium mb-1">
222+
{t("settings:contextManagement.diagnostics.maxMessages.label")}
223+
</span>
224+
<div className="flex items-center gap-2">
225+
<Slider
226+
min={1}
227+
max={100}
228+
step={1}
229+
value={[maxDiagnosticMessages ?? 50]}
230+
onValueChange={([value]) => setCachedStateField("maxDiagnosticMessages", value)}
231+
data-testid="max-diagnostic-messages-slider"
232+
/>
233+
<span className="w-10">{maxDiagnosticMessages ?? 50}</span>
239234
</div>
240-
)}
235+
<div className="text-vscode-descriptionForeground text-sm mt-1">
236+
{t("settings:contextManagement.diagnostics.maxMessages.description")}
237+
</div>
238+
</div>
241239
</Section>
242240
<Section className="pt-2">
243241
<VSCodeCheckbox

webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ vi.mock("@/components/ui", () => ({
99
Slider: ({ value, onValueChange, "data-testid": dataTestId, disabled }: any) => (
1010
<input
1111
type="range"
12-
value={value[0]}
12+
value={value?.[0] ?? 0}
1313
onChange={(e) => onValueChange([parseFloat(e.target.value)])}
1414
data-testid={dataTestId}
1515
disabled={disabled}
@@ -106,8 +106,9 @@ describe("ContextManagementSettings", () => {
106106
const checkbox = screen.getByTestId("include-diagnostic-messages-checkbox")
107107
expect(checkbox.querySelector("input")).not.toBeChecked()
108108

109-
// Slider should not be rendered when diagnostics are disabled
110-
expect(screen.queryByTestId("max-diagnostic-messages-slider")).not.toBeInTheDocument()
109+
// Slider should still be rendered when diagnostics are disabled
110+
expect(screen.getByTestId("max-diagnostic-messages-slider")).toBeInTheDocument()
111+
expect(screen.getByText("50")).toBeInTheDocument()
111112
})
112113

113114
it("calls setCachedStateField when include diagnostic messages checkbox is toggled", async () => {
@@ -134,15 +135,15 @@ describe("ContextManagementSettings", () => {
134135
})
135136
})
136137

137-
it("hides slider when include diagnostic messages is unchecked", () => {
138+
it("keeps slider visible when include diagnostic messages is unchecked", () => {
138139
const { rerender } = render(<ContextManagementSettings {...defaultProps} includeDiagnosticMessages={true} />)
139140

140141
const slider = screen.getByTestId("max-diagnostic-messages-slider")
141142
expect(slider).toBeInTheDocument()
142143

143-
// Update to disabled
144+
// Update to disabled - slider should still be visible
144145
rerender(<ContextManagementSettings {...defaultProps} includeDiagnosticMessages={false} />)
145-
expect(screen.queryByTestId("max-diagnostic-messages-slider")).not.toBeInTheDocument()
146+
expect(screen.getByTestId("max-diagnostic-messages-slider")).toBeInTheDocument()
146147
})
147148

148149
it("displays correct max diagnostic messages value", () => {
@@ -167,4 +168,110 @@ describe("ContextManagementSettings", () => {
167168
expect(screen.getByTestId("show-rooignored-files-checkbox")).toBeInTheDocument()
168169
expect(screen.getByTestId("auto-condense-context-checkbox")).toBeInTheDocument()
169170
})
171+
172+
describe("Edge cases for maxDiagnosticMessages", () => {
173+
it("handles zero value correctly", async () => {
174+
const setCachedStateField = vi.fn()
175+
render(
176+
<ContextManagementSettings
177+
{...defaultProps}
178+
maxDiagnosticMessages={0}
179+
setCachedStateField={setCachedStateField}
180+
/>,
181+
)
182+
183+
expect(screen.getByText("0")).toBeInTheDocument()
184+
185+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
186+
expect(slider).toHaveValue("0")
187+
})
188+
189+
it("handles negative values by displaying them", async () => {
190+
const setCachedStateField = vi.fn()
191+
render(
192+
<ContextManagementSettings
193+
{...defaultProps}
194+
maxDiagnosticMessages={-10}
195+
setCachedStateField={setCachedStateField}
196+
/>,
197+
)
198+
199+
// Component displays the actual negative value in the text span
200+
expect(screen.getByText("-10")).toBeInTheDocument()
201+
202+
// Note: The actual slider behavior with negative values depends on the implementation
203+
// In this case, we're just verifying the component renders without errors
204+
})
205+
206+
it("handles very large numbers by capping at maximum", async () => {
207+
const setCachedStateField = vi.fn()
208+
const largeNumber = 1000
209+
render(
210+
<ContextManagementSettings
211+
{...defaultProps}
212+
maxDiagnosticMessages={largeNumber}
213+
setCachedStateField={setCachedStateField}
214+
/>,
215+
)
216+
217+
// Should display the actual value even if it exceeds slider max
218+
expect(screen.getByText(largeNumber.toString())).toBeInTheDocument()
219+
220+
// Slider value would be capped at max (100)
221+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
222+
expect(slider).toHaveValue("100")
223+
})
224+
225+
it("enforces maximum value constraint", async () => {
226+
const setCachedStateField = vi.fn()
227+
render(<ContextManagementSettings {...defaultProps} setCachedStateField={setCachedStateField} />)
228+
229+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
230+
231+
// Test that setting value above 100 gets capped
232+
fireEvent.change(slider, { target: { value: "150" } })
233+
234+
await waitFor(() => {
235+
// Should be capped at 100 (the slider's max)
236+
expect(setCachedStateField).toHaveBeenCalledWith("maxDiagnosticMessages", 100)
237+
})
238+
})
239+
240+
it("handles boundary value at minimum (0)", async () => {
241+
const setCachedStateField = vi.fn()
242+
render(<ContextManagementSettings {...defaultProps} setCachedStateField={setCachedStateField} />)
243+
244+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
245+
fireEvent.change(slider, { target: { value: "0" } })
246+
247+
await waitFor(() => {
248+
expect(setCachedStateField).toHaveBeenCalledWith("maxDiagnosticMessages", 0)
249+
})
250+
})
251+
252+
it("handles boundary value at maximum (100)", async () => {
253+
const setCachedStateField = vi.fn()
254+
render(<ContextManagementSettings {...defaultProps} setCachedStateField={setCachedStateField} />)
255+
256+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
257+
fireEvent.change(slider, { target: { value: "100" } })
258+
259+
await waitFor(() => {
260+
expect(setCachedStateField).toHaveBeenCalledWith("maxDiagnosticMessages", 100)
261+
})
262+
})
263+
264+
it("handles decimal values by parsing as float", async () => {
265+
const setCachedStateField = vi.fn()
266+
render(<ContextManagementSettings {...defaultProps} setCachedStateField={setCachedStateField} />)
267+
268+
const slider = screen.getByTestId("max-diagnostic-messages-slider")
269+
fireEvent.change(slider, { target: { value: "50.7" } })
270+
271+
await waitFor(() => {
272+
// The mock slider component parses as float
273+
expect(setCachedStateField).toHaveBeenCalledWith("maxDiagnosticMessages", 50.7)
274+
})
275+
})
276+
})
170277
})

0 commit comments

Comments
 (0)