@@ -82,6 +82,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
8282 const urlHost = this . _getUrlHost ( modelUrl )
8383 const deepseekReasoner = modelId . includes ( "deepseek-reasoner" ) || enabledR1Format
8484 const ark = modelUrl . includes ( ".volces.com" )
85+
8586 if ( modelId . startsWith ( "o3-mini" ) ) {
8687 yield * this . handleO3FamilyMessage ( modelId , systemPrompt , messages )
8788 return
@@ -94,6 +95,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
9495 }
9596
9697 let convertedMessages
98+
9799 if ( deepseekReasoner ) {
98100 convertedMessages = convertToR1Format ( [ { role : "user" , content : systemPrompt } , ...messages ] )
99101 } else if ( ark || enabledLegacyFormat ) {
@@ -112,16 +114,20 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
112114 ] ,
113115 }
114116 }
117+
115118 convertedMessages = [ systemMessage , ...convertToOpenAiMessages ( messages ) ]
119+
116120 if ( modelInfo . supportsPromptCache ) {
117121 // Note: the following logic is copied from openrouter:
118122 // Add cache_control to the last two user messages
119123 // (note: this works because we only ever add one user message at a time, but if we added multiple we'd need to mark the user message before the last assistant message)
120124 const lastTwoUserMessages = convertedMessages . filter ( ( msg ) => msg . role === "user" ) . slice ( - 2 )
125+
121126 lastTwoUserMessages . forEach ( ( msg ) => {
122127 if ( typeof msg . content === "string" ) {
123128 msg . content = [ { type : "text" , text : msg . content } ]
124129 }
130+
125131 if ( Array . isArray ( msg . content ) ) {
126132 // NOTE: this is fine since env details will always be added at the end. but if it weren't there, and the user added a image_url type message, it would pop a text part before it and then move it after to the end.
127133 let lastTextPart = msg . content . filter ( ( part ) => part . type === "text" ) . pop ( )
@@ -130,6 +136,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
130136 lastTextPart = { type : "text" , text : "..." }
131137 msg . content . push ( lastTextPart )
132138 }
139+
133140 // @ts -ignore-next-line
134141 lastTextPart [ "cache_control" ] = { type : "ephemeral" }
135142 }
@@ -145,7 +152,9 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
145152 messages : convertedMessages ,
146153 stream : true as const ,
147154 ...( isGrokXAI ? { } : { stream_options : { include_usage : true } } ) ,
155+ reasoning_effort : modelId === "grok-3-mini-beta" ? "high" : this . getModel ( ) . info . reasoningEffort ,
148156 }
157+
149158 if ( this . options . includeMaxTokens ) {
150159 requestOptions . max_tokens = modelInfo . maxTokens
151160 }
@@ -185,6 +194,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
185194 lastUsage = chunk . usage
186195 }
187196 }
197+
188198 for ( const chunk of matcher . final ( ) ) {
189199 yield chunk
190200 }
@@ -217,6 +227,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
217227 type : "text" ,
218228 text : response . choices [ 0 ] ?. message . content || "" ,
219229 }
230+
220231 yield this . processUsageMetrics ( response . usage , modelInfo )
221232 }
222233 }
@@ -241,6 +252,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
241252 async completePrompt ( prompt : string ) : Promise < string > {
242253 try {
243254 const isAzureAiInference = this . _isAzureAiInference ( this . options . openAiBaseUrl )
255+
244256 const requestOptions : OpenAI . Chat . Completions . ChatCompletionCreateParamsNonStreaming = {
245257 model : this . getModel ( ) . id ,
246258 messages : [ { role : "user" , content : prompt } ] ,
@@ -250,11 +262,13 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
250262 requestOptions ,
251263 isAzureAiInference ? { path : AZURE_AI_INFERENCE_PATH } : { } ,
252264 )
265+
253266 return response . choices [ 0 ] ?. message . content || ""
254267 } catch ( error ) {
255268 if ( error instanceof Error ) {
256269 throw new Error ( `OpenAI completion error: ${ error . message } ` )
257270 }
271+
258272 throw error
259273 }
260274 }
@@ -281,7 +295,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
281295 ] ,
282296 stream : true ,
283297 ...( isGrokXAI ? { } : { stream_options : { include_usage : true } } ) ,
284- reasoning_effort : this . getModel ( ) . info . reasoningEffort ,
298+ reasoning_effort : modelId === "grok-3-mini-beta" ? "high" : this . getModel ( ) . info . reasoningEffort ,
285299 } ,
286300 methodIsAzureAiInference ? { path : AZURE_AI_INFERENCE_PATH } : { } ,
287301 )
@@ -333,6 +347,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
333347 }
334348 }
335349 }
350+
336351 private _getUrlHost ( baseUrl ?: string ) : string {
337352 try {
338353 return new URL ( baseUrl ?? "" ) . host
0 commit comments