@ai-sdk/zai 0.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # @ai-sdk/zai
2
+
3
+ ## 3.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [3e125ba]
8
+ - @ai-sdk/provider-utils@5.0.32
9
+ - @ai-sdk/openai-compatible@3.0.39
10
+
11
+ ## 3.0.0
12
+
13
+ ### Major Changes
14
+
15
+ - b580642: feat(zai): add the Z.AI provider with GLM chat completions, streaming, reasoning, tools, and multimodal inputs
16
+
17
+ ### Patch Changes
18
+
19
+ - 81bebaf: Add GLM-5.3-Flash model support to the Z.AI provider and AI Gateway.
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2023 Vercel, Inc.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md CHANGED
@@ -1,5 +1,47 @@
1
- # @ai-sdk/zai
1
+ # AI SDK - Z.AI Provider
2
2
 
3
- AI SDK provider for Z.ai.
3
+ The **Z.AI provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [Z.AI](https://z.ai/) GLM models.
4
4
 
5
- The implementation is maintained in the `vercel/ai` repository.
5
+ > **Deploying to Vercel?** With Vercel's AI Gateway you can access Z.AI (and hundreds of models from other providers) without installing an additional provider package. [Get started with AI Gateway](https://vercel.com/ai-gateway).
6
+
7
+ ## Setup
8
+
9
+ Install the Z.AI provider with:
10
+
11
+ ```bash
12
+ npm i @ai-sdk/zai
13
+ ```
14
+
15
+ ## Provider Instance
16
+
17
+ Import the default provider instance from `@ai-sdk/zai`:
18
+
19
+ ```ts
20
+ import { zai } from '@ai-sdk/zai';
21
+ ```
22
+
23
+ The provider reads the API key from `ZAI_API_KEY` by default. To configure it explicitly, use `createZai`:
24
+
25
+ ```ts
26
+ import { createZai } from '@ai-sdk/zai';
27
+
28
+ const zai = createZai({
29
+ apiKey: process.env.ZAI_API_KEY,
30
+ });
31
+ ```
32
+
33
+ ## Language Models
34
+
35
+ ```ts
36
+ import { zai } from '@ai-sdk/zai';
37
+ import { generateText } from 'ai';
38
+
39
+ const { text } = await generateText({
40
+ model: zai('glm-5.3'),
41
+ prompt: 'Explain why the sky is blue.',
42
+ });
43
+
44
+ console.log(text);
45
+ ```
46
+
47
+ The provider supports streaming, reasoning, function tools, JSON object output, and URL-based image and video input on compatible GLM models.
@@ -0,0 +1,88 @@
1
+ import { z } from 'zod/v4';
2
+ import { ProviderV4, LanguageModelV4 } from '@ai-sdk/provider';
3
+ import { FetchFunction } from '@ai-sdk/provider-utils';
4
+
5
+ declare const zaiLanguageModelChatOptions: z.ZodObject<{
6
+ doSample: z.ZodOptional<z.ZodBoolean>;
7
+ thinking: z.ZodOptional<z.ZodObject<{
8
+ type: z.ZodOptional<z.ZodEnum<{
9
+ enabled: "enabled";
10
+ disabled: "disabled";
11
+ }>>;
12
+ clearThinking: z.ZodOptional<z.ZodBoolean>;
13
+ }, z.core.$strip>>;
14
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
15
+ none: "none";
16
+ minimal: "minimal";
17
+ low: "low";
18
+ medium: "medium";
19
+ high: "high";
20
+ xhigh: "xhigh";
21
+ max: "max";
22
+ }>>;
23
+ toolStream: z.ZodOptional<z.ZodBoolean>;
24
+ requestId: z.ZodOptional<z.ZodString>;
25
+ userId: z.ZodOptional<z.ZodString>;
26
+ }, z.core.$strip>;
27
+ type ZaiLanguageModelChatOptions = z.infer<typeof zaiLanguageModelChatOptions>;
28
+
29
+ /**
30
+ * Z.AI chat model ids from the official OpenAPI 1.0.0 specification,
31
+ * retrieved from https://docs.z.ai/openapi.json on 2026-08-26.
32
+ */
33
+ type ZaiChatModelId = 'glm-5.3' | 'glm-5.2' | 'glm-5.1' | 'glm-5-turbo' | 'glm-5' | 'glm-4.7' | 'glm-4.7-flash' | 'glm-4.7-flashx' | 'glm-4.6' | 'glm-4.5' | 'glm-4.5-air' | 'glm-4.5-x' | 'glm-4.5-airx' | 'glm-4.5-flash' | 'glm-4-32b-0414-128k' | 'glm-5.3-flash' | 'glm-5v-turbo' | 'glm-4.6v' | 'glm-4.6v-flash' | 'glm-4.6v-flashx' | 'glm-4.5v' | 'autoglm-phone-multilingual' | (string & {});
34
+
35
+ declare const zaiErrorSchema: z.ZodUnion<readonly [z.ZodObject<{
36
+ code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
37
+ message: z.ZodString;
38
+ }, z.core.$strip>, z.ZodObject<{
39
+ error: z.ZodObject<{
40
+ code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
41
+ message: z.ZodString;
42
+ }, z.core.$strip>;
43
+ }, z.core.$strip>]>;
44
+ type ZaiErrorData = z.infer<typeof zaiErrorSchema>;
45
+
46
+ interface ZaiProviderSettings {
47
+ /**
48
+ * Z.AI API key. Defaults to the `ZAI_API_KEY` environment variable.
49
+ */
50
+ apiKey?: string;
51
+ /**
52
+ * Base URL for API calls. Defaults to
53
+ * `https://api.z.ai/api/paas/v4`.
54
+ */
55
+ baseURL?: string;
56
+ /**
57
+ * Custom headers to include in requests.
58
+ */
59
+ headers?: Record<string, string>;
60
+ /**
61
+ * Custom fetch implementation.
62
+ */
63
+ fetch?: FetchFunction;
64
+ }
65
+ interface ZaiProvider extends ProviderV4 {
66
+ /**
67
+ * Creates a Z.AI chat model for text generation.
68
+ */
69
+ (modelId: ZaiChatModelId): LanguageModelV4;
70
+ /**
71
+ * Creates a Z.AI language model.
72
+ */
73
+ languageModel(modelId: ZaiChatModelId): LanguageModelV4;
74
+ /**
75
+ * Creates a Z.AI chat model.
76
+ */
77
+ chat(modelId: ZaiChatModelId): LanguageModelV4;
78
+ /**
79
+ * @deprecated Use `embeddingModel` instead.
80
+ */
81
+ textEmbeddingModel(modelId: string): never;
82
+ }
83
+ declare function createZai(options?: ZaiProviderSettings): ZaiProvider;
84
+ declare const zai: ZaiProvider;
85
+
86
+ declare const VERSION: string;
87
+
88
+ export { VERSION, type ZaiChatModelId, type ZaiErrorData, type ZaiLanguageModelChatOptions, type ZaiProvider, type ZaiProviderSettings, createZai, zai };
package/dist/index.js ADDED
@@ -0,0 +1,265 @@
1
+ // src/zai-provider.ts
2
+ import {
3
+ NoSuchModelError
4
+ } from "@ai-sdk/provider";
5
+ import {
6
+ loadApiKey,
7
+ withoutTrailingSlash,
8
+ withUserAgentSuffix
9
+ } from "@ai-sdk/provider-utils";
10
+
11
+ // src/version.ts
12
+ var VERSION = true ? "3.0.1" : "0.0.0-test";
13
+
14
+ // src/zai-chat-language-model.ts
15
+ import { OpenAICompatibleChatLanguageModel } from "@ai-sdk/openai-compatible";
16
+ import {
17
+ parseProviderOptions,
18
+ serializeModelOptions,
19
+ WORKFLOW_DESERIALIZE,
20
+ WORKFLOW_SERIALIZE
21
+ } from "@ai-sdk/provider-utils";
22
+
23
+ // src/zai-chat-language-model-options.ts
24
+ import { z } from "zod/v4";
25
+ var zaiLanguageModelChatOptions = z.object({
26
+ /**
27
+ * Enables or disables sampling. When disabled, temperature and topP do not
28
+ * take effect.
29
+ */
30
+ doSample: z.boolean().optional(),
31
+ /**
32
+ * Controls model thinking and whether reasoning from earlier turns is kept.
33
+ */
34
+ thinking: z.object({
35
+ type: z.enum(["enabled", "disabled"]).optional(),
36
+ clearThinking: z.boolean().optional()
37
+ }).optional(),
38
+ /**
39
+ * Controls reasoning effort for GLM-5.2 and later models.
40
+ */
41
+ reasoningEffort: z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional(),
42
+ /**
43
+ * Enables incremental function-call argument streaming on supported models.
44
+ */
45
+ toolStream: z.boolean().optional(),
46
+ /**
47
+ * A caller-provided request identifier between 6 and 64 characters.
48
+ */
49
+ requestId: z.string().min(6).max(64).optional(),
50
+ /**
51
+ * A non-sensitive end-user identifier between 6 and 128 characters.
52
+ */
53
+ userId: z.string().min(6).max(128).optional()
54
+ });
55
+
56
+ // src/zai-error.ts
57
+ import { z as z2 } from "zod/v4";
58
+ var zaiErrorDetailsSchema = z2.object({
59
+ code: z2.union([z2.number(), z2.string()]).nullish(),
60
+ message: z2.string()
61
+ });
62
+ var zaiErrorSchema = z2.union([
63
+ zaiErrorDetailsSchema,
64
+ z2.object({ error: zaiErrorDetailsSchema })
65
+ ]);
66
+ var zaiErrorStructure = {
67
+ errorSchema: zaiErrorSchema,
68
+ errorToMessage: (data) => "error" in data ? data.error.message : data.message
69
+ };
70
+
71
+ // src/zai-chat-language-model.ts
72
+ function transformZaiRequestBody(args) {
73
+ const {
74
+ doSample,
75
+ frequency_penalty: _frequencyPenalty,
76
+ presence_penalty: _presencePenalty,
77
+ requestId,
78
+ seed: _seed,
79
+ thinking,
80
+ toolStream,
81
+ user: _user,
82
+ userId,
83
+ verbosity: _verbosity,
84
+ ...restArgs
85
+ } = args;
86
+ return {
87
+ ...restArgs,
88
+ ...doSample !== void 0 && { do_sample: doSample },
89
+ ...thinking !== void 0 && {
90
+ thinking: {
91
+ ...thinking.type !== void 0 && { type: thinking.type },
92
+ ...thinking.clearThinking !== void 0 && {
93
+ clear_thinking: thinking.clearThinking
94
+ }
95
+ }
96
+ },
97
+ ...toolStream !== void 0 && { tool_stream: toolStream },
98
+ ...requestId !== void 0 && { request_id: requestId },
99
+ ...userId !== void 0 && { user_id: userId }
100
+ };
101
+ }
102
+ function mapZaiFinishReason(finishReason) {
103
+ switch (finishReason.raw) {
104
+ case "sensitive":
105
+ return { unified: "content-filter", raw: finishReason.raw };
106
+ case "model_context_window_exceeded":
107
+ return { unified: "length", raw: finishReason.raw };
108
+ case "network_error":
109
+ return { unified: "error", raw: finishReason.raw };
110
+ default:
111
+ return finishReason;
112
+ }
113
+ }
114
+ var ZaiChatLanguageModel = class _ZaiChatLanguageModel extends OpenAICompatibleChatLanguageModel {
115
+ static [WORKFLOW_SERIALIZE](model) {
116
+ return serializeModelOptions({
117
+ modelId: model.modelId,
118
+ config: model.zaiConfig
119
+ });
120
+ }
121
+ static [WORKFLOW_DESERIALIZE](options) {
122
+ return new _ZaiChatLanguageModel(
123
+ options.modelId,
124
+ options.config
125
+ );
126
+ }
127
+ constructor(modelId, config) {
128
+ const headers = config.headers;
129
+ super(modelId, {
130
+ provider: config.provider,
131
+ url: ({ path }) => `${config.baseURL}${path}`,
132
+ headers: headers == null ? void 0 : () => typeof headers === "function" ? headers() : headers,
133
+ fetch: config.fetch,
134
+ errorStructure: zaiErrorStructure,
135
+ transformRequestBody: transformZaiRequestBody,
136
+ supportedUrls: () => ({
137
+ "image/*": [/^https?:\/\//],
138
+ "video/*": [/^https?:\/\//]
139
+ })
140
+ });
141
+ this.zaiConfig = config;
142
+ }
143
+ async prepareCallOptions(options) {
144
+ const warnings = [];
145
+ const zaiOptions = await parseProviderOptions({
146
+ provider: "zai",
147
+ providerOptions: options.providerOptions,
148
+ schema: zaiLanguageModelChatOptions
149
+ });
150
+ if (options.frequencyPenalty != null) {
151
+ warnings.push({ type: "unsupported", feature: "frequencyPenalty" });
152
+ }
153
+ if (options.presencePenalty != null) {
154
+ warnings.push({ type: "unsupported", feature: "presencePenalty" });
155
+ }
156
+ if (options.seed != null) {
157
+ warnings.push({ type: "unsupported", feature: "seed" });
158
+ }
159
+ let tools = options.tools;
160
+ let toolChoice = options.toolChoice;
161
+ if ((toolChoice == null ? void 0 : toolChoice.type) === "none") {
162
+ tools = void 0;
163
+ toolChoice = void 0;
164
+ } else if (toolChoice != null && toolChoice.type !== "auto") {
165
+ warnings.push({
166
+ type: "unsupported",
167
+ feature: `toolChoice ${toolChoice.type}`,
168
+ details: "Z.AI currently supports only automatic tool selection."
169
+ });
170
+ toolChoice = void 0;
171
+ }
172
+ const normalizedOptions = {
173
+ ...options,
174
+ frequencyPenalty: void 0,
175
+ presencePenalty: void 0,
176
+ seed: void 0,
177
+ tools,
178
+ toolChoice,
179
+ providerOptions: zaiOptions == null ? options.providerOptions : {
180
+ ...options.providerOptions,
181
+ zai: zaiOptions
182
+ }
183
+ };
184
+ return { normalizedOptions, warnings };
185
+ }
186
+ async doGenerate(options) {
187
+ const { normalizedOptions, warnings } = await this.prepareCallOptions(options);
188
+ const result = await super.doGenerate(normalizedOptions);
189
+ return {
190
+ ...result,
191
+ finishReason: mapZaiFinishReason(result.finishReason),
192
+ warnings: [...result.warnings, ...warnings]
193
+ };
194
+ }
195
+ async doStream(options) {
196
+ const { normalizedOptions, warnings } = await this.prepareCallOptions(options);
197
+ const result = await super.doStream(normalizedOptions);
198
+ return {
199
+ ...result,
200
+ stream: result.stream.pipeThrough(
201
+ new TransformStream({
202
+ transform(part, controller) {
203
+ if (part.type === "stream-start") {
204
+ controller.enqueue({
205
+ ...part,
206
+ warnings: [...part.warnings, ...warnings]
207
+ });
208
+ return;
209
+ }
210
+ if (part.type === "finish") {
211
+ controller.enqueue({
212
+ ...part,
213
+ finishReason: mapZaiFinishReason(part.finishReason)
214
+ });
215
+ return;
216
+ }
217
+ controller.enqueue(part);
218
+ }
219
+ })
220
+ )
221
+ };
222
+ }
223
+ };
224
+
225
+ // src/zai-provider.ts
226
+ function createZai(options = {}) {
227
+ var _a;
228
+ const baseURL = (_a = withoutTrailingSlash(options.baseURL)) != null ? _a : "https://api.z.ai/api/paas/v4";
229
+ const getHeaders = () => withUserAgentSuffix(
230
+ {
231
+ Authorization: `Bearer ${loadApiKey({
232
+ apiKey: options.apiKey,
233
+ environmentVariableName: "ZAI_API_KEY",
234
+ description: "Z.AI API key"
235
+ })}`,
236
+ ...options.headers
237
+ },
238
+ `ai-sdk/zai/${VERSION}`
239
+ );
240
+ const createLanguageModel = (modelId) => new ZaiChatLanguageModel(modelId, {
241
+ provider: "zai.chat",
242
+ baseURL,
243
+ headers: getHeaders,
244
+ fetch: options.fetch
245
+ });
246
+ const provider = (modelId) => createLanguageModel(modelId);
247
+ provider.specificationVersion = "v4";
248
+ provider.languageModel = createLanguageModel;
249
+ provider.chat = createLanguageModel;
250
+ provider.embeddingModel = (modelId) => {
251
+ throw new NoSuchModelError({ modelId, modelType: "embeddingModel" });
252
+ };
253
+ provider.textEmbeddingModel = provider.embeddingModel;
254
+ provider.imageModel = (modelId) => {
255
+ throw new NoSuchModelError({ modelId, modelType: "imageModel" });
256
+ };
257
+ return provider;
258
+ }
259
+ var zai = createZai();
260
+ export {
261
+ VERSION,
262
+ createZai,
263
+ zai
264
+ };
265
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/zai-provider.ts","../src/version.ts","../src/zai-chat-language-model.ts","../src/zai-chat-language-model-options.ts","../src/zai-error.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type LanguageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { VERSION } from './version';\nimport { ZaiChatLanguageModel } from './zai-chat-language-model';\nimport type { ZaiChatModelId } from './zai-chat-options';\n\nexport interface ZaiProviderSettings {\n /**\n * Z.AI API key. Defaults to the `ZAI_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Base URL for API calls. Defaults to\n * `https://api.z.ai/api/paas/v4`.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation.\n */\n fetch?: FetchFunction;\n}\n\nexport interface ZaiProvider extends ProviderV4 {\n /**\n * Creates a Z.AI chat model for text generation.\n */\n (modelId: ZaiChatModelId): LanguageModelV4;\n\n /**\n * Creates a Z.AI language model.\n */\n languageModel(modelId: ZaiChatModelId): LanguageModelV4;\n\n /**\n * Creates a Z.AI chat model.\n */\n chat(modelId: ZaiChatModelId): LanguageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nexport function createZai(options: ZaiProviderSettings = {}): ZaiProvider {\n const baseURL =\n withoutTrailingSlash(options.baseURL) ?? 'https://api.z.ai/api/paas/v4';\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'ZAI_API_KEY',\n description: 'Z.AI API key',\n })}`,\n ...options.headers,\n },\n `ai-sdk/zai/${VERSION}`,\n );\n\n const createLanguageModel = (modelId: ZaiChatModelId) =>\n new ZaiChatLanguageModel(modelId, {\n provider: 'zai.chat',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = (modelId: ZaiChatModelId) => createLanguageModel(modelId);\n\n provider.specificationVersion = 'v4' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n\n return provider;\n}\n\nexport const zai = createZai();\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';\nimport type {\n LanguageModelV4,\n LanguageModelV4CallOptions,\n LanguageModelV4FinishReason,\n LanguageModelV4GenerateResult,\n LanguageModelV4StreamPart,\n LanguageModelV4StreamResult,\n SharedV4Warning,\n} from '@ai-sdk/provider';\nimport {\n parseProviderOptions,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport type { ZaiChatModelId } from './zai-chat-options';\nimport { zaiLanguageModelChatOptions } from './zai-chat-language-model-options';\nimport { zaiErrorStructure } from './zai-error';\n\ntype OpenAICompatibleChatConfig = ConstructorParameters<\n typeof OpenAICompatibleChatLanguageModel\n>[1];\n\nexport type ZaiChatConfig = {\n provider: string;\n baseURL: string;\n headers?:\n | Record<string, string | undefined>\n | (() => Record<string, string | undefined>);\n fetch?: FetchFunction;\n};\n\nfunction transformZaiRequestBody(\n args: Record<string, any>,\n): Record<string, any> {\n const {\n doSample,\n frequency_penalty: _frequencyPenalty,\n presence_penalty: _presencePenalty,\n requestId,\n seed: _seed,\n thinking,\n toolStream,\n user: _user,\n userId,\n verbosity: _verbosity,\n ...restArgs\n } = args;\n\n return {\n ...restArgs,\n ...(doSample !== undefined && { do_sample: doSample }),\n ...(thinking !== undefined && {\n thinking: {\n ...(thinking.type !== undefined && { type: thinking.type }),\n ...(thinking.clearThinking !== undefined && {\n clear_thinking: thinking.clearThinking,\n }),\n },\n }),\n ...(toolStream !== undefined && { tool_stream: toolStream }),\n ...(requestId !== undefined && { request_id: requestId }),\n ...(userId !== undefined && { user_id: userId }),\n };\n}\n\nfunction mapZaiFinishReason(\n finishReason: LanguageModelV4FinishReason,\n): LanguageModelV4FinishReason {\n switch (finishReason.raw) {\n case 'sensitive':\n return { unified: 'content-filter', raw: finishReason.raw };\n case 'model_context_window_exceeded':\n return { unified: 'length', raw: finishReason.raw };\n case 'network_error':\n return { unified: 'error', raw: finishReason.raw };\n default:\n return finishReason;\n }\n}\n\nexport class ZaiChatLanguageModel\n extends OpenAICompatibleChatLanguageModel\n implements LanguageModelV4\n{\n private readonly zaiConfig: ZaiChatConfig;\n\n static [WORKFLOW_SERIALIZE](model: ZaiChatLanguageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.zaiConfig,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: string;\n config: OpenAICompatibleChatConfig;\n }) {\n return new ZaiChatLanguageModel(\n options.modelId,\n options.config as unknown as ZaiChatConfig,\n );\n }\n\n constructor(modelId: ZaiChatModelId, config: ZaiChatConfig) {\n const headers = config.headers;\n\n super(modelId, {\n provider: config.provider,\n url: ({ path }) => `${config.baseURL}${path}`,\n headers:\n headers == null\n ? undefined\n : () => (typeof headers === 'function' ? headers() : headers),\n fetch: config.fetch,\n errorStructure: zaiErrorStructure,\n transformRequestBody: transformZaiRequestBody,\n supportedUrls: () => ({\n 'image/*': [/^https?:\\/\\//],\n 'video/*': [/^https?:\\/\\//],\n }),\n });\n\n this.zaiConfig = config;\n }\n\n private async prepareCallOptions(options: LanguageModelV4CallOptions) {\n const warnings: SharedV4Warning[] = [];\n\n const zaiOptions = await parseProviderOptions({\n provider: 'zai',\n providerOptions: options.providerOptions,\n schema: zaiLanguageModelChatOptions,\n });\n\n if (options.frequencyPenalty != null) {\n warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' });\n }\n if (options.presencePenalty != null) {\n warnings.push({ type: 'unsupported', feature: 'presencePenalty' });\n }\n if (options.seed != null) {\n warnings.push({ type: 'unsupported', feature: 'seed' });\n }\n\n let tools = options.tools;\n let toolChoice = options.toolChoice;\n\n if (toolChoice?.type === 'none') {\n tools = undefined;\n toolChoice = undefined;\n } else if (toolChoice != null && toolChoice.type !== 'auto') {\n warnings.push({\n type: 'unsupported',\n feature: `toolChoice ${toolChoice.type}`,\n details: 'Z.AI currently supports only automatic tool selection.',\n });\n toolChoice = undefined;\n }\n\n const normalizedOptions: LanguageModelV4CallOptions = {\n ...options,\n frequencyPenalty: undefined,\n presencePenalty: undefined,\n seed: undefined,\n tools,\n toolChoice,\n providerOptions:\n zaiOptions == null\n ? options.providerOptions\n : {\n ...options.providerOptions,\n zai: zaiOptions,\n },\n };\n\n return { normalizedOptions, warnings };\n }\n\n async doGenerate(\n options: LanguageModelV4CallOptions,\n ): Promise<LanguageModelV4GenerateResult> {\n const { normalizedOptions, warnings } =\n await this.prepareCallOptions(options);\n const result = await super.doGenerate(normalizedOptions);\n\n return {\n ...result,\n finishReason: mapZaiFinishReason(result.finishReason),\n warnings: [...result.warnings, ...warnings],\n };\n }\n\n async doStream(\n options: LanguageModelV4CallOptions,\n ): Promise<LanguageModelV4StreamResult> {\n const { normalizedOptions, warnings } =\n await this.prepareCallOptions(options);\n const result = await super.doStream(normalizedOptions);\n\n return {\n ...result,\n stream: result.stream.pipeThrough(\n new TransformStream<\n LanguageModelV4StreamPart,\n LanguageModelV4StreamPart\n >({\n transform(part, controller) {\n if (part.type === 'stream-start') {\n controller.enqueue({\n ...part,\n warnings: [...part.warnings, ...warnings],\n });\n return;\n }\n\n if (part.type === 'finish') {\n controller.enqueue({\n ...part,\n finishReason: mapZaiFinishReason(part.finishReason),\n });\n return;\n }\n\n controller.enqueue(part);\n },\n }),\n ),\n };\n }\n}\n","import { z } from 'zod/v4';\n\nexport const zaiLanguageModelChatOptions = z.object({\n /**\n * Enables or disables sampling. When disabled, temperature and topP do not\n * take effect.\n */\n doSample: z.boolean().optional(),\n\n /**\n * Controls model thinking and whether reasoning from earlier turns is kept.\n */\n thinking: z\n .object({\n type: z.enum(['enabled', 'disabled']).optional(),\n clearThinking: z.boolean().optional(),\n })\n .optional(),\n\n /**\n * Controls reasoning effort for GLM-5.2 and later models.\n */\n reasoningEffort: z\n .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])\n .optional(),\n\n /**\n * Enables incremental function-call argument streaming on supported models.\n */\n toolStream: z.boolean().optional(),\n\n /**\n * A caller-provided request identifier between 6 and 64 characters.\n */\n requestId: z.string().min(6).max(64).optional(),\n\n /**\n * A non-sensitive end-user identifier between 6 and 128 characters.\n */\n userId: z.string().min(6).max(128).optional(),\n});\n\nexport type ZaiLanguageModelChatOptions = z.infer<\n typeof zaiLanguageModelChatOptions\n>;\n","import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';\nimport { z } from 'zod/v4';\n\nconst zaiErrorDetailsSchema = z.object({\n code: z.union([z.number(), z.string()]).nullish(),\n message: z.string(),\n});\n\nconst zaiErrorSchema = z.union([\n zaiErrorDetailsSchema,\n z.object({ error: zaiErrorDetailsSchema }),\n]);\n\nexport type ZaiErrorData = z.infer<typeof zaiErrorSchema>;\n\nexport const zaiErrorStructure: ProviderErrorStructure<ZaiErrorData> = {\n errorSchema: zaiErrorSchema,\n errorToMessage: data => ('error' in data ? data.error.message : data.message),\n};\n"],"mappings":"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","names":["z"]}
@@ -0,0 +1,159 @@
1
+ ---
2
+ title: Z.AI
3
+ description: Learn how to use Z.AI's GLM models with the AI SDK.
4
+ ---
5
+
6
+ # Z.AI Provider
7
+
8
+ The [Z.AI](https://z.ai/) provider gives you access to GLM language and vision models through the Z.AI API.
9
+
10
+ API keys can be created in the [Z.AI API key console](https://z.ai/manage-apikey/apikey-list).
11
+
12
+ ## Setup
13
+
14
+ The Z.AI provider is available through the `@ai-sdk/zai` package. Install it with:
15
+
16
+ <InstallPackages packages="@ai-sdk/zai" />
17
+
18
+ Set the `ZAI_API_KEY` environment variable:
19
+
20
+ ```bash
21
+ ZAI_API_KEY=your-api-key
22
+ ```
23
+
24
+ ## Provider Instance
25
+
26
+ Import the default provider instance `zai` from `@ai-sdk/zai`:
27
+
28
+ ```ts
29
+ import { zai } from '@ai-sdk/zai';
30
+ ```
31
+
32
+ For custom configuration, use `createZai`:
33
+
34
+ ```ts
35
+ import { createZai } from '@ai-sdk/zai';
36
+
37
+ const zai = createZai({
38
+ apiKey: process.env.ZAI_API_KEY,
39
+ baseURL: 'https://api.z.ai/api/paas/v4',
40
+ });
41
+ ```
42
+
43
+ The provider accepts these optional settings:
44
+
45
+ - **apiKey** _string_
46
+
47
+ API key sent in the `Authorization` header. It defaults to the `ZAI_API_KEY` environment variable.
48
+
49
+ - **baseURL** _string_
50
+
51
+ URL prefix for API requests. It defaults to `https://api.z.ai/api/paas/v4`.
52
+
53
+ - **headers** _Record&lt;string, string&gt;_
54
+
55
+ Additional request headers.
56
+
57
+ - **fetch** _FetchFunction_
58
+
59
+ Custom fetch implementation, for example to intercept requests in middleware.
60
+
61
+ ## Language Models
62
+
63
+ Create a language model by passing its model id to the provider:
64
+
65
+ ```ts
66
+ import { zai } from '@ai-sdk/zai';
67
+ import { generateText } from 'ai';
68
+
69
+ const { text } = await generateText({
70
+ model: zai('glm-5.3'),
71
+ prompt: 'Explain quantum entanglement in simple terms.',
72
+ });
73
+ ```
74
+
75
+ Current model families include GLM 5, GLM 4.7, GLM 4.6, GLM 4.5, and the GLM vision models. Model availability changes over time; see the [Z.AI model documentation](https://docs.z.ai/guides/llm) for the current catalog.
76
+
77
+ The provider supports:
78
+
79
+ - text generation and streaming
80
+ - reasoning output and reasoning history
81
+ - function calling, including incremental tool-call streaming
82
+ - JSON object output
83
+ - URL-based image and video inputs on compatible vision models
84
+
85
+ ## Provider Options
86
+
87
+ Z.AI-specific options can be passed through `providerOptions.zai`:
88
+
89
+ ```ts
90
+ import { zai } from '@ai-sdk/zai';
91
+ import { generateText } from 'ai';
92
+
93
+ const result = await generateText({
94
+ model: zai('glm-5.3'),
95
+ prompt: 'Compare two approaches to implementing a rate limiter.',
96
+ providerOptions: {
97
+ zai: {
98
+ thinking: { type: 'enabled', clearThinking: true },
99
+ reasoningEffort: 'high',
100
+ requestId: 'request-123456',
101
+ userId: 'user-123456',
102
+ },
103
+ },
104
+ });
105
+ ```
106
+
107
+ The following options are available:
108
+
109
+ - **doSample** _boolean_
110
+
111
+ Enables sampling. When disabled, `temperature` and `topP` do not take effect.
112
+
113
+ - **thinking** _object_
114
+
115
+ Controls thinking with `type: 'enabled' | 'disabled'`. Set `clearThinking` to `false` to retain reasoning from previous assistant messages.
116
+
117
+ - **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'_
118
+
119
+ Controls reasoning effort on supported models.
120
+
121
+ - **toolStream** _boolean_
122
+
123
+ Enables incremental function-call argument streaming on supported models.
124
+
125
+ - **requestId** _string_
126
+
127
+ A caller-provided request id between 6 and 64 characters.
128
+
129
+ - **userId** _string_
130
+
131
+ A non-sensitive end-user id between 6 and 128 characters.
132
+
133
+ ## Streaming Tool Calls
134
+
135
+ Enable `toolStream` when you want supported GLM models to stream function-call arguments incrementally:
136
+
137
+ ```ts
138
+ import { zai } from '@ai-sdk/zai';
139
+ import { streamText, tool } from 'ai';
140
+ import { z } from 'zod';
141
+
142
+ const result = streamText({
143
+ model: zai('glm-5.3'),
144
+ prompt: 'What is the weather in San Francisco?',
145
+ tools: {
146
+ weather: tool({
147
+ description: 'Get the weather for a city',
148
+ inputSchema: z.object({ city: z.string() }),
149
+ }),
150
+ },
151
+ providerOptions: {
152
+ zai: { toolStream: true },
153
+ },
154
+ });
155
+
156
+ for await (const part of result.fullStream) {
157
+ console.log(part);
158
+ }
159
+ ```
package/package.json CHANGED
@@ -1,23 +1,77 @@
1
1
  {
2
2
  "name": "@ai-sdk/zai",
3
- "version": "0.0.0",
4
- "description": "AI SDK provider for Z.ai",
5
- "license": "Apache-2.0",
3
+ "version": "3.0.1",
6
4
  "type": "module",
7
- "main": "./index.js",
8
- "exports": {
9
- ".": "./index.js"
10
- },
5
+ "license": "Apache-2.0",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
11
9
  "files": [
12
- "index.js",
10
+ "dist/**/*",
11
+ "docs/**/*",
12
+ "src",
13
+ "!src/**/*.test.ts",
14
+ "!src/**/*.test-d.ts",
15
+ "!src/**/__snapshots__",
16
+ "!src/**/__fixtures__",
17
+ "CHANGELOG.md",
13
18
  "README.md"
14
19
  ],
20
+ "directories": {
21
+ "doc": "./docs"
22
+ },
23
+ "exports": {
24
+ "./package.json": "./package.json",
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "dependencies": {
32
+ "@ai-sdk/openai-compatible": "3.0.39",
33
+ "@ai-sdk/provider": "4.0.8",
34
+ "@ai-sdk/provider-utils": "5.0.32"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "22.19.19",
38
+ "@vercel/ai-tsconfig": "0.0.0",
39
+ "tsup": "^8.5.1",
40
+ "typescript": "5.8.3",
41
+ "zod": "3.25.76"
42
+ },
43
+ "peerDependencies": {
44
+ "zod": "^3.25.76 || ^4.1.8"
45
+ },
46
+ "engines": {
47
+ "node": ">=22"
48
+ },
15
49
  "publishConfig": {
16
- "access": "public"
50
+ "access": "public",
51
+ "provenance": true
17
52
  },
53
+ "homepage": "https://ai-sdk.dev/docs",
18
54
  "repository": {
19
55
  "type": "git",
20
- "url": "git+https://github.com/vercel/ai.git",
56
+ "url": "https://github.com/vercel/ai",
21
57
  "directory": "packages/zai"
58
+ },
59
+ "bugs": {
60
+ "url": "https://github.com/vercel/ai/issues"
61
+ },
62
+ "keywords": [
63
+ "ai"
64
+ ],
65
+ "description": "The Z.AI provider for the AI SDK contains language model support for Z.AI's GLM models.",
66
+ "scripts": {
67
+ "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
68
+ "build:watch": "pnpm clean && tsup --watch",
69
+ "clean": "del-cli dist docs *.tsbuildinfo",
70
+ "type-check": "tsc --build",
71
+ "test": "pnpm test:node && pnpm test:edge",
72
+ "test:update": "pnpm test:node -u",
73
+ "test:watch": "vitest --config vitest.node.config.js",
74
+ "test:edge": "vitest --config vitest.edge.config.js --run",
75
+ "test:node": "vitest --config vitest.node.config.js --run"
22
76
  }
23
- }
77
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type { ZaiLanguageModelChatOptions } from './zai-chat-language-model-options';
2
+ export type { ZaiChatModelId } from './zai-chat-options';
3
+ export type { ZaiErrorData } from './zai-error';
4
+ export { createZai, zai } from './zai-provider';
5
+ export type { ZaiProvider, ZaiProviderSettings } from './zai-provider';
6
+ export { VERSION } from './version';
package/src/version.ts ADDED
@@ -0,0 +1,6 @@
1
+ // Version string of this package injected at build time.
2
+ declare const __PACKAGE_VERSION__: string | undefined;
3
+ export const VERSION: string =
4
+ typeof __PACKAGE_VERSION__ !== 'undefined'
5
+ ? __PACKAGE_VERSION__
6
+ : '0.0.0-test';
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod/v4';
2
+
3
+ export const zaiLanguageModelChatOptions = z.object({
4
+ /**
5
+ * Enables or disables sampling. When disabled, temperature and topP do not
6
+ * take effect.
7
+ */
8
+ doSample: z.boolean().optional(),
9
+
10
+ /**
11
+ * Controls model thinking and whether reasoning from earlier turns is kept.
12
+ */
13
+ thinking: z
14
+ .object({
15
+ type: z.enum(['enabled', 'disabled']).optional(),
16
+ clearThinking: z.boolean().optional(),
17
+ })
18
+ .optional(),
19
+
20
+ /**
21
+ * Controls reasoning effort for GLM-5.2 and later models.
22
+ */
23
+ reasoningEffort: z
24
+ .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])
25
+ .optional(),
26
+
27
+ /**
28
+ * Enables incremental function-call argument streaming on supported models.
29
+ */
30
+ toolStream: z.boolean().optional(),
31
+
32
+ /**
33
+ * A caller-provided request identifier between 6 and 64 characters.
34
+ */
35
+ requestId: z.string().min(6).max(64).optional(),
36
+
37
+ /**
38
+ * A non-sensitive end-user identifier between 6 and 128 characters.
39
+ */
40
+ userId: z.string().min(6).max(128).optional(),
41
+ });
42
+
43
+ export type ZaiLanguageModelChatOptions = z.infer<
44
+ typeof zaiLanguageModelChatOptions
45
+ >;
@@ -0,0 +1,233 @@
1
+ import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';
2
+ import type {
3
+ LanguageModelV4,
4
+ LanguageModelV4CallOptions,
5
+ LanguageModelV4FinishReason,
6
+ LanguageModelV4GenerateResult,
7
+ LanguageModelV4StreamPart,
8
+ LanguageModelV4StreamResult,
9
+ SharedV4Warning,
10
+ } from '@ai-sdk/provider';
11
+ import {
12
+ parseProviderOptions,
13
+ serializeModelOptions,
14
+ WORKFLOW_DESERIALIZE,
15
+ WORKFLOW_SERIALIZE,
16
+ type FetchFunction,
17
+ } from '@ai-sdk/provider-utils';
18
+ import type { ZaiChatModelId } from './zai-chat-options';
19
+ import { zaiLanguageModelChatOptions } from './zai-chat-language-model-options';
20
+ import { zaiErrorStructure } from './zai-error';
21
+
22
+ type OpenAICompatibleChatConfig = ConstructorParameters<
23
+ typeof OpenAICompatibleChatLanguageModel
24
+ >[1];
25
+
26
+ export type ZaiChatConfig = {
27
+ provider: string;
28
+ baseURL: string;
29
+ headers?:
30
+ | Record<string, string | undefined>
31
+ | (() => Record<string, string | undefined>);
32
+ fetch?: FetchFunction;
33
+ };
34
+
35
+ function transformZaiRequestBody(
36
+ args: Record<string, any>,
37
+ ): Record<string, any> {
38
+ const {
39
+ doSample,
40
+ frequency_penalty: _frequencyPenalty,
41
+ presence_penalty: _presencePenalty,
42
+ requestId,
43
+ seed: _seed,
44
+ thinking,
45
+ toolStream,
46
+ user: _user,
47
+ userId,
48
+ verbosity: _verbosity,
49
+ ...restArgs
50
+ } = args;
51
+
52
+ return {
53
+ ...restArgs,
54
+ ...(doSample !== undefined && { do_sample: doSample }),
55
+ ...(thinking !== undefined && {
56
+ thinking: {
57
+ ...(thinking.type !== undefined && { type: thinking.type }),
58
+ ...(thinking.clearThinking !== undefined && {
59
+ clear_thinking: thinking.clearThinking,
60
+ }),
61
+ },
62
+ }),
63
+ ...(toolStream !== undefined && { tool_stream: toolStream }),
64
+ ...(requestId !== undefined && { request_id: requestId }),
65
+ ...(userId !== undefined && { user_id: userId }),
66
+ };
67
+ }
68
+
69
+ function mapZaiFinishReason(
70
+ finishReason: LanguageModelV4FinishReason,
71
+ ): LanguageModelV4FinishReason {
72
+ switch (finishReason.raw) {
73
+ case 'sensitive':
74
+ return { unified: 'content-filter', raw: finishReason.raw };
75
+ case 'model_context_window_exceeded':
76
+ return { unified: 'length', raw: finishReason.raw };
77
+ case 'network_error':
78
+ return { unified: 'error', raw: finishReason.raw };
79
+ default:
80
+ return finishReason;
81
+ }
82
+ }
83
+
84
+ export class ZaiChatLanguageModel
85
+ extends OpenAICompatibleChatLanguageModel
86
+ implements LanguageModelV4
87
+ {
88
+ private readonly zaiConfig: ZaiChatConfig;
89
+
90
+ static [WORKFLOW_SERIALIZE](model: ZaiChatLanguageModel) {
91
+ return serializeModelOptions({
92
+ modelId: model.modelId,
93
+ config: model.zaiConfig,
94
+ });
95
+ }
96
+
97
+ static [WORKFLOW_DESERIALIZE](options: {
98
+ modelId: string;
99
+ config: OpenAICompatibleChatConfig;
100
+ }) {
101
+ return new ZaiChatLanguageModel(
102
+ options.modelId,
103
+ options.config as unknown as ZaiChatConfig,
104
+ );
105
+ }
106
+
107
+ constructor(modelId: ZaiChatModelId, config: ZaiChatConfig) {
108
+ const headers = config.headers;
109
+
110
+ super(modelId, {
111
+ provider: config.provider,
112
+ url: ({ path }) => `${config.baseURL}${path}`,
113
+ headers:
114
+ headers == null
115
+ ? undefined
116
+ : () => (typeof headers === 'function' ? headers() : headers),
117
+ fetch: config.fetch,
118
+ errorStructure: zaiErrorStructure,
119
+ transformRequestBody: transformZaiRequestBody,
120
+ supportedUrls: () => ({
121
+ 'image/*': [/^https?:\/\//],
122
+ 'video/*': [/^https?:\/\//],
123
+ }),
124
+ });
125
+
126
+ this.zaiConfig = config;
127
+ }
128
+
129
+ private async prepareCallOptions(options: LanguageModelV4CallOptions) {
130
+ const warnings: SharedV4Warning[] = [];
131
+
132
+ const zaiOptions = await parseProviderOptions({
133
+ provider: 'zai',
134
+ providerOptions: options.providerOptions,
135
+ schema: zaiLanguageModelChatOptions,
136
+ });
137
+
138
+ if (options.frequencyPenalty != null) {
139
+ warnings.push({ type: 'unsupported', feature: 'frequencyPenalty' });
140
+ }
141
+ if (options.presencePenalty != null) {
142
+ warnings.push({ type: 'unsupported', feature: 'presencePenalty' });
143
+ }
144
+ if (options.seed != null) {
145
+ warnings.push({ type: 'unsupported', feature: 'seed' });
146
+ }
147
+
148
+ let tools = options.tools;
149
+ let toolChoice = options.toolChoice;
150
+
151
+ if (toolChoice?.type === 'none') {
152
+ tools = undefined;
153
+ toolChoice = undefined;
154
+ } else if (toolChoice != null && toolChoice.type !== 'auto') {
155
+ warnings.push({
156
+ type: 'unsupported',
157
+ feature: `toolChoice ${toolChoice.type}`,
158
+ details: 'Z.AI currently supports only automatic tool selection.',
159
+ });
160
+ toolChoice = undefined;
161
+ }
162
+
163
+ const normalizedOptions: LanguageModelV4CallOptions = {
164
+ ...options,
165
+ frequencyPenalty: undefined,
166
+ presencePenalty: undefined,
167
+ seed: undefined,
168
+ tools,
169
+ toolChoice,
170
+ providerOptions:
171
+ zaiOptions == null
172
+ ? options.providerOptions
173
+ : {
174
+ ...options.providerOptions,
175
+ zai: zaiOptions,
176
+ },
177
+ };
178
+
179
+ return { normalizedOptions, warnings };
180
+ }
181
+
182
+ async doGenerate(
183
+ options: LanguageModelV4CallOptions,
184
+ ): Promise<LanguageModelV4GenerateResult> {
185
+ const { normalizedOptions, warnings } =
186
+ await this.prepareCallOptions(options);
187
+ const result = await super.doGenerate(normalizedOptions);
188
+
189
+ return {
190
+ ...result,
191
+ finishReason: mapZaiFinishReason(result.finishReason),
192
+ warnings: [...result.warnings, ...warnings],
193
+ };
194
+ }
195
+
196
+ async doStream(
197
+ options: LanguageModelV4CallOptions,
198
+ ): Promise<LanguageModelV4StreamResult> {
199
+ const { normalizedOptions, warnings } =
200
+ await this.prepareCallOptions(options);
201
+ const result = await super.doStream(normalizedOptions);
202
+
203
+ return {
204
+ ...result,
205
+ stream: result.stream.pipeThrough(
206
+ new TransformStream<
207
+ LanguageModelV4StreamPart,
208
+ LanguageModelV4StreamPart
209
+ >({
210
+ transform(part, controller) {
211
+ if (part.type === 'stream-start') {
212
+ controller.enqueue({
213
+ ...part,
214
+ warnings: [...part.warnings, ...warnings],
215
+ });
216
+ return;
217
+ }
218
+
219
+ if (part.type === 'finish') {
220
+ controller.enqueue({
221
+ ...part,
222
+ finishReason: mapZaiFinishReason(part.finishReason),
223
+ });
224
+ return;
225
+ }
226
+
227
+ controller.enqueue(part);
228
+ },
229
+ }),
230
+ ),
231
+ };
232
+ }
233
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Z.AI chat model ids from the official OpenAPI 1.0.0 specification,
3
+ * retrieved from https://docs.z.ai/openapi.json on 2026-08-26.
4
+ */
5
+ export type ZaiChatModelId =
6
+ | 'glm-5.3'
7
+ | 'glm-5.2'
8
+ | 'glm-5.1'
9
+ | 'glm-5-turbo'
10
+ | 'glm-5'
11
+ | 'glm-4.7'
12
+ | 'glm-4.7-flash'
13
+ | 'glm-4.7-flashx'
14
+ | 'glm-4.6'
15
+ | 'glm-4.5'
16
+ | 'glm-4.5-air'
17
+ | 'glm-4.5-x'
18
+ | 'glm-4.5-airx'
19
+ | 'glm-4.5-flash'
20
+ | 'glm-4-32b-0414-128k'
21
+ | 'glm-5.3-flash'
22
+ | 'glm-5v-turbo'
23
+ | 'glm-4.6v'
24
+ | 'glm-4.6v-flash'
25
+ | 'glm-4.6v-flashx'
26
+ | 'glm-4.5v'
27
+ | 'autoglm-phone-multilingual'
28
+ | (string & {});
@@ -0,0 +1,19 @@
1
+ import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';
2
+ import { z } from 'zod/v4';
3
+
4
+ const zaiErrorDetailsSchema = z.object({
5
+ code: z.union([z.number(), z.string()]).nullish(),
6
+ message: z.string(),
7
+ });
8
+
9
+ const zaiErrorSchema = z.union([
10
+ zaiErrorDetailsSchema,
11
+ z.object({ error: zaiErrorDetailsSchema }),
12
+ ]);
13
+
14
+ export type ZaiErrorData = z.infer<typeof zaiErrorSchema>;
15
+
16
+ export const zaiErrorStructure: ProviderErrorStructure<ZaiErrorData> = {
17
+ errorSchema: zaiErrorSchema,
18
+ errorToMessage: data => ('error' in data ? data.error.message : data.message),
19
+ };
@@ -0,0 +1,103 @@
1
+ import {
2
+ NoSuchModelError,
3
+ type LanguageModelV4,
4
+ type ProviderV4,
5
+ } from '@ai-sdk/provider';
6
+ import {
7
+ loadApiKey,
8
+ withoutTrailingSlash,
9
+ withUserAgentSuffix,
10
+ type FetchFunction,
11
+ } from '@ai-sdk/provider-utils';
12
+ import { VERSION } from './version';
13
+ import { ZaiChatLanguageModel } from './zai-chat-language-model';
14
+ import type { ZaiChatModelId } from './zai-chat-options';
15
+
16
+ export interface ZaiProviderSettings {
17
+ /**
18
+ * Z.AI API key. Defaults to the `ZAI_API_KEY` environment variable.
19
+ */
20
+ apiKey?: string;
21
+
22
+ /**
23
+ * Base URL for API calls. Defaults to
24
+ * `https://api.z.ai/api/paas/v4`.
25
+ */
26
+ baseURL?: string;
27
+
28
+ /**
29
+ * Custom headers to include in requests.
30
+ */
31
+ headers?: Record<string, string>;
32
+
33
+ /**
34
+ * Custom fetch implementation.
35
+ */
36
+ fetch?: FetchFunction;
37
+ }
38
+
39
+ export interface ZaiProvider extends ProviderV4 {
40
+ /**
41
+ * Creates a Z.AI chat model for text generation.
42
+ */
43
+ (modelId: ZaiChatModelId): LanguageModelV4;
44
+
45
+ /**
46
+ * Creates a Z.AI language model.
47
+ */
48
+ languageModel(modelId: ZaiChatModelId): LanguageModelV4;
49
+
50
+ /**
51
+ * Creates a Z.AI chat model.
52
+ */
53
+ chat(modelId: ZaiChatModelId): LanguageModelV4;
54
+
55
+ /**
56
+ * @deprecated Use `embeddingModel` instead.
57
+ */
58
+ textEmbeddingModel(modelId: string): never;
59
+ }
60
+
61
+ export function createZai(options: ZaiProviderSettings = {}): ZaiProvider {
62
+ const baseURL =
63
+ withoutTrailingSlash(options.baseURL) ?? 'https://api.z.ai/api/paas/v4';
64
+
65
+ const getHeaders = () =>
66
+ withUserAgentSuffix(
67
+ {
68
+ Authorization: `Bearer ${loadApiKey({
69
+ apiKey: options.apiKey,
70
+ environmentVariableName: 'ZAI_API_KEY',
71
+ description: 'Z.AI API key',
72
+ })}`,
73
+ ...options.headers,
74
+ },
75
+ `ai-sdk/zai/${VERSION}`,
76
+ );
77
+
78
+ const createLanguageModel = (modelId: ZaiChatModelId) =>
79
+ new ZaiChatLanguageModel(modelId, {
80
+ provider: 'zai.chat',
81
+ baseURL,
82
+ headers: getHeaders,
83
+ fetch: options.fetch,
84
+ });
85
+
86
+ const provider = (modelId: ZaiChatModelId) => createLanguageModel(modelId);
87
+
88
+ provider.specificationVersion = 'v4' as const;
89
+ provider.languageModel = createLanguageModel;
90
+ provider.chat = createLanguageModel;
91
+
92
+ provider.embeddingModel = (modelId: string) => {
93
+ throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' });
94
+ };
95
+ provider.textEmbeddingModel = provider.embeddingModel;
96
+ provider.imageModel = (modelId: string) => {
97
+ throw new NoSuchModelError({ modelId, modelType: 'imageModel' });
98
+ };
99
+
100
+ return provider;
101
+ }
102
+
103
+ export const zai = createZai();
package/index.js DELETED
@@ -1 +0,0 @@
1
- export {};