forked from gptscript-ai/gptscript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchat.go
97 lines (80 loc) · 2.19 KB
/
chat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package chat
import (
"context"
"os"
"github.com/fatih/color"
"github.com/gptscript-ai/gptscript/pkg/runner"
"github.com/gptscript-ai/gptscript/pkg/types"
)
type Prompter interface {
Readline() (string, bool, error)
Printf(format string, args ...interface{}) (int, error)
SetPrompt(p string)
Close() error
}
type Chatter interface {
Chat(ctx context.Context, prevState runner.ChatState, prg types.Program, env []string, input string) (resp runner.ChatResponse, err error)
}
type GetProgram func() (types.Program, error)
func getPrompt(prg types.Program, resp runner.ChatResponse) string {
name := prg.ChatName()
if newName := prg.ToolSet[resp.ToolID].Name; newName != "" {
name = newName
}
return color.GreenString("%s> ", name)
}
func Start(ctx context.Context, prevState runner.ChatState, chatter Chatter, prg GetProgram, env []string, startInput, chatStateSaveFile string) error {
var (
prompter Prompter
)
prompter, err := newReadlinePrompter(prg)
if err != nil {
return err
}
defer prompter.Close()
// We will want the tool name to be displayed in the prompt
var prevResp runner.ChatResponse
for {
var (
input string
ok bool
resp runner.ChatResponse
)
prg, err := prg()
if err != nil {
return err
}
prompter.SetPrompt(getPrompt(prg, prevResp))
if startInput != "" {
input = startInput
startInput = ""
} else if targetTool := prg.ToolSet[prg.EntryToolID]; !((prevState == nil || prevState == "") && targetTool.Arguments == nil && targetTool.Instructions != "") {
// The above logic will skip prompting if this is the first loop and the chat expects no args
input, ok, err = prompter.Readline()
if !ok || err != nil {
return err
}
}
resp, err = chatter.Chat(ctx, prevState, prg, env, input)
if err != nil {
return err
}
if resp.Done {
if chatStateSaveFile != "" {
_ = os.Remove(chatStateSaveFile)
}
return nil
}
if resp.Content != "" {
_, err := prompter.Printf("%s", color.RedString("< %s\n", resp.Content))
if err != nil {
return err
}
}
if chatStateSaveFile != "" {
_ = os.WriteFile(chatStateSaveFile, []byte(resp.Content), 0600)
}
prevState = resp.State
prevResp = resp
}
}