package cmd import ( "bufio" "fmt" "os" "strings" "github.com/fatih/color" "github.com/spf13/cobra" "gmgauthier.com/grokkit/config" _ "gmgauthier.com/grokkit/internal/grok" "gmgauthier.com/grokkit/internal/logger" ) var chatCmd = &cobra.Command{ Use: "chat", Short: "Interactive chat with Grok (use --agent for tool-enabled mode)", Long: `Start a persistent conversation with Grok. Normal mode: coherent, reasoning-focused chat. Agent mode (--agent): Grok can call tools (edit, scaffold, testgen, lint, commit, etc.) with full safety previews and confirmations.`, Run: runChat, } func init() { chatCmd.Flags().Bool("agent", false, "Enable agent mode with tool calling (uses fast model)") chatCmd.Flags().String("model", "", "Override model (normal: grok-4-1, agent: grok-4-1-fast-non-reasoning)") rootCmd.AddCommand(chatCmd) } func runChat(cmd *cobra.Command, args []string) { agentMode, _ := cmd.Flags().GetBool("agent") overrideModel, _ := cmd.Flags().GetString("model") // Model selection var model string if overrideModel != "" { model = overrideModel } else if agentMode { model = config.GetModel("chat-agent", "") } else { model = config.GetModel("chat", "") } logger.Info("starting chat", "mode", map[bool]string{true: "agent", false: "normal"}[agentMode], "model", model) color.Cyan("Grokkit Chat %s — Model: %s", map[bool]string{true: "(Agent Mode)", false: ""}[agentMode], model) color.Cyan("Type /quit to exit. Type /new to start fresh session.\n") client := newGrokClient() history := loadChatHistory() // Agent system prompt systemPrompt := `You are Grok, a helpful AI built by xAI.` if agentMode { systemPrompt = `You are Grok in Agent Mode. You have access to the following tools: - edit - scaffold - testgen - lint - commit Always use tools when the user asks you to change code, generate tests, lint, or commit. Be concise and action-oriented. After every tool call, wait for the result before continuing. Never make up file contents — always use the tools.` } history = append([]map[string]string{{"role": "system", "content": systemPrompt}}, history...) scanner := bufio.NewScanner(os.Stdin) for { color.Green("You: ") if !scanner.Scan() { break } input := strings.TrimSpace(scanner.Text()) if input == "/quit" || input == "/q" { break } if input == "/new" { history = []map[string]string{{"role": "system", "content": systemPrompt}} color.Yellow("New session started.\n") continue } if input == "" { continue } history = append(history, map[string]string{"role": "user", "content": input}) // In agent mode, we allow Grok to output tool calls in a simple JSON block reply := client.Stream(history, model) // Simple tool-call detection (can be expanded later) if agentMode && strings.Contains(reply, "```tool") { handleToolCall(reply, &history, model) continue } history = append(history, map[string]string{"role": "assistant", "content": reply}) saveChatHistory(history) } saveChatHistory(history) color.Yellow("Goodbye!") } // Placeholder — we'll flesh this out in the next step if you want more tools func handleToolCall(reply string, history *[]map[string]string, model string) { color.Yellow("\n[Agent] Grok wants to call a tool...") // For now we just echo — full implementation in next message if you approve fmt.Println(reply) *history = append(*history, map[string]string{"role": "assistant", "content": reply}) }