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/README.md ADDED
@@ -0,0 +1,871 @@
1
+ # kimi-vercel-ai-sdk-provider
2
+
3
+ Native Kimi (Moonshot AI) provider for Vercel AI SDK.
4
+
5
+ This is a native implementation with full support for Kimi-specific features, not a generic OpenAI-compatible wrapper.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/kimi-vercel-ai-sdk-provider
8
+ .svg?style=flat-square)](https://www.npmjs.com/package/kimi-vercel-ai-sdk-provider
9
+ )
10
+ [![npm bundle size](https://img.shields.io/bundlephobia/minzip/kimi-vercel-ai-sdk-provider
11
+ ?style=flat-square&label=bundle%20size)](https://bundlephobia.com/package/kimi-vercel-ai-sdk-provider
12
+ )
13
+ [![npm downloads](https://img.shields.io/npm/dm/kimi-vercel-ai-sdk-provider
14
+ .svg?style=flat-square)](https://www.npmjs.com/package/kimi-vercel-ai-sdk-provider
15
+ )
16
+ [![license](https://img.shields.io/npm/l/kimi-vercel-ai-sdk-provider
17
+ .svg?style=flat-square)](https://github.com/aaroniker/kimi-vercel-ai-sdk-provider/blob/main/LICENSE)
18
+
19
+ ## Table of Contents
20
+
21
+ - [Features](#features)
22
+ - [Install](#install)
23
+ - [Quick Start](#quick-start)
24
+ - [Kimi Code](#kimi-code)
25
+ - [Available Models](#available-models)
26
+ - [Extended Thinking](#extended-thinking)
27
+ - [Streaming with Thinking Blocks](#streaming-with-thinking-blocks)
28
+ - [Built-in Tools](#built-in-tools-kimi-chat)
29
+ - [Web Search](#web-search-web_search)
30
+ - [Code Interpreter](#code-interpreter-code)
31
+ - [Provider Tool Helpers](#provider-tool-helpers)
32
+ - [Native File & PDF Support](#native-file--pdf-support)
33
+ - [File Client](#file-client-simple)
34
+ - [Attachment Processing](#attachment-processing)
35
+ - [Supported File Types](#supported-file-types)
36
+ - [Tool Choice Polyfill](#tool-choice-polyfill)
37
+ - [Context Caching](#context-caching)
38
+ - [Token Tracking](#token-tracking)
39
+ - [Reasoning/Thinking Models](#reasoningthinking-models)
40
+ - [Video Input](#video-input-k25-models)
41
+ - [Model Capabilities](#model-capabilities)
42
+ - [Provider Options](#provider-options)
43
+ - [Available Models](#available-models-1)
44
+ - [Regional Endpoints](#regional-endpoints)
45
+ - [Environment Variables](#environment-variables)
46
+ - [Why Native vs OpenAI-Compatible?](#why-native-vs-openai-compatible)
47
+ - [API Reference](#api-reference)
48
+ - [License](#license)
49
+
50
+ ## Features
51
+
52
+ ### Kimi Chat (Standard API)
53
+ - Built-in web search (`$web_search`) for grounded responses
54
+ - Built-in code interpreter (`$code`) for programmatic reasoning
55
+ - Deep thinking/reasoning model streaming
56
+ - Video input support for K2.5 models
57
+ - 256k context window support
58
+ - Token tracking (cache hits, reasoning, web search, code interpreter)
59
+ - Regional endpoints (global and China)
60
+ - Provider tool helpers (`kimi.tools.*` and `kimiTools.*`)
61
+ - **Native File & PDF Support** - Automatic file upload and content extraction
62
+ - **Tool Choice Polyfill** - Simulates `required` and `tool` choices via system messages
63
+ - **Context Caching** - Reduce costs by up to 90% for repeated long prompts
64
+
65
+ ### Kimi Code (Premium Coding API)
66
+ - High-speed output (up to 100 tokens/s)
67
+ - Extended thinking/reasoning support with configurable effort levels
68
+ - 262k context window
69
+ - Streaming with thinking blocks
70
+
71
+ ## Install
72
+
73
+ ```bash
74
+ npm install kimi-vercel-ai-sdk-provider
75
+ ```
76
+
77
+ ## Quick Start
78
+
79
+ ### Kimi Chat (Standard)
80
+
81
+ ```ts
82
+ import { createKimi } from 'kimi-vercel-ai-sdk-provider
83
+ ';
84
+ import { generateText, streamText } from 'ai';
85
+
86
+ const kimi = createKimi({
87
+ // Uses MOONSHOT_API_KEY env var if not provided
88
+ endpoint: 'global',
89
+ });
90
+
91
+ // Basic usage
92
+ const result = await generateText({
93
+ model: kimi('kimi-k2.5'),
94
+ prompt: 'Explain quantum computing in one sentence.',
95
+ });
96
+
97
+ // Streaming with reasoning model
98
+ const stream = await streamText({
99
+ model: kimi('kimi-k2.5-thinking', { includeUsageInStream: true }),
100
+ prompt: 'Solve this step by step: What is 17 * 23?',
101
+ });
102
+ ```
103
+
104
+ ### Kimi Code (Premium)
105
+
106
+ ```ts
107
+ import { kimiCode, createKimiCode } from 'kimi-vercel-ai-sdk-provider
108
+ ';
109
+ import { generateText, streamText } from 'ai';
110
+
111
+ // Using default instance (uses KIMI_CODE_API_KEY or KIMI_API_KEY env var)
112
+ const result = await generateText({
113
+ model: kimiCode(), // Uses 'kimi-for-coding' by default
114
+ prompt: 'Write a TypeScript function to merge two sorted arrays',
115
+ });
116
+
117
+ // With extended thinking enabled
118
+ const stream = await streamText({
119
+ model: kimiCode('kimi-k2-thinking', {
120
+ extendedThinking: {
121
+ enabled: true,
122
+ effort: 'high' // 'low' | 'medium' | 'high'
123
+ }
124
+ }),
125
+ prompt: 'Design a distributed cache system',
126
+ });
127
+
128
+ // Or with custom configuration
129
+ const customKimiCode = createKimiCode({
130
+ apiKey: 'sk-kimi-xxx',
131
+ baseURL: 'https://api.kimi.com/coding/v1', // default
132
+ });
133
+ ```
134
+
135
+ ## Kimi Code
136
+
137
+ Kimi Code is a premium coding service optimized for development tasks with high-speed output and extended thinking support.
138
+
139
+ ### Available Models
140
+
141
+ | Model | Description |
142
+ |-------|-------------|
143
+ | `kimi-for-coding` | Primary coding model optimized for development tasks (default) |
144
+ | `kimi-k2-thinking` | Extended thinking model for complex reasoning |
145
+
146
+ ### Extended Thinking
147
+
148
+ Enable extended thinking to see the model's reasoning process:
149
+
150
+ ```ts
151
+ // Simple boolean
152
+ const model = kimiCode('kimi-for-coding', { extendedThinking: true });
153
+
154
+ // With effort level
155
+ const model = kimiCode('kimi-for-coding', {
156
+ extendedThinking: {
157
+ enabled: true,
158
+ effort: 'high' // 'low' (~2k tokens), 'medium' (~8k tokens), 'high' (~16k tokens)
159
+ }
160
+ });
161
+
162
+ // With explicit budget
163
+ const model = kimiCode('kimi-for-coding', {
164
+ extendedThinking: {
165
+ enabled: true,
166
+ budgetTokens: 10000
167
+ }
168
+ });
169
+ ```
170
+
171
+ ### Provider Options
172
+
173
+ Pass options via `providerOptions.kimiCode`:
174
+
175
+ ```ts
176
+ const result = await generateText({
177
+ model: kimiCode('kimi-for-coding'),
178
+ prompt: 'Write a REST API',
179
+ providerOptions: {
180
+ kimiCode: {
181
+ extendedThinking: { enabled: true, effort: 'medium' },
182
+ system: 'You are an expert TypeScript developer',
183
+ stopSequences: ['```']
184
+ }
185
+ }
186
+ });
187
+ ```
188
+
189
+ ### Streaming with Thinking Blocks
190
+
191
+ ```ts
192
+ const stream = await streamText({
193
+ model: kimiCode('kimi-k2-thinking'),
194
+ prompt: 'Design a microservices architecture',
195
+ });
196
+
197
+ for await (const part of stream.fullStream) {
198
+ switch (part.type) {
199
+ case 'reasoning-start':
200
+ console.log('--- Thinking ---');
201
+ break;
202
+ case 'reasoning-delta':
203
+ process.stdout.write(part.delta);
204
+ break;
205
+ case 'reasoning-end':
206
+ console.log('\n--- Answer ---');
207
+ break;
208
+ case 'text-delta':
209
+ process.stdout.write(part.delta);
210
+ break;
211
+ }
212
+ }
213
+ ```
214
+
215
+ ## Built-in Tools (Kimi Chat)
216
+
217
+ Kimi provides server-side tools that can be enabled in three ways:
218
+
219
+ 1. Model settings: `kimi('model', { webSearch: true })`
220
+ 2. Provider options: `providerOptions.kimi.webSearch = true`
221
+ 3. Provider tool helpers: `kimi.tools.webSearch()` or `kimiTools.webSearch()`
222
+
223
+ ### Web Search (`$web_search`)
224
+
225
+ ```ts
226
+ // Enable via model settings
227
+ const model = kimi('kimi-k2.5', { webSearch: true });
228
+
229
+ const result = await generateText({
230
+ model,
231
+ prompt: 'What are the latest AI news today?',
232
+ });
233
+
234
+ // Enable per request via provider options
235
+ const result = await generateText({
236
+ model: kimi('kimi-k2.5'),
237
+ prompt: 'What is the current Bitcoin price?',
238
+ providerOptions: {
239
+ kimi: {
240
+ webSearch: true,
241
+ },
242
+ },
243
+ });
244
+
245
+ // Advanced: Configure search behavior
246
+ const result = await generateText({
247
+ model: kimi('kimi-k2.5'),
248
+ prompt: 'Latest research on transformer architectures',
249
+ providerOptions: {
250
+ kimi: {
251
+ webSearch: {
252
+ enabled: true,
253
+ config: {
254
+ search_result: true,
255
+ },
256
+ },
257
+ },
258
+ },
259
+ });
260
+ ```
261
+
262
+ ### Code Interpreter (`$code`)
263
+
264
+ ```ts
265
+ // Enable via model settings
266
+ const model = kimi('kimi-k2.5', { codeInterpreter: true });
267
+
268
+ const result = await generateText({
269
+ model,
270
+ prompt: 'Calculate the factorial of 20 and show your work.',
271
+ });
272
+
273
+ // Enable per request via provider options
274
+ const result = await generateText({
275
+ model: kimi('kimi-k2.5'),
276
+ prompt: 'Simulate 1000 coin flips and report the distribution.',
277
+ providerOptions: {
278
+ kimi: {
279
+ codeInterpreter: true,
280
+ },
281
+ },
282
+ });
283
+
284
+ // Advanced: Configure code execution
285
+ const result = await generateText({
286
+ model: kimi('kimi-k2.5'),
287
+ prompt: 'Generate a CSV of prime numbers under 1000.',
288
+ providerOptions: {
289
+ kimi: {
290
+ codeInterpreter: {
291
+ enabled: true,
292
+ config: {
293
+ timeout: 30,
294
+ include_output: true,
295
+ },
296
+ },
297
+ },
298
+ },
299
+ });
300
+ ```
301
+
302
+ ### Provider Tool Helpers
303
+
304
+ ```ts
305
+ import { kimi, kimiTools } from 'kimi-vercel-ai-sdk-provider
306
+ ';
307
+
308
+ const result = await generateText({
309
+ model: kimi('kimi-k2.5'),
310
+ tools: {
311
+ webSearch: kimi.tools.webSearch(),
312
+ codeInterpreter: kimi.tools.codeInterpreter(),
313
+ },
314
+ prompt: 'Summarize today\'s headlines and compute sentiment stats.',
315
+ });
316
+
317
+ // Or use the named helper
318
+ const result = await generateText({
319
+ model: kimi('kimi-k2.5'),
320
+ tools: {
321
+ webSearch: kimiTools.webSearch(),
322
+ },
323
+ prompt: 'What is the weather in Tokyo?',
324
+ });
325
+ ```
326
+
327
+ ## Native File & PDF Support
328
+
329
+ Kimi excels at reading long documents. This provider includes a file handling module for automatic file upload and content extraction.
330
+
331
+ ### File Client (Simple)
332
+
333
+ The provider includes a pre-configured file client:
334
+
335
+ ```ts
336
+ import { createKimi } from 'kimi-vercel-ai-sdk-provider
337
+ ';
338
+
339
+ const kimi = createKimi();
340
+
341
+ // Upload and extract content from a PDF - no config needed!
342
+ const result = await kimi.files.uploadAndExtract({
343
+ data: pdfBuffer,
344
+ filename: 'document.pdf',
345
+ });
346
+
347
+ console.log(result.content); // Extracted text content
348
+ console.log(result.file.id); // File ID for reference
349
+
350
+ // List all uploaded files
351
+ const files = await kimi.files.listFiles();
352
+
353
+ // Delete a file
354
+ await kimi.files.deleteFile(fileId);
355
+ ```
356
+
357
+ ### File Client (Manual Configuration)
358
+
359
+ If you need custom configuration:
360
+
361
+ ```ts
362
+ import { KimiFileClient } from 'kimi-vercel-ai-sdk-provider
363
+ ';
364
+
365
+ const client = new KimiFileClient({
366
+ baseURL: 'https://api.moonshot.ai/v1',
367
+ headers: () => ({
368
+ Authorization: `Bearer ${process.env.MOONSHOT_API_KEY}`,
369
+ }),
370
+ });
371
+
372
+ const result = await client.uploadAndExtract({
373
+ data: pdfBuffer,
374
+ filename: 'document.pdf',
375
+ mediaType: 'application/pdf',
376
+ });
377
+ ```
378
+
379
+ ### Attachment Processing
380
+
381
+ Process experimental_attachments automatically:
382
+
383
+ ```ts
384
+ import { processAttachments } from 'kimi-vercel-ai-sdk-provider
385
+ ';
386
+
387
+ const processed = await processAttachments({
388
+ attachments: message.experimental_attachments ?? [],
389
+ clientConfig: {
390
+ baseURL: 'https://api.moonshot.ai/v1',
391
+ headers: () => ({ Authorization: `Bearer ${process.env.MOONSHOT_API_KEY}` }),
392
+ },
393
+ autoUploadDocuments: true,
394
+ cleanupAfterExtract: true, // Delete files after extraction
395
+ });
396
+
397
+ // Inject document content into messages
398
+ const documentContent = processed
399
+ .filter(p => p.type === 'text-inject' && p.textContent)
400
+ .map(p => p.textContent)
401
+ .join('\n');
402
+ ```
403
+
404
+ ### Supported File Types
405
+
406
+ Documents (extracted as text): PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, MD, HTML, JSON, EPUB, CSV, and code files.
407
+
408
+ Images (for vision): JPEG, PNG, GIF, WebP, SVG, BMP, TIFF, AVIF.
409
+
410
+ Videos (K2.5 models): MP4, WebM, OGG.
411
+
412
+ ## Tool Choice Polyfill
413
+
414
+ Kimi doesn't natively support `tool_choice: 'required'` or forcing a specific tool. This provider includes a polyfill that uses system message injection to simulate these behaviors.
415
+
416
+ ### Automatic Polyfill (Default)
417
+
418
+ ```ts
419
+ const result = await generateText({
420
+ model: kimi('kimi-k2.5'),
421
+ tools: { searchWeb: webSearchTool },
422
+ toolChoice: { type: 'required' }, // Polyfilled automatically
423
+ prompt: 'Find the weather in Tokyo',
424
+ });
425
+ ```
426
+
427
+ The provider will inject a system message like:
428
+ > "IMPORTANT INSTRUCTION: You MUST use one of the available tools to respond..."
429
+
430
+ ### Disable Polyfill
431
+
432
+ ```ts
433
+ // Disable via model settings
434
+ const model = kimi('kimi-k2.5', { toolChoicePolyfill: false });
435
+
436
+ // Or per-request via provider options
437
+ const result = await generateText({
438
+ model: kimi('kimi-k2.5'),
439
+ tools: { searchWeb: webSearchTool },
440
+ toolChoice: { type: 'required' },
441
+ providerOptions: {
442
+ kimi: { toolChoicePolyfill: false }
443
+ },
444
+ prompt: 'Find the weather',
445
+ });
446
+ ```
447
+
448
+ ## Context Caching
449
+
450
+ Reduce costs by up to 90% for repeated long prompts (like analyzing documents or maintaining long conversations).
451
+
452
+ ### Enable Caching
453
+
454
+ ```ts
455
+ // Simple boolean
456
+ const result = await generateText({
457
+ model: kimi('kimi-k2.5', { caching: true }),
458
+ prompt: 'Analyze this long document...',
459
+ });
460
+
461
+ // With configuration
462
+ const result = await generateText({
463
+ model: kimi('kimi-k2.5', {
464
+ caching: {
465
+ enabled: true,
466
+ cacheKey: 'book-analysis-v1', // Consistent key for cache hits
467
+ ttlSeconds: 7200, // 2 hours TTL
468
+ }
469
+ }),
470
+ prompt: 'What are the main themes?',
471
+ });
472
+ ```
473
+
474
+ ### Per-Request Caching
475
+
476
+ ```ts
477
+ const result = await generateText({
478
+ model: kimi('kimi-k2.5'),
479
+ prompt: 'Continue analysis...',
480
+ providerOptions: {
481
+ kimi: {
482
+ caching: {
483
+ enabled: true,
484
+ cacheKey: 'book-analysis-v1',
485
+ }
486
+ }
487
+ },
488
+ });
489
+ ```
490
+
491
+ ### Reset Cache
492
+
493
+ ```ts
494
+ const result = await generateText({
495
+ model: kimi('kimi-k2.5'),
496
+ prompt: 'Re-analyze with new context...',
497
+ providerOptions: {
498
+ kimi: {
499
+ caching: {
500
+ enabled: true,
501
+ cacheKey: 'book-analysis-v1',
502
+ resetCache: true, // Force cache refresh
503
+ }
504
+ }
505
+ },
506
+ });
507
+ ```
508
+
509
+ ## Token Tracking
510
+
511
+ Token usage includes built-in tool usage when present:
512
+
513
+ ```ts
514
+ const result = await generateText({
515
+ model: kimi('kimi-k2.5', { webSearch: true, codeInterpreter: true }),
516
+ prompt: 'Find today\'s EUR/USD rate and compute a 5% increase.',
517
+ });
518
+
519
+ console.log(result.usage);
520
+ // {
521
+ // inputTokens: { total: 150, cacheRead: 50, ... },
522
+ // outputTokens: { total: 200, reasoning: 0, ... },
523
+ // webSearchTokens: 1500,
524
+ // codeInterpreterTokens: 320,
525
+ // }
526
+ ```
527
+
528
+ ## Reasoning/Thinking Models
529
+
530
+ Kimi's thinking models provide step-by-step reasoning:
531
+
532
+ ```ts
533
+ const stream = await streamText({
534
+ model: kimi('kimi-k2.5-thinking'),
535
+ prompt: 'Prove that sqrt(2) is irrational.',
536
+ });
537
+
538
+ for await (const part of stream.fullStream) {
539
+ switch (part.type) {
540
+ case 'reasoning-start':
541
+ console.log('--- Reasoning ---');
542
+ break;
543
+ case 'reasoning-delta':
544
+ process.stdout.write(part.delta);
545
+ break;
546
+ case 'reasoning-end':
547
+ console.log('\n--- Answer ---');
548
+ break;
549
+ case 'text-delta':
550
+ process.stdout.write(part.delta);
551
+ break;
552
+ }
553
+ }
554
+ ```
555
+
556
+ ## Video Input (K2.5 models)
557
+
558
+ K2.5 models support video URLs:
559
+
560
+ ```ts
561
+ const result = await generateText({
562
+ model: kimi('kimi-k2.5'),
563
+ messages: [
564
+ {
565
+ role: 'user',
566
+ content: [
567
+ { type: 'text', text: 'What is happening in this video?' },
568
+ {
569
+ type: 'file',
570
+ mediaType: 'video/mp4',
571
+ data: new URL('https://example.com/video.mp4'),
572
+ },
573
+ ],
574
+ },
575
+ ],
576
+ });
577
+ ```
578
+
579
+ ## Model Capabilities
580
+
581
+ The provider automatically infers capabilities from model IDs:
582
+
583
+ ```ts
584
+ import { inferModelCapabilities, inferKimiCodeCapabilities } from 'kimi-vercel-ai-sdk-provider
585
+ ';
586
+
587
+ // Kimi Chat models
588
+ const caps = inferModelCapabilities('kimi-k2.5-thinking');
589
+ // {
590
+ // thinking: true,
591
+ // alwaysThinking: true,
592
+ // imageInput: true,
593
+ // videoInput: true,
594
+ // maxContextSize: 256000,
595
+ // toolCalling: true,
596
+ // jsonMode: true,
597
+ // structuredOutputs: true,
598
+ // }
599
+
600
+ // Kimi Code models
601
+ const codeCaps = inferKimiCodeCapabilities('kimi-k2-thinking');
602
+ // {
603
+ // extendedThinking: true,
604
+ // maxOutputTokens: 32768,
605
+ // maxContextSize: 262144,
606
+ // streaming: true,
607
+ // toolCalling: true,
608
+ // imageInput: true,
609
+ // }
610
+ ```
611
+
612
+ ## Provider Options
613
+
614
+ ### Kimi Chat Options
615
+
616
+ Pass Kimi-specific options via `providerOptions.kimi`:
617
+
618
+ ```ts
619
+ const result = await generateText({
620
+ model: kimi('kimi-k2.5'),
621
+ prompt: 'Return JSON with name and version.',
622
+ responseFormat: { type: 'json' },
623
+ providerOptions: {
624
+ kimi: {
625
+ user: 'user-123',
626
+ requestId: 'trace-abc',
627
+ strictJsonSchema: true,
628
+ extraHeaders: { 'X-Custom': 'value' },
629
+ parallelToolCalls: true,
630
+ webSearch: true,
631
+ codeInterpreter: true,
632
+ },
633
+ },
634
+ });
635
+ ```
636
+
637
+ ### Kimi Code Options
638
+
639
+ Pass options via `providerOptions.kimiCode`:
640
+
641
+ ```ts
642
+ const result = await generateText({
643
+ model: kimiCode('kimi-for-coding'),
644
+ prompt: 'Write clean code',
645
+ providerOptions: {
646
+ kimiCode: {
647
+ extendedThinking: { enabled: true, effort: 'medium' },
648
+ system: 'Follow best practices',
649
+ stopSequences: ['---'],
650
+ },
651
+ },
652
+ });
653
+ ```
654
+
655
+ ## Available Models
656
+
657
+ ### Kimi Chat
658
+
659
+ | Model | Features |
660
+ |-------|----------|
661
+ | `kimi-k2.5` | Latest, image/video input, built-in tools |
662
+ | `kimi-k2.5-thinking` | K2.5 + always-on deep reasoning |
663
+ | `kimi-k2-turbo` | Fast, cost-effective |
664
+ | `kimi-k2-thinking` | K2 + always-on deep reasoning |
665
+
666
+ ### Kimi Code
667
+
668
+ | Model | Features |
669
+ |-------|----------|
670
+ | `kimi-for-coding` | Primary coding model (default) |
671
+ | `kimi-k2-thinking` | Extended thinking for complex tasks |
672
+
673
+ ## Regional Endpoints
674
+
675
+ ### Kimi Chat
676
+
677
+ ```ts
678
+ // Global (default) - api.moonshot.ai
679
+ const kimiGlobal = createKimi({ endpoint: 'global' });
680
+
681
+ // China - api.moonshot.cn (lower latency in mainland China)
682
+ const kimiChina = createKimi({ endpoint: 'cn' });
683
+
684
+ // Custom endpoint
685
+ const kimiCustom = createKimi({
686
+ baseURL: 'https://your-proxy.example.com/v1',
687
+ });
688
+ ```
689
+
690
+ ### Kimi Code
691
+
692
+ ```ts
693
+ // Default - api.kimi.com/coding/v1
694
+ const codeProvider = createKimiCode();
695
+
696
+ // Custom endpoint
697
+ const customCodeProvider = createKimiCode({
698
+ baseURL: 'https://your-proxy.example.com/v1',
699
+ });
700
+ ```
701
+
702
+ ## Environment Variables
703
+
704
+ Copy `.env.example` to `.env` and configure your API keys:
705
+
706
+ ```bash
707
+ cp .env.example .env
708
+ ```
709
+
710
+ ### Kimi Chat
711
+ | Variable | Description |
712
+ |----------|-------------|
713
+ | `MOONSHOT_API_KEY` | Your Moonshot AI API key (required) |
714
+ | `MOONSHOT_BASE_URL` | Override the base URL (optional) |
715
+
716
+ ### Kimi Code
717
+ | Variable | Description |
718
+ |----------|-------------|
719
+ | `KIMI_CODE_API_KEY` | Your Kimi Code API key (preferred) |
720
+ | `KIMI_API_KEY` | Fallback API key if `KIMI_CODE_API_KEY` not set |
721
+ | `KIMI_CODE_BASE_URL` | Override the base URL (optional) |
722
+
723
+ Get your API keys at: https://platform.moonshot.cn/console/api-keys
724
+
725
+ ## Why Native vs OpenAI-Compatible?
726
+
727
+ This provider is built natively for Kimi rather than using `@ai-sdk/openai-compatible`. Benefits:
728
+
729
+ | Feature | Native Provider | OpenAI-Compatible |
730
+ |---------|-----------------|-------------------|
731
+ | `$web_search` built-in tool | Full support | Not available |
732
+ | `$code` code interpreter | Full support | Not available |
733
+ | Built-in tool token tracking | Included | Not available |
734
+ | Video input support | Automatic | Manual config |
735
+ | Reasoning content streaming | Native handling | May need config |
736
+ | Model capability inference | Automatic | Manual |
737
+ | Type-safe provider options | Full types | Partial |
738
+ | Error messages | Kimi-specific | Generic |
739
+ | Kimi Code extended thinking | Full support | Not available |
740
+
741
+ ## API Reference
742
+
743
+ ### Exports
744
+
745
+ ```ts
746
+ // Kimi Chat Provider
747
+ import {
748
+ createKimi,
749
+ kimi,
750
+ KimiChatLanguageModel,
751
+ inferModelCapabilities,
752
+ kimiProviderOptionsSchema,
753
+ kimiCachingConfigSchema,
754
+ kimiTools,
755
+ // Types
756
+ KimiProvider,
757
+ KimiProviderSettings,
758
+ KimiChatSettings,
759
+ KimiChatModelId,
760
+ KimiProviderOptions,
761
+ KimiModelCapabilities,
762
+ KimiCachingConfig,
763
+ } from 'kimi-vercel-ai-sdk-provider
764
+ ';
765
+
766
+ // Kimi Code Provider
767
+ import {
768
+ createKimiCode,
769
+ kimiCode,
770
+ KimiCodeLanguageModel,
771
+ inferKimiCodeCapabilities,
772
+ kimiCodeProviderOptionsSchema,
773
+ toAnthropicThinking,
774
+ // Constants
775
+ KIMI_CODE_BASE_URL,
776
+ KIMI_CODE_OPENAI_BASE_URL,
777
+ KIMI_CODE_DEFAULT_MODEL,
778
+ KIMI_CODE_THINKING_MODEL,
779
+ KIMI_CODE_MODELS,
780
+ KIMI_CODE_DEFAULT_MAX_TOKENS,
781
+ KIMI_CODE_DEFAULT_CONTEXT_WINDOW,
782
+ KIMI_CODE_ANTHROPIC_VERSION,
783
+ // Types
784
+ KimiCodeProvider,
785
+ KimiCodeProviderSettings,
786
+ KimiCodeSettings,
787
+ KimiCodeModelId,
788
+ KimiCodeCapabilities,
789
+ ExtendedThinkingConfig,
790
+ ReasoningEffort,
791
+ } from 'kimi-vercel-ai-sdk-provider';
792
+
793
+ // File Handling
794
+ import {
795
+ KimiFileClient,
796
+ processAttachments,
797
+ SUPPORTED_FILE_EXTENSIONS,
798
+ SUPPORTED_MIME_TYPES,
799
+ isImageMediaType,
800
+ isVideoMediaType,
801
+ isDocumentMediaType,
802
+ isFileExtractMediaType,
803
+ getMediaTypeFromExtension,
804
+ getPurposeFromMediaType,
805
+ // Types
806
+ KimiFile,
807
+ KimiFileClientConfig,
808
+ FileUploadOptions,
809
+ FileUploadResult,
810
+ Attachment,
811
+ ProcessedAttachment,
812
+ } from 'kimi-vercel-ai-sdk-provider
813
+ ';
814
+
815
+ // Built-in Tools
816
+ import {
817
+ createWebSearchTool,
818
+ createKimiWebSearchTool,
819
+ createCodeInterpreterTool,
820
+ KIMI_WEB_SEARCH_TOOL_NAME,
821
+ KIMI_CODE_INTERPRETER_TOOL_NAME,
822
+ } from 'kimi-vercel-ai-sdk-provider
823
+ ';
824
+
825
+ // Errors
826
+ import {
827
+ KimiError,
828
+ KimiAuthenticationError,
829
+ KimiRateLimitError,
830
+ KimiValidationError,
831
+ KimiContextLengthError,
832
+ KimiContentFilterError,
833
+ KimiModelNotFoundError,
834
+ } from 'kimi-vercel-ai-sdk-provider
835
+ ';
836
+ ```
837
+
838
+ ### Feature Comparison
839
+
840
+ | Feature | Generic OpenAI Provider | Kimi Provider |
841
+ |---------|------------------------|---------------|
842
+ | Setup | Manual baseURL & Headers | Plug-and-play |
843
+ | PDF/Doc Analysis | Not supported (only Vision) | Auto-upload & Extract |
844
+ | Thinking Models | Mixed text / Unparsed | Mapped to SDK reasoning |
845
+ | Tool Reliability | Crashes on `tool_choice: required` | Auto-fixed / Polyfilled |
846
+ | Long Context | Full price | Cached (up to 90% cheaper) |
847
+ | Web Search | Manual tool definition | `webSearch: true` toggle |
848
+ | Code Interpreter | Not available | `codeInterpreter: true` toggle |
849
+ | Type Safety | Raw strings | TypeScript enums for models |
850
+
851
+ ## License
852
+
853
+ Apache-2.0
854
+
855
+ ## Authors
856
+
857
+ <p><strong>Aaron Iker</strong></p>
858
+ <p valign="center">
859
+ <a href="https://x.com/aaroniker">
860
+ <img valign="top" src="https://img.shields.io/badge/X-@aaroniker-black?style=flat-square&logo=x" alt="X">
861
+ </a>
862
+ <span valign="center">&nbsp; • &nbsp;</span>
863
+ <a href="https://github.com/aaroniker">
864
+ <img valign="top" src="https://img.shields.io/badge/GitHub-aaroniker-black?style=flat-square&logo=github" alt="GitHub">
865
+ </a>
866
+ <span valign="center">&nbsp; • &nbsp;</span>
867
+ <a href="https://www.linkedin.com/in/aaron-iker-15606897/">
868
+ <img valign="top" src="https://img.shields.io/badge/LinkedIn-aaroniker-blue?style=flat-square&logo=linkedin" alt="LinkedIn">
869
+ </a>
870
+ </p>
871
+