grokkit/cmd/edit.go

92 lines
2.4 KiB
Go
Raw Normal View History

2026-02-28 18:03:12 +00:00
package cmd
2026-02-28 18:28:27 +00:00
2026-02-28 19:56:23 +00:00
import (
"bufio"
2026-02-28 19:56:23 +00:00
"fmt"
"os"
"strings"
2026-02-28 19:56:23 +00:00
"github.com/fatih/color"
"github.com/spf13/cobra"
"gmgauthier.com/grokkit/config"
2026-02-28 19:56:23 +00:00
"gmgauthier.com/grokkit/internal/grok"
)
2026-02-28 18:28:27 +00:00
var editCmd = &cobra.Command{
Use: "edit [file]",
Short: "Edit a file in-place with Grok (safe preview)",
Long: `Ask Grok to edit a file. Shows a preview diff and requires explicit confirmation before writing.`,
Run: runEdit,
}
2026-02-28 19:56:23 +00:00
func init() {
editCmd.Flags().String("instruction", "", "Edit instruction (used internally by agent mode)")
rootCmd.AddCommand(editCmd)
}
func runEdit(cmd *cobra.Command, args []string) {
if len(args) == 0 {
color.Red("Usage: grokkit edit <file>")
return
}
file := args[0]
2026-02-28 19:56:23 +00:00
// If agent mode passed an instruction, use it directly (no prompt)
var instruction string
if editInstruction != "" {
instruction = editInstruction
color.Cyan("Agent instruction: %s", instruction)
} else {
// Normal interactive mode
color.Yellow("Enter edit instruction for %s: ", file)
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
instruction = strings.TrimSpace(scanner.Text())
}
if instruction == "" {
color.Yellow("No instruction provided.")
return
2026-02-28 19:56:23 +00:00
}
}
2026-02-28 19:56:23 +00:00
client := grok.NewClient()
messages := buildEditMessages(file, instruction)
2026-02-28 19:56:23 +00:00
color.Yellow("Asking Grok to edit %s...", file)
edited := client.Stream(messages, config.GetModel("edit", ""))
2026-02-28 19:56:23 +00:00
// Show preview
color.Cyan("\n--- Proposed changes to %s ---\n%s\n--------------------------------", file, edited)
2026-02-28 19:56:23 +00:00
var confirm string
color.Yellow("Apply these changes to %s? (y/n): ", file)
fmt.Scanln(&confirm)
if confirm != "y" && confirm != "Y" {
color.Yellow("Aborted.")
return
}
if err := os.WriteFile(file, []byte(edited), 0644); err != nil {
color.Red("Failed to write file: %v", err)
return
}
color.Green("✅ Successfully edited %s", file)
}
// buildEditMessages is kept unchanged from original
func buildEditMessages(file, instruction string) []map[string]string {
content, _ := os.ReadFile(file)
return []map[string]string{
{
"role": "system",
"content": "You are an expert programmer. Edit the following file according to the user's instruction. Return ONLY the full new file content. Do not include any explanations.",
},
{
"role": "user",
"content": fmt.Sprintf("File: %s\n\nCurrent content:\n%s\n\nInstruction: %s", file, string(content), instruction),
},
}
}