summaryrefslogtreecommitdiffhomepage
path: root/internal/llm/tools/edit.go
diff options
context:
space:
mode:
authorKujtim Hoxha <[email protected]>2025-04-16 20:06:23 +0200
committerKujtim Hoxha <[email protected]>2025-04-21 13:42:00 +0200
commitbbfa60c787f2ec459f1689b9a650ddbec9693ed9 (patch)
treef7f2aa31c460c8cc22ec40cc299c386277152241 /internal/llm/tools/edit.go
parent76b4065f17b87a63092acfd98c997bab53700b35 (diff)
downloadopencode-bbfa60c787f2ec459f1689b9a650ddbec9693ed9.tar.gz
opencode-bbfa60c787f2ec459f1689b9a650ddbec9693ed9.zip
reimplement agent,provider and add file history
Diffstat (limited to 'internal/llm/tools/edit.go')
-rw-r--r--internal/llm/tools/edit.go75
1 files changed, 72 insertions, 3 deletions
diff --git a/internal/llm/tools/edit.go b/internal/llm/tools/edit.go
index 08d6d446c..148e7aba7 100644
--- a/internal/llm/tools/edit.go
+++ b/internal/llm/tools/edit.go
@@ -11,6 +11,7 @@ import (
"github.com/kujtimiihoxha/termai/internal/config"
"github.com/kujtimiihoxha/termai/internal/diff"
+ "github.com/kujtimiihoxha/termai/internal/history"
"github.com/kujtimiihoxha/termai/internal/lsp"
"github.com/kujtimiihoxha/termai/internal/permission"
)
@@ -35,6 +36,7 @@ type EditResponseMetadata struct {
type editTool struct {
lspClients map[string]*lsp.Client
permissions permission.Service
+ files history.Service
}
const (
@@ -88,10 +90,11 @@ When making edits:
Remember: when making multiple file edits in a row to the same file, you should prefer to send all edits in a single message with multiple calls to this tool, rather than multiple messages with a single call each.`
)
-func NewEditTool(lspClients map[string]*lsp.Client, permissions permission.Service) BaseTool {
+func NewEditTool(lspClients map[string]*lsp.Client, permissions permission.Service, files history.Service) BaseTool {
return &editTool{
lspClients: lspClients,
permissions: permissions,
+ files: files,
}
}
@@ -153,6 +156,11 @@ func (e *editTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
if err != nil {
return response, nil
}
+ if response.IsError {
+ // Return early if there was an error during content replacement
+ // This prevents unnecessary LSP diagnostics processing
+ return response, nil
+ }
waitForLspDiagnostics(ctx, params.FilePath, e.lspClients)
text := fmt.Sprintf("<result>\n%s\n</result>\n", response.Content)
@@ -208,6 +216,20 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
return ToolResponse{}, fmt.Errorf("failed to write file: %w", err)
}
+ // File can't be in the history so we create a new file history
+ _, err = e.files.Create(ctx, sessionID, filePath, "")
+ if err != nil {
+ // Log error but don't fail the operation
+ return ToolResponse{}, fmt.Errorf("error creating file history: %w", err)
+ }
+
+ // Add the new content to the file history
+ _, err = e.files.CreateVersion(ctx, sessionID, filePath, content)
+ if err != nil {
+ // Log error but don't fail the operation
+ fmt.Printf("Error creating file history version: %v\n", err)
+ }
+
recordFileWrite(filePath)
recordFileRead(filePath)
@@ -298,6 +320,29 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
if err != nil {
return ToolResponse{}, fmt.Errorf("failed to write file: %w", err)
}
+
+ // Check if file exists in history
+ file, err := e.files.GetByPathAndSession(ctx, filePath, sessionID)
+ if err != nil {
+ _, err = e.files.Create(ctx, sessionID, filePath, oldContent)
+ if err != nil {
+ // Log error but don't fail the operation
+ return ToolResponse{}, fmt.Errorf("error creating file history: %w", err)
+ }
+ }
+ if file.Content != oldContent {
+ // User Manually changed the content store an intermediate version
+ _, err = e.files.CreateVersion(ctx, sessionID, filePath, oldContent)
+ if err != nil {
+ fmt.Printf("Error creating file history version: %v\n", err)
+ }
+ }
+ // Store the new version
+ _, err = e.files.CreateVersion(ctx, sessionID, filePath, "")
+ if err != nil {
+ fmt.Printf("Error creating file history version: %v\n", err)
+ }
+
recordFileWrite(filePath)
recordFileRead(filePath)
@@ -356,6 +401,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
newContent := oldContent[:index] + newString + oldContent[index+len(oldString):]
+ if oldContent == newContent {
+ return NewTextErrorResponse("new content is the same as old content. No changes made."), nil
+ }
sessionID, messageID := GetContextValues(ctx)
if sessionID == "" || messageID == "" {
@@ -374,8 +422,7 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
Description: fmt.Sprintf("Replace content in file %s", filePath),
Params: EditPermissionsParams{
FilePath: filePath,
-
- Diff: diff,
+ Diff: diff,
},
},
)
@@ -388,6 +435,28 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
return ToolResponse{}, fmt.Errorf("failed to write file: %w", err)
}
+ // Check if file exists in history
+ file, err := e.files.GetByPathAndSession(ctx, filePath, sessionID)
+ if err != nil {
+ _, err = e.files.Create(ctx, sessionID, filePath, oldContent)
+ if err != nil {
+ // Log error but don't fail the operation
+ return ToolResponse{}, fmt.Errorf("error creating file history: %w", err)
+ }
+ }
+ if file.Content != oldContent {
+ // User Manually changed the content store an intermediate version
+ _, err = e.files.CreateVersion(ctx, sessionID, filePath, oldContent)
+ if err != nil {
+ fmt.Printf("Error creating file history version: %v\n", err)
+ }
+ }
+ // Store the new version
+ _, err = e.files.CreateVersion(ctx, sessionID, filePath, newContent)
+ if err != nil {
+ fmt.Printf("Error creating file history version: %v\n", err)
+ }
+
recordFileWrite(filePath)
recordFileRead(filePath)