1package tools
2
3import (
4 "context"
5 "fmt"
6
7 "charm.land/fantasy"
8 "github.com/charmbracelet/crush/internal/shell"
9)
10
11const (
12 BashKillToolName = "bash_kill"
13)
14
15type BashKillParams struct {
16 ShellID string `json:"shell_id" description:"The ID of the background shell to terminate"`
17}
18
19type BashKillResponseMetadata struct {
20 ShellID string `json:"shell_id"`
21}
22
23const bashKillDescription = `Terminates a background shell process.
24
25<usage>
26- Provide the shell ID returned from a background bash execution
27- Cancels the running process and cleans up resources
28</usage>
29
30<features>
31- Stop long-running background processes
32- Clean up completed background shells
33- Immediately terminates the process
34</features>
35
36<tips>
37- Use this when you need to stop a background process
38- The process is terminated immediately (similar to SIGTERM)
39- After killing, the shell ID becomes invalid
40</tips>
41`
42
43func NewBashKillTool() fantasy.AgentTool {
44 return fantasy.NewAgentTool(
45 BashKillToolName,
46 bashKillDescription,
47 func(ctx context.Context, params BashKillParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
48 if params.ShellID == "" {
49 return fantasy.NewTextErrorResponse("missing shell_id"), nil
50 }
51
52 bgManager := shell.GetBackgroundShellManager()
53 err := bgManager.Kill(params.ShellID)
54 if err != nil {
55 return fantasy.NewTextErrorResponse(err.Error()), nil
56 }
57
58 metadata := BashKillResponseMetadata(params)
59
60 result := fmt.Sprintf("Background shell %s terminated successfully", params.ShellID)
61 return fantasy.WithResponseMetadata(fantasy.NewTextResponse(result), metadata), nil
62 })
63}