Skip to content

Commit

Permalink
Set working directory of tool calls to the directory of the file
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Feb 29, 2024
1 parent 701b9c8 commit 6126d27
Show file tree
Hide file tree
Showing 23 changed files with 518 additions and 91 deletions.
2 changes: 1 addition & 1 deletion pkg/cli/gptscript.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type GPTScript struct {
OpenAIOptions
DisplayOptions
Debug bool `usage:"Enable debug logging"`
Quiet *bool `usage:"No output logging" short:"q"`
Quiet *bool `usage:"No output logging (set --quiet=false to force on even when there is no TTY)" short:"q"`
Output string `usage:"Save output to a file, or - for stdout" short:"o"`
Input string `usage:"Read input from a file (\"-\" for stdin)" short:"f"`
SubTool string `usage:"Use tool of this name, not the first tool in file"`
Expand Down
3 changes: 3 additions & 0 deletions pkg/engine/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ func (e *Engine) runCommand(ctx context.Context, tool types.Tool, input string)
cmd.Stdin = strings.NewReader(input)
cmd.Stderr = io.MultiWriter(all, os.Stderr)
cmd.Stdout = io.MultiWriter(all, output)
if tool.WorkingDir != "" {
cmd.Dir = tool.WorkingDir
}

if err := cmd.Run(); err != nil {
_, _ = os.Stderr.Write(output.Bytes())
Expand Down
3 changes: 1 addition & 2 deletions pkg/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,7 @@ func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) {
ToolName: content.ToolCall.Function.Name,
Input: content.ToolCall.Function.Arguments,
}
}
if content.Text != "" {
} else {
cp := content.Text
ret.Result = &cp
}
Expand Down
17 changes: 17 additions & 0 deletions pkg/engine/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"net/http"
"net/url"
"os"
"strings"

"github.com/gptscript-ai/gptscript/pkg/types"
Expand All @@ -15,7 +16,19 @@ import (
const DaemonURLSuffix = ".daemon.gpt.local"

func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Tool, input string) (cmdRet *Return, cmdErr error) {
envMap := map[string]string{}
for _, env := range e.Env {
v, ok := strings.CutPrefix(env, "GPTSCRIPT_VAR_")
if ok {
k, v, _ := strings.Cut(v, "=")
envMap[k] = v
}
}

toolURL := strings.Split(tool.Instructions, "\n")[0][2:]
toolURL = os.Expand(toolURL, func(s string) string {
return envMap[s]
})

parsed, err := url.Parse(toolURL)
if err != nil {
Expand Down Expand Up @@ -51,6 +64,10 @@ func (e *Engine) runHTTP(ctx context.Context, prg *types.Program, tool types.Too

req.Header.Set("X-GPTScript-Tool-Name", tool.Parameters.Name)

for k, v := range envMap {
req.Header.Set("X-GPTScript-Var-"+k, v)
}

if err := json.Unmarshal([]byte(input), &map[string]any{}); err == nil {
req.Header.Set("Content-Type", "application/json")
} else {
Expand Down
22 changes: 12 additions & 10 deletions pkg/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ func readTool(ctx context.Context, prg *types.Program, base *source, targetToolN
)

for i, tool := range tools {
tool.WorkingDir = base.Path
tool.Source.File = base.File

// Probably a better way to come up with an ID
Expand Down Expand Up @@ -234,7 +235,13 @@ var (
invalidChars = regexp.MustCompile("[^a-zA-Z0-9_-]+")
)

func toolNormalizer(tool string) string {
func ToolNormalizer(tool string) string {
parts := strings.Split(tool, "/")
tool = parts[len(parts)-1]
if strings.HasSuffix(tool, ".gpt") {
tool = strings.TrimSuffix(tool, filepath.Ext(tool))
}

if validToolName.MatchString(tool) {
return tool
}
Expand All @@ -251,22 +258,17 @@ func toolNormalizer(tool string) string {
}

func pickToolName(toolName string, existing map[string]struct{}) string {
newName, suffix, ok := strings.Cut(toolName, "/")
if ok {
newName = suffix
}
newName = strings.TrimSuffix(newName, filepath.Ext(newName))
if newName == "" {
newName = "external"
if toolName == "" {
toolName = "external"
}

for {
testName := toolNormalizer(newName)
testName := ToolNormalizer(toolName)
if _, ok := existing[testName]; !ok {
existing[testName] = struct{}{}
return testName
}
newName += "0"
toolName += "0"
}
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/mvl/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ func Package() Logger {
_, p, _, _ := runtime.Caller(1)
_, suffix, _ := strings.Cut(p, "gptscript/")
i := strings.LastIndex(suffix, "/")
return New(suffix[:i])
if i > 0 {
return New(suffix[:i])
}
return New(p)
}

func New(name string) Logger {
Expand Down
5 changes: 5 additions & 0 deletions pkg/runner/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package runner

import "github.com/gptscript-ai/gptscript/pkg/mvl"

var log = mvl.Package()
24 changes: 20 additions & 4 deletions pkg/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runner

import (
"context"
"os"
"sync"
"time"

Expand All @@ -20,30 +21,41 @@ type Monitor interface {
}

type Options struct {
WorkingDir string
MonitorFactory MonitorFactory `usage:"-"`
}

func complete(opts ...Options) (result Options) {
for _, opt := range opts {
result.WorkingDir = types.FirstSet(opt.WorkingDir, result.WorkingDir)
result.MonitorFactory = types.FirstSet(opt.MonitorFactory, result.MonitorFactory)
}
if result.MonitorFactory == nil {
result.MonitorFactory = noopFactory{}
}
if result.WorkingDir == "" {
var err error
result.WorkingDir, err = os.Getwd()
if err != nil {
log.Fatalf("failed to determine current working directory: %v", err)
}
}
return
}

type Runner struct {
c engine.Model
factory MonitorFactory
c engine.Model
factory MonitorFactory
workingDir string
}

func New(client engine.Model, opts ...Options) (*Runner, error) {
opt := complete(opts...)

return &Runner{
c: client,
factory: opt.MonitorFactory,
c: client,
factory: opt.MonitorFactory,
workingDir: opt.WorkingDir,
}, nil
}

Expand Down Expand Up @@ -94,6 +106,10 @@ func (r *Runner) call(callCtx engine.Context, monitor Monitor, env []string, inp
Env: env,
}

if r.workingDir != "" {
e.Env = append(e.Env, "GPTSCRIPT_VAR_WORKDIR="+r.workingDir)
}

monitor.Event(Event{
Time: time.Now(),
CallContext: &callCtx,
Expand Down
70 changes: 0 additions & 70 deletions pkg/test/examples_test.go

This file was deleted.

1 change: 0 additions & 1 deletion pkg/test/testdata/TestEcho.golden

This file was deleted.

1 change: 0 additions & 1 deletion pkg/test/testdata/TestExamples/fac.gpt.golden

This file was deleted.

1 change: 0 additions & 1 deletion pkg/test/testdata/TestExamples/helloworld.gpt.golden

This file was deleted.

26 changes: 26 additions & 0 deletions pkg/tests/runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tests

import (
"testing"

"github.com/gptscript-ai/gptscript/pkg/tests/tester"
"github.com/gptscript-ai/gptscript/pkg/types"
"github.com/stretchr/testify/assert"
)

func TestCwd(t *testing.T) {
runner := tester.NewRunner(t)

runner.RespondWith(tester.Result{
Func: types.CompletionFunctionCall{
Name: "subtool/test",
},
})
runner.RespondWith(tester.Result{
Func: types.CompletionFunctionCall{
Name: "local",
},
})
x := runner.RunDefault()
assert.Equal(t, "TEST RESULT CALL: 3", x)
}
91 changes: 91 additions & 0 deletions pkg/tests/testdata/TestCwd.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
`{
"Model": "gpt-4-turbo-preview",
"InternalSystemPrompt": null,
"Tools": [
{
"function": {
"name": "test",
"parameters": null
}
},
{
"function": {
"name": "local",
"parameters": null
}
}
],
"Messages": [
{
"role": "system",
"content": [
{
"text": "noop"
}
]
},
{
"role": "assistant",
"content": [
{
"toolCall": {
"index": 0,
"id": "call_1",
"function": {
"name": "test"
}
}
}
]
},
{
"role": "tool",
"content": [
{
"text": "sub\nsub"
}
],
"toolCall": {
"index": 0,
"id": "call_1",
"function": {
"name": "test"
}
}
},
{
"role": "assistant",
"content": [
{
"toolCall": {
"index": 1,
"id": "call_2",
"function": {
"name": "local"
}
}
}
]
},
{
"role": "tool",
"content": [
{
"text": "/testdata/TestCwd\nthe data"
}
],
"toolCall": {
"index": 1,
"id": "call_2",
"function": {
"name": "local"
}
}
}
],
"MaxTokens": 0,
"Temperature": null,
"JSONResponse": false,
"Grammar": "",
"Cache": null
}`
Loading

0 comments on commit 6126d27

Please sign in to comment.