diff --git a/electron/shared/providers/registry.ts b/electron/shared/providers/registry.ts index 1c6b65ef..aa483e37 100644 --- a/electron/shared/providers/registry.ts +++ b/electron/shared/providers/registry.ts @@ -144,6 +144,37 @@ export const PROVIDER_DEFINITIONS: ProviderDefinition[] = [ ], }, }, + { + id: 'moonshot-global', + name: 'Moonshot (Global)', + icon: '🌙', + placeholder: 'sk-...', + model: 'Kimi', + requiresApiKey: true, + defaultBaseUrl: 'https://api.moonshot.ai/v1', + defaultModelId: 'kimi-k2.5', + category: 'official', + envVar: 'MOONSHOT_GLOBAL_API_KEY', + supportedAuthModes: ['api_key'], + defaultAuthMode: 'api_key', + supportsMultipleAccounts: true, + providerConfig: { + baseUrl: 'https://api.moonshot.ai/v1', + api: 'openai-completions', + apiKeyEnv: 'MOONSHOT_GLOBAL_API_KEY', + models: [ + { + id: 'kimi-k2.5', + name: 'Kimi K2.5', + reasoning: false, + input: ['text'], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 256000, + maxTokens: 8192, + }, + ], + }, + }, { id: 'siliconflow', name: 'SiliconFlow (CN)', diff --git a/electron/shared/providers/types.ts b/electron/shared/providers/types.ts index 122c5244..5ecbbbc3 100644 --- a/electron/shared/providers/types.ts +++ b/electron/shared/providers/types.ts @@ -5,6 +5,7 @@ export const PROVIDER_TYPES = [ 'openrouter', 'ark', 'moonshot', + 'moonshot-global', 'siliconflow', 'minimax-portal', 'minimax-portal-cn', @@ -20,6 +21,7 @@ export const BUILTIN_PROVIDER_TYPES = [ 'openrouter', 'ark', 'moonshot', + 'moonshot-global', 'siliconflow', 'minimax-portal', 'minimax-portal-cn', diff --git a/src/lib/providers.ts b/src/lib/providers.ts index 4cb1af12..146863fd 100644 --- a/src/lib/providers.ts +++ b/src/lib/providers.ts @@ -13,6 +13,7 @@ export const PROVIDER_TYPES = [ 'openrouter', 'ark', 'moonshot', + 'moonshot-global', 'siliconflow', 'minimax-portal', 'minimax-portal-cn', @@ -29,6 +30,7 @@ export const BUILTIN_PROVIDER_TYPES = [ 'openrouter', 'ark', 'moonshot', + 'moonshot-global', 'siliconflow', 'minimax-portal', 'minimax-portal-cn', @@ -172,6 +174,7 @@ export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [ { id: 'openrouter', name: 'OpenRouter', icon: '🌐', placeholder: 'sk-or-v1-...', model: 'Multi-Model', requiresApiKey: true, showModelId: true, modelIdPlaceholder: 'openai/gpt-5.4', defaultModelId: 'openai/gpt-5.4', docsUrl: 'https://openrouter.ai/models' }, { id: 'minimax-portal-cn', name: 'MiniMax (CN)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.7', showModelId: true, showModelIdInDevModeOnly: true, modelIdPlaceholder: 'MiniMax-M2.7', apiKeyUrl: 'https://platform.minimaxi.com/' }, { id: 'moonshot', name: 'Moonshot (CN)', icon: '🌙', placeholder: 'sk-...', model: 'Kimi', requiresApiKey: true, defaultBaseUrl: 'https://api.moonshot.cn/v1', defaultModelId: 'kimi-k2.5', docsUrl: 'https://platform.moonshot.cn/' }, + { id: 'moonshot-global', name: 'Moonshot (Global)', icon: '🌙', placeholder: 'sk-...', model: 'Kimi', requiresApiKey: true, defaultBaseUrl: 'https://api.moonshot.ai/v1', defaultModelId: 'kimi-k2.5', docsUrl: 'https://platform.moonshot.ai/' }, { id: 'siliconflow', name: 'SiliconFlow (CN)', icon: '🌊', placeholder: 'sk-...', model: 'Multi-Model', requiresApiKey: true, defaultBaseUrl: 'https://api.siliconflow.cn/v1', showModelId: true, showModelIdInDevModeOnly: true, modelIdPlaceholder: 'deepseek-ai/DeepSeek-V3', defaultModelId: 'deepseek-ai/DeepSeek-V3', docsUrl: 'https://docs.siliconflow.cn/cn/userguide/introduction' }, { id: 'minimax-portal', name: 'MiniMax (Global)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.7', showModelId: true, showModelIdInDevModeOnly: true, modelIdPlaceholder: 'MiniMax-M2.7', apiKeyUrl: 'https://platform.minimax.io' }, { id: 'modelstudio', name: 'Model Studio', icon: '☁️', placeholder: 'sk-...', model: 'Qwen', requiresApiKey: true, defaultBaseUrl: 'https://coding.dashscope.aliyuncs.com/v1', showBaseUrl: true, defaultModelId: 'qwen3.5-plus', showModelId: true, showModelIdInDevModeOnly: true, modelIdPlaceholder: 'qwen3.5-plus', apiKeyUrl: 'https://bailian.console.aliyun.com/', hidden: true }, diff --git a/tests/e2e/provider-moonshot-global.spec.ts b/tests/e2e/provider-moonshot-global.spec.ts new file mode 100644 index 00000000..4f26794b --- /dev/null +++ b/tests/e2e/provider-moonshot-global.spec.ts @@ -0,0 +1,37 @@ +import { completeSetup, expect, test } from './fixtures/electron'; + +const TEST_PROVIDER_ID = 'moonshot-global-e2e'; +const TEST_PROVIDER_LABEL = 'Moonshot Global E2E'; + +async function seedTestProvider(page: Parameters[0]): Promise { + await page.evaluate(async ({ providerId, providerLabel }) => { + const now = new Date().toISOString(); + await window.electron.ipcRenderer.invoke('provider:save', { + id: providerId, + name: providerLabel, + type: 'moonshot-global', + baseUrl: 'https://api.moonshot.ai/v1', + model: 'kimi-k2.5', + enabled: true, + createdAt: now, + updatedAt: now, + }); + }, { providerId: TEST_PROVIDER_ID, providerLabel: TEST_PROVIDER_LABEL }); +} + +test.describe('Moonshot Global provider lifecycle', () => { + test('shows a saved moonshot-global provider with correct defaults and removes it cleanly', async ({ page }) => { + await completeSetup(page); + await seedTestProvider(page); + + await page.getByTestId('sidebar-nav-models').click(); + await expect(page.getByTestId('providers-settings')).toBeVisible(); + await expect(page.getByTestId(`provider-card-${TEST_PROVIDER_ID}`)).toContainText(TEST_PROVIDER_LABEL); + + await page.getByTestId(`provider-card-${TEST_PROVIDER_ID}`).hover(); + await page.getByTestId(`provider-delete-${TEST_PROVIDER_ID}`).click(); + + await expect(page.getByTestId(`provider-card-${TEST_PROVIDER_ID}`)).toHaveCount(0); + await expect(page.getByText(TEST_PROVIDER_LABEL)).toHaveCount(0); + }); +});