Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit ec0df58

Browse files
committed
feat: add DeepSeek V4 Pro and Flash models with correct 1M context and 384K output specs
1 parent 96d6e43 commit ec0df58

3 files changed

Lines changed: 99 additions & 3 deletions

File tree

packages/types/src/providers/deepseek.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@ export const deepSeekModels = {
3232
cacheReadsPrice: 0.028, // $0.028 per million tokens (cache hit) - Updated Dec 9, 2025
3333
description: `DeepSeek-V3.2 (Thinking Mode) achieves performance comparable to OpenAI-o1 across math, code, and reasoning tasks. Supports Chain of Thought reasoning with up to 8K output tokens. Supports JSON output, tool calls, and chat prefix completion (beta).`,
3434
},
35+
"deepseek-v4-pro": {
36+
maxTokens: 384_000, // 384K max output
37+
contextWindow: 1_000_000, // 1M context
38+
supportsImages: true,
39+
supportsPromptCache: true,
40+
preserveReasoning: true,
41+
inputPrice: 2.0, // $2.00 per million tokens (cache miss)
42+
outputPrice: 8.0, // $8.00 per million tokens
43+
cacheWritesPrice: 2.0, // $2.00 per million tokens (cache miss)
44+
cacheReadsPrice: 0.5, // $0.50 per million tokens (cache hit)
45+
description: `DeepSeek-V4-Pro is the flagship reasoning model with 1M context window and 384K max output. Features enhanced thinking mode, vision support, tool calls, and JSON output. Best suited for complex reasoning, code generation, and multi-step tasks.`,
46+
},
47+
"deepseek-v4-flash": {
48+
maxTokens: 384_000, // 384K max output
49+
contextWindow: 1_000_000, // 1M context
50+
supportsImages: true,
51+
supportsPromptCache: true,
52+
preserveReasoning: true,
53+
inputPrice: 1.0, // $1.00 per million tokens (cache miss)
54+
outputPrice: 4.0, // $4.00 per million tokens
55+
cacheWritesPrice: 1.0, // $1.00 per million tokens (cache miss)
56+
cacheReadsPrice: 0.25, // $0.25 per million tokens (cache hit)
57+
description: `DeepSeek-V4-Flash is a fast, cost-efficient reasoning model with 1M context window and 384K max output. Features thinking mode, vision support, tool calls, and JSON output. Optimized for speed while maintaining strong reasoning capabilities.`,
58+
},
3559
} as const satisfies Record<string, ModelInfo>
3660

3761
// https://api-docs.deepseek.com/quick_start/parameter_settings

src/api/providers/__tests__/deepseek.spec.ts

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
@@ -247,6 +248,36 @@ describe("DeepSeekHandler", () => {
247248
expect((model.info as ModelInfo).preserveReasoning).toBeUndefined()
248249
})
249250

251+
it("should return correct model info for deepseek-v4-pro", () => {
252+
const handlerWithV4Pro = new DeepSeekHandler({
253+
...mockOptions,
254+
apiModelId: "deepseek-v4-pro",
255+
})
256+
const model = handlerWithV4Pro.getModel()
257+
expect(model.id).toBe("deepseek-v4-pro")
258+
expect(model.info).toBeDefined()
259+
expect(model.info.maxTokens).toBe(384_000) // 384K max output
260+
expect(model.info.contextWindow).toBe(1_000_000) // 1M context
261+
expect(model.info.supportsImages).toBe(true)
262+
expect(model.info.supportsPromptCache).toBe(true)
263+
expect((model.info as ModelInfo).preserveReasoning).toBe(true)
264+
})
265+
266+
it("should return correct model info for deepseek-v4-flash", () => {
267+
const handlerWithV4Flash = new DeepSeekHandler({
268+
...mockOptions,
269+
apiModelId: "deepseek-v4-flash",
270+
})
271+
const model = handlerWithV4Flash.getModel()
272+
expect(model.id).toBe("deepseek-v4-flash")
273+
expect(model.info).toBeDefined()
274+
expect(model.info.maxTokens).toBe(384_000) // 384K max output
275+
expect(model.info.contextWindow).toBe(1_000_000) // 1M context
276+
expect(model.info.supportsImages).toBe(true)
277+
expect(model.info.supportsPromptCache).toBe(true)
278+
expect((model.info as ModelInfo).preserveReasoning).toBe(true)
279+
})
280+
250281
it("should return provided model ID with default model info if model does not exist", () => {
251282
const handlerWithInvalidModel = new DeepSeekHandler({
252283
...mockOptions,
@@ -475,6 +506,46 @@ describe("DeepSeekHandler", () => {
475506
expect(callArgs.thinking).toBeUndefined()
476507
})
477508

509+
it("should pass thinking parameter for deepseek-v4-pro model", async () => {
510+
const v4ProHandler = new DeepSeekHandler({
511+
...mockOptions,
512+
apiModelId: "deepseek-v4-pro",
513+
})
514+
515+
const stream = v4ProHandler.createMessage(systemPrompt, messages)
516+
for await (const _chunk of stream) {
517+
// Consume the stream
518+
}
519+
520+
// Verify that the thinking parameter was passed to the API
521+
expect(mockCreate).toHaveBeenCalledWith(
522+
expect.objectContaining({
523+
thinking: { type: "enabled" },
524+
}),
525+
{},
526+
)
527+
})
528+
529+
it("should pass thinking parameter for deepseek-v4-flash model", async () => {
530+
const v4FlashHandler = new DeepSeekHandler({
531+
...mockOptions,
532+
apiModelId: "deepseek-v4-flash",
533+
})
534+
535+
const stream = v4FlashHandler.createMessage(systemPrompt, messages)
536+
for await (const _chunk of stream) {
537+
// Consume the stream
538+
}
539+
540+
// Verify that the thinking parameter was passed to the API
541+
expect(mockCreate).toHaveBeenCalledWith(
542+
expect.objectContaining({
543+
thinking: { type: "enabled" },
544+
}),
545+
{},
546+
)
547+
})
548+
478549
it("should handle tool calls with reasoning_content", async () => {
479550
const reasonerHandler = new DeepSeekHandler({
480551
...mockOptions,

src/api/providers/deepseek.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ export class DeepSeekHandler extends OpenAiHandler {
5555
const modelId = this.options.apiModelId ?? deepSeekDefaultModelId
5656
const { info: modelInfo } = this.getModel()
5757

58-
// Check if this is a thinking-enabled model (deepseek-reasoner)
59-
const isThinkingModel = modelId.includes("deepseek-reasoner")
58+
// Check if this is a thinking-enabled model using the preserveReasoning flag
59+
// This covers deepseek-reasoner, deepseek-v4-pro, deepseek-v4-flash, and future thinking models
60+
const isThinkingModel = "preserveReasoning" in modelInfo && modelInfo.preserveReasoning === true
6061

6162
// Convert messages to R1 format (merges consecutive same-role messages)
6263
// This is required for DeepSeek which does not support successive messages with the same role

0 commit comments

Comments
 (0)