Skip to content

Commit

Permalink
Add sys.download
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Feb 10, 2024
1 parent fdd9404 commit 90a63c4
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
9 changes: 9 additions & 0 deletions examples/bob.gpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
tools: bob

Ask Bob how he is doing and let me know exactly what he said.

---
name: bob
description: I'm Bob, a friendly guy.

When asked how I am doing, respond with "I'm doing great fellow friendly AI tool!"
9 changes: 9 additions & 0 deletions examples/sqlite-download.gpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
tools: sys.download, sys.exec

Download https://www.sqlitetutorial.net/wp-content/uploads/2018/03/chinook.zip to the
local directory. Expand the archive as there is a sqlite database in it.

First inspect the schema of the database to understand the table structure.

Form and run a SQL query to find the artist with the most number of albums and output
the result of that.
65 changes: 65 additions & 0 deletions pkg/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package builtin
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
Expand Down Expand Up @@ -80,6 +81,13 @@ var tools = map[string]types.Tool{
"name", "The environment variable name to lookup"),
BuiltinFunc: SysGetenv,
},
"sys.download": {
Description: "Downloads a URL, saving the contents to disk at a given location",
Arguments: types.ObjectSchema(
"url", "The URL to download, either http or https.",
"location", "(optional) The on disk location to store the file. If no location is specified a temp location will be used. If the target file already exists it will not be overwritten and will fail."),
BuiltinFunc: SysDownload,
},
}

func SysProgram() *types.Program {
Expand Down Expand Up @@ -308,3 +316,60 @@ func SysAbort(ctx context.Context, env []string, input string) (string, error) {
}
return "", fmt.Errorf("ABORT: %s", params.Message)
}

func SysDownload(ctx context.Context, env []string, input string) (string, error) {
var params struct {
URL string `json:"url,omitempty"`
Location string `json:"location,omitempty"`
}
if err := json.Unmarshal([]byte(input), &params); err != nil {
return "", err
}

checkExists := true
if params.Location == "" {
f, err := os.CreateTemp("", "gpt-download")
if err != nil {
return "", err
}
if err := f.Close(); err != nil {
return "", err
}
checkExists = false
params.Location = f.Name()
}

if checkExists {
if _, err := os.Stat(params.Location); err == nil {
return "", fmt.Errorf("file %s already exists and can not be overwritten: %w", params.Location, err)
} else if err != nil && !errors.Is(err, fs.ErrNotExist) {
return "", err
}
}

log.Infof("download [%s] to [%s]", params.URL, params.Location)
resp, err := http.Get(params.URL)
if err != nil {
return "", err
}
defer func() {
_, _ = io.ReadAll(resp.Body)
_ = resp.Body.Close()
}()

if resp.StatusCode > 299 {
return "", fmt.Errorf("invalid status code [%d] downloading [%s]: %s", resp.StatusCode, params.URL, resp.Status)
}

f, err := os.Create(params.Location)
if err != nil {
return "", fmt.Errorf("failed to create [%s]: %w", params.Location, err)
}
defer f.Close()

if _, err := io.Copy(f, resp.Body); err != nil {
return "", fmt.Errorf("failed copying data from [%s] to [%s]: %w", params.URL, params.Location, err)
}

return params.Location, nil
}

0 comments on commit 90a63c4

Please sign in to comment.