blob: 9ad2addad47e94c0bc4dc175479c3f9cdb4203dd [file] [log] [blame]
package tools
import (
"encoding/json"
"fmt"
"strings"
"github.com/invopop/jsonschema"
)
type FuncTool[I any, O any] struct {
name string
desc string
schema *jsonschema.Schema
fn func(args I) (O, error)
}
func NewFuncTool[I any, O any](name string, fn func(args I) (O, error), desc string) *FuncTool[I, O] {
return &FuncTool[I, O]{
name,
fmt.Sprintf("%s\nResult schema: %s", desc, GenerateSchema[O]()),
GenerateSchema[I](),
fn,
}
}
func (ft *FuncTool[I, O]) Name() string {
return ft.name
}
func (ft *FuncTool[I, O]) Description() string {
return ft.desc
}
func (ft *FuncTool[I, O]) InputSchema() *jsonschema.Schema {
return ft.schema
}
func (ft *FuncTool[I, O]) Call(inp string) (string, error) {
var args I
if err := json.NewDecoder(strings.NewReader(inp)).Decode(&args); err != nil {
return "", err
}
out, err := ft.fn(args)
if err != nil {
return "", err
}
var resp strings.Builder
if err := json.NewEncoder(&resp).Encode(out); err != nil {
return "", err
}
ret := resp.String()
fmt.Printf("$$$ %s\n", ret)
return ret, nil
}
func GenerateSchema[T any]() *jsonschema.Schema {
reflector := jsonschema.Reflector{
AllowAdditionalProperties: false,
RequiredFromJSONSchemaTags: true,
DoNotReference: true,
}
var v T
return reflector.Reflect(v)
}