





















@@ -20,37 +20,59 @@ function createGlm47Template() {
2020};
2121}
222223+function expectReplayPolicyFields(
24+policy: Record<string, unknown> | undefined,
25+fields: Record<string, unknown>,
26+): void {
27+expect(policy).toBeDefined();
28+for (const [key, value] of Object.entries(fields)) {
29+expect(policy?.[key]).toEqual(value);
30+}
31+}
32+33+function expectModelFields(
34+model: Record<string, unknown> | undefined,
35+fields: Record<string, unknown>,
36+): void {
37+expect(model).toBeDefined();
38+for (const [key, value] of Object.entries(fields)) {
39+expect(model?.[key]).toEqual(value);
40+}
41+}
42+2343describe("zai provider plugin", () => {
2444it("owns replay policy for OpenAI-compatible Z.ai transports", async () => {
2545const provider = await registerSingleProviderPlugin(plugin);
264627-expect(
47+expectReplayPolicyFields(
2848provider.buildReplayPolicy?.({
2949provider: "zai",
3050modelApi: "openai-completions",
3151modelId: "glm-5.1",
32-} as never),
33-).toMatchObject({
34-sanitizeToolCallIds: true,
35-toolCallIdMode: "strict",
36-applyAssistantFirstOrderingFix: true,
37-validateGeminiTurns: true,
38-validateAnthropicTurns: true,
39-});
52+} as never) as Record<string, unknown> | undefined,
53+{
54+sanitizeToolCallIds: true,
55+toolCallIdMode: "strict",
56+applyAssistantFirstOrderingFix: true,
57+validateGeminiTurns: true,
58+validateAnthropicTurns: true,
59+},
60+);
406141-expect(
62+expectReplayPolicyFields(
4263provider.buildReplayPolicy?.({
4364provider: "zai",
4465modelApi: "openai-responses",
4566modelId: "glm-5.1",
46-} as never),
47-).toMatchObject({
48-sanitizeToolCallIds: true,
49-toolCallIdMode: "strict",
50-applyAssistantFirstOrderingFix: false,
51-validateGeminiTurns: false,
52-validateAnthropicTurns: false,
53-});
67+} as never) as Record<string, unknown> | undefined,
68+{
69+sanitizeToolCallIds: true,
70+toolCallIdMode: "strict",
71+applyAssistantFirstOrderingFix: false,
72+validateGeminiTurns: false,
73+validateAnthropicTurns: false,
74+},
75+);
5476});
55775678it("resolves persisted GLM-5 family models with provider-owned metadata", async () => {
@@ -79,15 +101,14 @@ describe("zai provider plugin", () => {
79101] as const;
8010281103for (const testCase of cases) {
82-expect(
83-provider.resolveDynamicModel?.({
84-provider: "zai",
85-modelId: testCase.modelId,
86-modelRegistry: {
87-find: (_provider: string, modelId: string) => (modelId === "glm-4.7" ? template : null),
88-},
89-} as never),
90-).toMatchObject({
104+const resolved = provider.resolveDynamicModel?.({
105+provider: "zai",
106+modelId: testCase.modelId,
107+modelRegistry: {
108+find: (_provider: string, modelId: string) => (modelId === "glm-4.7" ? template : null),
109+},
110+} as never) as Record<string, unknown> | undefined;
111+expectModelFields(resolved, {
91112provider: "zai",
92113api: "openai-completions",
93114baseUrl: "https://api.z.ai/api/paas/v4",
@@ -129,15 +150,14 @@ describe("zai provider plugin", () => {
129150const provider = await registerSingleProviderPlugin(plugin);
130151const template = createGlm47Template();
131152132-expect(
133-provider.resolveDynamicModel?.({
134-provider: "zai",
135-modelId: "glm-5-turbo",
136-modelRegistry: {
137-find: (_provider: string, modelId: string) => (modelId === "glm-4.7" ? template : null),
138-},
139-} as never),
140-).toMatchObject({
153+const resolved = provider.resolveDynamicModel?.({
154+provider: "zai",
155+modelId: "glm-5-turbo",
156+modelRegistry: {
157+find: (_provider: string, modelId: string) => (modelId === "glm-4.7" ? template : null),
158+},
159+} as never) as Record<string, unknown> | undefined;
160+expectModelFields(resolved, {
141161id: "glm-5-turbo",
142162name: "GLM-5 Turbo",
143163provider: "zai",
@@ -175,9 +195,7 @@ describe("zai provider plugin", () => {
175195{},
176196);
177197178-expect(capturedPayload).toMatchObject({
179-tool_stream: true,
180-});
198+expect(capturedPayload?.tool_stream).toBe(true);
181199182200const disabledWrapped = provider.wrapStreamFn?.({
183201provider: "zai",
@@ -227,10 +245,8 @@ describe("zai provider plugin", () => {
227245{},
228246);
229247230-expect(capturedPayload).toMatchObject({
231-tool_stream: true,
232-thinking: { type: "disabled" },
233-});
248+expect(capturedPayload?.tool_stream).toBe(true);
249+expect(capturedPayload?.thinking).toEqual({ type: "disabled" });
234250});
235251236252it("enables Z.AI preserved thinking only when requested", async () => {
@@ -261,7 +277,7 @@ describe("zai provider plugin", () => {
261277{},
262278);
263279264-expect(capturedPayload).toMatchObject({ tool_stream: true });
280+expect(capturedPayload?.tool_stream).toBe(true);
265281expect(capturedPayload).not.toHaveProperty("thinking");
266282267283const wrappedWithPreserve = provider.wrapStreamFn?.({
@@ -282,10 +298,8 @@ describe("zai provider plugin", () => {
282298{},
283299);
284300285-expect(capturedPayload).toMatchObject({
286-tool_stream: true,
287-thinking: { type: "enabled", clear_thinking: false },
288-});
301+expect(capturedPayload?.tool_stream).toBe(true);
302+expect(capturedPayload?.thinking).toEqual({ type: "enabled", clear_thinking: false });
289303});
290304291305it("preserves replayed reasoning_content for Z.AI preserved thinking", async () => {
@@ -352,14 +366,11 @@ describe("zai provider plugin", () => {
352366353367void wrapped?.(model, context, {});
354368355-expect(capturedPayload).toMatchObject({
356-thinking: { type: "enabled", clear_thinking: false },
357-});
358-expect((capturedPayload?.messages as Array<Record<string, unknown>>)[1]).toMatchObject({
359-role: "assistant",
360-content: "visible reply",
361-reasoning_content: "prior reasoning",
362-});
369+expect(capturedPayload?.thinking).toEqual({ type: "enabled", clear_thinking: false });
370+const assistantMessage = (capturedPayload?.messages as Array<Record<string, unknown>>)[1];
371+expect(assistantMessage?.role).toBe("assistant");
372+expect(assistantMessage?.content).toBe("visible reply");
373+expect(assistantMessage?.reasoning_content).toBe("prior reasoning");
363374});
364375365376it("defaults tool_stream extra params but preserves explicit values", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。