@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.
Files changed (116) hide show
  1. package/README.md +121 -0
  2. package/dist/ant_messages/client.d.ts +59 -0
  3. package/dist/ant_messages/client.d.ts.map +1 -0
  4. package/dist/ant_messages/client.js +419 -0
  5. package/dist/ant_messages/index.d.ts +2 -0
  6. package/dist/ant_messages/index.d.ts.map +1 -0
  7. package/dist/ant_messages/index.js +18 -0
  8. package/dist/anthropic_official/client.d.ts +63 -0
  9. package/dist/anthropic_official/client.d.ts.map +1 -0
  10. package/dist/anthropic_official/client.js +540 -0
  11. package/dist/anthropic_official/index.d.ts +2 -0
  12. package/dist/anthropic_official/index.d.ts.map +1 -0
  13. package/dist/anthropic_official/index.js +18 -0
  14. package/dist/autoClient.d.ts +96 -0
  15. package/dist/autoClient.d.ts.map +1 -0
  16. package/dist/autoClient.js +258 -0
  17. package/dist/baseClient.d.ts +111 -0
  18. package/dist/baseClient.d.ts.map +1 -0
  19. package/dist/baseClient.js +284 -0
  20. package/dist/deepseek_official/client.d.ts +60 -0
  21. package/dist/deepseek_official/client.d.ts.map +1 -0
  22. package/dist/deepseek_official/client.js +407 -0
  23. package/dist/deepseek_official/index.d.ts +2 -0
  24. package/dist/deepseek_official/index.d.ts.map +1 -0
  25. package/dist/deepseek_official/index.js +18 -0
  26. package/dist/errors.d.ts +84 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +140 -0
  29. package/dist/gemini_generate_content/client.d.ts +86 -0
  30. package/dist/gemini_generate_content/client.d.ts.map +1 -0
  31. package/dist/gemini_generate_content/client.js +809 -0
  32. package/dist/gemini_generate_content/index.d.ts +2 -0
  33. package/dist/gemini_generate_content/index.d.ts.map +1 -0
  34. package/dist/gemini_generate_content/index.js +18 -0
  35. package/dist/gemini_official/client.d.ts +87 -0
  36. package/dist/gemini_official/client.d.ts.map +1 -0
  37. package/dist/gemini_official/client.js +780 -0
  38. package/dist/gemini_official/index.d.ts +2 -0
  39. package/dist/gemini_official/index.d.ts.map +1 -0
  40. package/dist/gemini_official/index.js +18 -0
  41. package/dist/index.d.ts +6 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +44 -0
  44. package/dist/integration/index.d.ts +1 -0
  45. package/dist/integration/index.d.ts.map +1 -0
  46. package/dist/integration/index.js +14 -0
  47. package/dist/integration/playground.d.ts +17 -0
  48. package/dist/integration/playground.d.ts.map +1 -0
  49. package/dist/integration/playground.js +3246 -0
  50. package/dist/integration/tracer.d.ts +188 -0
  51. package/dist/integration/tracer.d.ts.map +1 -0
  52. package/dist/integration/tracer.js +1928 -0
  53. package/dist/legacy.d.ts +13 -0
  54. package/dist/legacy.d.ts.map +1 -0
  55. package/dist/legacy.js +59 -0
  56. package/dist/minimax_official/client.d.ts +43 -0
  57. package/dist/minimax_official/client.d.ts.map +1 -0
  58. package/dist/minimax_official/client.js +346 -0
  59. package/dist/minimax_official/index.d.ts +2 -0
  60. package/dist/minimax_official/index.d.ts.map +1 -0
  61. package/dist/minimax_official/index.js +18 -0
  62. package/dist/moonshot_official/client.d.ts +73 -0
  63. package/dist/moonshot_official/client.d.ts.map +1 -0
  64. package/dist/moonshot_official/client.js +477 -0
  65. package/dist/moonshot_official/index.d.ts +2 -0
  66. package/dist/moonshot_official/index.d.ts.map +1 -0
  67. package/dist/moonshot_official/index.js +18 -0
  68. package/dist/openai_chat/client.d.ts +67 -0
  69. package/dist/openai_chat/client.d.ts.map +1 -0
  70. package/dist/openai_chat/client.js +419 -0
  71. package/dist/openai_chat/index.d.ts +2 -0
  72. package/dist/openai_chat/index.d.ts.map +1 -0
  73. package/dist/openai_chat/index.js +18 -0
  74. package/dist/openai_chat_vllm_adapter/client.d.ts +15 -0
  75. package/dist/openai_chat_vllm_adapter/client.d.ts.map +1 -0
  76. package/dist/openai_chat_vllm_adapter/client.js +118 -0
  77. package/dist/openai_chat_vllm_adapter/index.d.ts +2 -0
  78. package/dist/openai_chat_vllm_adapter/index.d.ts.map +1 -0
  79. package/dist/openai_chat_vllm_adapter/index.js +5 -0
  80. package/dist/openai_embedding/client.d.ts +46 -0
  81. package/dist/openai_embedding/client.d.ts.map +1 -0
  82. package/dist/openai_embedding/client.js +124 -0
  83. package/dist/openai_embedding/index.d.ts +2 -0
  84. package/dist/openai_embedding/index.d.ts.map +1 -0
  85. package/dist/openai_embedding/index.js +18 -0
  86. package/dist/openai_official/client.d.ts +61 -0
  87. package/dist/openai_official/client.d.ts.map +1 -0
  88. package/dist/openai_official/client.js +464 -0
  89. package/dist/openai_official/index.d.ts +2 -0
  90. package/dist/openai_official/index.d.ts.map +1 -0
  91. package/dist/openai_official/index.js +18 -0
  92. package/dist/openai_responses/client.d.ts +61 -0
  93. package/dist/openai_responses/client.d.ts.map +1 -0
  94. package/dist/openai_responses/client.js +449 -0
  95. package/dist/openai_responses/index.d.ts +2 -0
  96. package/dist/openai_responses/index.d.ts.map +1 -0
  97. package/dist/openai_responses/index.js +18 -0
  98. package/dist/registry.d.ts +49 -0
  99. package/dist/registry.d.ts.map +1 -0
  100. package/dist/registry.js +798 -0
  101. package/dist/streamItems.d.ts +36 -0
  102. package/dist/streamItems.d.ts.map +1 -0
  103. package/dist/streamItems.js +183 -0
  104. package/dist/types.d.ts +190 -0
  105. package/dist/types.d.ts.map +1 -0
  106. package/dist/types.js +37 -0
  107. package/dist/utils.d.ts +99 -0
  108. package/dist/utils.d.ts.map +1 -0
  109. package/dist/utils.js +312 -0
  110. package/dist/zai_official/client.d.ts +78 -0
  111. package/dist/zai_official/client.d.ts.map +1 -0
  112. package/dist/zai_official/client.js +420 -0
  113. package/dist/zai_official/index.d.ts +2 -0
  114. package/dist/zai_official/index.d.ts.map +1 -0
  115. package/dist/zai_official/index.js +18 -0
  116. package/package.json +68 -0
@@ -0,0 +1,477 @@
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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ var __importDefault = (this && this.__importDefault) || function (mod) {
49
+ return (mod && mod.__esModule) ? mod : { "default": mod };
50
+ };
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.MoonshotOfficialClient = void 0;
53
+ const path = __importStar(require("path"));
54
+ const openai_1 = __importDefault(require("openai"));
55
+ const baseClient_1 = require("../baseClient");
56
+ const errors_1 = require("../errors");
57
+ const types_1 = require("../types");
58
+ const utils_1 = require("../utils");
59
+ /**
60
+ * Kimi K3-specific LLM client implementation using OpenAI-compatible API (also serves K2.5 and K2.6).
61
+ */
62
+ class MoonshotOfficialClient extends baseClient_1.LLMClient {
63
+ /**
64
+ * Initialize Kimi K3 client with model and API key.
65
+ */
66
+ constructor(options) {
67
+ super();
68
+ this._model = options.model;
69
+ // The wrapped OpenAI SDK falls back to OPENAI_API_KEY when handed undefined, which would send
70
+ // an OpenAI credential to the Moonshot host, so resolve the key here and fail loudly instead.
71
+ const key = options.apiKey || process.env.MOONSHOT_API_KEY;
72
+ if (!key) {
73
+ throw new Error("MOONSHOT_API_KEY is required for MoonshotOfficialClient.");
74
+ }
75
+ const url = options.baseUrl ||
76
+ process.env.MOONSHOT_BASE_URL ||
77
+ "https://api.moonshot.cn/v1";
78
+ this._client = new openai_1.default({
79
+ apiKey: key,
80
+ baseURL: url,
81
+ defaultHeaders: options.defaultHeaders,
82
+ });
83
+ }
84
+ /**
85
+ * Detect MIME type from URL extension for image.
86
+ */
87
+ _detectImageMimeType(url) {
88
+ const ext = path.extname(url).toLowerCase();
89
+ const mimeTypes = {
90
+ ".bmp": "image/bmp",
91
+ ".gif": "image/gif",
92
+ ".jpg": "image/jpeg",
93
+ ".jpeg": "image/jpeg",
94
+ ".png": "image/png",
95
+ ".svg": "image/svg+xml",
96
+ ".tiff": "image/tiff",
97
+ ".webp": "image/webp",
98
+ };
99
+ return mimeTypes[ext] || "image/jpeg";
100
+ }
101
+ /**
102
+ * Convert image URL to base64-encoded data URL.
103
+ */
104
+ async _convertImageUrlToBase64(url, signal) {
105
+ if (url.startsWith("data:")) {
106
+ return url;
107
+ }
108
+ const response = await fetch(url, { signal });
109
+ if (!response.ok) {
110
+ throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
111
+ }
112
+ const arrayBuffer = await response.arrayBuffer();
113
+ const buffer = Buffer.from(arrayBuffer);
114
+ const mimeType = this._detectImageMimeType(url);
115
+ const base64String = buffer.toString("base64");
116
+ return `data:${mimeType};base64,${base64String}`;
117
+ }
118
+ /**
119
+ * Convert ThinkingLevel enum to the K2-generation thinking configuration.
120
+ */
121
+ _convertThinkingLevelToThinkingConfig(thinkingLevel) {
122
+ const mapping = {
123
+ [types_1.ThinkingLevel.NONE]: { type: "disabled" },
124
+ [types_1.ThinkingLevel.LOW]: { type: "enabled", keep: "all" },
125
+ [types_1.ThinkingLevel.MEDIUM]: { type: "enabled", keep: "all" },
126
+ [types_1.ThinkingLevel.HIGH]: { type: "enabled", keep: "all" },
127
+ [types_1.ThinkingLevel.XHIGH]: { type: "enabled", keep: "all" },
128
+ [types_1.ThinkingLevel.MAX]: { type: "enabled", keep: "all" },
129
+ };
130
+ return mapping[thinkingLevel];
131
+ }
132
+ /**
133
+ * Convert ThinkingLevel enum to Kimi K3's reasoning_effort.
134
+ *
135
+ * K3 cannot disable reasoning, so NONE degrades to the lowest effort
136
+ * instead of throwing.
137
+ */
138
+ _convertThinkingLevelToReasoningEffort(thinkingLevel) {
139
+ const mapping = {
140
+ [types_1.ThinkingLevel.NONE]: "low",
141
+ [types_1.ThinkingLevel.LOW]: "low",
142
+ [types_1.ThinkingLevel.MEDIUM]: "high",
143
+ [types_1.ThinkingLevel.HIGH]: "high",
144
+ [types_1.ThinkingLevel.XHIGH]: "max",
145
+ [types_1.ThinkingLevel.MAX]: "max",
146
+ };
147
+ return mapping[thinkingLevel];
148
+ }
149
+ /**
150
+ * Convert ToolChoice to OpenAI's tool_choice format.
151
+ */
152
+ _convertToolChoice(toolChoice) {
153
+ if (toolChoice === "auto") {
154
+ return "auto";
155
+ }
156
+ else if (toolChoice === "none") {
157
+ return "none";
158
+ }
159
+ else if (toolChoice === "required" &&
160
+ !this._model.toLowerCase().includes("k2.")) {
161
+ return "required";
162
+ }
163
+ else {
164
+ // the K2 generation rejects "required"; forcing a specific tool is
165
+ // unsupported family-wide
166
+ throw new errors_1.UnsupportedParameterError({
167
+ client: this.constructor.name,
168
+ parameter: "tool_choice",
169
+ message: "Kimi does not support this tool_choice ('required' needs Kimi K3).",
170
+ });
171
+ }
172
+ }
173
+ /**
174
+ * Transform universal configuration to Kimi K3-specific configuration.
175
+ */
176
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
+ transformUniConfigToModelConfig(config) {
178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
+ const kimiConfig = {
180
+ model: this._model,
181
+ stream: true,
182
+ stream_options: { include_usage: true },
183
+ };
184
+ if (config.max_tokens !== undefined) {
185
+ kimiConfig.max_completion_tokens = config.max_tokens;
186
+ }
187
+ if (config.temperature !== undefined && config.temperature !== 1.0) {
188
+ throw new errors_1.UnsupportedParameterError({
189
+ client: this.constructor.name,
190
+ parameter: "temperature",
191
+ message: "Kimi does not support setting temperature.",
192
+ });
193
+ }
194
+ if (config.thinking_level !== undefined) {
195
+ // the K2 generation configures thinking through extra_body and can disable
196
+ // it; K3 uses reasoning_effort and cannot
197
+ if (this._model.toLowerCase().includes("k2.")) {
198
+ kimiConfig.extra_body = kimiConfig.extra_body || {};
199
+ kimiConfig.extra_body.thinking =
200
+ this._convertThinkingLevelToThinkingConfig(config.thinking_level);
201
+ }
202
+ else {
203
+ kimiConfig.reasoning_effort =
204
+ this._convertThinkingLevelToReasoningEffort(config.thinking_level);
205
+ }
206
+ }
207
+ if (config.tools !== undefined) {
208
+ kimiConfig.tools = config.tools.map((tool) => ({
209
+ type: "function",
210
+ function: tool,
211
+ }));
212
+ }
213
+ if (config.tool_choice !== undefined) {
214
+ kimiConfig.tool_choice = this._convertToolChoice(config.tool_choice);
215
+ }
216
+ if (config.fast_mode) {
217
+ throw new errors_1.UnsupportedParameterError({
218
+ client: this.constructor.name,
219
+ parameter: "fast_mode",
220
+ message: "Kimi does not support fast mode.",
221
+ });
222
+ }
223
+ if (config.prompt_caching !== undefined &&
224
+ config.prompt_caching !== types_1.PromptCaching.ENABLE) {
225
+ throw new errors_1.UnsupportedParameterError({
226
+ client: this.constructor.name,
227
+ parameter: "prompt_caching",
228
+ message: "prompt_caching must be ENABLE for Kimi.",
229
+ });
230
+ }
231
+ // K3 context caching is automatic; the K2 generation keys its prompt
232
+ // cache on trace_id
233
+ if (config.trace_id !== undefined &&
234
+ this._model.toLowerCase().includes("k2.")) {
235
+ kimiConfig.prompt_cache_key = config.trace_id;
236
+ }
237
+ return kimiConfig;
238
+ }
239
+ /**
240
+ * Transform universal message format to OpenAI's message format.
241
+ */
242
+ async transformUniMessageToModelInput(messages, signal) {
243
+ const openaiMessages = [];
244
+ for (const msg of messages) {
245
+ const contentParts = [];
246
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
+ const toolCalls = [];
248
+ let thinking = "";
249
+ const thinkingFields = new Set();
250
+ for (const item of msg.content_items) {
251
+ if (item.type === "text.done") {
252
+ contentParts.push({ type: "text", text: item.text });
253
+ }
254
+ else if (item.type === "image_url.done") {
255
+ const base64Image = await this._convertImageUrlToBase64(item.image_url, signal);
256
+ contentParts.push({
257
+ type: "image_url",
258
+ image_url: { url: base64Image },
259
+ });
260
+ }
261
+ else if (item.type === "thinking.done") {
262
+ thinking += item.thinking;
263
+ thinkingFields.add(item.fidelity?.reasoning_field);
264
+ }
265
+ else if (item.type === "tool_call.done") {
266
+ toolCalls.push({
267
+ id: item.tool_call_id,
268
+ type: "function",
269
+ function: {
270
+ name: item.name,
271
+ arguments: JSON.stringify(item.arguments, null, 0),
272
+ },
273
+ });
274
+ }
275
+ else if (item.type === "tool_result.done") {
276
+ if (!item.tool_call_id) {
277
+ throw new Error("tool_call_id is required for tool result.");
278
+ }
279
+ // Chat Completions lets a tool message carry text only, and a server that
280
+ // validates the schema rejects the whole request over an image part in one.
281
+ // The images ride in the user message that follows the turn's tool messages,
282
+ // the one place every OpenAI-compatible server reads them.
283
+ if (item.images && item.images.length > 0) {
284
+ for (const imageUrl of item.images) {
285
+ const base64Image = await this._convertImageUrlToBase64(imageUrl, signal);
286
+ contentParts.push({
287
+ type: "image_url",
288
+ image_url: { url: base64Image },
289
+ });
290
+ }
291
+ }
292
+ // the plain string is the form Moonshot's own tool-call examples send and every
293
+ // OpenAI-compatible server accepts
294
+ openaiMessages.push({
295
+ role: "tool",
296
+ tool_call_id: item.tool_call_id,
297
+ content: item.text,
298
+ });
299
+ }
300
+ else {
301
+ throw new Error(`Unknown item type: ${item.type}`);
302
+ }
303
+ }
304
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
305
+ const message = { role: msg.role };
306
+ if (contentParts.length > 0) {
307
+ message.content = contentParts;
308
+ }
309
+ if (toolCalls.length > 0) {
310
+ message.tool_calls = toolCalls;
311
+ }
312
+ if (thinking) {
313
+ // send thinking back through the exact field the upstream produced (recorded
314
+ // in the item fidelity); servers may reject the spelling they did not emit
315
+ if (thinkingFields.size === 1 &&
316
+ thinkingFields.has("reasoning_content")) {
317
+ message.reasoning_content = thinking;
318
+ }
319
+ else if (thinkingFields.size === 1 &&
320
+ thinkingFields.has("reasoning")) {
321
+ message.reasoning = thinking;
322
+ }
323
+ else {
324
+ message.reasoning_content = thinking; // vLLM & siliconflow compatibility
325
+ message.reasoning = thinking; // openrouter compatibility
326
+ }
327
+ }
328
+ if (Object.keys(message).length > 1) {
329
+ openaiMessages.push(message);
330
+ }
331
+ }
332
+ return openaiMessages;
333
+ }
334
+ /**
335
+ * Transform one Kimi K3 streaming chunk into a universal event.
336
+ *
337
+ * Chat Completions gives an item no identity, so each delta's item_id is the wire field
338
+ * that carried it: an item runs until a delta arrives from another field, or names the next
339
+ * tool call.
340
+ */
341
+ transformModelOutputToUniEvent(modelOutput) {
342
+ let eventType = "delta";
343
+ const contentItems = [];
344
+ let usageMetadata = null;
345
+ let finishReason = null;
346
+ // gateways inject content-free heartbeat chunks on long generations, whose
347
+ // choices arrive as undefined rather than an empty list
348
+ if (modelOutput.choices?.length) {
349
+ const choice = modelOutput.choices[0];
350
+ const delta = choice?.delta;
351
+ // the thinking field name differs by server: vLLM & siliconflow use
352
+ // reasoning_content while openrouter uses reasoning; record the wire
353
+ // field that carried each delta so a replay can reproduce exactly the
354
+ // field the upstream produced. The reasoning goes before the content
355
+ // because a chunk may end the reasoning and begin the answer.
356
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
+ const reasoningContent = delta?.reasoning_content;
358
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
359
+ const reasoning = delta?.reasoning;
360
+ if (reasoningContent && reasoning) {
361
+ // ambiguous origin: record no reasoning_field so a replay sends both fields back
362
+ contentItems.push({
363
+ type: "thinking.delta",
364
+ thinking: reasoningContent,
365
+ fidelity: { item_id: "reasoning_content" },
366
+ });
367
+ }
368
+ else if (reasoningContent) {
369
+ contentItems.push({
370
+ type: "thinking.delta",
371
+ thinking: reasoningContent,
372
+ fidelity: {
373
+ item_id: "reasoning_content",
374
+ reasoning_field: "reasoning_content",
375
+ },
376
+ });
377
+ }
378
+ else if (reasoning) {
379
+ contentItems.push({
380
+ type: "thinking.delta",
381
+ thinking: reasoning,
382
+ fidelity: { item_id: "reasoning", reasoning_field: "reasoning" },
383
+ });
384
+ }
385
+ if (delta?.content) {
386
+ contentItems.push({
387
+ type: "text.delta",
388
+ text: delta.content,
389
+ fidelity: { item_id: "content" },
390
+ });
391
+ }
392
+ if (delta?.tool_calls) {
393
+ for (const toolCall of delta.tool_calls) {
394
+ contentItems.push({
395
+ type: "tool_call.delta",
396
+ name: toolCall.function?.name || "",
397
+ arguments: toolCall.function?.arguments || "",
398
+ tool_call_id: toolCall.id || "",
399
+ fidelity: { item_id: "tool_calls" },
400
+ });
401
+ }
402
+ }
403
+ if (choice?.finish_reason) {
404
+ eventType = "stop";
405
+ const finishReasonMapping = {
406
+ stop: "stop",
407
+ length: "length",
408
+ tool_calls: "tool_call",
409
+ content_filter: "stop",
410
+ };
411
+ finishReason = finishReasonMapping[choice.finish_reason] || "unknown";
412
+ }
413
+ }
414
+ if (modelOutput.usage) {
415
+ eventType = "stop";
416
+ const cachedTokens = modelOutput.usage.prompt_tokens_details?.cached_tokens || null;
417
+ const reasoningTokens = modelOutput.usage.completion_tokens_details?.reasoning_tokens || null;
418
+ const promptTokens = cachedTokens !== null
419
+ ? modelOutput.usage.prompt_tokens - cachedTokens
420
+ : modelOutput.usage.prompt_tokens;
421
+ const responseTokens = reasoningTokens !== null
422
+ ? modelOutput.usage.completion_tokens - reasoningTokens
423
+ : modelOutput.usage.completion_tokens;
424
+ usageMetadata = {
425
+ cached_tokens: cachedTokens,
426
+ prompt_tokens: promptTokens,
427
+ thoughts_tokens: reasoningTokens,
428
+ response_tokens: responseTokens,
429
+ };
430
+ usageMetadata = (0, utils_1.fixOpenrouterUsageMetadata)(usageMetadata, this._client.baseURL);
431
+ }
432
+ return {
433
+ role: "assistant",
434
+ event_type: eventType,
435
+ content_items: contentItems,
436
+ usage_metadata: usageMetadata,
437
+ finish_reason: finishReason,
438
+ };
439
+ }
440
+ /**
441
+ * Stream generate using Kimi SDK with unified conversion methods.
442
+ */
443
+ async *_streamingResponseInternal(options) {
444
+ const kimiConfig = this.transformUniConfigToModelConfig(options.config);
445
+ const kimiMessages = await this.transformUniMessageToModelInput(options.messages, options.signal);
446
+ if (options.config.system_prompt) {
447
+ kimiMessages.unshift({
448
+ role: "system",
449
+ content: options.config.system_prompt,
450
+ });
451
+ }
452
+ const params = {
453
+ ...kimiConfig,
454
+ messages: kimiMessages,
455
+ stream: true,
456
+ };
457
+ const stream = await this._client.chat.completions.create(params, {
458
+ signal: options.signal,
459
+ });
460
+ for await (const chunk of stream) {
461
+ yield this.transformModelOutputToUniEvent(chunk);
462
+ }
463
+ }
464
+ /**
465
+ * List the model ids the configured endpoint serves.
466
+ *
467
+ * @returns The model ids, in the order the endpoint returned them.
468
+ */
469
+ async listModels() {
470
+ const models = [];
471
+ for await (const model of this._client.models.list()) {
472
+ models.push(model.id);
473
+ }
474
+ return models;
475
+ }
476
+ }
477
+ exports.MoonshotOfficialClient = MoonshotOfficialClient;
@@ -0,0 +1,2 @@
1
+ export { MoonshotOfficialClient } from "./client";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/moonshot_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.MoonshotOfficialClient = void 0;
17
+ var client_1 = require("./client");
18
+ Object.defineProperty(exports, "MoonshotOfficialClient", { enumerable: true, get: function () { return client_1.MoonshotOfficialClient; } });
@@ -0,0 +1,67 @@
1
+ import type { ChatCompletionChunk, ChatCompletionMessageParam } from "openai/resources/chat/completions";
2
+ import { LLMClient } from "../baseClient";
3
+ import { UniConfig, UniEvent, UniMessage } from "../types";
4
+ /**
5
+ * OpenAI Chat Completions-compatible client implementation.
6
+ */
7
+ export declare class OpenaiChatClient extends LLMClient {
8
+ protected _model: string;
9
+ private _client;
10
+ /**
11
+ * Initialize OpenAI-compatible chat client with model, API key, and base URL.
12
+ */
13
+ constructor(options: {
14
+ model: string;
15
+ apiKey?: string;
16
+ baseUrl?: string | null;
17
+ defaultHeaders?: Record<string, string>;
18
+ });
19
+ /**
20
+ * Detect MIME type from URL extension for image.
21
+ */
22
+ private _detectImageMimeType;
23
+ /**
24
+ * Convert image URL to base64-encoded data URL.
25
+ */
26
+ private _convertImageUrlToBase64;
27
+ /**
28
+ * Convert ToolChoice to OpenAI Chat Completions tool_choice format.
29
+ */
30
+ private _convertToolChoice;
31
+ /**
32
+ * Convert a fetched image to an image_url part, at the detail the API needs
33
+ * to read it.
34
+ */
35
+ private _convertImageUrl;
36
+ /**
37
+ * Transform universal configuration to OpenAI Chat Completions configuration.
38
+ */
39
+ transformUniConfigToModelConfig(config: UniConfig): any;
40
+ /**
41
+ * Transform universal message format to OpenAI Chat Completions message format.
42
+ */
43
+ transformUniMessageToModelInput(messages: UniMessage[], signal?: AbortSignal): Promise<ChatCompletionMessageParam[]>;
44
+ /**
45
+ * Transform one OpenAI Chat Completions streaming chunk into a universal event.
46
+ *
47
+ * Chat Completions gives an item no identity, so each delta's item_id is the wire field
48
+ * that carried it: an item runs until a delta arrives from another field, or names the next
49
+ * tool call.
50
+ */
51
+ transformModelOutputToUniEvent(modelOutput: ChatCompletionChunk): UniEvent;
52
+ /**
53
+ * Stream generate using OpenAI Chat Completions-compatible API.
54
+ */
55
+ _streamingResponseInternal(options: {
56
+ messages: UniMessage[];
57
+ config: UniConfig;
58
+ signal?: AbortSignal;
59
+ }): AsyncGenerator<UniEvent>;
60
+ /**
61
+ * List the model ids the configured endpoint serves.
62
+ *
63
+ * @returns The model ids, in the order the endpoint returned them.
64
+ */
65
+ listModels(): Promise<string[]>;
66
+ }
67
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/openai_chat/client.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EACnB,0BAA0B,EAE3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAML,SAAS,EACT,QAAQ,EACR,UAAU,EAEX,MAAM,UAAU,CAAC;AAOlB;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,OAAO,CAAS;IAExB;;OAEG;gBACS,OAAO,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACzC;IAeD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;OAEG;YACW,wBAAwB;IAqBtC;;OAEG;IAEH,OAAO,CAAC,kBAAkB;IAiB1B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IAEH,+BAA+B,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG;IA6CvD;;OAEG;IACG,+BAA+B,CACnC,QAAQ,EAAE,UAAU,EAAE,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,0BAA0B,EAAE,CAAC;IA6GxC;;;;;;OAMG;IACH,8BAA8B,CAAC,WAAW,EAAE,mBAAmB,GAAG,QAAQ;IAmH1E;;OAEG;IACI,0BAA0B,CAAC,OAAO,EAAE;QACzC,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,MAAM,EAAE,SAAS,CAAC;QAClB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,cAAc,CAAC,QAAQ,CAAC;IA6B5B;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAQtC"}