• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kshard / thinker / 13444992255

20 Feb 2025 09:26PM UTC coverage: 72.098% (+4.3%) from 67.766%
13444992255

Pull #2

github

fogfish
support command and codeblock
Pull Request #2: generalize reasoner for command workflow

152 of 189 new or added lines in 5 files covered. (80.42%)

8 existing lines in 1 file now uncovered.

323 of 448 relevant lines covered (72.1%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.13
/command/python.go
1
//
2
// Copyright (C) 2025 Dmitry Kolesnikov
3
//
4
// This file may be modified and distributed under the terms
5
// of the MIT license.  See the LICENSE file for details.
6
// https://github.com/kshard/thinker
7
//
8

9
package command
10

11
import (
12
        "bytes"
13
        "fmt"
14
        "os"
15
        "os/exec"
16
        "path/filepath"
17

18
        "github.com/kshard/chatter"
19
        "github.com/kshard/thinker"
20
)
21

22
// A unique name for bash (the shell)
23
const PYTHON = "python"
24

25
// (format python code with \\t, \\n)
26

27
// Create new bash command, defining the os variant and working dir
28
func Python(dir string) thinker.Cmd {
1✔
29
        return thinker.Cmd{
1✔
30
                Cmd:    PYTHON,
1✔
31
                Short:  "Use python to execute scripts that help you complete your task. Enclose the python code in <codeblock> tags.",
1✔
32
                Syntax: `python  <codeblock>source code</codeblock>`,
1✔
33
                Run:    python(dir),
1✔
34
        }
1✔
35
}
1✔
36

37
func pySetup(dir string) error {
1✔
38
        pyenv := filepath.Join(dir, ".venv")
1✔
39
        if _, err := os.Stat(pyenv); err != nil {
2✔
40
                setup := exec.Command("python3", "-m", "venv", ".venv")
1✔
41
                setup.Dir = dir
1✔
42

1✔
43
                _, err := setup.Output()
1✔
44
                if err != nil {
1✔
NEW
45
                        return err
×
NEW
46
                }
×
47

48
                pipreqs := exec.Command(filepath.Join(pyenv, "bin/python"), "-m", "pip", "install", "pigar")
1✔
49
                pipreqs.Dir = dir
1✔
50

1✔
51
                _, err = pipreqs.Output()
1✔
52
                if err != nil {
1✔
NEW
53
                        return err
×
NEW
54
                }
×
55
        }
56

57
        return nil
1✔
58
}
59

60
func pyDeps(dir string) error {
1✔
61
        pyenv := filepath.Join(dir, ".venv")
1✔
62

1✔
63
        deps := exec.Command(filepath.Join(pyenv, "bin/pigar"), "generate", "--question-answer", "yes", "--auto-select")
1✔
64
        deps.Dir = dir
1✔
65

1✔
66
        _, err := deps.Output()
1✔
67
        if err != nil {
1✔
NEW
68
                return err
×
NEW
69
        }
×
70

71
        pip := exec.Command(filepath.Join(pyenv, "bin/python"), "-m", "pip", "install", "-r", "requirements.txt")
1✔
72
        pip.Dir = dir
1✔
73

1✔
74
        _, err = pip.Output()
1✔
75
        if err != nil {
1✔
NEW
76
                return err
×
NEW
77
        }
×
78

79
        return nil
1✔
80
}
81

82
func pyfile(dir, code string) (string, error) {
1✔
83
        fd, err := os.CreateTemp(dir, "job-*.py")
1✔
84
        if err != nil {
1✔
NEW
85
                return "", err
×
NEW
86
        }
×
87
        defer fd.Close()
1✔
88

1✔
89
        _, err = fd.WriteString(code)
1✔
90
        if err != nil {
1✔
NEW
91
                return "", err
×
NEW
92
        }
×
93

94
        return fd.Name(), nil
1✔
95
}
96

97
func python(dir string) func(chatter.Reply) (float64, thinker.CmdOut, error) {
1✔
98
        return func(command chatter.Reply) (float64, thinker.CmdOut, error) {
2✔
99
                if err := pySetup(dir); err != nil {
1✔
NEW
100
                        return 0.0, thinker.CmdOut{}, err
×
NEW
101
                }
×
102

103
                code, err := CodeBlock(PYTHON, command.Text)
1✔
104
                if err != nil {
1✔
NEW
105
                        return 0.00, thinker.CmdOut{Cmd: PYTHON}, err
×
NEW
106
                }
×
107

108
                file, err := pyfile(dir, code)
1✔
109
                if err != nil {
1✔
NEW
110
                        return 0.00, thinker.CmdOut{Cmd: PYTHON}, err
×
NEW
111
                }
×
112

113
                if err := pyDeps(dir); err != nil {
1✔
NEW
114
                        return 0.0, thinker.CmdOut{}, err
×
NEW
115
                }
×
116

117
                pyenv := filepath.Join(dir, ".venv")
1✔
118
                cmd := exec.Command(filepath.Join(pyenv, "bin/python"), file)
1✔
119
                var stdout bytes.Buffer
1✔
120
                var stderr bytes.Buffer
1✔
121
                cmd.Dir = dir
1✔
122
                cmd.Stdout = &stdout
1✔
123
                cmd.Stderr = &stderr
1✔
124

1✔
125
                if err := cmd.Run(); err != nil {
1✔
NEW
126
                        err = thinker.Feedback(
×
NEW
127
                                fmt.Sprintf("The TOOL:%s has failed, improve the response based on feedback:", PYTHON),
×
NEW
128

×
NEW
129
                                `Strictly adhere python code formatting, use \t, \n where is needed`,
×
NEW
130
                                "Execution of python script is failed with the error: "+err.Error(),
×
NEW
131
                                "The error output is "+stderr.String(),
×
NEW
132
                        )
×
NEW
133
                        return 0.05, thinker.CmdOut{Cmd: PYTHON}, err
×
NEW
134
                }
×
135

136
                return 1.0, thinker.CmdOut{Cmd: PYTHON, Output: stdout.String()}, nil
1✔
137
        }
138
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc