@@ -30,7 +30,8 @@ vi.mock("openai", () => {
3030 }
3131
3232 // Check if this is a reasoning_content test by looking at model
33- const isReasonerModel = options . model ?. includes ( "deepseek-reasoner" )
33+ const isReasonerModel =
34+ options . model ?. includes ( "deepseek-reasoner" ) || options . model ?. includes ( "deepseek-v4" )
3435 const isToolCallTest = options . tools ?. length > 0
3536
3637 // Return async iterator for streaming
@@ -122,7 +123,7 @@ vi.mock("openai", () => {
122123import OpenAI from "openai"
123124import type { Anthropic } from "@anthropic-ai/sdk"
124125
125- import { deepSeekDefaultModelId , DEEP_SEEK_DEFAULT_TEMPERATURE , type ModelInfo } from "@roo-code/types"
126+ import { deepSeekDefaultModelId , deepSeekModels , DEEP_SEEK_DEFAULT_TEMPERATURE , type ModelInfo } from "@roo-code/types"
126127
127128import type { ApiHandlerOptions } from "../../../shared/api"
128129
@@ -226,6 +227,28 @@ describe("DeepSeekHandler", () => {
226227 expect ( model . info . supportsPromptCache ) . toBe ( true )
227228 } )
228229
230+ it . each ( [
231+ [ "deepseek-v4-flash" , deepSeekModels [ "deepseek-v4-flash" ] ] ,
232+ [ "deepseek-v4-pro" , deepSeekModels [ "deepseek-v4-pro" ] ] ,
233+ ] ) ( "should return correct model info for %s" , ( modelId , expectedInfo ) => {
234+ const handlerWithV4 = new DeepSeekHandler ( {
235+ ...mockOptions ,
236+ apiModelId : modelId ,
237+ } )
238+
239+ const model = handlerWithV4 . getModel ( )
240+ const info = model . info as ModelInfo
241+
242+ expect ( model . id ) . toBe ( modelId )
243+ expect ( info . maxTokens ) . toBe ( 384_000 )
244+ expect ( info . contextWindow ) . toBe ( 1_000_000 )
245+ expect ( info . supportsPromptCache ) . toBe ( true )
246+ expect ( info . preserveReasoning ) . toBe ( true )
247+ expect ( info . supportsReasoningEffort ) . toEqual ( [ "disable" , "high" , "xhigh" ] )
248+ expect ( info . reasoningEffort ) . toBe ( "high" )
249+ expect ( model . info ) . toBe ( expectedInfo )
250+ } )
251+
229252 it ( "should have preserveReasoning enabled for deepseek-reasoner to support interleaved thinking" , ( ) => {
230253 // This is critical for DeepSeek's interleaved thinking mode with tool calls.
231254 // See: https://api-docs.deepseek.com/guides/thinking_mode
@@ -475,6 +498,60 @@ describe("DeepSeekHandler", () => {
475498 expect ( callArgs . thinking ) . toBeUndefined ( )
476499 } )
477500
501+ it ( "should pass reasoning parameters for DeepSeek V4 models" , async ( ) => {
502+ const v4Handler = new DeepSeekHandler ( {
503+ ...mockOptions ,
504+ apiModelId : "deepseek-v4-flash" ,
505+ enableReasoningEffort : true ,
506+ reasoningEffort : "high" ,
507+ } )
508+
509+ const stream = v4Handler . createMessage ( systemPrompt , messages )
510+ for await ( const _chunk of stream ) {
511+ // Consume the stream
512+ }
513+
514+ const callArgs = mockCreate . mock . calls [ 0 ] [ 0 ]
515+ expect ( callArgs . thinking ) . toEqual ( { type : "enabled" } )
516+ expect ( callArgs . reasoning_effort ) . toBe ( "high" )
517+ } )
518+
519+ it ( "should map xhigh reasoning effort to DeepSeek max" , async ( ) => {
520+ const v4Handler = new DeepSeekHandler ( {
521+ ...mockOptions ,
522+ apiModelId : "deepseek-v4-pro" ,
523+ enableReasoningEffort : true ,
524+ reasoningEffort : "xhigh" ,
525+ } )
526+
527+ const stream = v4Handler . createMessage ( systemPrompt , messages )
528+ for await ( const _chunk of stream ) {
529+ // Consume the stream
530+ }
531+
532+ const callArgs = mockCreate . mock . calls [ 0 ] [ 0 ]
533+ expect ( callArgs . thinking ) . toEqual ( { type : "enabled" } )
534+ expect ( callArgs . reasoning_effort ) . toBe ( "max" )
535+ } )
536+
537+ it ( "should disable thinking for DeepSeek V4 when reasoning effort is disabled" , async ( ) => {
538+ const v4Handler = new DeepSeekHandler ( {
539+ ...mockOptions ,
540+ apiModelId : "deepseek-v4-flash" ,
541+ enableReasoningEffort : true ,
542+ reasoningEffort : "disable" ,
543+ } )
544+
545+ const stream = v4Handler . createMessage ( systemPrompt , messages )
546+ for await ( const _chunk of stream ) {
547+ // Consume the stream
548+ }
549+
550+ const callArgs = mockCreate . mock . calls [ 0 ] [ 0 ]
551+ expect ( callArgs . thinking ) . toEqual ( { type : "disabled" } )
552+ expect ( callArgs . reasoning_effort ) . toBeUndefined ( )
553+ } )
554+
478555 it ( "should handle tool calls with reasoning_content" , async ( ) => {
479556 const reasonerHandler = new DeepSeekHandler ( {
480557 ...mockOptions ,
0 commit comments