-
Notifications
You must be signed in to change notification settings - Fork 286
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial http and daemon support. Add nocache flag
- Loading branch information
1 parent
78917b2
commit 0b88314
Showing
8 changed files
with
365 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package engine | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
"sync/atomic" | ||
|
||
"github.com/google/shlex" | ||
"github.com/gptscript-ai/gptscript/pkg/openai" | ||
"github.com/gptscript-ai/gptscript/pkg/types" | ||
"github.com/gptscript-ai/gptscript/pkg/version" | ||
) | ||
|
||
func (e *Engine) runCommand(ctx context.Context, tool types.Tool, input string) (cmdOut string, cmdErr error) { | ||
id := fmt.Sprint(atomic.AddInt64(&completionID, 1)) | ||
|
||
defer func() { | ||
e.Progress <- openai.Status{ | ||
CompletionID: id, | ||
Response: map[string]any{ | ||
"output": cmdOut, | ||
"err": cmdErr, | ||
}, | ||
} | ||
}() | ||
|
||
if tool.BuiltinFunc != nil { | ||
e.Progress <- openai.Status{ | ||
CompletionID: id, | ||
Request: map[string]any{ | ||
"command": []string{tool.ID}, | ||
"input": input, | ||
}, | ||
} | ||
return tool.BuiltinFunc(ctx, e.Env, input) | ||
} | ||
|
||
cmd, close, err := e.newCommand(ctx, nil, tool.Instructions, input) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer close() | ||
|
||
e.Progress <- openai.Status{ | ||
CompletionID: id, | ||
Request: map[string]any{ | ||
"command": cmd.Args, | ||
"input": input, | ||
}, | ||
} | ||
|
||
output := &bytes.Buffer{} | ||
cmd.Stdin = strings.NewReader(input) | ||
cmd.Stderr = os.Stderr | ||
cmd.Stdout = output | ||
|
||
if err := cmd.Run(); err != nil { | ||
_, _ = os.Stderr.Write(output.Bytes()) | ||
log.Errorf("failed to run tool [%s] cmd %v: %v", tool.Name, cmd.Args, err) | ||
return "", err | ||
} | ||
|
||
return output.String(), nil | ||
} | ||
|
||
func (e *Engine) newCommand(ctx context.Context, extraEnv []string, instructions, input string) (*exec.Cmd, func(), error) { | ||
env := append(e.Env[:], extraEnv...) | ||
data := map[string]any{} | ||
|
||
dec := json.NewDecoder(bytes.NewReader([]byte(input))) | ||
dec.UseNumber() | ||
|
||
envMap := map[string]string{} | ||
for _, env := range env { | ||
key, value, ok := strings.Cut(env, "=") | ||
key, ok = strings.CutPrefix(key, "GPTSCRIPT_VAR_") | ||
if !ok { | ||
continue | ||
} | ||
envMap[key] = value | ||
} | ||
|
||
if err := json.Unmarshal([]byte(input), &data); err == nil { | ||
for k, v := range data { | ||
envName := strings.ToUpper(strings.ReplaceAll(k, "-", "_")) | ||
switch val := v.(type) { | ||
case string: | ||
envMap[envName] = val | ||
env = append(env, envName+"="+val) | ||
envMap[k] = val | ||
env = append(env, k+"="+val) | ||
case json.Number: | ||
envMap[envName] = string(val) | ||
env = append(env, envName+"="+string(val)) | ||
envMap[k] = string(val) | ||
env = append(env, k+"="+string(val)) | ||
case bool: | ||
envMap[envName] = fmt.Sprint(val) | ||
env = append(env, envName+"="+fmt.Sprint(val)) | ||
envMap[k] = fmt.Sprint(val) | ||
env = append(env, k+"="+fmt.Sprint(val)) | ||
default: | ||
data, err := json.Marshal(val) | ||
if err == nil { | ||
envMap[envName] = string(data) | ||
env = append(env, envName+"="+string(data)) | ||
envMap[k] = string(data) | ||
env = append(env, k+"="+string(data)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
interpreter, rest, _ := strings.Cut(instructions, "\n") | ||
interpreter = strings.TrimSpace(interpreter)[2:] | ||
|
||
interpreter = os.Expand(interpreter, func(s string) string { | ||
return envMap[s] | ||
}) | ||
|
||
args, err := shlex.Split(interpreter) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
var ( | ||
cmdArgs = args[1:] | ||
close func() | ||
) | ||
|
||
if strings.TrimSpace(rest) != "" { | ||
f, err := os.CreateTemp("", version.ProgramName) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
close = func() { | ||
os.Remove(f.Name()) | ||
} | ||
|
||
_, err = f.Write([]byte(rest)) | ||
_ = f.Close() | ||
if err != nil { | ||
close() | ||
return nil, nil, err | ||
} | ||
cmdArgs = append(cmdArgs, f.Name()) | ||
} | ||
|
||
cmd := exec.CommandContext(ctx, args[0], cmdArgs...) | ||
cmd.Env = env | ||
return cmd, close, nil | ||
} |
Oops, something went wrong.