diff --git a/packages/cli/src/auth/allProviders.ts b/packages/cli/src/auth/allProviders.ts index ead80188c75..2b0bfceef38 100644 --- a/packages/cli/src/auth/allProviders.ts +++ b/packages/cli/src/auth/allProviders.ts @@ -19,6 +19,7 @@ import { deepseekProvider } from './providers/thirdParty/deepseek.js'; import { minimaxProvider } from './providers/thirdParty/minimax.js'; import { zaiProvider } from './providers/thirdParty/zai.js'; import { idealabProvider } from './providers/thirdParty/idealab.js'; +import { modelscopeProvider } from './providers/thirdParty/modelscope.js'; import { customProvider } from './providers/custom/customProvider.js'; // Re-export all providers @@ -31,6 +32,7 @@ export { minimaxProvider, zaiProvider, idealabProvider, + modelscopeProvider, customProvider, }; export { @@ -52,6 +54,7 @@ export const ALL_PROVIDERS: readonly ProviderConfig[] = [ minimaxProvider, zaiProvider, idealabProvider, + modelscopeProvider, customProvider, ]; diff --git a/packages/cli/src/auth/providers/thirdParty/modelscope.test.ts b/packages/cli/src/auth/providers/thirdParty/modelscope.test.ts new file mode 100644 index 00000000000..90a6bf39710 --- /dev/null +++ b/packages/cli/src/auth/providers/thirdParty/modelscope.test.ts @@ -0,0 +1,60 @@ +/** + * @license + * Copyright 2026 Qwen Team + * SPDX-License-Identifier: Apache-2.0 + */ + +import { describe, expect, it } from 'vitest'; +import { AuthType } from '@qwen-code/qwen-code-core'; +import { modelscopeProvider, buildInstallPlan } from '../../allProviders.js'; + +describe('modelscopeProvider', () => { + it('has correct provider config', () => { + expect(modelscopeProvider).toMatchObject({ + id: 'modelscope', + protocol: AuthType.USE_OPENAI, + baseUrl: 'https://api-inference.modelscope.cn/v1', + envKey: 'MODELSCOPE_API_KEY', + }); + }); + + it('creates an install plan with per-model metadata for known IDs', () => { + const plan = buildInstallPlan(modelscopeProvider, { + baseUrl: 'https://api-inference.modelscope.cn/v1', + apiKey: 'sk-modelscope', + modelIds: ['deepseek-ai/DeepSeek-V4-Flash', 'Qwen/Qwen3.5-397B-A17B'], + }); + + const models = plan.modelProviders?.[0]?.models; + expect(models).toHaveLength(2); + expect(models?.[0]).toMatchObject({ + id: 'deepseek-ai/DeepSeek-V4-Flash', + name: '[ModelScope] deepseek-ai/DeepSeek-V4-Flash', + generationConfig: { contextWindowSize: 1000000 }, + }); + expect(models?.[1]).toMatchObject({ + id: 'Qwen/Qwen3.5-397B-A17B', + name: '[ModelScope] Qwen/Qwen3.5-397B-A17B', + generationConfig: { contextWindowSize: 1000000 }, + }); + }); + + it('falls back gracefully for unknown model IDs', () => { + const plan = buildInstallPlan(modelscopeProvider, { + baseUrl: 'https://api-inference.modelscope.cn/v1', + apiKey: 'sk-modelscope', + modelIds: ['deepseek-ai/DeepSeek-V4-Flash', 'some-new-model'], + }); + + const models = plan.modelProviders?.[0]?.models; + expect(models).toHaveLength(2); + expect(models?.[0]?.generationConfig).toMatchObject({ + contextWindowSize: 1000000, + }); + expect(models?.[1]).toMatchObject({ + id: 'some-new-model', + name: '[ModelScope] some-new-model', + }); + expect(models?.[1]?.generationConfig).toBeUndefined(); + }); +}); diff --git a/packages/cli/src/auth/providers/thirdParty/modelscope.ts b/packages/cli/src/auth/providers/thirdParty/modelscope.ts new file mode 100644 index 00000000000..f7e7ad365d7 --- /dev/null +++ b/packages/cli/src/auth/providers/thirdParty/modelscope.ts @@ -0,0 +1,40 @@ +/** + * @license + * Copyright 2026 Qwen Team + * SPDX-License-Identifier: Apache-2.0 + */ + +import { AuthType } from '@qwen-code/qwen-code-core'; +import type { ProviderConfig } from '../../providerConfig.js'; + +export const modelscopeProvider: ProviderConfig = { + id: 'modelscope', + label: 'ModelScope API Key', + description: 'Quick setup for ModelScope API Inference', + protocol: AuthType.USE_OPENAI, + baseUrl: 'https://api-inference.modelscope.cn/v1', + envKey: 'MODELSCOPE_API_KEY', + authMethod: 'input', + models: [ + { + id: 'deepseek-ai/DeepSeek-V4-Flash', + contextWindowSize: 1000000, + enableThinking: true, + }, + { + id: 'Qwen/Qwen3.5-397B-A17B', + contextWindowSize: 1000000, + enableThinking: true, + }, + { + id: 'ZhipuAI/GLM-5.1', + contextWindowSize: 1000000, + enableThinking: true, + }, + ], + modelsEditable: true, + modelNamePrefix: 'ModelScope', + documentationUrl: + 'https://modelscope.cn/docs/model-service/API-Inference/intro', + uiGroup: 'third-party', +};