diff options
| author | Kujtim Hoxha <[email protected]> | 2025-04-08 19:42:59 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-04-08 19:42:59 +0200 |
| commit | 124bd57c507fdcbb56ab27137cbe892f12e1b48f (patch) | |
| tree | 894d335a5f2f6587a19e94f139f681b91b01e877 /internal/llm/tools/write.go | |
| parent | 5acf0cba6040aaf90acb5dcacd3e4127d6833ac5 (diff) | |
| parent | c571283ac26cdf03be5a1d5c1e36051e3b7ea7be (diff) | |
| download | opencode-124bd57c507fdcbb56ab27137cbe892f12e1b48f.tar.gz opencode-124bd57c507fdcbb56ab27137cbe892f12e1b48f.zip | |
Merge pull request #24 from kujtimiihoxha/cleanup-tools
Cleanup tools
Diffstat (limited to 'internal/llm/tools/write.go')
| -rw-r--r-- | internal/llm/tools/write.go | 105 |
1 files changed, 47 insertions, 58 deletions
diff --git a/internal/llm/tools/write.go b/internal/llm/tools/write.go index 86c9be37e..7b698d2d8 100644 --- a/internal/llm/tools/write.go +++ b/internal/llm/tools/write.go @@ -13,14 +13,6 @@ import ( "github.com/kujtimiihoxha/termai/internal/permission" ) -type writeTool struct { - lspClients map[string]*lsp.Client -} - -const ( - WriteToolName = "write" -) - type WriteParams struct { FilePath string `json:"file_path"` Content string `json:"content"` @@ -31,10 +23,54 @@ type WritePermissionsParams struct { Content string `json:"content"` } +type writeTool struct { + lspClients map[string]*lsp.Client + permissions permission.Service +} + +const ( + WriteToolName = "write" + writeDescription = `File writing tool that creates or updates files in the filesystem, allowing you to save or modify text content. + +WHEN TO USE THIS TOOL: +- Use when you need to create a new file +- Helpful for updating existing files with modified content +- Perfect for saving generated code, configurations, or text data + +HOW TO USE: +- Provide the path to the file you want to write +- Include the content to be written to the file +- The tool will create any necessary parent directories + +FEATURES: +- Can create new files or overwrite existing ones +- Creates parent directories automatically if they don't exist +- Checks if the file has been modified since last read for safety +- Avoids unnecessary writes when content hasn't changed + +LIMITATIONS: +- You should read a file before writing to it to avoid conflicts +- Cannot append to files (rewrites the entire file) + + +TIPS: +- Use the View tool first to examine existing files before modifying them +- Use the LS tool to verify the correct location when creating new files +- Combine with Glob and Grep tools to find and modify multiple files +- Always include descriptive comments when making changes to existing code` +) + +func NewWriteTool(lspClients map[string]*lsp.Client, permissions permission.Service) BaseTool { + return &writeTool{ + lspClients: lspClients, + permissions: permissions, + } +} + func (w *writeTool) Info() ToolInfo { return ToolInfo{ Name: WriteToolName, - Description: writeDescription(), + Description: writeDescription, Parameters: map[string]any{ "file_path": map[string]any{ "type": "string", @@ -49,7 +85,6 @@ func (w *writeTool) Info() ToolInfo { } } -// Run implements Tool. func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) { var params WriteParams if err := json.Unmarshal([]byte(call.Input), ¶ms); err != nil { @@ -64,20 +99,17 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error return NewTextErrorResponse("content is required"), nil } - // Handle relative paths filePath := params.FilePath if !filepath.IsAbs(filePath) { filePath = filepath.Join(config.WorkingDirectory(), filePath) } - // Check if file exists and is a directory fileInfo, err := os.Stat(filePath) if err == nil { if fileInfo.IsDir() { return NewTextErrorResponse(fmt.Sprintf("Path is a directory, not a file: %s", filePath)), nil } - // Check if file was modified since last read modTime := fileInfo.ModTime() lastRead := getLastReadTime(filePath) if modTime.After(lastRead) { @@ -85,7 +117,6 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error filePath, modTime.Format(time.RFC3339), lastRead.Format(time.RFC3339))), nil } - // Optional: Get old content for diff oldContent, readErr := os.ReadFile(filePath) if readErr == nil && string(oldContent) == params.Content { return NewTextErrorResponse(fmt.Sprintf("File %s already contains the exact content. No changes made.", filePath)), nil @@ -94,13 +125,11 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error return NewTextErrorResponse(fmt.Sprintf("Failed to access file: %s", err)), nil } - // Create parent directories if needed dir := filepath.Dir(filePath) if err = os.MkdirAll(dir, 0o755); err != nil { return NewTextErrorResponse(fmt.Sprintf("Failed to create parent directories: %s", err)), nil } - // Get old content for diff if file exists oldContent := "" if fileInfo != nil && !fileInfo.IsDir() { oldBytes, readErr := os.ReadFile(filePath) @@ -108,8 +137,8 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error oldContent = string(oldBytes) } } - - p := permission.Default.Request( + + p := w.permissions.Request( permission.CreatePermissionRequest{ Path: filePath, ToolName: WriteToolName, @@ -125,16 +154,13 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error return NewTextErrorResponse(fmt.Sprintf("Permission denied to create file: %s", filePath)), nil } - // Write the file err = os.WriteFile(filePath, []byte(params.Content), 0o644) if err != nil { return NewTextErrorResponse(fmt.Sprintf("Failed to write file: %s", err)), nil } - // Record the file write recordFileWrite(filePath) recordFileRead(filePath) - // Wait for LSP diagnostics after writing the file waitForLspDiagnostics(ctx, filePath, w.lspClients) result := fmt.Sprintf("File successfully written: %s", filePath) @@ -142,40 +168,3 @@ func (w *writeTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error result += appendDiagnostics(filePath, w.lspClients) return NewTextResponse(result), nil } - -func writeDescription() string { - return `File writing tool that creates or updates files in the filesystem, allowing you to save or modify text content. - -WHEN TO USE THIS TOOL: -- Use when you need to create a new file -- Helpful for updating existing files with modified content -- Perfect for saving generated code, configurations, or text data - -HOW TO USE: -- Provide the path to the file you want to write -- Include the content to be written to the file -- The tool will create any necessary parent directories - -FEATURES: -- Can create new files or overwrite existing ones -- Creates parent directories automatically if they don't exist -- Checks if the file has been modified since last read for safety -- Avoids unnecessary writes when content hasn't changed - -LIMITATIONS: -- You should read a file before writing to it to avoid conflicts -- Cannot append to files (rewrites the entire file) - - -TIPS: -- Use the View tool first to examine existing files before modifying them -- Use the LS tool to verify the correct location when creating new files -- Combine with Glob and Grep tools to find and modify multiple files -- Always include descriptive comments when making changes to existing code` -} - -func NewWriteTool(lspClients map[string]*lsp.Client) BaseTool { - return &writeTool{ - lspClients, - } -} |
