7
7
"strings"
8
8
9
9
"github.com/getkin/kin-openapi/openapi3"
10
+ "github.com/gptscript-ai/gptscript/pkg/system"
10
11
"golang.org/x/exp/maps"
11
12
)
12
13
@@ -16,6 +17,14 @@ const (
16
17
CommandPrefix = "#!"
17
18
)
18
19
20
+ type ErrToolNotFound struct {
21
+ ToolName string
22
+ }
23
+
24
+ func (e * ErrToolNotFound ) Error () string {
25
+ return fmt .Sprintf ("tool not found: %s" , e .ToolName )
26
+ }
27
+
19
28
type ToolSet map [string ]Tool
20
29
21
30
type Program struct {
@@ -24,6 +33,17 @@ type Program struct {
24
33
ToolSet ToolSet `json:"toolSet,omitempty"`
25
34
}
26
35
36
+ func (p Program ) GetCompletionTools () (result []CompletionTool , err error ) {
37
+ return Tool {
38
+ Parameters : Parameters {
39
+ Tools : []string {"main" },
40
+ },
41
+ ToolMapping : map [string ]string {
42
+ "main" : p .EntryToolID ,
43
+ },
44
+ }.GetCompletionTools (p )
45
+ }
46
+
27
47
func (p Program ) TopLevelTools () (result []Tool ) {
28
48
for _ , tool := range p .ToolSet [p .EntryToolID ].LocalTools {
29
49
result = append (result , p .ToolSet [tool ])
@@ -124,6 +144,75 @@ func (t Tool) String() string {
124
144
return buf .String ()
125
145
}
126
146
147
+ func (t Tool ) GetCompletionTools (prg Program ) (result []CompletionTool , err error ) {
148
+ toolNames := map [string ]struct {}{}
149
+
150
+ for _ , subToolName := range t .Parameters .Tools {
151
+ result , err = appendTool (result , prg , t , subToolName , toolNames )
152
+ if err != nil {
153
+ return nil , err
154
+ }
155
+ }
156
+
157
+ return result , nil
158
+ }
159
+
160
+ func getTool (prg Program , parent Tool , name string ) (Tool , error ) {
161
+ toolID , ok := parent .ToolMapping [name ]
162
+ if ! ok {
163
+ return Tool {}, & ErrToolNotFound {
164
+ ToolName : name ,
165
+ }
166
+ }
167
+ tool , ok := prg .ToolSet [toolID ]
168
+ if ! ok {
169
+ return Tool {}, & ErrToolNotFound {
170
+ ToolName : name ,
171
+ }
172
+ }
173
+ return tool , nil
174
+ }
175
+
176
+ func appendTool (completionTools []CompletionTool , prg Program , parentTool Tool , subToolName string , toolNames map [string ]struct {}) ([]CompletionTool , error ) {
177
+ subTool , err := getTool (prg , parentTool , subToolName )
178
+ if err != nil {
179
+ return nil , err
180
+ }
181
+
182
+ args := subTool .Parameters .Arguments
183
+ if args == nil && ! subTool .IsCommand () {
184
+ args = & system .DefaultToolSchema
185
+ }
186
+
187
+ for _ , existingTool := range completionTools {
188
+ if existingTool .Function .ToolID == subTool .ID {
189
+ return completionTools , nil
190
+ }
191
+ }
192
+
193
+ if subTool .Instructions == "" {
194
+ log .Debugf ("Skipping zero instruction tool %s (%s)" , subToolName , subTool .ID )
195
+ } else {
196
+ completionTools = append (completionTools , CompletionTool {
197
+ Function : CompletionFunctionDefinition {
198
+ ToolID : subTool .ID ,
199
+ Name : PickToolName (subToolName , toolNames ),
200
+ Description : subTool .Parameters .Description ,
201
+ Parameters : args ,
202
+ },
203
+ })
204
+ }
205
+
206
+ for _ , export := range subTool .Export {
207
+ completionTools , err = appendTool (completionTools , prg , subTool , export , toolNames )
208
+ if err != nil {
209
+ return nil , err
210
+ }
211
+ }
212
+
213
+ return completionTools , nil
214
+ }
215
+
127
216
type Repo struct {
128
217
// VCS The VCS type, such as "git"
129
218
VCS string
0 commit comments