Просмотр исходного кода

Adjust searching outside of the workspace to respect the auto-approve… (#4670)

Adjust searching outside of the workspace to respect the auto-approve checkbox
Matt Rubens 6 месяцев назад
Родитель
Сommit
10b2fb32ed
37 измененных файлов с 65 добавлено и 384 удалено
  1. 0 300
      src/core/tools/__tests__/searchFilesTool.spec.ts
  2. 4 14
      src/core/tools/searchFilesTool.ts
  3. 0 3
      src/i18n/locales/ca/tools.json
  4. 0 3
      src/i18n/locales/de/tools.json
  5. 0 3
      src/i18n/locales/en/tools.json
  6. 0 3
      src/i18n/locales/es/tools.json
  7. 0 3
      src/i18n/locales/fr/tools.json
  8. 0 3
      src/i18n/locales/hi/tools.json
  9. 0 3
      src/i18n/locales/it/tools.json
  10. 0 3
      src/i18n/locales/ja/tools.json
  11. 0 3
      src/i18n/locales/ko/tools.json
  12. 0 3
      src/i18n/locales/nl/tools.json
  13. 0 3
      src/i18n/locales/pl/tools.json
  14. 0 3
      src/i18n/locales/pt-BR/tools.json
  15. 0 3
      src/i18n/locales/ru/tools.json
  16. 0 3
      src/i18n/locales/tr/tools.json
  17. 0 3
      src/i18n/locales/vi/tools.json
  18. 0 3
      src/i18n/locales/zh-CN/tools.json
  19. 0 3
      src/i18n/locales/zh-TW/tools.json
  20. 10 2
      webview-ui/src/components/chat/ChatRow.tsx
  21. 3 1
      webview-ui/src/i18n/locales/ca/chat.json
  22. 3 1
      webview-ui/src/i18n/locales/de/chat.json
  23. 3 1
      webview-ui/src/i18n/locales/en/chat.json
  24. 3 1
      webview-ui/src/i18n/locales/es/chat.json
  25. 3 1
      webview-ui/src/i18n/locales/fr/chat.json
  26. 3 1
      webview-ui/src/i18n/locales/hi/chat.json
  27. 3 1
      webview-ui/src/i18n/locales/it/chat.json
  28. 3 1
      webview-ui/src/i18n/locales/ja/chat.json
  29. 3 1
      webview-ui/src/i18n/locales/ko/chat.json
  30. 3 1
      webview-ui/src/i18n/locales/nl/chat.json
  31. 3 1
      webview-ui/src/i18n/locales/pl/chat.json
  32. 3 1
      webview-ui/src/i18n/locales/pt-BR/chat.json
  33. 3 1
      webview-ui/src/i18n/locales/ru/chat.json
  34. 3 1
      webview-ui/src/i18n/locales/tr/chat.json
  35. 3 1
      webview-ui/src/i18n/locales/vi/chat.json
  36. 3 1
      webview-ui/src/i18n/locales/zh-CN/chat.json
  37. 3 1
      webview-ui/src/i18n/locales/zh-TW/chat.json

+ 0 - 300
src/core/tools/__tests__/searchFilesTool.spec.ts

@@ -1,300 +0,0 @@
-import path from "path"
-import { describe, it, expect, beforeEach, vi, type Mock, type MockedFunction } from "vitest"
-import { searchFilesTool } from "../searchFilesTool"
-import { Task } from "../../task/Task"
-import { SearchFilesToolUse } from "../../../shared/tools"
-import { isPathOutsideWorkspace } from "../../../utils/pathUtils"
-import { regexSearchFiles } from "../../../services/ripgrep"
-import { RooIgnoreController } from "../../ignore/RooIgnoreController"
-
-// Mock dependencies
-vi.mock("../../../utils/pathUtils", () => ({
-	isPathOutsideWorkspace: vi.fn(),
-}))
-
-vi.mock("../../../services/ripgrep", () => ({
-	regexSearchFiles: vi.fn(),
-}))
-
-vi.mock("../../../utils/path", () => ({
-	getReadablePath: vi.fn((cwd: string, relPath: string) => relPath),
-}))
-
-vi.mock("../../ignore/RooIgnoreController")
-
-vi.mock("../../../i18n", () => ({
-	t: vi.fn((key: string, params?: any) => {
-		if (key === "tools:searchFiles.workspaceBoundaryError") {
-			return `Cannot search outside workspace. Path '${params?.path}' is outside the current workspace.`
-		}
-		return key
-	}),
-}))
-
-const mockedIsPathOutsideWorkspace = isPathOutsideWorkspace as MockedFunction<typeof isPathOutsideWorkspace>
-const mockedRegexSearchFiles = regexSearchFiles as MockedFunction<typeof regexSearchFiles>
-
-describe("searchFilesTool", () => {
-	let mockTask: Partial<Task>
-	let mockAskApproval: Mock
-	let mockHandleError: Mock
-	let mockPushToolResult: Mock
-	let mockRemoveClosingTag: Mock
-
-	beforeEach(() => {
-		vi.clearAllMocks()
-
-		mockTask = {
-			cwd: "/workspace",
-			consecutiveMistakeCount: 0,
-			recordToolError: vi.fn(),
-			sayAndCreateMissingParamError: vi.fn().mockResolvedValue("Missing parameter error"),
-			say: vi.fn().mockResolvedValue(undefined),
-			rooIgnoreController: new RooIgnoreController("/workspace"),
-		}
-
-		mockAskApproval = vi.fn().mockResolvedValue(true)
-		mockHandleError = vi.fn()
-		mockPushToolResult = vi.fn()
-		mockRemoveClosingTag = vi.fn((tag: string, value: string | undefined) => value || "")
-
-		mockedRegexSearchFiles.mockResolvedValue("Search results")
-	})
-
-	describe("workspace boundary validation", () => {
-		it("should allow search within workspace", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "src",
-					regex: "test",
-					file_pattern: "*.ts",
-				},
-				partial: false,
-			}
-
-			mockedIsPathOutsideWorkspace.mockReturnValue(false)
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockedIsPathOutsideWorkspace).toHaveBeenCalledWith(path.resolve("/workspace", "src"))
-			expect(mockedRegexSearchFiles).toHaveBeenCalled()
-			expect(mockPushToolResult).toHaveBeenCalledWith("Search results")
-		})
-
-		it("should block search outside workspace", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "../external",
-					regex: "test",
-					file_pattern: "*.ts",
-				},
-				partial: false,
-			}
-
-			mockedIsPathOutsideWorkspace.mockReturnValue(true)
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockedIsPathOutsideWorkspace).toHaveBeenCalledWith(path.resolve("/workspace", "../external"))
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-			expect(mockTask.say).toHaveBeenCalledWith(
-				"error",
-				"Cannot search outside workspace. Path '../external' is outside the current workspace.",
-			)
-			expect(mockPushToolResult).toHaveBeenCalledWith(
-				"Cannot search outside workspace. Path '../external' is outside the current workspace.",
-			)
-			expect(mockTask.consecutiveMistakeCount).toBe(1)
-			expect(mockTask.recordToolError).toHaveBeenCalledWith("search_files")
-		})
-
-		it("should block search with absolute path outside workspace", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "/etc/passwd",
-					regex: "root",
-				},
-				partial: false,
-			}
-
-			mockedIsPathOutsideWorkspace.mockReturnValue(true)
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockedIsPathOutsideWorkspace).toHaveBeenCalledWith(path.resolve("/workspace", "/etc/passwd"))
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-			expect(mockTask.say).toHaveBeenCalledWith(
-				"error",
-				"Cannot search outside workspace. Path '/etc/passwd' is outside the current workspace.",
-			)
-			expect(mockPushToolResult).toHaveBeenCalledWith(
-				"Cannot search outside workspace. Path '/etc/passwd' is outside the current workspace.",
-			)
-		})
-
-		it("should handle relative paths that resolve outside workspace", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "../../..",
-					regex: "sensitive",
-				},
-				partial: false,
-			}
-
-			mockedIsPathOutsideWorkspace.mockReturnValue(true)
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockedIsPathOutsideWorkspace).toHaveBeenCalledWith(path.resolve("/workspace", "../../.."))
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-			expect(mockTask.say).toHaveBeenCalledWith(
-				"error",
-				"Cannot search outside workspace. Path '../../..' is outside the current workspace.",
-			)
-			expect(mockPushToolResult).toHaveBeenCalledWith(
-				"Cannot search outside workspace. Path '../../..' is outside the current workspace.",
-			)
-		})
-	})
-
-	describe("existing functionality", () => {
-		beforeEach(() => {
-			mockedIsPathOutsideWorkspace.mockReturnValue(false)
-		})
-
-		it("should handle missing path parameter", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					regex: "test",
-				},
-				partial: false,
-			}
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockTask.sayAndCreateMissingParamError).toHaveBeenCalledWith("search_files", "path")
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-		})
-
-		it("should handle missing regex parameter", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "src",
-				},
-				partial: false,
-			}
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockTask.sayAndCreateMissingParamError).toHaveBeenCalledWith("search_files", "regex")
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-		})
-
-		it("should handle partial blocks", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "src",
-					regex: "test",
-				},
-				partial: true,
-			}
-
-			const mockAsk = vi.fn()
-			mockTask.ask = mockAsk
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockAsk).toHaveBeenCalled()
-			expect(mockedRegexSearchFiles).not.toHaveBeenCalled()
-		})
-
-		it("should handle user rejection", async () => {
-			const block: SearchFilesToolUse = {
-				type: "tool_use",
-				name: "search_files",
-				params: {
-					path: "src",
-					regex: "test",
-				},
-				partial: false,
-			}
-
-			mockAskApproval.mockResolvedValue(false)
-
-			await searchFilesTool(
-				mockTask as Task,
-				block,
-				mockAskApproval,
-				mockHandleError,
-				mockPushToolResult,
-				mockRemoveClosingTag,
-			)
-
-			expect(mockedRegexSearchFiles).toHaveBeenCalled()
-			expect(mockPushToolResult).not.toHaveBeenCalled()
-		})
-	})
-})

+ 4 - 14
src/core/tools/searchFilesTool.ts

@@ -6,7 +6,6 @@ import { ClineSayTool } from "../../shared/ExtensionMessage"
 import { getReadablePath } from "../../utils/path"
 import { isPathOutsideWorkspace } from "../../utils/pathUtils"
 import { regexSearchFiles } from "../../services/ripgrep"
-import { t } from "../../i18n"
 
 export async function searchFilesTool(
 	cline: Task,
@@ -20,11 +19,15 @@ export async function searchFilesTool(
 	const regex: string | undefined = block.params.regex
 	const filePattern: string | undefined = block.params.file_pattern
 
+	const absolutePath = relDirPath ? path.resolve(cline.cwd, relDirPath) : cline.cwd
+	const isOutsideWorkspace = isPathOutsideWorkspace(absolutePath)
+
 	const sharedMessageProps: ClineSayTool = {
 		tool: "searchFiles",
 		path: getReadablePath(cline.cwd, removeClosingTag("path", relDirPath)),
 		regex: removeClosingTag("regex", regex),
 		filePattern: removeClosingTag("file_pattern", filePattern),
+		isOutsideWorkspace,
 	}
 
 	try {
@@ -49,19 +52,6 @@ export async function searchFilesTool(
 
 			cline.consecutiveMistakeCount = 0
 
-			const absolutePath = path.resolve(cline.cwd, relDirPath)
-
-			// Check if path is outside workspace
-			if (isPathOutsideWorkspace(absolutePath)) {
-				const userErrorMessage = t("tools:searchFiles.workspaceBoundaryError", { path: relDirPath })
-				const llmErrorMessage = `Cannot search outside workspace. Path '${relDirPath}' is outside the current workspace.`
-				cline.consecutiveMistakeCount++
-				cline.recordToolError("search_files")
-				await cline.say("error", userErrorMessage)
-				pushToolResult(llmErrorMessage)
-				return
-			}
-
 			const results = await regexSearchFiles(
 				cline.cwd,
 				absolutePath,

+ 0 - 3
src/i18n/locales/ca/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo sembla estar atrapat en un bucle, intentant la mateixa acció ({{toolName}}) repetidament. Això podria indicar un problema amb la seva estratègia actual. Considera reformular la tasca, proporcionar instruccions més específiques o guiar-lo cap a un enfocament diferent.",
 	"codebaseSearch": {
 		"approval": "Cercant '{{query}}' a la base de codi..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "No es pot cercar fora de l'espai de treball. El camí '{{path}}' està fora de l'espai de treball actual."
 	}
 }

+ 0 - 3
src/i18n/locales/de/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo scheint in einer Schleife festzustecken und versucht wiederholt dieselbe Aktion ({{toolName}}). Dies könnte auf ein Problem mit der aktuellen Strategie hindeuten. Überlege dir, die Aufgabe umzuformulieren, genauere Anweisungen zu geben oder Roo zu einem anderen Ansatz zu führen.",
 	"codebaseSearch": {
 		"approval": "Suche nach '{{query}}' im Codebase..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Kann nicht außerhalb des Arbeitsbereichs suchen. Pfad '{{path}}' liegt außerhalb des aktuellen Arbeitsbereichs."
 	}
 }

+ 0 - 3
src/i18n/locales/en/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo appears to be stuck in a loop, attempting the same action ({{toolName}}) repeatedly. This might indicate a problem with its current strategy. Consider rephrasing the task, providing more specific instructions, or guiding it towards a different approach.",
 	"codebaseSearch": {
 		"approval": "Searching for '{{query}}' in codebase..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Cannot search outside workspace. Path '{{path}}' is outside the current workspace."
 	}
 }

+ 0 - 3
src/i18n/locales/es/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo parece estar atrapado en un bucle, intentando la misma acción ({{toolName}}) repetidamente. Esto podría indicar un problema con su estrategia actual. Considera reformular la tarea, proporcionar instrucciones más específicas o guiarlo hacia un enfoque diferente.",
 	"codebaseSearch": {
 		"approval": "Buscando '{{query}}' en la base de código..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "No se puede buscar fuera del espacio de trabajo. La ruta '{{path}}' está fuera del espacio de trabajo actual."
 	}
 }

+ 0 - 3
src/i18n/locales/fr/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo semble être bloqué dans une boucle, tentant la même action ({{toolName}}) de façon répétée. Cela pourrait indiquer un problème avec sa stratégie actuelle. Envisage de reformuler la tâche, de fournir des instructions plus spécifiques ou de le guider vers une approche différente.",
 	"codebaseSearch": {
 		"approval": "Recherche de '{{query}}' dans la base de code..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Impossible de rechercher en dehors de l'espace de travail. Le chemin '{{path}}' est en dehors de l'espace de travail actuel."
 	}
 }

+ 0 - 3
src/i18n/locales/hi/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo एक लूप में फंसा हुआ लगता है, बार-बार एक ही क्रिया ({{toolName}}) को दोहरा रहा है। यह उसकी वर्तमान रणनीति में किसी समस्या का संकेत हो सकता है। कार्य को पुनः परिभाषित करने, अधिक विशिष्ट निर्देश देने, या उसे एक अलग दृष्टिकोण की ओर मार्गदर्शित करने पर विचार करें।",
 	"codebaseSearch": {
 		"approval": "कोडबेस में '{{query}}' खोज रहा है..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "वर्कस्पेस के बाहर खोज नहीं की जा सकती। पथ '{{path}}' वर्तमान वर्कस्पेस के बाहर है।"
 	}
 }

+ 0 - 3
src/i18n/locales/it/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo sembra essere bloccato in un ciclo, tentando ripetutamente la stessa azione ({{toolName}}). Questo potrebbe indicare un problema con la sua strategia attuale. Considera di riformulare l'attività, fornire istruzioni più specifiche o guidarlo verso un approccio diverso.",
 	"codebaseSearch": {
 		"approval": "Ricerca di '{{query}}' nella base di codice..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Impossibile cercare al di fuori dell'area di lavoro. Il percorso '{{path}}' è al di fuori dell'area di lavoro corrente."
 	}
 }

+ 0 - 3
src/i18n/locales/ja/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Rooが同じ操作({{toolName}})を繰り返し試みるループに陥っているようです。これは現在の方法に問題がある可能性を示しています。タスクの言い換え、より具体的な指示の提供、または別のアプローチへの誘導を検討してください。",
 	"codebaseSearch": {
 		"approval": "コードベースで '{{query}}' を検索中..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "ワークスペース外では検索できません。パス '{{path}}' は現在のワークスペース外にあります。"
 	}
 }

+ 0 - 3
src/i18n/locales/ko/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo가 같은 동작({{toolName}})을 반복적으로 시도하면서 루프에 갇힌 것 같습니다. 이는 현재 전략에 문제가 있을 수 있음을 나타냅니다. 작업을 다시 표현하거나, 더 구체적인 지침을 제공하거나, 다른 접근 방식으로 안내해 보세요.",
 	"codebaseSearch": {
 		"approval": "코드베이스에서 '{{query}}' 검색 중..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "워크스페이스 외부에서는 검색할 수 없습니다. 경로 '{{path}}'는 현재 워크스페이스 외부에 있습니다."
 	}
 }

+ 0 - 3
src/i18n/locales/nl/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo lijkt vast te zitten in een lus, waarbij hij herhaaldelijk dezelfde actie ({{toolName}}) probeert. Dit kan duiden op een probleem met de huidige strategie. Overweeg de taak te herformuleren, specifiekere instructies te geven of Roo naar een andere aanpak te leiden.",
 	"codebaseSearch": {
 		"approval": "Zoeken naar '{{query}}' in codebase..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Kan niet zoeken buiten de werkruimte. Pad '{{path}}' ligt buiten de huidige werkruimte."
 	}
 }

+ 0 - 3
src/i18n/locales/pl/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Wygląda na to, że Roo utknął w pętli, wielokrotnie próbując wykonać tę samą akcję ({{toolName}}). Może to wskazywać na problem z jego obecną strategią. Rozważ przeformułowanie zadania, podanie bardziej szczegółowych instrukcji lub nakierowanie go na inne podejście.",
 	"codebaseSearch": {
 		"approval": "Wyszukiwanie '{{query}}' w bazie kodu..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Nie można wyszukiwać poza obszarem roboczym. Ścieżka '{{path}}' znajduje się poza bieżącym obszarem roboczym."
 	}
 }

+ 0 - 3
src/i18n/locales/pt-BR/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo parece estar preso em um loop, tentando a mesma ação ({{toolName}}) repetidamente. Isso pode indicar um problema com sua estratégia atual. Considere reformular a tarefa, fornecer instruções mais específicas ou guiá-lo para uma abordagem diferente.",
 	"codebaseSearch": {
 		"approval": "Pesquisando '{{query}}' na base de código..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Não é possível pesquisar fora do espaço de trabalho. O caminho '{{path}}' está fora do espaço de trabalho atual."
 	}
 }

+ 0 - 3
src/i18n/locales/ru/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Похоже, что Roo застрял в цикле, многократно пытаясь выполнить одно и то же действие ({{toolName}}). Это может указывать на проблему с его текущей стратегией. Попробуйте переформулировать задачу, предоставить более конкретные инструкции или направить его к другому подходу.",
 	"codebaseSearch": {
 		"approval": "Поиск '{{query}}' в кодовой базе..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Невозможно выполнить поиск за пределами рабочего пространства. Путь '{{path}}' находится за пределами текущего рабочего пространства."
 	}
 }

+ 0 - 3
src/i18n/locales/tr/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo bir döngüye takılmış gibi görünüyor, aynı eylemi ({{toolName}}) tekrar tekrar deniyor. Bu, mevcut stratejisinde bir sorun olduğunu gösterebilir. Görevi yeniden ifade etmeyi, daha spesifik talimatlar vermeyi veya onu farklı bir yaklaşıma yönlendirmeyi düşünün.",
 	"codebaseSearch": {
 		"approval": "Kod tabanında '{{query}}' aranıyor..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Çalışma alanı dışında arama yapılamaz. '{{path}}' yolu mevcut çalışma alanının dışında."
 	}
 }

+ 0 - 3
src/i18n/locales/vi/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo dường như đang bị mắc kẹt trong một vòng lặp, liên tục cố gắng thực hiện cùng một hành động ({{toolName}}). Điều này có thể cho thấy vấn đề với chiến lược hiện tại. Hãy cân nhắc việc diễn đạt lại nhiệm vụ, cung cấp hướng dẫn cụ thể hơn, hoặc hướng Roo theo một cách tiếp cận khác.",
 	"codebaseSearch": {
 		"approval": "Đang tìm kiếm '{{query}}' trong cơ sở mã..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "Không thể tìm kiếm bên ngoài không gian làm việc. Đường dẫn '{{path}}' nằm ngoài không gian làm việc hiện tại."
 	}
 }

+ 0 - 3
src/i18n/locales/zh-CN/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo 似乎陷入循环,反复尝试同一操作 ({{toolName}})。这可能表明当前策略存在问题。请考虑重新描述任务、提供更具体的指示或引导其尝试不同的方法。",
 	"codebaseSearch": {
 		"approval": "正在搜索代码库中的 '{{query}}'..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "无法在工作区外搜索。路径 '{{path}}' 位于当前工作区外。"
 	}
 }

+ 0 - 3
src/i18n/locales/zh-TW/tools.json

@@ -7,8 +7,5 @@
 	"toolRepetitionLimitReached": "Roo 似乎陷入循環,反覆嘗試同一操作 ({{toolName}})。這可能表明目前策略存在問題。請考慮重新描述工作、提供更具體的指示或引導其嘗試不同的方法。",
 	"codebaseSearch": {
 		"approval": "正在搜尋程式碼庫中的「{{query}}」..."
-	},
-	"searchFiles": {
-		"workspaceBoundaryError": "無法在工作區外搜尋。路徑「{{path}}」位於目前工作區外。"
 	}
 }

+ 10 - 2
webview-ui/src/components/chat/ChatRow.tsx

@@ -560,13 +560,21 @@ export const ChatRowContent = ({
 							<span style={{ fontWeight: "bold" }}>
 								{message.type === "ask" ? (
 									<Trans
-										i18nKey="chat:directoryOperations.wantsToSearch"
+										i18nKey={
+											tool.isOutsideWorkspace
+												? "chat:directoryOperations.wantsToSearchOutsideWorkspace"
+												: "chat:directoryOperations.wantsToSearch"
+										}
 										components={{ code: <code>{tool.regex}</code> }}
 										values={{ regex: tool.regex }}
 									/>
 								) : (
 									<Trans
-										i18nKey="chat:directoryOperations.didSearch"
+										i18nKey={
+											tool.isOutsideWorkspace
+												? "chat:directoryOperations.didSearchOutsideWorkspace"
+												: "chat:directoryOperations.didSearch"
+										}
 										components={{ code: <code>{tool.regex}</code> }}
 										values={{ regex: tool.regex }}
 									/>

+ 3 - 1
webview-ui/src/i18n/locales/ca/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo vol veure noms de definicions de codi font utilitzats en aquest directori:",
 		"didViewDefinitions": "Roo ha vist noms de definicions de codi font utilitzats en aquest directori:",
 		"wantsToSearch": "Roo vol cercar en aquest directori <code>{{regex}}</code>:",
-		"didSearch": "Roo ha cercat en aquest directori <code>{{regex}}</code>:"
+		"didSearch": "Roo ha cercat en aquest directori <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo vol cercar en aquest directori (fora de l'espai de treball) <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo ha cercat en aquest directori (fora de l'espai de treball) <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Sortida de l'ordre",
 	"response": "Resposta",

+ 3 - 1
webview-ui/src/i18n/locales/de/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo möchte Quellcode-Definitionsnamen in diesem Verzeichnis anzeigen:",
 		"didViewDefinitions": "Roo hat Quellcode-Definitionsnamen in diesem Verzeichnis angezeigt:",
 		"wantsToSearch": "Roo möchte dieses Verzeichnis nach <code>{{regex}}</code> durchsuchen:",
-		"didSearch": "Roo hat dieses Verzeichnis nach <code>{{regex}}</code> durchsucht:"
+		"didSearch": "Roo hat dieses Verzeichnis nach <code>{{regex}}</code> durchsucht:",
+		"wantsToSearchOutsideWorkspace": "Roo möchte dieses Verzeichnis (außerhalb des Arbeitsbereichs) nach <code>{{regex}}</code> durchsuchen:",
+		"didSearchOutsideWorkspace": "Roo hat dieses Verzeichnis (außerhalb des Arbeitsbereichs) nach <code>{{regex}}</code> durchsucht:"
 	},
 	"commandOutput": "Befehlsausgabe",
 	"response": "Antwort",

+ 3 - 1
webview-ui/src/i18n/locales/en/chat.json

@@ -172,7 +172,9 @@
 		"wantsToViewDefinitions": "Roo wants to view source code definition names used in this directory:",
 		"didViewDefinitions": "Roo viewed source code definition names used in this directory:",
 		"wantsToSearch": "Roo wants to search this directory for <code>{{regex}}</code>:",
-		"didSearch": "Roo searched this directory for <code>{{regex}}</code>:"
+		"didSearch": "Roo searched this directory for <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo wants to search this directory (outside workspace) for <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo searched this directory (outside workspace) for <code>{{regex}}</code>:"
 	},
 	"codebaseSearch": {
 		"wantsToSearch": "Roo wants to search the codebase for <code>{{query}}</code>:",

+ 3 - 1
webview-ui/src/i18n/locales/es/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo quiere ver nombres de definiciones de código fuente utilizados en este directorio:",
 		"didViewDefinitions": "Roo vio nombres de definiciones de código fuente utilizados en este directorio:",
 		"wantsToSearch": "Roo quiere buscar en este directorio <code>{{regex}}</code>:",
-		"didSearch": "Roo buscó en este directorio <code>{{regex}}</code>:"
+		"didSearch": "Roo buscó en este directorio <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo quiere buscar en este directorio (fuera del espacio de trabajo) <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo buscó en este directorio (fuera del espacio de trabajo) <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Salida del comando",
 	"response": "Respuesta",

+ 3 - 1
webview-ui/src/i18n/locales/fr/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo veut voir les noms de définitions de code source utilisés dans ce répertoire :",
 		"didViewDefinitions": "Roo a vu les noms de définitions de code source utilisés dans ce répertoire :",
 		"wantsToSearch": "Roo veut rechercher dans ce répertoire <code>{{regex}}</code> :",
-		"didSearch": "Roo a recherché dans ce répertoire <code>{{regex}}</code> :"
+		"didSearch": "Roo a recherché dans ce répertoire <code>{{regex}}</code> :",
+		"wantsToSearchOutsideWorkspace": "Roo veut rechercher dans ce répertoire (hors espace de travail) <code>{{regex}}</code> :",
+		"didSearchOutsideWorkspace": "Roo a recherché dans ce répertoire (hors espace de travail) <code>{{regex}}</code> :"
 	},
 	"commandOutput": "Sortie de commande",
 	"response": "Réponse",

+ 3 - 1
webview-ui/src/i18n/locales/hi/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo इस निर्देशिका में उपयोग किए गए सोर्स कोड परिभाषा नामों को देखना चाहता है:",
 		"didViewDefinitions": "Roo ने इस निर्देशिका में उपयोग किए गए सोर्स कोड परिभाषा नामों को देखा:",
 		"wantsToSearch": "Roo इस निर्देशिका में <code>{{regex}}</code> के लिए खोज करना चाहता है:",
-		"didSearch": "Roo ने इस निर्देशिका में <code>{{regex}}</code> के लिए खोज की:"
+		"didSearch": "Roo ने इस निर्देशिका में <code>{{regex}}</code> के लिए खोज की:",
+		"wantsToSearchOutsideWorkspace": "Roo इस निर्देशिका (कार्यक्षेत्र के बाहर) में <code>{{regex}}</code> के लिए खोज करना चाहता है:",
+		"didSearchOutsideWorkspace": "Roo ने इस निर्देशिका (कार्यक्षेत्र के बाहर) में <code>{{regex}}</code> के लिए खोज की:"
 	},
 	"commandOutput": "कमांड आउटपुट",
 	"response": "प्रतिक्रिया",

+ 3 - 1
webview-ui/src/i18n/locales/it/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo vuole visualizzare i nomi delle definizioni di codice sorgente utilizzate in questa directory:",
 		"didViewDefinitions": "Roo ha visualizzato i nomi delle definizioni di codice sorgente utilizzate in questa directory:",
 		"wantsToSearch": "Roo vuole cercare in questa directory <code>{{regex}}</code>:",
-		"didSearch": "Roo ha cercato in questa directory <code>{{regex}}</code>:"
+		"didSearch": "Roo ha cercato in questa directory <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo vuole cercare in questa directory (fuori dall'area di lavoro) <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo ha cercato in questa directory (fuori dall'area di lavoro) <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Output del comando",
 	"response": "Risposta",

+ 3 - 1
webview-ui/src/i18n/locales/ja/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Rooはこのディレクトリで使用されているソースコード定義名を表示したい:",
 		"didViewDefinitions": "Rooはこのディレクトリで使用されているソースコード定義名を表示しました:",
 		"wantsToSearch": "Rooはこのディレクトリで <code>{{regex}}</code> を検索したい:",
-		"didSearch": "Rooはこのディレクトリで <code>{{regex}}</code> を検索しました:"
+		"didSearch": "Rooはこのディレクトリで <code>{{regex}}</code> を検索しました:",
+		"wantsToSearchOutsideWorkspace": "Rooはこのディレクトリ(ワークスペース外)で <code>{{regex}}</code> を検索したい:",
+		"didSearchOutsideWorkspace": "Rooはこのディレクトリ(ワークスペース外)で <code>{{regex}}</code> を検索しました:"
 	},
 	"commandOutput": "コマンド出力",
 	"response": "応答",

+ 3 - 1
webview-ui/src/i18n/locales/ko/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo가 이 디렉토리에서 사용된 소스 코드 정의 이름을 보고 싶어합니다:",
 		"didViewDefinitions": "Roo가 이 디렉토리에서 사용된 소스 코드 정의 이름을 보았습니다:",
 		"wantsToSearch": "Roo가 이 디렉토리에서 <code>{{regex}}</code>을(를) 검색하고 싶어합니다:",
-		"didSearch": "Roo가 이 디렉토리에서 <code>{{regex}}</code>을(를) 검색했습니다:"
+		"didSearch": "Roo가 이 디렉토리에서 <code>{{regex}}</code>을(를) 검색했습니다:",
+		"wantsToSearchOutsideWorkspace": "Roo가 이 디렉토리(워크스페이스 외부)에서 <code>{{regex}}</code>을(를) 검색하고 싶어합니다:",
+		"didSearchOutsideWorkspace": "Roo가 이 디렉토리(워크스페이스 외부)에서 <code>{{regex}}</code>을(를) 검색했습니다:"
 	},
 	"commandOutput": "명령 출력",
 	"response": "응답",

+ 3 - 1
webview-ui/src/i18n/locales/nl/chat.json

@@ -158,7 +158,9 @@
 		"wantsToViewDefinitions": "Roo wil broncode-definitienamen bekijken die in deze map worden gebruikt:",
 		"didViewDefinitions": "Roo heeft broncode-definitienamen bekeken die in deze map worden gebruikt:",
 		"wantsToSearch": "Roo wil deze map doorzoeken op <code>{{regex}}</code>:",
-		"didSearch": "Roo heeft deze map doorzocht op <code>{{regex}}</code>:"
+		"didSearch": "Roo heeft deze map doorzocht op <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo wil deze map (buiten werkruimte) doorzoeken op <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo heeft deze map (buiten werkruimte) doorzocht op <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Commando-uitvoer",
 	"response": "Antwoord",

+ 3 - 1
webview-ui/src/i18n/locales/pl/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo chce zobaczyć nazwy definicji kodu źródłowego używane w tym katalogu:",
 		"didViewDefinitions": "Roo zobaczył nazwy definicji kodu źródłowego używane w tym katalogu:",
 		"wantsToSearch": "Roo chce przeszukać ten katalog w poszukiwaniu <code>{{regex}}</code>:",
-		"didSearch": "Roo przeszukał ten katalog w poszukiwaniu <code>{{regex}}</code>:"
+		"didSearch": "Roo przeszukał ten katalog w poszukiwaniu <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo chce przeszukać ten katalog (poza obszarem roboczym) w poszukiwaniu <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo przeszukał ten katalog (poza obszarem roboczym) w poszukiwaniu <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Wyjście polecenia",
 	"response": "Odpowiedź",

+ 3 - 1
webview-ui/src/i18n/locales/pt-BR/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo quer visualizar nomes de definição de código-fonte usados neste diretório:",
 		"didViewDefinitions": "Roo visualizou nomes de definição de código-fonte usados neste diretório:",
 		"wantsToSearch": "Roo quer pesquisar neste diretório por <code>{{regex}}</code>:",
-		"didSearch": "Roo pesquisou neste diretório por <code>{{regex}}</code>:"
+		"didSearch": "Roo pesquisou neste diretório por <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo quer pesquisar neste diretório (fora do espaço de trabalho) por <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo pesquisou neste diretório (fora do espaço de trabalho) por <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Saída do comando",
 	"response": "Resposta",

+ 3 - 1
webview-ui/src/i18n/locales/ru/chat.json

@@ -158,7 +158,9 @@
 		"wantsToViewDefinitions": "Roo хочет просмотреть имена определений исходного кода в этой директории:",
 		"didViewDefinitions": "Roo просмотрел имена определений исходного кода в этой директории:",
 		"wantsToSearch": "Roo хочет выполнить поиск в этой директории по <code>{{regex}}</code>:",
-		"didSearch": "Roo выполнил поиск в этой директории по <code>{{regex}}</code>:"
+		"didSearch": "Roo выполнил поиск в этой директории по <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo хочет выполнить поиск в этой директории (вне рабочего пространства) по <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo выполнил поиск в этой директории (вне рабочего пространства) по <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Вывод команды",
 	"response": "Ответ",

+ 3 - 1
webview-ui/src/i18n/locales/tr/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo bu dizinde kullanılan kaynak kod tanımlama isimlerini görüntülemek istiyor:",
 		"didViewDefinitions": "Roo bu dizinde kullanılan kaynak kod tanımlama isimlerini görüntüledi:",
 		"wantsToSearch": "Roo bu dizinde <code>{{regex}}</code> için arama yapmak istiyor:",
-		"didSearch": "Roo bu dizinde <code>{{regex}}</code> için arama yaptı:"
+		"didSearch": "Roo bu dizinde <code>{{regex}}</code> için arama yaptı:",
+		"wantsToSearchOutsideWorkspace": "Roo bu dizinde (çalışma alanı dışında) <code>{{regex}}</code> için arama yapmak istiyor:",
+		"didSearchOutsideWorkspace": "Roo bu dizinde (çalışma alanı dışında) <code>{{regex}}</code> için arama yaptı:"
 	},
 	"commandOutput": "Komut Çıktısı",
 	"response": "Yanıt",

+ 3 - 1
webview-ui/src/i18n/locales/vi/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo muốn xem tên định nghĩa mã nguồn được sử dụng trong thư mục này:",
 		"didViewDefinitions": "Roo đã xem tên định nghĩa mã nguồn được sử dụng trong thư mục này:",
 		"wantsToSearch": "Roo muốn tìm kiếm trong thư mục này cho <code>{{regex}}</code>:",
-		"didSearch": "Roo đã tìm kiếm trong thư mục này cho <code>{{regex}}</code>:"
+		"didSearch": "Roo đã tìm kiếm trong thư mục này cho <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo muốn tìm kiếm trong thư mục này (ngoài không gian làm việc) cho <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo đã tìm kiếm trong thư mục này (ngoài không gian làm việc) cho <code>{{regex}}</code>:"
 	},
 	"commandOutput": "Kết quả lệnh",
 	"response": "Phản hồi",

+ 3 - 1
webview-ui/src/i18n/locales/zh-CN/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo想查看此目录中使用的源代码定义名称:",
 		"didViewDefinitions": "Roo已查看此目录中使用的源代码定义名称:",
 		"wantsToSearch": "需要搜索内容: {{regex}}",
-		"didSearch": "已完成内容搜索: {{regex}}"
+		"didSearch": "已完成内容搜索: {{regex}}",
+		"wantsToSearchOutsideWorkspace": "需要搜索内容(工作区外): {{regex}}",
+		"didSearchOutsideWorkspace": "已完成内容搜索(工作区外): {{regex}}"
 	},
 	"commandOutput": "命令输出",
 	"response": "响应",

+ 3 - 1
webview-ui/src/i18n/locales/zh-TW/chat.json

@@ -163,7 +163,9 @@
 		"wantsToViewDefinitions": "Roo 想要檢視此目錄中使用的原始碼定義名稱:",
 		"didViewDefinitions": "Roo 已檢視此目錄中使用的原始碼定義名稱:",
 		"wantsToSearch": "Roo 想要在此目錄中搜尋 <code>{{regex}}</code>:",
-		"didSearch": "Roo 已在此目錄中搜尋 <code>{{regex}}</code>:"
+		"didSearch": "Roo 已在此目錄中搜尋 <code>{{regex}}</code>:",
+		"wantsToSearchOutsideWorkspace": "Roo 想要在此目錄(工作區外)中搜尋 <code>{{regex}}</code>:",
+		"didSearchOutsideWorkspace": "Roo 已在此目錄(工作區外)中搜尋 <code>{{regex}}</code>:"
 	},
 	"commandOutput": "命令輸出",
 	"response": "回應",