


















@@ -2611,6 +2611,93 @@ describe("openai transport stream", () => {
26112611]);
26122612});
261326132614+it("treats singular tool_call finish_reason as tool use", async () => {
2615+const model = {
2616+id: "minimax-m2.5-8bit",
2617+name: "MiniMax M2.5 8bit",
2618+api: "openai-completions",
2619+provider: "mlx-lm",
2620+baseUrl: "http://localhost:1234/v1",
2621+reasoning: false,
2622+input: ["text"],
2623+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
2624+contextWindow: 128000,
2625+maxTokens: 8192,
2626+} satisfies Model<"openai-completions">;
2627+2628+const output = {
2629+role: "assistant" as const,
2630+content: [],
2631+api: model.api,
2632+provider: model.provider,
2633+model: model.id,
2634+usage: {
2635+input: 0,
2636+output: 0,
2637+cacheRead: 0,
2638+cacheWrite: 0,
2639+totalTokens: 0,
2640+cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
2641+},
2642+stopReason: "stop",
2643+timestamp: Date.now(),
2644+};
2645+2646+const stream: { push(event: unknown): void } = { push() {} };
2647+2648+const mockChunks = [
2649+{
2650+id: "chatcmpl-mlx",
2651+object: "chat.completion.chunk" as const,
2652+created: 1775425651,
2653+model: model.id,
2654+choices: [
2655+{
2656+index: 0,
2657+delta: {
2658+tool_calls: [
2659+{
2660+id: "call_1",
2661+type: "function" as const,
2662+function: { name: "lookup", arguments: "{}" },
2663+},
2664+],
2665+},
2666+logprobs: null,
2667+finish_reason: null,
2668+},
2669+],
2670+},
2671+{
2672+id: "chatcmpl-mlx",
2673+object: "chat.completion.chunk" as const,
2674+created: 1775425651,
2675+model: model.id,
2676+choices: [
2677+{
2678+index: 0,
2679+delta: {},
2680+logprobs: null,
2681+finish_reason: "tool_call",
2682+},
2683+],
2684+},
2685+] as const;
2686+2687+async function* mockStream() {
2688+for (const chunk of mockChunks) {
2689+yield chunk as never;
2690+}
2691+}
2692+2693+await __testing.processOpenAICompletionsStream(mockStream(), output, model, stream);
2694+2695+expect(output.stopReason).toBe("toolUse");
2696+expect(output.content).toContainEqual(
2697+expect.objectContaining({ type: "toolCall", id: "call_1", name: "lookup" }),
2698+);
2699+});
2700+26142701it("keeps streamed tool call arguments intact when reasoning_details repeats", async () => {
26152702const model = {
26162703id: "openrouter/qwen/qwen3-235b-a22b",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。