Skip to content

Commit 2e69f70

Browse files
Merge pull request #695 from ibuildthecloud/main
chore: compress env vars that are too large
2 parents f27e193 + d28649a commit 2e69f70

File tree

9 files changed

+237
-2
lines changed

9 files changed

+237
-2
lines changed

docs/docs/04-command-line-reference/gptscript.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ gptscript [flags] PROGRAM_FILE [INPUT...]
5151
* [gptscript credential](gptscript_credential.md) - List stored credentials
5252
* [gptscript eval](gptscript_eval.md) -
5353
* [gptscript fmt](gptscript_fmt.md) -
54+
* [gptscript getenv](gptscript_getenv.md) - Looks up an environment variable for use in GPTScript tools
5455
* [gptscript parse](gptscript_parse.md) -
5556

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
title: "gptscript getenv"
3+
---
4+
## gptscript getenv
5+
6+
Looks up an environment variable for use in GPTScript tools
7+
8+
```
9+
gptscript getenv [flags] KEY [DEFAULT]
10+
```
11+
12+
### Options
13+
14+
```
15+
-h, --help help for getenv
16+
```
17+
18+
### Options inherited from parent commands
19+
20+
```
21+
--cache-dir string Directory to store cache (default: $XDG_CACHE_HOME/gptscript) ($GPTSCRIPT_CACHE_DIR)
22+
-C, --chdir string Change current working directory ($GPTSCRIPT_CHDIR)
23+
--color Use color in output (default true) ($GPTSCRIPT_COLOR)
24+
--config string Path to GPTScript config file ($GPTSCRIPT_CONFIG)
25+
--confirm Prompt before running potentially dangerous commands ($GPTSCRIPT_CONFIRM)
26+
--credential-context string Context name in which to store credentials ($GPTSCRIPT_CREDENTIAL_CONTEXT) (default "default")
27+
--credential-override strings Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234) ($GPTSCRIPT_CREDENTIAL_OVERRIDE)
28+
--debug Enable debug logging ($GPTSCRIPT_DEBUG)
29+
--debug-messages Enable logging of chat completion calls ($GPTSCRIPT_DEBUG_MESSAGES)
30+
--default-model string Default LLM model to use ($GPTSCRIPT_DEFAULT_MODEL) (default "gpt-4o")
31+
--default-model-provider string Default LLM model provider to use, this will override OpenAI settings ($GPTSCRIPT_DEFAULT_MODEL_PROVIDER)
32+
--disable-cache Disable caching of LLM API responses ($GPTSCRIPT_DISABLE_CACHE)
33+
--dump-state string Dump the internal execution state to a file ($GPTSCRIPT_DUMP_STATE)
34+
--events-stream-to string Stream events to this location, could be a file descriptor/handle (e.g. fd://2), filename, or named pipe (e.g. \\.\pipe\my-pipe) ($GPTSCRIPT_EVENTS_STREAM_TO)
35+
-f, --input string Read input from a file ("-" for stdin) ($GPTSCRIPT_INPUT_FILE)
36+
--no-trunc Do not truncate long log messages ($GPTSCRIPT_NO_TRUNC)
37+
--openai-api-key string OpenAI API KEY ($OPENAI_API_KEY)
38+
--openai-base-url string OpenAI base URL ($OPENAI_BASE_URL)
39+
--openai-org-id string OpenAI organization ID ($OPENAI_ORG_ID)
40+
-o, --output string Save output to a file, or - for stdout ($GPTSCRIPT_OUTPUT)
41+
-q, --quiet No output logging (set --quiet=false to force on even when there is no TTY) ($GPTSCRIPT_QUIET)
42+
--workspace string Directory to use for the workspace, if specified it will not be deleted on exit ($GPTSCRIPT_WORKSPACE)
43+
```
44+
45+
### SEE ALSO
46+
47+
* [gptscript](gptscript.md) -
48+

pkg/cli/getenv.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package cli
2+
3+
import (
4+
"bytes"
5+
"compress/gzip"
6+
"encoding/base64"
7+
"fmt"
8+
"io"
9+
"os"
10+
"strings"
11+
12+
"github.com/spf13/cobra"
13+
)
14+
15+
type Getenv struct {
16+
}
17+
18+
func (e *Getenv) Customize(cmd *cobra.Command) {
19+
cmd.Use = "getenv [flags] KEY [DEFAULT]"
20+
cmd.Short = "Looks up an environment variable for use in GPTScript tools"
21+
cmd.Args = cobra.RangeArgs(1, 2)
22+
}
23+
24+
func (e *Getenv) Run(_ *cobra.Command, args []string) error {
25+
var (
26+
key = args[0]
27+
def string
28+
)
29+
if len(args) > 1 {
30+
def = args[1]
31+
}
32+
value := getEnv(key, def)
33+
fmt.Print(value)
34+
return nil
35+
}
36+
37+
func getEnv(key, def string) string {
38+
v := os.Getenv(key)
39+
if v == "" {
40+
return def
41+
}
42+
43+
if strings.HasPrefix(v, `{"_gz":"`) && strings.HasSuffix(v, `"}`) {
44+
data, err := base64.StdEncoding.DecodeString(v[8 : len(v)-2])
45+
if err != nil {
46+
return v
47+
}
48+
gz, err := gzip.NewReader(bytes.NewBuffer(data))
49+
if err != nil {
50+
return v
51+
}
52+
strBytes, err := io.ReadAll(gz)
53+
if err != nil {
54+
return v
55+
}
56+
return string(strBytes)
57+
}
58+
59+
return v
60+
}

pkg/cli/getenv_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package cli
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
func TestGetEnv(t *testing.T) {
9+
// Cleaning up
10+
defer func(currentEnvValue string) {
11+
os.Setenv("testKey", currentEnvValue)
12+
}(os.Getenv("testKey"))
13+
14+
// Tests
15+
testCases := []struct {
16+
name string
17+
key string
18+
def string
19+
envValue string
20+
expectedResult string
21+
}{
22+
{
23+
name: "NoValueUseDefault",
24+
key: "testKey",
25+
def: "defaultValue",
26+
envValue: "",
27+
expectedResult: "defaultValue",
28+
},
29+
{
30+
name: "ValueExistsNoCompress",
31+
key: "testKey",
32+
def: "defaultValue",
33+
envValue: "testValue",
34+
expectedResult: "testValue",
35+
},
36+
{
37+
name: "ValueExistsCompressed",
38+
key: "testKey",
39+
def: "defaultValue",
40+
envValue: `{"_gz":"H4sIAEosrGYC/ytJLS5RKEvMKU0FACtB3ewKAAAA"}`,
41+
42+
expectedResult: "test value",
43+
},
44+
}
45+
46+
for _, test := range testCases {
47+
t.Run(test.name, func(t *testing.T) {
48+
os.Setenv(test.key, test.envValue)
49+
50+
result := getEnv(test.key, test.def)
51+
52+
if result != test.expectedResult {
53+
t.Errorf("expected: %s, got: %s", test.expectedResult, result)
54+
}
55+
})
56+
}
57+
}

pkg/cli/gptscript.go

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func New() *cobra.Command {
8585
&Credential{root: root},
8686
&Parse{},
8787
&Fmt{},
88+
&Getenv{},
8889
&SDKServer{
8990
GPTScript: root,
9091
},

pkg/engine/cmd.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package engine
22

33
import (
44
"bytes"
5+
"compress/gzip"
56
"context"
7+
"encoding/base64"
68
"encoding/json"
79
"fmt"
810
"io"
@@ -44,6 +46,25 @@ func (o *outputWriter) Write(p []byte) (n int, err error) {
4446
return len(p), nil
4547
}
4648

49+
func compressEnv(envs []string) (result []string) {
50+
for _, env := range envs {
51+
k, v, ok := strings.Cut(env, "=")
52+
if !ok || len(v) < 40_000 {
53+
result = append(result, env)
54+
continue
55+
}
56+
57+
out := bytes.NewBuffer(nil)
58+
b64 := base64.NewEncoder(base64.StdEncoding, out)
59+
gz := gzip.NewWriter(b64)
60+
_, _ = gz.Write([]byte(v))
61+
_ = gz.Close()
62+
_ = b64.Close()
63+
result = append(result, k+`={"_gz":"`+out.String()+`"}`)
64+
}
65+
return
66+
}
67+
4768
func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCategory ToolCategory) (cmdOut string, cmdErr error) {
4869
id := counter.Next()
4970

@@ -95,10 +116,10 @@ func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCate
95116
for _, inputContext := range ctx.InputContext {
96117
instructions = append(instructions, inputContext.Content)
97118
}
119+
98120
var extraEnv = []string{
99121
strings.TrimSpace("GPTSCRIPT_CONTEXT=" + strings.Join(instructions, "\n")),
100122
}
101-
102123
cmd, stop, err := e.newCommand(ctx.Ctx, extraEnv, tool, input)
103124
if err != nil {
104125
return "", err
@@ -277,6 +298,6 @@ func (e *Engine) newCommand(ctx context.Context, extraEnv []string, tool types.T
277298
}
278299

279300
cmd := exec.CommandContext(ctx, env.Lookup(envvars, args[0]), cmdArgs...)
280-
cmd.Env = envvars
301+
cmd.Env = compressEnv(envvars)
281302
return cmd, stop, nil
282303
}

pkg/tests/runner_test.go

+32
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"_gz":"H4sIAAAAAAAA/+zAgQAAAADCMNb8JQK4wjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHgAA//+94pKFQBkBAA=="}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
context: c
2+
3+
#!/bin/bash
4+
5+
echo "${GPTSCRIPT_CONTEXT}"
6+
echo "${GPTSCRIPT_CONTEXT}" > ${GPTSCRIPT_TOOL_DIR}/context.json
7+
8+
---
9+
name: c
10+
11+
#!/bin/bash
12+
13+
string=$(printf 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%.0s' {1..1000})
14+
echo "$string"

0 commit comments

Comments
 (0)