From e9c6d95e6b8e223898b3680113554ba5fda572e8 Mon Sep 17 00:00:00 2001 From: Anton Kuzmenko <1917237+default-anton@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:37:34 -0800 Subject: [PATCH] Migrate zai provider from Anthropic to OpenAI-compatible API - Change all zai models from anthropic-messages to openai-completions API - Update baseUrl from https://api.z.ai/api/anthropic to https://api.z.ai/api/coding/paas/v4 - Add compat setting to disable developer role for zai - Update zai provider tests to use OpenAI-style options (reasoningEffort instead of thinkingEnabled/thinkingBudgetTokens) - Enable previously disabled thinking and image input tests for zai models --- packages/ai/src/models.generated.ts | 49 ++++++++++++++++------------- packages/ai/test/stream.test.ts | 21 ++++++------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 579eab84..6cde070c 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -6978,9 +6978,10 @@ export const MODELS = { "glm-4.5": { id: "glm-4.5", name: "GLM-4.5", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text"], cost: { @@ -6991,13 +6992,14 @@ export const MODELS = { }, contextWindow: 131072, maxTokens: 98304, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.5-air": { id: "glm-4.5-air", name: "GLM-4.5-Air", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text"], cost: { @@ -7008,13 +7010,14 @@ export const MODELS = { }, contextWindow: 131072, maxTokens: 98304, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.5-flash": { id: "glm-4.5-flash", name: "GLM-4.5-Flash", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text"], cost: { @@ -7025,13 +7028,14 @@ export const MODELS = { }, contextWindow: 131072, maxTokens: 98304, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.5v": { id: "glm-4.5v", name: "GLM-4.5V", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text", "image"], cost: { @@ -7042,13 +7046,14 @@ export const MODELS = { }, contextWindow: 64000, maxTokens: 16384, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.6": { id: "glm-4.6", name: "GLM-4.6", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text"], cost: { @@ -7059,13 +7064,14 @@ export const MODELS = { }, contextWindow: 204800, maxTokens: 131072, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.6v": { id: "glm-4.6v", name: "GLM-4.6V", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text", "image"], cost: { @@ -7076,13 +7082,14 @@ export const MODELS = { }, contextWindow: 128000, maxTokens: 32768, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, "glm-4.7": { id: "glm-4.7", name: "GLM-4.7", - api: "anthropic-messages", + api: "openai-completions", provider: "zai", - baseUrl: "https://api.z.ai/api/anthropic", + baseUrl: "https://api.z.ai/api/coding/paas/v4", + compat: {"supportsDeveloperRole":false}, reasoning: true, input: ["text"], cost: { @@ -7093,6 +7100,6 @@ export const MODELS = { }, contextWindow: 204800, maxTokens: 131072, - } satisfies Model<"anthropic-messages">, + } satisfies Model<"openai-completions">, }, } as const; diff --git a/packages/ai/test/stream.test.ts b/packages/ai/test/stream.test.ts index 3da9b055..d5e22ac4 100644 --- a/packages/ai/test/stream.test.ts +++ b/packages/ai/test/stream.test.ts @@ -556,7 +556,7 @@ describe("Generate E2E Tests", () => { }); }); - describe.skipIf(!process.env.ZAI_API_KEY)("zAI Provider (glm-4.5-air via Anthropic Messages)", () => { + describe.skipIf(!process.env.ZAI_API_KEY)("zAI Provider (glm-4.5-air via OpenAI Completions)", () => { const llm = getModel("zai", "glm-4.5-air"); it("should complete basic text generation", { retry: 3 }, async () => { @@ -571,17 +571,16 @@ describe("Generate E2E Tests", () => { await handleStreaming(llm); }); - it("should handle thinking", { retry: 3 }, async () => { - // Prompt doesn't trigger thinking - // await handleThinking(llm, { thinkingEnabled: true, thinkingBudgetTokens: 2048 }); + it("should handle thinking mode", { retry: 3 }, async () => { + await handleThinking(llm, { reasoningEffort: "medium" }); }); it("should handle multi-turn with thinking and tools", { retry: 3 }, async () => { - await multiTurn(llm, { thinkingEnabled: true, thinkingBudgetTokens: 2048 }); + await multiTurn(llm, { reasoningEffort: "medium" }); }); }); - describe.skipIf(!process.env.ZAI_API_KEY)("zAI Provider (glm-4.5v via Anthropic Messages)", () => { + describe.skipIf(!process.env.ZAI_API_KEY)("zAI Provider (glm-4.5v via OpenAI Completions)", () => { const llm = getModel("zai", "glm-4.5v"); it("should complete basic text generation", { retry: 3 }, async () => { @@ -596,18 +595,16 @@ describe("Generate E2E Tests", () => { await handleStreaming(llm); }); - it("should handle thinking", { retry: 3 }, async () => { - // Prompt doesn't trigger thinking - // await handleThinking(llm, { thinkingEnabled: true, thinkingBudgetTokens: 2048 }); + it("should handle thinking mode", { retry: 3 }, async () => { + await handleThinking(llm, { reasoningEffort: "medium" }); }); it("should handle multi-turn with thinking and tools", { retry: 3 }, async () => { - await multiTurn(llm, { thinkingEnabled: true, thinkingBudgetTokens: 2048 }); + await multiTurn(llm, { reasoningEffort: "medium" }); }); it("should handle image input", { retry: 3 }, async () => { - // Can't see image for some reason? - // await handleImage(llm); + await handleImage(llm); }); });