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,
|
||
|
|
})
|
||
|
|
}
|