-
Notifications
You must be signed in to change notification settings - Fork 3k
feat(auth): add Kimi (Moonshot AI) as a built-in third-party provider #9756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a39605e
7c7f4fc
c3e21ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2026 Qwen Team | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { describe, expect, it } from 'vitest'; | ||
| import { AuthType } from '../../../core/contentGenerator.js'; | ||
| import { moonshotProvider } from '../../presets/moonshot.js'; | ||
| import { | ||
| ALL_PROVIDERS, | ||
| THIRD_PARTY_PROVIDERS, | ||
| findProviderByCredentials, | ||
| findProviderById, | ||
| getAllProviderBaseUrls, | ||
| } from '../../all-providers.js'; | ||
| import { buildInstallPlan } from '../../provider-config.js'; | ||
|
|
||
| const INTL_BASE_URL = 'https://api.moonshot.ai/v1'; | ||
| const CHINA_BASE_URL = 'https://api.moonshot.cn/v1'; | ||
|
|
||
| describe('moonshotProvider', () => { | ||
| it('has correct provider config', () => { | ||
| expect(moonshotProvider).toMatchObject({ | ||
| id: 'moonshot', | ||
| label: 'Kimi (Moonshot AI) API Key', | ||
| protocol: AuthType.USE_OPENAI, | ||
| envKey: 'MOONSHOT_API_KEY', | ||
| modelNamePrefix: 'Kimi', | ||
| modelsEditable: true, | ||
| uiGroup: 'third-party', | ||
| }); | ||
| }); | ||
|
|
||
| it('offers international and China endpoints', () => { | ||
| expect(Array.isArray(moonshotProvider.baseUrl)).toBe(true); | ||
| const urls = (moonshotProvider.baseUrl as Array<{ url: string }>).map( | ||
| (o) => o.url, | ||
| ); | ||
| expect(urls).toEqual([INTL_BASE_URL, CHINA_BASE_URL]); | ||
| }); | ||
|
|
||
| it('is registered and discoverable in the provider registry', () => { | ||
| expect(findProviderById('moonshot')).toBe(moonshotProvider); | ||
| expect(ALL_PROVIDERS).toContain(moonshotProvider); | ||
| expect(THIRD_PARTY_PROVIDERS).toContain(moonshotProvider); | ||
| expect(getAllProviderBaseUrls()).toContain(INTL_BASE_URL); | ||
| expect(getAllProviderBaseUrls()).toContain(CHINA_BASE_URL); | ||
| }); | ||
|
|
||
| it('is found by its env key + base URL credentials', () => { | ||
| expect( | ||
| findProviderByCredentials(INTL_BASE_URL, 'MOONSHOT_API_KEY')?.id, | ||
| ).toBe('moonshot'); | ||
| expect( | ||
| findProviderByCredentials(CHINA_BASE_URL, 'MOONSHOT_API_KEY')?.id, | ||
| ).toBe('moonshot'); | ||
| // Wrong base URL for the right key must not match. | ||
| expect( | ||
| findProviderByCredentials( | ||
| 'https://wrong.example.com/v1', | ||
| 'MOONSHOT_API_KEY', | ||
| ), | ||
| ).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('creates an install plan with per-model metadata for known IDs', () => { | ||
| const plan = buildInstallPlan(moonshotProvider, { | ||
| baseUrl: INTL_BASE_URL, | ||
| apiKey: 'sk-moonshot', | ||
| modelIds: [ | ||
| 'kimi-k3', | ||
| 'kimi-k2.7-code', | ||
| 'kimi-k2.7-code-highspeed', | ||
| 'kimi-k2.6', | ||
| ], | ||
| }); | ||
|
|
||
| const models = plan.modelProviders?.[0]?.models; | ||
| expect(models).toHaveLength(4); | ||
|
|
||
| // K3 always thinks: mandatory, never a plain enable_thinking toggle. | ||
| expect(models?.[0]).toMatchObject({ | ||
| id: 'kimi-k3', | ||
| name: '[Kimi] kimi-k3', | ||
| generationConfig: { | ||
| contextWindowSize: 1000000, | ||
| thinkingMandatory: true, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| }); | ||
| expect(models?.[0]?.generationConfig?.extra_body).toBeUndefined(); | ||
|
|
||
| expect(models?.[1]).toMatchObject({ | ||
| id: 'kimi-k2.7-code', | ||
| name: '[Kimi] kimi-k2.7-code', | ||
| generationConfig: { | ||
| contextWindowSize: 262144, | ||
| extra_body: { enable_thinking: true }, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| }); | ||
| expect(models?.[1]?.generationConfig?.thinkingMandatory).toBeUndefined(); | ||
|
|
||
| expect(models?.[2]).toMatchObject({ | ||
| id: 'kimi-k2.7-code-highspeed', | ||
| name: '[Kimi] kimi-k2.7-code-highspeed', | ||
|
Comment on lines
+105
to
+107
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The new Witness (mutation run in a scratch tree, Mirror the K3 negative assertion — after the highspeed block closes, add: expect(models?.[2]?.generationConfig?.thinkingMandatory).toBeUndefined();(optionally the same for 中文说明新增的 见证(在临时树中运行变异, 建议参照 K3 的负向断言——在 highspeed 断言块结束后补充 — qwen3.8-max via Qwen Code /review (v0.22.0)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed — fixed in 03b9651. Added Re-ran your probe against the fix: adding 中文说明同意,已在 03b9651 修复。在两个代码模型断言块之后都补充了 已用你的探针回验:向 highspeed 规格加入 |
||
| generationConfig: { | ||
| contextWindowSize: 262144, | ||
| extra_body: { enable_thinking: true }, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| }); | ||
| expect(models?.[2]?.generationConfig?.thinkingMandatory).toBeUndefined(); | ||
|
|
||
| expect(models?.[3]).toMatchObject({ | ||
| id: 'kimi-k2.6', | ||
| name: '[Kimi] kimi-k2.6', | ||
| generationConfig: { | ||
| contextWindowSize: 262144, | ||
| extra_body: { enable_thinking: true }, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| }); | ||
| expect(models?.[3]?.generationConfig?.thinkingMandatory).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('falls back gracefully for unknown model IDs', () => { | ||
| const plan = buildInstallPlan(moonshotProvider, { | ||
| baseUrl: CHINA_BASE_URL, | ||
| apiKey: 'sk-moonshot', | ||
| modelIds: ['kimi-k4-preview'], | ||
| }); | ||
|
|
||
| const models = plan.modelProviders?.[0]?.models; | ||
| expect(models?.[0]).toMatchObject({ | ||
| id: 'kimi-k4-preview', | ||
| name: '[Kimi] kimi-k4-preview', | ||
| }); | ||
| expect(models?.[0]?.generationConfig).toBeUndefined(); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2026 Qwen Team | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { AuthType } from '../../core/contentGenerator.js'; | ||
| import type { ProviderConfig } from '../types.js'; | ||
|
|
||
| export const moonshotProvider: ProviderConfig = { | ||
| id: 'moonshot', | ||
| label: 'Kimi (Moonshot AI) API Key', | ||
| description: 'Quick setup for Kimi models', | ||
| protocol: AuthType.USE_OPENAI, | ||
| baseUrl: [ | ||
| { | ||
| id: 'international', | ||
| label: 'International', | ||
| url: 'https://api.moonshot.ai/v1', | ||
| documentationUrl: 'https://platform.kimi.ai/docs', | ||
| }, | ||
| { | ||
| id: 'china', | ||
| label: 'China', | ||
| url: 'https://api.moonshot.cn/v1', | ||
| documentationUrl: 'https://platform.moonshot.cn/docs', | ||
| }, | ||
| ], | ||
| envKey: 'MOONSHOT_API_KEY', | ||
| models: [ | ||
| { | ||
| id: 'kimi-k3', | ||
| contextWindowSize: 1000000, | ||
| // K3 always thinks: the API exposes `reasoning_effort` but no way to | ||
| // turn thinking off, so never emit a disable shape on the wire. | ||
| thinkingMandatory: true, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| { | ||
| id: 'kimi-k2.7-code', | ||
| contextWindowSize: 262144, | ||
| enableThinking: true, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| { | ||
| id: 'kimi-k2.7-code-highspeed', | ||
| contextWindowSize: 262144, | ||
| enableThinking: true, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| { | ||
| id: 'kimi-k2.6', | ||
| contextWindowSize: 262144, | ||
| enableThinking: true, | ||
| modalities: { image: true, video: true }, | ||
| }, | ||
| ], | ||
| modelsEditable: true, | ||
| modelNamePrefix: 'Kimi', | ||
| uiGroup: 'third-party', | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] This PR adds Kimi to two provider lists (this one and the one in
docs/users/overview.md) but not to the third sibling list atdocs/users/quickstart.md:75— "choose a built-in provider (DeepSeek, MiniMax, Z.AI, ModelScope, OpenRouter, Requesty, and more)" — so immediately after this change ships a built-in Kimi, the three first-run docs disagree about which providers are built in. The quickstart list is explicitly non-exhaustive ("and more") and already omitted Grok and Idealab before this PR, so leaving it as a summary is defensible — but syncing it would fix every stale entry at once. If the list is meant to track the registry, update it to(DeepSeek, Grok, MiniMax, Z.AI, Kimi, Idealab, ModelScope, OpenRouter, Requesty, and more).中文说明
本 PR 在两处 provider 列表(此处的
auth.md与docs/users/overview.md)中加入了 Kimi,但第三处同类列表docs/users/quickstart.md:75—— "choose a built-in provider (DeepSeek, MiniMax, Z.AI, ModelScope, OpenRouter, Requesty, and more)" —— 未同步,导致本改动上线后三个入门文档对内置 provider 的口径不一致。quickstart 的列表本身是非穷举的("and more"),且在本 PR 之前就已缺少 Grok 与 Idealab,因此维持现状作为摘要也说得通;但若同步一次,可以一并修复所有过期条目。若该列表意在跟随注册表,可更新为(DeepSeek, Grok, MiniMax, Z.AI, Kimi, Idealab, ModelScope, OpenRouter, Requesty, and more)。— qwen3.8-max via Qwen Code /review (v0.22.0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed and synced in e9d712f. The list now reads
(DeepSeek, Grok, MiniMax, Z.AI, Kimi, Idealab, ModelScope, OpenRouter, Requesty, and more), so all three first-run docs now name the same set. As you noted, that also clears the Grok and Idealab entries that were already stale before this branch.中文说明
同意,已在 e9d712f 同步。该列表现为
(DeepSeek, Grok, MiniMax, Z.AI, Kimi, Idealab, ModelScope, OpenRouter, Requesty, and more),三处入门文档口径已一致。正如你指出的,这同时修正了本分支之前就已过期的 Grok 与 Idealab 条目。