@@ -14,6 +14,7 @@ import { safeJsonParse } from "../../shared/safeJsonParse"
1414
1515import { convertAnthropicContentToGemini , convertAnthropicMessageToGemini } from "../transform/gemini-format"
1616import type { ApiStream } from "../transform/stream"
17+ import { getModelParams } from "../transform/model-params"
1718
1819import type { SingleCompletionHandler , ApiHandlerCreateMessageMetadata } from "../index"
1920import { BaseProvider } from "./base-provider"
@@ -62,15 +63,15 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
6263 messages : Anthropic . Messages . MessageParam [ ] ,
6364 metadata ?: ApiHandlerCreateMessageMetadata ,
6465 ) : ApiStream {
65- const { id : model , thinkingConfig , maxOutputTokens , info } = this . getModel ( )
66+ const { id : model , info , reasoning : thinkingConfig , maxTokens } = this . getModel ( )
6667
6768 const contents = messages . map ( convertAnthropicMessageToGemini )
6869
6970 const config : GenerateContentConfig = {
7071 systemInstruction,
7172 httpOptions : this . options . googleGeminiBaseUrl ? { baseUrl : this . options . googleGeminiBaseUrl } : undefined ,
7273 thinkingConfig,
73- maxOutputTokens,
74+ maxOutputTokens : this . options . modelMaxTokens ?? maxTokens ?? undefined ,
7475 temperature : this . options . modelTemperature ?? 0 ,
7576 }
7677
@@ -81,7 +82,28 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
8182 let lastUsageMetadata : GenerateContentResponseUsageMetadata | undefined
8283
8384 for await ( const chunk of result ) {
84- if ( chunk . text ) {
85+ // Process candidates and their parts to separate thoughts from content
86+ if ( chunk . candidates && chunk . candidates . length > 0 ) {
87+ const candidate = chunk . candidates [ 0 ]
88+ if ( candidate . content && candidate . content . parts ) {
89+ for ( const part of candidate . content . parts ) {
90+ if ( part . thought ) {
91+ // This is a thinking/reasoning part
92+ if ( part . text ) {
93+ yield { type : "reasoning" , text : part . text }
94+ }
95+ } else {
96+ // This is regular content
97+ if ( part . text ) {
98+ yield { type : "text" , text : part . text }
99+ }
100+ }
101+ }
102+ }
103+ }
104+
105+ // Fallback to the original text property if no candidates structure
106+ else if ( chunk . text ) {
85107 yield { type : "text" , text : chunk . text }
86108 }
87109
@@ -108,32 +130,16 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
108130 }
109131
110132 override getModel ( ) {
111- let id = this . options . apiModelId ?? geminiDefaultModelId
112- let info : ModelInfo = geminiModels [ id as GeminiModelId ]
113-
114- if ( id ?. endsWith ( ":thinking" ) ) {
115- id = id . slice ( 0 , - ":thinking" . length )
116-
117- if ( geminiModels [ id as GeminiModelId ] ) {
118- info = geminiModels [ id as GeminiModelId ]
119-
120- return {
121- id,
122- info,
123- thinkingConfig : this . options . modelMaxThinkingTokens
124- ? { thinkingBudget : this . options . modelMaxThinkingTokens }
125- : undefined ,
126- maxOutputTokens : this . options . modelMaxTokens ?? info . maxTokens ?? undefined ,
127- }
128- }
129- }
130-
131- if ( ! info ) {
132- id = geminiDefaultModelId
133- info = geminiModels [ geminiDefaultModelId ]
134- }
135-
136- return { id, info }
133+ const modelId = this . options . apiModelId
134+ let id = modelId && modelId in geminiModels ? ( modelId as GeminiModelId ) : geminiDefaultModelId
135+ const info : ModelInfo = geminiModels [ id ]
136+ const params = getModelParams ( { format : "gemini" , modelId : id , model : info , settings : this . options } )
137+
138+ // The `:thinking` suffix indicates that the model is a "Hybrid"
139+ // reasoning model and that reasoning is required to be enabled.
140+ // The actual model ID honored by Gemini's API does not have this
141+ // suffix.
142+ return { id : id . endsWith ( ":thinking" ) ? id . replace ( ":thinking" , "" ) : id , info, ...params }
137143 }
138144
139145 async completePrompt ( prompt : string ) : Promise < string > {
0 commit comments