Skip to content

Commit 22c5d9b

Browse files
chore: add sys.chat.current
1 parent b26476b commit 22c5d9b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+240
-75
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/gptscript-ai/broadcaster v0.0.0-20240625175512-c43682019b86
1717
github.com/gptscript-ai/chat-completion-client v0.0.0-20240531200700-af8e7ecf0379
1818
github.com/gptscript-ai/cmd v0.0.0-20240625175447-4250b42feb7d
19-
github.com/gptscript-ai/tui v0.0.0-20240625175717-1e6eca7a66c1
19+
github.com/gptscript-ai/tui v0.0.0-20240627001757-8b452fa47eb5
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
@@ -94,6 +94,7 @@ require (
9494
github.com/pterm/pterm v0.12.79 // indirect
9595
github.com/rivo/uniseg v0.4.7 // indirect
9696
github.com/russross/blackfriday/v2 v2.1.0 // indirect
97+
github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e // indirect
9798
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
9899
github.com/therootcompany/xz v1.0.1 // indirect
99100
github.com/tidwall/match v1.1.1 // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ github.com/gptscript-ai/cmd v0.0.0-20240625175447-4250b42feb7d h1:sKf7T7twhGXs6A
173173
github.com/gptscript-ai/cmd v0.0.0-20240625175447-4250b42feb7d/go.mod h1:DJAo1xTht1LDkNYFNydVjTHd576TC7MlpsVRl3oloVw=
174174
github.com/gptscript-ai/go-gptscript v0.0.0-20240625134437-4b83849794cc h1:ABV7VAK65YBkqL7VlNp5ryVXnRqkKQ+U/NZfUO3ypqA=
175175
github.com/gptscript-ai/go-gptscript v0.0.0-20240625134437-4b83849794cc/go.mod h1:Dh6vYRAiVcyC3ElZIGzTvNF1FxtYwA07BHfSiFKQY7s=
176-
github.com/gptscript-ai/tui v0.0.0-20240625175717-1e6eca7a66c1 h1:sx/dJ0IRh3P9Ehr1g1TQ/jEw83KISmQyjrssVgPGUbE=
177-
github.com/gptscript-ai/tui v0.0.0-20240625175717-1e6eca7a66c1/go.mod h1:R33cfOnNaqsEn9es5jLKR39wvDyHvsIVgeTMNqtzCb8=
176+
github.com/gptscript-ai/tui v0.0.0-20240627001757-8b452fa47eb5 h1:knDhTTJNqaZB1XMudXJuVVnTqj9USrXzNfsl1nTqKXA=
177+
github.com/gptscript-ai/tui v0.0.0-20240627001757-8b452fa47eb5/go.mod h1:NwFdBDmGQvjLFFDnSRBRakkhw0MIO1sSdRnWNk4cCQ0=
178178
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
179179
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
180180
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
@@ -308,6 +308,8 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
308308
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
309309
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
310310
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
311+
github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e h1:H+jDTUeF+SVd4ApwnSFoew8ZwGNRfgb9EsZc7LcocAg=
312+
github.com/sourcegraph/go-diff-patch v0.0.0-20240223163233-798fd1e94a8e/go.mod h1:VsUklG6OQo7Ctunu0gS3AtEOCEc2kMB6r5rKzxAes58=
311313
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
312314
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
313315
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

pkg/builtin/builtin.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var SafeTools = map[string]struct{}{
2929
"sys.abort": {},
3030
"sys.chat.finish": {},
3131
"sys.chat.history": {},
32+
"sys.chat.current": {},
3233
"sys.echo": {},
3334
"sys.prompt": {},
3435
"sys.time.now": {},
@@ -229,6 +230,15 @@ var tools = map[string]types.Tool{
229230
BuiltinFunc: SysChatHistory,
230231
},
231232
},
233+
"sys.chat.current": {
234+
ToolDef: types.ToolDef{
235+
Parameters: types.Parameters{
236+
Description: "Retrieves the current chat dialog",
237+
Arguments: types.ObjectSchema(),
238+
},
239+
BuiltinFunc: SysChatCurrent,
240+
},
241+
},
232242
"sys.context": {
233243
ToolDef: types.ToolDef{
234244
Parameters: types.Parameters{
@@ -715,6 +725,28 @@ func writeHistory(ctx *engine.Context) (result []engine.ChatHistoryCall) {
715725
return
716726
}
717727

728+
func SysChatCurrent(ctx context.Context, _ []string, _ string, _ chan<- string) (string, error) {
729+
engineContext, _ := engine.FromContext(ctx)
730+
731+
var call any
732+
if engineContext != nil && engineContext.CurrentReturn != nil && engineContext.CurrentReturn.State != nil {
733+
call = engine.ChatHistoryCall{
734+
ID: engineContext.ID,
735+
Tool: engineContext.Tool,
736+
Completion: engineContext.CurrentReturn.State.Completion,
737+
}
738+
} else {
739+
call = map[string]any{}
740+
}
741+
742+
data, err := json.Marshal(call)
743+
if err != nil {
744+
return invalidArgument("", err), nil
745+
}
746+
747+
return string(data), nil
748+
}
749+
718750
func SysChatFinish(_ context.Context, _ []string, input string, _ chan<- string) (string, error) {
719751
var params struct {
720752
Message string `json:"return,omitempty"`

pkg/cli/gptscript.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ func (r *GPTScript) Run(cmd *cobra.Command, args []string) (retErr error) {
467467
DefaultModel: r.DefaultModel,
468468
TrustedRepoPrefixes: []string{"github.com/gptscript-ai"},
469469
DisableCache: r.DisableCache,
470-
Input: strings.Join(args[1:], " "),
470+
Input: toolInput,
471471
CacheDir: r.CacheDir,
472472
SubTool: r.SubTool,
473473
Workspace: r.Workspace,

pkg/engine/engine.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type CallResult struct {
5959
type commonContext struct {
6060
ID string `json:"id"`
6161
Tool types.Tool `json:"tool"`
62+
CurrentAgent types.ToolReference `json:"currentAgent,omitempty"`
6263
AgentGroup []types.ToolReference `json:"agentGroup,omitempty"`
6364
InputContext []InputContext `json:"inputContext"`
6465
ToolCategory ToolCategory `json:"toolCategory,omitempty"`
@@ -73,10 +74,11 @@ type CallContext struct {
7374

7475
type Context struct {
7576
commonContext
76-
Ctx context.Context
77-
Parent *Context
78-
LastReturn *Return
79-
Program *types.Program
77+
Ctx context.Context
78+
Parent *Context
79+
LastReturn *Return
80+
CurrentReturn *Return
81+
Program *types.Program
8082
// Input is saved only so that we can render display text, don't use otherwise
8183
Input string
8284
}
@@ -129,6 +131,18 @@ func (c *Context) ParentID() string {
129131
return c.Parent.ID
130132
}
131133

134+
func (c *Context) CurrentAgent() types.ToolReference {
135+
for _, ref := range c.AgentGroup {
136+
if ref.ToolID == c.Tool.ID {
137+
return ref
138+
}
139+
}
140+
if c.Parent != nil {
141+
return c.Parent.CurrentAgent()
142+
}
143+
return types.ToolReference{}
144+
}
145+
132146
func (c *Context) GetCallContext() *CallContext {
133147
var toolName string
134148
if c.Parent != nil {
@@ -143,12 +157,15 @@ func (c *Context) GetCallContext() *CallContext {
143157
}
144158
}
145159

146-
return &CallContext{
160+
result := &CallContext{
147161
commonContext: c.commonContext,
148162
ParentID: c.ParentID(),
149163
ToolName: toolName,
150164
DisplayText: types.ToDisplayText(c.Tool, c.Input),
151165
}
166+
167+
result.CurrentAgent = c.CurrentAgent()
168+
return result
152169
}
153170

154171
func (c *Context) UnmarshalJSON([]byte) error {
@@ -215,10 +232,11 @@ func (c *Context) SubCallContext(ctx context.Context, input, toolID, callID stri
215232
AgentGroup: agentGroup,
216233
ToolCategory: toolCategory,
217234
},
218-
Ctx: ctx,
219-
Parent: c,
220-
Program: c.Program,
221-
Input: input,
235+
Ctx: ctx,
236+
Parent: c,
237+
Program: c.Program,
238+
CurrentReturn: c.CurrentReturn,
239+
Input: input,
222240
}, nil
223241
}
224242

@@ -270,6 +288,7 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) {
270288
MaxTokens: tool.Parameters.MaxTokens,
271289
JSONResponse: tool.Parameters.JSONResponse,
272290
Cache: tool.Parameters.Cache,
291+
Chat: tool.Parameters.Chat,
273292
Temperature: tool.Parameters.Temperature,
274293
InternalSystemPrompt: tool.Parameters.InternalPrompt,
275294
}

pkg/openai/client.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,16 @@ func (c *Client) Call(ctx context.Context, messageRequest types.CompletionReques
300300
if messageRequest.Model == "" {
301301
messageRequest.Model = c.defaultModel
302302
}
303+
303304
msgs, err := toMessages(messageRequest, !c.setSeed)
304305
if err != nil {
305306
return nil, err
306307
}
307308

309+
if messageRequest.Chat {
310+
msgs = dropMessagesOverCount(messageRequest.MaxTokens, msgs)
311+
}
312+
308313
if len(msgs) == 0 {
309314
log.Errorf("invalid request, no messages to send to LLM")
310315
return &types.CompletionMessage{

pkg/openai/count.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package openai
2+
3+
import openai "github.com/gptscript-ai/chat-completion-client"
4+
5+
func dropMessagesOverCount(maxTokens int, msgs []openai.ChatCompletionMessage) (result []openai.ChatCompletionMessage) {
6+
var (
7+
lastSystem int
8+
withinBudget int
9+
budget = maxTokens
10+
)
11+
12+
if maxTokens == 0 {
13+
budget = 300_000
14+
} else {
15+
budget *= 3
16+
}
17+
18+
for i, msg := range msgs {
19+
if msg.Role == openai.ChatMessageRoleSystem {
20+
budget -= countMessage(msg)
21+
lastSystem = i
22+
result = append(result, msg)
23+
} else {
24+
break
25+
}
26+
}
27+
28+
for i := len(msgs) - 1; i > lastSystem; i-- {
29+
withinBudget = i
30+
budget -= countMessage(msgs[i])
31+
if budget <= 0 {
32+
break
33+
}
34+
}
35+
36+
if withinBudget == len(msgs)-1 {
37+
// We are going to drop all non system messages, which seems useless, so just return them
38+
// all and let it fail
39+
return msgs
40+
}
41+
42+
return append(result, msgs[withinBudget:]...)
43+
}
44+
45+
func countMessage(msg openai.ChatCompletionMessage) (count int) {
46+
count += len(msg.Role)
47+
count += len(msg.Content)
48+
for _, content := range msg.MultiContent {
49+
count += len(content.Text)
50+
}
51+
for _, tool := range msg.ToolCalls {
52+
count += len(tool.Function.Name)
53+
count += len(tool.Function.Arguments)
54+
}
55+
count += len(msg.ToolCallID)
56+
return count / 3
57+
}

pkg/runner/output.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ func (r *Runner) handleOutput(callCtx engine.Context, monitor Monitor, env []str
4141
for _, outputToolRef := range outputToolRefs {
4242
inputData, err := json.Marshal(map[string]any{
4343
"output": output,
44-
"chatFinish": chatFinish,
4544
"continuation": continuation,
4645
"chat": callCtx.Tool.Chat,
4746
})

pkg/runner/runner.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ func (r *Runner) resume(callCtx engine.Context, monitor Monitor, env []string, s
559559
}
560560

561561
for {
562+
callCtx.CurrentReturn = state.Continuation
563+
562564
if state.Continuation.Result != nil && len(state.Continuation.Calls) == 0 && state.SubCallID == "" && state.ResumeInput == nil {
563565
progressClose()
564566
monitor.Event(Event{

pkg/tests/runner_test.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ func TestSubChat(t *testing.T) {
413413
],
414414
"usage": {}
415415
}
416-
]
416+
],
417+
"chat": true
417418
}
418419
},
419420
"result": "Assistant 1"
@@ -555,7 +556,8 @@ func TestSubChat(t *testing.T) {
555556
],
556557
"usage": {}
557558
}
558-
]
559+
],
560+
"chat": true
559561
}
560562
},
561563
"result": "Assistant 2"
@@ -622,7 +624,8 @@ func TestChat(t *testing.T) {
622624
],
623625
"usage": {}
624626
}
625-
]
627+
],
628+
"chat": true
626629
}
627630
},
628631
"result": "Assistant 1"
@@ -691,7 +694,8 @@ func TestChat(t *testing.T) {
691694
],
692695
"usage": {}
693696
}
694-
]
697+
],
698+
"chat": true
695699
}
696700
},
697701
"result": "Assistant 2"
@@ -866,7 +870,7 @@ func TestOutput(t *testing.T) {
866870
require.NoError(t, err)
867871
r.AssertResponded(t)
868872
assert.False(t, resp.Done)
869-
autogold.Expect(`CHAT: true CONTENT: Response 1 CONTINUATION: true FINISH: false suffix
873+
autogold.Expect(`CHAT: true CONTENT: Response 1 CONTINUATION: true suffix
870874
`).Equal(t, resp.Content)
871875
autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step1"))
872876

@@ -877,7 +881,7 @@ func TestOutput(t *testing.T) {
877881
require.NoError(t, err)
878882
r.AssertResponded(t)
879883
assert.False(t, resp.Done)
880-
autogold.Expect(`CHAT: true CONTENT: Response 2 CONTINUATION: true FINISH: false suffix
884+
autogold.Expect(`CHAT: true CONTENT: Response 2 CONTINUATION: true suffix
881885
`).Equal(t, resp.Content)
882886
autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step2"))
883887

@@ -890,7 +894,7 @@ func TestOutput(t *testing.T) {
890894
require.NoError(t, err)
891895
r.AssertResponded(t)
892896
assert.True(t, resp.Done)
893-
autogold.Expect(`CHAT FINISH: CHAT: true CONTENT: Chat Done CONTINUATION: false FINISH: true suffix
897+
autogold.Expect(`CHAT FINISH: CHAT: true CONTENT: Chat Done CONTINUATION: false suffix
894898
`).Equal(t, resp.Content)
895899
autogold.ExpectFile(t, toJSONString(t, resp), autogold.Name(t.Name()+"/step3"))
896900
}

pkg/tests/testdata/TestAgents/call1.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@
5252
],
5353
"usage": {}
5454
}
55-
]
55+
],
56+
"chat": true
5657
}`

pkg/tests/testdata/TestAgents/call2.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
],
2929
"usage": {}
3030
}
31-
]
31+
],
32+
"chat": true
3233
}`

pkg/tests/testdata/TestAgents/call3.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@
4343
],
4444
"usage": {}
4545
}
46-
]
46+
],
47+
"chat": true
4748
}`

pkg/tests/testdata/TestAgents/call4.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
],
1212
"usage": {}
1313
}
14-
]
14+
],
15+
"chat": true
1516
}`

0 commit comments

Comments
 (0)