Skip to content

Commit c8c7735

Browse files
committed
fix: route deepseek through chat completions
The Anthropic message format drops reasoning blocks that carry no signature, and DeepSeek never issues one. A reasoning-only assistant turn — which DeepSeek produces routinely, since it returns reasoning_content with empty content — therefore lowers to `content: []`, and the API rejects the whole request with "all messages must have non-empty content". Once such a turn is in the history every later request in that session fails, so the session is unrecoverable. Chat Completions lowers the same turn to `content: ""`, which DeepSeek accepts, and round-trips reasoning_content as its thinking mode requires — something the Anthropic route cannot do at all.
1 parent 00443ed commit c8c7735

3 files changed

Lines changed: 23 additions & 25 deletions

File tree

src/models.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ type Protocol = "openai" | "anthropic";
4141
const PROVIDERS = new Map<string, { protocol: Protocol; npm: string }>([
4242
["openai", { protocol: "openai", npm: "@ai-sdk/openai" }],
4343
["anthropic", { protocol: "anthropic", npm: "@ai-sdk/anthropic" }],
44-
["deepseek", { protocol: "anthropic", npm: "@ai-sdk/anthropic" }],
44+
// DeepSeek must use Chat Completions, not the Anthropic protocol: the
45+
// Anthropic message format drops reasoning blocks that carry no signature,
46+
// and DeepSeek never issues one. A reasoning-only assistant turn then lowers
47+
// to `content: []` and the API rejects the whole request with "all messages
48+
// must have non-empty content", while `reasoning_content` never survives the
49+
// round-trip that DeepSeek's thinking mode requires.
50+
["deepseek", { protocol: "openai", npm: "@ai-sdk/openai-compatible" }],
4551
["zai", { protocol: "openai", npm: "@ai-sdk/openai-compatible" }],
4652
["moonshotai", { protocol: "openai", npm: "@ai-sdk/openai-compatible" }],
4753
]);

test/index.test.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ const MODELS_DEV_DATA = {
8080
output: ["text"],
8181
},
8282
cost: { input: 1.5, output: 6, cache_read: 0.15, cache_write: 1.5 },
83+
interleaved: { field: "reasoning_content" },
8384
},
8485
"deepseek-v4-flash": {
8586
id: "deepseek-v4-flash",
@@ -99,6 +100,7 @@ const MODELS_DEV_DATA = {
99100
cache_read: 0.015,
100101
cache_write: 0.15,
101102
},
103+
interleaved: { field: "reasoning_content" },
102104
},
103105
},
104106
},
@@ -217,8 +219,8 @@ describe("config hook", () => {
217219
id: "deepseek-v4-pro",
218220
name: "DeepSeek V4 Pro",
219221
provider: {
220-
api: "https://hub.coreinfra.ai/anthropic/api/v1",
221-
npm: "@ai-sdk/anthropic",
222+
api: "https://hub.coreinfra.ai/openai/api/v1",
223+
npm: "@ai-sdk/openai-compatible",
222224
},
223225
attachment: false,
224226
reasoning: true,
@@ -228,18 +230,15 @@ describe("config hook", () => {
228230
cost: { input: 1.5, output: 6, cache_read: 0.15, cache_write: 1.5 },
229231
limit: { context: 1000000, output: 384000 },
230232
interleaved: { field: "reasoning_content" },
231-
headers: {
232-
"anthropic-beta":
233-
"interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
234-
},
233+
headers: {},
235234
});
236235

237236
expect(models["deepseek-v4-flash"]).toEqual({
238237
id: "deepseek-v4-flash",
239238
name: "DeepSeek V4 Flash",
240239
provider: {
241-
api: "https://hub.coreinfra.ai/anthropic/api/v1",
242-
npm: "@ai-sdk/anthropic",
240+
api: "https://hub.coreinfra.ai/openai/api/v1",
241+
npm: "@ai-sdk/openai-compatible",
243242
},
244243
attachment: false,
245244
reasoning: true,
@@ -249,10 +248,7 @@ describe("config hook", () => {
249248
cost: { input: 0.15, output: 0.6, cache_read: 0.015, cache_write: 0.15 },
250249
limit: { context: 1000000, output: 384000 },
251250
interleaved: { field: "reasoning_content" },
252-
headers: {
253-
"anthropic-beta":
254-
"interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
255-
},
251+
headers: {},
256252
});
257253
});
258254

test/models.test.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const MODELS_DEV_FIXTURE = {
6767
output: ["text"],
6868
},
6969
cost: { input: 1.5, output: 6, cache_read: 0.15, cache_write: 1.5 },
70+
interleaved: { field: "reasoning_content" },
7071
},
7172
"deepseek-v4-flash": {
7273
id: "deepseek-v4-flash",
@@ -86,6 +87,7 @@ const MODELS_DEV_FIXTURE = {
8687
cache_read: 0.015,
8788
cache_write: 0.15,
8889
},
90+
interleaved: { field: "reasoning_content" },
8991
},
9092
},
9193
},
@@ -174,8 +176,8 @@ describe("buildConfigModels", () => {
174176
id: "deepseek-v4-pro",
175177
name: "DeepSeek V4 Pro",
176178
provider: {
177-
api: "https://hub.coreinfra.ai/anthropic/api/v1",
178-
npm: "@ai-sdk/anthropic",
179+
api: "https://hub.coreinfra.ai/openai/api/v1",
180+
npm: "@ai-sdk/openai-compatible",
179181
},
180182
attachment: false,
181183
reasoning: true,
@@ -188,19 +190,16 @@ describe("buildConfigModels", () => {
188190
cost: { input: 1.5, output: 6, cache_read: 0.15, cache_write: 1.5 },
189191
limit: { context: 1000000, output: 384000 },
190192
interleaved: { field: "reasoning_content" },
191-
headers: {
192-
"anthropic-beta":
193-
"interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
194-
},
193+
headers: {},
195194
});
196195

197196
const dsFlash = models["deepseek-v4-flash"];
198197
expect(dsFlash).toEqual({
199198
id: "deepseek-v4-flash",
200199
name: "DeepSeek V4 Flash",
201200
provider: {
202-
api: "https://hub.coreinfra.ai/anthropic/api/v1",
203-
npm: "@ai-sdk/anthropic",
201+
api: "https://hub.coreinfra.ai/openai/api/v1",
202+
npm: "@ai-sdk/openai-compatible",
204203
},
205204
attachment: false,
206205
reasoning: true,
@@ -213,10 +212,7 @@ describe("buildConfigModels", () => {
213212
cost: { input: 0.15, output: 0.6, cache_read: 0.015, cache_write: 0.15 },
214213
limit: { context: 1000000, output: 384000 },
215214
interleaved: { field: "reasoning_content" },
216-
headers: {
217-
"anthropic-beta":
218-
"interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
219-
},
215+
headers: {},
220216
});
221217
});
222218

0 commit comments

Comments
 (0)