@directory not respecting .rooIgnore Fix (#4075)

* Issue fixed.

* Update src/core/mentions/index.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Update index.ts

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
xyOz 2025-05-29 02:58:50 +01:00 committed by GitHub
parent 70e753ebb1
commit aa6265462e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 77 additions and 25 deletions

View file

@ -17,6 +17,8 @@ import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
import { FileContextTracker } from "../context-tracking/FileContextTracker"
import { RooIgnoreController } from "../ignore/RooIgnoreController"
export async function openMention(mention?: string): Promise<void> {
if (!mention) {
return
@ -50,6 +52,8 @@ export async function parseMentions(
cwd: string,
urlContentFetcher: UrlContentFetcher,
fileContextTracker?: FileContextTracker,
rooIgnoreController?: RooIgnoreController,
showRooIgnoredFiles: boolean = true,
): Promise<string> {
const mentions: Set<string> = new Set()
let parsedText = text.replace(mentionRegexGlobal, (match, mention) => {
@ -102,12 +106,11 @@ export async function parseMentions(
} else if (mention.startsWith("/")) {
const mentionPath = mention.slice(1)
try {
const content = await getFileOrFolderContent(mentionPath, cwd)
const content = await getFileOrFolderContent(mentionPath, cwd, rooIgnoreController, showRooIgnoredFiles)
if (mention.endsWith("/")) {
parsedText += `\n\n<folder_content path="${mentionPath}">\n${content}\n</folder_content>`
} else {
parsedText += `\n\n<file_content path="${mentionPath}">\n${content}\n</file_content>`
// Track that this file was mentioned and its content was included
if (fileContextTracker) {
await fileContextTracker.trackFileContext(mentionPath, "file_mentioned")
}
@ -161,8 +164,12 @@ export async function parseMentions(
return parsedText
}
async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise<string> {
// Unescape spaces in the path before resolving it
async function getFileOrFolderContent(
mentionPath: string,
cwd: string,
rooIgnoreController?: any,
showRooIgnoredFiles: boolean = true,
): Promise<string> {
const unescapedPath = unescapeSpaces(mentionPath)
const absPath = path.resolve(cwd, unescapedPath)
@ -170,6 +177,9 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
const stats = await fs.stat(absPath)
if (stats.isFile()) {
if (rooIgnoreController && !rooIgnoreController.validateAccess(absPath)) {
return `(File ${mentionPath} is ignored by .rooignore)`
}
try {
const content = await extractTextFromFile(absPath)
return content
@ -180,33 +190,51 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
const entries = await fs.readdir(absPath, { withFileTypes: true })
let folderContent = ""
const fileContentPromises: Promise<string | undefined>[] = []
entries.forEach((entry, index) => {
const LOCK_SYMBOL = "🔒"
for (let index = 0; index < entries.length; index++) {
const entry = entries[index]
const isLast = index === entries.length - 1
const linePrefix = isLast ? "└── " : "├── "
const entryPath = path.join(absPath, entry.name)
let isIgnored = false
if (rooIgnoreController) {
isIgnored = !rooIgnoreController.validateAccess(entryPath)
}
if (isIgnored && !showRooIgnoredFiles) {
continue
}
const displayName = isIgnored ? `${LOCK_SYMBOL} ${entry.name}` : entry.name
if (entry.isFile()) {
folderContent += `${linePrefix}${entry.name}\n`
const filePath = path.join(mentionPath, entry.name)
const absoluteFilePath = path.resolve(absPath, entry.name)
fileContentPromises.push(
(async () => {
try {
const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
if (isBinary) {
folderContent += `${linePrefix}${displayName}\n`
if (!isIgnored) {
const filePath = path.join(mentionPath, entry.name)
const absoluteFilePath = path.resolve(absPath, entry.name)
fileContentPromises.push(
(async () => {
try {
const isBinary = await isBinaryFile(absoluteFilePath).catch(() => false)
if (isBinary) {
return undefined
}
const content = await extractTextFromFile(absoluteFilePath)
return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
} catch (error) {
return undefined
}
const content = await extractTextFromFile(absoluteFilePath)
return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
} catch (error) {
return undefined
}
})(),
)
})(),
)
}
} else if (entry.isDirectory()) {
folderContent += `${linePrefix}${entry.name}/\n`
folderContent += `${linePrefix}${displayName}/\n`
} else {
folderContent += `${linePrefix}${entry.name}\n`
folderContent += `${linePrefix}${displayName}\n`
}
})
}
const fileContents = (await Promise.all(fileContentPromises)).filter((content) => content)
return `${folderContent}\n${fileContents.join("\n\n")}`.trim()
} else {

View file

@ -11,11 +11,15 @@ export async function processUserContentMentions({
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles = true,
}: {
userContent: Anthropic.Messages.ContentBlockParam[]
cwd: string
urlContentFetcher: UrlContentFetcher
fileContextTracker: FileContextTracker
rooIgnoreController?: any
showRooIgnoredFiles?: boolean
}) {
// Process userContent array, which contains various block types:
// TextBlockParam, ImageBlockParam, ToolUseBlockParam, and ToolResultBlockParam.
@ -35,7 +39,14 @@ export async function processUserContentMentions({
if (shouldProcessMentions(block.text)) {
return {
...block,
text: await parseMentions(block.text, cwd, urlContentFetcher, fileContextTracker),
text: await parseMentions(
block.text,
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles,
),
}
}
@ -45,7 +56,14 @@ export async function processUserContentMentions({
if (shouldProcessMentions(block.content)) {
return {
...block,
content: await parseMentions(block.content, cwd, urlContentFetcher, fileContextTracker),
content: await parseMentions(
block.content,
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles,
),
}
}
@ -61,6 +79,8 @@ export async function processUserContentMentions({
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles,
),
}
}

View file

@ -1107,11 +1107,15 @@ export class Task extends EventEmitter<ClineEvents> {
}),
)
const { showRooIgnoredFiles = true } = (await this.providerRef.deref()?.getState()) ?? {}
const parsedUserContent = await processUserContentMentions({
userContent,
cwd: this.cwd,
urlContentFetcher: this.urlContentFetcher,
fileContextTracker: this.fileContextTracker,
rooIgnoreController: this.rooIgnoreController,
showRooIgnoredFiles,
})
const environmentDetails = await getEnvironmentDetails(this, includeFileDetails)