Add support for Grok to call tools (edit, scaffold, testgen, lint, commit) via JSON in ```tool blocks. Introduce HandleToolCall to parse and execute tool requests, integrating with existing commands. Update system prompt and chat loop to handle tool calls and feed results back.
96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package agent
|
|
|
|
import (
|
|
"encoding/json"
|
|
_ "fmt"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
"gmgauthier.com/grokkit/cmd"
|
|
"gmgauthier.com/grokkit/internal/git"
|
|
)
|
|
|
|
// ToolCall represents a tool request from Grok
|
|
type ToolCall struct {
|
|
Tool string `json:"tool"`
|
|
File string `json:"file,omitempty"`
|
|
Path string `json:"path,omitempty"`
|
|
Instruction string `json:"instruction,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
Message string `json:"message,omitempty"`
|
|
}
|
|
|
|
// handleToolCall parses and executes tool calls from Grok's response
|
|
func HandleToolCall(reply string, history *[]map[string]string, model string) {
|
|
// Look for ```tool ... ``` blocks
|
|
start := strings.Index(reply, "```tool")
|
|
if start == -1 {
|
|
return
|
|
}
|
|
end := strings.Index(reply[start:], "```")
|
|
if end == -1 {
|
|
return
|
|
}
|
|
block := strings.TrimSpace(reply[start+7 : start+end])
|
|
|
|
var tc ToolCall
|
|
if err := json.Unmarshal([]byte(block), &tc); err != nil {
|
|
color.Red("Failed to parse tool call: %v", err)
|
|
return
|
|
}
|
|
|
|
color.Yellow("\n[Agent] Grok wants to call tool: %s", tc.Tool)
|
|
|
|
switch tc.Tool {
|
|
case "edit":
|
|
if tc.File == "" || tc.Instruction == "" {
|
|
color.Red("Invalid edit call — missing file or instruction")
|
|
break
|
|
}
|
|
color.Cyan("Editing %s with instruction: %s", tc.File, tc.Instruction)
|
|
// Reuse the existing edit flow (it already does preview + confirm)
|
|
cmd.RunEditWithInstruction(tc.File, tc.Instruction)
|
|
|
|
case "scaffold":
|
|
if tc.Path == "" || tc.Description == "" {
|
|
color.Red("Invalid scaffold call")
|
|
break
|
|
}
|
|
color.Cyan("Scaffolding %s: %s", tc.Path, tc.Description)
|
|
cmd.RunScaffoldWithDescription(tc.Path, tc.Description)
|
|
|
|
case "testgen":
|
|
if tc.File == "" {
|
|
color.Red("Invalid testgen call")
|
|
break
|
|
}
|
|
color.Cyan("Generating tests for %s", tc.File)
|
|
cmd.RunTestgenWithFile(tc.File)
|
|
|
|
case "lint":
|
|
if tc.File == "" {
|
|
color.Red("Invalid lint call")
|
|
break
|
|
}
|
|
color.Cyan("Linting %s", tc.File)
|
|
cmd.RunLintWithFile(tc.File)
|
|
|
|
case "commit":
|
|
if tc.Message == "" {
|
|
color.Red("Invalid commit call")
|
|
break
|
|
}
|
|
color.Cyan("Committing with message: %s", tc.Message)
|
|
git.Run([]string{"commit", "-m", tc.Message})
|
|
|
|
default:
|
|
color.Red("Unknown tool: %s", tc.Tool)
|
|
}
|
|
|
|
// Feed result back to Grok
|
|
*history = append(*history, map[string]string{
|
|
"role": "assistant",
|
|
"content": reply,
|
|
})
|
|
}
|