Skip to content

Commit ee2b368

Browse files
authoredMay 10, 2024
Merge pull request #17 from thedadams/first-rewrite
feat: add Run type for more manageable implementation
·
v0.9.5v0.8.5-rc1
2 parents 62ca3d9 + e6b6bf8 commit ee2b368

File tree

13 files changed

+1619
-1071
lines changed

13 files changed

+1619
-1071
lines changed
 

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ go.work
2424
.idea/
2525
.vscode/
2626

27+
workspace/
2728
bin/
2829
workspace/

‎README.md

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ To use the module, you need to first set the OPENAI_API_KEY environment variable
1616

1717
Additionally, you need the `gptscript` binary. You can install it on your system using the [installation instructions](https://github.com/gptscript-ai/gptscript?tab=readme-ov-file#1-install-the-latest-release). The binary can be on the PATH, or the `GPTSCRIPT_BIN` environment variable can be used to specify its location.
1818

19+
## Client
20+
21+
There are currently a couple "global" options, and the client helps to manage those. A client without any options is
22+
likely what you want. However, here are the current global options:
23+
24+
- `gptscriptURL`: The URL (including `http(s)://) of an "SDK server" to use instead of the fork/exec model.
25+
- `gptscriptBin`: The path to a `gptscript` binary to use instead of the bundled one.
26+
1927
## Options
2028

2129
These are optional options that can be passed to the various `exec` functions.
@@ -26,6 +34,10 @@ None of the options is required, and the defaults will reduce the number of call
2634
- `quiet`: No output logging
2735
- `chdir`: Change current working directory
2836
- `subTool`: Use tool of this name, not the first tool
37+
- `input`: Input arguments for the tool run
38+
- `workspace`: Directory to use for the workspace, if specified it will not be deleted on exit
39+
- `inlcudeEvents`: Whether to include the streaming of events. Default (false). Note that if this is true, you must stream the events. See below for details.
40+
- `chatState`: The chat state to continue, or null to start a new chat and return the state
2941

3042
## Functions
3143

@@ -45,7 +57,9 @@ import (
4557
)
4658

4759
func listTools(ctx context.Context) (string, error) {
48-
return gogptscript.ListTools(ctx)
60+
client := &gogptscript.Client{}
61+
client.Complete()
62+
return client.ListTools(ctx)
4963
}
5064
```
5165

@@ -65,13 +79,15 @@ import (
6579
)
6680

6781
func listModels(ctx context.Context) ([]string, error) {
68-
return gogptscript.ListModels(ctx)
82+
client := &gogptscript.Client{}
83+
client.Complete()
84+
return client.ListModels(ctx)
6985
}
7086
```
7187

72-
### ExecTool
88+
### Parse
7389

74-
Executes a prompt with optional arguments.
90+
Parse file into a Tool data structure
7591

7692
```go
7793
package main
@@ -82,18 +98,17 @@ import (
8298
gogptscript "github.com/gptscript-ai/go-gptscript"
8399
)
84100

85-
func runTool(ctx context.Context) (string, error) {
86-
t := gogptscript.Tool{
87-
Instructions: "who was the president of the united states in 1928?",
88-
}
89-
90-
return gogptscript.ExecTool(ctx, gogptscript.Opts{}, t)
101+
func parse(ctx context.Context, fileName string) ([]gogptscript.Node, error) {
102+
client := &gogptscript.Client{}
103+
client.Complete()
104+
105+
return client.Parse(ctx, fileName)
91106
}
92107
```
93108

94-
### ExecFile
109+
### ParseTool
95110

96-
Executes a GPT script file with optional input and arguments. The script is relative to the callers source directory.
111+
Parse contents that represents a GPTScript file into a data structure.
97112

98113
```go
99114
package main
@@ -104,18 +119,17 @@ import (
104119
gogptscript "github.com/gptscript-ai/go-gptscript"
105120
)
106121

107-
func execFile(ctx context.Context) (string, error) {
108-
opts := gogptscript.Opts{
109-
DisableCache: &[]bool{true}[0],
110-
}
111-
112-
return gogptscript.ExecFile(ctx, "./hello.gpt", "--input World", opts)
122+
func parseTool(ctx context.Context, contents string) ([]gogptscript.Node, error) {
123+
client := &gogptscript.Client{}
124+
client.Complete()
125+
126+
return client.ParseTool(ctx, contents)
113127
}
114128
```
115129

116-
### StreamExecTool
130+
### Fmt
117131

118-
Executes a gptscript with optional input and arguments, and returns the output streams.
132+
Parse convert a tool data structure into a GPTScript file.
119133

120134
```go
121135
package main
@@ -126,22 +140,17 @@ import (
126140
gogptscript "github.com/gptscript-ai/go-gptscript"
127141
)
128142

129-
func streamExecTool(ctx context.Context) error {
130-
t := gogptscript.Tool{
131-
Instructions: "who was the president of the united states in 1928?",
132-
}
133-
134-
stdOut, stdErr, wait := gogptscript.StreamExecTool(ctx, gogptscript.Opts{}, t)
135-
136-
// Read from stdOut and stdErr before call wait()
137-
138-
return wait()
143+
func parse(ctx context.Context, nodes []gogptscript.node) (string, error) {
144+
client := &gogptscript.Client{}
145+
client.Complete()
146+
147+
return client.Fmt(ctx, nodes)
139148
}
140149
```
141150

142-
### StreamExecToolWithEvents
151+
### Evaluate
143152

144-
Executes a gptscript with optional input and arguments, and returns the stdout, stderr, and gptscript events streams.
153+
Executes a tool with optional arguments.
145154

146155
```go
147156
package main
@@ -152,22 +161,26 @@ import (
152161
gogptscript "github.com/gptscript-ai/go-gptscript"
153162
)
154163

155-
func streamExecTool(ctx context.Context) error {
156-
t := gogptscript.Tool{
164+
func runTool(ctx context.Context) (string, error) {
165+
t := gogptscript.ToolDef{
157166
Instructions: "who was the president of the united states in 1928?",
158167
}
159168

160-
stdOut, stdErr, events, wait := gogptscript.StreamExecToolWithEvents(ctx, gogptscript.Opts{}, t)
169+
client := &gogptscript.Client{}
170+
client.Complete()
161171

162-
// Read from stdOut and stdErr before call wait()
172+
run, err := client.Evaluate(ctx, gogptscript.Opts{}, t)
173+
if err != nil {
174+
return "", err
175+
}
163176

164-
return wait()
177+
return run.Text()
165178
}
166179
```
167180

168-
### streamExecFile
181+
### Run
169182

170-
The script is relative to the callers source directory.
183+
Executes a GPT script file with optional input and arguments. The script is relative to the callers source directory.
171184

172185
```go
173186
package main
@@ -178,22 +191,27 @@ import (
178191
gogptscript "github.com/gptscript-ai/go-gptscript"
179192
)
180193

181-
func streamExecTool(ctx context.Context) error {
194+
func runFile(ctx context.Context) (string, error) {
182195
opts := gogptscript.Opts{
183196
DisableCache: &[]bool{true}[0],
197+
Input: "--input hello",
184198
}
185199

186-
stdOut, stdErr, wait := gogptscript.StreamExecFile(ctx, "./hello.gpt", "--input world", opts)
200+
client := &gogptscript.Client{}
201+
client.Complete()
187202

188-
// Read from stdOut and stdErr before call wait()
203+
run, err := client.Run(ctx, "./hello.gpt", opts)
204+
if err != nil {
205+
return "", err
206+
}
189207

190-
return wait()
208+
return run.Text()
191209
}
192210
```
193211

194-
### streamExecFileWithEvents
212+
### Streaming events
195213

196-
The script is relative to the callers source directory.
214+
In order to stream events, you must set `IncludeEvents` option to `true`. You if you don't set this and try to stream events, then it will succeed, but you will not get any events. More importantly, if you set `IncludeEvents` to `true`, you must stream the events for the script to complete.
197215

198216
```go
199217
package main
@@ -206,14 +224,26 @@ import (
206224

207225
func streamExecTool(ctx context.Context) error {
208226
opts := gogptscript.Opts{
209-
DisableCache: &[]bool{true}[0],
227+
DisableCache: &[]bool{true}[0],
228+
IncludeEvents: true,
229+
Input: "--input world",
210230
}
211231

212-
stdOut, stdErr, events, wait := gogptscript.StreamExecFileWithEvents(ctx, "./hello.gpt", "--input world", opts)
232+
client := &gogptscript.Client{}
233+
client.Complete()
213234

214-
// Read from stdOut and stdErr before call wait()
235+
run, err := client.Run(ctx, "./hello.gpt", opts)
236+
if err != nil {
237+
return err
238+
}
215239

216-
return wait()
240+
for event := range run.Events() {
241+
// Process event...
242+
}
243+
244+
// Wait for the output to ensure the script completes successfully.
245+
_, err = run.Text()
246+
return err
217247
}
218248
```
219249

@@ -235,12 +265,6 @@ func streamExecTool(ctx context.Context) error {
235265
| instructions | string | `""` | Instructions on how to use the tool. |
236266
| jsonResponse | boolean | `false` | Whether the tool returns a JSON response instead of plain text. You must include the word 'json' in the body of the prompt |
237267

238-
### FreeForm Parameters
239-
240-
| Argument | Type | Default | Description |
241-
|-----------|--------|---------|---------------------------------------|
242-
| content | string | `""` | This is a multi-line string that contains the entire contents of a valid gptscript file|
243-
244268
## License
245269

246270
Copyright (c) 2024, [Acorn Labs, Inc.](https://www.acorn.io)

‎client.go

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package gptscript
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"log/slog"
8+
"os"
9+
"path/filepath"
10+
"strings"
11+
)
12+
13+
const relativeToBinaryPath = "<me>"
14+
15+
type Client struct {
16+
GPTScriptURL string
17+
GPTScriptBin string
18+
}
19+
20+
func (c *Client) Complete() {
21+
if c.GPTScriptBin == "" {
22+
c.GPTScriptBin = getCommand()
23+
}
24+
}
25+
26+
func (c *Client) Evaluate(ctx context.Context, opts Opts, tools ...fmt.Stringer) (*Run, error) {
27+
return (&Run{
28+
url: c.GPTScriptURL,
29+
binPath: c.GPTScriptBin,
30+
requestPath: "evaluate",
31+
state: Creating,
32+
opts: opts,
33+
content: concatTools(tools),
34+
chatState: opts.ChatState,
35+
}).NextChat(ctx, opts.Input)
36+
}
37+
38+
func (c *Client) Run(ctx context.Context, toolPath string, opts Opts) (*Run, error) {
39+
return (&Run{
40+
url: c.GPTScriptURL,
41+
binPath: c.GPTScriptBin,
42+
requestPath: "run",
43+
state: Creating,
44+
opts: opts,
45+
toolPath: toolPath,
46+
chatState: opts.ChatState,
47+
}).NextChat(ctx, opts.Input)
48+
}
49+
50+
// Parse will parse the given file into an array of Nodes.
51+
func (c *Client) Parse(ctx context.Context, fileName string) ([]Node, error) {
52+
out, err := c.runBasicCommand(ctx, "parse", "parse", fileName, "")
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
var doc Document
58+
if err = json.Unmarshal([]byte(out), &doc); err != nil {
59+
return nil, err
60+
}
61+
62+
return doc.Nodes, nil
63+
}
64+
65+
// ParseTool will parse the given string into a tool.
66+
func (c *Client) ParseTool(ctx context.Context, toolDef string) ([]Node, error) {
67+
out, err := c.runBasicCommand(ctx, "parse", "parse", "", toolDef)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
var doc Document
73+
if err = json.Unmarshal([]byte(out), &doc); err != nil {
74+
return nil, err
75+
}
76+
77+
return doc.Nodes, nil
78+
}
79+
80+
// Fmt will format the given nodes into a string.
81+
func (c *Client) Fmt(ctx context.Context, nodes []Node) (string, error) {
82+
b, err := json.Marshal(Document{Nodes: nodes})
83+
if err != nil {
84+
return "", fmt.Errorf("failed to marshal nodes: %w", err)
85+
}
86+
87+
run := &runSubCommand{
88+
Run: Run{
89+
url: c.GPTScriptURL,
90+
binPath: c.GPTScriptBin,
91+
requestPath: "fmt",
92+
state: Creating,
93+
toolPath: "",
94+
content: string(b),
95+
},
96+
}
97+
98+
if run.url != "" {
99+
err = run.request(ctx, Document{Nodes: nodes})
100+
} else {
101+
err = run.exec(ctx, "fmt")
102+
}
103+
if err != nil {
104+
return "", err
105+
}
106+
107+
out, err := run.Text()
108+
if err != nil {
109+
return "", err
110+
}
111+
if run.err != nil {
112+
return run.ErrorOutput(), run.err
113+
}
114+
115+
return out, nil
116+
}
117+
118+
// Version will return the output of `gptscript --version`
119+
func (c *Client) Version(ctx context.Context) (string, error) {
120+
out, err := c.runBasicCommand(ctx, "--version", "version", "", "")
121+
if err != nil {
122+
return "", err
123+
}
124+
125+
return out, nil
126+
}
127+
128+
// ListTools will list all the available tools.
129+
func (c *Client) ListTools(ctx context.Context) (string, error) {
130+
out, err := c.runBasicCommand(ctx, "--list-tools", "list-tools", "", "")
131+
if err != nil {
132+
return "", err
133+
}
134+
135+
return out, nil
136+
}
137+
138+
// ListModels will list all the available models.
139+
func (c *Client) ListModels(ctx context.Context) ([]string, error) {
140+
out, err := c.runBasicCommand(ctx, "--list-models", "list-models", "", "")
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
return strings.Split(strings.TrimSpace(out), "\n"), nil
146+
}
147+
148+
func (c *Client) runBasicCommand(ctx context.Context, command, requestPath, toolPath, content string) (string, error) {
149+
run := &runSubCommand{
150+
Run: Run{
151+
url: c.GPTScriptURL,
152+
binPath: c.GPTScriptBin,
153+
requestPath: requestPath,
154+
state: Creating,
155+
toolPath: toolPath,
156+
content: content,
157+
},
158+
}
159+
160+
var err error
161+
if run.url != "" {
162+
var m any
163+
if content != "" || toolPath != "" {
164+
m = map[string]any{"input": content, "file": toolPath}
165+
}
166+
err = run.request(ctx, m)
167+
} else {
168+
err = run.exec(ctx, command)
169+
}
170+
if err != nil {
171+
return "", err
172+
}
173+
174+
out, err := run.Text()
175+
if err != nil {
176+
return "", err
177+
}
178+
if run.err != nil {
179+
return run.ErrorOutput(), run.err
180+
}
181+
182+
return out, nil
183+
}
184+
185+
func getCommand() string {
186+
if gptScriptBin := os.Getenv("GPTSCRIPT_BIN"); gptScriptBin != "" {
187+
if len(os.Args) == 0 {
188+
return gptScriptBin
189+
}
190+
return determineProperCommand(filepath.Dir(os.Args[0]), gptScriptBin)
191+
}
192+
193+
return "gptscript"
194+
}
195+
196+
// determineProperCommand is for testing purposes. Users should use getCommand instead.
197+
func determineProperCommand(dir, bin string) string {
198+
if !strings.HasPrefix(bin, relativeToBinaryPath) {
199+
return bin
200+
}
201+
202+
bin = filepath.Join(dir, strings.TrimPrefix(bin, relativeToBinaryPath))
203+
if !filepath.IsAbs(bin) {
204+
bin = "." + string(os.PathSeparator) + bin
205+
}
206+
207+
slog.Debug("Using gptscript binary: " + bin)
208+
return bin
209+
}

‎client_test.go

Lines changed: 629 additions & 0 deletions
Large diffs are not rendered by default.

‎event.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package gptscript
2+
3+
import "time"
4+
5+
type Event struct {
6+
RunID string `json:"runID,omitempty"`
7+
Time time.Time `json:"time,omitempty"`
8+
CallContext *CallContext `json:"callContext,omitempty"`
9+
ToolSubCalls map[string]Call `json:"toolSubCalls,omitempty"`
10+
ToolResults int `json:"toolResults,omitempty"`
11+
Type EventType `json:"type,omitempty"`
12+
ChatCompletionID string `json:"chatCompletionId,omitempty"`
13+
ChatRequest any `json:"chatRequest,omitempty"`
14+
ChatResponse any `json:"chatResponse,omitempty"`
15+
ChatResponseCached bool `json:"chatResponseCached,omitempty"`
16+
Content string `json:"content,omitempty"`
17+
Program *Program `json:"program,omitempty"`
18+
Input string `json:"input,omitempty"`
19+
Output string `json:"output,omitempty"`
20+
Err string `json:"err,omitempty"`
21+
}
22+
23+
type Program struct {
24+
Name string `json:"name,omitempty"`
25+
EntryToolID string `json:"entryToolId,omitempty"`
26+
ToolSet ToolSet `json:"toolSet,omitempty"`
27+
}
28+
29+
type ToolSet map[string]Tool
30+
31+
type Call struct {
32+
ToolID string `json:"toolID,omitempty"`
33+
Input string `json:"input,omitempty"`
34+
}
35+
36+
type CallContext struct {
37+
ID string `json:"id"`
38+
Tool Tool `json:"tool"`
39+
InputContext []InputContext `json:"inputContext"`
40+
ToolCategory ToolCategory `json:"toolCategory,omitempty"`
41+
ToolName string `json:"toolName,omitempty"`
42+
ParentID string `json:"parentID,omitempty"`
43+
}
44+
45+
type InputContext struct {
46+
ToolID string `json:"toolID,omitempty"`
47+
Content string `json:"content,omitempty"`
48+
}
49+
50+
type ToolCategory string
51+
52+
const (
53+
CredentialToolCategory ToolCategory = "credential"
54+
ContextToolCategory ToolCategory = "context"
55+
NoCategory ToolCategory = ""
56+
)
57+
58+
type EventType string
59+
60+
const (
61+
EventTypeCallStart EventType = "callStart"
62+
EventTypeCallContinue EventType = "callContinue"
63+
EventTypeCallSubCalls EventType = "callSubCalls"
64+
EventTypeCallProgress EventType = "callProgress"
65+
EventTypeChat EventType = "callChat"
66+
EventTypeCallFinish EventType = "callFinish"
67+
)

‎exec.go

Lines changed: 0 additions & 361 deletions
This file was deleted.

‎exec_test.go

Lines changed: 0 additions & 576 deletions
This file was deleted.

‎exec_unix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ import (
1010

1111
func appendExtraFiles(cmd *exec.Cmd, extraFiles ...*os.File) {
1212
cmd.ExtraFiles = append(cmd.ExtraFiles, extraFiles...)
13-
cmd.Args = append(cmd.Args[:1], append([]string{"--events-stream-to", fmt.Sprintf("fd://%d", len(cmd.ExtraFiles)+2)}, cmd.Args[1:]...)...)
13+
cmd.Args = append(cmd.Args[:1], append([]string{fmt.Sprintf("--events-stream-to=fd://%d", len(cmd.ExtraFiles)+2)}, cmd.Args[1:]...)...)
1414
}

‎opts.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package gptscript
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Opts represents options for the gptscript tool or file.
8+
type Opts struct {
9+
Input string `json:"input"`
10+
DisableCache bool `json:"disableCache"`
11+
CacheDir string `json:"cacheDir"`
12+
Quiet bool `json:"quiet"`
13+
Chdir string `json:"chdir"`
14+
SubTool string `json:"subTool"`
15+
Workspace string `json:"workspace"`
16+
ChatState string `json:"chatState"`
17+
IncludeEvents bool `json:"includeEvents"`
18+
}
19+
20+
func (o Opts) toArgs() []string {
21+
var args []string
22+
if o.DisableCache {
23+
args = append(args, "--disable-cache")
24+
}
25+
if o.CacheDir != "" {
26+
args = append(args, "--cache-dir="+o.CacheDir)
27+
}
28+
if o.Chdir != "" {
29+
args = append(args, "--chdir="+o.Chdir)
30+
}
31+
if o.SubTool != "" {
32+
args = append(args, "--sub-tool="+o.SubTool)
33+
}
34+
if o.Workspace != "" {
35+
args = append(args, "--workspace="+o.Workspace)
36+
}
37+
return append(args, "--quiet="+fmt.Sprint(o.Quiet))
38+
}

‎run.go

Lines changed: 545 additions & 0 deletions
Large diffs are not rendered by default.

‎test/catcher.gpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Who wrote Catcher in the Rye?

‎test/chat.gpt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
chat: true
2+
tools: sys.chat.finish
3+
4+
You are a chat bot. Don't finish the conversation until I say 'bye'.

‎tool.go

Lines changed: 45 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,31 @@ import (
77
"github.com/getkin/kin-openapi/openapi3"
88
)
99

10-
// SimpleTool struct represents a tool with various configurations.
11-
type SimpleTool struct {
12-
Name string
13-
Description string
14-
Tools []string
15-
MaxTokens *int // Using a pointer to represent optional int
16-
Model string
17-
Cache bool
18-
Temperature *float64 // Using a pointer to represent optional float64
19-
Args map[string]string
20-
InternalPrompt bool
21-
Instructions string
22-
JSONResponse bool
10+
// ToolDef struct represents a tool with various configurations.
11+
type ToolDef struct {
12+
Name string `json:"name,omitempty"`
13+
Description string `json:"description,omitempty"`
14+
MaxTokens int `json:"maxTokens,omitempty"`
15+
ModelName string `json:"modelName,omitempty"`
16+
ModelProvider bool `json:"modelProvider,omitempty"`
17+
JSONResponse bool `json:"jsonResponse,omitempty"`
18+
Chat bool `json:"chat,omitempty"`
19+
Temperature *float32 `json:"temperature,omitempty"`
20+
Cache *bool `json:"cache,omitempty"`
21+
InternalPrompt *bool `json:"internalPrompt"`
22+
Args map[string]string `json:"args,omitempty"`
23+
Tools []string `json:"tools,omitempty"`
24+
GlobalTools []string `json:"globalTools,omitempty"`
25+
GlobalModelName string `json:"globalModelName,omitempty"`
26+
Context []string `json:"context,omitempty"`
27+
ExportContext []string `json:"exportContext,omitempty"`
28+
Export []string `json:"export,omitempty"`
29+
Credentials []string `json:"credentials,omitempty"`
30+
Instructions string `json:"instructions,omitempty"`
2331
}
2432

25-
// NewSimpleTool is a constructor for SimpleTool struct.
26-
func NewSimpleTool(name, description string, tools []string, maxTokens *int, model string, cache bool, temperature *float64, args map[string]string, internalPrompt bool, instructions string, jsonResponse bool) *SimpleTool {
27-
return &SimpleTool{
28-
Name: name,
29-
Description: description,
30-
Tools: tools,
31-
MaxTokens: maxTokens,
32-
Model: model,
33-
Cache: cache,
34-
Temperature: temperature,
35-
Args: args,
36-
InternalPrompt: internalPrompt,
37-
Instructions: instructions,
38-
JSONResponse: jsonResponse,
39-
}
40-
}
41-
42-
// String method returns the string representation of SimpleTool.
43-
func (t *SimpleTool) String() string {
33+
// String method returns the string representation of ToolDef.
34+
func (t *ToolDef) String() string {
4435
var sb strings.Builder
4536

4637
if t.Name != "" {
@@ -52,13 +43,13 @@ func (t *SimpleTool) String() string {
5243
if len(t.Tools) > 0 {
5344
sb.WriteString(fmt.Sprintf("Tools: %s\n", strings.Join(t.Tools, ", ")))
5445
}
55-
if t.MaxTokens != nil {
56-
sb.WriteString(fmt.Sprintf("Max tokens: %d\n", *t.MaxTokens))
46+
if t.MaxTokens != 0 {
47+
sb.WriteString(fmt.Sprintf("Max tokens: %d\n", t.MaxTokens))
5748
}
58-
if t.Model != "" {
59-
sb.WriteString(fmt.Sprintf("Model: %s\n", t.Model))
49+
if t.ModelName != "" {
50+
sb.WriteString(fmt.Sprintf("Model: %s\n", t.ModelName))
6051
}
61-
if !t.Cache {
52+
if t.Cache != nil && !*t.Cache {
6253
sb.WriteString("Cache: false\n")
6354
}
6455
if t.Temperature != nil {
@@ -72,7 +63,10 @@ func (t *SimpleTool) String() string {
7263
sb.WriteString(fmt.Sprintf("Args: %s: %s\n", arg, desc))
7364
}
7465
}
75-
if t.InternalPrompt {
66+
if t.Chat {
67+
sb.WriteString("Chat: true\n")
68+
}
69+
if t.InternalPrompt != nil && *t.InternalPrompt {
7670
sb.WriteString("Internal prompt: true\n")
7771
}
7872
if t.Instructions != "" {
@@ -82,24 +76,9 @@ func (t *SimpleTool) String() string {
8276
return sb.String()
8377
}
8478

85-
// FreeForm struct represents free-form content.
86-
type FreeForm struct {
87-
Content string
88-
}
89-
90-
// NewFreeForm is a constructor for FreeForm struct.
91-
func NewFreeForm(content string) *FreeForm {
92-
return &FreeForm{Content: content}
93-
}
79+
type ToolDefs []ToolDef
9480

95-
// String method returns the string representation of FreeForm.
96-
func (f *FreeForm) String() string {
97-
return f.Content
98-
}
99-
100-
type Tools []SimpleTool
101-
102-
func (t Tools) String() string {
81+
func (t ToolDefs) String() string {
10382
resp := make([]string, 0, len(t))
10483
for _, tool := range t {
10584
resp = append(resp, tool.String())
@@ -125,10 +104,9 @@ type ToolNode struct {
125104
}
126105

127106
type Tool struct {
128-
Parameters `json:",inline"`
129-
Instructions string `json:"instructions,omitempty"`
130-
107+
ToolDef `json:",inline"`
131108
ID string `json:"id,omitempty"`
109+
Arguments *openapi3.Schema `json:"arguments,omitempty"`
132110
ToolMapping map[string]string `json:"toolMapping,omitempty"`
133111
LocalTools map[string]string `json:"localTools,omitempty"`
134112
Source ToolSource `json:"source,omitempty"`
@@ -149,24 +127,13 @@ type Repo struct {
149127
Revision string
150128
}
151129

152-
type Parameters struct {
153-
Name string `json:"name,omitempty"`
154-
Description string `json:"description,omitempty"`
155-
MaxTokens int `json:"maxTokens,omitempty"`
156-
ModelName string `json:"modelName,omitempty"`
157-
ModelProvider bool `json:"modelProvider,omitempty"`
158-
JSONResponse bool `json:"jsonResponse,omitempty"`
159-
Chat bool `json:"chat,omitempty"`
160-
Temperature *float32 `json:"temperature,omitempty"`
161-
Cache *bool `json:"cache,omitempty"`
162-
InternalPrompt *bool `json:"internalPrompt"`
163-
Arguments *openapi3.Schema `json:"arguments,omitempty"`
164-
Tools []string `json:"tools,omitempty"`
165-
GlobalTools []string `json:"globalTools,omitempty"`
166-
GlobalModelName string `json:"globalModelName,omitempty"`
167-
Context []string `json:"context,omitempty"`
168-
ExportContext []string `json:"exportContext,omitempty"`
169-
Export []string `json:"export,omitempty"`
170-
Credentials []string `json:"credentials,omitempty"`
171-
Blocking bool `json:"-"`
130+
func concatTools(tools []fmt.Stringer) string {
131+
var sb strings.Builder
132+
for i, tool := range tools {
133+
sb.WriteString(tool.String())
134+
if i < len(tools)-1 {
135+
sb.WriteString("\n---\n")
136+
}
137+
}
138+
return sb.String()
172139
}

0 commit comments

Comments
 (0)
Please sign in to comment.