Skip to content

Commit 9fe36e9

Browse files
chore: compress env vars that are too large
1 parent f27e193 commit 9fe36e9

File tree

7 files changed

+203
-2
lines changed

7 files changed

+203
-2
lines changed

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

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package cli
2+
3+
import (
4+
"bytes"
5+
"compress/gzip"
6+
"encoding/base64"
7+
"os"
8+
"testing"
9+
)
10+
11+
func TestGetEnv(t *testing.T) {
12+
// Cleaning up
13+
defer func(currentEnvValue string) {
14+
os.Setenv("testKey", currentEnvValue)
15+
}(os.Getenv("testKey"))
16+
17+
// Tests
18+
testCases := []struct {
19+
name string
20+
key string
21+
def string
22+
envValue string
23+
expectedResult string
24+
}{
25+
{
26+
name: "NoValueUseDefault",
27+
key: "testKey",
28+
def: "defaultValue",
29+
envValue: "",
30+
expectedResult: "defaultValue",
31+
},
32+
{
33+
name: "ValueExistsNoCompress",
34+
key: "testKey",
35+
def: "defaultValue",
36+
envValue: "testValue",
37+
expectedResult: "testValue",
38+
},
39+
{
40+
name: "ValueExistsCompressed",
41+
key: "testKey",
42+
def: "defaultValue",
43+
envValue: `{"_gz":"H4sIAEosrGYC/ytJLS5RKEvMKU0FACtB3ewKAAAA"}`,
44+
45+
expectedResult: "test value",
46+
},
47+
}
48+
49+
for _, test := range testCases {
50+
t.Run(test.name, func(t *testing.T) {
51+
os.Setenv(test.key, test.envValue)
52+
53+
result := getEnv(test.key, test.def)
54+
55+
if result != test.expectedResult {
56+
t.Errorf("expected: %s, got: %s", test.expectedResult, result)
57+
}
58+
})
59+
}
60+
}
61+
62+
// Helper Function to Get Compressed String for Testing
63+
func getCompressedString(s string) string {
64+
var buf bytes.Buffer
65+
gz := gzip.NewWriter(&buf)
66+
67+
_, _ = gz.Write([]byte(s))
68+
_ = gz.Close()
69+
70+
encodedStr := base64.StdEncoding.EncodeToString(buf.Bytes())
71+
return `{"_gz":"` + encodedStr + `"}`
72+
}

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)