44 "encoding/json"
55 "fmt"
66 "iter"
7+ "strings"
78
89 "github.com/google/uuid"
910 "google.golang.org/genai"
@@ -17,6 +18,51 @@ type GoogleStreamIterator interface {
1718
1819func ToolsToGoogle (tools []Tool ) ([]* genai.Tool , error ) {
1920 googleTools := []* genai.Tool {}
21+
22+ var propertyToSchema func (property map [string ]any ) (* genai.Schema , error )
23+ propertyToSchema = func (property map [string ]any ) (* genai.Schema , error ) {
24+ schema := & genai.Schema {}
25+
26+ typeRaw , ok := property ["type" ]
27+ if ok {
28+ typ , ok := typeRaw .(string )
29+ if ! ok {
30+ return nil , fmt .Errorf ("type is not a string: %T" , typeRaw )
31+ }
32+ schema .Type = genai .Type (strings .ToUpper (typ ))
33+ }
34+
35+ descriptionRaw , ok := property ["description" ]
36+ if ok {
37+ description , ok := descriptionRaw .(string )
38+ if ! ok {
39+ return nil , fmt .Errorf ("description is not a string: %T" , descriptionRaw )
40+ }
41+ schema .Description = description
42+ }
43+
44+ propertiesRaw , ok := property ["properties" ]
45+ if ok {
46+ properties , ok := propertiesRaw .(map [string ]any )
47+ if ! ok {
48+ return nil , fmt .Errorf ("properties is not a map[string]any: %T" , propertiesRaw )
49+ }
50+ for key , value := range properties {
51+ propMap , ok := value .(map [string ]any )
52+ if ! ok {
53+ return nil , fmt .Errorf ("property %q is not a map[string]any: %T" , key , value )
54+ }
55+ subschema , err := propertyToSchema (propMap )
56+ if err != nil {
57+ return nil , fmt .Errorf ("property %q has non-object properties: %w" , key , err )
58+ }
59+ schema .Properties [key ] = subschema
60+ }
61+ }
62+
63+ return schema , nil
64+ }
65+
2066 for _ , tool := range tools {
2167 var schema * genai.Schema
2268 if tool .Schema .Properties != nil {
@@ -26,62 +72,16 @@ func ToolsToGoogle(tools []Tool) ([]*genai.Tool, error) {
2672 Required : tool .Schema .Required ,
2773 }
2874
29- // Convert properties
30- for propName , propSchema := range tool .Schema .Properties {
31- // Handle both simple type strings and complex objects
32- var propMap map [string ]any
33- switch ps := propSchema .(type ) {
34- case map [string ]any :
35- propMap = ps
36- case map [string ]string :
37- // Convert map[string]string to map[string]any
38- propMap = make (map [string ]any , len (ps ))
39- for k , v := range ps {
40- propMap [k ] = v
41- }
42- case string :
43- // Handle simple type string (convert to a type definition)
44- propMap = map [string ]any {"type" : ps }
45- default :
46- return nil , fmt .Errorf ("property %q has unsupported schema type %T" , propName , propSchema )
47- }
48-
49- // Get the type
50- typeStr , ok := propMap ["type" ].(string )
75+ for key , value := range tool .Schema .Properties {
76+ propMap , ok := value .(map [string ]any )
5177 if ! ok {
52- return nil , fmt .Errorf ("property %q missing type field" , propName )
53- }
54-
55- prop := & genai.Schema {}
56- switch typeStr {
57- case "string" :
58- prop .Type = genai .TypeString
59- case "number" :
60- prop .Type = genai .TypeNumber
61- case "integer" :
62- prop .Type = genai .TypeInteger
63- case "boolean" :
64- prop .Type = genai .TypeBoolean
65- case "array" :
66- prop .Type = genai .TypeArray
67- case "object" :
68- prop .Type = genai .TypeObject
69- default :
70- return nil , fmt .Errorf ("property %q has unsupported type %q" , propName , typeStr )
71- }
72-
73- // Copy over common fields if they exist
74- if desc , ok := propMap ["description" ].(string ); ok {
75- prop .Description = desc
78+ return nil , fmt .Errorf ("property %q is not a map[string]any: %T" , key , value )
7679 }
77- if enum , ok := propMap ["enum" ].([]any ); ok {
78- prop .Enum = make ([]string , len (enum ))
79- for i , e := range enum {
80- prop .Enum [i ] = fmt .Sprintf ("%v" , e )
81- }
80+ subschema , err := propertyToSchema (propMap )
81+ if err != nil {
82+ return nil , fmt .Errorf ("property %q has non-object properties: %w" , key , err )
8283 }
83-
84- schema .Properties [propName ] = prop
84+ schema .Properties [key ] = subschema
8585 }
8686 }
8787
@@ -323,10 +323,6 @@ func GoogleToDataStream(stream iter.Seq2[*genai.GenerateContentResponse, error])
323323 }, nil ) {
324324 return
325325 }
326- if ! yield (ErrorStreamPart {Content : fmt .Sprintf ("failed to marshal function call args for %s: %s" , fc .Name , err )}, nil ) {
327- return
328- }
329- continue
330326 }
331327
332328 finalReason = FinishReasonToolCalls
0 commit comments