diff --git a/internal/fsext/fileutil.go b/internal/fsext/fileutil.go index aee72bb1a5fa1affbd36e86e73f02d8407fa982b..d0d47eaed4aa946db50a9c5c4a50a0b214e92b0b 100644 --- a/internal/fsext/fileutil.go +++ b/internal/fsext/fileutil.go @@ -262,3 +262,23 @@ func DirTrim(pwd string, lim int) string { out = filepath.Join("~", out) return out } + +// PathOrPrefix returns the prefix if the path starts with it, or falls back to +// the path otherwise. +func PathOrPrefix(path, prefix string) string { + if HasPrefix(path, prefix) { + return prefix + } + return path +} + +// HasPrefix checks if the given path starts with the specified prefix. +func HasPrefix(path, prefix string) bool { + if abs, err := filepath.Abs(path); err == nil { + path = abs + } + if abs, err := filepath.Abs(prefix); err == nil { + prefix = abs + } + return strings.HasPrefix(path, prefix) +} diff --git a/internal/llm/tools/edit.go b/internal/llm/tools/edit.go index 36af176af8d8e531e30707dffad33b66ebb8d33b..fd9ed81d55bc96e7b7767adad2f1186d88d97023 100644 --- a/internal/llm/tools/edit.go +++ b/internal/llm/tools/edit.go @@ -11,6 +11,7 @@ import ( "time" "github.com/charmbracelet/crush/internal/diff" + "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/history" "github.com/charmbracelet/crush/internal/lsp" @@ -215,14 +216,10 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string, content, strings.TrimPrefix(filePath, e.workingDir), ) - permissionPath := filePath - if strings.HasPrefix(filePath, e.workingDir) { - permissionPath = e.workingDir - } p := e.permissions.Request( permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(filePath, e.workingDir), ToolCallID: call.ID, ToolName: EditToolName, Action: "write", @@ -340,15 +337,10 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string strings.TrimPrefix(filePath, e.workingDir), ) - permissionPath := filePath - if strings.HasPrefix(filePath, e.workingDir) { - permissionPath = e.workingDir - } - p := e.permissions.Request( permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(filePath, e.workingDir), ToolCallID: call.ID, ToolName: EditToolName, Action: "write", @@ -476,14 +468,10 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS strings.TrimPrefix(filePath, e.workingDir), ) - permissionPath := filePath - if strings.HasPrefix(filePath, e.workingDir) { - permissionPath = e.workingDir - } p := e.permissions.Request( permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(filePath, e.workingDir), ToolCallID: call.ID, ToolName: EditToolName, Action: "write", diff --git a/internal/llm/tools/multiedit.go b/internal/llm/tools/multiedit.go index 86a734611de35eb9beda7b78b6af338a985c7be9..271603a5b0f97b78bb7dbe53b93a060cff48b9cc 100644 --- a/internal/llm/tools/multiedit.go +++ b/internal/llm/tools/multiedit.go @@ -11,6 +11,7 @@ import ( "time" "github.com/charmbracelet/crush/internal/diff" + "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/history" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/permission" @@ -250,14 +251,9 @@ func (m *multiEditTool) processMultiEditWithCreation(ctx context.Context, params // Check permissions _, additions, removals := diff.GenerateDiff("", currentContent, strings.TrimPrefix(params.FilePath, m.workingDir)) - permissionPath := params.FilePath - if strings.HasPrefix(params.FilePath, m.workingDir) { - permissionPath = m.workingDir - } - p := m.permissions.Request(permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(params.FilePath, m.workingDir), ToolCallID: call.ID, ToolName: MultiEditToolName, Action: "write", @@ -364,13 +360,9 @@ func (m *multiEditTool) processMultiEditExistingFile(ctx context.Context, params // Generate diff and check permissions _, additions, removals := diff.GenerateDiff(oldContent, currentContent, strings.TrimPrefix(params.FilePath, m.workingDir)) - permissionPath := params.FilePath - if strings.HasPrefix(params.FilePath, m.workingDir) { - permissionPath = m.workingDir - } p := m.permissions.Request(permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(params.FilePath, m.workingDir), ToolCallID: call.ID, ToolName: MultiEditToolName, Action: "write", diff --git a/internal/llm/tools/write.go b/internal/llm/tools/write.go index da8722d5646a058b9241fbe487b0ecc6c95d82ae..d719337a971cb09babd47753444d761586806fdd 100644 --- a/internal/llm/tools/write.go +++ b/internal/llm/tools/write.go @@ -11,6 +11,7 @@ import ( "time" "github.com/charmbracelet/crush/internal/diff" + "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/history" "github.com/charmbracelet/crush/internal/lsp" @@ -172,15 +173,10 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error strings.TrimPrefix(filePath, w.workingDir), ) - permissionPath := filePath - if strings.HasPrefix(filePath, w.workingDir) { - permissionPath = w.workingDir - } - p := w.permissions.Request( permission.CreatePermissionRequest{ SessionID: sessionID, - Path: permissionPath, + Path: fsext.PathOrPrefix(filePath, w.workingDir), ToolCallID: call.ID, ToolName: WriteToolName, Action: "write",