























@@ -0,0 +1,94 @@
1+import type { StreamFn } from "@mariozechner/pi-agent-core";
2+import type { Context, Model } from "@mariozechner/pi-ai";
3+import { describe, expect, it } from "vitest";
4+import { createQwenThinkingWrapper, wrapQwenProviderStream } from "./stream.js";
5+6+function capturePayload(params: {
7+thinkingLevel?: "off" | "low" | "medium" | "high" | "xhigh" | "max";
8+reasoning?: unknown;
9+initialPayload?: Record<string, unknown>;
10+model?: Partial<Model<"openai-completions">>;
11+}): Record<string, unknown> {
12+let captured: Record<string, unknown> = {};
13+const baseStreamFn: StreamFn = (_model, _context, options) => {
14+const payload = { ...params.initialPayload };
15+options?.onPayload?.(payload, _model);
16+captured = payload;
17+return {} as ReturnType<StreamFn>;
18+};
19+20+const wrapped = createQwenThinkingWrapper(baseStreamFn, params.thinkingLevel ?? "high");
21+void wrapped(
22+{
23+api: "openai-completions",
24+provider: "qwen",
25+id: "qwen3.6-plus",
26+reasoning: true,
27+ ...params.model,
28+} as Model<"openai-completions">,
29+{ messages: [] } as Context,
30+params.reasoning === undefined ? {} : ({ reasoning: params.reasoning } as never),
31+);
32+33+return captured;
34+}
35+36+describe("createQwenThinkingWrapper", () => {
37+it("maps disabled thinking to Qwen top-level enable_thinking", () => {
38+const payload = capturePayload({
39+reasoning: "none",
40+initialPayload: {
41+reasoning_effort: "high",
42+reasoning: { effort: "high" },
43+reasoningEffort: "high",
44+},
45+});
46+47+expect(payload).toEqual({ enable_thinking: false });
48+});
49+50+it("maps enabled thinking to Qwen top-level enable_thinking", () => {
51+expect(capturePayload({ reasoning: "medium" })).toEqual({ enable_thinking: true });
52+});
53+54+it("falls back to the session thinking level", () => {
55+expect(capturePayload({ thinkingLevel: "off" })).toEqual({ enable_thinking: false });
56+expect(capturePayload({ thinkingLevel: "high" })).toEqual({ enable_thinking: true });
57+});
58+59+it("skips non-reasoning and non-completions models", () => {
60+expect(capturePayload({ model: { reasoning: false } })).toEqual({});
61+expect(capturePayload({ model: { api: "openai-responses" as never } })).toEqual({});
62+});
63+});
64+65+describe("wrapQwenProviderStream", () => {
66+it("only registers for Qwen-family OpenAI-compatible providers", () => {
67+expect(
68+wrapQwenProviderStream({
69+provider: "qwencloud",
70+modelId: "qwen3.6-plus",
71+model: {
72+api: "openai-completions",
73+provider: "qwen",
74+id: "qwen3.6-plus",
75+reasoning: true,
76+} as Model<"openai-completions">,
77+streamFn: undefined,
78+} as never),
79+).toBeTypeOf("function");
80+81+expect(
82+wrapQwenProviderStream({
83+provider: "openai",
84+modelId: "gpt-5.4",
85+model: {
86+api: "openai-completions",
87+provider: "openai",
88+id: "gpt-5.4",
89+} as Model<"openai-completions">,
90+streamFn: undefined,
91+} as never),
92+).toBeUndefined();
93+});
94+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。