55 type GenerateContentParameters ,
66 type GenerateContentConfig ,
77 type GroundingMetadata ,
8+ FunctionCallingConfigMode ,
9+ Content ,
810} from "@google/genai"
911import type { JWTInput } from "google-auth-library"
1012
@@ -101,9 +103,9 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
101103 return true
102104 } )
103105
104- const contents = geminiMessages . map ( ( message ) =>
105- convertAnthropicMessageToGemini ( message , { includeThoughtSignatures } ) ,
106- )
106+ const contents : Content [ ] = geminiMessages
107+ . map ( ( message ) => convertAnthropicMessageToGemini ( message , { includeThoughtSignatures } ) )
108+ . flat ( )
107109
108110 const tools : GenerateContentConfig [ "tools" ] = [ ]
109111 if ( this . options . enableUrlContext ) {
@@ -114,6 +116,16 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
114116 tools . push ( { googleSearch : { } } )
115117 }
116118
119+ if ( metadata ?. tools && metadata . tools . length > 0 ) {
120+ tools . push ( {
121+ functionDeclarations : metadata . tools . map ( ( tool ) => ( {
122+ name : ( tool as any ) . function . name ,
123+ description : ( tool as any ) . function . description ,
124+ parametersJsonSchema : ( tool as any ) . function . parameters ,
125+ } ) ) ,
126+ } )
127+ }
128+
117129 // Determine temperature respecting model capabilities and defaults:
118130 // - If supportsTemperature is explicitly false, ignore user overrides
119131 // and pin to the model's defaultTemperature (or omit if undefined).
@@ -133,6 +145,25 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
133145 ...( tools . length > 0 ? { tools } : { } ) ,
134146 }
135147
148+ if ( metadata ?. tool_choice ) {
149+ config . toolConfig = {
150+ functionCallingConfig : {
151+ mode :
152+ metadata . tool_choice === "auto"
153+ ? FunctionCallingConfigMode . AUTO
154+ : metadata . tool_choice === "required"
155+ ? FunctionCallingConfigMode . ANY
156+ : metadata . tool_choice === "none"
157+ ? FunctionCallingConfigMode . NONE
158+ : FunctionCallingConfigMode . ANY ,
159+ allowedFunctionNames :
160+ typeof metadata . tool_choice === "object" && "function" in metadata . tool_choice
161+ ? [ metadata . tool_choice . function . name ]
162+ : undefined ,
163+ } ,
164+ }
165+ }
166+
136167 const params : GenerateContentParameters = { model, contents, config }
137168 try {
138169 const result = await this . client . models . generateContentStream ( params )
@@ -159,6 +190,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
159190 thought ?: boolean
160191 text ?: string
161192 thoughtSignature ?: string
193+ functionCall ?: { name : string ; args : Record < string , unknown > }
162194 } > ) {
163195 // Capture thought signatures so they can be persisted into API history.
164196 const thoughtSignature = part . thoughtSignature
@@ -174,6 +206,13 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
174206 if ( part . text ) {
175207 yield { type : "reasoning" , text : part . text }
176208 }
209+ } else if ( part . functionCall ) {
210+ yield {
211+ type : "tool_call" ,
212+ id : part . functionCall . name , // Gemini doesn't provide call IDs, so we use the function name
213+ name : part . functionCall . name ,
214+ arguments : JSON . stringify ( part . functionCall . args ) ,
215+ }
177216 } else {
178217 // This is regular content
179218 if ( part . text ) {
@@ -351,7 +390,10 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
351390 const countTokensRequest = {
352391 model,
353392 // Token counting does not need encrypted continuation; always drop thoughtSignature.
354- contents : convertAnthropicContentToGemini ( content , { includeThoughtSignatures : false } ) ,
393+ contents : convertAnthropicMessageToGemini (
394+ { role : "user" , content } ,
395+ { includeThoughtSignatures : false } ,
396+ ) ,
355397 }
356398
357399 const response = await this . client . models . countTokens ( countTokensRequest )
0 commit comments