on main help sign in
fix: small improvements around command execution
1ad3485Carlos Alexandro Becker
internal/fsext/fileutil.go+15−5
@@ -25,12 +25,10 @@ func init() {
25 rgPath, err = exec.LookPath("rg")
25 rgPath, err = exec.LookPath("rg")
26 if err != nil {
26 if err != nil {
27 logging.Warn("Ripgrep (rg) not found in $PATH. Some features might be limited or slower.")
27 logging.Warn("Ripgrep (rg) not found in $PATH. Some features might be limited or slower.")
28− rgPath = ""
29 }
28 }
30 fzfPath, err = exec.LookPath("fzf")
29 fzfPath, err = exec.LookPath("fzf")
31 if err != nil {
30 if err != nil {
32 logging.Warn("FZF not found in $PATH. Some features might be limited or slower.")
31 logging.Warn("FZF not found in $PATH. Some features might be limited or slower.")
33− fzfPath = ""
34 }
32 }
35}
33}
36
34
@@ -49,9 +47,21 @@ func GetRgCmd(globPattern string) *exec.Cmd {
49 }
47 }
50 rgArgs = append(rgArgs, "--glob", globPattern)
48 rgArgs = append(rgArgs, "--glob", globPattern)
51 }
49 }
52− cmd := exec.Command(rgPath, rgArgs...)
50+ return exec.Command(rgPath, rgArgs...)
53− cmd.Dir = "."
51+}
54− return cmd
52+
53+func GetRgSearchCmd(pattern, path, include string) *exec.Cmd {
54+ if rgPath == "" {
55+ return nil
56+ }
57+ // Use -n to show line numbers and include the matched line
58+ args := []string{"-n", pattern}
59+ if include != "" {
60+ args = append(args, "--glob", include)
61+ }
62+ args = append(args, path)
63+
64+ return exec.Command("rg", args...)
55}
65}
56
66
57type FileInfo struct {
67type FileInfo struct {
internal/llm/tools/glob.go+1−1
@@ -150,7 +150,7 @@ func runRipgrep(cmd *exec.Cmd, searchRoot string, limit int) ([]string, error) {
150 }
150 }
151
151
152 var matches []string
152 var matches []string
153− for _, p := range bytes.Split(out, []byte{0}) {
153+ for p := range bytes.SplitSeq(out, []byte{0}) {
154 if len(p) == 0 {
154 if len(p) == 0 {
155 continue
155 continue
156 }
156 }
internal/llm/tools/grep.go+3−11
@@ -257,19 +257,11 @@ func searchFiles(pattern, rootPath, include string, limit int) ([]grepMatch, boo
257}
257}
258
258
259func searchWithRipgrep(pattern, path, include string) ([]grepMatch, error) {
259func searchWithRipgrep(pattern, path, include string) ([]grepMatch, error) {
260− _, err := exec.LookPath("rg")
260+ cmd := fsext.GetRgSearchCmd(pattern, path, include)
261− if err != nil {
261+ if cmd == nil {
262− return nil, fmt.Errorf("ripgrep not found: %w", err)
262+ return nil, fmt.Errorf("ripgrep not found in $PATH")
263− }
264−
265− // Use -n to show line numbers and include the matched line
266− args := []string{"-n", pattern}
267− if include != "" {
268− args = append(args, "--glob", include)
269 }
263 }
270− args = append(args, path)
271
264
272− cmd := exec.Command("rg", args...)
273 output, err := cmd.Output()
265 output, err := cmd.Output()
274 if err != nil {
266 if err != nil {
275 if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
267 if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
internal/llm/tools/shell/shell.go+6−12
@@ -4,6 +4,7 @@ import (
4 "context"
4 "context"
5 "errors"
5 "errors"
6 "fmt"
6 "fmt"
7+ "io"
7 "os"
8 "os"
8 "os/exec"
9 "os/exec"
9 "path/filepath"
10 "path/filepath"
@@ -17,7 +18,7 @@ import (
17
18
18type PersistentShell struct {
19type PersistentShell struct {
19 cmd *exec.Cmd
20 cmd *exec.Cmd
20− stdin *os.File
21+ stdin io.WriteCloser
21 isAlive bool
22 isAlive bool
22 cwd string
23 cwd string
23 mu sync.Mutex
24 mu sync.Mutex
@@ -39,22 +40,15 @@ type commandResult struct {
39 err error
40 err error
40}
41}
41
42
42−var (
43− shellInstance *PersistentShell
43+var shellInstance *PersistentShell
44− shellInstanceOnce sync.Once
45−)
46
44
47func GetPersistentShell(workingDir string) *PersistentShell {
45func GetPersistentShell(workingDir string) *PersistentShell {
48− shellInstanceOnce.Do(func() {
49− shellInstance = newPersistentShell(workingDir)
50− })
51−
52 if shellInstance == nil {
46 if shellInstance == nil {
53 shellInstance = newPersistentShell(workingDir)
47 shellInstance = newPersistentShell(workingDir)
48+ }
54− } else if !shellInstance.isAlive {
49+ if !shellInstance.isAlive {
55 shellInstance = newPersistentShell(shellInstance.cwd)
50 shellInstance = newPersistentShell(shellInstance.cwd)
56 }
51 }
57−
58 return shellInstance
52 return shellInstance
59}
53}
60
54
@@ -100,7 +94,7 @@ func newPersistentShell(cwd string) *PersistentShell {
100
94
101 shell := &PersistentShell{
95 shell := &PersistentShell{
102 cmd: cmd,
96 cmd: cmd,
103− stdin: stdinPipe.(*os.File),
97+ stdin: stdinPipe,
104 isAlive: true,
98 isAlive: true,
105 cwd: cwd,
99 cwd: cwd,
106 commandQueue: make(chan *commandExecution, 10),
100 commandQueue: make(chan *commandExecution, 10),