




















@@ -940,6 +940,138 @@ describe("openai transport stream", () => {
940940]);
941941});
942942943+it("filters DeepSeek DSML text queued after native tool calls", async () => {
944+const model = createDeepSeekCompletionsModel();
945+const output = createAssistantOutput(model);
946+const events: CapturedStreamEvent[] = [];
947+948+await __testing.processOpenAICompletionsStream(
949+streamChunks([
950+{
951+id: "chatcmpl-deepseek-post-tool-dsml",
952+object: "chat.completion.chunk",
953+created: 1,
954+model: model.id,
955+choices: [
956+{
957+index: 0,
958+delta: {
959+tool_calls: [
960+{
961+index: 0,
962+id: "call_native_1",
963+type: "function",
964+function: { name: "read", arguments: '{"path":"/tmp/native.md"}' },
965+},
966+],
967+},
968+logprobs: null,
969+finish_reason: "tool_calls",
970+},
971+],
972+},
973+{
974+id: "chatcmpl-deepseek-post-tool-dsml",
975+object: "chat.completion.chunk",
976+created: 1,
977+model: model.id,
978+choices: [
979+{
980+index: 0,
981+delta: {
982+content: "<|DSML|tool_calls>shadow</|DSML|tool_calls> visible",
983+},
984+logprobs: null,
985+finish_reason: null,
986+},
987+],
988+},
989+]),
990+output,
991+model,
992+{ push: (event) => events.push(event as CapturedStreamEvent) },
993+);
994+995+expect(output.content).toEqual([
996+{
997+type: "toolCall",
998+id: "call_native_1",
999+name: "read",
1000+arguments: { path: "/tmp/native.md" },
1001+partialArgs: '{"path":"/tmp/native.md"}',
1002+},
1003+{ type: "text", text: " visible" },
1004+]);
1005+expect(JSON.stringify(events)).not.toContain("DSML");
1006+});
1007+1008+it("keeps DeepSeek DSML state across native tool-call chunks", async () => {
1009+const model = createDeepSeekCompletionsModel();
1010+const output = createAssistantOutput(model);
1011+const events: CapturedStreamEvent[] = [];
1012+1013+await __testing.processOpenAICompletionsStream(
1014+streamChunks([
1015+{
1016+id: "chatcmpl-deepseek-split-dsml",
1017+object: "chat.completion.chunk",
1018+created: 1,
1019+model: model.id,
1020+choices: [
1021+{
1022+index: 0,
1023+delta: {
1024+content: "before <|DSML|tool",
1025+tool_calls: [
1026+{
1027+index: 0,
1028+id: "call_native_1",
1029+type: "function",
1030+function: { name: "read", arguments: '{"path":"/tmp/native.md"}' },
1031+},
1032+],
1033+},
1034+logprobs: null,
1035+finish_reason: "tool_calls",
1036+},
1037+],
1038+},
1039+{
1040+id: "chatcmpl-deepseek-split-dsml",
1041+object: "chat.completion.chunk",
1042+created: 1,
1043+model: model.id,
1044+choices: [
1045+{
1046+index: 0,
1047+delta: {
1048+content: "_calls>shadow</|DSML|tool_calls> after",
1049+},
1050+logprobs: null,
1051+finish_reason: null,
1052+},
1053+],
1054+},
1055+]),
1056+output,
1057+model,
1058+{ push: (event) => events.push(event as CapturedStreamEvent) },
1059+);
1060+1061+expect(output.content).toEqual([
1062+{ type: "text", text: "before " },
1063+{
1064+type: "toolCall",
1065+id: "call_native_1",
1066+name: "read",
1067+arguments: { path: "/tmp/native.md" },
1068+partialArgs: '{"path":"/tmp/native.md"}',
1069+},
1070+{ type: "text", text: " after" },
1071+]);
1072+expect(JSON.stringify(events)).not.toContain("DSML");
1073+});
1074+9431075it("keeps OpenRouter thinking format for declared OpenRouter providers on custom proxy URLs", () => {
9441076const params = buildOpenAICompletionsParams(
9451077attachModelProviderRequestTransport(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。