@@ -181,11 +181,15 @@ func loadOpenAPI(prg *types.Program, data []byte) *openapi3.T {
181
181
return openAPIDocument
182
182
}
183
183
184
- func readTool (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , targetToolName string ) (types.Tool , error ) {
184
+ func readTool (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , targetToolName string ) ([] types.Tool , error ) {
185
185
data := base .Content
186
186
187
187
if bytes .HasPrefix (data , assemble .Header ) {
188
- return loadProgram (data , prg , targetToolName )
188
+ tool , err := loadProgram (data , prg , targetToolName )
189
+ if err != nil {
190
+ return nil , err
191
+ }
192
+ return []types.Tool {tool }, nil
189
193
}
190
194
191
195
var (
@@ -200,7 +204,7 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base
200
204
tools , err = getOpenAPITools (openAPIDocument , "" )
201
205
}
202
206
if err != nil {
203
- return types. Tool {} , fmt .Errorf ("error parsing OpenAPI definition: %w" , err )
207
+ return nil , fmt .Errorf ("error parsing OpenAPI definition: %w" , err )
204
208
}
205
209
}
206
210
@@ -222,17 +226,17 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base
222
226
AssignGlobals : true ,
223
227
})
224
228
if err != nil {
225
- return types. Tool {} , err
229
+ return nil , err
226
230
}
227
231
}
228
232
229
233
if len (tools ) == 0 {
230
- return types. Tool {} , fmt .Errorf ("no tools found in %s" , base )
234
+ return nil , fmt .Errorf ("no tools found in %s" , base )
231
235
}
232
236
233
237
var (
234
- localTools = types.ToolSet {}
235
- mainTool types.Tool
238
+ localTools = types.ToolSet {}
239
+ targetTools [] types.Tool
236
240
)
237
241
238
242
for i , tool := range tools {
@@ -243,44 +247,65 @@ func readTool(ctx context.Context, cache *cache.Client, prg *types.Program, base
243
247
// Probably a better way to come up with an ID
244
248
tool .ID = tool .Source .Location + ":" + tool .Name
245
249
246
- if i == 0 {
247
- mainTool = tool
250
+ if i == 0 && targetToolName == "" {
251
+ targetTools = append ( targetTools , tool )
248
252
}
249
253
250
254
if i != 0 && tool .Parameters .Name == "" {
251
- return types. Tool {} , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have no name" ))
255
+ return nil , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have no name" ))
252
256
}
253
257
254
258
if i != 0 && tool .Parameters .GlobalModelName != "" {
255
- return types. Tool {} , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have global model name" ))
259
+ return nil , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have global model name" ))
256
260
}
257
261
258
262
if i != 0 && len (tool .Parameters .GlobalTools ) > 0 {
259
- return types. Tool {} , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have global tools" ))
263
+ return nil , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , fmt .Errorf ("only the first tool in a file can have global tools" ))
260
264
}
261
265
262
- if targetToolName != "" && strings .EqualFold (tool .Parameters .Name , targetToolName ) {
263
- mainTool = tool
266
+ if targetToolName != "" && tool .Parameters .Name != "" {
267
+ if strings .EqualFold (tool .Parameters .Name , targetToolName ) {
268
+ targetTools = append (targetTools , tool )
269
+ } else if strings .Contains (targetToolName , "*" ) {
270
+ match , err := filepath .Match (strings .ToLower (targetToolName ), strings .ToLower (tool .Parameters .Name ))
271
+ if err != nil {
272
+ return nil , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo , err )
273
+ }
274
+ if match {
275
+ targetTools = append (targetTools , tool )
276
+ }
277
+ }
264
278
}
265
279
266
280
if existing , ok := localTools [strings .ToLower (tool .Parameters .Name )]; ok {
267
- return types. Tool {} , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo ,
281
+ return nil , parser .NewErrLine (tool .Source .Location , tool .Source .LineNo ,
268
282
fmt .Errorf ("duplicate tool name [%s] in %s found at lines %d and %d" , tool .Parameters .Name , tool .Source .Location ,
269
283
tool .Source .LineNo , existing .Source .LineNo ))
270
284
}
271
285
272
286
localTools [strings .ToLower (tool .Parameters .Name )] = tool
273
287
}
274
288
275
- return link (ctx , cache , prg , base , mainTool , localTools )
289
+ return linkAll (ctx , cache , prg , base , targetTools , localTools )
290
+ }
291
+
292
+ func linkAll (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , tools []types.Tool , localTools types.ToolSet ) (result []types.Tool , _ error ) {
293
+ for _ , tool := range tools {
294
+ tool , err := link (ctx , cache , prg , base , tool , localTools )
295
+ if err != nil {
296
+ return nil , err
297
+ }
298
+ result = append (result , tool )
299
+ }
300
+ return
276
301
}
277
302
278
303
func link (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , tool types.Tool , localTools types.ToolSet ) (types.Tool , error ) {
279
304
if existing , ok := prg .ToolSet [tool .ID ]; ok {
280
305
return existing , nil
281
306
}
282
307
283
- tool .ToolMapping = map [string ]string {}
308
+ tool .ToolMapping = map [string ][]types. ToolReference {}
284
309
tool .LocalTools = map [string ]string {}
285
310
toolNames := map [string ]struct {}{}
286
311
@@ -310,16 +335,17 @@ func link(ctx context.Context, cache *cache.Client, prg *types.Program, base *so
310
335
}
311
336
}
312
337
313
- tool .ToolMapping [ targetToolName ] = linkedTool . ID
338
+ tool .AddToolMapping ( targetToolName , linkedTool )
314
339
toolNames [targetToolName ] = struct {}{}
315
340
} else {
316
341
toolName , subTool := types .SplitToolRef (targetToolName )
317
- resolvedTool , err := resolve (ctx , cache , prg , base , toolName , subTool )
342
+ resolvedTools , err := resolve (ctx , cache , prg , base , toolName , subTool )
318
343
if err != nil {
319
344
return types.Tool {}, fmt .Errorf ("failed resolving %s from %s: %w" , targetToolName , base , err )
320
345
}
321
-
322
- tool .ToolMapping [targetToolName ] = resolvedTool .ID
346
+ for _ , resolvedTool := range resolvedTools {
347
+ tool .AddToolMapping (targetToolName , resolvedTool )
348
+ }
323
349
}
324
350
}
325
351
@@ -345,14 +371,14 @@ func ProgramFromSource(ctx context.Context, content, subToolName string, opts ..
345
371
prg := types.Program {
346
372
ToolSet : types.ToolSet {},
347
373
}
348
- tool , err := readTool (ctx , opt .Cache , & prg , & source {
374
+ tools , err := readTool (ctx , opt .Cache , & prg , & source {
349
375
Content : []byte (content ),
350
376
Location : "inline" ,
351
377
}, subToolName )
352
378
if err != nil {
353
379
return types.Program {}, err
354
380
}
355
- prg .EntryToolID = tool .ID
381
+ prg .EntryToolID = tools [ 0 ] .ID
356
382
return prg , nil
357
383
}
358
384
@@ -385,26 +411,26 @@ func Program(ctx context.Context, name, subToolName string, opts ...Options) (ty
385
411
Name : name ,
386
412
ToolSet : types.ToolSet {},
387
413
}
388
- tool , err := resolve (ctx , opt .Cache , & prg , & source {}, name , subToolName )
414
+ tools , err := resolve (ctx , opt .Cache , & prg , & source {}, name , subToolName )
389
415
if err != nil {
390
416
return types.Program {}, err
391
417
}
392
- prg .EntryToolID = tool .ID
418
+ prg .EntryToolID = tools [ 0 ] .ID
393
419
return prg , nil
394
420
}
395
421
396
- func resolve (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , name , subTool string ) (types.Tool , error ) {
422
+ func resolve (ctx context.Context , cache * cache.Client , prg * types.Program , base * source , name , subTool string ) ([] types.Tool , error ) {
397
423
if subTool == "" {
398
424
t , ok := builtin .Builtin (name )
399
425
if ok {
400
426
prg .ToolSet [t .ID ] = t
401
- return t , nil
427
+ return []types. Tool { t } , nil
402
428
}
403
429
}
404
430
405
431
s , err := input (ctx , cache , base , name )
406
432
if err != nil {
407
- return types. Tool {} , err
433
+ return nil , err
408
434
}
409
435
410
436
return readTool (ctx , cache , prg , s , subTool )
0 commit comments