Skip to content

Commit b2c74a5

Browse files
feat: add sys.chat.history
This allows multi agent flows to recall previous conversations
1 parent 171bb77 commit b2c74a5

File tree

5 files changed

+97
-21
lines changed

5 files changed

+97
-21
lines changed

pkg/builtin/builtin.go

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ import (
2020
"github.com/AlecAivazis/survey/v2"
2121
"github.com/BurntSushi/locker"
2222
"github.com/google/shlex"
23+
"github.com/gptscript-ai/gptscript/pkg/engine"
2324
"github.com/gptscript-ai/gptscript/pkg/types"
2425
"github.com/jaytaylor/html2text"
2526
)
2627

2728
var SafeTools = map[string]struct{}{
28-
"sys.echo": {},
29-
"sys.time.now": {},
30-
"sys.prompt": {},
31-
"sys.chat.finish": {},
29+
"sys.echo": {},
30+
"sys.time.now": {},
31+
"sys.prompt": {},
32+
"sys.chat.finish": {},
33+
"sys.chat.history": {},
3234
}
3335

3436
var tools = map[string]types.Tool{
@@ -182,6 +184,13 @@ var tools = map[string]types.Tool{
182184
},
183185
BuiltinFunc: SysPrompt,
184186
},
187+
"sys.chat.history": {
188+
Parameters: types.Parameters{
189+
Description: "Retrieves the previous chat dialog",
190+
Arguments: types.ObjectSchema(),
191+
},
192+
BuiltinFunc: SysChatHistory,
193+
},
185194
}
186195

187196
func SysProgram() *types.Program {
@@ -567,6 +576,33 @@ func (e *ErrChatFinish) Error() string {
567576
return fmt.Sprintf("CHAT FINISH: %s", e.Message)
568577
}
569578

579+
func SysChatHistory(ctx context.Context, _ []string, _ string) (string, error) {
580+
engineContext, _ := engine.FromContext(ctx)
581+
582+
data, err := json.Marshal(engine.ChatHistory{
583+
History: writeHistory(engineContext),
584+
})
585+
586+
return string(data), err
587+
}
588+
589+
func writeHistory(ctx *engine.Context) (result []engine.ChatHistoryCall) {
590+
if ctx == nil {
591+
return nil
592+
}
593+
if ctx.Parent != nil {
594+
result = append(result, writeHistory(ctx.Parent)...)
595+
}
596+
if ctx.LastReturn != nil && ctx.LastReturn.State != nil {
597+
result = append(result, engine.ChatHistoryCall{
598+
ID: ctx.ID,
599+
Tool: ctx.Tool,
600+
Completion: ctx.LastReturn.State.Completion,
601+
})
602+
}
603+
return
604+
}
605+
570606
func SysChatFinish(ctx context.Context, env []string, input string) (string, error) {
571607
var params struct {
572608
Message string `json:"return,omitempty"`

pkg/engine/cmd.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"github.com/gptscript-ai/gptscript/pkg/version"
2222
)
2323

24-
func (e *Engine) runCommand(ctx context.Context, tool types.Tool, input string, toolCategory ToolCategory) (cmdOut string, cmdErr error) {
24+
func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCategory ToolCategory) (cmdOut string, cmdErr error) {
2525
id := counter.Next()
2626

2727
defer func() {
@@ -42,10 +42,18 @@ func (e *Engine) runCommand(ctx context.Context, tool types.Tool, input string,
4242
"input": input,
4343
},
4444
}
45-
return tool.BuiltinFunc(ctx, e.Env, input)
45+
return tool.BuiltinFunc(ctx.WrappedContext(), e.Env, input)
4646
}
4747

48-
cmd, stop, err := e.newCommand(ctx, nil, tool, input)
48+
var instructions []string
49+
for _, inputContext := range ctx.InputContext {
50+
instructions = append(instructions, inputContext.Content)
51+
}
52+
var extraEnv = []string{
53+
strings.TrimSpace(fmt.Sprintf("GPTSCRIPT_CONTEXT=%s", strings.Join(instructions, "\n"))),
54+
}
55+
56+
cmd, stop, err := e.newCommand(ctx.Ctx, extraEnv, tool, input)
4957
if err != nil {
5058
return "", err
5159
}
@@ -66,7 +74,7 @@ func (e *Engine) runCommand(ctx context.Context, tool types.Tool, input string,
6674
cmd.Stdout = io.MultiWriter(all, output)
6775

6876
if toolCategory == CredentialToolCategory {
69-
pause := context2.GetPauseFuncFromCtx(ctx)
77+
pause := context2.GetPauseFuncFromCtx(ctx.Ctx)
7078
unpause := pause()
7179
defer unpause()
7280
}

pkg/engine/engine.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,20 @@ type CallContext struct {
6969

7070
type Context struct {
7171
commonContext
72-
Ctx context.Context
73-
Parent *Context
74-
Program *types.Program
72+
Ctx context.Context
73+
Parent *Context
74+
LastReturn *Return
75+
Program *types.Program
76+
}
77+
78+
type ChatHistory struct {
79+
History []ChatHistoryCall `json:"history,omitempty"`
80+
}
81+
82+
type ChatHistoryCall struct {
83+
ID string `json:"id,omitempty"`
84+
Tool types.Tool `json:"tool,omitempty"`
85+
Completion types.CompletionRequest `json:"completion,omitempty"`
7586
}
7687

7788
type ToolCategory string
@@ -194,7 +205,7 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
194205
} else if tool.IsEcho() {
195206
return e.runEcho(tool)
196207
}
197-
s, err := e.runCommand(ctx.WrappedContext(), tool, input, ctx.ToolCategory)
208+
s, err := e.runCommand(ctx, tool, input, ctx.ToolCategory)
198209
if err != nil {
199210
return nil, err
200211
}
@@ -233,6 +244,10 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
233244
input = ""
234245
}
235246

247+
if tool.Chat && input == "{}" {
248+
input = ""
249+
}
250+
236251
if input != "" {
237252
completion.Messages = append(completion.Messages, types.CompletionMessage{
238253
Role: types.CompletionMessageRoleTypeUser,

pkg/runner/runner.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,10 @@ func (r *Runner) subCalls(callCtx engine.Context, monitor Monitor, env []string,
711711
resultLock sync.Mutex
712712
)
713713

714+
if state.Continuation != nil {
715+
callCtx.LastReturn = state.Continuation
716+
}
717+
714718
if state.InputContextContinuation != nil {
715719
return state, nil, nil
716720
}

pkg/types/completion.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import (
99
)
1010

1111
type CompletionRequest struct {
12-
Model string
13-
InternalSystemPrompt *bool
14-
Tools []CompletionTool
15-
Messages []CompletionMessage
16-
MaxTokens int
17-
Temperature *float32
18-
JSONResponse bool
19-
Grammar string
20-
Cache *bool
12+
Model string `json:"model,omitempty"`
13+
InternalSystemPrompt *bool `json:"internalSystemPrompt,omitempty"`
14+
Tools []CompletionTool `json:"tools,omitempty"`
15+
Messages []CompletionMessage `json:"messages,omitempty"`
16+
MaxTokens int `json:"maxTokens,omitempty"`
17+
Temperature *float32 `json:"temperature,omitempty"`
18+
JSONResponse bool `json:"jsonResponse,omitempty"`
19+
Cache *bool `json:"cache,omitempty"`
2120
}
2221

2322
func (r *CompletionRequest) GetCache() bool {
@@ -57,6 +56,20 @@ type CompletionMessage struct {
5756
Usage Usage `json:"usage,omitempty"`
5857
}
5958

59+
func (c CompletionMessage) ChatText() string {
60+
var buf strings.Builder
61+
for _, part := range c.Content {
62+
if part.Text == "" {
63+
continue
64+
}
65+
if buf.Len() > 0 {
66+
buf.WriteString(" ")
67+
}
68+
buf.WriteString(part.Text)
69+
}
70+
return buf.String()
71+
}
72+
6073
type Usage struct {
6174
PromptTokens int `json:"promptTokens,omitempty"`
6275
CompletionTokens int `json:"completionTokens,omitempty"`

0 commit comments

Comments
 (0)