kimi-vercel-ai-sdk-provider 0.2.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 (44) hide show
  1. package/LICENSE +198 -0
  2. package/README.md +871 -0
  3. package/dist/index.d.mts +1317 -0
  4. package/dist/index.d.ts +1317 -0
  5. package/dist/index.js +2764 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +2734 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +70 -0
  10. package/src/__tests__/caching.test.ts +97 -0
  11. package/src/__tests__/chat.test.ts +386 -0
  12. package/src/__tests__/code-integration.test.ts +562 -0
  13. package/src/__tests__/code-provider.test.ts +289 -0
  14. package/src/__tests__/code.test.ts +427 -0
  15. package/src/__tests__/core.test.ts +172 -0
  16. package/src/__tests__/files.test.ts +185 -0
  17. package/src/__tests__/integration.test.ts +457 -0
  18. package/src/__tests__/provider.test.ts +188 -0
  19. package/src/__tests__/tools.test.ts +519 -0
  20. package/src/chat/index.ts +42 -0
  21. package/src/chat/kimi-chat-language-model.ts +829 -0
  22. package/src/chat/kimi-chat-messages.ts +297 -0
  23. package/src/chat/kimi-chat-response.ts +84 -0
  24. package/src/chat/kimi-chat-settings.ts +216 -0
  25. package/src/code/index.ts +66 -0
  26. package/src/code/kimi-code-language-model.ts +669 -0
  27. package/src/code/kimi-code-messages.ts +303 -0
  28. package/src/code/kimi-code-provider.ts +239 -0
  29. package/src/code/kimi-code-settings.ts +193 -0
  30. package/src/code/kimi-code-types.ts +354 -0
  31. package/src/core/errors.ts +140 -0
  32. package/src/core/index.ts +36 -0
  33. package/src/core/types.ts +148 -0
  34. package/src/core/utils.ts +210 -0
  35. package/src/files/attachment-processor.ts +276 -0
  36. package/src/files/file-utils.ts +257 -0
  37. package/src/files/index.ts +24 -0
  38. package/src/files/kimi-file-client.ts +292 -0
  39. package/src/index.ts +122 -0
  40. package/src/kimi-provider.ts +263 -0
  41. package/src/tools/builtin-tools.ts +273 -0
  42. package/src/tools/index.ts +33 -0
  43. package/src/tools/prepare-tools.ts +306 -0
  44. package/src/version.ts +4 -0
package/dist/index.js ADDED
@@ -0,0 +1,2764 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ KIMI_CODE_BASE_URL: () => KIMI_CODE_BASE_URL,
24
+ KIMI_CODE_DEFAULT_MODEL: () => KIMI_CODE_DEFAULT_MODEL,
25
+ KIMI_CODE_INTERPRETER_TOOL_NAME: () => KIMI_CODE_INTERPRETER_TOOL_NAME,
26
+ KIMI_CODE_THINKING_MODEL: () => KIMI_CODE_THINKING_MODEL,
27
+ KIMI_WEB_SEARCH_TOOL_NAME: () => KIMI_WEB_SEARCH_TOOL_NAME,
28
+ KimiAuthenticationError: () => KimiAuthenticationError,
29
+ KimiChatLanguageModel: () => KimiChatLanguageModel,
30
+ KimiCodeLanguageModel: () => KimiCodeLanguageModel,
31
+ KimiContentFilterError: () => KimiContentFilterError,
32
+ KimiContextLengthError: () => KimiContextLengthError,
33
+ KimiError: () => KimiError,
34
+ KimiFileClient: () => KimiFileClient,
35
+ KimiModelNotFoundError: () => KimiModelNotFoundError,
36
+ KimiRateLimitError: () => KimiRateLimitError,
37
+ KimiValidationError: () => KimiValidationError,
38
+ SUPPORTED_FILE_EXTENSIONS: () => SUPPORTED_FILE_EXTENSIONS,
39
+ SUPPORTED_MIME_TYPES: () => SUPPORTED_MIME_TYPES,
40
+ createCodeInterpreterTool: () => createCodeInterpreterTool,
41
+ createKimi: () => createKimi,
42
+ createKimiCode: () => createKimiCode,
43
+ createKimiWebSearchTool: () => createKimiWebSearchTool,
44
+ createWebSearchTool: () => createWebSearchTool,
45
+ getMediaTypeFromExtension: () => getMediaTypeFromExtension,
46
+ getPurposeFromMediaType: () => getPurposeFromMediaType,
47
+ inferKimiCodeCapabilities: () => inferKimiCodeCapabilities,
48
+ inferModelCapabilities: () => inferModelCapabilities,
49
+ isDocumentMediaType: () => isDocumentMediaType,
50
+ isFileExtractMediaType: () => isFileExtractMediaType,
51
+ isImageMediaType: () => isImageMediaType2,
52
+ isVideoMediaType: () => isVideoMediaType2,
53
+ kimi: () => kimi,
54
+ kimiCachingConfigSchema: () => kimiCachingConfigSchema,
55
+ kimiCode: () => kimiCode,
56
+ kimiCodeProviderOptionsSchema: () => kimiCodeProviderOptionsSchema,
57
+ kimiProviderOptionsSchema: () => kimiProviderOptionsSchema,
58
+ kimiTools: () => kimiTools,
59
+ processAttachments: () => processAttachments
60
+ });
61
+ module.exports = __toCommonJS(index_exports);
62
+
63
+ // src/kimi-provider.ts
64
+ var import_provider4 = require("@ai-sdk/provider");
65
+ var import_provider_utils4 = require("@ai-sdk/provider-utils");
66
+
67
+ // src/chat/kimi-chat-language-model.ts
68
+ var import_provider3 = require("@ai-sdk/provider");
69
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
70
+ var import_v43 = require("zod/v4");
71
+
72
+ // src/core/errors.ts
73
+ var import_provider_utils = require("@ai-sdk/provider-utils");
74
+ var import_v4 = require("zod/v4");
75
+ var kimiErrorSchema = import_v4.z.union([
76
+ import_v4.z.object({
77
+ error: import_v4.z.object({
78
+ message: import_v4.z.string(),
79
+ type: import_v4.z.string().nullish(),
80
+ param: import_v4.z.any().nullish(),
81
+ code: import_v4.z.union([import_v4.z.string(), import_v4.z.number()]).nullish(),
82
+ request_id: import_v4.z.string().nullish()
83
+ })
84
+ }),
85
+ import_v4.z.object({
86
+ message: import_v4.z.string()
87
+ })
88
+ ]);
89
+ var kimiFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
90
+ errorSchema: kimiErrorSchema,
91
+ errorToMessage: (error) => {
92
+ if ("error" in error) {
93
+ return error.error.message;
94
+ }
95
+ return error.message;
96
+ },
97
+ isRetryable: (response) => response.status === 408 || response.status === 409 || response.status === 429 || response.status >= 500
98
+ });
99
+ var KimiError = class extends Error {
100
+ constructor(message, code, statusCode) {
101
+ super(message);
102
+ this.name = "KimiError";
103
+ this.code = code;
104
+ this.statusCode = statusCode;
105
+ }
106
+ };
107
+ var KimiAuthenticationError = class extends KimiError {
108
+ constructor(message = "Invalid API key or authentication failed") {
109
+ super(message, "authentication_error", 401);
110
+ this.name = "KimiAuthenticationError";
111
+ }
112
+ };
113
+ var KimiRateLimitError = class extends KimiError {
114
+ constructor(message = "Rate limit exceeded", retryAfter) {
115
+ super(message, "rate_limit_error", 429);
116
+ this.name = "KimiRateLimitError";
117
+ this.retryAfter = retryAfter;
118
+ }
119
+ };
120
+ var KimiValidationError = class extends KimiError {
121
+ constructor(message, param) {
122
+ super(param ? `${message} (param: ${param})` : message, "validation_error", 400);
123
+ this.name = "KimiValidationError";
124
+ }
125
+ };
126
+ var KimiModelNotFoundError = class extends KimiError {
127
+ constructor(modelId) {
128
+ super(`Model '${modelId}' not found`, "model_not_found", 404);
129
+ this.name = "KimiModelNotFoundError";
130
+ this.modelId = modelId;
131
+ }
132
+ };
133
+ var KimiContentFilterError = class extends KimiError {
134
+ constructor(message = "Content was filtered due to policy violation") {
135
+ super(message, "content_filter", 400);
136
+ this.name = "KimiContentFilterError";
137
+ }
138
+ };
139
+ var KimiContextLengthError = class extends KimiError {
140
+ constructor(message = "Context length exceeded") {
141
+ super(message, "context_length_exceeded", 400);
142
+ this.name = "KimiContextLengthError";
143
+ }
144
+ };
145
+
146
+ // src/core/types.ts
147
+ function inferModelCapabilities(modelId) {
148
+ const isThinkingModel = modelId.includes("-thinking");
149
+ const isK25Model = modelId.includes("k2.5") || modelId.includes("k2-5");
150
+ return {
151
+ thinking: isThinkingModel,
152
+ alwaysThinking: isThinkingModel,
153
+ imageInput: true,
154
+ // All Kimi models support images
155
+ videoInput: isK25Model,
156
+ // Only K2.5 models support video
157
+ maxContextSize: 256e3,
158
+ // 256k context window
159
+ toolCalling: true,
160
+ jsonMode: true,
161
+ structuredOutputs: true
162
+ };
163
+ }
164
+
165
+ // src/core/utils.ts
166
+ function mapKimiFinishReason(finishReason) {
167
+ switch (finishReason) {
168
+ case "stop":
169
+ return "stop";
170
+ case "length":
171
+ return "length";
172
+ case "content_filter":
173
+ return "content-filter";
174
+ case "tool_calls":
175
+ case "function_call":
176
+ return "tool-calls";
177
+ default:
178
+ return "other";
179
+ }
180
+ }
181
+ function convertKimiUsage(usage, webSearchTokens, codeInterpreterTokens) {
182
+ if (usage == null) {
183
+ return {
184
+ inputTokens: {
185
+ total: void 0,
186
+ noCache: void 0,
187
+ cacheRead: void 0,
188
+ cacheWrite: void 0
189
+ },
190
+ outputTokens: {
191
+ total: void 0,
192
+ text: void 0,
193
+ reasoning: void 0
194
+ },
195
+ raw: void 0,
196
+ ...webSearchTokens != null ? { webSearchTokens } : {},
197
+ ...codeInterpreterTokens != null ? { codeInterpreterTokens } : {}
198
+ };
199
+ }
200
+ const promptTokens = usage.prompt_tokens ?? 0;
201
+ const completionTokens = usage.completion_tokens ?? 0;
202
+ const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;
203
+ const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;
204
+ const rawUsage = {
205
+ prompt_tokens: usage.prompt_tokens ?? void 0,
206
+ completion_tokens: usage.completion_tokens ?? void 0,
207
+ total_tokens: usage.total_tokens ?? void 0,
208
+ ...usage.prompt_tokens_details ? {
209
+ prompt_tokens_details: {
210
+ cached_tokens: usage.prompt_tokens_details.cached_tokens ?? void 0
211
+ }
212
+ } : {},
213
+ ...usage.completion_tokens_details ? {
214
+ completion_tokens_details: {
215
+ reasoning_tokens: usage.completion_tokens_details.reasoning_tokens ?? void 0
216
+ }
217
+ } : {}
218
+ };
219
+ return {
220
+ inputTokens: {
221
+ total: promptTokens,
222
+ noCache: promptTokens - cacheReadTokens,
223
+ cacheRead: cacheReadTokens,
224
+ cacheWrite: void 0
225
+ },
226
+ outputTokens: {
227
+ total: completionTokens,
228
+ text: completionTokens - reasoningTokens,
229
+ reasoning: reasoningTokens
230
+ },
231
+ raw: rawUsage,
232
+ ...webSearchTokens != null ? { webSearchTokens } : {},
233
+ ...codeInterpreterTokens != null ? { codeInterpreterTokens } : {}
234
+ };
235
+ }
236
+ function getResponseMetadata(response) {
237
+ return {
238
+ id: response.id ?? void 0,
239
+ modelId: response.model ?? void 0,
240
+ timestamp: response.created != null ? new Date(response.created * 1e3) : void 0
241
+ };
242
+ }
243
+ function getKimiRequestId(headers) {
244
+ if (!headers) {
245
+ return void 0;
246
+ }
247
+ const lowerHeaders = Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]));
248
+ return lowerHeaders["x-request-id"] || lowerHeaders["x-trace-id"] || lowerHeaders["x-moonshot-request-id"];
249
+ }
250
+ function extractMessageContent(message) {
251
+ let text = "";
252
+ let reasoning = "";
253
+ if (typeof message.content === "string") {
254
+ text = message.content;
255
+ } else if (Array.isArray(message.content)) {
256
+ for (const part of message.content) {
257
+ if (part && typeof part === "object") {
258
+ const candidate = part;
259
+ if (candidate.type === "text" && typeof candidate.text === "string") {
260
+ text += candidate.text;
261
+ }
262
+ if (candidate.type === "thinking" && typeof candidate.thinking === "string") {
263
+ reasoning += candidate.thinking;
264
+ }
265
+ if (candidate.type === "reasoning" && typeof candidate.text === "string") {
266
+ reasoning += candidate.text;
267
+ }
268
+ }
269
+ }
270
+ }
271
+ if (typeof message.reasoning_content === "string") {
272
+ reasoning += message.reasoning_content;
273
+ }
274
+ if (typeof message.reasoning === "string") {
275
+ reasoning += message.reasoning;
276
+ }
277
+ return { text, reasoning };
278
+ }
279
+
280
+ // src/tools/builtin-tools.ts
281
+ var KIMI_WEB_SEARCH_TOOL_NAME = "$web_search";
282
+ var KIMI_CODE_INTERPRETER_TOOL_NAME = "$code";
283
+ function createWebSearchTool(config) {
284
+ return {
285
+ type: "builtin_function",
286
+ function: {
287
+ name: KIMI_WEB_SEARCH_TOOL_NAME,
288
+ ...config ? { config } : {}
289
+ }
290
+ };
291
+ }
292
+ function createKimiWebSearchTool(config) {
293
+ return createWebSearchTool(config);
294
+ }
295
+ function createCodeInterpreterTool(config) {
296
+ return {
297
+ type: "builtin_function",
298
+ function: {
299
+ name: KIMI_CODE_INTERPRETER_TOOL_NAME,
300
+ ...config ? { config } : {}
301
+ }
302
+ };
303
+ }
304
+ function isBuiltinToolName(toolName) {
305
+ return toolName.startsWith("$");
306
+ }
307
+ var kimiTools = {
308
+ /**
309
+ * Create a web search tool for use with Kimi models.
310
+ *
311
+ * @param config - Optional configuration
312
+ * @returns A provider tool definition
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * import { kimi, kimiTools } from 'ai-sdk-provider-kimi';
317
+ *
318
+ * const result = await generateText({
319
+ * model: kimi('kimi-k2.5'),
320
+ * tools: {
321
+ * webSearch: kimiTools.webSearch(),
322
+ * },
323
+ * prompt: 'What are the latest AI news?',
324
+ * });
325
+ * ```
326
+ */
327
+ webSearch: (config) => {
328
+ return {
329
+ type: "provider",
330
+ id: "kimi.webSearch",
331
+ args: createWebSearchTool(config)
332
+ };
333
+ },
334
+ /**
335
+ * Create a code interpreter tool for use with Kimi models.
336
+ *
337
+ * @param config - Optional configuration
338
+ * @returns A provider tool definition
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * import { kimi, kimiTools } from 'ai-sdk-provider-kimi';
343
+ *
344
+ * const result = await generateText({
345
+ * model: kimi('kimi-k2.5'),
346
+ * tools: {
347
+ * codeInterpreter: kimiTools.codeInterpreter(),
348
+ * },
349
+ * prompt: 'Calculate the factorial of 10',
350
+ * });
351
+ * ```
352
+ */
353
+ codeInterpreter: (config) => {
354
+ return {
355
+ type: "provider",
356
+ id: "kimi.codeInterpreter",
357
+ args: createCodeInterpreterTool(config)
358
+ };
359
+ }
360
+ };
361
+
362
+ // src/tools/prepare-tools.ts
363
+ var import_provider = require("@ai-sdk/provider");
364
+ function prepareKimiTools({
365
+ tools,
366
+ toolChoice,
367
+ webSearch,
368
+ codeInterpreter,
369
+ toolChoicePolyfill = true
370
+ }) {
371
+ tools = tools?.length ? tools : void 0;
372
+ const toolWarnings = [];
373
+ const kimiTools2 = [];
374
+ if (webSearch) {
375
+ const config = typeof webSearch === "boolean" ? void 0 : webSearch.config;
376
+ kimiTools2.push(createWebSearchTool(config));
377
+ }
378
+ if (codeInterpreter) {
379
+ const config = typeof codeInterpreter === "boolean" ? void 0 : codeInterpreter.config;
380
+ kimiTools2.push(createCodeInterpreterTool(config));
381
+ }
382
+ if (tools != null) {
383
+ for (const tool of tools) {
384
+ if (tool.type === "provider") {
385
+ const builtinTool = tryConvertToKimiBuiltinTool(tool);
386
+ if (builtinTool) {
387
+ kimiTools2.push(builtinTool);
388
+ continue;
389
+ }
390
+ toolWarnings.push({
391
+ type: "unsupported",
392
+ feature: `provider-defined tool ${tool.id}`
393
+ });
394
+ continue;
395
+ }
396
+ kimiTools2.push({
397
+ type: "function",
398
+ function: {
399
+ name: tool.name,
400
+ description: tool.description,
401
+ parameters: tool.inputSchema,
402
+ ...tool.strict != null ? { strict: tool.strict } : {}
403
+ }
404
+ });
405
+ }
406
+ }
407
+ if (kimiTools2.length === 0) {
408
+ return { tools: void 0, toolChoice: void 0, toolWarnings };
409
+ }
410
+ if (toolChoice == null) {
411
+ return { tools: kimiTools2, toolChoice: void 0, toolWarnings };
412
+ }
413
+ switch (toolChoice.type) {
414
+ case "auto":
415
+ case "none":
416
+ return { tools: kimiTools2, toolChoice: toolChoice.type, toolWarnings };
417
+ case "required": {
418
+ if (toolChoicePolyfill) {
419
+ const toolNames = kimiTools2.map((t) => t.type === "function" ? t.function.name : t.function.name).join(", ");
420
+ const systemMessage = generateRequiredToolMessage(toolNames);
421
+ toolWarnings.push({
422
+ type: "compatibility",
423
+ feature: "toolChoice.required",
424
+ details: "Using tool choice polyfill with system message injection."
425
+ });
426
+ return {
427
+ tools: kimiTools2,
428
+ toolChoice: "auto",
429
+ toolWarnings,
430
+ toolChoiceSystemMessage: systemMessage
431
+ };
432
+ }
433
+ toolWarnings.push({
434
+ type: "compatibility",
435
+ feature: "toolChoice.required",
436
+ details: "Moonshot does not support required tool choice. Falling back to auto."
437
+ });
438
+ return { tools: kimiTools2, toolChoice: "auto", toolWarnings };
439
+ }
440
+ case "tool": {
441
+ if (toolChoicePolyfill) {
442
+ const systemMessage = generateSpecificToolMessage(toolChoice.toolName);
443
+ toolWarnings.push({
444
+ type: "compatibility",
445
+ feature: `toolChoice.tool:${toolChoice.toolName}`,
446
+ details: "Using tool choice polyfill with system message injection."
447
+ });
448
+ return {
449
+ tools: kimiTools2,
450
+ toolChoice: "auto",
451
+ toolWarnings,
452
+ toolChoiceSystemMessage: systemMessage
453
+ };
454
+ }
455
+ toolWarnings.push({
456
+ type: "compatibility",
457
+ feature: `toolChoice.tool:${toolChoice.toolName}`,
458
+ details: "Moonshot does not support forcing a specific tool. Falling back to auto."
459
+ });
460
+ return { tools: kimiTools2, toolChoice: "auto", toolWarnings };
461
+ }
462
+ default: {
463
+ const _exhaustiveCheck = toolChoice;
464
+ throw new import_provider.UnsupportedFunctionalityError({
465
+ functionality: `tool choice type: ${_exhaustiveCheck}`
466
+ });
467
+ }
468
+ }
469
+ }
470
+ function generateRequiredToolMessage(toolNames) {
471
+ return `IMPORTANT INSTRUCTION: You MUST use one of the available tools (${toolNames}) to respond to the user's request. Do NOT provide a direct text response without first calling a tool. Always invoke a tool to complete this task.`;
472
+ }
473
+ function generateSpecificToolMessage(toolName) {
474
+ return `IMPORTANT INSTRUCTION: You MUST use the "${toolName}" tool to respond to this request. Do NOT use any other tool or provide a direct text response. Call the "${toolName}" tool with appropriate parameters.`;
475
+ }
476
+ function tryConvertToKimiBuiltinTool(tool) {
477
+ if (!tool.id.startsWith("kimi.")) {
478
+ return void 0;
479
+ }
480
+ const args = tool.args;
481
+ if (args && typeof args === "object" && "type" in args && args.type === "builtin_function" && "function" in args && typeof args.function === "object") {
482
+ const fn = args.function;
483
+ if (typeof fn.name === "string") {
484
+ return {
485
+ type: "builtin_function",
486
+ function: {
487
+ name: fn.name,
488
+ ...fn.config ? { config: fn.config } : {}
489
+ }
490
+ };
491
+ }
492
+ }
493
+ return void 0;
494
+ }
495
+
496
+ // src/chat/kimi-chat-messages.ts
497
+ var import_provider2 = require("@ai-sdk/provider");
498
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
499
+ var SUPPORTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/*"];
500
+ var SUPPORTED_VIDEO_TYPES = ["video/mp4", "video/webm", "video/ogg", "video/*"];
501
+ function convertToKimiChatMessages(prompt) {
502
+ const messages = [];
503
+ for (const { role, content } of prompt) {
504
+ switch (role) {
505
+ case "system": {
506
+ messages.push({ role: "system", content });
507
+ break;
508
+ }
509
+ case "user": {
510
+ if (content.length === 1 && content[0].type === "text") {
511
+ messages.push({ role: "user", content: content[0].text });
512
+ break;
513
+ }
514
+ messages.push({
515
+ role: "user",
516
+ content: content.map((part) => {
517
+ switch (part.type) {
518
+ case "text":
519
+ return { type: "text", text: part.text };
520
+ case "file": {
521
+ if (isImageMediaType(part.mediaType)) {
522
+ return convertImagePart(part);
523
+ }
524
+ if (isVideoMediaType(part.mediaType)) {
525
+ return convertVideoPart(part);
526
+ }
527
+ if (part.mediaType.startsWith("text/")) {
528
+ const text = part.data instanceof URL ? part.data.toString() : typeof part.data === "string" ? part.data : new TextDecoder().decode(part.data);
529
+ return { type: "text", text };
530
+ }
531
+ throw new import_provider2.UnsupportedFunctionalityError({
532
+ functionality: `file part media type ${part.mediaType}`
533
+ });
534
+ }
535
+ default: {
536
+ const _exhaustiveCheck = part;
537
+ throw new Error(`Unsupported part type: ${_exhaustiveCheck}`);
538
+ }
539
+ }
540
+ })
541
+ });
542
+ break;
543
+ }
544
+ case "assistant": {
545
+ let text = "";
546
+ let reasoning = "";
547
+ const toolCalls = [];
548
+ for (const part of content) {
549
+ switch (part.type) {
550
+ case "text": {
551
+ text += part.text;
552
+ break;
553
+ }
554
+ case "reasoning": {
555
+ reasoning += part.text;
556
+ break;
557
+ }
558
+ case "tool-call": {
559
+ toolCalls.push({
560
+ id: part.toolCallId,
561
+ type: "function",
562
+ function: {
563
+ name: part.toolName,
564
+ arguments: JSON.stringify(part.input)
565
+ }
566
+ });
567
+ break;
568
+ }
569
+ case "file": {
570
+ break;
571
+ }
572
+ case "tool-result": {
573
+ break;
574
+ }
575
+ default: {
576
+ const _exhaustiveCheck = part;
577
+ throw new Error(`Unsupported assistant part: ${_exhaustiveCheck}`);
578
+ }
579
+ }
580
+ }
581
+ messages.push({
582
+ role: "assistant",
583
+ content: text.length > 0 ? text : null,
584
+ ...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
585
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
586
+ });
587
+ break;
588
+ }
589
+ case "tool": {
590
+ for (const toolResponse of content) {
591
+ if (toolResponse.type === "tool-approval-response") {
592
+ continue;
593
+ }
594
+ messages.push({
595
+ role: "tool",
596
+ tool_call_id: toolResponse.toolCallId,
597
+ content: serializeToolResult(toolResponse)
598
+ });
599
+ }
600
+ break;
601
+ }
602
+ default: {
603
+ const _exhaustiveCheck = role;
604
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
605
+ }
606
+ }
607
+ }
608
+ return messages;
609
+ }
610
+ function isImageMediaType(mediaType) {
611
+ return mediaType.startsWith("image/") || SUPPORTED_IMAGE_TYPES.includes(mediaType);
612
+ }
613
+ function isVideoMediaType(mediaType) {
614
+ return mediaType.startsWith("video/") || SUPPORTED_VIDEO_TYPES.includes(mediaType);
615
+ }
616
+ function convertImagePart(part) {
617
+ const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
618
+ const url = part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${(0, import_provider_utils2.convertToBase64)(part.data)}`;
619
+ return { type: "image_url", image_url: { url } };
620
+ }
621
+ function convertVideoPart(part) {
622
+ if (!(part.data instanceof URL)) {
623
+ throw new import_provider2.UnsupportedFunctionalityError({
624
+ functionality: "inline video data (video must be provided as a URL)"
625
+ });
626
+ }
627
+ return { type: "video_url", video_url: { url: part.data.toString() } };
628
+ }
629
+ function serializeToolResult(toolResponse) {
630
+ const { toolName } = toolResponse;
631
+ const output = toolResponse.output;
632
+ if (isBuiltinToolName(toolName)) {
633
+ return serializeBuiltinToolResult(output);
634
+ }
635
+ switch (output.type) {
636
+ case "text":
637
+ case "error-text":
638
+ return output.value;
639
+ case "execution-denied":
640
+ return output.reason ?? "Tool execution denied.";
641
+ case "json":
642
+ case "error-json":
643
+ case "content":
644
+ return JSON.stringify(output.value);
645
+ default: {
646
+ const _exhaustiveCheck = output;
647
+ return JSON.stringify(_exhaustiveCheck);
648
+ }
649
+ }
650
+ }
651
+ function serializeBuiltinToolResult(output) {
652
+ switch (output.type) {
653
+ case "text":
654
+ case "error-text":
655
+ return output.value;
656
+ case "json":
657
+ case "error-json":
658
+ case "content":
659
+ return JSON.stringify(output.value);
660
+ case "execution-denied":
661
+ return output.reason ?? "Tool execution denied.";
662
+ default: {
663
+ const _exhaustiveCheck = output;
664
+ return JSON.stringify(_exhaustiveCheck);
665
+ }
666
+ }
667
+ }
668
+
669
+ // src/chat/kimi-chat-response.ts
670
+ function extractWebSearchTokens(toolCalls) {
671
+ return extractBuiltinToolTokens(toolCalls, KIMI_WEB_SEARCH_TOOL_NAME);
672
+ }
673
+ function extractCodeInterpreterTokens(toolCalls) {
674
+ return extractBuiltinToolTokens(toolCalls, KIMI_CODE_INTERPRETER_TOOL_NAME);
675
+ }
676
+ function extractBuiltinToolTokens(toolCalls, toolName) {
677
+ if (!toolCalls) {
678
+ return void 0;
679
+ }
680
+ let totalTokens = 0;
681
+ let foundTool = false;
682
+ for (const toolCall of toolCalls) {
683
+ if (toolCall.function.name === toolName) {
684
+ foundTool = true;
685
+ if (toolCall.function.arguments) {
686
+ try {
687
+ const args = JSON.parse(toolCall.function.arguments);
688
+ if (typeof args.total_tokens === "number") {
689
+ totalTokens += args.total_tokens;
690
+ }
691
+ } catch {
692
+ }
693
+ }
694
+ }
695
+ }
696
+ return foundTool ? totalTokens : void 0;
697
+ }
698
+
699
+ // src/chat/kimi-chat-settings.ts
700
+ var import_v42 = require("zod/v4");
701
+ var kimiCachingConfigSchema = import_v42.z.object({
702
+ enabled: import_v42.z.boolean(),
703
+ cacheKey: import_v42.z.string().optional(),
704
+ ttlSeconds: import_v42.z.number().optional(),
705
+ resetCache: import_v42.z.boolean().optional()
706
+ });
707
+ var kimiProviderOptionsSchema = import_v42.z.object({
708
+ /**
709
+ * A unique identifier representing your end-user.
710
+ */
711
+ user: import_v42.z.string().optional(),
712
+ /**
713
+ * Whether to use strict JSON schema validation when supported.
714
+ */
715
+ strictJsonSchema: import_v42.z.boolean().optional(),
716
+ /**
717
+ * Optional request ID to correlate logs.
718
+ */
719
+ requestId: import_v42.z.string().optional(),
720
+ /**
721
+ * Optional extra headers for this call.
722
+ */
723
+ extraHeaders: import_v42.z.record(import_v42.z.string(), import_v42.z.string()).optional(),
724
+ /**
725
+ * Whether the provider should allow parallel tool calls.
726
+ */
727
+ parallelToolCalls: import_v42.z.boolean().optional(),
728
+ /**
729
+ * Enable or configure the built-in web search tool for this request.
730
+ * This allows Kimi to search the web to help answer questions.
731
+ */
732
+ webSearch: import_v42.z.union([
733
+ import_v42.z.boolean(),
734
+ import_v42.z.object({
735
+ enabled: import_v42.z.boolean(),
736
+ config: import_v42.z.object({
737
+ search_result: import_v42.z.boolean().optional()
738
+ }).optional()
739
+ })
740
+ ]).optional(),
741
+ /**
742
+ * Enable or configure the built-in code interpreter tool for this request.
743
+ * This allows Kimi to execute code to help solve problems.
744
+ */
745
+ codeInterpreter: import_v42.z.union([
746
+ import_v42.z.boolean(),
747
+ import_v42.z.object({
748
+ enabled: import_v42.z.boolean(),
749
+ config: import_v42.z.object({
750
+ timeout: import_v42.z.number().optional(),
751
+ include_output: import_v42.z.boolean().optional()
752
+ }).optional()
753
+ })
754
+ ]).optional(),
755
+ /**
756
+ * Enable or configure context caching for this request.
757
+ * Reduces costs for repeated long prompts.
758
+ */
759
+ caching: import_v42.z.union([import_v42.z.boolean(), kimiCachingConfigSchema]).optional(),
760
+ /**
761
+ * Enable tool choice polyfill for this request.
762
+ */
763
+ toolChoicePolyfill: import_v42.z.boolean().optional()
764
+ });
765
+
766
+ // src/chat/kimi-chat-language-model.ts
767
+ var KimiChatLanguageModel = class {
768
+ constructor(modelId, settings, config) {
769
+ this.specificationVersion = "v3";
770
+ this.modelId = modelId;
771
+ this.settings = settings;
772
+ this.config = config;
773
+ this.generateIdFn = config.generateId ?? import_provider_utils3.generateId;
774
+ this.supportsStructuredOutputs = config.supportsStructuredOutputs ?? false;
775
+ }
776
+ get provider() {
777
+ return this.config.provider;
778
+ }
779
+ get providerOptionsName() {
780
+ return this.config.provider.split(".")[0].trim();
781
+ }
782
+ /**
783
+ * Get the inferred or configured capabilities for this model.
784
+ */
785
+ get capabilities() {
786
+ const inferred = inferModelCapabilities(this.modelId);
787
+ return {
788
+ ...inferred,
789
+ ...this.settings.capabilities
790
+ };
791
+ }
792
+ get supportedUrls() {
793
+ const caps = this.capabilities;
794
+ const patterns = {
795
+ "image/*": [/^https?:\/\/.*$/i]
796
+ };
797
+ if (caps.videoInput) {
798
+ patterns["video/*"] = [/^https?:\/\/.*$/i];
799
+ }
800
+ return this.settings.supportedUrls ?? this.config.supportedUrls ?? patterns;
801
+ }
802
+ async getArgs({
803
+ prompt,
804
+ maxOutputTokens,
805
+ temperature,
806
+ topP,
807
+ topK,
808
+ frequencyPenalty,
809
+ presencePenalty,
810
+ stopSequences,
811
+ responseFormat,
812
+ seed,
813
+ providerOptions,
814
+ tools,
815
+ toolChoice
816
+ }) {
817
+ const warnings = [];
818
+ const deprecatedOptions = await (0, import_provider_utils3.parseProviderOptions)({
819
+ provider: "moonshot",
820
+ providerOptions,
821
+ schema: kimiProviderOptionsSchema
822
+ });
823
+ if (deprecatedOptions != null) {
824
+ warnings.push({
825
+ type: "other",
826
+ message: "The 'moonshot' key in providerOptions is deprecated. Use 'kimi' instead."
827
+ });
828
+ }
829
+ const providerOptionsName = this.providerOptionsName;
830
+ const kimiOptions = await (0, import_provider_utils3.parseProviderOptions)({
831
+ provider: providerOptionsName,
832
+ providerOptions,
833
+ schema: kimiProviderOptionsSchema
834
+ });
835
+ const options = {
836
+ ...deprecatedOptions ?? {},
837
+ ...kimiOptions ?? {}
838
+ };
839
+ if (topK != null) {
840
+ warnings.push({ type: "unsupported", feature: "topK" });
841
+ }
842
+ const strictJsonSchema = options.strictJsonSchema ?? true;
843
+ if (responseFormat?.type === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) {
844
+ warnings.push({
845
+ type: "unsupported",
846
+ feature: "responseFormat",
847
+ details: "JSON schema response format requires structured outputs support."
848
+ });
849
+ }
850
+ const webSearch = resolveBuiltinToolConfig(this.settings.webSearch, options.webSearch);
851
+ const codeInterpreter = resolveBuiltinToolConfig(this.settings.codeInterpreter, options.codeInterpreter);
852
+ const toolChoicePolyfill = options.toolChoicePolyfill ?? this.settings.toolChoicePolyfill ?? true;
853
+ const {
854
+ tools: kimiTools2,
855
+ toolChoice: kimiToolChoice,
856
+ toolWarnings,
857
+ toolChoiceSystemMessage
858
+ } = prepareKimiTools({
859
+ tools,
860
+ toolChoice,
861
+ webSearch,
862
+ codeInterpreter,
863
+ toolChoicePolyfill
864
+ });
865
+ const caching = resolveCachingConfig(this.settings.caching, options.caching);
866
+ const cachingHeaders = buildCachingHeaders(caching);
867
+ const passthroughOptions = getPassthroughOptions({
868
+ providerOptions,
869
+ providerOptionsName,
870
+ deprecatedProviderOptionsName: "moonshot",
871
+ knownKeys: Object.keys(kimiProviderOptionsSchema.shape)
872
+ });
873
+ const messages = convertToKimiChatMessages(prompt);
874
+ if (toolChoiceSystemMessage) {
875
+ messages.unshift({ role: "system", content: toolChoiceSystemMessage });
876
+ }
877
+ const body = (0, import_provider_utils3.removeUndefinedEntries)({
878
+ model: this.modelId,
879
+ messages,
880
+ max_tokens: maxOutputTokens,
881
+ temperature,
882
+ top_p: topP,
883
+ frequency_penalty: frequencyPenalty,
884
+ presence_penalty: presencePenalty,
885
+ stop: stopSequences,
886
+ seed,
887
+ response_format: responseFormat?.type === "json" ? this.supportsStructuredOutputs && responseFormat.schema != null ? {
888
+ type: "json_schema",
889
+ json_schema: {
890
+ schema: responseFormat.schema,
891
+ strict: strictJsonSchema,
892
+ name: responseFormat.name ?? "response",
893
+ description: responseFormat.description
894
+ }
895
+ } : { type: "json_object" } : void 0,
896
+ tools: kimiTools2,
897
+ tool_choice: kimiToolChoice,
898
+ user: options.user,
899
+ ...kimiTools2 != null && options.parallelToolCalls != null ? { parallel_tool_calls: options.parallelToolCalls } : {},
900
+ ...passthroughOptions
901
+ });
902
+ const requestHeaders = {
903
+ ...options.requestId ? { "X-Request-ID": options.requestId } : {},
904
+ ...options.extraHeaders ?? {},
905
+ ...cachingHeaders
906
+ };
907
+ return {
908
+ body,
909
+ warnings: [...warnings, ...toolWarnings],
910
+ requestHeaders
911
+ };
912
+ }
913
+ async doGenerate(options) {
914
+ const { body, warnings, requestHeaders } = await this.getArgs(options);
915
+ const {
916
+ responseHeaders,
917
+ value: response,
918
+ rawValue
919
+ } = await (0, import_provider_utils3.postJsonToApi)({
920
+ url: `${this.config.baseURL}/chat/completions`,
921
+ headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), requestHeaders, options.headers),
922
+ body,
923
+ failedResponseHandler: kimiFailedResponseHandler,
924
+ successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)(kimiChatResponseSchema),
925
+ abortSignal: options.abortSignal,
926
+ fetch: this.config.fetch
927
+ });
928
+ const choice = response.choices[0];
929
+ const content = [];
930
+ const { text, reasoning } = extractMessageContent(choice.message);
931
+ if (reasoning.length > 0) {
932
+ content.push({ type: "reasoning", text: reasoning });
933
+ }
934
+ if (text.length > 0) {
935
+ content.push({ type: "text", text });
936
+ }
937
+ if (choice.message.tool_calls != null) {
938
+ for (const toolCall of choice.message.tool_calls) {
939
+ content.push({
940
+ type: "tool-call",
941
+ toolCallId: toolCall.id ?? this.generateIdFn(),
942
+ toolName: toolCall.function.name,
943
+ input: toolCall.function.arguments ?? ""
944
+ });
945
+ }
946
+ }
947
+ const webSearchTokens = extractWebSearchTokens(choice.message.tool_calls);
948
+ const codeInterpreterTokens = extractCodeInterpreterTokens(choice.message.tool_calls);
949
+ const providerMetadata = buildProviderMetadata({
950
+ providerOptionsName: this.providerOptionsName,
951
+ responseHeaders,
952
+ webSearchTokens,
953
+ codeInterpreterTokens
954
+ });
955
+ return {
956
+ content,
957
+ finishReason: {
958
+ unified: mapKimiFinishReason(choice.finish_reason),
959
+ raw: choice.finish_reason ?? void 0
960
+ },
961
+ usage: convertKimiUsage(response.usage, webSearchTokens, codeInterpreterTokens),
962
+ ...providerMetadata ? { providerMetadata } : {},
963
+ request: { body },
964
+ response: {
965
+ ...getResponseMetadata(response),
966
+ headers: responseHeaders,
967
+ body: rawValue
968
+ },
969
+ warnings
970
+ };
971
+ }
972
+ async doStream(options) {
973
+ const { body, warnings, requestHeaders } = await this.getArgs(options);
974
+ const streamBody = {
975
+ ...body,
976
+ stream: true,
977
+ stream_options: this.config.includeUsageInStream ? { include_usage: true } : void 0
978
+ };
979
+ const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({
980
+ url: `${this.config.baseURL}/chat/completions`,
981
+ headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), requestHeaders, options.headers),
982
+ body: streamBody,
983
+ failedResponseHandler: kimiFailedResponseHandler,
984
+ successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)(kimiChatChunkSchema),
985
+ abortSignal: options.abortSignal,
986
+ fetch: this.config.fetch
987
+ });
988
+ const requestId = getKimiRequestId(responseHeaders);
989
+ let finishReason = {
990
+ unified: "other",
991
+ raw: void 0
992
+ };
993
+ let usage;
994
+ let isFirstChunk = true;
995
+ let isActiveText = false;
996
+ let isActiveReasoning = false;
997
+ const toolCalls = [];
998
+ const providerOptionsName = this.providerOptionsName;
999
+ const _generateIdFn = this.generateIdFn;
1000
+ return {
1001
+ stream: response.pipeThrough(
1002
+ new TransformStream({
1003
+ start(controller) {
1004
+ controller.enqueue({ type: "stream-start", warnings });
1005
+ },
1006
+ transform(chunk, controller) {
1007
+ if (options.includeRawChunks) {
1008
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
1009
+ }
1010
+ if (!chunk.success) {
1011
+ finishReason = { unified: "error", raw: void 0 };
1012
+ controller.enqueue({ type: "error", error: chunk.error });
1013
+ return;
1014
+ }
1015
+ if ("error" in chunk.value) {
1016
+ finishReason = { unified: "error", raw: void 0 };
1017
+ const error = chunk.value.error;
1018
+ controller.enqueue({
1019
+ type: "error",
1020
+ error: error?.message ?? chunk.value
1021
+ });
1022
+ return;
1023
+ }
1024
+ const value = chunk.value;
1025
+ if (isFirstChunk) {
1026
+ isFirstChunk = false;
1027
+ controller.enqueue({
1028
+ type: "response-metadata",
1029
+ ...getResponseMetadata(value)
1030
+ });
1031
+ }
1032
+ if (value.usage != null) {
1033
+ usage = value.usage;
1034
+ }
1035
+ const choice = value.choices[0];
1036
+ if (!choice) {
1037
+ return;
1038
+ }
1039
+ if (choice.finish_reason != null) {
1040
+ finishReason = {
1041
+ unified: mapKimiFinishReason(choice.finish_reason),
1042
+ raw: choice.finish_reason ?? void 0
1043
+ };
1044
+ }
1045
+ const delta = choice.delta;
1046
+ if (!delta) {
1047
+ return;
1048
+ }
1049
+ const reasoningDelta = delta.reasoning_content ?? delta.reasoning;
1050
+ if (reasoningDelta) {
1051
+ if (!isActiveReasoning) {
1052
+ if (isActiveText) {
1053
+ controller.enqueue({ type: "text-end", id: "text-0" });
1054
+ isActiveText = false;
1055
+ }
1056
+ controller.enqueue({
1057
+ type: "reasoning-start",
1058
+ id: "reasoning-0"
1059
+ });
1060
+ isActiveReasoning = true;
1061
+ }
1062
+ controller.enqueue({
1063
+ type: "reasoning-delta",
1064
+ id: "reasoning-0",
1065
+ delta: reasoningDelta
1066
+ });
1067
+ }
1068
+ if (delta.content) {
1069
+ if (isActiveReasoning) {
1070
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
1071
+ isActiveReasoning = false;
1072
+ }
1073
+ if (!isActiveText) {
1074
+ controller.enqueue({ type: "text-start", id: "text-0" });
1075
+ isActiveText = true;
1076
+ }
1077
+ controller.enqueue({
1078
+ type: "text-delta",
1079
+ id: "text-0",
1080
+ delta: delta.content
1081
+ });
1082
+ }
1083
+ if (delta.tool_calls != null) {
1084
+ if (isActiveReasoning) {
1085
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
1086
+ isActiveReasoning = false;
1087
+ }
1088
+ for (const toolCallDelta of delta.tool_calls) {
1089
+ const index = toolCallDelta.index ?? toolCalls.length;
1090
+ if (toolCalls[index] == null) {
1091
+ if (toolCallDelta.id == null) {
1092
+ throw new import_provider3.InvalidResponseDataError({
1093
+ data: toolCallDelta,
1094
+ message: "Expected 'id' to be a string."
1095
+ });
1096
+ }
1097
+ if (toolCallDelta.function?.name == null) {
1098
+ throw new import_provider3.InvalidResponseDataError({
1099
+ data: toolCallDelta,
1100
+ message: "Expected 'function.name' to be a string."
1101
+ });
1102
+ }
1103
+ controller.enqueue({
1104
+ type: "tool-input-start",
1105
+ id: toolCallDelta.id,
1106
+ toolName: toolCallDelta.function.name
1107
+ });
1108
+ toolCalls[index] = {
1109
+ id: toolCallDelta.id,
1110
+ type: "function",
1111
+ function: {
1112
+ name: toolCallDelta.function.name,
1113
+ arguments: toolCallDelta.function.arguments ?? ""
1114
+ },
1115
+ hasFinished: false
1116
+ };
1117
+ const toolCall2 = toolCalls[index];
1118
+ if (toolCall2.function.arguments.length > 0) {
1119
+ controller.enqueue({
1120
+ type: "tool-input-delta",
1121
+ id: toolCall2.id,
1122
+ delta: toolCall2.function.arguments
1123
+ });
1124
+ }
1125
+ if ((0, import_provider_utils3.isParsableJson)(toolCall2.function.arguments)) {
1126
+ controller.enqueue({ type: "tool-input-end", id: toolCall2.id });
1127
+ controller.enqueue({
1128
+ type: "tool-call",
1129
+ toolCallId: toolCall2.id,
1130
+ toolName: toolCall2.function.name,
1131
+ input: toolCall2.function.arguments
1132
+ });
1133
+ toolCall2.hasFinished = true;
1134
+ }
1135
+ continue;
1136
+ }
1137
+ const toolCall = toolCalls[index];
1138
+ if (toolCall.hasFinished) {
1139
+ continue;
1140
+ }
1141
+ if (toolCallDelta.function?.arguments != null) {
1142
+ toolCall.function.arguments += toolCallDelta.function.arguments;
1143
+ }
1144
+ controller.enqueue({
1145
+ type: "tool-input-delta",
1146
+ id: toolCall.id,
1147
+ delta: toolCallDelta.function?.arguments ?? ""
1148
+ });
1149
+ if ((0, import_provider_utils3.isParsableJson)(toolCall.function.arguments)) {
1150
+ controller.enqueue({ type: "tool-input-end", id: toolCall.id });
1151
+ controller.enqueue({
1152
+ type: "tool-call",
1153
+ toolCallId: toolCall.id,
1154
+ toolName: toolCall.function.name,
1155
+ input: toolCall.function.arguments
1156
+ });
1157
+ toolCall.hasFinished = true;
1158
+ }
1159
+ }
1160
+ }
1161
+ },
1162
+ flush(controller) {
1163
+ if (isActiveReasoning) {
1164
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
1165
+ isActiveReasoning = false;
1166
+ }
1167
+ if (isActiveText) {
1168
+ controller.enqueue({ type: "text-end", id: "text-0" });
1169
+ isActiveText = false;
1170
+ }
1171
+ for (const toolCall of toolCalls.filter((call) => !call.hasFinished)) {
1172
+ controller.enqueue({ type: "tool-input-end", id: toolCall.id });
1173
+ controller.enqueue({
1174
+ type: "tool-call",
1175
+ toolCallId: toolCall.id,
1176
+ toolName: toolCall.function.name,
1177
+ input: toolCall.function.arguments
1178
+ });
1179
+ }
1180
+ const webSearchTokens = extractWebSearchTokens(toolCalls);
1181
+ const codeInterpreterTokens = extractCodeInterpreterTokens(toolCalls);
1182
+ const providerMetadata = requestId || webSearchTokens != null || codeInterpreterTokens != null ? {
1183
+ [providerOptionsName]: {
1184
+ ...requestId ? { requestId } : {},
1185
+ ...webSearchTokens != null ? { webSearchTokens } : {},
1186
+ ...codeInterpreterTokens != null ? { codeInterpreterTokens } : {}
1187
+ }
1188
+ } : void 0;
1189
+ controller.enqueue({
1190
+ type: "finish",
1191
+ finishReason,
1192
+ usage: convertKimiUsage(usage, webSearchTokens, codeInterpreterTokens),
1193
+ ...providerMetadata ? { providerMetadata } : {}
1194
+ });
1195
+ }
1196
+ })
1197
+ ),
1198
+ request: { body: streamBody },
1199
+ response: { headers: responseHeaders }
1200
+ };
1201
+ }
1202
+ };
1203
+ function buildProviderMetadata({
1204
+ providerOptionsName,
1205
+ responseHeaders,
1206
+ webSearchTokens,
1207
+ codeInterpreterTokens
1208
+ }) {
1209
+ const requestId = getKimiRequestId(responseHeaders);
1210
+ if (!requestId && webSearchTokens == null && codeInterpreterTokens == null) {
1211
+ return void 0;
1212
+ }
1213
+ return {
1214
+ [providerOptionsName]: {
1215
+ ...requestId ? { requestId } : {},
1216
+ ...webSearchTokens != null ? { webSearchTokens } : {},
1217
+ ...codeInterpreterTokens != null ? { codeInterpreterTokens } : {}
1218
+ }
1219
+ };
1220
+ }
1221
+ function getPassthroughOptions({
1222
+ providerOptions,
1223
+ providerOptionsName,
1224
+ deprecatedProviderOptionsName,
1225
+ knownKeys
1226
+ }) {
1227
+ const rawOptions = [providerOptions?.[deprecatedProviderOptionsName], providerOptions?.[providerOptionsName]].filter(
1228
+ (entry) => entry != null && typeof entry === "object"
1229
+ );
1230
+ const passthrough = {};
1231
+ for (const options of rawOptions) {
1232
+ for (const [key, value] of Object.entries(options ?? {})) {
1233
+ if (!knownKeys.includes(key)) {
1234
+ passthrough[key] = value;
1235
+ }
1236
+ }
1237
+ }
1238
+ return passthrough;
1239
+ }
1240
+ function resolveBuiltinToolConfig(settingsConfig, optionsConfig) {
1241
+ if (optionsConfig != null) {
1242
+ if (typeof optionsConfig === "boolean") {
1243
+ return optionsConfig ? { enabled: true } : void 0;
1244
+ }
1245
+ const config = optionsConfig;
1246
+ return config.enabled ? optionsConfig : void 0;
1247
+ }
1248
+ if (settingsConfig != null) {
1249
+ if (typeof settingsConfig === "boolean") {
1250
+ return settingsConfig ? { enabled: true } : void 0;
1251
+ }
1252
+ const config = settingsConfig;
1253
+ return config.enabled ? settingsConfig : void 0;
1254
+ }
1255
+ return void 0;
1256
+ }
1257
+ function resolveCachingConfig(settingsConfig, optionsConfig) {
1258
+ const config = optionsConfig ?? settingsConfig;
1259
+ if (config == null) {
1260
+ return void 0;
1261
+ }
1262
+ if (typeof config === "boolean") {
1263
+ return config ? { enabled: true } : void 0;
1264
+ }
1265
+ return config.enabled ? config : void 0;
1266
+ }
1267
+ function buildCachingHeaders(caching) {
1268
+ if (!caching?.enabled) {
1269
+ return {};
1270
+ }
1271
+ const headers = {
1272
+ "X-Kimi-Cache": "enabled"
1273
+ };
1274
+ if (caching.cacheKey) {
1275
+ headers["X-Kimi-Cache-Key"] = caching.cacheKey;
1276
+ }
1277
+ if (caching.ttlSeconds) {
1278
+ headers["X-Kimi-Cache-TTL"] = String(caching.ttlSeconds);
1279
+ }
1280
+ if (caching.resetCache) {
1281
+ headers["X-Kimi-Cache-Reset"] = "true";
1282
+ }
1283
+ return headers;
1284
+ }
1285
+ var kimiTokenUsageSchema = import_v43.z.object({
1286
+ prompt_tokens: import_v43.z.number().nullish(),
1287
+ completion_tokens: import_v43.z.number().nullish(),
1288
+ total_tokens: import_v43.z.number().nullish(),
1289
+ prompt_tokens_details: import_v43.z.object({
1290
+ cached_tokens: import_v43.z.number().nullish()
1291
+ }).nullish(),
1292
+ completion_tokens_details: import_v43.z.object({
1293
+ reasoning_tokens: import_v43.z.number().nullish()
1294
+ }).nullish()
1295
+ }).nullish();
1296
+ var kimiChatResponseSchema = import_v43.z.looseObject({
1297
+ id: import_v43.z.string().nullish(),
1298
+ created: import_v43.z.number().nullish(),
1299
+ model: import_v43.z.string().nullish(),
1300
+ choices: import_v43.z.array(
1301
+ import_v43.z.object({
1302
+ message: import_v43.z.object({
1303
+ role: import_v43.z.string().nullish(),
1304
+ content: import_v43.z.union([import_v43.z.string(), import_v43.z.array(import_v43.z.any())]).nullish(),
1305
+ reasoning_content: import_v43.z.string().nullish(),
1306
+ reasoning: import_v43.z.string().nullish(),
1307
+ tool_calls: import_v43.z.array(
1308
+ import_v43.z.object({
1309
+ id: import_v43.z.string().nullish(),
1310
+ function: import_v43.z.object({
1311
+ name: import_v43.z.string(),
1312
+ arguments: import_v43.z.string().nullish()
1313
+ })
1314
+ })
1315
+ ).nullish()
1316
+ }),
1317
+ finish_reason: import_v43.z.string().nullish()
1318
+ })
1319
+ ),
1320
+ usage: kimiTokenUsageSchema
1321
+ });
1322
+ var kimiChatChunkBaseSchema = import_v43.z.looseObject({
1323
+ id: import_v43.z.string().nullish(),
1324
+ created: import_v43.z.number().nullish(),
1325
+ model: import_v43.z.string().nullish(),
1326
+ choices: import_v43.z.array(
1327
+ import_v43.z.object({
1328
+ delta: import_v43.z.object({
1329
+ role: import_v43.z.enum(["assistant"]).nullish(),
1330
+ content: import_v43.z.string().nullish(),
1331
+ reasoning_content: import_v43.z.string().nullish(),
1332
+ reasoning: import_v43.z.string().nullish(),
1333
+ tool_calls: import_v43.z.array(
1334
+ import_v43.z.object({
1335
+ index: import_v43.z.number().nullish(),
1336
+ id: import_v43.z.string().nullish(),
1337
+ function: import_v43.z.object({
1338
+ name: import_v43.z.string().nullish(),
1339
+ arguments: import_v43.z.string().nullish()
1340
+ })
1341
+ })
1342
+ ).nullish()
1343
+ }).nullish(),
1344
+ finish_reason: import_v43.z.string().nullish()
1345
+ })
1346
+ ),
1347
+ usage: kimiTokenUsageSchema
1348
+ });
1349
+ var kimiChatChunkSchema = import_v43.z.union([kimiChatChunkBaseSchema, kimiErrorSchema]);
1350
+
1351
+ // src/files/file-utils.ts
1352
+ var SUPPORTED_FILE_EXTENSIONS = [
1353
+ // Documents
1354
+ ".pdf",
1355
+ ".txt",
1356
+ ".csv",
1357
+ ".doc",
1358
+ ".docx",
1359
+ ".xls",
1360
+ ".xlsx",
1361
+ ".ppt",
1362
+ ".pptx",
1363
+ ".md",
1364
+ ".epub",
1365
+ ".mobi",
1366
+ ".html",
1367
+ ".json",
1368
+ ".log",
1369
+ ".dot",
1370
+ ".ini",
1371
+ ".conf",
1372
+ ".yaml",
1373
+ ".yml",
1374
+ // Images
1375
+ ".jpeg",
1376
+ ".jpg",
1377
+ ".png",
1378
+ ".bmp",
1379
+ ".gif",
1380
+ ".svg",
1381
+ ".svgz",
1382
+ ".webp",
1383
+ ".ico",
1384
+ ".xbm",
1385
+ ".dib",
1386
+ ".pjp",
1387
+ ".tif",
1388
+ ".tiff",
1389
+ ".pjpeg",
1390
+ ".avif",
1391
+ ".apng",
1392
+ ".jfif",
1393
+ // Code files
1394
+ ".go",
1395
+ ".h",
1396
+ ".c",
1397
+ ".cpp",
1398
+ ".cxx",
1399
+ ".cc",
1400
+ ".cs",
1401
+ ".java",
1402
+ ".js",
1403
+ ".css",
1404
+ ".jsp",
1405
+ ".php",
1406
+ ".py",
1407
+ ".py3",
1408
+ ".asp",
1409
+ ".ts",
1410
+ ".tsx"
1411
+ ];
1412
+ var SUPPORTED_MIME_TYPES = {
1413
+ // Documents
1414
+ "application/pdf": "file-extract",
1415
+ "text/plain": "file-extract",
1416
+ "text/csv": "file-extract",
1417
+ "application/msword": "file-extract",
1418
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "file-extract",
1419
+ "application/vnd.ms-excel": "file-extract",
1420
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "file-extract",
1421
+ "application/vnd.ms-powerpoint": "file-extract",
1422
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "file-extract",
1423
+ "text/markdown": "file-extract",
1424
+ "text/html": "file-extract",
1425
+ "application/json": "file-extract",
1426
+ "application/epub+zip": "file-extract",
1427
+ "text/yaml": "file-extract",
1428
+ "application/x-yaml": "file-extract",
1429
+ // Code files (treated as text)
1430
+ "text/javascript": "file-extract",
1431
+ "text/typescript": "file-extract",
1432
+ "text/x-python": "file-extract",
1433
+ "text/x-java": "file-extract",
1434
+ "text/x-c": "file-extract",
1435
+ "text/x-c++": "file-extract",
1436
+ "text/css": "file-extract",
1437
+ // Images
1438
+ "image/jpeg": "image",
1439
+ "image/png": "image",
1440
+ "image/gif": "image",
1441
+ "image/webp": "image",
1442
+ "image/svg+xml": "image",
1443
+ "image/bmp": "image",
1444
+ "image/tiff": "image",
1445
+ "image/avif": "image",
1446
+ "image/apng": "image",
1447
+ "image/x-icon": "image",
1448
+ // Videos
1449
+ "video/mp4": "video",
1450
+ "video/webm": "video",
1451
+ "video/ogg": "video",
1452
+ "video/quicktime": "video"
1453
+ };
1454
+ function isImageMediaType2(mediaType) {
1455
+ return mediaType.startsWith("image/");
1456
+ }
1457
+ function isVideoMediaType2(mediaType) {
1458
+ return mediaType.startsWith("video/");
1459
+ }
1460
+ function isFileExtractMediaType(mediaType) {
1461
+ if (mediaType in SUPPORTED_MIME_TYPES) {
1462
+ return SUPPORTED_MIME_TYPES[mediaType] === "file-extract";
1463
+ }
1464
+ if (mediaType.startsWith("text/") || mediaType === "application/pdf") {
1465
+ return true;
1466
+ }
1467
+ return false;
1468
+ }
1469
+ function isDocumentMediaType(mediaType) {
1470
+ const documentTypes = [
1471
+ "application/pdf",
1472
+ "application/msword",
1473
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1474
+ "application/vnd.ms-excel",
1475
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1476
+ "application/vnd.ms-powerpoint",
1477
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1478
+ "application/epub+zip"
1479
+ ];
1480
+ return documentTypes.includes(mediaType);
1481
+ }
1482
+ function getPurposeFromMediaType(mediaType) {
1483
+ if (isImageMediaType2(mediaType)) {
1484
+ return "image";
1485
+ }
1486
+ if (isVideoMediaType2(mediaType)) {
1487
+ return "video";
1488
+ }
1489
+ return "file-extract";
1490
+ }
1491
+ function getMediaTypeFromExtension(extension) {
1492
+ const ext = extension.toLowerCase().startsWith(".") ? extension.toLowerCase() : `.${extension.toLowerCase()}`;
1493
+ const extensionToMime = {
1494
+ // Documents
1495
+ ".pdf": "application/pdf",
1496
+ ".txt": "text/plain",
1497
+ ".csv": "text/csv",
1498
+ ".doc": "application/msword",
1499
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1500
+ ".xls": "application/vnd.ms-excel",
1501
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1502
+ ".ppt": "application/vnd.ms-powerpoint",
1503
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
1504
+ ".md": "text/markdown",
1505
+ ".html": "text/html",
1506
+ ".json": "application/json",
1507
+ ".epub": "application/epub+zip",
1508
+ ".yaml": "text/yaml",
1509
+ ".yml": "text/yaml",
1510
+ ".log": "text/plain",
1511
+ ".ini": "text/plain",
1512
+ ".conf": "text/plain",
1513
+ // Code
1514
+ ".js": "text/javascript",
1515
+ ".ts": "text/typescript",
1516
+ ".tsx": "text/typescript",
1517
+ ".py": "text/x-python",
1518
+ ".java": "text/x-java",
1519
+ ".c": "text/x-c",
1520
+ ".cpp": "text/x-c++",
1521
+ ".h": "text/x-c",
1522
+ ".css": "text/css",
1523
+ ".go": "text/plain",
1524
+ ".php": "text/plain",
1525
+ // Images
1526
+ ".jpeg": "image/jpeg",
1527
+ ".jpg": "image/jpeg",
1528
+ ".png": "image/png",
1529
+ ".gif": "image/gif",
1530
+ ".webp": "image/webp",
1531
+ ".svg": "image/svg+xml",
1532
+ ".bmp": "image/bmp",
1533
+ ".tif": "image/tiff",
1534
+ ".tiff": "image/tiff",
1535
+ ".avif": "image/avif",
1536
+ ".apng": "image/apng",
1537
+ ".ico": "image/x-icon",
1538
+ // Videos
1539
+ ".mp4": "video/mp4",
1540
+ ".webm": "video/webm",
1541
+ ".ogg": "video/ogg",
1542
+ ".mov": "video/quicktime"
1543
+ };
1544
+ return extensionToMime[ext] ?? "application/octet-stream";
1545
+ }
1546
+ function getExtensionFromPath(path) {
1547
+ const match = path.match(/\.([^./?#]+)(?:[?#]|$)/);
1548
+ return match ? `.${match[1].toLowerCase()}` : null;
1549
+ }
1550
+
1551
+ // src/files/kimi-file-client.ts
1552
+ var KimiFileClient = class {
1553
+ constructor(config) {
1554
+ this.config = config;
1555
+ }
1556
+ /**
1557
+ * Upload a file to the Kimi API.
1558
+ */
1559
+ async upload(options) {
1560
+ const { data, filename, mediaType, purpose } = options;
1561
+ const resolvedMediaType = mediaType ?? getMediaTypeFromExtension(getExtensionFromPath(filename) ?? "") ?? "application/octet-stream";
1562
+ const resolvedPurpose = purpose ?? getPurposeFromMediaType(resolvedMediaType);
1563
+ const formData = new FormData();
1564
+ const fileData = typeof data === "string" ? base64ToUint8Array(data) : data;
1565
+ const blob = new Blob([new Uint8Array(fileData).buffer], { type: resolvedMediaType });
1566
+ formData.append("file", blob, filename);
1567
+ formData.append("purpose", resolvedPurpose);
1568
+ const fetchFn = this.config.fetch ?? fetch;
1569
+ const headers = this.config.headers();
1570
+ const response = await fetchFn(`${this.config.baseURL}/files`, {
1571
+ method: "POST",
1572
+ headers: {
1573
+ ...Object.fromEntries(
1574
+ Object.entries(headers).filter((entry) => entry[1] !== void 0)
1575
+ )
1576
+ // Don't set Content-Type - let the browser set it with boundary for FormData
1577
+ },
1578
+ body: formData
1579
+ });
1580
+ if (!response.ok) {
1581
+ const errorBody = await response.text();
1582
+ throw new Error(`Failed to upload file: ${response.status} ${response.statusText} - ${errorBody}`);
1583
+ }
1584
+ return await response.json();
1585
+ }
1586
+ /**
1587
+ * Get the content of an uploaded file (for file-extract purpose).
1588
+ */
1589
+ async getContent(fileId) {
1590
+ const fetchFn = this.config.fetch ?? fetch;
1591
+ const headers = this.config.headers();
1592
+ const response = await fetchFn(`${this.config.baseURL}/files/${fileId}/content`, {
1593
+ method: "GET",
1594
+ headers: Object.fromEntries(
1595
+ Object.entries(headers).filter((entry) => entry[1] !== void 0)
1596
+ )
1597
+ });
1598
+ if (!response.ok) {
1599
+ const errorBody = await response.text();
1600
+ throw new Error(`Failed to get file content: ${response.status} ${response.statusText} - ${errorBody}`);
1601
+ }
1602
+ return response.text();
1603
+ }
1604
+ /**
1605
+ * Upload a file and extract its content in one operation.
1606
+ * Only works for files with purpose="file-extract".
1607
+ */
1608
+ async uploadAndExtract(options) {
1609
+ const file = await this.upload({
1610
+ ...options,
1611
+ purpose: options.purpose ?? "file-extract"
1612
+ });
1613
+ let currentFile = file;
1614
+ let attempts = 0;
1615
+ const maxAttempts = 30;
1616
+ const pollInterval = 1e3;
1617
+ while (currentFile.status === "processing" && attempts < maxAttempts) {
1618
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
1619
+ currentFile = await this.getFile(file.id);
1620
+ attempts++;
1621
+ }
1622
+ if (currentFile.status === "error") {
1623
+ throw new Error(`File processing failed: ${currentFile.status_details ?? "Unknown error"}`);
1624
+ }
1625
+ if (currentFile.status === "processing") {
1626
+ throw new Error("File processing timed out");
1627
+ }
1628
+ let content;
1629
+ if (currentFile.purpose === "file-extract") {
1630
+ content = await this.getContent(file.id);
1631
+ }
1632
+ return { file: currentFile, content };
1633
+ }
1634
+ /**
1635
+ * Get file information.
1636
+ */
1637
+ async getFile(fileId) {
1638
+ const fetchFn = this.config.fetch ?? fetch;
1639
+ const headers = this.config.headers();
1640
+ const response = await fetchFn(`${this.config.baseURL}/files/${fileId}`, {
1641
+ method: "GET",
1642
+ headers: Object.fromEntries(
1643
+ Object.entries(headers).filter((entry) => entry[1] !== void 0)
1644
+ )
1645
+ });
1646
+ if (!response.ok) {
1647
+ const errorBody = await response.text();
1648
+ throw new Error(`Failed to get file: ${response.status} ${response.statusText} - ${errorBody}`);
1649
+ }
1650
+ return await response.json();
1651
+ }
1652
+ /**
1653
+ * List all uploaded files.
1654
+ */
1655
+ async listFiles() {
1656
+ const fetchFn = this.config.fetch ?? fetch;
1657
+ const headers = this.config.headers();
1658
+ const response = await fetchFn(`${this.config.baseURL}/files`, {
1659
+ method: "GET",
1660
+ headers: Object.fromEntries(
1661
+ Object.entries(headers).filter((entry) => entry[1] !== void 0)
1662
+ )
1663
+ });
1664
+ if (!response.ok) {
1665
+ const errorBody = await response.text();
1666
+ throw new Error(`Failed to list files: ${response.status} ${response.statusText} - ${errorBody}`);
1667
+ }
1668
+ const result = await response.json();
1669
+ return result.data;
1670
+ }
1671
+ /**
1672
+ * Delete a file.
1673
+ */
1674
+ async deleteFile(fileId) {
1675
+ const fetchFn = this.config.fetch ?? fetch;
1676
+ const headers = this.config.headers();
1677
+ const response = await fetchFn(`${this.config.baseURL}/files/${fileId}`, {
1678
+ method: "DELETE",
1679
+ headers: Object.fromEntries(
1680
+ Object.entries(headers).filter((entry) => entry[1] !== void 0)
1681
+ )
1682
+ });
1683
+ if (!response.ok) {
1684
+ const errorBody = await response.text();
1685
+ throw new Error(`Failed to delete file: ${response.status} ${response.statusText} - ${errorBody}`);
1686
+ }
1687
+ }
1688
+ };
1689
+ function base64ToUint8Array(base64) {
1690
+ const base64Data = base64.includes(",") ? base64.split(",")[1] : base64;
1691
+ const binaryString = atob(base64Data);
1692
+ const bytes = new Uint8Array(binaryString.length);
1693
+ for (let i = 0; i < binaryString.length; i++) {
1694
+ bytes[i] = binaryString.charCodeAt(i);
1695
+ }
1696
+ return bytes;
1697
+ }
1698
+
1699
+ // src/files/attachment-processor.ts
1700
+ async function processAttachments(options) {
1701
+ const {
1702
+ attachments,
1703
+ clientConfig,
1704
+ autoUploadDocuments = true,
1705
+ uploadImages = false,
1706
+ cleanupAfterExtract = false
1707
+ } = options;
1708
+ const results = [];
1709
+ const client = new KimiFileClient(clientConfig);
1710
+ for (const attachment of attachments) {
1711
+ try {
1712
+ const processed = await processAttachment(attachment, client, {
1713
+ autoUploadDocuments,
1714
+ uploadImages,
1715
+ cleanupAfterExtract
1716
+ });
1717
+ results.push(processed);
1718
+ } catch (error) {
1719
+ results.push({
1720
+ original: attachment,
1721
+ type: "skip",
1722
+ error: error instanceof Error ? error.message : String(error)
1723
+ });
1724
+ }
1725
+ }
1726
+ return results;
1727
+ }
1728
+ async function processAttachment(attachment, client, options) {
1729
+ const contentType = resolveContentType(attachment);
1730
+ if (isImageMediaType2(contentType)) {
1731
+ if (options.uploadImages && attachment.content) {
1732
+ const result = await client.upload({
1733
+ data: attachment.content,
1734
+ filename: attachment.name ?? "image.jpg",
1735
+ mediaType: contentType,
1736
+ purpose: "image"
1737
+ });
1738
+ return {
1739
+ original: attachment,
1740
+ type: "image-url",
1741
+ fileId: result.id,
1742
+ mediaUrl: attachment.url
1743
+ };
1744
+ }
1745
+ return {
1746
+ original: attachment,
1747
+ type: "image-url",
1748
+ mediaUrl: attachment.url
1749
+ };
1750
+ }
1751
+ if (isVideoMediaType2(contentType)) {
1752
+ return {
1753
+ original: attachment,
1754
+ type: "video-url",
1755
+ mediaUrl: attachment.url
1756
+ };
1757
+ }
1758
+ if (options.autoUploadDocuments && (isDocumentMediaType(contentType) || isFileExtractMediaType(contentType))) {
1759
+ let data;
1760
+ if (attachment.content) {
1761
+ data = attachment.content;
1762
+ } else if (attachment.url) {
1763
+ const response = await fetch(attachment.url);
1764
+ if (!response.ok) {
1765
+ throw new Error(`Failed to fetch attachment: ${response.status}`);
1766
+ }
1767
+ data = new Uint8Array(await response.arrayBuffer());
1768
+ } else {
1769
+ return {
1770
+ original: attachment,
1771
+ type: "skip",
1772
+ error: "No content or URL provided for document attachment"
1773
+ };
1774
+ }
1775
+ const result = await client.uploadAndExtract({
1776
+ data,
1777
+ filename: attachment.name ?? guessFilename(attachment, contentType),
1778
+ mediaType: contentType,
1779
+ purpose: "file-extract"
1780
+ });
1781
+ if (options.cleanupAfterExtract && result.file.id) {
1782
+ try {
1783
+ await client.deleteFile(result.file.id);
1784
+ } catch {
1785
+ }
1786
+ }
1787
+ return {
1788
+ original: attachment,
1789
+ type: "text-inject",
1790
+ textContent: result.content,
1791
+ fileId: result.file.id
1792
+ };
1793
+ }
1794
+ return {
1795
+ original: attachment,
1796
+ type: "skip",
1797
+ error: `Unsupported content type: ${contentType}`
1798
+ };
1799
+ }
1800
+ function resolveContentType(attachment) {
1801
+ if (attachment.contentType) {
1802
+ return attachment.contentType;
1803
+ }
1804
+ const path = attachment.name ?? attachment.url;
1805
+ if (path) {
1806
+ const ext = getExtensionFromPath(path);
1807
+ if (ext) {
1808
+ return getMediaTypeFromExtension(ext);
1809
+ }
1810
+ }
1811
+ return "application/octet-stream";
1812
+ }
1813
+ function guessFilename(attachment, contentType) {
1814
+ if (attachment.name) {
1815
+ return attachment.name;
1816
+ }
1817
+ if (attachment.url) {
1818
+ const urlPath = attachment.url.split("?")[0];
1819
+ const segments = urlPath.split("/");
1820
+ const lastSegment = segments[segments.length - 1];
1821
+ if (lastSegment && lastSegment.includes(".")) {
1822
+ return lastSegment;
1823
+ }
1824
+ }
1825
+ const extensionMap = {
1826
+ "application/pdf": "document.pdf",
1827
+ "text/plain": "document.txt",
1828
+ "application/msword": "document.doc",
1829
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "document.docx",
1830
+ "image/jpeg": "image.jpg",
1831
+ "image/png": "image.png"
1832
+ };
1833
+ return extensionMap[contentType] ?? "file.bin";
1834
+ }
1835
+
1836
+ // src/version.ts
1837
+ var VERSION = "0.2.0".length > 0 ? "0.2.0" : "0.0.0";
1838
+
1839
+ // src/kimi-provider.ts
1840
+ var GLOBAL_BASE_URL = "https://api.moonshot.ai/v1";
1841
+ var CN_BASE_URL = "https://api.moonshot.cn/v1";
1842
+ function createKimi(options = {}) {
1843
+ const resolvedBaseURL = (0, import_provider_utils4.loadOptionalSetting)({
1844
+ settingValue: options.baseURL,
1845
+ environmentVariableName: "MOONSHOT_BASE_URL"
1846
+ }) ?? (options.endpoint === "cn" ? CN_BASE_URL : GLOBAL_BASE_URL);
1847
+ const baseURL = (0, import_provider_utils4.withoutTrailingSlash)(resolvedBaseURL) ?? GLOBAL_BASE_URL;
1848
+ const getHeaders = () => (0, import_provider_utils4.withUserAgentSuffix)(
1849
+ {
1850
+ Authorization: `Bearer ${(0, import_provider_utils4.loadApiKey)({
1851
+ apiKey: options.apiKey,
1852
+ environmentVariableName: "MOONSHOT_API_KEY",
1853
+ description: "Moonshot"
1854
+ })}`,
1855
+ ...options.headers
1856
+ },
1857
+ `ai-sdk/kimi/${VERSION}`
1858
+ );
1859
+ const createChatModel = (modelId, settings = {}) => new KimiChatLanguageModel(modelId, settings, {
1860
+ provider: "kimi.chat",
1861
+ baseURL,
1862
+ headers: getHeaders,
1863
+ fetch: options.fetch,
1864
+ generateId: options.generateId,
1865
+ supportsStructuredOutputs: settings.supportsStructuredOutputs ?? options.supportsStructuredOutputs,
1866
+ includeUsageInStream: settings.includeUsageInStream ?? options.includeUsageInStream,
1867
+ supportedUrls: settings.supportedUrls ?? options.supportedUrls
1868
+ });
1869
+ const provider = (modelId, settings) => {
1870
+ if (new.target) {
1871
+ throw new Error("The Kimi provider function cannot be called with new.");
1872
+ }
1873
+ return createChatModel(modelId, settings);
1874
+ };
1875
+ provider.specificationVersion = "v3";
1876
+ provider.languageModel = createChatModel;
1877
+ provider.chat = createChatModel;
1878
+ provider.tools = kimiTools;
1879
+ provider.files = new KimiFileClient({
1880
+ baseURL,
1881
+ headers: getHeaders,
1882
+ fetch: options.fetch
1883
+ });
1884
+ provider.embeddingModel = (modelId) => {
1885
+ throw new import_provider4.NoSuchModelError({ modelId, modelType: "embeddingModel" });
1886
+ };
1887
+ provider.imageModel = (modelId) => {
1888
+ throw new import_provider4.NoSuchModelError({ modelId, modelType: "imageModel" });
1889
+ };
1890
+ provider.rerankingModel = (modelId) => {
1891
+ throw new import_provider4.NoSuchModelError({ modelId, modelType: "rerankingModel" });
1892
+ };
1893
+ return provider;
1894
+ }
1895
+ var kimi = createKimi();
1896
+
1897
+ // src/code/kimi-code-language-model.ts
1898
+ var import_provider_utils6 = require("@ai-sdk/provider-utils");
1899
+ var import_v45 = require("zod/v4");
1900
+
1901
+ // src/code/kimi-code-messages.ts
1902
+ var import_provider5 = require("@ai-sdk/provider");
1903
+ var import_provider_utils5 = require("@ai-sdk/provider-utils");
1904
+ async function convertToKimiCodePrompt(prompt) {
1905
+ let systemMessage;
1906
+ const messages = [];
1907
+ for (const message of prompt) {
1908
+ switch (message.role) {
1909
+ case "system": {
1910
+ const systemText = typeof message.content === "string" ? message.content : "";
1911
+ systemMessage = systemMessage ? `${systemMessage}
1912
+
1913
+ ${systemText}` : systemText;
1914
+ break;
1915
+ }
1916
+ case "user": {
1917
+ const content = [];
1918
+ for (const part of message.content) {
1919
+ switch (part.type) {
1920
+ case "text":
1921
+ content.push({ type: "text", text: part.text });
1922
+ break;
1923
+ case "file":
1924
+ if (part.mediaType?.startsWith("image/")) {
1925
+ content.push(await convertFilePart(part));
1926
+ } else {
1927
+ throw new import_provider5.UnsupportedFunctionalityError({
1928
+ functionality: `file type: ${part.mediaType}`
1929
+ });
1930
+ }
1931
+ break;
1932
+ default:
1933
+ throw new import_provider5.UnsupportedFunctionalityError({
1934
+ functionality: `user content part type: ${part.type}`
1935
+ });
1936
+ }
1937
+ }
1938
+ messages.push({
1939
+ role: "user",
1940
+ content: content.length === 1 && content[0].type === "text" ? content[0].text : content
1941
+ });
1942
+ break;
1943
+ }
1944
+ case "assistant": {
1945
+ const content = [];
1946
+ for (const part of message.content) {
1947
+ switch (part.type) {
1948
+ case "text":
1949
+ content.push({ type: "text", text: part.text });
1950
+ break;
1951
+ case "tool-call":
1952
+ content.push({
1953
+ type: "tool_use",
1954
+ id: part.toolCallId,
1955
+ name: part.toolName,
1956
+ input: typeof part.input === "string" ? JSON.parse(part.input) : part.input
1957
+ });
1958
+ break;
1959
+ case "reasoning":
1960
+ if (part.text) {
1961
+ content.push({ type: "text", text: `<thinking>${part.text}</thinking>` });
1962
+ }
1963
+ break;
1964
+ default:
1965
+ throw new import_provider5.UnsupportedFunctionalityError({
1966
+ functionality: `assistant content part type: ${part.type}`
1967
+ });
1968
+ }
1969
+ }
1970
+ if (content.length > 0) {
1971
+ messages.push({
1972
+ role: "assistant",
1973
+ content: content.length === 1 && content[0].type === "text" ? content[0].text : content
1974
+ });
1975
+ }
1976
+ break;
1977
+ }
1978
+ case "tool": {
1979
+ const toolResults = [];
1980
+ for (const part of message.content) {
1981
+ if (part.type === "tool-result") {
1982
+ toolResults.push(convertToolResultPart(part));
1983
+ }
1984
+ }
1985
+ if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
1986
+ messages.push({
1987
+ role: "user",
1988
+ content: toolResults
1989
+ });
1990
+ } else {
1991
+ const lastMessage = messages[messages.length - 1];
1992
+ if (lastMessage?.role === "user" && Array.isArray(lastMessage.content)) {
1993
+ lastMessage.content.push(...toolResults);
1994
+ } else {
1995
+ messages.push({
1996
+ role: "user",
1997
+ content: toolResults
1998
+ });
1999
+ }
2000
+ }
2001
+ break;
2002
+ }
2003
+ default:
2004
+ throw new import_provider5.UnsupportedFunctionalityError({
2005
+ functionality: `message role: ${message.role}`
2006
+ });
2007
+ }
2008
+ }
2009
+ return {
2010
+ system: systemMessage,
2011
+ messages
2012
+ };
2013
+ }
2014
+ async function convertFilePart(part) {
2015
+ const mediaType = part.mediaType ?? "image/png";
2016
+ if (part.data instanceof URL) {
2017
+ return {
2018
+ type: "image",
2019
+ source: {
2020
+ type: "url",
2021
+ url: part.data.toString()
2022
+ }
2023
+ };
2024
+ }
2025
+ if (typeof part.data === "string") {
2026
+ if (part.data.startsWith("http://") || part.data.startsWith("https://")) {
2027
+ return {
2028
+ type: "image",
2029
+ source: {
2030
+ type: "url",
2031
+ url: part.data
2032
+ }
2033
+ };
2034
+ }
2035
+ if (part.data.startsWith("data:")) {
2036
+ const [header, data] = part.data.split(",");
2037
+ const extractedMimeType = header.match(/data:([^;]+)/)?.[1] ?? mediaType;
2038
+ return {
2039
+ type: "image",
2040
+ source: {
2041
+ type: "base64",
2042
+ media_type: extractedMimeType,
2043
+ data
2044
+ }
2045
+ };
2046
+ }
2047
+ return {
2048
+ type: "image",
2049
+ source: {
2050
+ type: "base64",
2051
+ media_type: mediaType,
2052
+ data: part.data
2053
+ }
2054
+ };
2055
+ }
2056
+ const base64 = (0, import_provider_utils5.convertToBase64)(part.data);
2057
+ return {
2058
+ type: "image",
2059
+ source: {
2060
+ type: "base64",
2061
+ media_type: mediaType,
2062
+ data: base64
2063
+ }
2064
+ };
2065
+ }
2066
+ function convertToolResultPart(part) {
2067
+ const output = part.output;
2068
+ let content;
2069
+ let isError = false;
2070
+ switch (output.type) {
2071
+ case "text":
2072
+ content = String(output.value ?? "");
2073
+ break;
2074
+ case "error-text":
2075
+ content = String(output.value ?? "");
2076
+ isError = true;
2077
+ break;
2078
+ case "execution-denied":
2079
+ content = output.reason ?? "Tool execution denied.";
2080
+ isError = true;
2081
+ break;
2082
+ case "json":
2083
+ case "content":
2084
+ content = JSON.stringify(output.value);
2085
+ break;
2086
+ case "error-json":
2087
+ content = JSON.stringify(output.value);
2088
+ isError = true;
2089
+ break;
2090
+ default:
2091
+ content = JSON.stringify(output);
2092
+ }
2093
+ return {
2094
+ type: "tool_result",
2095
+ tool_use_id: part.toolCallId,
2096
+ content,
2097
+ is_error: isError || void 0
2098
+ };
2099
+ }
2100
+
2101
+ // src/code/kimi-code-settings.ts
2102
+ var import_v44 = require("zod/v4");
2103
+ var kimiCodeProviderOptionsSchema = import_v44.z.object({
2104
+ /**
2105
+ * Extended thinking configuration.
2106
+ */
2107
+ extendedThinking: import_v44.z.union([
2108
+ import_v44.z.boolean(),
2109
+ import_v44.z.object({
2110
+ enabled: import_v44.z.boolean().optional(),
2111
+ effort: import_v44.z.enum(["low", "medium", "high"]).optional(),
2112
+ budgetTokens: import_v44.z.number().optional()
2113
+ })
2114
+ ]).optional(),
2115
+ /**
2116
+ * System prompt to prepend.
2117
+ */
2118
+ system: import_v44.z.string().optional(),
2119
+ /**
2120
+ * Custom stop sequences.
2121
+ */
2122
+ stopSequences: import_v44.z.array(import_v44.z.string()).optional()
2123
+ });
2124
+ function normalizeExtendedThinkingConfig(config) {
2125
+ if (config === void 0) {
2126
+ return void 0;
2127
+ }
2128
+ if (typeof config === "boolean") {
2129
+ return config ? { enabled: true, effort: "medium" } : { enabled: false };
2130
+ }
2131
+ return {
2132
+ enabled: config.enabled ?? true,
2133
+ effort: config.effort ?? "medium",
2134
+ budgetTokens: config.budgetTokens
2135
+ };
2136
+ }
2137
+ function effortToBudgetTokens(effort) {
2138
+ switch (effort) {
2139
+ case "low":
2140
+ return 2048;
2141
+ case "medium":
2142
+ return 8192;
2143
+ case "high":
2144
+ return 16384;
2145
+ default:
2146
+ return 8192;
2147
+ }
2148
+ }
2149
+
2150
+ // src/code/kimi-code-types.ts
2151
+ var KIMI_CODE_BASE_URL = "https://api.kimi.com/coding/v1";
2152
+ var KIMI_CODE_DEFAULT_MODEL = "kimi-for-coding";
2153
+ var KIMI_CODE_THINKING_MODEL = "kimi-k2-thinking";
2154
+ var KIMI_CODE_DEFAULT_MAX_TOKENS = 32768;
2155
+ var KIMI_CODE_DEFAULT_CONTEXT_WINDOW = 262144;
2156
+ function inferKimiCodeCapabilities(modelId) {
2157
+ const isThinkingModel = modelId.includes("-thinking") || modelId.includes("k2-thinking");
2158
+ return {
2159
+ extendedThinking: isThinkingModel,
2160
+ maxOutputTokens: KIMI_CODE_DEFAULT_MAX_TOKENS,
2161
+ maxContextSize: KIMI_CODE_DEFAULT_CONTEXT_WINDOW,
2162
+ streaming: true,
2163
+ toolCalling: true,
2164
+ imageInput: true
2165
+ };
2166
+ }
2167
+
2168
+ // src/code/kimi-code-language-model.ts
2169
+ var kimiCodeErrorSchema = import_v45.z.union([
2170
+ import_v45.z.object({
2171
+ error: import_v45.z.object({
2172
+ message: import_v45.z.string(),
2173
+ type: import_v45.z.string().nullish(),
2174
+ code: import_v45.z.union([import_v45.z.string(), import_v45.z.number()]).nullish()
2175
+ })
2176
+ }),
2177
+ import_v45.z.object({
2178
+ message: import_v45.z.string()
2179
+ })
2180
+ ]);
2181
+ var kimiCodeTextContentSchema = import_v45.z.object({
2182
+ type: import_v45.z.literal("text"),
2183
+ text: import_v45.z.string()
2184
+ });
2185
+ var kimiCodeThinkingContentSchema = import_v45.z.object({
2186
+ type: import_v45.z.literal("thinking"),
2187
+ thinking: import_v45.z.string()
2188
+ });
2189
+ var kimiCodeToolUseContentSchema = import_v45.z.object({
2190
+ type: import_v45.z.literal("tool_use"),
2191
+ id: import_v45.z.string(),
2192
+ name: import_v45.z.string(),
2193
+ input: import_v45.z.record(import_v45.z.string(), import_v45.z.unknown())
2194
+ });
2195
+ var kimiCodeContentBlockSchema = import_v45.z.union([
2196
+ kimiCodeTextContentSchema,
2197
+ kimiCodeThinkingContentSchema,
2198
+ kimiCodeToolUseContentSchema
2199
+ ]);
2200
+ var kimiCodeResponseSchema = import_v45.z.object({
2201
+ id: import_v45.z.string().optional(),
2202
+ type: import_v45.z.string().optional(),
2203
+ model: import_v45.z.string().optional(),
2204
+ stop_reason: import_v45.z.string().nullish(),
2205
+ stop_sequence: import_v45.z.string().nullish(),
2206
+ content: import_v45.z.array(kimiCodeContentBlockSchema),
2207
+ usage: import_v45.z.object({
2208
+ input_tokens: import_v45.z.number().optional(),
2209
+ output_tokens: import_v45.z.number().optional(),
2210
+ cache_read_input_tokens: import_v45.z.number().optional(),
2211
+ cache_creation_input_tokens: import_v45.z.number().optional()
2212
+ }).optional()
2213
+ });
2214
+ var kimiCodeStreamChunkSchema = import_v45.z.object({
2215
+ type: import_v45.z.string(),
2216
+ index: import_v45.z.number().optional(),
2217
+ message: import_v45.z.object({
2218
+ id: import_v45.z.string().optional(),
2219
+ type: import_v45.z.string().optional(),
2220
+ model: import_v45.z.string().optional(),
2221
+ content: import_v45.z.array(import_v45.z.unknown()).optional(),
2222
+ stop_reason: import_v45.z.string().nullish(),
2223
+ stop_sequence: import_v45.z.string().nullish(),
2224
+ usage: import_v45.z.object({
2225
+ input_tokens: import_v45.z.number().optional(),
2226
+ output_tokens: import_v45.z.number().optional()
2227
+ }).optional()
2228
+ }).optional(),
2229
+ content_block: import_v45.z.object({
2230
+ type: import_v45.z.string(),
2231
+ text: import_v45.z.string().optional(),
2232
+ thinking: import_v45.z.string().optional(),
2233
+ id: import_v45.z.string().optional(),
2234
+ name: import_v45.z.string().optional(),
2235
+ input: import_v45.z.record(import_v45.z.string(), import_v45.z.unknown()).optional()
2236
+ }).optional(),
2237
+ delta: import_v45.z.object({
2238
+ type: import_v45.z.string().optional(),
2239
+ text: import_v45.z.string().optional(),
2240
+ thinking: import_v45.z.string().optional(),
2241
+ partial_json: import_v45.z.string().optional(),
2242
+ stop_reason: import_v45.z.string().optional(),
2243
+ stop_sequence: import_v45.z.string().optional()
2244
+ }).optional(),
2245
+ usage: import_v45.z.object({
2246
+ input_tokens: import_v45.z.number().optional(),
2247
+ output_tokens: import_v45.z.number().optional()
2248
+ }).optional()
2249
+ });
2250
+ var kimiCodeFailedResponseHandler = (0, import_provider_utils6.createJsonErrorResponseHandler)({
2251
+ errorSchema: kimiCodeErrorSchema,
2252
+ errorToMessage: (error) => {
2253
+ if ("error" in error) {
2254
+ return error.error.message;
2255
+ }
2256
+ return error.message;
2257
+ },
2258
+ isRetryable: (response) => response.status === 408 || response.status === 409 || response.status === 429 || response.status >= 500
2259
+ });
2260
+ function mapStopReason(stopReason) {
2261
+ switch (stopReason) {
2262
+ case "end_turn":
2263
+ case "stop_sequence":
2264
+ return { unified: "stop", raw: stopReason };
2265
+ case "tool_use":
2266
+ return { unified: "tool-calls", raw: stopReason };
2267
+ case "max_tokens":
2268
+ return { unified: "length", raw: stopReason };
2269
+ default:
2270
+ return { unified: "other", raw: stopReason ?? void 0 };
2271
+ }
2272
+ }
2273
+ function convertUsage(usage) {
2274
+ const inputTokens = usage?.input_tokens ?? 0;
2275
+ const outputTokens = usage?.output_tokens ?? 0;
2276
+ const cacheRead = usage?.cache_read_input_tokens ?? 0;
2277
+ return {
2278
+ inputTokens: {
2279
+ total: inputTokens,
2280
+ cacheRead,
2281
+ cacheWrite: usage?.cache_creation_input_tokens,
2282
+ noCache: inputTokens - cacheRead
2283
+ },
2284
+ outputTokens: {
2285
+ total: outputTokens,
2286
+ text: outputTokens,
2287
+ reasoning: 0
2288
+ },
2289
+ raw: usage
2290
+ };
2291
+ }
2292
+ function convertTools(tools) {
2293
+ if (!tools || tools.length === 0) {
2294
+ return void 0;
2295
+ }
2296
+ return tools.map((tool) => {
2297
+ return {
2298
+ name: tool.name,
2299
+ description: tool.description,
2300
+ input_schema: tool.inputSchema ?? { type: "object", properties: {} }
2301
+ };
2302
+ });
2303
+ }
2304
+ var KimiCodeLanguageModel = class {
2305
+ constructor(modelId, settings, config) {
2306
+ this.specificationVersion = "v3";
2307
+ this.modelId = modelId;
2308
+ this.settings = settings;
2309
+ this.config = config;
2310
+ this.generateIdFn = config.generateId ?? import_provider_utils6.generateId;
2311
+ }
2312
+ get provider() {
2313
+ return this.config.provider;
2314
+ }
2315
+ get providerOptionsName() {
2316
+ return "kimiCode";
2317
+ }
2318
+ /**
2319
+ * Get the inferred or configured capabilities for this model.
2320
+ */
2321
+ get capabilities() {
2322
+ const inferred = inferKimiCodeCapabilities(this.modelId);
2323
+ return {
2324
+ ...inferred,
2325
+ ...this.settings.capabilities
2326
+ };
2327
+ }
2328
+ get supportedUrls() {
2329
+ const patterns = {
2330
+ "image/*": [/^https?:\/\/.*$/i]
2331
+ };
2332
+ return this.settings.supportedUrls ?? this.config.supportedUrls ?? patterns;
2333
+ }
2334
+ /**
2335
+ * Build request arguments.
2336
+ */
2337
+ async getArgs(options) {
2338
+ const { prompt, maxOutputTokens, temperature, topP, topK, stopSequences, tools, toolChoice, providerOptions } = options;
2339
+ const warnings = [];
2340
+ const kimiCodeOptions = await (0, import_provider_utils6.parseProviderOptions)({
2341
+ provider: this.providerOptionsName,
2342
+ providerOptions,
2343
+ schema: kimiCodeProviderOptionsSchema
2344
+ });
2345
+ const extendedThinking = normalizeExtendedThinkingConfig(kimiCodeOptions?.extendedThinking) ?? normalizeExtendedThinkingConfig(this.settings.extendedThinking);
2346
+ if (topK != null) {
2347
+ warnings.push({
2348
+ type: "unsupported",
2349
+ feature: "topK"
2350
+ });
2351
+ }
2352
+ const { system, messages } = await convertToKimiCodePrompt(prompt);
2353
+ let toolChoiceParam;
2354
+ if (toolChoice != null) {
2355
+ switch (toolChoice.type) {
2356
+ case "auto":
2357
+ toolChoiceParam = { type: "auto" };
2358
+ break;
2359
+ case "none":
2360
+ toolChoiceParam = { type: "none" };
2361
+ break;
2362
+ case "required":
2363
+ toolChoiceParam = { type: "any" };
2364
+ break;
2365
+ case "tool":
2366
+ toolChoiceParam = { type: "tool", name: toolChoice.toolName };
2367
+ break;
2368
+ }
2369
+ }
2370
+ const functionTools = tools?.filter((t) => t.type === "function");
2371
+ const body = (0, import_provider_utils6.removeUndefinedEntries)({
2372
+ model: this.modelId,
2373
+ system: kimiCodeOptions?.system ?? system,
2374
+ messages,
2375
+ max_tokens: maxOutputTokens ?? this.capabilities.maxOutputTokens ?? 32768,
2376
+ temperature,
2377
+ top_p: topP,
2378
+ stop_sequences: kimiCodeOptions?.stopSequences ?? stopSequences,
2379
+ tools: convertTools(functionTools),
2380
+ tool_choice: toolChoiceParam,
2381
+ // Extended thinking parameters
2382
+ ...extendedThinking?.enabled && {
2383
+ thinking: {
2384
+ type: "enabled",
2385
+ budget_tokens: extendedThinking.budgetTokens ?? effortToBudgetTokens(extendedThinking.effort ?? "medium")
2386
+ }
2387
+ }
2388
+ });
2389
+ const requestHeaders = {
2390
+ ...options.headers ?? {}
2391
+ };
2392
+ return {
2393
+ body,
2394
+ warnings,
2395
+ requestHeaders
2396
+ };
2397
+ }
2398
+ async doGenerate(options) {
2399
+ const { body, warnings, requestHeaders } = await this.getArgs(options);
2400
+ const {
2401
+ responseHeaders,
2402
+ value: rawResponse,
2403
+ rawValue
2404
+ } = await (0, import_provider_utils6.postJsonToApi)({
2405
+ url: `${this.config.baseURL}/messages`,
2406
+ headers: (0, import_provider_utils6.combineHeaders)(this.config.headers(), requestHeaders, options.headers),
2407
+ body,
2408
+ failedResponseHandler: kimiCodeFailedResponseHandler,
2409
+ successfulResponseHandler: (0, import_provider_utils6.createJsonResponseHandler)(kimiCodeResponseSchema),
2410
+ abortSignal: options.abortSignal,
2411
+ fetch: this.config.fetch
2412
+ });
2413
+ const response = rawResponse;
2414
+ const content = [];
2415
+ for (const block of response.content) {
2416
+ switch (block.type) {
2417
+ case "text":
2418
+ content.push({ type: "text", text: block.text });
2419
+ break;
2420
+ case "thinking":
2421
+ content.push({
2422
+ type: "reasoning",
2423
+ text: block.thinking
2424
+ });
2425
+ break;
2426
+ case "tool_use":
2427
+ content.push({
2428
+ type: "tool-call",
2429
+ toolCallId: block.id,
2430
+ toolName: block.name,
2431
+ input: JSON.stringify(block.input)
2432
+ });
2433
+ break;
2434
+ }
2435
+ }
2436
+ const providerMetadata = {
2437
+ [this.providerOptionsName]: {
2438
+ requestId: responseHeaders?.["x-request-id"] ?? void 0,
2439
+ modelId: response.model,
2440
+ stopReason: response.stop_reason,
2441
+ stopSequence: response.stop_sequence
2442
+ }
2443
+ };
2444
+ return {
2445
+ content,
2446
+ finishReason: mapStopReason(response.stop_reason),
2447
+ usage: convertUsage(response.usage),
2448
+ providerMetadata,
2449
+ request: { body },
2450
+ response: {
2451
+ id: response.id,
2452
+ modelId: response.model,
2453
+ headers: responseHeaders,
2454
+ body: rawValue
2455
+ },
2456
+ warnings
2457
+ };
2458
+ }
2459
+ async doStream(options) {
2460
+ const { body, warnings, requestHeaders } = await this.getArgs(options);
2461
+ const streamBody = {
2462
+ ...body,
2463
+ stream: true
2464
+ };
2465
+ const { responseHeaders, value: response } = await (0, import_provider_utils6.postJsonToApi)({
2466
+ url: `${this.config.baseURL}/messages`,
2467
+ headers: (0, import_provider_utils6.combineHeaders)(this.config.headers(), requestHeaders, options.headers),
2468
+ body: streamBody,
2469
+ failedResponseHandler: kimiCodeFailedResponseHandler,
2470
+ successfulResponseHandler: (0, import_provider_utils6.createEventSourceResponseHandler)(kimiCodeStreamChunkSchema),
2471
+ abortSignal: options.abortSignal,
2472
+ fetch: this.config.fetch
2473
+ });
2474
+ const providerOptionsName = this.providerOptionsName;
2475
+ const generateIdFn = this.generateIdFn;
2476
+ const capturedResponseHeaders = responseHeaders;
2477
+ let currentBlockType;
2478
+ let currentToolCallId;
2479
+ let currentToolName;
2480
+ let accumulatedToolInput = "";
2481
+ let finishReason = { unified: "other", raw: void 0 };
2482
+ let usage;
2483
+ let responseId;
2484
+ let responseModel;
2485
+ let isActiveText = false;
2486
+ let isActiveReasoning = false;
2487
+ let hasToolCallFinished = false;
2488
+ return {
2489
+ stream: response.pipeThrough(
2490
+ new TransformStream({
2491
+ start(controller) {
2492
+ controller.enqueue({ type: "stream-start", warnings });
2493
+ },
2494
+ transform(chunk, controller) {
2495
+ if (!chunk.success) {
2496
+ controller.enqueue({ type: "error", error: chunk.error });
2497
+ return;
2498
+ }
2499
+ const data = chunk.value;
2500
+ switch (data.type) {
2501
+ case "message_start":
2502
+ if (data.message) {
2503
+ responseId = data.message.id;
2504
+ responseModel = data.message.model;
2505
+ if (data.message.usage) {
2506
+ usage = convertUsage(data.message.usage);
2507
+ }
2508
+ controller.enqueue({
2509
+ type: "response-metadata",
2510
+ id: responseId,
2511
+ modelId: responseModel
2512
+ });
2513
+ }
2514
+ break;
2515
+ case "content_block_start":
2516
+ if (data.content_block) {
2517
+ currentBlockType = data.content_block.type;
2518
+ if (data.content_block.type === "tool_use") {
2519
+ currentToolCallId = data.content_block.id ?? generateIdFn();
2520
+ currentToolName = data.content_block.name;
2521
+ accumulatedToolInput = "";
2522
+ hasToolCallFinished = false;
2523
+ if (isActiveText) {
2524
+ controller.enqueue({ type: "text-end", id: "text-0" });
2525
+ isActiveText = false;
2526
+ }
2527
+ if (isActiveReasoning) {
2528
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
2529
+ isActiveReasoning = false;
2530
+ }
2531
+ controller.enqueue({
2532
+ type: "tool-input-start",
2533
+ id: currentToolCallId,
2534
+ toolName: currentToolName ?? ""
2535
+ });
2536
+ } else if (data.content_block.type === "text") {
2537
+ if (!isActiveText) {
2538
+ if (isActiveReasoning) {
2539
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
2540
+ isActiveReasoning = false;
2541
+ }
2542
+ controller.enqueue({ type: "text-start", id: "text-0" });
2543
+ isActiveText = true;
2544
+ }
2545
+ } else if (data.content_block.type === "thinking") {
2546
+ if (!isActiveReasoning) {
2547
+ if (isActiveText) {
2548
+ controller.enqueue({ type: "text-end", id: "text-0" });
2549
+ isActiveText = false;
2550
+ }
2551
+ controller.enqueue({ type: "reasoning-start", id: "reasoning-0" });
2552
+ isActiveReasoning = true;
2553
+ }
2554
+ }
2555
+ }
2556
+ break;
2557
+ case "content_block_delta":
2558
+ if (data.delta) {
2559
+ if (data.delta.type === "text_delta" && data.delta.text) {
2560
+ if (!isActiveText) {
2561
+ if (isActiveReasoning) {
2562
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
2563
+ isActiveReasoning = false;
2564
+ }
2565
+ controller.enqueue({ type: "text-start", id: "text-0" });
2566
+ isActiveText = true;
2567
+ }
2568
+ controller.enqueue({
2569
+ type: "text-delta",
2570
+ id: "text-0",
2571
+ delta: data.delta.text
2572
+ });
2573
+ } else if (data.delta.type === "thinking_delta" && data.delta.thinking) {
2574
+ if (!isActiveReasoning) {
2575
+ if (isActiveText) {
2576
+ controller.enqueue({ type: "text-end", id: "text-0" });
2577
+ isActiveText = false;
2578
+ }
2579
+ controller.enqueue({ type: "reasoning-start", id: "reasoning-0" });
2580
+ isActiveReasoning = true;
2581
+ }
2582
+ controller.enqueue({
2583
+ type: "reasoning-delta",
2584
+ id: "reasoning-0",
2585
+ delta: data.delta.thinking
2586
+ });
2587
+ } else if (data.delta.type === "input_json_delta" && data.delta.partial_json) {
2588
+ accumulatedToolInput += data.delta.partial_json;
2589
+ controller.enqueue({
2590
+ type: "tool-input-delta",
2591
+ id: currentToolCallId ?? "",
2592
+ delta: data.delta.partial_json
2593
+ });
2594
+ }
2595
+ }
2596
+ break;
2597
+ case "content_block_stop":
2598
+ if (currentBlockType === "tool_use" && currentToolCallId && !hasToolCallFinished) {
2599
+ controller.enqueue({ type: "tool-input-end", id: currentToolCallId });
2600
+ controller.enqueue({
2601
+ type: "tool-call",
2602
+ toolCallId: currentToolCallId,
2603
+ toolName: currentToolName ?? "",
2604
+ input: accumulatedToolInput
2605
+ });
2606
+ hasToolCallFinished = true;
2607
+ } else if (currentBlockType === "text" && isActiveText) {
2608
+ controller.enqueue({ type: "text-end", id: "text-0" });
2609
+ isActiveText = false;
2610
+ } else if (currentBlockType === "thinking" && isActiveReasoning) {
2611
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
2612
+ isActiveReasoning = false;
2613
+ }
2614
+ currentBlockType = void 0;
2615
+ currentToolCallId = void 0;
2616
+ currentToolName = void 0;
2617
+ accumulatedToolInput = "";
2618
+ break;
2619
+ case "message_delta":
2620
+ if (data.delta?.stop_reason) {
2621
+ finishReason = mapStopReason(data.delta.stop_reason);
2622
+ }
2623
+ if (data.usage) {
2624
+ usage = convertUsage(data.usage);
2625
+ }
2626
+ break;
2627
+ case "message_stop":
2628
+ if (isActiveText) {
2629
+ controller.enqueue({ type: "text-end", id: "text-0" });
2630
+ }
2631
+ if (isActiveReasoning) {
2632
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
2633
+ }
2634
+ controller.enqueue({
2635
+ type: "finish",
2636
+ finishReason,
2637
+ usage: usage ?? convertUsage({}),
2638
+ providerMetadata: {
2639
+ [providerOptionsName]: {
2640
+ requestId: capturedResponseHeaders?.["x-request-id"] ?? void 0,
2641
+ modelId: responseModel
2642
+ }
2643
+ }
2644
+ });
2645
+ break;
2646
+ case "error":
2647
+ controller.enqueue({
2648
+ type: "error",
2649
+ error: new Error(
2650
+ data.error?.message ?? "Unknown streaming error"
2651
+ )
2652
+ });
2653
+ break;
2654
+ }
2655
+ }
2656
+ })
2657
+ ),
2658
+ request: { body: streamBody },
2659
+ response: {
2660
+ headers: responseHeaders
2661
+ }
2662
+ };
2663
+ }
2664
+ };
2665
+
2666
+ // src/code/kimi-code-provider.ts
2667
+ var import_provider6 = require("@ai-sdk/provider");
2668
+ var import_provider_utils7 = require("@ai-sdk/provider-utils");
2669
+ function createKimiCode(options = {}) {
2670
+ const resolvedBaseURL = (0, import_provider_utils7.loadOptionalSetting)({
2671
+ settingValue: options.baseURL,
2672
+ environmentVariableName: "KIMI_CODE_BASE_URL"
2673
+ }) ?? KIMI_CODE_BASE_URL;
2674
+ const baseURL = (0, import_provider_utils7.withoutTrailingSlash)(resolvedBaseURL) ?? KIMI_CODE_BASE_URL;
2675
+ const getHeaders = () => {
2676
+ let apiKey = options.apiKey;
2677
+ if (!apiKey) {
2678
+ apiKey = process.env.KIMI_CODE_API_KEY ?? process.env.KIMI_API_KEY;
2679
+ }
2680
+ if (!apiKey) {
2681
+ throw new Error(
2682
+ "Kimi Code API key is required. Set the KIMI_CODE_API_KEY or KIMI_API_KEY environment variable, or pass the apiKey option."
2683
+ );
2684
+ }
2685
+ return (0, import_provider_utils7.withUserAgentSuffix)(
2686
+ {
2687
+ "x-api-key": apiKey,
2688
+ "anthropic-version": "2023-06-01",
2689
+ ...options.headers
2690
+ },
2691
+ `ai-sdk/kimi-code/${VERSION}`
2692
+ );
2693
+ };
2694
+ const createCodeModel = (modelId = KIMI_CODE_DEFAULT_MODEL, settings = {}) => new KimiCodeLanguageModel(modelId, settings, {
2695
+ provider: "kimi.code",
2696
+ baseURL,
2697
+ headers: getHeaders,
2698
+ fetch: options.fetch,
2699
+ generateId: options.generateId,
2700
+ includeUsageInStream: settings.includeUsageInStream ?? options.includeUsageInStream,
2701
+ supportedUrls: settings.supportedUrls ?? options.supportedUrls
2702
+ });
2703
+ const provider = (modelId = KIMI_CODE_DEFAULT_MODEL, settings) => {
2704
+ if (new.target) {
2705
+ throw new Error("The Kimi Code provider function cannot be called with new.");
2706
+ }
2707
+ return createCodeModel(modelId, settings);
2708
+ };
2709
+ provider.specificationVersion = "v3";
2710
+ provider.languageModel = createCodeModel;
2711
+ provider.chat = createCodeModel;
2712
+ provider.embeddingModel = (modelId) => {
2713
+ throw new import_provider6.NoSuchModelError({ modelId, modelType: "embeddingModel" });
2714
+ };
2715
+ provider.imageModel = (modelId) => {
2716
+ throw new import_provider6.NoSuchModelError({ modelId, modelType: "imageModel" });
2717
+ };
2718
+ provider.rerankingModel = (modelId) => {
2719
+ throw new import_provider6.NoSuchModelError({ modelId, modelType: "rerankingModel" });
2720
+ };
2721
+ return provider;
2722
+ }
2723
+ var kimiCode = createKimiCode();
2724
+ // Annotate the CommonJS export names for ESM import in node:
2725
+ 0 && (module.exports = {
2726
+ KIMI_CODE_BASE_URL,
2727
+ KIMI_CODE_DEFAULT_MODEL,
2728
+ KIMI_CODE_INTERPRETER_TOOL_NAME,
2729
+ KIMI_CODE_THINKING_MODEL,
2730
+ KIMI_WEB_SEARCH_TOOL_NAME,
2731
+ KimiAuthenticationError,
2732
+ KimiChatLanguageModel,
2733
+ KimiCodeLanguageModel,
2734
+ KimiContentFilterError,
2735
+ KimiContextLengthError,
2736
+ KimiError,
2737
+ KimiFileClient,
2738
+ KimiModelNotFoundError,
2739
+ KimiRateLimitError,
2740
+ KimiValidationError,
2741
+ SUPPORTED_FILE_EXTENSIONS,
2742
+ SUPPORTED_MIME_TYPES,
2743
+ createCodeInterpreterTool,
2744
+ createKimi,
2745
+ createKimiCode,
2746
+ createKimiWebSearchTool,
2747
+ createWebSearchTool,
2748
+ getMediaTypeFromExtension,
2749
+ getPurposeFromMediaType,
2750
+ inferKimiCodeCapabilities,
2751
+ inferModelCapabilities,
2752
+ isDocumentMediaType,
2753
+ isFileExtractMediaType,
2754
+ isImageMediaType,
2755
+ isVideoMediaType,
2756
+ kimi,
2757
+ kimiCachingConfigSchema,
2758
+ kimiCode,
2759
+ kimiCodeProviderOptionsSchema,
2760
+ kimiProviderOptionsSchema,
2761
+ kimiTools,
2762
+ processAttachments
2763
+ });
2764
+ //# sourceMappingURL=index.js.map