Skip to content

Commit 4517e07

Browse files
author
Eric Wheeler
committed
feat: implement parentRulesMaxDepth setting
This commit implements the parentRulesMaxDepth setting which controls how many parent directories are searched for .roo/rules files. The setting is accessible from the Modes view and persists across sessions. Key changes: - Added parentRulesMaxDepth to the global settings schema - Added UI component in ModesView.tsx with improved styling - Updated state management to properly persist the setting Signed-off-by: Eric Wheeler <[email protected]>
1 parent b45252d commit 4517e07

File tree

9 files changed

+86
-6
lines changed

9 files changed

+86
-6
lines changed

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const globalSettingsSchema = z.object({
4848
allowedCommands: z.array(z.string()).optional(),
4949
allowedMaxRequests: z.number().nullish(),
5050
autoCondenseContext: z.boolean().optional(),
51+
parentRulesMaxDepth: z.number().min(1).optional(),
5152
autoCondenseContextPercent: z.number().optional(),
5253
maxConcurrentFileReads: z.number().optional(),
5354

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,7 @@ export class ClineProvider
14021402
terminalCompressProgressBar,
14031403
historyPreviewCollapsed,
14041404
cloudUserInfo,
1405+
parentRulesMaxDepth,
14051406
cloudIsAuthenticated,
14061407
sharingEnabled,
14071408
organizationAllowList,
@@ -1490,6 +1491,7 @@ export class ClineProvider
14901491
maxOpenTabsContext: maxOpenTabsContext ?? 20,
14911492
maxWorkspaceFiles: maxWorkspaceFiles ?? 200,
14921493
cwd,
1494+
parentRulesMaxDepth: parentRulesMaxDepth ?? 1,
14931495
browserToolEnabled: browserToolEnabled ?? true,
14941496
telemetrySetting,
14951497
telemetryKey,
@@ -1654,6 +1656,7 @@ export class ClineProvider
16541656
showRooIgnoredFiles: stateValues.showRooIgnoredFiles ?? true,
16551657
maxReadFileLine: stateValues.maxReadFileLine ?? -1,
16561658
maxConcurrentFileReads: stateValues.maxConcurrentFileReads ?? 5,
1659+
parentRulesMaxDepth: stateValues.parentRulesMaxDepth ?? 1,
16571660
historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
16581661
cloudUserInfo,
16591662
cloudIsAuthenticated,

src/core/webview/webviewMessageHandler.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ export const webviewMessageHandler = async (
193193
await updateGlobalState("autoCondenseContextPercent", message.value)
194194
await provider.postStateToWebview()
195195
break
196+
case "parentRulesMaxDepth":
197+
await updateGlobalState("parentRulesMaxDepth", Math.max(1, message.value ?? 1))
198+
await provider.postStateToWebview()
199+
break
196200
case "terminalOperation":
197201
if (message.terminalOperation) {
198202
provider.getCurrentCline()?.handleTerminalOperation(message.terminalOperation)

src/services/roo-config/index.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as path from "path"
22
import * as os from "os"
33
import fs from "fs/promises"
4+
import { string } from "zod"
5+
import { dir } from "console"
46

57
/**
68
* Gets the global .roo directory path based on the current platform
@@ -145,15 +147,48 @@ export async function readFileIfExists(filePath: string): Promise<string | null>
145147
* ```
146148
*/
147149
export function getRooDirectoriesForCwd(cwd: string): string[] {
148-
const directories: string[] = []
150+
const directories: Set<string> = new Set<string>()
149151

150152
// Add global directory first
151-
directories.push(getGlobalRooDirectory())
153+
directories.add(getGlobalRooDirectory())
152154

153-
// Add project-local directory second
154-
directories.push(getProjectRooDirectoryForCwd(cwd))
155+
// Add project and any parent directories
156+
let currentCwd = path.resolve(cwd)
157+
const rootDir = path.parse(currentCwd).root
155158

156-
return directories
159+
// Get parentRulesMaxDepth from global state
160+
let maxDepth = 1
161+
try {
162+
const { ContextProxy } = require("../../core/config/ContextProxy")
163+
maxDepth = ContextProxy.instance?.getValue("parentRulesMaxDepth") ?? 1
164+
console.log("Using parentRulesMaxDepth:", maxDepth)
165+
} catch (error) {
166+
// In test environments, ContextProxy might not be initialized
167+
// Fall back to default value of 1
168+
console.error("Using default parentRulesMaxDepth: 1", error)
169+
}
170+
171+
let currentDepth = 0
172+
173+
// Loop from initialCwd up to root or until max depth is reached
174+
while (currentDepth < maxDepth) {
175+
directories.add(getProjectRooDirectoryForCwd(currentCwd))
176+
177+
// Stop if we've reached the root directory
178+
if (currentCwd === rootDir) {
179+
break
180+
}
181+
const parentCwd = path.resolve(currentCwd, "..")
182+
183+
// Safety break if path.resolve doesn't change currentCwd (e.g., already at root)
184+
if (parentCwd === currentCwd) {
185+
break
186+
}
187+
currentCwd = parentCwd
188+
currentDepth++
189+
}
190+
191+
return Array.from(directories).sort()
157192
}
158193

159194
/**

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ export type ExtensionState = Pick<
203203
| "fuzzyMatchThreshold"
204204
// | "experiments" // Optional in GlobalSettings, required here.
205205
| "language"
206+
| "parentRulesMaxDepth"
206207
// | "telemetrySetting" // Optional in GlobalSettings, required here.
207208
// | "mcpEnabled" // Optional in GlobalSettings, required here.
208209
// | "enableMcpServerCreation" // Optional in GlobalSettings, required here.

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export interface WebviewMessage {
100100
| "enhancePrompt"
101101
| "enhancedPrompt"
102102
| "draggedImages"
103+
| "parentRulesMaxDepth"
103104
| "deleteMessage"
104105
| "terminalOutputLineLimit"
105106
| "terminalShellIntegrationTimeout"

webview-ui/src/components/modes/ModesView.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ const ModesView = ({ onDone }: ModesViewProps) => {
7373
customInstructions,
7474
setCustomInstructions,
7575
customModes,
76+
parentRulesMaxDepth,
77+
setParentRulesMaxDepth,
7678
} = useExtensionState()
7779

7880
// Use a local state to track the visually active mode
@@ -1032,6 +1034,30 @@ const ModesView = ({ onDone }: ModesViewProps) => {
10321034
</div>
10331035
</div>
10341036

1037+
{/* Parent Rules Max Depth Setting */}
1038+
<div className="mt-4 mb-4">
1039+
<div className="font-bold mb-1">{t("settings:prompts.parentRulesMaxDepth.label")}</div>
1040+
<div className="flex items-center gap-2 mt-1">
1041+
<input
1042+
type="number"
1043+
className="w-16 bg-vscode-input-background text-vscode-input-foreground border border-vscode-input-border px-2 py-1 rounded text-right disabled:opacity-50"
1044+
min="1"
1045+
value={parentRulesMaxDepth ?? 1}
1046+
onChange={(e) => {
1047+
const value = Math.max(1, parseInt(e.target.value) || 1)
1048+
setParentRulesMaxDepth(value)
1049+
vscode.postMessage({
1050+
type: "parentRulesMaxDepth",
1051+
value: value,
1052+
})
1053+
}}
1054+
/>
1055+
</div>
1056+
<div className="text-xs text-vscode-descriptionForeground mt-1">
1057+
{t("settings:prompts.parentRulesMaxDepth.description")}
1058+
</div>
1059+
</div>
1060+
10351061
<div className="pb-4 border-b border-vscode-input-border">
10361062
<div className="flex gap-2">
10371063
<Button

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export interface ExtensionStateContextType extends ExtensionState {
4040
mdmCompliant?: boolean
4141
hasOpenedModeSelector: boolean // New property to track if user has opened mode selector
4242
setHasOpenedModeSelector: (value: boolean) => void // Setter for the new property
43+
parentRulesMaxDepth?: number
44+
setParentRulesMaxDepth: (value: number) => void
4345
condensingApiConfigId?: string
4446
setCondensingApiConfigId: (value: string) => void
4547
customCondensingPrompt?: string
@@ -205,6 +207,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
205207
sharingEnabled: false,
206208
organizationAllowList: ORGANIZATION_ALLOW_ALL,
207209
autoCondenseContext: true,
210+
parentRulesMaxDepth: 1, // Default value for parentRulesMaxDepth
208211
autoCondenseContextPercent: 100,
209212
profileThresholds: {},
210213
codebaseIndexConfig: {
@@ -438,6 +441,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
438441
setCustomCondensingPrompt: (value) =>
439442
setState((prevState) => ({ ...prevState, customCondensingPrompt: value })),
440443
setProfileThresholds: (value) => setState((prevState) => ({ ...prevState, profileThresholds: value })),
444+
setParentRulesMaxDepth: (value: number) =>
445+
setState((prevState) => ({ ...prevState, parentRulesMaxDepth: value })),
441446
}
442447

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

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
"about": "About Roo Code"
3535
},
3636
"prompts": {
37-
"description": "Configure support prompts that are used for quick actions like enhancing prompts, explaining code, and fixing issues. These prompts help Roo provide better assistance for common development tasks."
37+
"description": "Configure support prompts that are used for quick actions like enhancing prompts, explaining code, and fixing issues. These prompts help Roo provide better assistance for common development tasks.",
38+
"parentRulesMaxDepth": {
39+
"label": "Parent Rule Search Levels",
40+
"description": "Maximum directory levels to search upward for .roo/rules. Default: 1 (workspace directory only). Higher values enable hierarchical loading from parent directories (feature, repository, organization, user-global, etc, …), where large values search to the filesystem root."
41+
}
3842
},
3943
"codeIndex": {
4044
"title": "Codebase Indexing",

0 commit comments

Comments
 (0)