Skip to content

Commit 4283d79

Browse files
chore: add --save-chat-state-file
This also makes is so that if you want "stateless" chat through the CLI you have to do --save-chate-state-file stdout
1 parent 793ad21 commit 4283d79

File tree

6 files changed

+42
-18
lines changed

6 files changed

+42
-18
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
1717
github.com/google/uuid v1.6.0
1818
github.com/gptscript-ai/chat-completion-client v0.0.0-20240515050533-bdef9f2226a9
19-
github.com/gptscript-ai/tui v0.0.0-20240604045848-e01b0b7aab9f
19+
github.com/gptscript-ai/tui v0.0.0-20240604233332-4a5ff43cdc58
2020
github.com/hexops/autogold/v2 v2.2.1
2121
github.com/hexops/valast v1.4.4
2222
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
@@ -62,7 +62,7 @@ require (
6262
github.com/gookit/color v1.5.4 // indirect
6363
github.com/gorilla/css v1.0.0 // indirect
6464
github.com/gorilla/websocket v1.5.0 // indirect
65-
github.com/gptscript-ai/go-gptscript v0.0.0-20240604030145-39497c0575b3 // indirect
65+
github.com/gptscript-ai/go-gptscript v0.0.0-20240604231423-7a845df843b1 // indirect
6666
github.com/hashicorp/errwrap v1.0.0 // indirect
6767
github.com/hashicorp/go-multierror v1.1.1 // indirect
6868
github.com/hexops/autogold v1.3.1 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
172172
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
173173
github.com/gptscript-ai/chat-completion-client v0.0.0-20240515050533-bdef9f2226a9 h1:s6nL/aokB1sJTqVXEjN0zFI5CJa66ubw9g68VTMzEw0=
174174
github.com/gptscript-ai/chat-completion-client v0.0.0-20240515050533-bdef9f2226a9/go.mod h1:7P/o6/IWa1KqsntVf68hSnLKuu3+xuqm6lYhch1w4jo=
175-
github.com/gptscript-ai/go-gptscript v0.0.0-20240604030145-39497c0575b3 h1:mXLpCzEg4DoOeFZt6w99QFh9n60UwpRGGG0c+aaT+5k=
176-
github.com/gptscript-ai/go-gptscript v0.0.0-20240604030145-39497c0575b3/go.mod h1:h1yYzC0rgB5Kk7lwdba+Xs6cWkuJfLq6sPRna45OVG0=
177-
github.com/gptscript-ai/tui v0.0.0-20240604045848-e01b0b7aab9f h1:7dCE0E/y3y3p1BPSQGQ4mtsz5cWWl0FbXfCCDCf57SI=
178-
github.com/gptscript-ai/tui v0.0.0-20240604045848-e01b0b7aab9f/go.mod h1:ybD/8QfwaMiK2QUSnnTxgzrIaXRgipowU4pW1qxgNJ8=
175+
github.com/gptscript-ai/go-gptscript v0.0.0-20240604231423-7a845df843b1 h1:SHoqsU8Ne2V4zfrFve9kQn4vcv4N4TItD6Oju+pzKV8=
176+
github.com/gptscript-ai/go-gptscript v0.0.0-20240604231423-7a845df843b1/go.mod h1:h1yYzC0rgB5Kk7lwdba+Xs6cWkuJfLq6sPRna45OVG0=
177+
github.com/gptscript-ai/tui v0.0.0-20240604233332-4a5ff43cdc58 h1:kbr6cY4VdvxAfJf+xk6x/gxDzmgZMkX2ZfLcyskGYsw=
178+
github.com/gptscript-ai/tui v0.0.0-20240604233332-4a5ff43cdc58/go.mod h1:At6zmCk0XrJ2J1yo95fzbEDOGwaPPEMwxxcQGJx7IGE=
179179
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
180180
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
181181
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=

pkg/chat/chat.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package chat
22

33
import (
44
"context"
5+
"os"
56

67
"github.com/fatih/color"
78
"github.com/gptscript-ai/gptscript/pkg/runner"
@@ -30,7 +31,7 @@ func getPrompt(prg types.Program, resp runner.ChatResponse) string {
3031
return color.GreenString("%s> ", name)
3132
}
3233

33-
func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg GetProgram, env []string, startInput string) error {
34+
func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg GetProgram, env []string, startInput, chatStateSaveFile string) error {
3435
var (
3536
prompter Prompter
3637
)
@@ -60,7 +61,7 @@ func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg
6061
if startInput != "" {
6162
input = startInput
6263
startInput = ""
63-
} else if targetTool := prg.ToolSet[prg.EntryToolID]; !(prevState == nil && targetTool.Arguments == nil && targetTool.Instructions != "") {
64+
} else if targetTool := prg.ToolSet[prg.EntryToolID]; !((prevState == nil || prevState == "") && targetTool.Arguments == nil && targetTool.Instructions != "") {
6465
// The above logic will skip prompting if this is the first loop and the chat expects no args
6566
input, ok, err = prompter.Readline()
6667
if !ok || err != nil {
@@ -69,9 +70,15 @@ func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg
6970
}
7071

7172
resp, err = chatter.Chat(ctx, prevState, prg, env, input)
72-
if err != nil || resp.Done {
73+
if err != nil {
7374
return err
7475
}
76+
if resp.Done {
77+
if chatStateSaveFile != "" {
78+
_ = os.Remove(chatStateSaveFile)
79+
}
80+
return nil
81+
}
7582

7683
if resp.Content != "" {
7784
_, err := prompter.Printf("%s", color.RedString("< %s\n", resp.Content))
@@ -80,6 +87,10 @@ func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg
8087
}
8188
}
8289

90+
if chatStateSaveFile != "" {
91+
_ = os.WriteFile(chatStateSaveFile, []byte(resp.Content), 0600)
92+
}
93+
8394
prevState = resp.State
8495
prevResp = resp
8596
}

pkg/cli/eval.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (e *Eval) Run(cmd *cobra.Command, args []string) error {
7676
if e.Chat {
7777
return chat.Start(cmd.Context(), nil, runner, func() (types.Program, error) {
7878
return prg, nil
79-
}, os.Environ(), toolInput)
79+
}, os.Environ(), toolInput, "")
8080
}
8181

8282
toolOutput, err := runner.Run(cmd.Context(), prg, opts.Env, toolInput)

pkg/cli/gptscript.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,13 @@ type GPTScript struct {
6565
Ports string `usage:"The port range to use for ephemeral daemon ports (ex: 11000-12000)" hidden:"true"`
6666
CredentialContext string `usage:"Context name in which to store credentials" default:"default"`
6767
CredentialOverride string `usage:"Credentials to override (ex: --credential-override github.com/example/cred-tool:API_TOKEN=1234)"`
68-
ChatState string `usage:"The chat state to continue, or null to start a new chat and return the state"`
69-
ForceChat bool `usage:"Force an interactive chat session if even the top level tool is not a chat tool"`
70-
ForceSequential bool `usage:"Force parallel calls to run sequentially"`
68+
ChatState string `usage:"The chat state to continue, or null to start a new chat and return the state" local:"true"`
69+
ForceChat bool `usage:"Force an interactive chat session if even the top level tool is not a chat tool" local:"true"`
70+
ForceSequential bool `usage:"Force parallel calls to run sequentially" local:"true"`
7171
Workspace string `usage:"Directory to use for the workspace, if specified it will not be deleted on exit"`
7272
UI bool `usage:"Launch the UI" local:"true" name:"ui"`
7373
DisableTUI bool `usage:"Don't use chat TUI but instead verbose output" local:"true" name:"disable-tui"`
74+
SaveChatStateFile string `usage:"A file to save the chat state to so that a conversation can be resumed with --chat-state" local:"true"`
7475

7576
readData []byte
7677
}
@@ -425,8 +426,18 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) {
425426
return err
426427
}
427428

428-
if r.ChatState != "" {
429-
resp, err := gptScript.Chat(cmd.Context(), r.ChatState, prg, gptOpt.Env, toolInput)
429+
var chatState string
430+
if r.ChatState != "" && r.ChatState != "null" && !strings.HasPrefix(r.ChatState, "{") {
431+
data, err := os.ReadFile(r.ChatState)
432+
if err != nil {
433+
return fmt.Errorf("reading %s: %w", r.ChatState, err)
434+
}
435+
chatState = string(data)
436+
}
437+
438+
// This chat in a stateless mode
439+
if r.SaveChatStateFile == "-" || r.SaveChatStateFile == "stdout" {
440+
resp, err := gptScript.Chat(cmd.Context(), chatState, prg, gptOpt.Env, toolInput)
430441
if err != nil {
431442
return err
432443
}
@@ -446,11 +457,13 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) {
446457
CacheDir: r.CacheDir,
447458
SubTool: r.SubTool,
448459
Workspace: r.Workspace,
460+
SaveChatStateFile: r.SaveChatStateFile,
461+
ChatState: chatState,
449462
})
450463
}
451-
return chat.Start(cmd.Context(), nil, gptScript, func() (types.Program, error) {
464+
return chat.Start(cmd.Context(), chatState, gptScript, func() (types.Program, error) {
452465
return r.readProgram(ctx, gptScript, args)
453-
}, gptOpt.Env, toolInput)
466+
}, gptOpt.Env, toolInput, r.SaveChatStateFile)
454467
}
455468

456469
s, err := gptScript.Run(cmd.Context(), prg, gptOpt.Env, toolInput)

pkg/runner/runner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Progra
132132
case *State:
133133
state = v
134134
case string:
135-
if v != "null" {
135+
if v != "null" && v != "" {
136136
state = &State{}
137137
if err := json.Unmarshal([]byte(v), state); err != nil {
138138
return resp, fmt.Errorf("failed to unmarshal chat state: %w", err)

0 commit comments

Comments
 (0)