@@ -76,6 +76,7 @@ struct GenerateContentIntegrationTests {
7676 let promptTokensDetails = try #require( usageMetadata. promptTokensDetails. first)
7777 #expect( promptTokensDetails. modality == . text)
7878 #expect( promptTokensDetails. tokenCount == usageMetadata. promptTokenCount)
79+ #expect( usageMetadata. thoughtsTokenCount == 0 )
7980 // The fields `candidatesTokenCount` and `candidatesTokensDetails` are not included when using
8081 // Gemma models.
8182 if modelName. hasPrefix ( " gemma " ) {
@@ -119,6 +120,7 @@ struct GenerateContentIntegrationTests {
119120 let usageMetadata = try #require( response. usageMetadata)
120121 #expect( usageMetadata. promptTokenCount. isEqual ( to: 15 , accuracy: tokenCountAccuracy) )
121122 #expect( usageMetadata. candidatesTokenCount. isEqual ( to: 1 , accuracy: tokenCountAccuracy) )
123+ #expect( usageMetadata. thoughtsTokenCount == 0 )
122124 #expect( usageMetadata. totalTokenCount
123125 == usageMetadata. promptTokenCount + usageMetadata. candidatesTokenCount)
124126 #expect( usageMetadata. promptTokensDetails. count == 1 )
@@ -131,6 +133,68 @@ struct GenerateContentIntegrationTests {
131133 #expect( candidatesTokensDetails. tokenCount == usageMetadata. candidatesTokenCount)
132134 }
133135
136+ @Test ( arguments: [
137+ ( InstanceConfig . vertexAI_v1beta, ModelNames . gemini2_5_FlashPreview, 0 ) ,
138+ ( InstanceConfig . vertexAI_v1beta, ModelNames . gemini2_5_FlashPreview, 24576 ) ,
139+ // TODO: Add Vertex AI Gemini 2.5 Pro tests when available.
140+ // (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2_5_ProPreview, 128),
141+ // (InstanceConfig.vertexAI_v1beta, ModelNames.gemini2_5_ProPreview, 32768),
142+ ( InstanceConfig . googleAI_v1beta, ModelNames . gemini2_5_FlashPreview, 0 ) ,
143+ ( InstanceConfig . googleAI_v1beta, ModelNames . gemini2_5_FlashPreview, 24576 ) ,
144+ ( InstanceConfig . googleAI_v1beta, ModelNames . gemini2_5_ProPreview, 128 ) ,
145+ ( InstanceConfig . googleAI_v1beta, ModelNames . gemini2_5_ProPreview, 32768 ) ,
146+ ( InstanceConfig . googleAI_v1beta_freeTier, ModelNames . gemini2_5_FlashPreview, 0 ) ,
147+ ( InstanceConfig . googleAI_v1beta_freeTier, ModelNames . gemini2_5_FlashPreview, 24576 ) ,
148+ ] )
149+ func generateContentThinking( _ config: InstanceConfig , modelName: String ,
150+ thinkingBudget: Int ) async throws {
151+ let model = FirebaseAI . componentInstance ( config) . generativeModel (
152+ modelName: modelName,
153+ generationConfig: GenerationConfig (
154+ temperature: 0.0 ,
155+ topP: 0.0 ,
156+ topK: 1 ,
157+ thinkingConfig: ThinkingConfig ( thinkingBudget: thinkingBudget)
158+ ) ,
159+ safetySettings: safetySettings
160+ )
161+ let prompt = " Where is Google headquarters located? Answer with the city name only. "
162+
163+ let response = try await model. generateContent ( prompt)
164+
165+ let text = try #require( response. text) . trimmingCharacters ( in: . whitespacesAndNewlines)
166+ #expect( text == " Mountain View " )
167+
168+ let usageMetadata = try #require( response. usageMetadata)
169+ #expect( usageMetadata. promptTokenCount. isEqual ( to: 13 , accuracy: tokenCountAccuracy) )
170+ #expect( usageMetadata. promptTokensDetails. count == 1 )
171+ let promptTokensDetails = try #require( usageMetadata. promptTokensDetails. first)
172+ #expect( promptTokensDetails. modality == . text)
173+ #expect( promptTokensDetails. tokenCount == usageMetadata. promptTokenCount)
174+ if thinkingBudget == 0 {
175+ #expect( usageMetadata. thoughtsTokenCount == 0 )
176+ } else {
177+ #expect( usageMetadata. thoughtsTokenCount <= thinkingBudget)
178+ }
179+ #expect( usageMetadata. candidatesTokenCount. isEqual ( to: 3 , accuracy: tokenCountAccuracy) )
180+ // The `candidatesTokensDetails` field is erroneously omitted when using the Google AI (Gemini
181+ // Developer API) backend.
182+ if case . googleAI = config. apiConfig. service {
183+ #expect( usageMetadata. candidatesTokensDetails. isEmpty)
184+ } else {
185+ #expect( usageMetadata. candidatesTokensDetails. count == 1 )
186+ let candidatesTokensDetails = try #require( usageMetadata. candidatesTokensDetails. first)
187+ #expect( candidatesTokensDetails. modality == . text)
188+ #expect( candidatesTokensDetails. tokenCount == usageMetadata. candidatesTokenCount)
189+ }
190+ #expect( usageMetadata. totalTokenCount > 0 )
191+ #expect( usageMetadata. totalTokenCount == (
192+ usageMetadata. promptTokenCount
193+ + usageMetadata. thoughtsTokenCount
194+ + usageMetadata. candidatesTokenCount
195+ ) )
196+ }
197+
134198 @Test ( arguments: [
135199 InstanceConfig . vertexAI_v1beta,
136200 InstanceConfig . googleAI_v1beta,
0 commit comments