feat: add silicon provider support for Anthropic API compatibility (#11468)
* feat: add silicon provider support for Anthropic API compatibility * fix: update handling of ANTHROPIC_BASE_URL for silicon provider compatibility * fix: update anthropicApiHost for silicon provider to use the correct endpoint * fix: remove silicon from CLAUDE_OFFICIAL_SUPPORTED_PROVIDERS * chore: add comment to clarify silicon model fallback logic in CLAUDE_OFFICIAL_SUPPORTED_PROVIDERS
This commit is contained in:
48
packages/shared/config/providers.ts
Normal file
48
packages/shared/config/providers.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @fileoverview Shared provider configuration for Claude Code and Anthropic API compatibility
|
||||
*
|
||||
* This module defines which models from specific providers support the Anthropic API endpoint.
|
||||
* Used by both the Code Tools page and the Anthropic SDK client.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Silicon provider models that support Anthropic API endpoint.
|
||||
* These models can be used with Claude Code via the Anthropic-compatible API.
|
||||
*
|
||||
* @see https://docs.siliconflow.cn/cn/api-reference/chat-completions/messages
|
||||
*/
|
||||
export const SILICON_ANTHROPIC_COMPATIBLE_MODELS: readonly string[] = [
|
||||
// DeepSeek V3.1 series
|
||||
'Pro/deepseek-ai/DeepSeek-V3.1-Terminus',
|
||||
'deepseek-ai/DeepSeek-V3.1',
|
||||
'Pro/deepseek-ai/DeepSeek-V3.1',
|
||||
// DeepSeek V3 series
|
||||
'deepseek-ai/DeepSeek-V3',
|
||||
'Pro/deepseek-ai/DeepSeek-V3',
|
||||
// Moonshot/Kimi series
|
||||
'moonshotai/Kimi-K2-Instruct-0905',
|
||||
'Pro/moonshotai/Kimi-K2-Instruct-0905',
|
||||
'moonshotai/Kimi-Dev-72B',
|
||||
// Baidu ERNIE
|
||||
'baidu/ERNIE-4.5-300B-A47B'
|
||||
]
|
||||
|
||||
/**
|
||||
* Creates a Set for efficient lookup of silicon Anthropic-compatible model IDs.
|
||||
*/
|
||||
const SILICON_ANTHROPIC_COMPATIBLE_MODEL_SET = new Set(SILICON_ANTHROPIC_COMPATIBLE_MODELS)
|
||||
|
||||
/**
|
||||
* Checks if a model ID is compatible with Anthropic API on Silicon provider.
|
||||
*
|
||||
* @param modelId - The model ID to check
|
||||
* @returns true if the model supports Anthropic API endpoint
|
||||
*/
|
||||
export function isSiliconAnthropicCompatibleModel(modelId: string): boolean {
|
||||
return SILICON_ANTHROPIC_COMPATIBLE_MODEL_SET.has(modelId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Silicon provider's Anthropic API host URL.
|
||||
*/
|
||||
export const SILICON_ANTHROPIC_API_HOST = 'https://api.siliconflow.cn'
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CacheService } from '@main/services/CacheService'
|
||||
import { loggerService } from '@main/services/LoggerService'
|
||||
import { reduxService } from '@main/services/ReduxService'
|
||||
import { isSiliconAnthropicCompatibleModel } from '@shared/config/providers'
|
||||
import type { ApiModel, Model, Provider } from '@types'
|
||||
|
||||
const logger = loggerService.withContext('ApiServerUtils')
|
||||
@@ -287,6 +288,8 @@ export const getProviderAnthropicModelChecker = (providerId: string): ((m: Model
|
||||
return (m: Model) => m.endpoint_type === 'anthropic'
|
||||
case 'aihubmix':
|
||||
return (m: Model) => m.id.includes('claude')
|
||||
case 'silicon':
|
||||
return (m: Model) => isSiliconAnthropicCompatibleModel(m.id)
|
||||
default:
|
||||
// allow all models when checker not configured
|
||||
return () => true
|
||||
|
||||
@@ -95,6 +95,7 @@ export const SYSTEM_PROVIDERS_CONFIG: Record<SystemProviderId, SystemProvider> =
|
||||
type: 'openai',
|
||||
apiKey: '',
|
||||
apiHost: 'https://api.siliconflow.cn',
|
||||
anthropicApiHost: 'https://api.siliconflow.cn',
|
||||
models: SYSTEM_MODELS.silicon,
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
@@ -168,6 +169,7 @@ export const SYSTEM_PROVIDERS_CONFIG: Record<SystemProviderId, SystemProvider> =
|
||||
type: 'openai',
|
||||
apiKey: '',
|
||||
apiHost: 'https://www.dmxapi.cn',
|
||||
anthropicApiHost: 'https://www.dmxapi.cn',
|
||||
models: SYSTEM_MODELS.dmxapi,
|
||||
isSystem: true,
|
||||
enabled: false
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { EndpointType, Model } from '@renderer/types'
|
||||
import { getClaudeSupportedProviders } from '@renderer/utils/provider'
|
||||
import type { TerminalConfig } from '@shared/config/constant'
|
||||
import { codeTools, terminalApps } from '@shared/config/constant'
|
||||
import { isSiliconAnthropicCompatibleModel } from '@shared/config/providers'
|
||||
import { Alert, Avatar, Button, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
||||
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -81,6 +82,10 @@ const CodeToolsPage: FC = () => {
|
||||
if (m.supported_endpoint_types) {
|
||||
return m.supported_endpoint_types.includes('anthropic')
|
||||
}
|
||||
// Special handling for silicon provider: only specific models support Anthropic API
|
||||
if (m.provider === 'silicon') {
|
||||
return isSiliconAnthropicCompatibleModel(m.id)
|
||||
}
|
||||
return m.id.includes('claude') || CLAUDE_OFFICIAL_SUPPORTED_PROVIDERS.includes(m.provider)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EndpointType, Model, Provider } from '@renderer/types'
|
||||
import { type EndpointType, type Model, type Provider, SystemProviderIds } from '@renderer/types'
|
||||
import { codeTools } from '@shared/config/constant'
|
||||
|
||||
export interface LaunchValidationResult {
|
||||
@@ -25,7 +25,18 @@ export const CLI_TOOLS = [
|
||||
]
|
||||
|
||||
export const GEMINI_SUPPORTED_PROVIDERS = ['aihubmix', 'dmxapi', 'new-api', 'cherryin']
|
||||
export const CLAUDE_OFFICIAL_SUPPORTED_PROVIDERS = ['deepseek', 'moonshot', 'zhipu', 'dashscope', 'modelscope']
|
||||
export const CLAUDE_OFFICIAL_SUPPORTED_PROVIDERS = [
|
||||
'deepseek',
|
||||
'moonshot',
|
||||
'zhipu',
|
||||
'dashscope',
|
||||
'modelscope',
|
||||
'minimax',
|
||||
'longcat',
|
||||
SystemProviderIds.qiniu
|
||||
// If silicon is in this list, the fallback logic above will return true for all silicon models,
|
||||
// potentially bypassing the specific model filtering you added above.
|
||||
]
|
||||
export const CLAUDE_SUPPORTED_PROVIDERS = [
|
||||
'aihubmix',
|
||||
'dmxapi',
|
||||
@@ -79,6 +90,11 @@ export const getCodeToolsApiBaseUrl = (model: Model, type: EndpointType) => {
|
||||
anthropic: {
|
||||
api_base_url: 'https://api-inference.modelscope.cn'
|
||||
}
|
||||
},
|
||||
minimax: {
|
||||
anthropic: {
|
||||
api_base_url: 'https://api.minimaxi.com/anthropic'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +141,8 @@ export const generateToolEnvironment = ({
|
||||
|
||||
switch (tool) {
|
||||
case codeTools.claudeCode:
|
||||
env.ANTHROPIC_BASE_URL = getCodeToolsApiBaseUrl(model, 'anthropic') || modelProvider.apiHost
|
||||
env.ANTHROPIC_BASE_URL =
|
||||
getCodeToolsApiBaseUrl(model, 'anthropic') || modelProvider.anthropicApiHost || modelProvider.apiHost
|
||||
env.ANTHROPIC_MODEL = model.id
|
||||
if (modelProvider.type === 'anthropic') {
|
||||
env.ANTHROPIC_API_KEY = apiKey
|
||||
|
||||
@@ -82,7 +82,10 @@ const ANTHROPIC_COMPATIBLE_PROVIDER_IDS = [
|
||||
SystemProviderIds.grok,
|
||||
SystemProviderIds.cherryin,
|
||||
SystemProviderIds.longcat,
|
||||
SystemProviderIds.minimax
|
||||
SystemProviderIds.minimax,
|
||||
SystemProviderIds.silicon,
|
||||
SystemProviderIds.qiniu,
|
||||
SystemProviderIds.dmxapi
|
||||
] as const
|
||||
type AnthropicCompatibleProviderId = (typeof ANTHROPIC_COMPATIBLE_PROVIDER_IDS)[number]
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 178,
|
||||
version: 179,
|
||||
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@@ -2884,6 +2884,28 @@ const migrateConfig = {
|
||||
logger.error('migrate 178 error', error as Error)
|
||||
return state
|
||||
}
|
||||
},
|
||||
'179': (state: RootState) => {
|
||||
try {
|
||||
state.llm.providers.forEach((provider) => {
|
||||
switch (provider.id) {
|
||||
case SystemProviderIds.silicon:
|
||||
provider.anthropicApiHost = 'https://api.siliconflow.cn'
|
||||
break
|
||||
case SystemProviderIds.qiniu:
|
||||
provider.anthropicApiHost = 'https://api.qnaigc.com'
|
||||
break
|
||||
case SystemProviderIds.dmxapi:
|
||||
provider.anthropicApiHost = provider.apiHost
|
||||
break
|
||||
}
|
||||
})
|
||||
logger.info('migrate 179 success')
|
||||
return state
|
||||
} catch (error) {
|
||||
logger.error('migrate 179 error', error as Error)
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user