





















@@ -38,6 +38,29 @@ function requireStreamFn(streamFn: StreamFn | null | undefined) {
3838return streamFn;
3939}
404041+function requireRecord(value: unknown, label: string): Record<string, unknown> {
42+expect(value).toBeTypeOf("object");
43+expect(value).not.toBeNull();
44+if (!value || typeof value !== "object" || Array.isArray(value)) {
45+throw new Error(`expected ${label} to be an object`);
46+}
47+return value as Record<string, unknown>;
48+}
49+50+function requirePayload(payload: Record<string, unknown> | undefined): Record<string, unknown> {
51+expect(payload).toBeDefined();
52+if (!payload) {
53+throw new Error("expected captured payload");
54+}
55+return payload;
56+}
57+58+function expectDefaultThinkingBudget(payload: Record<string, unknown>) {
59+const config = requireRecord(payload.config, "payload.config");
60+const thinkingConfig = requireRecord(config.thinkingConfig, "payload.config.thinkingConfig");
61+expect(thinkingConfig.thinkingBudget).toBe(-1);
62+}
63+4164describe("composeProviderStreamWrappers", () => {
4265it("re-exports the shared wrapper composer", () => {
4366expect(composeProviderStreamWrappers).toBe(composeProviderStreamWrappersShared);
@@ -113,12 +136,13 @@ describe("buildProviderStreamFamilyHooks", () => {
113136{} as never,
114137{},
115138);
116-expect(capturedPayload).toMatchObject({
117-config: { thinkingConfig: { thinkingLevel: "HIGH" } },
118-});
119-const googleThinkingConfig = (
120-(capturedPayload as Record<string, unknown>).config as Record<string, unknown>
121-).thinkingConfig as Record<string, unknown>;
139+const googlePayload = requirePayload(capturedPayload);
140+const googleConfig = requireRecord(googlePayload.config, "google payload config");
141+const googleThinkingConfig = requireRecord(
142+googleConfig.thinkingConfig,
143+"google thinking config",
144+);
145+expect(googleThinkingConfig.thinkingLevel).toBe("HIGH");
122146expect(googleThinkingConfig).not.toHaveProperty("thinkingBudget");
123147124148const minimaxHooks = MINIMAX_FAST_MODE_STREAM_HOOKS;
@@ -147,10 +171,11 @@ describe("buildProviderStreamFamilyHooks", () => {
147171modelId: "openai/gpt-5.4",
148172} as never),
149173)({ provider: "kilocode", id: "openai/gpt-5.4" } as never, {} as never, {});
150-expect(capturedPayload).toMatchObject({
151-config: { thinkingConfig: { thinkingBudget: -1 } },
152-reasoning: { effort: "high" },
153-});
174+const kilocodeOpenAiPayload = requirePayload(capturedPayload);
175+expectDefaultThinkingBudget(kilocodeOpenAiPayload);
176+expect(requireRecord(kilocodeOpenAiPayload.reasoning, "kilocode reasoning").effort).toBe(
177+"high",
178+);
154179155180void requireStreamFn(
156181requireWrapStreamFn(kilocodeHooks.wrapStreamFn)({
@@ -159,10 +184,9 @@ describe("buildProviderStreamFamilyHooks", () => {
159184modelId: "kilo/auto",
160185} as never),
161186)({ provider: "kilocode", id: "kilo/auto" } as never, {} as never, {});
162-expect(capturedPayload).toMatchObject({
163-config: { thinkingConfig: { thinkingBudget: -1 } },
164-});
165-expect(capturedPayload).not.toHaveProperty("reasoning");
187+const kilocodeAutoPayload = requirePayload(capturedPayload);
188+expectDefaultThinkingBudget(kilocodeAutoPayload);
189+expect(kilocodeAutoPayload).not.toHaveProperty("reasoning");
166190167191const moonshotHooks = MOONSHOT_THINKING_STREAM_HOOKS;
168192const moonshotStream = requireStreamFn(
@@ -172,10 +196,11 @@ describe("buildProviderStreamFamilyHooks", () => {
172196} as never),
173197);
174198await moonshotStream({ api: "openai-completions", id: "kimi-k2.5" } as never, {} as never, {});
175-expect(capturedPayload).toMatchObject({
176-config: { thinkingConfig: { thinkingBudget: -1 } },
177-thinking: { type: "disabled" },
178-});
199+const moonshotDisabledPayload = requirePayload(capturedPayload);
200+expectDefaultThinkingBudget(moonshotDisabledPayload);
201+expect(requireRecord(moonshotDisabledPayload.thinking, "moonshot thinking").type).toBe(
202+"disabled",
203+);
179204180205const moonshotKeepStream = requireStreamFn(
181206requireWrapStreamFn(moonshotHooks.wrapStreamFn)({
@@ -189,34 +214,47 @@ describe("buildProviderStreamFamilyHooks", () => {
189214{} as never,
190215{},
191216);
192-expect(capturedPayload).toMatchObject({
193-config: { thinkingConfig: { thinkingBudget: -1 } },
194-thinking: { type: "enabled", keep: "all" },
195-});
217+const moonshotKeepPayload = requirePayload(capturedPayload);
218+expectDefaultThinkingBudget(moonshotKeepPayload);
219+const moonshotKeepThinking = requireRecord(
220+moonshotKeepPayload.thinking,
221+"moonshot keep thinking",
222+);
223+expect(moonshotKeepThinking.type).toBe("enabled");
224+expect(moonshotKeepThinking.keep).toBe("all");
196225197226await moonshotKeepStream(
198227{ api: "openai-completions", id: "kimi-k2.5" } as never,
199228{} as never,
200229{},
201230);
202-expect(capturedPayload).toMatchObject({
203-config: { thinkingConfig: { thinkingBudget: -1 } },
204-thinking: { type: "enabled" },
205-});
206-expect((capturedPayload?.thinking as Record<string, unknown>) ?? {}).not.toHaveProperty("keep");
231+const moonshotStrippedPayload = requirePayload(capturedPayload);
232+expectDefaultThinkingBudget(moonshotStrippedPayload);
233+const moonshotStrippedThinking = requireRecord(
234+moonshotStrippedPayload.thinking,
235+"moonshot stripped thinking",
236+);
237+expect(moonshotStrippedThinking.type).toBe("enabled");
238+expect(moonshotStrippedThinking).not.toHaveProperty("keep");
207239208240payloadSeed = { tool_choice: { type: "tool", name: "read" } };
209241await moonshotKeepStream(
210242{ api: "openai-completions", id: "kimi-k2.6" } as never,
211243{} as never,
212244{},
213245);
214-expect(capturedPayload).toMatchObject({
215-config: { thinkingConfig: { thinkingBudget: -1 } },
216-tool_choice: { type: "tool", name: "read" },
217-thinking: { type: "disabled" },
246+const moonshotToolChoicePayload = requirePayload(capturedPayload);
247+expectDefaultThinkingBudget(moonshotToolChoicePayload);
248+expect(requireRecord(moonshotToolChoicePayload.tool_choice, "tool choice")).toEqual({
249+type: "tool",
250+name: "read",
218251});
219-expect((capturedPayload?.thinking as Record<string, unknown>) ?? {}).not.toHaveProperty("keep");
252+const moonshotToolChoiceThinking = requireRecord(
253+moonshotToolChoicePayload.thinking,
254+"moonshot tool-choice thinking",
255+);
256+expect(moonshotToolChoiceThinking.type).toBe("disabled");
257+expect(moonshotToolChoiceThinking).not.toHaveProperty("keep");
220258221259const openAiHooks = OPENAI_RESPONSES_STREAM_HOOKS;
222260void requireStreamFn(
@@ -236,10 +274,9 @@ describe("buildProviderStreamFamilyHooks", () => {
236274{} as never,
237275{},
238276);
239-expect(capturedPayload).toMatchObject({
240-config: { thinkingConfig: { thinkingBudget: -1 } },
241-service_tier: "flex",
242-});
277+const openAiPayload = requirePayload(capturedPayload);
278+expectDefaultThinkingBudget(openAiPayload);
279+expect(openAiPayload.service_tier).toBe("flex");
243280expect(capturedHeaders).toEqual({
244281"User-Agent": `openclaw/${VERSION}`,
245282originator: "openclaw",
@@ -254,10 +291,11 @@ describe("buildProviderStreamFamilyHooks", () => {
254291modelId: "openai/gpt-5.4",
255292} as never),
256293)({ provider: "openrouter", id: "openai/gpt-5.4" } as never, {} as never, {});
257-expect(capturedPayload).toMatchObject({
258-config: { thinkingConfig: { thinkingBudget: -1 } },
259-reasoning: { effort: "high" },
260-});
294+const openRouterOpenAiPayload = requirePayload(capturedPayload);
295+expectDefaultThinkingBudget(openRouterOpenAiPayload);
296+expect(requireRecord(openRouterOpenAiPayload.reasoning, "openrouter reasoning").effort).toBe(
297+"high",
298+);
261299262300void requireStreamFn(
263301requireWrapStreamFn(openRouterHooks.wrapStreamFn)({
@@ -266,10 +304,9 @@ describe("buildProviderStreamFamilyHooks", () => {
266304modelId: "x-ai/grok-3",
267305} as never),
268306)({ provider: "openrouter", id: "x-ai/grok-3" } as never, {} as never, {});
269-expect(capturedPayload).toMatchObject({
270-config: { thinkingConfig: { thinkingBudget: -1 } },
271-});
272-expect(capturedPayload).not.toHaveProperty("reasoning");
307+const openRouterGrokPayload = requirePayload(capturedPayload);
308+expectDefaultThinkingBudget(openRouterGrokPayload);
309+expect(openRouterGrokPayload).not.toHaveProperty("reasoning");
273310274311const toolStreamHooks = TOOL_STREAM_DEFAULT_ON_HOOKS;
275312const toolStreamDefault = requireStreamFn(
@@ -279,10 +316,9 @@ describe("buildProviderStreamFamilyHooks", () => {
279316} as never),
280317);
281318await toolStreamDefault({ id: "glm-4.7" } as never, {} as never, {});
282-expect(capturedPayload).toMatchObject({
283-config: { thinkingConfig: { thinkingBudget: -1 } },
284-tool_stream: true,
285-});
319+const toolStreamDefaultPayload = requirePayload(capturedPayload);
320+expectDefaultThinkingBudget(toolStreamDefaultPayload);
321+expect(toolStreamDefaultPayload.tool_stream).toBe(true);
286322287323const toolStreamDisabled = requireStreamFn(
288324requireWrapStreamFn(toolStreamHooks.wrapStreamFn)({
@@ -291,10 +327,9 @@ describe("buildProviderStreamFamilyHooks", () => {
291327} as never),
292328);
293329await toolStreamDisabled({ id: "glm-4.7" } as never, {} as never, {});
294-expect(capturedPayload).toMatchObject({
295-config: { thinkingConfig: { thinkingBudget: -1 } },
296-});
297-expect(capturedPayload).not.toHaveProperty("tool_stream");
330+const toolStreamDisabledPayload = requirePayload(capturedPayload);
331+expectDefaultThinkingBudget(toolStreamDisabledPayload);
332+expect(toolStreamDisabledPayload).not.toHaveProperty("tool_stream");
298333});
299334300335it("exposes canonical stream hook constants for reused families", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。