






















@@ -217,6 +217,96 @@ describe("deepseek provider plugin", () => {
217217});
218218});
219219220+it("adds blank reasoning_content for replayed tool calls from non-DeepSeek turns", async () => {
221+let capturedPayload: Record<string, unknown> | undefined;
222+const model = {
223+provider: "deepseek",
224+id: "deepseek-v4-pro",
225+name: "DeepSeek V4 Pro",
226+api: "openai-completions",
227+baseUrl: "https://api.deepseek.com",
228+reasoning: true,
229+input: ["text"],
230+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
231+contextWindow: 1_000_000,
232+maxTokens: 384_000,
233+compat: {
234+supportsUsageInStreaming: true,
235+supportsReasoningEffort: true,
236+maxTokensField: "max_tokens",
237+},
238+} as Model<"openai-completions">;
239+const context = {
240+messages: [
241+{ role: "user", content: "hi", timestamp: 1 },
242+{
243+role: "assistant",
244+api: "openai-completions",
245+provider: "openai",
246+model: "gpt-5.4",
247+content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
248+usage: {
249+input: 0,
250+output: 0,
251+cacheRead: 0,
252+cacheWrite: 0,
253+totalTokens: 0,
254+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
255+},
256+stopReason: "toolUse",
257+timestamp: 2,
258+},
259+{
260+role: "toolResult",
261+toolCallId: "call_1",
262+toolName: "read",
263+content: [{ type: "text", text: "ok" }],
264+isError: false,
265+timestamp: 3,
266+},
267+],
268+tools: [
269+{
270+name: "read",
271+description: "Read data",
272+parameters: { type: "object", properties: {}, required: [], additionalProperties: false },
273+},
274+],
275+} as Context;
276+const baseStreamFn = (
277+streamModel: Model<"openai-completions">,
278+streamContext: Context,
279+options?: { onPayload?: (payload: unknown, model: unknown) => unknown },
280+) => {
281+capturedPayload = buildOpenAICompletionsParams(streamModel, streamContext, {
282+reasoning: "high",
283+} as never);
284+options?.onPayload?.(capturedPayload, streamModel);
285+const stream = createAssistantMessageEventStream();
286+queueMicrotask(() => stream.end());
287+return stream;
288+};
289+290+const wrapThinkingHigh = createDeepSeekV4ThinkingWrapper(baseStreamFn as never, "high");
291+expect(wrapThinkingHigh).toBeDefined();
292+wrapThinkingHigh?.(model, context, {});
293+294+expect((capturedPayload?.messages as Array<Record<string, unknown>>)[1]).toMatchObject({
295+role: "assistant",
296+reasoning_content: "",
297+tool_calls: [
298+{
299+id: "call_1",
300+type: "function",
301+function: {
302+name: "read",
303+arguments: "{}",
304+},
305+},
306+],
307+});
308+});
309+220310it("strips replayed reasoning_content when DeepSeek V4 thinking is disabled", async () => {
221311let capturedPayload: Record<string, unknown> | undefined;
222312const model = {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。