Refactor edit and scaffold commands to support invocation from chat --agent mode by using temporary global variables for passing instructions/descriptions. Add interactive prompts for normal usage, preview diffs, and confirmation before writing files. Update chat handler to set these variables and reset after execution.
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/spf13/cobra"
|
|
"gmgauthier.com/grokkit/config"
|
|
"gmgauthier.com/grokkit/internal/grok"
|
|
)
|
|
|
|
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,
|
|
}
|
|
|
|
var editInstruction string // set by agent mode when calling from chat --agent
|
|
|
|
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]
|
|
|
|
// 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
|
|
}
|
|
}
|
|
|
|
client := grok.NewClient()
|
|
messages := buildEditMessages(file, instruction)
|
|
|
|
color.Yellow("Asking Grok to edit %s...", file)
|
|
edited := client.Stream(messages, config.GetModel("edit", ""))
|
|
|
|
// Show preview
|
|
color.Cyan("\n--- Proposed changes to %s ---\n%s\n--------------------------------", file, edited)
|
|
|
|
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),
|
|
},
|
|
}
|
|
}
|