diff --git a/main.go b/main.go index 597bf11a..8421b526 100644 --- a/main.go +++ b/main.go @@ -1,13 +1,25 @@ package main import ( + "os" + "github.com/acorn-io/cmd" "github.com/gptscript-ai/gptscript/pkg/cli" + "github.com/gptscript-ai/gptscript/pkg/daemon" + "github.com/gptscript-ai/gptscript/pkg/mvl" // Load all VCS _ "github.com/gptscript-ai/gptscript/pkg/loader/vcs" ) +var log = mvl.Package() + func main() { + if len(os.Args) > 2 && os.Args[1] == "sys.daemon" { + if err := daemon.SysDaemon(); err != nil { + log.Fatalf("failed running daemon: %v", err) + } + os.Exit(0) + } cmd.Main(cli.New()) } diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go new file mode 100644 index 00000000..63bbd315 --- /dev/null +++ b/pkg/daemon/daemon.go @@ -0,0 +1,24 @@ +package daemon + +import ( + "context" + "io" + "os" + "os/exec" +) + +func SysDaemon() error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + go func() { + _, _ = io.ReadAll(os.Stdin) + cancel() + }() + + cmd := exec.CommandContext(ctx, os.Args[2], os.Args[3:]...) + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + return cmd.Run() +} diff --git a/pkg/engine/daemon.go b/pkg/engine/daemon.go index c5863833..42140128 100644 --- a/pkg/engine/daemon.go +++ b/pkg/engine/daemon.go @@ -131,6 +131,10 @@ func (e *Engine) startDaemon(_ context.Context, tool types.Tool) (string, error) return "", err } + // Loop back to gptscript to help with process supervision + cmd.Args = append([]string{os.Args[0], "sys.daemon", cmd.Path}, cmd.Args[1:]...) + cmd.Path = self() + cmd.Stdin = r cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout diff --git a/pkg/engine/self.go b/pkg/engine/self.go new file mode 100644 index 00000000..b58a2716 --- /dev/null +++ b/pkg/engine/self.go @@ -0,0 +1,27 @@ +//go:build !linux + +package engine + +import ( + "os" + "os/exec" + "path/filepath" +) + +// Copied from github.com/moby/moby/pkg/reexec d25b0bd7ea6ce17ca085c54d5965eeeb66417e52 + +func self() string { + name := os.Args[0] + if filepath.Base(name) == name { + if lp, err := exec.LookPath(name); err == nil { + return lp + } + } + // handle conversion of relative paths to absolute + if absName, err := filepath.Abs(name); err == nil { + return absName + } + // if we couldn't get absolute name, return original + // (NOTE: Go only errors on Abs() if os.Getwd fails) + return name +} diff --git a/pkg/engine/self_linux.go b/pkg/engine/self_linux.go new file mode 100644 index 00000000..ea54eb02 --- /dev/null +++ b/pkg/engine/self_linux.go @@ -0,0 +1,5 @@ +package engine + +func self() string { + return "/proc/self/exe" +}