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.
93 lines
2.5 KiB
Go
93 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 scaffoldCmd = &cobra.Command{
|
|
Use: "scaffold [path]",
|
|
Short: "Scaffold a new file with Grok (safe preview + confirmation)",
|
|
Long: `Generate a new file from a description. Shows preview and requires explicit confirmation before writing.`,
|
|
Run: runScaffold,
|
|
}
|
|
|
|
var scaffoldDescription string // set by agent mode when calling from chat --agent
|
|
|
|
func init() {
|
|
scaffoldCmd.Flags().String("description", "", "Scaffold description (used internally by agent mode)")
|
|
rootCmd.AddCommand(scaffoldCmd)
|
|
}
|
|
|
|
func runScaffold(cmd *cobra.Command, args []string) {
|
|
if len(args) == 0 {
|
|
color.Red("Usage: grokkit scaffold <path>")
|
|
return
|
|
}
|
|
path := args[0]
|
|
|
|
// If agent mode passed a description, use it directly
|
|
var description string
|
|
if scaffoldDescription != "" {
|
|
description = scaffoldDescription
|
|
color.Cyan("Agent description: %s", description)
|
|
} else {
|
|
// Normal interactive mode
|
|
color.Yellow("Enter description for %s: ", path)
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
if scanner.Scan() {
|
|
description = strings.TrimSpace(scanner.Text())
|
|
}
|
|
if description == "" {
|
|
color.Yellow("No description provided.")
|
|
return
|
|
}
|
|
}
|
|
|
|
client := grok.NewClient()
|
|
messages := buildScaffoldMessages(path, description)
|
|
|
|
color.Yellow("Asking Grok to scaffold %s...", path)
|
|
scaffolded := client.Stream(messages, config.GetModel("scaffold", ""))
|
|
|
|
// Show preview
|
|
color.Cyan("\n--- Proposed content for %s ---\n%s\n--------------------------------", path, scaffolded)
|
|
|
|
var confirm string
|
|
color.Yellow("Create %s with this content? (y/n): ", path)
|
|
fmt.Scanln(&confirm)
|
|
|
|
if confirm != "y" && confirm != "Y" {
|
|
color.Yellow("Aborted.")
|
|
return
|
|
}
|
|
|
|
if err := os.WriteFile(path, []byte(scaffolded), 0644); err != nil {
|
|
color.Red("Failed to write file: %v", err)
|
|
return
|
|
}
|
|
|
|
color.Green("✅ Successfully scaffolded %s", path)
|
|
}
|
|
|
|
// buildScaffoldMessages is kept unchanged from original
|
|
func buildScaffoldMessages(path, description string) []map[string]string {
|
|
return []map[string]string{
|
|
{
|
|
"role": "system",
|
|
"content": "You are an expert programmer. Generate a complete, well-structured file based on the user's description. Return ONLY the full file content. Do not include any explanations or markdown fences.",
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": fmt.Sprintf("Path: %s\n\nDescription: %s", path, description),
|
|
},
|
|
}
|
|
}
|