| 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) |
| } |