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