Skip to content

Commit 2945dbb

Browse files
committed
Merge branch 'main' into cte/roo-code-cloud
2 parents 37117e1 + 4cf240f commit 2945dbb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1168
-614
lines changed

.changeset/eager-buckets-feel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"roo-cline": major
3+
---
4+
5+
Default enabled autoCondenseContext and moved settings out of Experimental

evals/packages/types/src/roo-code.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ export type CommandExecutionStatus = z.infer<typeof commandExecutionStatusSchema
297297
* ExperimentId
298298
*/
299299

300-
export const experimentIds = ["autoCondenseContext", "powerSteering"] as const
300+
export const experimentIds = ["powerSteering"] as const
301301

302302
export const experimentIdsSchema = z.enum(experimentIds)
303303

@@ -308,7 +308,6 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
308308
*/
309309

310310
const experimentsSchema = z.object({
311-
autoCondenseContext: z.boolean(),
312311
powerSteering: z.boolean(),
313312
})
314313

packages/types/src/experiment.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { Keys, Equals, AssertEqual } from "./type-fu.js"
66
* ExperimentId
77
*/
88

9-
export const experimentIds = ["autoCondenseContext", "powerSteering"] as const
9+
export const experimentIds = ["powerSteering"] as const
1010

1111
export const experimentIdsSchema = z.enum(experimentIds)
1212

@@ -17,7 +17,6 @@ export type ExperimentId = z.infer<typeof experimentIdsSchema>
1717
*/
1818

1919
export const experimentsSchema = z.object({
20-
autoCondenseContext: z.boolean(),
2120
powerSteering: z.boolean(),
2221
})
2322

packages/types/src/global-settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const globalSettingsSchema = z.object({
4646
alwaysAllowExecute: z.boolean().optional(),
4747
allowedCommands: z.array(z.string()).optional(),
4848
allowedMaxRequests: z.number().nullish(),
49+
autoCondenseContext: z.boolean().optional(),
4950
autoCondenseContextPercent: z.number().optional(),
5051

5152
browserToolEnabled: z.boolean().optional(),
@@ -131,6 +132,7 @@ export const GLOBAL_SETTINGS_KEYS = keysOf<GlobalSettings>()([
131132
"alwaysAllowExecute",
132133
"allowedCommands",
133134
"allowedMaxRequests",
135+
"autoCondenseContext",
134136
"autoCondenseContextPercent",
135137

136138
"browserToolEnabled",

src/core/mentions/index.ts

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
1717

1818
import { FileContextTracker } from "../context-tracking/FileContextTracker"
1919

20+
import { RooIgnoreController } from "../ignore/RooIgnoreController"
21+
2022
export async function openMention(mention?: string): Promise<void> {
2123
if (!mention) {
2224
return
@@ -50,6 +52,8 @@ export async function parseMentions(
5052
cwd: string,
5153
urlContentFetcher: UrlContentFetcher,
5254
fileContextTracker?: FileContextTracker,
55+
rooIgnoreController?: RooIgnoreController,
56+
showRooIgnoredFiles: boolean = true,
5357
): Promise<string> {
5458
const mentions: Set<string> = new Set()
5559
let parsedText = text.replace(mentionRegexGlobal, (match, mention) => {
@@ -102,12 +106,11 @@ export async function parseMentions(
102106
} else if (mention.startsWith("/")) {
103107
const mentionPath = mention.slice(1)
104108
try {
105-
const content = await getFileOrFolderContent(mentionPath, cwd)
109+
const content = await getFileOrFolderContent(mentionPath, cwd, rooIgnoreController, showRooIgnoredFiles)
106110
if (mention.endsWith("/")) {
107111
parsedText += `\n\n<folder_content path="${mentionPath}">\n${content}\n</folder_content>`
108112
} else {
109113
parsedText += `\n\n<file_content path="${mentionPath}">\n${content}\n</file_content>`
110-
// Track that this file was mentioned and its content was included
111114
if (fileContextTracker) {
112115
await fileContextTracker.trackFileContext(mentionPath, "file_mentioned")
113116
}
@@ -161,15 +164,22 @@ export async function parseMentions(
161164
return parsedText
162165
}
163166

164-
async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise<string> {
165-
// Unescape spaces in the path before resolving it
167+
async function getFileOrFolderContent(
168+
mentionPath: string,
169+
cwd: string,
170+
rooIgnoreController?: any,
171+
showRooIgnoredFiles: boolean = true,
172+
): Promise<string> {
166173
const unescapedPath = unescapeSpaces(mentionPath)
167174
const absPath = path.resolve(cwd, unescapedPath)
168175

169176
try {
170177
const stats = await fs.stat(absPath)
171178

172179
if (stats.isFile()) {
180+
if (rooIgnoreController && !rooIgnoreController.validateAccess(absPath)) {
181+
return `(File ${mentionPath} is ignored by .rooignore)`
182+
}
173183
try {
174184
const content = await extractTextFromFile(absPath)
175185
return content
@@ -180,33 +190,51 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
180190
const entries = await fs.readdir(absPath, { withFileTypes: true })
181191
let folderContent = ""
182192
const fileContentPromises: Promise<string | undefined>[] = []
183-
entries.forEach((entry, index) => {
193+
const LOCK_SYMBOL = "🔒"
194+
195+
for (let index = 0; index < entries.length; index++) {
196+
const entry = entries[index]
184197
const isLast = index === entries.length - 1
185198
const linePrefix = isLast ? "└── " : "├── "
199+
const entryPath = path.join(absPath, entry.name)
200+
201+
let isIgnored = false
202+
if (rooIgnoreController) {
203+
isIgnored = !rooIgnoreController.validateAccess(entryPath)
204+
}
205+
206+
if (isIgnored && !showRooIgnoredFiles) {
207+
continue
208+
}
209+
210+
const displayName = isIgnored ? `${LOCK_SYMBOL} ${entry.name}` : entry.name
211+
186212
if (entry.isFile()) {
187-
folderContent += `${linePrefix}${entry.name}\n`
188-
const filePath = path.join(mentionPath, entry.name)
189-
const absoluteFilePath = path.resolve(absPath, entry.name)
190-
fileContentPromises.push(
191-
(async () => {
192-
try {
193-
const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
194-
if (isBinary) {
213+
folderContent += `${linePrefix}${displayName}\n`
214+
if (!isIgnored) {
215+
const filePath = path.join(mentionPath, entry.name)
216+
const absoluteFilePath = path.resolve(absPath, entry.name)
217+
fileContentPromises.push(
218+
(async () => {
219+
try {
220+
const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
221+
if (isBinary) {
222+
return undefined
223+
}
224+
const content = await extractTextFromFile(absoluteFilePath)
225+
return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
226+
} catch (error) {
195227
return undefined
196228
}
197-
const content = await extractTextFromFile(absoluteFilePath)
198-
return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
199-
} catch (error) {
200-
return undefined
201-
}
202-
})(),
203-
)
229+
})(),
230+
)
231+
}
204232
} else if (entry.isDirectory()) {
205-
folderContent += `${linePrefix}${entry.name}/\n`
233+
folderContent += `${linePrefix}${displayName}/\n`
206234
} else {
207-
folderContent += `${linePrefix}${entry.name}\n`
235+
folderContent += `${linePrefix}${displayName}\n`
208236
}
209-
})
237+
}
210238
const fileContents = (await Promise.all(fileContentPromises)).filter((content) => content)
211239
return `${folderContent}\n${fileContents.join("\n\n")}`.trim()
212240
} else {

src/core/mentions/processUserContentMentions.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ export async function processUserContentMentions({
1111
cwd,
1212
urlContentFetcher,
1313
fileContextTracker,
14+
rooIgnoreController,
15+
showRooIgnoredFiles = true,
1416
}: {
1517
userContent: Anthropic.Messages.ContentBlockParam[]
1618
cwd: string
1719
urlContentFetcher: UrlContentFetcher
1820
fileContextTracker: FileContextTracker
21+
rooIgnoreController?: any
22+
showRooIgnoredFiles?: boolean
1923
}) {
2024
// Process userContent array, which contains various block types:
2125
// TextBlockParam, ImageBlockParam, ToolUseBlockParam, and ToolResultBlockParam.
@@ -35,7 +39,14 @@ export async function processUserContentMentions({
3539
if (shouldProcessMentions(block.text)) {
3640
return {
3741
...block,
38-
text: await parseMentions(block.text, cwd, urlContentFetcher, fileContextTracker),
42+
text: await parseMentions(
43+
block.text,
44+
cwd,
45+
urlContentFetcher,
46+
fileContextTracker,
47+
rooIgnoreController,
48+
showRooIgnoredFiles,
49+
),
3950
}
4051
}
4152

@@ -45,7 +56,14 @@ export async function processUserContentMentions({
4556
if (shouldProcessMentions(block.content)) {
4657
return {
4758
...block,
48-
content: await parseMentions(block.content, cwd, urlContentFetcher, fileContextTracker),
59+
content: await parseMentions(
60+
block.content,
61+
cwd,
62+
urlContentFetcher,
63+
fileContextTracker,
64+
rooIgnoreController,
65+
showRooIgnoredFiles,
66+
),
4967
}
5068
}
5169

@@ -61,6 +79,8 @@ export async function processUserContentMentions({
6179
cwd,
6280
urlContentFetcher,
6381
fileContextTracker,
82+
rooIgnoreController,
83+
showRooIgnoredFiles,
6484
),
6585
}
6686
}

src/core/task/Task.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,11 +1127,15 @@ export class Task extends EventEmitter<ClineEvents> {
11271127
}),
11281128
)
11291129

1130+
const { showRooIgnoredFiles = true } = (await this.providerRef.deref()?.getState()) ?? {}
1131+
11301132
const parsedUserContent = await processUserContentMentions({
11311133
userContent,
11321134
cwd: this.cwd,
11331135
urlContentFetcher: this.urlContentFetcher,
11341136
fileContextTracker: this.fileContextTracker,
1137+
rooIgnoreController: this.rooIgnoreController,
1138+
showRooIgnoredFiles,
11351139
})
11361140

11371141
const environmentDetails = await getEnvironmentDetails(this, includeFileDetails)
@@ -1547,8 +1551,8 @@ export class Task extends EventEmitter<ClineEvents> {
15471551
autoApprovalEnabled,
15481552
alwaysApproveResubmit,
15491553
requestDelaySeconds,
1550-
experiments,
15511554
mode,
1555+
autoCondenseContext = true,
15521556
autoCondenseContextPercent = 100,
15531557
} = state ?? {}
15541558

@@ -1612,7 +1616,6 @@ export class Task extends EventEmitter<ClineEvents> {
16121616

16131617
const contextWindow = modelInfo.contextWindow
16141618

1615-
const autoCondenseContext = experiments?.autoCondenseContext ?? false
16161619
const truncateResult = await truncateConversationIfNeeded({
16171620
messages: this.apiConversationHistory,
16181621
totalTokens: contextTokens,

src/core/tools/insertContentTool.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ export async function insertContentTool(
5858
return
5959
}
6060

61+
const accessAllowed = cline.rooIgnoreController?.validateAccess(relPath)
62+
63+
if (!accessAllowed) {
64+
await cline.say("rooignore_error", relPath)
65+
pushToolResult(formatResponse.toolError(formatResponse.rooIgnoreError(relPath)))
66+
return
67+
}
68+
6169
const absolutePath = path.resolve(cline.cwd, relPath)
6270
const fileExists = await fileExistsAtPath(absolutePath)
6371

src/core/tools/searchAndReplaceTool.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ export async function searchAndReplaceTool(
115115
endLine: endLine,
116116
}
117117

118+
const accessAllowed = cline.rooIgnoreController?.validateAccess(validRelPath)
119+
120+
if (!accessAllowed) {
121+
await cline.say("rooignore_error", validRelPath)
122+
pushToolResult(formatResponse.toolError(formatResponse.rooIgnoreError(validRelPath)))
123+
return
124+
}
125+
118126
const absolutePath = path.resolve(cline.cwd, validRelPath)
119127
const fileExists = await fileExistsAtPath(absolutePath)
120128

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ export class ClineProvider
12481248
alwaysAllowModeSwitch,
12491249
alwaysAllowSubtasks,
12501250
allowedMaxRequests,
1251+
autoCondenseContext,
12511252
autoCondenseContextPercent,
12521253
soundEnabled,
12531254
ttsEnabled,
@@ -1325,6 +1326,7 @@ export class ClineProvider
13251326
alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
13261327
alwaysAllowSubtasks: alwaysAllowSubtasks ?? false,
13271328
allowedMaxRequests,
1329+
autoCondenseContext: autoCondenseContext ?? true,
13281330
autoCondenseContextPercent: autoCondenseContextPercent ?? 100,
13291331
uriScheme: vscode.env.uriScheme,
13301332
currentTaskItem: this.getCurrentCline()?.taskId
@@ -1450,6 +1452,7 @@ export class ClineProvider
14501452
alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
14511453
alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
14521454
allowedMaxRequests: stateValues.allowedMaxRequests,
1455+
autoCondenseContext: stateValues.autoCondenseContext ?? true,
14531456
autoCondenseContextPercent: stateValues.autoCondenseContextPercent ?? 100,
14541457
taskHistory: stateValues.taskHistory,
14551458
allowedCommands: stateValues.allowedCommands,

0 commit comments

Comments
 (0)