@arnilo/prism-provider-zai 0.0.96 → 0.1.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 CHANGED
@@ -1,3 +1,116 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2026-08-09
4
+
5
+ ### Changed
6
+ - Released with exact 0.1.0 graph.
7
+
8
+ ## [0.0.28] - 2026-08-08
9
+
10
+ ### Changed
11
+ - Released with exact 0.0.28 graph.
12
+
13
+ ## [0.0.27] - 2026-08-07
14
+
15
+ ### Changed
16
+ - Released with exact 0.0.27 graph.
17
+
18
+ ## [0.0.26] - 2026-08-06
19
+
20
+ ### Changed
21
+ - Released with exact 0.0.26 graph.
22
+
23
+ ## [0.0.25] - 2026-08-06
24
+
25
+ ### Changed
26
+ - Released with exact 0.0.25 graph.
27
+
28
+ ## [0.0.24] - 2026-08-04
29
+
30
+ ### Added
31
+ - Durable `AgentEventSource` (memory + PostgreSQL LISTEN/NOTIFY), recoverable `ToolEffectStore`, and AG-UI MCP/MCP Apps/A2A fronting for Phase 7.
32
+
33
+ ### Changed
34
+ - Publishable graph remains **47** manifests at **0.0.24**; peers and lockfile move together.
35
+
36
+ See [migration guide](../../docs/migration.md) for the 0.0.23 → 0.0.24 notes.
37
+
38
+ ## [0.0.23] - 2026-08-03
39
+
40
+ ### Changed
41
+ - Released with exact 0.0.23 graph.
42
+
43
+ ## [0.0.22] - 2026-07-31
44
+
45
+ ### Changed
46
+ - Released with exact 0.0.22 graph.
47
+
48
+ ## [0.0.21] - 2026-07-31
49
+
50
+ ### Changed
51
+ - Released with exact 0.0.21 graph.
52
+
53
+ ## [0.0.20] - 2026-07-31
54
+
55
+ ### Changed
56
+ - Released with exact 0.0.20 graph.
57
+
58
+ ## [0.0.19] - 2026-07-30
59
+
60
+ ### Changed
61
+ - Released with exact 0.0.19 graph.
62
+
63
+ ## [0.0.18] - 2026-07-30
64
+
65
+ ### Changed
66
+ - Released with exact 0.0.18 graph.
67
+
68
+ ## [0.0.17] - 2026-07-29
69
+
70
+ ### Changed
71
+ - Released with exact 0.0.17 graph.
72
+
73
+ ## [0.0.16] - 2026-07-26
74
+
75
+ ### Changed
76
+ - Released with exact 0.0.16 graph.
77
+
78
+ ## [0.0.15] - 2026-07-26
79
+
80
+ ### Changed
81
+
82
+ - Released with exact 0.0.15 graph.
83
+
84
+ ## [0.0.14] - 2026-07-26
85
+
86
+ ### Changed
87
+
88
+ - Released with exact 0.0.14 graph.
89
+
90
+ ## [0.0.13] - 2026-07-24
91
+
92
+ ### Changed
93
+
94
+ - Released with exact 0.0.13 graph.
95
+
96
+ ## [0.0.12] - 2026-07-22
97
+
98
+ ### Changed
99
+
100
+ - Released with exact 0.0.12 graph.
101
+
102
+ ## [0.0.11] - 2026-07-22
103
+
104
+ ### Changed
105
+
106
+ - Released with exact 0.0.11 graph.
107
+
108
+ ## [0.0.10] - 2026-07-21
109
+
110
+ ### Changed
111
+
112
+ - Released with exact 0.0.10 graph.
113
+
1
114
  ## [0.0.96] - 2026-07-21
2
115
 
3
116
  ### Changed
@@ -12,7 +125,6 @@
12
125
 
13
126
  - Malformed streamed tool-call arguments yield recoverable tool calls via `toolCallFromArgumentsText` instead of throwing `ProviderTransportError` / terminal stream errors.
14
127
 
15
-
16
128
  ## [0.0.8] - 2026-07-20
17
129
 
18
130
  - Released with the exact 0.0.8 first-party package graph.
@@ -44,7 +156,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
44
156
 
45
157
  - Pinned the required `@arnilo/prism` peer and package metadata to 0.0.5; runtime behavior is unchanged.
46
158
 
47
-
48
159
  ## [0.0.4] - 2026-07-14
49
160
 
50
161
  ### Changed
package/dist/index.d.ts CHANGED
@@ -7,6 +7,6 @@ export interface ZaiProviderPackageOptions {
7
7
  readonly models?: readonly ModelConfig[];
8
8
  }
9
9
  export declare function createZaiProviderPackage(options?: ZaiProviderPackageOptions): ProviderPackage;
10
- export { defineZaiModel, listZaiModels, mapZaiModel, zaiModels, type ListZaiModelsOptions, type ZaiModelConfig, type ZaiModelEntry, } from "./models.js";
11
- export { createZaiProvider, toZaiMessage, zaiBody, zaiEvents, ZAI_DEFAULT_BASE_URL, type ZaiProviderOptions, } from "./provider.js";
10
+ export { defineZaiModel, type ListZaiModelsOptions, listZaiModels, mapZaiModel, type ZaiModelConfig, type ZaiModelEntry, zaiModels, } from "./models.js";
11
+ export { createZaiProvider, toZaiMessage, ZAI_DEFAULT_BASE_URL, type ZaiProviderOptions, zaiBody, zaiEvents, } from "./provider.js";
12
12
  export { zaiClearThinking, zaiPreserveThinking, zaiReasoningEffort, zaiThinking, zaiToolStream, } from "./thinking.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineProviderPackage } from "@arnilo/prism";
2
- import { createZaiProvider } from "./provider.js";
3
2
  import { zaiModels } from "./models.js";
3
+ import { createZaiProvider } from "./provider.js";
4
4
  export function createZaiProviderPackage(options = {}) {
5
5
  const providerId = options.id ?? "zai";
6
6
  return defineProviderPackage({
@@ -16,6 +16,6 @@ export function createZaiProviderPackage(options = {}) {
16
16
  });
17
17
  }
18
18
  export { defineZaiModel, listZaiModels, mapZaiModel, zaiModels, } from "./models.js";
19
- export { createZaiProvider, toZaiMessage, zaiBody, zaiEvents, ZAI_DEFAULT_BASE_URL, } from "./provider.js";
19
+ export { createZaiProvider, toZaiMessage, ZAI_DEFAULT_BASE_URL, zaiBody, zaiEvents, } from "./provider.js";
20
20
  export { zaiClearThinking, zaiPreserveThinking, zaiReasoningEffort, zaiThinking, zaiToolStream, } from "./thinking.js";
21
21
  //# sourceMappingURL=index.js.map
package/dist/models.js CHANGED
@@ -24,7 +24,7 @@ export function defineZaiModel(config) {
24
24
  */
25
25
  export async function listZaiModels(options = {}) {
26
26
  const provider = options.provider ?? "zai";
27
- const baseUrl = (options.baseUrl ?? "https://api.z.ai/api/paas/v4").replace(/\/$/, "");
27
+ const baseUrl = (options.baseUrl ?? "https://api.z.ai/api/paas/v4").replace(/\/+$/, "");
28
28
  const token = await resolveCredentialValue(options.apiKey, { provider, name: "apiKey" });
29
29
  const response = await (options.fetch ?? fetch)(`${baseUrl}/models`, {
30
30
  method: "GET",
@@ -165,10 +165,7 @@ function limitsForZaiModel(modelId) {
165
165
  }
166
166
  function looksLikeReasoningModel(modelId) {
167
167
  const id = modelId.toLowerCase();
168
- return (id.includes("glm-5")
169
- || id.includes("glm-4.7")
170
- || id.includes("glm-4.6")
171
- || id.includes("glm-4.5"));
168
+ return id.includes("glm-5") || id.includes("glm-4.7") || id.includes("glm-4.6") || id.includes("glm-4.5");
172
169
  }
173
170
  function looksLikeVisionModel(modelId) {
174
171
  const id = modelId.toLowerCase();
package/dist/provider.js CHANGED
@@ -1,107 +1,43 @@
1
- import { assertStructuredOutputRequestSupported, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, resolveCredentialValue, toolCallFromArgumentsText } from "@arnilo/prism";
2
- import { applyOpenAIChatStructuredOutput, mapOpenAIChatUsage, serializeOpenAITool } from "@arnilo/prism/providers/openai";
3
- import { readBoundedResponseText, readSseData } from "@arnilo/prism/providers/transport";
1
+ import { applyOpenAIChatStructuredOutput } from "@arnilo/prism/providers/openai";
2
+ import { buildOpenAIChatBody, createOpenAICompatibleProvider, openAIChatEvents } from "@arnilo/prism/providers/openai-compatible";
4
3
  import { zaiPreserveThinking, zaiReasoningEffort, zaiThinking, zaiToolStream } from "./thinking.js";
5
4
  /** Official international Chat Completions base (China `open.bigmodel.cn` remains overridable). */
6
5
  export const ZAI_DEFAULT_BASE_URL = "https://api.z.ai/api/paas/v4";
7
6
  export function createZaiProvider(options = {}) {
8
- const id = options.id ?? "zai";
9
- const baseUrl = (options.baseUrl ?? ZAI_DEFAULT_BASE_URL).replace(/\/$/, "");
10
- return {
11
- id,
12
- async *generate(request) {
13
- if (request.signal?.aborted)
14
- throw request.signal.reason ?? new Error("aborted");
15
- const token = await resolveCredentialValue(options.apiKey, { provider: id, name: "apiKey" });
16
- const secrets = [token];
17
- try {
18
- const response = await (options.fetch ?? fetch)(`${baseUrl}/chat/completions`, {
19
- method: "POST",
20
- headers: {
21
- ...request.options?.headers,
22
- "content-type": "application/json",
23
- ...(token ? { authorization: `Bearer ${token}` } : {})
24
- },
25
- body: JSON.stringify(zaiBody(request)),
26
- signal: request.signal
27
- });
28
- if (!response.ok) {
29
- return yield providerError(new Error(`Z.AI request failed: ${response.status} ${await readBoundedResponseText(response, { secrets })}`), secrets);
30
- }
31
- if (!response.body)
32
- return yield providerError(new Error("Z.AI response had no body"), secrets);
33
- yield* zaiEvents(response.body, request.signal);
34
- }
35
- catch (error) {
36
- yield providerError(error, secrets);
37
- }
38
- }
39
- };
7
+ return createOpenAICompatibleProvider({
8
+ id: options.id ?? "zai",
9
+ baseUrl: (options.baseUrl ?? ZAI_DEFAULT_BASE_URL).replace(/\/+$/, ""),
10
+ apiKey: options.apiKey,
11
+ fetch: options.fetch,
12
+ doneUsage: true,
13
+ requestFailedPrefix: "Z.AI request failed",
14
+ serializeMessage: (message, request) => toZaiMessage(message, request.model, zaiPreserveThinking(request)),
15
+ transformBody: (body, request) => zaiTransform(body, request),
16
+ });
40
17
  }
41
18
  export function zaiBody(request) {
42
- assertStructuredOutputRequestSupported(request.model, request.options);
43
- const { maxTokens, ...parameters } = request.model.parameters ?? {};
44
- const compatRest = stripZaiManagedCompat(request.options?.compat);
45
- const preserveThinking = zaiPreserveThinking(request);
46
- const body = {
47
- model: request.model.model,
48
- messages: request.messages.map((message) => toZaiMessage(message, request.model, preserveThinking)),
49
- tools: request.tools?.map(serializeOpenAITool),
50
- stream: true,
51
- ...parameters,
19
+ return buildOpenAIChatBody(request, {
20
+ serializeMessage: (message, req) => toZaiMessage(message, req.model, zaiPreserveThinking(req)),
21
+ transformBody: (body, req) => zaiTransform(body, req),
22
+ });
23
+ }
24
+ function zaiTransform(body, request) {
25
+ const { maxTokens, stream_options: _streamOptions, ...rest } = body;
26
+ const transformed = {
27
+ ...rest,
52
28
  max_tokens: maxTokens ?? request.model.limits?.maxOutputTokens,
53
- ...compatRest,
29
+ ...stripZaiManagedCompat(request.options?.compat),
54
30
  ...request.options?.extra,
55
31
  // Resolved official fields win over raw compat/extra escape hatches.
56
32
  thinking: zaiThinking(request),
57
33
  reasoning_effort: zaiReasoningEffort(request),
58
- tool_stream: zaiToolStream(request)
34
+ tool_stream: zaiToolStream(request),
59
35
  };
60
- applyOpenAIChatStructuredOutput(body, request.options?.structuredOutput);
61
- return clean(body);
36
+ applyOpenAIChatStructuredOutput(transformed, request.options?.structuredOutput);
37
+ return clean(transformed);
62
38
  }
63
- export async function* zaiEvents(body, signal) {
64
- const tools = new Map();
65
- let usage;
66
- for await (const data of readSseData(body, { signal })) {
67
- if (data === "[DONE]")
68
- break;
69
- const chunk = JSON.parse(data);
70
- if (chunk.usage) {
71
- const mapped = mapOpenAIChatUsage(chunk.usage);
72
- if (mapped) {
73
- usage = mapped;
74
- yield providerUsage(mapped);
75
- }
76
- }
77
- for (const choice of chunk.choices ?? []) {
78
- const delta = choice.delta ?? {};
79
- if (delta.content)
80
- yield providerTextDelta(delta.content);
81
- if (delta.reasoning_content)
82
- yield providerThinkingDelta(delta.reasoning_content);
83
- for (const tool of delta.tool_calls ?? []) {
84
- const index = tool.index ?? 0;
85
- const current = tools.get(index) ?? { argumentsText: "" };
86
- current.id = tool.id ?? current.id;
87
- current.name = tool.function?.name ?? current.name;
88
- current.argumentsText += tool.function?.arguments ?? "";
89
- tools.set(index, current);
90
- yield providerToolCallDelta({
91
- index,
92
- id: tool.id,
93
- name: tool.function?.name,
94
- argumentsText: tool.function?.arguments
95
- });
96
- }
97
- }
98
- }
99
- for (const call of tools.values()) {
100
- if (call.id && call.name) {
101
- yield providerToolCall(toolCallFromArgumentsText(call.id, call.name, call.argumentsText));
102
- }
103
- }
104
- yield providerDone(usage);
39
+ export function zaiEvents(body, signal) {
40
+ return openAIChatEvents(body, { signal, doneUsage: true });
105
41
  }
106
42
  /**
107
43
  * Serialize Prism messages for Z.AI Chat Completions.
@@ -112,15 +48,13 @@ export async function* zaiEvents(body, signal) {
112
48
  export function toZaiMessage(message, model, preserveThinking = false) {
113
49
  const capabilities = model.capabilities ?? {};
114
50
  const thinkingParts = message.content.filter((part) => part.type === "thinking");
115
- const reasoningContent = preserveThinking && thinkingParts.length > 0
116
- ? thinkingParts.map((part) => part.text).join("\n")
117
- : undefined;
51
+ const reasoningContent = preserveThinking && thinkingParts.length > 0 ? thinkingParts.map((part) => part.text).join("\n") : undefined;
118
52
  if (message.role === "tool") {
119
53
  const result = message.content.find((part) => part.type === "tool_result");
120
54
  return {
121
55
  role: "tool",
122
56
  tool_call_id: result?.toolCallId ?? "",
123
- content: result ? JSON.stringify(result.result ?? result.error ?? null) : ""
57
+ content: result ? JSON.stringify(result.result ?? result.error ?? null) : "",
124
58
  };
125
59
  }
126
60
  if (message.role === "assistant") {
@@ -133,9 +67,9 @@ export function toZaiMessage(message, model, preserveThinking = false) {
133
67
  tool_calls: toolCalls.map((call) => ({
134
68
  id: call.id,
135
69
  type: "function",
136
- function: { name: call.name, arguments: JSON.stringify(call.arguments) }
70
+ function: { name: call.name, arguments: JSON.stringify(call.arguments) },
137
71
  })),
138
- reasoning_content: reasoningContent
72
+ reasoning_content: reasoningContent,
139
73
  });
140
74
  }
141
75
  }
@@ -145,8 +79,6 @@ export function toZaiMessage(message, model, preserveThinking = false) {
145
79
  content.push({ type: "text", text: part.text });
146
80
  }
147
81
  else if (part.type === "thinking") {
148
- // Handled via reasoning_content when preserving; otherwise dropped.
149
- continue;
150
82
  }
151
83
  else if (part.type === "image") {
152
84
  if (!capabilities.input?.includes("image")) {
package/dist/thinking.js CHANGED
@@ -30,9 +30,7 @@ export function zaiThinking(request) {
30
30
  * @see https://docs.z.ai/guides/capabilities/thinking
31
31
  */
32
32
  export function zaiReasoningEffort(request) {
33
- const effort = request.options?.compat?.reasoning_effort
34
- ?? request.options?.compat?.reasoningEffort
35
- ?? request.model.compat?.reasoning_effort;
33
+ const effort = request.options?.compat?.reasoning_effort ?? request.options?.compat?.reasoningEffort ?? request.model.compat?.reasoning_effort;
36
34
  return typeof effort === "string" ? effort : undefined;
37
35
  }
38
36
  /**
@@ -52,9 +50,7 @@ export function zaiClearThinking(request) {
52
50
  const fromThinkingObject = readClearThinkingFromObject(request.options?.compat?.thinking ?? request.model.compat?.thinking);
53
51
  if (fromThinkingObject !== undefined)
54
52
  return fromThinkingObject;
55
- const value = request.options?.compat?.clear_thinking
56
- ?? request.options?.compat?.clearThinking
57
- ?? request.model.compat?.clear_thinking;
53
+ const value = request.options?.compat?.clear_thinking ?? request.options?.compat?.clearThinking ?? request.model.compat?.clear_thinking;
58
54
  return typeof value === "boolean" ? value : undefined;
59
55
  }
60
56
  /**
@@ -66,10 +62,10 @@ export function zaiPreserveThinking(request) {
66
62
  const clear = zaiClearThinking(request);
67
63
  if (clear === true)
68
64
  return false;
69
- const value = request.options?.compat?.preserveThinking
70
- ?? request.options?.compat?.preserve_thinking
71
- ?? request.model.compat?.preserveThinking
72
- ?? request.model.compat?.preserve_thinking;
65
+ const value = request.options?.compat?.preserveThinking ??
66
+ request.options?.compat?.preserve_thinking ??
67
+ request.model.compat?.preserveThinking ??
68
+ request.model.compat?.preserve_thinking;
73
69
  if (typeof value === "boolean")
74
70
  return value;
75
71
  // clear_thinking:false implies preserved thinking even without an explicit preserve flag.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism-provider-zai",
3
- "version": "0.0.96",
3
+ "version": "0.1.1",
4
4
  "description": "Z.AI provider package for Prism.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "pack:dry-run": "npm pack --dry-run"
26
26
  },
27
27
  "peerDependencies": {
28
- "@arnilo/prism": "0.0.96"
28
+ "@arnilo/prism": "0.1.1"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@arnilo/prism": "file:../.."