}
const pathMap = {
@@ -163,7 +165,8 @@ const MainMenus: FC = () => {
translate: '/translate',
minapp: '/apps',
knowledge: '/knowledge',
- files: '/files'
+ files: '/files',
+ code_tools: '/code'
}
return sidebarIcons.visible.map((icon) => {
diff --git a/src/renderer/src/pages/code/CodeToolsPage.tsx b/src/renderer/src/pages/code/CodeToolsPage.tsx
index c6d0b05977..fec6f20672 100644
--- a/src/renderer/src/pages/code/CodeToolsPage.tsx
+++ b/src/renderer/src/pages/code/CodeToolsPage.tsx
@@ -1,4 +1,5 @@
import AiProvider from '@renderer/aiCore'
+import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
import ModelSelector from '@renderer/components/ModelSelector'
import { isEmbeddingModel, isRerankModel, isTextToImageModel } from '@renderer/config/models'
import { useCodeTools } from '@renderer/hooks/useCodeTools'
@@ -22,6 +23,8 @@ const CLI_TOOLS = [
{ value: 'gemini-cli', label: 'Gemini CLI' }
]
+const SUPPORTED_PROVIDERS = ['aihubmix', 'dmxapi', 'new-api']
+
const logger = loggerService.withContext('CodeToolsPage')
const CodeToolsPage: FC = () => {
@@ -54,12 +57,23 @@ const CodeToolsPage: FC = () => {
}
const openAiProviders = providers.filter((p) => p.type.includes('openai'))
- const geminiProviders = providers.filter((p) => p.type === 'gemini')
- const claudeProviders = providers.filter((p) => p.type === 'anthropic')
+ const geminiProviders = providers.filter((p) => p.type === 'gemini' || SUPPORTED_PROVIDERS.includes(p.id))
+ const claudeProviders = providers.filter((p) => p.type === 'anthropic' || SUPPORTED_PROVIDERS.includes(p.id))
const modelPredicate = useCallback(
- (m: Model) => !isEmbeddingModel(m) && !isRerankModel(m) && !isTextToImageModel(m),
- []
+ (m: Model) => {
+ if (isEmbeddingModel(m) || isRerankModel(m) || isTextToImageModel(m)) {
+ return false
+ }
+ if (selectedCliTool === 'claude-code') {
+ return m.id.includes('claude')
+ }
+ if (selectedCliTool === 'gemini-cli') {
+ return m.id.includes('gemini')
+ }
+ return true
+ },
+ [selectedCliTool]
)
const availableProviders =
@@ -176,13 +190,19 @@ const CodeToolsPage: FC = () => {
if (selectedCliTool === 'claude-code') {
env = {
ANTHROPIC_API_KEY: apiKey,
+ ANTHROPIC_BASE_URL: modelProvider.apiHost,
ANTHROPIC_MODEL: selectedModel.id
}
}
if (selectedCliTool === 'gemini-cli') {
+ const apiSuffix = modelProvider.id === 'aihubmix' ? '/gemini' : ''
+ const apiBaseUrl = modelProvider.apiHost + apiSuffix
env = {
- GEMINI_API_KEY: apiKey
+ GEMINI_API_KEY: apiKey,
+ GEMINI_BASE_URL: apiBaseUrl,
+ GOOGLE_GEMINI_BASE_URL: apiBaseUrl,
+ GEMINI_MODEL: selectedModel.id
}
}
@@ -228,117 +248,134 @@ const CodeToolsPage: FC = () => {
return (
,
text: t('title.code'),
path: '/code',
bgColor: 'linear-gradient(135deg, #1F2937, #374151)' // Code CLI:高级暗黑色,代表专业和技术
diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts
index 0f8e88cd3f..c328f8b6c3 100644
--- a/src/renderer/src/store/index.ts
+++ b/src/renderer/src/store/index.ts
@@ -62,7 +62,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
- version: 132,
+ version: 133,
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs'],
migrate
},
diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts
index dc799b0d48..a22619254a 100644
--- a/src/renderer/src/store/migrate.ts
+++ b/src/renderer/src/store/migrate.ts
@@ -2119,6 +2119,15 @@ const migrateConfig = {
logger.error('migrate 132 error', error as Error)
return state
}
+ },
+ '133': (state: RootState) => {
+ try {
+ state.settings.sidebarIcons.visible.push('code_tools')
+ return state
+ } catch (error) {
+ logger.error('migrate 133 error', error as Error)
+ return state
+ }
}
}
diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts
index aecd4311bc..fd2853360f 100644
--- a/src/renderer/src/store/settings.ts
+++ b/src/renderer/src/store/settings.ts
@@ -21,7 +21,15 @@ import { RemoteSyncState } from './backup'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter'
-export type SidebarIcon = 'assistants' | 'agents' | 'paintings' | 'translate' | 'minapp' | 'knowledge' | 'files'
+export type SidebarIcon =
+ | 'assistants'
+ | 'agents'
+ | 'paintings'
+ | 'translate'
+ | 'minapp'
+ | 'knowledge'
+ | 'files'
+ | 'code_tools'
export const DEFAULT_SIDEBAR_ICONS: SidebarIcon[] = [
'assistants',