@prismshadow/mmsp 0.5.0
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/README.md +121 -0
- package/dist/ant_messages/client.d.ts +59 -0
- package/dist/ant_messages/client.d.ts.map +1 -0
- package/dist/ant_messages/client.js +419 -0
- package/dist/ant_messages/index.d.ts +2 -0
- package/dist/ant_messages/index.d.ts.map +1 -0
- package/dist/ant_messages/index.js +18 -0
- package/dist/anthropic_official/client.d.ts +63 -0
- package/dist/anthropic_official/client.d.ts.map +1 -0
- package/dist/anthropic_official/client.js +540 -0
- package/dist/anthropic_official/index.d.ts +2 -0
- package/dist/anthropic_official/index.d.ts.map +1 -0
- package/dist/anthropic_official/index.js +18 -0
- package/dist/autoClient.d.ts +96 -0
- package/dist/autoClient.d.ts.map +1 -0
- package/dist/autoClient.js +258 -0
- package/dist/baseClient.d.ts +111 -0
- package/dist/baseClient.d.ts.map +1 -0
- package/dist/baseClient.js +284 -0
- package/dist/deepseek_official/client.d.ts +60 -0
- package/dist/deepseek_official/client.d.ts.map +1 -0
- package/dist/deepseek_official/client.js +407 -0
- package/dist/deepseek_official/index.d.ts +2 -0
- package/dist/deepseek_official/index.d.ts.map +1 -0
- package/dist/deepseek_official/index.js +18 -0
- package/dist/errors.d.ts +84 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +140 -0
- package/dist/gemini_generate_content/client.d.ts +86 -0
- package/dist/gemini_generate_content/client.d.ts.map +1 -0
- package/dist/gemini_generate_content/client.js +809 -0
- package/dist/gemini_generate_content/index.d.ts +2 -0
- package/dist/gemini_generate_content/index.d.ts.map +1 -0
- package/dist/gemini_generate_content/index.js +18 -0
- package/dist/gemini_official/client.d.ts +87 -0
- package/dist/gemini_official/client.d.ts.map +1 -0
- package/dist/gemini_official/client.js +780 -0
- package/dist/gemini_official/index.d.ts +2 -0
- package/dist/gemini_official/index.d.ts.map +1 -0
- package/dist/gemini_official/index.js +18 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/integration/index.d.ts +1 -0
- package/dist/integration/index.d.ts.map +1 -0
- package/dist/integration/index.js +14 -0
- package/dist/integration/playground.d.ts +17 -0
- package/dist/integration/playground.d.ts.map +1 -0
- package/dist/integration/playground.js +3246 -0
- package/dist/integration/tracer.d.ts +188 -0
- package/dist/integration/tracer.d.ts.map +1 -0
- package/dist/integration/tracer.js +1928 -0
- package/dist/legacy.d.ts +13 -0
- package/dist/legacy.d.ts.map +1 -0
- package/dist/legacy.js +59 -0
- package/dist/minimax_official/client.d.ts +43 -0
- package/dist/minimax_official/client.d.ts.map +1 -0
- package/dist/minimax_official/client.js +346 -0
- package/dist/minimax_official/index.d.ts +2 -0
- package/dist/minimax_official/index.d.ts.map +1 -0
- package/dist/minimax_official/index.js +18 -0
- package/dist/moonshot_official/client.d.ts +73 -0
- package/dist/moonshot_official/client.d.ts.map +1 -0
- package/dist/moonshot_official/client.js +477 -0
- package/dist/moonshot_official/index.d.ts +2 -0
- package/dist/moonshot_official/index.d.ts.map +1 -0
- package/dist/moonshot_official/index.js +18 -0
- package/dist/openai_chat/client.d.ts +67 -0
- package/dist/openai_chat/client.d.ts.map +1 -0
- package/dist/openai_chat/client.js +419 -0
- package/dist/openai_chat/index.d.ts +2 -0
- package/dist/openai_chat/index.d.ts.map +1 -0
- package/dist/openai_chat/index.js +18 -0
- package/dist/openai_chat_vllm_adapter/client.d.ts +15 -0
- package/dist/openai_chat_vllm_adapter/client.d.ts.map +1 -0
- package/dist/openai_chat_vllm_adapter/client.js +118 -0
- package/dist/openai_chat_vllm_adapter/index.d.ts +2 -0
- package/dist/openai_chat_vllm_adapter/index.d.ts.map +1 -0
- package/dist/openai_chat_vllm_adapter/index.js +5 -0
- package/dist/openai_embedding/client.d.ts +46 -0
- package/dist/openai_embedding/client.d.ts.map +1 -0
- package/dist/openai_embedding/client.js +124 -0
- package/dist/openai_embedding/index.d.ts +2 -0
- package/dist/openai_embedding/index.d.ts.map +1 -0
- package/dist/openai_embedding/index.js +18 -0
- package/dist/openai_official/client.d.ts +61 -0
- package/dist/openai_official/client.d.ts.map +1 -0
- package/dist/openai_official/client.js +464 -0
- package/dist/openai_official/index.d.ts +2 -0
- package/dist/openai_official/index.d.ts.map +1 -0
- package/dist/openai_official/index.js +18 -0
- package/dist/openai_responses/client.d.ts +61 -0
- package/dist/openai_responses/client.d.ts.map +1 -0
- package/dist/openai_responses/client.js +449 -0
- package/dist/openai_responses/index.d.ts +2 -0
- package/dist/openai_responses/index.d.ts.map +1 -0
- package/dist/openai_responses/index.js +18 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +798 -0
- package/dist/streamItems.d.ts +36 -0
- package/dist/streamItems.d.ts.map +1 -0
- package/dist/streamItems.js +183 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/utils.d.ts +99 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +312 -0
- package/dist/zai_official/client.d.ts +78 -0
- package/dist/zai_official/client.d.ts.map +1 -0
- package/dist/zai_official/client.js +420 -0
- package/dist/zai_official/index.d.ts +2 -0
- package/dist/zai_official/index.d.ts.map +1 -0
- package/dist/zai_official/index.js +18 -0
- package/package.json +68 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2025 Prism Shadow. and/or its affiliates
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.ZAIOfficialClient = void 0;
|
|
20
|
+
const openai_1 = __importDefault(require("openai"));
|
|
21
|
+
const baseClient_1 = require("../baseClient");
|
|
22
|
+
const errors_1 = require("../errors");
|
|
23
|
+
const types_1 = require("../types");
|
|
24
|
+
const utils_1 = require("../utils");
|
|
25
|
+
/**
|
|
26
|
+
* Unified client for the GLM series, named for the newest generation it serves (5.3).
|
|
27
|
+
*
|
|
28
|
+
* The wire format is shared across GLM-5.1 through 5.3; only the thinking
|
|
29
|
+
* parameter contract differs per generation, handled model-by-model.
|
|
30
|
+
*/
|
|
31
|
+
class ZAIOfficialClient extends baseClient_1.LLMClient {
|
|
32
|
+
/**
|
|
33
|
+
* Initialize GLM client with model and API key.
|
|
34
|
+
*/
|
|
35
|
+
constructor(options) {
|
|
36
|
+
super();
|
|
37
|
+
this._model = options.model;
|
|
38
|
+
// The wrapped OpenAI SDK falls back to OPENAI_API_KEY when handed undefined, which would send
|
|
39
|
+
// an OpenAI credential to the Z.AI host, so resolve the key here and fail loudly instead.
|
|
40
|
+
const key = options.apiKey || process.env.ZAI_API_KEY;
|
|
41
|
+
if (!key) {
|
|
42
|
+
throw new Error("ZAI_API_KEY is required for ZAIOfficialClient.");
|
|
43
|
+
}
|
|
44
|
+
const url = options.baseUrl ||
|
|
45
|
+
process.env.ZAI_BASE_URL ||
|
|
46
|
+
"https://api.z.ai/api/paas/v4/";
|
|
47
|
+
this._client = new openai_1.default({
|
|
48
|
+
apiKey: key,
|
|
49
|
+
baseURL: url,
|
|
50
|
+
defaultHeaders: options.defaultHeaders,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Convert ThinkingLevel enum to GLM's thinking configuration.
|
|
55
|
+
*
|
|
56
|
+
* GLM-5.3 uses forced thinking and errors on {"type": "disabled"}, so NONE
|
|
57
|
+
* stays enabled there and degrades through the lightest reasoning effort
|
|
58
|
+
* instead (llmsdk_docs/glm5_3/docs/thinking.md).
|
|
59
|
+
*/
|
|
60
|
+
_convertThinkingLevelToConfig(thinkingLevel) {
|
|
61
|
+
// Provider-hosted ids keep their own casing (e.g. SiliconFlow's zai-org/GLM-5.2),
|
|
62
|
+
// so generation detection is case-insensitive.
|
|
63
|
+
if (thinkingLevel === types_1.ThinkingLevel.NONE &&
|
|
64
|
+
!this._model.toLowerCase().includes("glm-5.3")) {
|
|
65
|
+
return { type: "disabled" };
|
|
66
|
+
}
|
|
67
|
+
return { type: "enabled", clear_thinking: false };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert ThinkingLevel enum to the reasoning_effort the model accepts.
|
|
71
|
+
*
|
|
72
|
+
* GLM-5.3 accepts only low/high/max and errors on anything else, so the
|
|
73
|
+
* client clamps to the closest value; NONE rides on low because 5.3 cannot
|
|
74
|
+
* disable thinking. Every earlier generation takes the vocabulary unchanged:
|
|
75
|
+
* 5.2 maps it server-side (low/medium to high, xhigh to max), and 5.1 and
|
|
76
|
+
* below accept the parameter and ignore it (verified live 2026-09-03 on
|
|
77
|
+
* Z.AI, OpenRouter and SiliconFlow), so the level is forwarded there rather
|
|
78
|
+
* than dropped. Outside 5.3 NONE disables thinking outright, which leaves no
|
|
79
|
+
* effort to send.
|
|
80
|
+
*/
|
|
81
|
+
_convertThinkingLevelToReasoningEffort(thinkingLevel) {
|
|
82
|
+
const model = this._model.toLowerCase(); // provider-hosted ids keep their own casing
|
|
83
|
+
if (model.includes("glm-5.3")) {
|
|
84
|
+
const mapping = {
|
|
85
|
+
[types_1.ThinkingLevel.NONE]: "low",
|
|
86
|
+
[types_1.ThinkingLevel.LOW]: "low",
|
|
87
|
+
[types_1.ThinkingLevel.MEDIUM]: "high",
|
|
88
|
+
[types_1.ThinkingLevel.HIGH]: "high",
|
|
89
|
+
[types_1.ThinkingLevel.XHIGH]: "max",
|
|
90
|
+
[types_1.ThinkingLevel.MAX]: "max",
|
|
91
|
+
};
|
|
92
|
+
return mapping[thinkingLevel];
|
|
93
|
+
}
|
|
94
|
+
const mapping = {
|
|
95
|
+
[types_1.ThinkingLevel.LOW]: "low",
|
|
96
|
+
[types_1.ThinkingLevel.MEDIUM]: "medium",
|
|
97
|
+
[types_1.ThinkingLevel.HIGH]: "high",
|
|
98
|
+
[types_1.ThinkingLevel.XHIGH]: "xhigh",
|
|
99
|
+
[types_1.ThinkingLevel.MAX]: "max",
|
|
100
|
+
};
|
|
101
|
+
return mapping[thinkingLevel];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Convert ToolChoice to OpenAI's tool_choice format.
|
|
105
|
+
*/
|
|
106
|
+
_convertToolChoice(toolChoice) {
|
|
107
|
+
if (toolChoice === "auto") {
|
|
108
|
+
return "auto";
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
throw new errors_1.UnsupportedParameterError({
|
|
112
|
+
client: this.constructor.name,
|
|
113
|
+
parameter: "tool_choice",
|
|
114
|
+
message: 'GLM only supports "auto" for tool_choice.',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Transform universal configuration to GLM-specific configuration.
|
|
120
|
+
*/
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
transformUniConfigToModelConfig(config) {
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
124
|
+
const glmConfig = {
|
|
125
|
+
model: this._model,
|
|
126
|
+
stream: true,
|
|
127
|
+
extra_body: { tool_stream: true },
|
|
128
|
+
};
|
|
129
|
+
if (config.max_tokens !== undefined) {
|
|
130
|
+
glmConfig.max_tokens = config.max_tokens;
|
|
131
|
+
}
|
|
132
|
+
if (config.temperature !== undefined) {
|
|
133
|
+
glmConfig.temperature = config.temperature;
|
|
134
|
+
}
|
|
135
|
+
if (config.thinking_level !== undefined) {
|
|
136
|
+
const thinkingConfig = this._convertThinkingLevelToConfig(config.thinking_level);
|
|
137
|
+
glmConfig.extra_body = {
|
|
138
|
+
...(glmConfig.extra_body || {}),
|
|
139
|
+
thinking: thinkingConfig,
|
|
140
|
+
};
|
|
141
|
+
const reasoningEffort = this._convertThinkingLevelToReasoningEffort(config.thinking_level);
|
|
142
|
+
if (reasoningEffort !== undefined) {
|
|
143
|
+
glmConfig.reasoning_effort = reasoningEffort;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (config.tools !== undefined) {
|
|
147
|
+
glmConfig.tools = config.tools.map((tool) => ({
|
|
148
|
+
type: "function",
|
|
149
|
+
function: tool,
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
if (config.tool_choice !== undefined) {
|
|
153
|
+
glmConfig.tool_choice = this._convertToolChoice(config.tool_choice);
|
|
154
|
+
}
|
|
155
|
+
if (config.fast_mode) {
|
|
156
|
+
throw new errors_1.UnsupportedParameterError({
|
|
157
|
+
client: this.constructor.name,
|
|
158
|
+
parameter: "fast_mode",
|
|
159
|
+
message: "GLM does not support fast mode.",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (config.prompt_caching !== undefined &&
|
|
163
|
+
config.prompt_caching !== types_1.PromptCaching.ENABLE) {
|
|
164
|
+
throw new errors_1.UnsupportedParameterError({
|
|
165
|
+
client: this.constructor.name,
|
|
166
|
+
parameter: "prompt_caching",
|
|
167
|
+
message: "prompt_caching must be ENABLE for GLM.",
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return glmConfig;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Transform universal message format to OpenAI's message format.
|
|
174
|
+
*/
|
|
175
|
+
transformUniMessageToModelInput(messages, _signal) {
|
|
176
|
+
// glm-5.3-flash is the natively multimodal GLM and the only one that reads image
|
|
177
|
+
// parts (https://docs.z.ai/guides/vlm/glm-5.3-flash); every other GLM answers a
|
|
178
|
+
// request carrying one with an error, so the item is refused here rather than
|
|
179
|
+
// dropped. Provider-hosted ids keep their own casing (e.g. z-ai/glm-5.3-flash),
|
|
180
|
+
// so the version match is case-insensitive.
|
|
181
|
+
const supportsImage = this._model.toLowerCase().includes("glm-5.3-flash");
|
|
182
|
+
const openaiMessages = [];
|
|
183
|
+
for (const msg of messages) {
|
|
184
|
+
const contentParts = [];
|
|
185
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
186
|
+
const toolCalls = [];
|
|
187
|
+
let thinking = "";
|
|
188
|
+
const thinkingFields = new Set();
|
|
189
|
+
for (const item of msg.content_items) {
|
|
190
|
+
if (item.type === "text.done") {
|
|
191
|
+
contentParts.push({ type: "text", text: item.text });
|
|
192
|
+
}
|
|
193
|
+
else if (item.type === "image_url.done") {
|
|
194
|
+
if (!supportsImage) {
|
|
195
|
+
throw new Error(`GLM ${this._model} does not support image inputs.`);
|
|
196
|
+
}
|
|
197
|
+
contentParts.push({
|
|
198
|
+
type: "image_url",
|
|
199
|
+
image_url: { url: item.image_url },
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
else if (item.type === "thinking.done") {
|
|
203
|
+
thinking += item.thinking;
|
|
204
|
+
thinkingFields.add(item.fidelity?.reasoning_field);
|
|
205
|
+
}
|
|
206
|
+
else if (item.type === "tool_call.done") {
|
|
207
|
+
toolCalls.push({
|
|
208
|
+
id: item.tool_call_id,
|
|
209
|
+
type: "function",
|
|
210
|
+
function: {
|
|
211
|
+
name: item.name,
|
|
212
|
+
arguments: JSON.stringify(item.arguments, null, 0),
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else if (item.type === "tool_result.done") {
|
|
217
|
+
if (!item.tool_call_id) {
|
|
218
|
+
throw new Error("tool_call_id is required for tool result.");
|
|
219
|
+
}
|
|
220
|
+
// Chat Completions lets a tool message carry text only, and a server that
|
|
221
|
+
// validates the schema rejects the whole request over an image part in one.
|
|
222
|
+
// The images ride in the user message that follows the turn's tool messages,
|
|
223
|
+
// the one place every OpenAI-compatible server reads them.
|
|
224
|
+
if (item.images && item.images.length > 0) {
|
|
225
|
+
if (!supportsImage) {
|
|
226
|
+
throw new Error(`GLM ${this._model} does not support images in tool results.`);
|
|
227
|
+
}
|
|
228
|
+
for (const imageUrl of item.images) {
|
|
229
|
+
contentParts.push({
|
|
230
|
+
type: "image_url",
|
|
231
|
+
image_url: { url: imageUrl },
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// the plain string is the only content shape the Chat Completion schema
|
|
236
|
+
// documents for a tool message
|
|
237
|
+
openaiMessages.push({
|
|
238
|
+
role: "tool",
|
|
239
|
+
tool_call_id: item.tool_call_id,
|
|
240
|
+
content: item.text,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
throw new Error(`Unknown item type: ${item.type}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
248
|
+
const message = { role: msg.role };
|
|
249
|
+
if (contentParts.length > 0) {
|
|
250
|
+
message.content = contentParts;
|
|
251
|
+
}
|
|
252
|
+
if (toolCalls.length > 0) {
|
|
253
|
+
message.tool_calls = toolCalls;
|
|
254
|
+
}
|
|
255
|
+
if (thinking) {
|
|
256
|
+
// send thinking back through the exact field the upstream produced (recorded
|
|
257
|
+
// in the item fidelity); servers may reject the spelling they did not emit
|
|
258
|
+
if (thinkingFields.size === 1 &&
|
|
259
|
+
thinkingFields.has("reasoning_content")) {
|
|
260
|
+
message.reasoning_content = thinking;
|
|
261
|
+
}
|
|
262
|
+
else if (thinkingFields.size === 1 &&
|
|
263
|
+
thinkingFields.has("reasoning")) {
|
|
264
|
+
message.reasoning = thinking;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
message.reasoning_content = thinking; // vLLM & siliconflow compatibility
|
|
268
|
+
message.reasoning = thinking; // openrouter compatibility
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (Object.keys(message).length > 1) {
|
|
272
|
+
openaiMessages.push(message);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return openaiMessages;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Transform one GLM streaming chunk into a universal event.
|
|
279
|
+
*
|
|
280
|
+
* Chat Completions gives an item no identity, so each delta's item_id is the wire field
|
|
281
|
+
* that carried it: an item runs until a delta arrives from another field, or names the next
|
|
282
|
+
* tool call.
|
|
283
|
+
*/
|
|
284
|
+
transformModelOutputToUniEvent(modelOutput) {
|
|
285
|
+
let eventType = "delta";
|
|
286
|
+
const contentItems = [];
|
|
287
|
+
let usageMetadata = null;
|
|
288
|
+
let finishReason = null;
|
|
289
|
+
// gateways inject content-free heartbeat chunks on long generations, whose
|
|
290
|
+
// choices arrive as undefined rather than an empty list
|
|
291
|
+
if (modelOutput.choices?.length) {
|
|
292
|
+
const choice = modelOutput.choices[0];
|
|
293
|
+
const delta = choice?.delta;
|
|
294
|
+
// the thinking field name differs by server: vLLM & siliconflow use
|
|
295
|
+
// reasoning_content while openrouter uses reasoning; record the wire
|
|
296
|
+
// field that carried each delta so a replay can reproduce exactly the
|
|
297
|
+
// field the upstream produced. The reasoning goes before the content
|
|
298
|
+
// because a chunk may end the reasoning and begin the answer.
|
|
299
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
300
|
+
const reasoningContent = delta?.reasoning_content;
|
|
301
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
302
|
+
const reasoning = delta?.reasoning;
|
|
303
|
+
if (reasoningContent && reasoning) {
|
|
304
|
+
// ambiguous origin: record no reasoning_field so a replay sends both fields back
|
|
305
|
+
contentItems.push({
|
|
306
|
+
type: "thinking.delta",
|
|
307
|
+
thinking: reasoningContent,
|
|
308
|
+
fidelity: { item_id: "reasoning_content" },
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else if (reasoningContent) {
|
|
312
|
+
contentItems.push({
|
|
313
|
+
type: "thinking.delta",
|
|
314
|
+
thinking: reasoningContent,
|
|
315
|
+
fidelity: {
|
|
316
|
+
item_id: "reasoning_content",
|
|
317
|
+
reasoning_field: "reasoning_content",
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
else if (reasoning) {
|
|
322
|
+
contentItems.push({
|
|
323
|
+
type: "thinking.delta",
|
|
324
|
+
thinking: reasoning,
|
|
325
|
+
fidelity: { item_id: "reasoning", reasoning_field: "reasoning" },
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (delta?.content) {
|
|
329
|
+
contentItems.push({
|
|
330
|
+
type: "text.delta",
|
|
331
|
+
text: delta.content,
|
|
332
|
+
fidelity: { item_id: "content" },
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
if (delta?.tool_calls) {
|
|
336
|
+
for (const toolCall of delta.tool_calls) {
|
|
337
|
+
contentItems.push({
|
|
338
|
+
type: "tool_call.delta",
|
|
339
|
+
name: toolCall.function?.name || "",
|
|
340
|
+
arguments: toolCall.function?.arguments || "",
|
|
341
|
+
tool_call_id: toolCall.id || "",
|
|
342
|
+
fidelity: { item_id: "tool_calls" },
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (choice?.finish_reason) {
|
|
347
|
+
eventType = "stop";
|
|
348
|
+
const finishReasonMapping = {
|
|
349
|
+
stop: "stop",
|
|
350
|
+
length: "length",
|
|
351
|
+
tool_calls: "tool_call",
|
|
352
|
+
content_filter: "stop",
|
|
353
|
+
};
|
|
354
|
+
finishReason = finishReasonMapping[choice.finish_reason] || "unknown";
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (modelOutput.usage) {
|
|
358
|
+
eventType = "stop";
|
|
359
|
+
const cachedTokens = modelOutput.usage.prompt_tokens_details?.cached_tokens || null;
|
|
360
|
+
const reasoningTokens = modelOutput.usage.completion_tokens_details?.reasoning_tokens || null;
|
|
361
|
+
const promptTokens = cachedTokens !== null
|
|
362
|
+
? modelOutput.usage.prompt_tokens - cachedTokens
|
|
363
|
+
: modelOutput.usage.prompt_tokens;
|
|
364
|
+
const responseTokens = reasoningTokens !== null
|
|
365
|
+
? modelOutput.usage.completion_tokens - reasoningTokens
|
|
366
|
+
: modelOutput.usage.completion_tokens;
|
|
367
|
+
usageMetadata = {
|
|
368
|
+
cached_tokens: cachedTokens,
|
|
369
|
+
prompt_tokens: promptTokens,
|
|
370
|
+
thoughts_tokens: reasoningTokens,
|
|
371
|
+
response_tokens: responseTokens,
|
|
372
|
+
};
|
|
373
|
+
usageMetadata = (0, utils_1.fixOpenrouterUsageMetadata)(usageMetadata, this._client.baseURL);
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
role: "assistant",
|
|
377
|
+
event_type: eventType,
|
|
378
|
+
content_items: contentItems,
|
|
379
|
+
usage_metadata: usageMetadata,
|
|
380
|
+
finish_reason: finishReason,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Stream generate using GLM SDK with unified conversion methods.
|
|
385
|
+
*/
|
|
386
|
+
async *_streamingResponseInternal(options) {
|
|
387
|
+
const glmConfig = this.transformUniConfigToModelConfig(options.config);
|
|
388
|
+
const glmMessages = this.transformUniMessageToModelInput(options.messages, options.signal);
|
|
389
|
+
if (options.config.system_prompt) {
|
|
390
|
+
glmMessages.unshift({
|
|
391
|
+
role: "system",
|
|
392
|
+
content: options.config.system_prompt,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
const params = {
|
|
396
|
+
...glmConfig,
|
|
397
|
+
messages: glmMessages,
|
|
398
|
+
stream: true,
|
|
399
|
+
};
|
|
400
|
+
const stream = await this._client.chat.completions.create(params, {
|
|
401
|
+
signal: options.signal,
|
|
402
|
+
});
|
|
403
|
+
for await (const chunk of stream) {
|
|
404
|
+
yield this.transformModelOutputToUniEvent(chunk);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* List the model ids the configured endpoint serves.
|
|
409
|
+
*
|
|
410
|
+
* @returns The model ids, in the order the endpoint returned them.
|
|
411
|
+
*/
|
|
412
|
+
async listModels() {
|
|
413
|
+
const models = [];
|
|
414
|
+
for await (const model of this._client.models.list()) {
|
|
415
|
+
models.push(model.id);
|
|
416
|
+
}
|
|
417
|
+
return models;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
exports.ZAIOfficialClient = ZAIOfficialClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/zai_official/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2025 Prism Shadow. and/or its affiliates
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ZAIOfficialClient = void 0;
|
|
17
|
+
var client_1 = require("./client");
|
|
18
|
+
Object.defineProperty(exports, "ZAIOfficialClient", { enumerable: true, get: function () { return client_1.ZAIOfficialClient; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prismshadow/mmsp",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "MMSP, the Model Message Stream Protocol: one message format and one streaming grammar for every model provider, in Python and TypeScript.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./dist/index.js",
|
|
12
|
+
"./integration/tracer": "./dist/integration/tracer.js",
|
|
13
|
+
"./integration/playground": "./dist/integration/playground.js"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"lint": "eslint src --ext .ts",
|
|
18
|
+
"start": "node dist/index.js",
|
|
19
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
|
20
|
+
"tracer": "tsx examples/tracerExample.ts",
|
|
21
|
+
"playground": "tsx examples/playgroundExample.ts"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@anthropic-ai/bedrock-sdk": "^0.26.4",
|
|
25
|
+
"@anthropic-ai/sdk": "^0.81.0",
|
|
26
|
+
"@google/genai": "^2.24.0",
|
|
27
|
+
"express": "^4.18.2",
|
|
28
|
+
"openai": "^6.33.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@eslint/js": "^9.0.0",
|
|
32
|
+
"@types/express": "^4.17.21",
|
|
33
|
+
"@types/jest": "^30.0.0",
|
|
34
|
+
"@types/node": "^25.0.10",
|
|
35
|
+
"@types/supertest": "^7.2.0",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
37
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
38
|
+
"eslint": "^9.0.0",
|
|
39
|
+
"gaxios": "^7.1.3",
|
|
40
|
+
"jest": "^30.2.0",
|
|
41
|
+
"supertest": "^7.2.2",
|
|
42
|
+
"ts-jest": "^29.4.6",
|
|
43
|
+
"tsx": "^4.21.0",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
},
|
|
46
|
+
"directories": {
|
|
47
|
+
"example": "examples",
|
|
48
|
+
"test": "tests"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/Prism-Shadow/model-message-stream-protocol.git"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"mmsp",
|
|
56
|
+
"llm",
|
|
57
|
+
"stream",
|
|
58
|
+
"gemini",
|
|
59
|
+
"claude",
|
|
60
|
+
"gpt"
|
|
61
|
+
],
|
|
62
|
+
"author": "PrismShadow",
|
|
63
|
+
"license": "Apache-2.0",
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/Prism-Shadow/model-message-stream-protocol/issues"
|
|
66
|
+
},
|
|
67
|
+
"homepage": "https://github.com/Prism-Shadow/model-message-stream-protocol#readme"
|
|
68
|
+
}
|