mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-02-18 11:02:26 -05:00
This PR adds preliminary parsing of parameters. Currently it only supports 4 types: string, int, float32, and bool. Almost certainly we will need to introduce more complicated parsing configuration (to handle objects and arrays), but my initial attempts got quickly complicated, so I simplified in the short term. This also makes 2 breaking changes to config.yaml: - changes "parameters" to be a list over object -- this is because parameter ordering is important, and needs to be preserved - removed the "required" field from parameter objects -- we need to determine how to handle optional parameters in SQL queries
113 lines
2.7 KiB
Go
113 lines
2.7 KiB
Go
// Copyright 2024 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package tools
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Config interface {
|
|
toolKind() string
|
|
Initialize(map[string]sources.Source) (Tool, error)
|
|
}
|
|
|
|
// SourceConfigs is a type used to allow unmarshal of the data source config map
|
|
type Configs map[string]Config
|
|
|
|
// validate interface
|
|
var _ yaml.Unmarshaler = &Configs{}
|
|
|
|
func (c *Configs) UnmarshalYAML(node *yaml.Node) error {
|
|
*c = make(Configs)
|
|
// Parse the 'kind' fields for each source
|
|
var raw map[string]yaml.Node
|
|
if err := node.Decode(&raw); err != nil {
|
|
return err
|
|
}
|
|
|
|
for name, n := range raw {
|
|
var k struct {
|
|
Kind string `yaml:"kind"`
|
|
}
|
|
err := n.Decode(&k)
|
|
if err != nil {
|
|
return fmt.Errorf("missing 'kind' field for %q", k)
|
|
}
|
|
switch k.Kind {
|
|
case CloudSQLPgSQLGenericKind:
|
|
actual := CloudSQLPgGenericConfig{Name: name}
|
|
if err := n.Decode(&actual); err != nil {
|
|
return fmt.Errorf("unable to parse as %q: %w", k.Kind, err)
|
|
}
|
|
(*c)[name] = actual
|
|
default:
|
|
return fmt.Errorf("%q is not a valid kind of tool", k.Kind)
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Tool interface {
|
|
Invoke([]any) (string, error)
|
|
ParseParams(data map[string]any) ([]any, error)
|
|
}
|
|
|
|
type Parameter struct {
|
|
Name string `yaml:"name"`
|
|
Type string `yaml:"type"`
|
|
Description string `yaml:"description"`
|
|
}
|
|
|
|
// ParseTypeError is a customer error for incorrectly typed Parameters.
|
|
type ParseTypeError struct {
|
|
Name string
|
|
Type string
|
|
Value any
|
|
}
|
|
|
|
func (e ParseTypeError) Error() string {
|
|
return fmt.Sprintf("Error parsing parameter %q: %q not type %q", e.Name, e.Value, e.Type)
|
|
}
|
|
|
|
// ParseParams is a helper function for parsing Parameters from an arbitratyJSON object.
|
|
func parseParams(ps []Parameter, data map[string]any) ([]any, error) {
|
|
params := []any{}
|
|
for _, p := range ps {
|
|
v, ok := data[p.Name]
|
|
if !ok {
|
|
return nil, fmt.Errorf("Parameter %q is required!", p.Name)
|
|
}
|
|
switch p.Type {
|
|
case "string":
|
|
v, ok = v.(string)
|
|
case "integer":
|
|
v, ok = v.(int)
|
|
case "float":
|
|
v, ok = v.(float32)
|
|
case "boolean":
|
|
v, ok = v.(bool)
|
|
}
|
|
if !ok {
|
|
return nil, &ParseTypeError{p.Name, p.Type, v}
|
|
}
|
|
params = append(params, v)
|
|
}
|
|
return params, nil
|
|
}
|