@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,407 @@
|
|
|
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.DeepSeekOfficialClient = 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
|
+
* The DeepSeek ids that read no image: the current V4 Flash and V4 Pro, bare or with a
|
|
27
|
+
* dated snapshot suffix (`deepseek-v4-flash-0731`). Every other id forwards its images.
|
|
28
|
+
* Matched against the bare id — the part after the last `/`, lowercased — so a gateway
|
|
29
|
+
* prefix (`deepseek/`, `deepseek-ai/`) and the spelling a platform uses do not change the
|
|
30
|
+
* verdict.
|
|
31
|
+
*/
|
|
32
|
+
const TEXT_ONLY_MODELS = /^deepseek-v4-(flash|pro)(-\d{4})?$/;
|
|
33
|
+
/**
|
|
34
|
+
* DeepSeek V4-specific LLM client implementation using the OpenAI-compatible Responses API.
|
|
35
|
+
*/
|
|
36
|
+
class DeepSeekOfficialClient extends baseClient_1.LLMClient {
|
|
37
|
+
/**
|
|
38
|
+
* Initialize DeepSeek client with model, API key, and base URL.
|
|
39
|
+
*/
|
|
40
|
+
constructor(options) {
|
|
41
|
+
super();
|
|
42
|
+
this._model = options.model;
|
|
43
|
+
// The wrapped OpenAI SDK falls back to OPENAI_API_KEY when handed undefined, which would send
|
|
44
|
+
// an OpenAI credential to the DeepSeek host, so resolve the key here and fail loudly instead.
|
|
45
|
+
const key = options.apiKey || process.env.DEEPSEEK_API_KEY;
|
|
46
|
+
if (!key) {
|
|
47
|
+
throw new Error("DEEPSEEK_API_KEY is required for DeepSeekOfficialClient.");
|
|
48
|
+
}
|
|
49
|
+
const url = options.baseUrl ||
|
|
50
|
+
process.env.DEEPSEEK_BASE_URL ||
|
|
51
|
+
"https://api.deepseek.com";
|
|
52
|
+
this._client = new openai_1.default({
|
|
53
|
+
apiKey: key,
|
|
54
|
+
baseURL: url,
|
|
55
|
+
defaultHeaders: options.defaultHeaders,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Convert ThinkingLevel enum to DeepSeek's reasoning effort.
|
|
60
|
+
*
|
|
61
|
+
* DeepSeek accepts low/high/max and maps medium and xhigh onto high server-side
|
|
62
|
+
* (llmsdk_docs/deepseek_v4/docs/thinking-mode.md), so this sends the value the server
|
|
63
|
+
* would settle on anyway. Effort "none" is what turns thinking off on this endpoint:
|
|
64
|
+
* the Chat Completions `thinking` toggle is ignored here (verified live 2026-08-21).
|
|
65
|
+
*/
|
|
66
|
+
_convertThinkingLevelToEffort(thinkingLevel) {
|
|
67
|
+
const mapping = {
|
|
68
|
+
[types_1.ThinkingLevel.NONE]: "none",
|
|
69
|
+
[types_1.ThinkingLevel.LOW]: "low",
|
|
70
|
+
[types_1.ThinkingLevel.MEDIUM]: "high",
|
|
71
|
+
[types_1.ThinkingLevel.HIGH]: "high",
|
|
72
|
+
[types_1.ThinkingLevel.XHIGH]: "high",
|
|
73
|
+
[types_1.ThinkingLevel.MAX]: "max",
|
|
74
|
+
};
|
|
75
|
+
return mapping[thinkingLevel];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Convert ToolChoice to DeepSeek's Responses-compatible tool_choice format.
|
|
79
|
+
*/
|
|
80
|
+
_convertToolChoice(toolChoice) {
|
|
81
|
+
if (toolChoice === "auto" || toolChoice === "none") {
|
|
82
|
+
return toolChoice;
|
|
83
|
+
}
|
|
84
|
+
throw new errors_1.UnsupportedParameterError({
|
|
85
|
+
client: this.constructor.name,
|
|
86
|
+
parameter: "tool_choice",
|
|
87
|
+
message: "DeepSeek V4 only supports 'auto' and 'none' for tool_choice.",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Transform universal configuration to DeepSeek-specific configuration.
|
|
92
|
+
*/
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
transformUniConfigToModelConfig(config) {
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
const deepseekConfig = {
|
|
97
|
+
model: this._model,
|
|
98
|
+
store: false,
|
|
99
|
+
};
|
|
100
|
+
if (config.system_prompt !== undefined) {
|
|
101
|
+
deepseekConfig.instructions = config.system_prompt;
|
|
102
|
+
}
|
|
103
|
+
if (config.max_tokens !== undefined) {
|
|
104
|
+
deepseekConfig.max_output_tokens = config.max_tokens;
|
|
105
|
+
}
|
|
106
|
+
if (config.temperature !== undefined && config.temperature !== 1.0) {
|
|
107
|
+
throw new errors_1.UnsupportedParameterError({
|
|
108
|
+
client: this.constructor.name,
|
|
109
|
+
parameter: "temperature",
|
|
110
|
+
message: "DeepSeek V4 does not support setting temperature.",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (config.thinking_level !== undefined) {
|
|
114
|
+
deepseekConfig.reasoning = {
|
|
115
|
+
effort: this._convertThinkingLevelToEffort(config.thinking_level),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (config.thinking_summary) {
|
|
119
|
+
// DeepSeek takes reasoning.summary with or without an effort and returns an empty
|
|
120
|
+
// summary list for now (verified live 2026-09-03 on api.deepseek.com and
|
|
121
|
+
// OpenRouter), so the request carries the preference instead of dropping it and
|
|
122
|
+
// picks up summaries as soon as the vendor generates them. False needs no key:
|
|
123
|
+
// the Responses API returns no summary unless one is asked for.
|
|
124
|
+
deepseekConfig.reasoning = deepseekConfig.reasoning ?? {};
|
|
125
|
+
deepseekConfig.reasoning.summary = "concise";
|
|
126
|
+
}
|
|
127
|
+
if (config.tools !== undefined) {
|
|
128
|
+
deepseekConfig.tools = config.tools.map((tool) => ({
|
|
129
|
+
type: "function",
|
|
130
|
+
...tool,
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
if (config.tool_choice !== undefined) {
|
|
134
|
+
deepseekConfig.tool_choice = this._convertToolChoice(config.tool_choice);
|
|
135
|
+
}
|
|
136
|
+
if (config.fast_mode) {
|
|
137
|
+
throw new errors_1.UnsupportedParameterError({
|
|
138
|
+
client: this.constructor.name,
|
|
139
|
+
parameter: "fast_mode",
|
|
140
|
+
message: "DeepSeek V4 does not support fast mode.",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (config.prompt_caching !== undefined &&
|
|
144
|
+
config.prompt_caching !== types_1.PromptCaching.ENABLE) {
|
|
145
|
+
throw new errors_1.UnsupportedParameterError({
|
|
146
|
+
client: this.constructor.name,
|
|
147
|
+
parameter: "prompt_caching",
|
|
148
|
+
message: "prompt_caching must be ENABLE for DeepSeek.",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return deepseekConfig;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Transform universal message format to DeepSeek's Responses-compatible input format.
|
|
155
|
+
*/
|
|
156
|
+
transformUniMessageToModelInput(messages, _signal) {
|
|
157
|
+
// a text-only model answers from a placeholder instead of failing
|
|
158
|
+
// (llmsdk_docs/deepseek_v4/docs/responses-api.md), so an image is refused here rather
|
|
159
|
+
// than silently dropped
|
|
160
|
+
const supportsImage = !TEXT_ONLY_MODELS.test(this._model.toLowerCase().replace(/^.*\//, ""));
|
|
161
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
162
|
+
const inputList = [];
|
|
163
|
+
for (const msg of messages) {
|
|
164
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
165
|
+
const contentItems = [];
|
|
166
|
+
for (const item of msg.content_items) {
|
|
167
|
+
// anything that is not message content becomes an input item of its own, so the
|
|
168
|
+
// text collected so far is flushed first to keep the original order: DeepSeek
|
|
169
|
+
// merges a function call into the adjacent assistant message and answers a call
|
|
170
|
+
// whose output does not follow it with "No tool output found for tool call"
|
|
171
|
+
// (verified live 2026-08-21)
|
|
172
|
+
if (item.type !== "text.done" &&
|
|
173
|
+
item.type !== "image_url.done" &&
|
|
174
|
+
contentItems.length > 0) {
|
|
175
|
+
// Every turn goes back as a typed message item — the Responses API's EasyInputMessage
|
|
176
|
+
// shape, where type "message" is valid for any role. A vLLM-style Responses server
|
|
177
|
+
// answers a bare { role: "assistant", content: [...] } item with a 400 on the turn that
|
|
178
|
+
// replays it and takes the typed form for every role; OpenAI, DeepSeek and MiniMax accept
|
|
179
|
+
// either shape. Nothing beyond that minimal shape goes out: an id or a status the server
|
|
180
|
+
// never sent would be an invention.
|
|
181
|
+
inputList.push({
|
|
182
|
+
type: "message",
|
|
183
|
+
role: msg.role,
|
|
184
|
+
content: [...contentItems],
|
|
185
|
+
});
|
|
186
|
+
contentItems.length = 0;
|
|
187
|
+
}
|
|
188
|
+
if (item.type === "text.done") {
|
|
189
|
+
if (msg.role === "user") {
|
|
190
|
+
contentItems.push({ type: "input_text", text: item.text });
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
contentItems.push({ type: "output_text", text: item.text });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (item.type === "image_url.done") {
|
|
197
|
+
if (!supportsImage) {
|
|
198
|
+
throw new Error(`DeepSeek ${this._model} does not support image inputs.`);
|
|
199
|
+
}
|
|
200
|
+
contentItems.push({ type: "input_image", image_url: item.image_url });
|
|
201
|
+
}
|
|
202
|
+
else if (item.type === "thinking.done") {
|
|
203
|
+
// DeepSeek carries the chain of thought as plain reasoning_text and ignores the
|
|
204
|
+
// summary and encrypted_content channels, so the item is rebuilt from the text
|
|
205
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
206
|
+
const reasoning = { type: "reasoning", summary: [] };
|
|
207
|
+
if (item.thinking) {
|
|
208
|
+
reasoning.content = [
|
|
209
|
+
{ type: "reasoning_text", text: item.thinking },
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
inputList.push(reasoning);
|
|
213
|
+
}
|
|
214
|
+
else if (item.type === "tool_call.done") {
|
|
215
|
+
inputList.push({
|
|
216
|
+
type: "function_call",
|
|
217
|
+
call_id: item.tool_call_id,
|
|
218
|
+
name: item.name,
|
|
219
|
+
arguments: JSON.stringify(item.arguments),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
else if (item.type === "tool_result.done") {
|
|
223
|
+
if (!item.tool_call_id) {
|
|
224
|
+
throw new Error("tool_call_id is required for tool result.");
|
|
225
|
+
}
|
|
226
|
+
// NOTE: tool results are input items
|
|
227
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
228
|
+
const imageParts = [];
|
|
229
|
+
if (item.images) {
|
|
230
|
+
if (!supportsImage) {
|
|
231
|
+
throw new Error(`DeepSeek ${this._model} does not support images in tool results.`);
|
|
232
|
+
}
|
|
233
|
+
for (const imageUrl of item.images) {
|
|
234
|
+
imageParts.push({ type: "input_image", image_url: imageUrl });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// a plain string is the form the Responses API documents for a text
|
|
238
|
+
// result and the one every endpoint fronting this model accepts; the
|
|
239
|
+
// content-part list is reserved for results carrying images
|
|
240
|
+
const output = imageParts.length > 0
|
|
241
|
+
? [{ type: "input_text", text: item.text }, ...imageParts]
|
|
242
|
+
: item.text;
|
|
243
|
+
inputList.push({
|
|
244
|
+
type: "function_call_output",
|
|
245
|
+
call_id: item.tool_call_id,
|
|
246
|
+
output,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
throw new Error(`Unknown item: ${JSON.stringify(item)}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (contentItems.length > 0) {
|
|
254
|
+
inputList.push({
|
|
255
|
+
type: "message",
|
|
256
|
+
role: msg.role,
|
|
257
|
+
content: contentItems,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return inputList;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Transform one DeepSeek stream event into a universal event, identifying items by output
|
|
265
|
+
* item id. An item needs no done: it is done when the next one begins or the stream ends.
|
|
266
|
+
*/
|
|
267
|
+
transformModelOutputToUniEvent(modelOutput) {
|
|
268
|
+
let eventType = "delta";
|
|
269
|
+
const contentItems = [];
|
|
270
|
+
let usageMetadata = null;
|
|
271
|
+
let finishReason = null;
|
|
272
|
+
const deepseekEventType = modelOutput.type;
|
|
273
|
+
if (deepseekEventType === "response.output_text.delta") {
|
|
274
|
+
contentItems.push({
|
|
275
|
+
type: "text.delta",
|
|
276
|
+
text: modelOutput.delta,
|
|
277
|
+
fidelity: { item_id: modelOutput.item_id },
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
else if (deepseekEventType === "response.reasoning_text.delta") {
|
|
281
|
+
contentItems.push({
|
|
282
|
+
type: "thinking.delta",
|
|
283
|
+
thinking: modelOutput.delta,
|
|
284
|
+
fidelity: { item_id: modelOutput.item_id },
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
else if (deepseekEventType === "response.output_item.added") {
|
|
288
|
+
// an item begins: a delta under its id, empty unless it carries the call's name, ends
|
|
289
|
+
// the item before it
|
|
290
|
+
const item = modelOutput.item;
|
|
291
|
+
if (item.type === "function_call") {
|
|
292
|
+
contentItems.push({
|
|
293
|
+
type: "tool_call.delta",
|
|
294
|
+
name: item.name,
|
|
295
|
+
arguments: "",
|
|
296
|
+
tool_call_id: item.call_id,
|
|
297
|
+
// a server that sends no item id still sends the call id
|
|
298
|
+
fidelity: { item_id: item.id || item.call_id },
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
else if (item.type === "message") {
|
|
302
|
+
contentItems.push({
|
|
303
|
+
type: "text.delta",
|
|
304
|
+
text: "",
|
|
305
|
+
fidelity: { item_id: item.id },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
else if (item.type === "reasoning") {
|
|
309
|
+
contentItems.push({
|
|
310
|
+
type: "thinking.delta",
|
|
311
|
+
thinking: "",
|
|
312
|
+
fidelity: { item_id: item.id },
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else if (deepseekEventType === "response.function_call_arguments.delta") {
|
|
317
|
+
contentItems.push({
|
|
318
|
+
type: "tool_call.delta",
|
|
319
|
+
name: "",
|
|
320
|
+
arguments: modelOutput.delta,
|
|
321
|
+
tool_call_id: "",
|
|
322
|
+
fidelity: { item_id: modelOutput.item_id },
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
else if (deepseekEventType === "response.completed" ||
|
|
326
|
+
deepseekEventType === "response.incomplete") {
|
|
327
|
+
eventType = "stop";
|
|
328
|
+
const response = modelOutput.response;
|
|
329
|
+
const finishReasonMapping = {
|
|
330
|
+
completed: "stop",
|
|
331
|
+
incomplete: "length",
|
|
332
|
+
};
|
|
333
|
+
if (response.status) {
|
|
334
|
+
finishReason = finishReasonMapping[response.status] || "unknown";
|
|
335
|
+
}
|
|
336
|
+
if (response.usage) {
|
|
337
|
+
const cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;
|
|
338
|
+
const reasoningTokens = response.usage.output_tokens_details?.reasoning_tokens || 0;
|
|
339
|
+
usageMetadata = {
|
|
340
|
+
cached_tokens: cachedTokens,
|
|
341
|
+
prompt_tokens: response.usage.input_tokens - cachedTokens,
|
|
342
|
+
thoughts_tokens: reasoningTokens,
|
|
343
|
+
response_tokens: response.usage.output_tokens - reasoningTokens,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if ([
|
|
348
|
+
"response.created",
|
|
349
|
+
"response.in_progress",
|
|
350
|
+
"response.output_item.done",
|
|
351
|
+
"response.output_text.done",
|
|
352
|
+
"response.reasoning_text.done",
|
|
353
|
+
"response.function_call_arguments.done",
|
|
354
|
+
"response.content_part.added",
|
|
355
|
+
"response.content_part.done",
|
|
356
|
+
// gateway heartbeat on long generations; carries no content
|
|
357
|
+
"keepalive",
|
|
358
|
+
].includes(deepseekEventType)) {
|
|
359
|
+
// lifecycle events, and repeats of what the deltas carry
|
|
360
|
+
}
|
|
361
|
+
else if ((0, utils_1.isDebugEnabled)()) {
|
|
362
|
+
throw new Error(`Unknown output: ${JSON.stringify(modelOutput)}`);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
// a gateway injects its own events (heartbeats, cost tickers) into the stream, and
|
|
366
|
+
// killing a long generation over one costs more than dropping it
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
role: "assistant",
|
|
370
|
+
event_type: eventType,
|
|
371
|
+
content_items: contentItems,
|
|
372
|
+
usage_metadata: usageMetadata,
|
|
373
|
+
finish_reason: finishReason,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Stream generate using DeepSeek's OpenAI-compatible Responses API.
|
|
378
|
+
*/
|
|
379
|
+
async *_streamingResponseInternal(options) {
|
|
380
|
+
const deepseekConfig = this.transformUniConfigToModelConfig(options.config);
|
|
381
|
+
const inputList = this.transformUniMessageToModelInput(options.messages, options.signal);
|
|
382
|
+
const params = {
|
|
383
|
+
...deepseekConfig,
|
|
384
|
+
input: inputList,
|
|
385
|
+
stream: true,
|
|
386
|
+
};
|
|
387
|
+
const stream = await this._client.responses.create(params, {
|
|
388
|
+
signal: options.signal,
|
|
389
|
+
});
|
|
390
|
+
for await (const event of stream) {
|
|
391
|
+
yield this.transformModelOutputToUniEvent(event);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* List the model ids the configured endpoint serves.
|
|
396
|
+
*
|
|
397
|
+
* @returns The model ids, in the order the endpoint returned them.
|
|
398
|
+
*/
|
|
399
|
+
async listModels() {
|
|
400
|
+
const models = [];
|
|
401
|
+
for await (const model of this._client.models.list()) {
|
|
402
|
+
models.push(model.id);
|
|
403
|
+
}
|
|
404
|
+
return models;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
exports.DeepSeekOfficialClient = DeepSeekOfficialClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/deepseek_official/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,sBAAsB,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.DeepSeekOfficialClient = void 0;
|
|
17
|
+
var client_1 = require("./client");
|
|
18
|
+
Object.defineProperty(exports, "DeepSeekOfficialClient", { enumerable: true, get: function () { return client_1.DeepSeekOfficialClient; } });
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { UsageMetadata } from "./types";
|
|
2
|
+
export declare class MMSPError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Raised when a UniConfig parameter value is not supported by the target model client.
|
|
7
|
+
*
|
|
8
|
+
* Thinking levels never raise this by design: every client maps each ThinkingLevel
|
|
9
|
+
* onto the closest level the model supports. Parameters such as temperature and
|
|
10
|
+
* tool_choice may reject unsupported values with this error.
|
|
11
|
+
*/
|
|
12
|
+
export declare class UnsupportedParameterError extends MMSPError {
|
|
13
|
+
readonly client: string;
|
|
14
|
+
readonly parameter: string;
|
|
15
|
+
constructor(args: {
|
|
16
|
+
client: string;
|
|
17
|
+
parameter: string;
|
|
18
|
+
message: string;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Raised when a completed response carries no non-thinking content and no tool calls.
|
|
23
|
+
*
|
|
24
|
+
* Models occasionally finish a turn with thinking output only (reasoning models in
|
|
25
|
+
* particular); replaying such an assistant message on the next turn fails with a 400
|
|
26
|
+
* error, so the response is rejected as soon as the stream completes.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Raised when a client cannot perform an operation at all, whatever it is passed.
|
|
30
|
+
*
|
|
31
|
+
* Distinct from UnsupportedParameterError, which rejects a UniConfig parameter value:
|
|
32
|
+
* this one reports a capability the routed client does not have, such as listing models
|
|
33
|
+
* through an SDK client that carries no models endpoint.
|
|
34
|
+
*/
|
|
35
|
+
export declare class UnsupportedOperationError extends MMSPError {
|
|
36
|
+
readonly client: string;
|
|
37
|
+
readonly operation: string;
|
|
38
|
+
constructor(args: {
|
|
39
|
+
client: string;
|
|
40
|
+
operation: string;
|
|
41
|
+
message: string;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export declare class EmptyResponseError extends MMSPError {
|
|
45
|
+
readonly client: string;
|
|
46
|
+
readonly finishReason: string | null;
|
|
47
|
+
readonly usageMetadata: UsageMetadata | null;
|
|
48
|
+
constructor(args: {
|
|
49
|
+
client: string;
|
|
50
|
+
finishReason: string | null;
|
|
51
|
+
usageMetadata?: UsageMetadata | null;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Raised when a client produces a stream that breaks the streaming protocol: a content item
|
|
56
|
+
* that is not a delta, a second different fidelity within one item, a tool call whose first
|
|
57
|
+
* delta lacks its name or id, or a delta event carrying usage or a finish reason.
|
|
58
|
+
*
|
|
59
|
+
* It always reports a bug in the client rather than in the provider's output, so it is
|
|
60
|
+
* raised in every mode instead of being repaired into a stream that breaks the contract.
|
|
61
|
+
*/
|
|
62
|
+
export declare class StreamProtocolError extends MMSPError {
|
|
63
|
+
readonly client: string;
|
|
64
|
+
constructor(args: {
|
|
65
|
+
client: string;
|
|
66
|
+
message: string;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export declare class ToolCallArgumentParseError extends MMSPError {
|
|
70
|
+
readonly client: string;
|
|
71
|
+
readonly toolName: string;
|
|
72
|
+
readonly toolCallId: string;
|
|
73
|
+
readonly rawArgumentsLength: number;
|
|
74
|
+
readonly rawArgumentsPreview: string;
|
|
75
|
+
constructor(args: {
|
|
76
|
+
client: string;
|
|
77
|
+
toolName: string;
|
|
78
|
+
toolCallId: string;
|
|
79
|
+
rawArguments: string;
|
|
80
|
+
reason: string;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
export declare function parseToolCallArguments(rawArguments: string | undefined, client: string, toolName: string, toolCallId: string): Record<string, unknown>;
|
|
84
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAWxC,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAMzE;AAED;;;;;;GAMG;AACH;;;;;;GAMG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAMzE;AAED,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAErC,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;gBAEjC,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;KACtC;CAUF;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAKtD;AAED,qBAAa,0BAA2B,SAAQ,SAAS;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;gBAEzB,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB;CAcF;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BzB"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
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.ToolCallArgumentParseError = exports.StreamProtocolError = exports.EmptyResponseError = exports.UnsupportedOperationError = exports.UnsupportedParameterError = exports.MMSPError = void 0;
|
|
17
|
+
exports.parseToolCallArguments = parseToolCallArguments;
|
|
18
|
+
function previewToolCallArguments(raw) {
|
|
19
|
+
const maxLength = 160;
|
|
20
|
+
if (raw.length <= maxLength) {
|
|
21
|
+
return raw;
|
|
22
|
+
}
|
|
23
|
+
const edgeLength = 72;
|
|
24
|
+
return `${raw.slice(0, edgeLength)}...[truncated]...${raw.slice(-edgeLength)}`;
|
|
25
|
+
}
|
|
26
|
+
class MMSPError extends Error {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "MMSPError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.MMSPError = MMSPError;
|
|
33
|
+
/**
|
|
34
|
+
* Raised when a UniConfig parameter value is not supported by the target model client.
|
|
35
|
+
*
|
|
36
|
+
* Thinking levels never raise this by design: every client maps each ThinkingLevel
|
|
37
|
+
* onto the closest level the model supports. Parameters such as temperature and
|
|
38
|
+
* tool_choice may reject unsupported values with this error.
|
|
39
|
+
*/
|
|
40
|
+
class UnsupportedParameterError extends MMSPError {
|
|
41
|
+
constructor(args) {
|
|
42
|
+
super(args.message);
|
|
43
|
+
this.name = "UnsupportedParameterError";
|
|
44
|
+
this.client = args.client;
|
|
45
|
+
this.parameter = args.parameter;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.UnsupportedParameterError = UnsupportedParameterError;
|
|
49
|
+
/**
|
|
50
|
+
* Raised when a completed response carries no non-thinking content and no tool calls.
|
|
51
|
+
*
|
|
52
|
+
* Models occasionally finish a turn with thinking output only (reasoning models in
|
|
53
|
+
* particular); replaying such an assistant message on the next turn fails with a 400
|
|
54
|
+
* error, so the response is rejected as soon as the stream completes.
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Raised when a client cannot perform an operation at all, whatever it is passed.
|
|
58
|
+
*
|
|
59
|
+
* Distinct from UnsupportedParameterError, which rejects a UniConfig parameter value:
|
|
60
|
+
* this one reports a capability the routed client does not have, such as listing models
|
|
61
|
+
* through an SDK client that carries no models endpoint.
|
|
62
|
+
*/
|
|
63
|
+
class UnsupportedOperationError extends MMSPError {
|
|
64
|
+
constructor(args) {
|
|
65
|
+
super(args.message);
|
|
66
|
+
this.name = "UnsupportedOperationError";
|
|
67
|
+
this.client = args.client;
|
|
68
|
+
this.operation = args.operation;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.UnsupportedOperationError = UnsupportedOperationError;
|
|
72
|
+
class EmptyResponseError extends MMSPError {
|
|
73
|
+
constructor(args) {
|
|
74
|
+
super(`${args.client} returned no content other than thinking ` +
|
|
75
|
+
`(finish_reason=${JSON.stringify(args.finishReason)}).`);
|
|
76
|
+
this.name = "EmptyResponseError";
|
|
77
|
+
this.client = args.client;
|
|
78
|
+
this.finishReason = args.finishReason;
|
|
79
|
+
this.usageMetadata = args.usageMetadata ?? null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.EmptyResponseError = EmptyResponseError;
|
|
83
|
+
/**
|
|
84
|
+
* Raised when a client produces a stream that breaks the streaming protocol: a content item
|
|
85
|
+
* that is not a delta, a second different fidelity within one item, a tool call whose first
|
|
86
|
+
* delta lacks its name or id, or a delta event carrying usage or a finish reason.
|
|
87
|
+
*
|
|
88
|
+
* It always reports a bug in the client rather than in the provider's output, so it is
|
|
89
|
+
* raised in every mode instead of being repaired into a stream that breaks the contract.
|
|
90
|
+
*/
|
|
91
|
+
class StreamProtocolError extends MMSPError {
|
|
92
|
+
constructor(args) {
|
|
93
|
+
super(`${args.client} broke the streaming protocol: ${args.message}`);
|
|
94
|
+
this.name = "StreamProtocolError";
|
|
95
|
+
this.client = args.client;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.StreamProtocolError = StreamProtocolError;
|
|
99
|
+
class ToolCallArgumentParseError extends MMSPError {
|
|
100
|
+
constructor(args) {
|
|
101
|
+
const preview = previewToolCallArguments(args.rawArguments);
|
|
102
|
+
super(`Invalid streamed tool call arguments from ${args.client} for tool "${args.toolName}" ` +
|
|
103
|
+
`(tool_call_id="${args.toolCallId}", length=${args.rawArguments.length}, ` +
|
|
104
|
+
`preview=${JSON.stringify(preview)}): ${args.reason}`);
|
|
105
|
+
this.name = "ToolCallArgumentParseError";
|
|
106
|
+
this.client = args.client;
|
|
107
|
+
this.toolName = args.toolName;
|
|
108
|
+
this.toolCallId = args.toolCallId;
|
|
109
|
+
this.rawArgumentsLength = args.rawArguments.length;
|
|
110
|
+
this.rawArgumentsPreview = preview;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.ToolCallArgumentParseError = ToolCallArgumentParseError;
|
|
114
|
+
function parseToolCallArguments(rawArguments, client, toolName, toolCallId) {
|
|
115
|
+
const raw = rawArguments || "{}";
|
|
116
|
+
let parsed;
|
|
117
|
+
try {
|
|
118
|
+
parsed = JSON.parse(raw);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
122
|
+
throw new ToolCallArgumentParseError({
|
|
123
|
+
client,
|
|
124
|
+
toolName,
|
|
125
|
+
toolCallId,
|
|
126
|
+
rawArguments: raw,
|
|
127
|
+
reason,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
131
|
+
throw new ToolCallArgumentParseError({
|
|
132
|
+
client,
|
|
133
|
+
toolName,
|
|
134
|
+
toolCallId,
|
|
135
|
+
rawArguments: raw,
|
|
136
|
+
reason: "Expected a JSON object.",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return parsed;
|
|
140
|
+
}
|