Skip to content

Commit cea1c89

Browse files
authored
feat(providers): add Kimi (Moonshot AI) provider (#5716)
* feat(providers): add Kimi (Moonshot AI) provider * fix(providers): preserve reasoning_content in kimi tool loop
1 parent 2f9144e commit cea1c89

16 files changed

Lines changed: 845 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/settings/components/byok/byok.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
HunterIOIcon,
2121
IcypeasIcon,
2222
JinaAIIcon,
23+
KimiIcon,
2324
LeadMagicIcon,
2425
LinkupIcon,
2526
MillionVerifierIcon,
@@ -86,6 +87,13 @@ const PROVIDERS: (BYOKManagerProvider & { id: BYOKProviderId })[] = [
8687
description: 'LLM calls',
8788
placeholder: 'xai-...',
8889
},
90+
{
91+
id: 'kimi',
92+
name: 'Kimi',
93+
icon: KimiIcon,
94+
description: 'LLM calls',
95+
placeholder: 'sk-...',
96+
},
8997
{
9098
id: 'fireworks',
9199
name: 'Fireworks',
@@ -298,6 +306,7 @@ const PROVIDER_SECTIONS: BYOKProviderSection[] = [
298306
'google',
299307
'mistral',
300308
'xai',
309+
'kimi',
301310
'fireworks',
302311
'together',
303312
'baseten',

apps/sim/components/icons.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3823,6 +3823,20 @@ export const ZaiIcon = (props: SVGProps<SVGSVGElement>) => (
38233823
</svg>
38243824
)
38253825

3826+
export const KimiIcon = (props: SVGProps<SVGSVGElement>) => (
3827+
<svg {...props} height='1em' viewBox='0 0 24 24' width='1em' xmlns='http://www.w3.org/2000/svg'>
3828+
<title>Kimi</title>
3829+
<path
3830+
d='M21.846 0a1.923 1.923 0 110 3.846H20.15a.226.226 0 01-.227-.226V1.923C19.923.861 20.784 0 21.846 0z'
3831+
fill='#1783FF'
3832+
/>
3833+
<path
3834+
d='M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 00-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 01.205-.023l6.484 4.772a7.677 7.677 0 003.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 01-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z'
3835+
fill='currentColor'
3836+
/>
3837+
</svg>
3838+
)
3839+
38263840
export function MetaIcon(props: SVGProps<SVGSVGElement>) {
38273841
const id = useId()
38283842
const gradient1Id = `meta_gradient_1_${id}`

apps/sim/lib/api-key/byok.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,20 @@ export async function getApiKeyWithBYOK(
206206
const isMistralModel = provider === 'mistral'
207207
const isZaiModel = provider === 'zai'
208208
const isXaiModel = provider === 'xai'
209+
const isKimiModel = provider === 'kimi'
209210

210211
const byokProviderId = isGeminiModel ? 'google' : (provider as BYOKProviderId)
211212

212213
if (
213214
isHosted &&
214215
workspaceId &&
215-
(isOpenAIModel || isClaudeModel || isGeminiModel || isMistralModel || isZaiModel || isXaiModel)
216+
(isOpenAIModel ||
217+
isClaudeModel ||
218+
isGeminiModel ||
219+
isMistralModel ||
220+
isZaiModel ||
221+
isXaiModel ||
222+
isKimiModel)
216223
) {
217224
const hostedModels = getHostedModels()
218225
const isModelHosted = hostedModels.some((m) => m.toLowerCase() === model.toLowerCase())

apps/sim/lib/api/contracts/byok-keys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const byokProviderIdSchema = z.enum([
77
'google',
88
'mistral',
99
'zai',
10+
'kimi',
1011
'xai',
1112
'fireworks',
1213
'together',

apps/sim/lib/core/config/api-keys.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export function getRotatingApiKey(provider: string): string {
1313
provider !== 'gemini' &&
1414
provider !== 'cohere' &&
1515
provider !== 'zai' &&
16-
provider !== 'xai'
16+
provider !== 'xai' &&
17+
provider !== 'kimi'
1718
) {
1819
throw new Error(`No rotation implemented for provider: ${provider}`)
1920
}
@@ -44,6 +45,10 @@ export function getRotatingApiKey(provider: string): string {
4445
if (env.XAI_API_KEY_1) keys.push(env.XAI_API_KEY_1)
4546
if (env.XAI_API_KEY_2) keys.push(env.XAI_API_KEY_2)
4647
if (env.XAI_API_KEY_3) keys.push(env.XAI_API_KEY_3)
48+
} else if (provider === 'kimi') {
49+
if (env.KIMI_API_KEY_1) keys.push(env.KIMI_API_KEY_1)
50+
if (env.KIMI_API_KEY_2) keys.push(env.KIMI_API_KEY_2)
51+
if (env.KIMI_API_KEY_3) keys.push(env.KIMI_API_KEY_3)
4752
}
4853

4954
if (keys.length === 0) {

apps/sim/lib/core/config/env.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ export const env = createEnv({
154154
ZAI_API_KEY_1: z.string().min(1).optional(), // Primary Z.ai API key for load balancing
155155
ZAI_API_KEY_2: z.string().min(1).optional(), // Additional Z.ai API key for load balancing
156156
ZAI_API_KEY_3: z.string().min(1).optional(), // Additional Z.ai API key for load balancing
157+
KIMI_API_KEY_1: z.string().min(1).optional(), // Primary Kimi (Moonshot AI) API key for load balancing
158+
KIMI_API_KEY_2: z.string().min(1).optional(), // Additional Kimi API key for load balancing
159+
KIMI_API_KEY_3: z.string().min(1).optional(), // Additional Kimi API key for load balancing
157160
XAI_API_KEY_1: z.string().min(1).optional(), // Primary xAI API key for load balancing
158161
XAI_API_KEY_2: z.string().min(1).optional(), // Additional xAI API key for load balancing
159162
XAI_API_KEY_3: z.string().min(1).optional(), // Additional xAI API key for load balancing

apps/sim/lib/tokenization/constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ export const TOKENIZATION_CONFIG = {
7676
confidence: 'medium',
7777
supportedMethods: ['heuristic', 'fallback'],
7878
},
79+
kimi: {
80+
avgCharsPerToken: 4,
81+
confidence: 'medium',
82+
supportedMethods: ['heuristic', 'fallback'],
83+
},
7984
ollama: {
8085
avgCharsPerToken: 4,
8186
confidence: 'low',

apps/sim/providers/attachments.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type AttachmentProvider =
3939
| 'nvidia'
4040
| 'meta'
4141
| 'zai'
42+
| 'kimi'
4243

4344
export interface PreparedProviderAttachment {
4445
file: UserFile
@@ -152,6 +153,7 @@ const PROVIDER_SUPPORTED_LABELS: Record<AttachmentProvider, string> = {
152153
nvidia: 'no file attachments in the current API adapter',
153154
meta: 'no file attachments in the current API adapter',
154155
zai: 'no file attachments in the current API adapter',
156+
kimi: 'images through image_url message parts on multimodal models',
155157
}
156158

157159
export function getAttachmentProvider(providerId: ProviderId | string): AttachmentProvider | null {
@@ -175,6 +177,7 @@ export function getAttachmentProvider(providerId: ProviderId | string): Attachme
175177
if (providerId === 'nvidia') return 'nvidia'
176178
if (providerId === 'meta') return 'meta'
177179
if (providerId === 'zai') return 'zai'
180+
if (providerId === 'kimi') return 'kimi'
178181
return null
179182
}
180183

@@ -319,6 +322,7 @@ function isMimeTypeSupportedByProvider(
319322
case 'vllm':
320323
case 'litellm':
321324
case 'xai':
325+
case 'kimi':
322326
return isImageMimeType(mimeType)
323327
case 'deepseek':
324328
case 'cerebras':

0 commit comments

Comments
 (0)