Skip to content

Commit b3d7cf7

Browse files
authored
Merge pull request #1 from thedadams/add-chdir
feat: add chdir option
2 parents 1d4e1bd + 2abdd82 commit b3d7cf7

File tree

3 files changed

+44
-81
lines changed

3 files changed

+44
-81
lines changed

README.md

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ To use the module, you need to first set the OPENAI_API_KEY environment variable
1616

1717
Additionally, you need the `gptscript` binary. You can install it on your system using the [installation instructions](https://github.com/gptscript-ai/gptscript?tab=readme-ov-file#1-install-the-latest-release).
1818

19+
## Options
20+
21+
These are optional options that can be passed to the various `exec` functions.
22+
None of the options is required, and the defaults will reduce the number of calls made to the Model API.
23+
24+
- `cache`: Enable or disable caching. Default (true).
25+
- `cacheDir`: Specify the cache directory.
26+
- `quiet`: No output logging
27+
- `chdir`: Change current working directory
28+
1929
## Functions
2030

2131
### listTools
@@ -62,16 +72,6 @@ func listModels(ctx context.Context) ([]string, error) {
6272

6373
Executes a prompt with optional arguments.
6474

65-
**Options:**
66-
67-
These are optional options that can be passed to the `ExecTool` functions.
68-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
69-
70-
- `cache`: Enable or disable caching. Default (true).
71-
- `cacheDir`: Specify the cache directory.
72-
73-
**Usage:**
74-
7575
```go
7676
package main
7777

@@ -92,19 +92,7 @@ func runTool(ctx context.Context) (string, error) {
9292

9393
### ExecFile
9494

95-
Executes a GPT script file with optional input and arguments.
96-
97-
**Options:**
98-
99-
These are optional options that can be passed to the `ExecFile` function.
100-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
101-
102-
- `cache`: Enable or disable caching.
103-
- `cacheDir`: Specify the cache directory.
104-
105-
**Usage:**
106-
107-
The script is relative to the callers source directory.
95+
Executes a GPT script file with optional input and arguments. The script is relative to the callers source directory.
10896

10997
```go
11098
package main
@@ -128,16 +116,6 @@ func execFile(ctx context.Context) (string, error) {
128116

129117
Executes a gptscript with optional input and arguments, and returns the output streams.
130118

131-
**Options:**
132-
133-
These are optional options that can be passed to the `StreamExecTool` function.
134-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
135-
136-
- `cache`: Enable or disable caching.
137-
- `cacheDir`: Specify the cache directory.
138-
139-
**Usage:**
140-
141119
```go
142120
package main
143121

@@ -164,16 +142,6 @@ func streamExecTool(ctx context.Context) error {
164142

165143
Executes a gptscript with optional input and arguments, and returns the stdout, stderr, and gptscript events streams.
166144

167-
**Options:**
168-
169-
These are optional options that can be passed to the `StreamExecTool` function.
170-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
171-
172-
- `cache`: Enable or disable caching.
173-
- `cacheDir`: Specify the cache directory.
174-
175-
**Usage:**
176-
177145
```go
178146
package main
179147

@@ -198,16 +166,6 @@ func streamExecTool(ctx context.Context) error {
198166

199167
### streamExecFile
200168

201-
**Options:**
202-
203-
These are optional options that can be passed to the `exec` function.
204-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
205-
206-
- `cache`: Enable or disable caching.
207-
- `cacheDir`: Specify the cache directory.
208-
209-
**Usage:**
210-
211169
The script is relative to the callers source directory.
212170

213171
```go
@@ -234,16 +192,6 @@ func streamExecTool(ctx context.Context) error {
234192

235193
### streamExecFileWithEvents
236194

237-
**Options:**
238-
239-
These are optional options that can be passed to the `exec` function.
240-
Neither option is required, and the defaults will reduce the number of calls made to the Model API.
241-
242-
- `cache`: Enable or disable caching.
243-
- `cacheDir`: Specify the cache directory.
244-
245-
**Usage:**
246-
247195
The script is relative to the callers source directory.
248196

249197
```go

exec.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ type Opts struct {
1414
DisableCache bool
1515
CacheDir string
1616
Quiet bool
17+
Chdir string
18+
}
19+
20+
func (o Opts) toArgs() []string {
21+
var args []string
22+
if o.DisableCache {
23+
args = append(args, "--disable-cache")
24+
}
25+
if o.CacheDir != "" {
26+
args = append(args, "--cache-dir="+o.CacheDir)
27+
}
28+
if o.Chdir != "" {
29+
args = append(args, "--chdir="+o.Chdir)
30+
}
31+
return append(args, "--quiet="+fmt.Sprint(o.Quiet))
1732
}
1833

1934
// ListTools will list all the available tools.
@@ -33,7 +48,7 @@ func ListModels(ctx context.Context) ([]string, error) {
3348

3449
// ExecTool will execute a tool. The tool must be a fmt.Stringer, and the string should be a valid gptscript file.
3550
func ExecTool(ctx context.Context, opts Opts, tools ...fmt.Stringer) (string, error) {
36-
c := exec.CommandContext(ctx, getCommand(), append(toArgs(opts), "-")...)
51+
c := exec.CommandContext(ctx, getCommand(), append(opts.toArgs(), "-")...)
3752
c.Stdin = strings.NewReader(concatTools(tools))
3853
out, err := c.CombinedOutput()
3954
return string(out), err
@@ -43,7 +58,7 @@ func ExecTool(ctx context.Context, opts Opts, tools ...fmt.Stringer) (string, er
4358
// This returns two io.ReadClosers, one for stdout and one for stderr, and a function to wait for the process to exit.
4459
// Reading from stdOut and stdErr should be completed before calling the wait function.
4560
func StreamExecTool(ctx context.Context, opts Opts, tools ...fmt.Stringer) (io.Reader, io.Reader, func() error) {
46-
c, stdout, stderr, err := setupForkCommand(ctx, "", append(toArgs(opts), "-"))
61+
c, stdout, stderr, err := setupForkCommand(ctx, "", append(opts.toArgs(), "-"))
4762
if err != nil {
4863
return stdout, stderr, func() error { return err }
4964
}
@@ -68,7 +83,7 @@ func StreamExecToolWithEvents(ctx context.Context, opts Opts, tools ...fmt.Strin
6883
// Close the parent pipe after starting the child process
6984
defer eventsWrite.Close()
7085

71-
c, stdout, stderr, err := setupForkCommand(ctx, "", append(toArgs(opts), "-"))
86+
c, stdout, stderr, err := setupForkCommand(ctx, "", append(opts.toArgs(), "-"))
7287
if err != nil {
7388
_ = eventsRead.Close()
7489
return stdout, stderr, new(reader), func() error { return err }
@@ -95,7 +110,7 @@ func StreamExecToolWithEvents(ctx context.Context, opts Opts, tools ...fmt.Strin
95110
// The file at the path should be a valid gptscript file.
96111
// The input should be command line arguments in the form of a string (i.e. "--arg1 value1 --arg2 value2").
97112
func ExecFile(ctx context.Context, toolPath, input string, opts Opts) (string, error) {
98-
args := append(toArgs(opts), toolPath)
113+
args := append(opts.toArgs(), toolPath)
99114
if input != "" {
100115
args = append(args, input)
101116
}
@@ -110,7 +125,7 @@ func ExecFile(ctx context.Context, toolPath, input string, opts Opts) (string, e
110125
// This returns two io.ReadClosers, one for stdout and one for stderr, and a function to wait for the process to exit.
111126
// Reading from stdOut and stdErr should be completed before calling the wait function.
112127
func StreamExecFile(ctx context.Context, toolPath, input string, opts Opts) (io.Reader, io.Reader, func() error) {
113-
args := append(toArgs(opts), toolPath)
128+
args := append(opts.toArgs(), toolPath)
114129
c, stdout, stderr, err := setupForkCommand(ctx, input, args)
115130
if err != nil {
116131
return stdout, stderr, func() error { return err }
@@ -136,7 +151,7 @@ func StreamExecFileWithEvents(ctx context.Context, toolPath, input string, opts
136151
// Close the parent pipe after starting the child process
137152
defer eventsWrite.Close()
138153

139-
args := append(toArgs(opts), toolPath)
154+
args := append(opts.toArgs(), toolPath)
140155

141156
c, stdout, stderr, err := setupForkCommand(ctx, input, args)
142157
if err != nil {
@@ -160,18 +175,6 @@ func StreamExecFileWithEvents(ctx context.Context, toolPath, input string, opts
160175
return stdout, stderr, eventsRead, wait
161176
}
162177

163-
func toArgs(opts Opts) []string {
164-
var args []string
165-
if opts.DisableCache {
166-
args = append(args, "--disable-cache")
167-
}
168-
if opts.CacheDir != "" {
169-
args = append(args, "--cache-dir="+opts.CacheDir)
170-
}
171-
args = append(args, "--quiet="+fmt.Sprint(opts.Quiet))
172-
return args
173-
}
174-
175178
func concatTools(tools []fmt.Stringer) string {
176179
var sb strings.Builder
177180
for i, tool := range tools {

exec_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ func TestSimpleExec(t *testing.T) {
5353
}
5454
}
5555

56+
func TestExecFileChdir(t *testing.T) {
57+
// By changing the directory here, we should be able to find the test.gpt file without `./test` (see TestStreamExecFile)
58+
out, err := ExecFile(context.Background(), "test.gpt", "", Opts{Chdir: "./test"})
59+
if err != nil {
60+
t.Errorf("Error executing tool: %v", err)
61+
}
62+
63+
if out == "" {
64+
t.Error("No output from tool")
65+
}
66+
}
67+
5668
func TestExecComplexTool(t *testing.T) {
5769
tool := &Tool{
5870
Tools: []string{"sys.write"},

0 commit comments

Comments
 (0)