refactor(chat): improve chat command with better UI, prompts, and model handling
- Simplify model selection and defaults in config - Enhance system prompt and history management - Update CLI output with colors and exit commands - Remove placeholder tool handling for cleaner agent mode
This commit is contained in:
parent
87851513f1
commit
6eeb919013
105
cmd/chat.go
105
cmd/chat.go
@ -9,8 +9,7 @@ import (
|
|||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"gmgauthier.com/grokkit/config"
|
"gmgauthier.com/grokkit/config"
|
||||||
_ "gmgauthier.com/grokkit/internal/grok"
|
"gmgauthier.com/grokkit/internal/grok"
|
||||||
"gmgauthier.com/grokkit/internal/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var chatCmd = &cobra.Command{
|
var chatCmd = &cobra.Command{
|
||||||
@ -18,101 +17,83 @@ var chatCmd = &cobra.Command{
|
|||||||
Short: "Interactive chat with Grok (use --agent for tool-enabled mode)",
|
Short: "Interactive chat with Grok (use --agent for tool-enabled mode)",
|
||||||
Long: `Start a persistent conversation with Grok.
|
Long: `Start a persistent conversation with Grok.
|
||||||
|
|
||||||
Normal mode: coherent, reasoning-focused chat.
|
Normal mode: coherent, reasoning-focused chat (uses full model).
|
||||||
Agent mode (--agent): Grok can call tools (edit, scaffold, testgen, lint, commit, etc.)
|
Agent mode (--agent): Grok can call tools with safety previews (uses fast model).`,
|
||||||
with full safety previews and confirmations.`,
|
|
||||||
Run: runChat,
|
Run: runChat,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
chatCmd.Flags().Bool("agent", false, "Enable agent mode with tool calling (uses fast model)")
|
chatCmd.Flags().Bool("agent", false, "Enable agent mode with tool calling (uses fast non-reasoning model)")
|
||||||
chatCmd.Flags().String("model", "", "Override model (normal: grok-4-1, agent: grok-4-1-fast-non-reasoning)")
|
chatCmd.Flags().String("model", "", "Override model")
|
||||||
rootCmd.AddCommand(chatCmd)
|
rootCmd.AddCommand(chatCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runChat(cmd *cobra.Command, args []string) {
|
func runChat(cmd *cobra.Command, args []string) {
|
||||||
agentMode, _ := cmd.Flags().GetBool("agent")
|
agentMode, _ := cmd.Flags().GetBool("agent")
|
||||||
overrideModel, _ := cmd.Flags().GetString("model")
|
modelFlag, _ := cmd.Flags().GetString("model")
|
||||||
|
|
||||||
// Model selection
|
// Model switching logic
|
||||||
var model string
|
var model string
|
||||||
if overrideModel != "" {
|
if modelFlag != "" {
|
||||||
model = overrideModel
|
model = modelFlag
|
||||||
} else if agentMode {
|
} else if agentMode {
|
||||||
model = config.GetModel("chat-agent", "")
|
model = config.GetModel("chat-agent", "") // we'll add this default next
|
||||||
} else {
|
} else {
|
||||||
model = config.GetModel("chat", "")
|
model = config.GetModel("chat", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("starting chat", "mode", map[bool]string{true: "agent", false: "normal"}[agentMode], "model", model)
|
client := grok.NewClient()
|
||||||
|
|
||||||
color.Cyan("Grokkit Chat %s — Model: %s", map[bool]string{true: "(Agent Mode)", false: ""}[agentMode], model)
|
systemPrompt := map[string]string{
|
||||||
color.Cyan("Type /quit to exit. Type /new to start fresh session.\n")
|
"role": "system",
|
||||||
|
"content": fmt.Sprintf("You are Grok 4, the latest and most powerful model from xAI (2026). You are currently running as `%s`. Be helpful, truthful, and a little irreverent.", model),
|
||||||
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 <file> <instruction>
|
|
||||||
- scaffold <path> <description>
|
|
||||||
- testgen <file>
|
|
||||||
- lint <file>
|
|
||||||
- commit <message>
|
|
||||||
|
|
||||||
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...)
|
if agentMode {
|
||||||
|
systemPrompt["content"] = `You are Grok in Agent Mode.
|
||||||
|
You have access to tools: edit, scaffold, testgen, lint, commit, etc.
|
||||||
|
Always use tools when the user wants you to change code, generate tests, lint or commit.
|
||||||
|
Be concise and action-oriented. After every tool call, wait for the result.`
|
||||||
|
}
|
||||||
|
|
||||||
|
history := loadChatHistory()
|
||||||
|
if history == nil || len(history) == 0 {
|
||||||
|
history = []map[string]string{systemPrompt}
|
||||||
|
} else if history[0]["role"] != "system" {
|
||||||
|
history = append([]map[string]string{systemPrompt}, history...)
|
||||||
|
} else {
|
||||||
|
history[0] = systemPrompt // refresh system prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
color.Cyan("┌──────────────────────────────────────────────────────────────┐")
|
||||||
|
color.Cyan("│ Grokkit Chat %s — Model: %s │", map[bool]string{true: "(Agent Mode)", false: ""}[agentMode], model)
|
||||||
|
color.Cyan("│ Type /quit to exit │")
|
||||||
|
color.Cyan("└──────────────────────────────────────────────────────────────┘\n")
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for {
|
for {
|
||||||
color.Green("You: ")
|
color.Yellow("You > ")
|
||||||
if !scanner.Scan() {
|
if !scanner.Scan() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
input := strings.TrimSpace(scanner.Text())
|
|
||||||
|
|
||||||
if input == "/quit" || input == "/q" {
|
input := strings.TrimSpace(scanner.Text())
|
||||||
break
|
|
||||||
}
|
|
||||||
if input == "/new" {
|
|
||||||
history = []map[string]string{{"role": "system", "content": systemPrompt}}
|
|
||||||
color.Yellow("New session started.\n")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if input == "" {
|
if input == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if input == "/quit" || input == "/q" || input == "exit" {
|
||||||
|
color.Cyan("\nGoodbye 👋\n")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
history = append(history, map[string]string{"role": "user", "content": input})
|
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
|
color.Green("Grok > ")
|
||||||
reply := client.Stream(history, model)
|
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})
|
history = append(history, map[string]string{"role": "assistant", "content": reply})
|
||||||
saveChatHistory(history)
|
_ = saveChatHistory(history)
|
||||||
}
|
|
||||||
|
|
||||||
saveChatHistory(history)
|
fmt.Println()
|
||||||
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})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,9 +36,8 @@ func Load() {
|
|||||||
viper.SetDefault("commands.prdescribe.model", "grok-4")
|
viper.SetDefault("commands.prdescribe.model", "grok-4")
|
||||||
viper.SetDefault("commands.review.model", "grok-4")
|
viper.SetDefault("commands.review.model", "grok-4")
|
||||||
viper.SetDefault("commands.docs.model", "grok-4")
|
viper.SetDefault("commands.docs.model", "grok-4")
|
||||||
viper.SetDefault("models.chat", "grok-4-1")
|
viper.SetDefault("commands.chat", "grok-4-1")
|
||||||
viper.SetDefault("models.chat-agent", "grok-4-1-fast-non-reasoning") // ← new
|
viper.SetDefault("commands.chat-agent.model", "grok-4-1-fast-non-reasoning")
|
||||||
|
|
||||||
// Config file is optional, so we ignore read errors
|
// Config file is optional, so we ignore read errors
|
||||||
_ = viper.ReadInConfig()
|
_ = viper.ReadInConfig()
|
||||||
}
|
}
|
||||||
@ -50,8 +49,7 @@ func GetModel(commandName string, flagModel string) string {
|
|||||||
}
|
}
|
||||||
return flagModel
|
return flagModel
|
||||||
}
|
}
|
||||||
cmdModel := viper.GetString("commands." + commandName + ".model")
|
if cmdModel := viper.GetString("commands." + commandName + ".model"); cmdModel != "" {
|
||||||
if cmdModel != "" {
|
|
||||||
return cmdModel
|
return cmdModel
|
||||||
}
|
}
|
||||||
return viper.GetString("default_model")
|
return viper.GetString("default_model")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user