@@ -20,10 +20,10 @@ import (
20
20
"github.com/gptscript-ai/gptscript/pkg/assemble"
21
21
"github.com/gptscript-ai/gptscript/pkg/builtin"
22
22
"github.com/gptscript-ai/gptscript/pkg/cache"
23
+ "github.com/gptscript-ai/gptscript/pkg/hash"
23
24
"github.com/gptscript-ai/gptscript/pkg/parser"
24
25
"github.com/gptscript-ai/gptscript/pkg/system"
25
26
"github.com/gptscript-ai/gptscript/pkg/types"
26
- "gopkg.in/yaml.v3"
27
27
)
28
28
29
29
const CacheTimeout = time .Hour
@@ -120,24 +120,50 @@ func loadProgram(data []byte, into *types.Program, targetToolName string) (types
120
120
return tool , nil
121
121
}
122
122
123
+ func loadOpenAPI (prg * types.Program , data []byte ) * openapi3.T {
124
+ var (
125
+ openAPICacheKey = hash .Digest (data )
126
+ openAPIDocument , ok = prg .OpenAPICache [openAPICacheKey ].(* openapi3.T )
127
+ err error
128
+ )
129
+
130
+ if ok {
131
+ return openAPIDocument
132
+ }
133
+
134
+ if prg .OpenAPICache == nil {
135
+ prg .OpenAPICache = map [string ]any {}
136
+ }
137
+
138
+ openAPIDocument , err = openapi3 .NewLoader ().LoadFromData (data )
139
+ if err != nil || openAPIDocument .Paths .Len () == 0 {
140
+ openAPIDocument = nil
141
+ }
142
+
143
+ prg .OpenAPICache [openAPICacheKey ] = openAPIDocument
144
+ return openAPIDocument
145
+ }
146
+
123
147
func readTool (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , targetToolName string ) (types.Tool , error ) {
124
148
data := base .Content
125
149
126
150
if bytes .HasPrefix (data , assemble .Header ) {
127
151
return loadProgram (data , prg , targetToolName )
128
152
}
129
153
130
- var tools []types.Tool
131
- if isOpenAPI (data ) {
132
- if t , err := openapi3 .NewLoader ().LoadFromData (data ); err == nil {
133
- if base .Remote {
134
- tools , err = getOpenAPITools (t , base .Location )
135
- } else {
136
- tools , err = getOpenAPITools (t , "" )
137
- }
138
- if err != nil {
139
- return types.Tool {}, fmt .Errorf ("error parsing OpenAPI definition: %w" , err )
140
- }
154
+ var (
155
+ tools []types.Tool
156
+ )
157
+
158
+ if openAPIDocument := loadOpenAPI (prg , data ); openAPIDocument != nil {
159
+ var err error
160
+ if base .Remote {
161
+ tools , err = getOpenAPITools (openAPIDocument , base .Location )
162
+ } else {
163
+ tools , err = getOpenAPITools (openAPIDocument , "" )
164
+ }
165
+ if err != nil {
166
+ return types.Tool {}, fmt .Errorf ("error parsing OpenAPI definition: %w" , err )
141
167
}
142
168
}
143
169
@@ -263,6 +289,12 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so
263
289
}
264
290
265
291
func ProgramFromSource (ctx context.Context , content , subToolName string , opts ... Options ) (types.Program , error ) {
292
+ if log .IsDebug () {
293
+ start := time .Now ()
294
+ defer func () {
295
+ log .Debugf ("loaded program from source took %v" , time .Since (start ))
296
+ }()
297
+ }
266
298
opt := complete (opts ... )
267
299
268
300
prg := types.Program {
@@ -292,6 +324,13 @@ func complete(opts ...Options) (result Options) {
292
324
}
293
325
294
326
func Program (ctx context.Context , name , subToolName string , opts ... Options ) (types.Program , error ) {
327
+ if log .IsDebug () {
328
+ start := time .Now ()
329
+ defer func () {
330
+ log .Debugf ("loaded program %s source took %v" , name , time .Since (start ))
331
+ }()
332
+ }
333
+
295
334
opt := complete (opts ... )
296
335
297
336
if subToolName == "" {
@@ -363,16 +402,3 @@ func SplitToolRef(targetToolName string) (toolName, subTool string) {
363
402
return strings .Join (fields [idx + 1 :], " " ),
364
403
strings .Join (fields [:idx ], " " )
365
404
}
366
-
367
- func isOpenAPI (data []byte ) bool {
368
- var fragment struct {
369
- Paths map [string ]any `json:"paths,omitempty"`
370
- }
371
-
372
- if err := json .Unmarshal (data , & fragment ); err != nil {
373
- if err := yaml .Unmarshal (data , & fragment ); err != nil {
374
- return false
375
- }
376
- }
377
- return len (fragment .Paths ) > 0
378
- }
0 commit comments