-
{server.name}
+
+
+
+ {server.logoUrl && (
+

+ )}
+
{server.name}
+
{server.description ? (
-
{server.description}
+
+ {server.description}
+
) : null}
= ({
items={pluginTypeTabItems}
className="w-full"
size="small"
+ centered
/>
diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts
index 7b13f14f7a..1906d2e55d 100644
--- a/src/renderer/src/store/index.ts
+++ b/src/renderer/src/store/index.ts
@@ -71,7 +71,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
- version: 171,
+ version: 172,
blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'],
migrate
},
diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts
index 5ca545d838..7fb7f40d2e 100644
--- a/src/renderer/src/store/migrate.ts
+++ b/src/renderer/src/store/migrate.ts
@@ -2628,132 +2628,6 @@ const migrateConfig = {
return state
}
},
- '162': (state: RootState) => {
- try {
- // @ts-ignore
- if (state?.agents?.agents) {
- // @ts-ignore
- state.assistants.presets = [...state.agents.agents]
- // @ts-ignore
- delete state.agents.agents
- }
-
- if (state.settings.sidebarIcons) {
- state.settings.sidebarIcons.visible = state.settings.sidebarIcons.visible.map((icon) => {
- // @ts-ignore
- return icon === 'agents' ? 'store' : icon
- })
- state.settings.sidebarIcons.disabled = state.settings.sidebarIcons.disabled.map((icon) => {
- // @ts-ignore
- return icon === 'agents' ? 'store' : icon
- })
- }
-
- state.llm.providers.forEach((provider) => {
- if (provider.anthropicApiHost) {
- return
- }
-
- switch (provider.id) {
- case 'deepseek':
- provider.anthropicApiHost = 'https://api.deepseek.com/anthropic'
- break
- case 'moonshot':
- provider.anthropicApiHost = 'https://api.moonshot.cn/anthropic'
- break
- case 'zhipu':
- provider.anthropicApiHost = 'https://open.bigmodel.cn/api/anthropic'
- break
- case 'dashscope':
- provider.anthropicApiHost = 'https://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy'
- break
- case 'modelscope':
- provider.anthropicApiHost = 'https://api-inference.modelscope.cn'
- break
- case 'aihubmix':
- provider.anthropicApiHost = 'https://aihubmix.com'
- break
- case 'new-api':
- provider.anthropicApiHost = 'http://localhost:3000'
- break
- case 'grok':
- provider.anthropicApiHost = 'https://api.x.ai'
- }
- })
- return state
- } catch (error) {
- logger.error('migrate 162 error', error as Error)
- return state
- }
- },
- '163': (state: RootState) => {
- try {
- addOcrProvider(state, BUILTIN_OCR_PROVIDERS_MAP.ovocr)
- state.llm.providers.forEach((provider) => {
- if (provider.id === 'cherryin') {
- provider.anthropicApiHost = 'https://open.cherryin.net'
- }
- })
- state.paintings.ovms_paintings = []
- return state
- } catch (error) {
- logger.error('migrate 163 error', error as Error)
- return state
- }
- },
- '164': (state: RootState) => {
- try {
- addMiniApp(state, 'ling')
- return state
- } catch (error) {
- logger.error('migrate 164 error', error as Error)
- return state
- }
- },
- '165': (state: RootState) => {
- try {
- addMiniApp(state, 'huggingchat')
- return state
- } catch (error) {
- logger.error('migrate 165 error', error as Error)
- return state
- }
- },
- '166': (state: RootState) => {
- try {
- if (state.assistants.presets === undefined) {
- state.assistants.presets = []
- }
- state.assistants.presets.forEach((preset) => {
- if (!preset.settings) {
- preset.settings = DEFAULT_ASSISTANT_SETTINGS
- } else if (!preset.settings.toolUseMode) {
- preset.settings.toolUseMode = DEFAULT_ASSISTANT_SETTINGS.toolUseMode
- }
- })
- // 更新阿里云百炼的 Anthropic API 地址
- const dashscopeProvider = state.llm.providers.find((provider) => provider.id === 'dashscope')
- if (dashscopeProvider) {
- dashscopeProvider.anthropicApiHost = 'https://dashscope.aliyuncs.com/apps/anthropic'
- }
-
- state.llm.providers.forEach((provider) => {
- if (provider.id === SystemProviderIds['new-api'] && provider.type !== 'new-api') {
- provider.type = 'new-api'
- }
- if (provider.id === SystemProviderIds.longcat) {
- // https://longcat.chat/platform/docs/zh/#anthropic-api-%E6%A0%BC%E5%BC%8F
- if (!provider.anthropicApiHost) {
- provider.anthropicApiHost = 'https://api.longcat.chat/anthropic'
- }
- }
- })
- return state
- } catch (error) {
- logger.error('migrate 166 error', error as Error)
- return state
- }
- },
'167': (state: RootState) => {
try {
addProvider(state, 'huggingface')
@@ -2822,6 +2696,98 @@ const migrateConfig = {
logger.error('migrate 171 error', error as Error)
return state
}
+ },
+ '172': (state: RootState) => {
+ try {
+ // Add ling and huggingchat mini apps
+ addMiniApp(state, 'ling')
+ addMiniApp(state, 'huggingchat')
+
+ // Add ovocr provider and clear ovms paintings
+ addOcrProvider(state, BUILTIN_OCR_PROVIDERS_MAP.ovocr)
+ if (isEmpty(state.paintings.ovms_paintings)) {
+ state.paintings.ovms_paintings = []
+ }
+
+ // Migrate agents to assistants presets
+ // @ts-ignore
+ if (state?.agents?.agents) {
+ // @ts-ignore
+ state.assistants.presets = [...state.agents.agents]
+ // @ts-ignore
+ delete state.agents.agents
+ }
+
+ // Initialize assistants presets
+ if (state.assistants.presets === undefined) {
+ state.assistants.presets = []
+ }
+
+ // Migrate assistants presets
+ state.assistants.presets.forEach((preset) => {
+ if (!preset.settings) {
+ preset.settings = DEFAULT_ASSISTANT_SETTINGS
+ } else if (!preset.settings.toolUseMode) {
+ preset.settings.toolUseMode = DEFAULT_ASSISTANT_SETTINGS.toolUseMode
+ }
+ })
+
+ // Migrate sidebar icons
+ if (state.settings.sidebarIcons) {
+ state.settings.sidebarIcons.visible = state.settings.sidebarIcons.visible.map((icon) => {
+ // @ts-ignore
+ return icon === 'agents' ? 'store' : icon
+ })
+ state.settings.sidebarIcons.disabled = state.settings.sidebarIcons.disabled.map((icon) => {
+ // @ts-ignore
+ return icon === 'agents' ? 'store' : icon
+ })
+ }
+
+ // Migrate llm providers
+ state.llm.providers.forEach((provider) => {
+ if (provider.id === SystemProviderIds['new-api'] && provider.type !== 'new-api') {
+ provider.type = 'new-api'
+ }
+
+ switch (provider.id) {
+ case 'deepseek':
+ provider.anthropicApiHost = 'https://api.deepseek.com/anthropic'
+ break
+ case 'moonshot':
+ provider.anthropicApiHost = 'https://api.moonshot.cn/anthropic'
+ break
+ case 'zhipu':
+ provider.anthropicApiHost = 'https://open.bigmodel.cn/api/anthropic'
+ break
+ case 'dashscope':
+ provider.anthropicApiHost = 'https://dashscope.aliyuncs.com/apps/anthropic'
+ break
+ case 'modelscope':
+ provider.anthropicApiHost = 'https://api-inference.modelscope.cn'
+ break
+ case 'aihubmix':
+ provider.anthropicApiHost = 'https://aihubmix.com'
+ break
+ case 'new-api':
+ provider.anthropicApiHost = 'http://localhost:3000'
+ break
+ case 'grok':
+ provider.anthropicApiHost = 'https://api.x.ai'
+ break
+ case 'cherryin':
+ provider.anthropicApiHost = 'https://open.cherryin.net'
+ break
+ case 'longcat':
+ provider.anthropicApiHost = 'https://api.longcat.chat/anthropic'
+ break
+ }
+ })
+ return state
+ } catch (error) {
+ logger.error('migrate 172 error', error as Error)
+ return state
+ }
}
}
diff --git a/src/renderer/src/ui/context-menu.tsx b/src/renderer/src/ui/context-menu.tsx
deleted file mode 100644
index 7fdd27c38f..0000000000
--- a/src/renderer/src/ui/context-menu.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-'use client'
-
-import * as React from 'react'
-import * as ContextMenuPrimitive from '@radix-ui/react-context-menu'
-import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'
-import { cn } from '@renderer/utils'
-
-function ContextMenu({ ...props }: React.ComponentProps
) {
- return
-}
-
-function ContextMenuTrigger({ ...props }: React.ComponentProps) {
- return
-}
-
-function ContextMenuGroup({ ...props }: React.ComponentProps) {
- return
-}
-
-function ContextMenuPortal({ ...props }: React.ComponentProps) {
- return
-}
-
-function ContextMenuSub({ ...props }: React.ComponentProps) {
- return
-}
-
-function ContextMenuRadioGroup({ ...props }: React.ComponentProps) {
- return
-}
-
-function ContextMenuSubTrigger({
- className,
- inset,
- children,
- ...props
-}: React.ComponentProps & {
- inset?: boolean
-}) {
- return (
-
- {children}
-
-
- )
-}
-
-function ContextMenuSubContent({ className, ...props }: React.ComponentProps) {
- return (
-
- )
-}
-
-function ContextMenuContent({ className, ...props }: React.ComponentProps) {
- return (
-
-
-
- )
-}
-
-function ContextMenuItem({
- className,
- inset,
- variant = 'default',
- ...props
-}: React.ComponentProps & {
- inset?: boolean
- variant?: 'default' | 'destructive'
-}) {
- return (
-
- )
-}
-
-function ContextMenuCheckboxItem({
- className,
- children,
- checked,
- ...props
-}: React.ComponentProps) {
- return (
-
-
-
-
-
-
- {children}
-
- )
-}
-
-function ContextMenuRadioItem({
- className,
- children,
- ...props
-}: React.ComponentProps) {
- return (
-
-
-
-
-
-
- {children}
-
- )
-}
-
-function ContextMenuLabel({
- className,
- inset,
- ...props
-}: React.ComponentProps & {
- inset?: boolean
-}) {
- return (
-
- )
-}
-
-function ContextMenuSeparator({ className, ...props }: React.ComponentProps) {
- return (
-
- )
-}
-
-function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
- return (
-
- )
-}
-
-export {
- ContextMenu,
- ContextMenuTrigger,
- ContextMenuContent,
- ContextMenuItem,
- ContextMenuCheckboxItem,
- ContextMenuRadioItem,
- ContextMenuLabel,
- ContextMenuSeparator,
- ContextMenuShortcut,
- ContextMenuGroup,
- ContextMenuPortal,
- ContextMenuSub,
- ContextMenuSubContent,
- ContextMenuSubTrigger,
- ContextMenuRadioGroup
-}