Implemented automatic addition of "// Last modified: [timestamp]" headers across command and internal files for better tracking. Updated prompts in agent and edit commands to enforce header format. Added logic to prepend header if missing in generated content. Fixed minor issues like missing newlines at end of files.
122 lines
3.8 KiB
Go
122 lines
3.8 KiB
Go
// Last modified: 2026-02-28 22:43:17 GMT
|
|
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/spf13/cobra"
|
|
"gmgauthier.com/grokkit/config"
|
|
"gmgauthier.com/grokkit/internal/grok"
|
|
)
|
|
|
|
var agentCmd = &cobra.Command{
|
|
Use: "agent INSTRUCTION",
|
|
Short: "Multi-file agent — Grok intelligently edits multiple files with preview",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
instruction := args[0]
|
|
modelFlag, _ := cmd.Flags().GetString("model")
|
|
model := config.GetModel(modelFlag)
|
|
|
|
client := grok.NewClient()
|
|
|
|
color.Yellow("🔍 Agent mode activated. Scanning project...")
|
|
|
|
var files []string
|
|
filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
|
if err != nil || info.IsDir() {
|
|
return err
|
|
}
|
|
if strings.HasSuffix(path, ".go") {
|
|
files = append(files, path)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
if len(files) == 0 {
|
|
color.Yellow("No .go files found.")
|
|
return
|
|
}
|
|
|
|
color.Yellow("📄 Found %d files. Asking Grok for a plan...", len(files))
|
|
|
|
planMessages := []map[string]string{
|
|
{"role": "system", "content": "You are an expert software engineer. Given an instruction and list of files, return a clear plan: which files to change and a brief description of what to do in each. List files one per line."},
|
|
{"role": "user", "content": fmt.Sprintf("Instruction: %s\n\nFiles:\n%s", instruction, strings.Join(files, "\n"))},
|
|
}
|
|
|
|
plan := client.Stream(planMessages, model)
|
|
color.Cyan("\nGrok's Plan:\n%s", plan)
|
|
|
|
fmt.Print("\nProceed with changes? (y/n): ")
|
|
var confirm string
|
|
fmt.Scanln(&confirm)
|
|
if confirm != "y" && confirm != "Y" {
|
|
color.Yellow("Aborted.")
|
|
return
|
|
}
|
|
|
|
color.Yellow("Applying changes file by file...\n")
|
|
|
|
applyAll := false
|
|
for i, file := range files {
|
|
color.Yellow("[%d/%d] → %s", i+1, len(files), file)
|
|
|
|
original, err := os.ReadFile(file)
|
|
if err != nil {
|
|
color.Red("Could not read %s", file)
|
|
continue
|
|
}
|
|
|
|
backupPath := file + ".bak"
|
|
_ = os.WriteFile(backupPath, original, 0644)
|
|
|
|
currentTime := time.Now().Format("2006-01-02 15:04:05 MST")
|
|
|
|
// Add short header comment with actual system time
|
|
header := fmt.Sprintf("// Last modified: %s\n\n", time.Now().Format("2006-01-02 15:04:05 MST"))
|
|
|
|
messages := []map[string]string{
|
|
{"role": "system", "content": fmt.Sprintf("You are an expert programmer. The VERY FIRST LINE of the returned file MUST be a header comment in this exact format: '// Last modified: %s'. Then return the complete updated file content. No explanations, no markdown, no diffs, no extra text.", currentTime)},
|
|
{"role": "user", "content": fmt.Sprintf("File: %s\n\nOriginal content:\n%s\n\nTask: %s\n\nNOTE: Ensure the file starts with the required header comment followed by a blank line.", filepath.Base(file), original, instruction)},
|
|
}
|
|
|
|
raw := client.StreamSilent(messages, "grok-4-1-fast-non-reasoning")
|
|
newContent := grok.CleanCodeResponse(raw)
|
|
|
|
// Ensure header is present - prepend if missing
|
|
if !strings.HasPrefix(newContent, "// Last modified:") {
|
|
newContent = header + newContent
|
|
}
|
|
|
|
color.Cyan("Proposed changes for %s:", filepath.Base(file))
|
|
fmt.Println("--- a/" + filepath.Base(file))
|
|
fmt.Println("+++ b/" + filepath.Base(file))
|
|
fmt.Print(newContent)
|
|
|
|
if !applyAll {
|
|
fmt.Print("\nApply this file? (y/n/a = all remaining): ")
|
|
var answer string
|
|
fmt.Scanln(&answer)
|
|
answer = strings.ToLower(strings.TrimSpace(answer))
|
|
|
|
if answer == "a" {
|
|
applyAll = true
|
|
} else if answer != "y" {
|
|
color.Yellow("Skipped %s (backup kept)", file)
|
|
continue
|
|
}
|
|
}
|
|
|
|
_ = os.WriteFile(file, []byte(newContent), 0644)
|
|
color.Green("✅ Applied %s", file)
|
|
}
|
|
|
|
color.Green("\n🎉 Agent mode complete! All changes applied.")
|
|
},
|
|
} |