mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: handle absolute paths in WriteToFileTool consistently with other tools
This fix addresses issue #11208 where WriteToFileTool would fail with EACCES permission denied when the LLM outputs an absolute path like "/plans" instead of a relative path. The fix adds the same absolute path handling that already exists in SearchReplaceTool and EditFileTool: - Detect if the provided path is absolute using path.isAbsolute() - Convert absolute paths to relative paths using path.relative(task.cwd, absolutePath) This ensures that absolute paths get normalized to workspace-relative paths rather than attempting to write to system root level directories. Also adds two new tests for absolute path handling to prevent regression.
This commit is contained in:
parent
aa49871a5d
commit
44c3fd4e57
2 changed files with 39 additions and 2 deletions
|
|
@ -28,10 +28,9 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
|
|||
|
||||
async execute(params: WriteToFileParams, task: Task, callbacks: ToolCallbacks): Promise<void> {
|
||||
const { pushToolResult, handleError, askApproval } = callbacks
|
||||
const relPath = params.path
|
||||
let newContent = params.content
|
||||
|
||||
if (!relPath) {
|
||||
if (!params.path) {
|
||||
task.consecutiveMistakeCount++
|
||||
task.recordToolError("write_to_file")
|
||||
pushToolResult(await task.sayAndCreateMissingParamError("write_to_file", "path"))
|
||||
|
|
@ -39,6 +38,14 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
|
|||
return
|
||||
}
|
||||
|
||||
// Determine relative path - path can be absolute or relative
|
||||
let relPath: string
|
||||
if (path.isAbsolute(params.path)) {
|
||||
relPath = path.relative(task.cwd, params.path)
|
||||
} else {
|
||||
relPath = params.path
|
||||
}
|
||||
|
||||
if (newContent === undefined) {
|
||||
task.consecutiveMistakeCount++
|
||||
task.recordToolError("write_to_file")
|
||||
|
|
|
|||
|
|
@ -244,6 +244,36 @@ describe("writeToFileTool", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("absolute path handling", () => {
|
||||
it("converts absolute path to relative path within workspace", async () => {
|
||||
// Set up a workspace directory
|
||||
mockCline.cwd = "/workspace/project"
|
||||
|
||||
// Provide an absolute path that's within the workspace
|
||||
const absoluteInputPath = "/workspace/project/plans/architecture.md"
|
||||
|
||||
await executeWriteFileTool({ path: absoluteInputPath }, { accessAllowed: true })
|
||||
|
||||
// The path should be converted to relative and used for access validation
|
||||
expect(mockCline.rooIgnoreController.validateAccess).toHaveBeenCalledWith("plans/architecture.md")
|
||||
})
|
||||
|
||||
it("handles absolute path at root level (issue #11208)", async () => {
|
||||
// This reproduces the bug where LLM outputs "/plans" as an absolute path
|
||||
mockCline.cwd = "/workspace/project"
|
||||
|
||||
// Absolute path "/plans" would resolve to root without the fix
|
||||
const absoluteInputPath = "/plans"
|
||||
|
||||
await executeWriteFileTool({ path: absoluteInputPath }, { accessAllowed: true })
|
||||
|
||||
// The path should be converted to a relative path (relative to cwd)
|
||||
// path.relative("/workspace/project", "/plans") = "../../../plans" on Unix
|
||||
// This is safer than trying to write to system root
|
||||
expect(mockCline.rooIgnoreController.validateAccess).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("file existence detection", () => {
|
||||
it.skipIf(process.platform === "win32")("detects existing file and sets editType to modify", async () => {
|
||||
await executeWriteFileTool({}, { fileExists: true })
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue