diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 8c9efbe6..d0ceafc0 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -42,7 +42,12 @@ export default defineConfig({ } }, preload: { - plugins: [externalizeDepsPlugin()] + plugins: [externalizeDepsPlugin()], + resolve: { + alias: { + '@shared': resolve('packages/shared') + } + } }, renderer: { plugins: [ @@ -70,7 +75,7 @@ export default defineConfig({ } }, optimizeDeps: { - exclude: ['chunk-PZ64DZKH.js', 'chunk-JMKENWIY.js', 'chunk-UXYB6GHG.js', 'chunk-ALDIEZMG.js', 'chunk-4X6ZJEXY.js'] + exclude: [] } } }) diff --git a/packages/shared/IpcChannel.ts b/packages/shared/IpcChannel.ts index 57bf8967..d07a0a52 100644 --- a/packages/shared/IpcChannel.ts +++ b/packages/shared/IpcChannel.ts @@ -146,5 +146,5 @@ export enum IpcChannel { MiniWindowReload = 'miniwindow-reload', ReduxStateChange = 'redux-state-change', - ReduxStoreReady = 'redux-store-ready', + ReduxStoreReady = 'redux-store-ready' } diff --git a/src/main/index.ts b/src/main/index.ts index e753602a..816695bb 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,5 +1,6 @@ import { electronApp, optimizer } from '@electron-toolkit/utils' import { replaceDevtoolsFont } from '@main/utils/windowUtil' +import { IpcChannel } from '@shared/IpcChannel' import { app, ipcMain } from 'electron' import installExtension, { REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } from 'electron-devtools-installer' @@ -9,7 +10,6 @@ import { CHERRY_STUDIO_PROTOCOL, handleProtocolUrl, registerProtocolClient } fro import { registerShortcuts } from './services/ShortcutService' import { TrayService } from './services/TrayService' import { windowService } from './services/WindowService' -import { IpcChannel } from '@shared/IpcChannel' // Check for single instance lock if (!app.requestSingleInstanceLock()) { diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 491b69ca..f5eec985 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -2,6 +2,7 @@ import fs from 'node:fs' import { isMac, isWin } from '@main/constant' import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process' +import { IpcChannel } from '@shared/IpcChannel' import { Shortcut, ThemeMode } from '@types' import { BrowserWindow, ipcMain, session, shell } from 'electron' import log from 'electron-log' @@ -27,7 +28,6 @@ import { getResourcePath } from './utils' import { decrypt, encrypt } from './utils/aes' import { getFilesDir } from './utils/file' import { compress, decompress } from './utils/zip' -import { IpcChannel } from '@shared/IpcChannel' const fileManager = new FileStorage() const backupManager = new BackupManager() @@ -303,11 +303,3 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { NutstoreService.getDirectoryContents(token, path) ) } - - // Listen for changes in MCP servers and notify renderer - mcpService.on('servers-updated', (servers) => { - mainWindow?.webContents.send(IpcChannel.Mcp_ServersUpdated, servers) - }) - -app.on('before-quit', () => mcpService.cleanup()) - \ No newline at end of file diff --git a/src/main/services/AppUpdater.ts b/src/main/services/AppUpdater.ts index 3be259bc..5a1f45ba 100644 --- a/src/main/services/AppUpdater.ts +++ b/src/main/services/AppUpdater.ts @@ -1,10 +1,10 @@ +import { IpcChannel } from '@shared/IpcChannel' import { UpdateInfo } from 'builder-util-runtime' import { app, BrowserWindow, dialog } from 'electron' import logger from 'electron-log' import { AppUpdater as _AppUpdater, autoUpdater } from 'electron-updater' import icon from '../../../build/icon.png?asset' -import { IpcChannel } from '@shared/IpcChannel' export default class AppUpdater { autoUpdater: _AppUpdater = autoUpdater diff --git a/src/main/services/BackupManager.ts b/src/main/services/BackupManager.ts index e3c26fdd..136ffbce 100644 --- a/src/main/services/BackupManager.ts +++ b/src/main/services/BackupManager.ts @@ -1,3 +1,4 @@ +import { IpcChannel } from '@shared/IpcChannel' import { WebDavConfig } from '@types' import AdmZip from 'adm-zip' import { exec } from 'child_process' @@ -9,7 +10,6 @@ import { createClient, CreateDirectoryOptions, FileStat } from 'webdav' import WebDav from './WebDav' import { windowService } from './WindowService' -import { IpcChannel } from '@shared/IpcChannel' class BackupManager { private tempDir = path.join(app.getPath('temp'), 'cherry-studio', 'backup', 'temp') diff --git a/src/main/services/KnowledgeService.ts b/src/main/services/KnowledgeService.ts index d282b278..ef8fa1b8 100644 --- a/src/main/services/KnowledgeService.ts +++ b/src/main/services/KnowledgeService.ts @@ -26,13 +26,13 @@ import { addFileLoader } from '@main/loader' import Reranker from '@main/reranker/Reranker' import { windowService } from '@main/services/WindowService' import { getAllFiles } from '@main/utils/file' +import { MB } from '@shared/config/constant' import type { LoaderReturn } from '@shared/config/types' +import { IpcChannel } from '@shared/IpcChannel' import { FileType, KnowledgeBaseParams, KnowledgeItem } from '@types' import { app } from 'electron' import Logger from 'electron-log' import { v4 as uuidv4 } from 'uuid' -import { IpcChannel } from '@shared/IpcChannel' -import { MB } from '@shared/config/constant' export interface KnowledgeBaseAddItemOptions { base: KnowledgeBaseParams diff --git a/src/main/services/ReduxService.ts b/src/main/services/ReduxService.ts index 479f62da..ec9b1c08 100644 --- a/src/main/services/ReduxService.ts +++ b/src/main/services/ReduxService.ts @@ -1,8 +1,8 @@ +import { IpcChannel } from '@shared/IpcChannel' import { ipcMain } from 'electron' import { EventEmitter } from 'events' import { windowService } from './WindowService' -import { IpcChannel } from '@shared/IpcChannel' type StoreValue = any type Unsubscribe = () => void diff --git a/src/main/services/WindowService.ts b/src/main/services/WindowService.ts index 966cc6f2..380d98a5 100644 --- a/src/main/services/WindowService.ts +++ b/src/main/services/WindowService.ts @@ -1,6 +1,7 @@ import { is } from '@electron-toolkit/utils' import { isDev, isLinux, isMac, isWin } from '@main/constant' import { getFilesDir } from '@main/utils/file' +import { IpcChannel } from '@shared/IpcChannel' import { app, BrowserWindow, ipcMain, Menu, MenuItem, shell } from 'electron' import Logger from 'electron-log' import windowStateKeeper from 'electron-window-state' @@ -10,7 +11,6 @@ import icon from '../../../build/icon.png?asset' import { titleBarOverlayDark, titleBarOverlayLight } from '../config' import { locales } from '../utils/locales' import { configManager } from './ConfigManager' -import { IpcChannel } from '@shared/IpcChannel' export class WindowService { private static instance: WindowService | null = null diff --git a/src/preload/index.ts b/src/preload/index.ts index 899d3e87..c8b6fb1a 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -1,9 +1,9 @@ import type { ExtractChunkData } from '@cherrystudio/embedjs-interfaces' import { electronAPI } from '@electron-toolkit/preload' +import { IpcChannel } from '@shared/IpcChannel' import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types' import { contextBridge, ipcRenderer, OpenDialogOptions, shell } from 'electron' import { CreateDirectoryOptions } from 'webdav' -import { IpcChannel } from '@shared/IpcChannel' // Custom APIs for renderer const api = { @@ -35,9 +35,12 @@ const api = { restore: (backupPath: string) => ipcRenderer.invoke(IpcChannel.Backup_Restore, backupPath), backupToWebdav: (data: string, webdavConfig: WebDavConfig) => ipcRenderer.invoke(IpcChannel.Backup_BackupToWebdav, data, webdavConfig), - restoreFromWebdav: (webdavConfig: WebDavConfig) => ipcRenderer.invoke(IpcChannel.Backup_RestoreFromWebdav, webdavConfig), - listWebdavFiles: (webdavConfig: WebDavConfig) => ipcRenderer.invoke(IpcChannel.Backup_ListWebdavFiles, webdavConfig), - checkConnection: (webdavConfig: WebDavConfig) => ipcRenderer.invoke(IpcChannel.Backup_CheckConnection, webdavConfig), + restoreFromWebdav: (webdavConfig: WebDavConfig) => + ipcRenderer.invoke(IpcChannel.Backup_RestoreFromWebdav, webdavConfig), + listWebdavFiles: (webdavConfig: WebDavConfig) => + ipcRenderer.invoke(IpcChannel.Backup_ListWebdavFiles, webdavConfig), + checkConnection: (webdavConfig: WebDavConfig) => + ipcRenderer.invoke(IpcChannel.Backup_CheckConnection, webdavConfig), createDirectory: (webdavConfig: WebDavConfig, path: string, options?: CreateDirectoryOptions) => ipcRenderer.invoke(IpcChannel.Backup_CreateDirectory, webdavConfig, path, options) }, @@ -114,7 +117,7 @@ const api = { show: () => ipcRenderer.invoke(IpcChannel.MiniWindow_Show), hide: () => ipcRenderer.invoke(IpcChannel.MiniWindow_Hide), close: () => ipcRenderer.invoke(IpcChannel.MiniWindow_Close), - toggle: () => ipcRenderer.invoke(IpcChannel.MiniWindow_Toggle) + toggle: () => ipcRenderer.invoke(IpcChannel.MiniWindow_Toggle), setPin: (isPinned: boolean) => ipcRenderer.invoke(IpcChannel.MiniWindow_SetPin, isPinned) }, aes: { @@ -150,7 +153,7 @@ const api = { isBinaryExist: (name: string) => ipcRenderer.invoke(IpcChannel.App_IsBinaryExist, name), getBinaryPath: (name: string) => ipcRenderer.invoke(IpcChannel.App_GetBinaryPath, name), installUVBinary: () => ipcRenderer.invoke(IpcChannel.App_InstallUvBinary), - installBunBinary: () => ipcRenderer.invoke(IpcChannel.App_InstallBunBinary) + installBunBinary: () => ipcRenderer.invoke(IpcChannel.App_InstallBunBinary), protocol: { onReceiveData: (callback: (data: { url: string; params: any }) => void) => { const listener = (_event: Electron.IpcRendererEvent, data: { url: string; params: any }) => { diff --git a/src/renderer/src/components/Popups/BackupPopup.tsx b/src/renderer/src/components/Popups/BackupPopup.tsx index 813e27a1..d3f99f6b 100644 --- a/src/renderer/src/components/Popups/BackupPopup.tsx +++ b/src/renderer/src/components/Popups/BackupPopup.tsx @@ -1,10 +1,10 @@ import { backup } from '@renderer/services/BackupService' +import { IpcChannel } from '@shared/IpcChannel' import { Modal, Progress } from 'antd' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { TopView } from '../TopView' -import { IpcChannel } from '@shared/IpcChannel' interface Props { resolve: (data: any) => void diff --git a/src/renderer/src/components/Popups/RestorePopup.tsx b/src/renderer/src/components/Popups/RestorePopup.tsx index ee9ef850..36c11944 100644 --- a/src/renderer/src/components/Popups/RestorePopup.tsx +++ b/src/renderer/src/components/Popups/RestorePopup.tsx @@ -1,10 +1,10 @@ import { restore } from '@renderer/services/BackupService' +import { IpcChannel } from '@shared/IpcChannel' import { Modal, Progress } from 'antd' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { TopView } from '../TopView' -import { IpcChannel } from '@shared/IpcChannel' interface Props { resolve: (data: any) => void diff --git a/src/renderer/src/context/ThemeProvider.tsx b/src/renderer/src/context/ThemeProvider.tsx index 14c77de5..dd31b0ae 100644 --- a/src/renderer/src/context/ThemeProvider.tsx +++ b/src/renderer/src/context/ThemeProvider.tsx @@ -1,8 +1,8 @@ import { isMac } from '@renderer/config/constant' import { useSettings } from '@renderer/hooks/useSettings' import { ThemeMode } from '@renderer/types' -import React, { createContext, PropsWithChildren, use, useEffect, useState } from 'react' import { IpcChannel } from '@shared/IpcChannel' +import React, { createContext, PropsWithChildren, use, useEffect, useState } from 'react' interface ThemeContextType { theme: ThemeMode diff --git a/src/renderer/src/hooks/useAppInit.ts b/src/renderer/src/hooks/useAppInit.ts index 112bd11d..90b778da 100644 --- a/src/renderer/src/hooks/useAppInit.ts +++ b/src/renderer/src/hooks/useAppInit.ts @@ -6,6 +6,7 @@ import i18n from '@renderer/i18n' import { useAppDispatch } from '@renderer/store' import { setAvatar, setFilesPath, setResourcesPath, setUpdateState } from '@renderer/store/runtime' import { delay, runAsyncFunction } from '@renderer/utils' +import { defaultLanguage } from '@shared/config/constant' import { useLiveQuery } from 'dexie-react-hooks' import { useEffect } from 'react' @@ -15,8 +16,6 @@ import { useRuntime } from './useRuntime' import { useSettings } from './useSettings' import useUpdateHandler from './useUpdateHandler' -import { defaultLanguage } from '@shared/config/constant' - export function useAppInit() { const dispatch = useAppDispatch() const { proxyUrl, language, windowStyle, autoCheckUpdate, proxyMode, customCss } = useSettings() diff --git a/src/renderer/src/hooks/useFullScreenNotice.ts b/src/renderer/src/hooks/useFullScreenNotice.ts index ea62e0f2..9f95ddd9 100644 --- a/src/renderer/src/hooks/useFullScreenNotice.ts +++ b/src/renderer/src/hooks/useFullScreenNotice.ts @@ -1,7 +1,7 @@ import { isWindows } from '@renderer/config/constant' +import { IpcChannel } from '@shared/IpcChannel' import { useEffect } from 'react' import { useTranslation } from 'react-i18next' -import { IpcChannel } from '@shared/IpcChannel' export function useFullScreenNotice() { const { t } = useTranslation() diff --git a/src/renderer/src/hooks/useKnowledge.ts b/src/renderer/src/hooks/useKnowledge.ts index 4eed0093..e69b5850 100644 --- a/src/renderer/src/hooks/useKnowledge.ts +++ b/src/renderer/src/hooks/useKnowledge.ts @@ -21,13 +21,13 @@ import { } from '@renderer/store/knowledge' import { FileType, KnowledgeBase, KnowledgeItem, ProcessingStatus } from '@renderer/types' import { runAsyncFunction } from '@renderer/utils' +import { IpcChannel } from '@shared/IpcChannel' import { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { v4 as uuidv4 } from 'uuid' import { useAgents } from './useAgents' import { useAssistants } from './useAssistant' -import { IpcChannel } from '@shared/IpcChannel' export const useKnowledge = (baseId: string) => { const dispatch = useDispatch() diff --git a/src/renderer/src/hooks/useUpdateHandler.ts b/src/renderer/src/hooks/useUpdateHandler.ts index 5dd42e03..576da468 100644 --- a/src/renderer/src/hooks/useUpdateHandler.ts +++ b/src/renderer/src/hooks/useUpdateHandler.ts @@ -1,9 +1,9 @@ import { useAppDispatch } from '@renderer/store' import { setUpdateState } from '@renderer/store/runtime' +import { IpcChannel } from '@shared/IpcChannel' import type { ProgressInfo, UpdateInfo } from 'builder-util-runtime' import { useEffect } from 'react' import { useTranslation } from 'react-i18next' -import { IpcChannel } from '@shared/IpcChannel' export default function useUpdateHandler() { const dispatch = useAppDispatch() diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index 3b6dc7a3..9ecc0581 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -1,3 +1,4 @@ +import { defaultLanguage } from '@shared/config/constant' import i18n from 'i18next' import { initReactI18next } from 'react-i18next' @@ -13,8 +14,6 @@ import esES from './translate/es-es.json' import frFR from './translate/fr-fr.json' import ptPT from './translate/pt-pt.json' -import { defaultLanguage } from '@shared/config/constant' - const resources = { 'el-GR': elGR, 'en-US': enUS, diff --git a/src/renderer/src/pages/files/GeminiFiles.tsx b/src/renderer/src/pages/files/GeminiFiles.tsx index 3e2739db..9d9035f8 100644 --- a/src/renderer/src/pages/files/GeminiFiles.tsx +++ b/src/renderer/src/pages/files/GeminiFiles.tsx @@ -2,13 +2,13 @@ import { DeleteOutlined } from '@ant-design/icons' import type { FileMetadataResponse } from '@google/generative-ai/server' import { useProvider } from '@renderer/hooks/useProvider' import { runAsyncFunction } from '@renderer/utils' +import { MB } from '@shared/config/constant' import { Spin } from 'antd' import dayjs from 'dayjs' import { FC, useCallback, useEffect, useState } from 'react' import styled from 'styled-components' import FileItem from './FileItem' -import { MB } from '@shared/config/constant' interface GeminiFilesProps { id: string diff --git a/src/renderer/src/pages/settings/GeneralSettings.tsx b/src/renderer/src/pages/settings/GeneralSettings.tsx index c3239952..a041c924 100644 --- a/src/renderer/src/pages/settings/GeneralSettings.tsx +++ b/src/renderer/src/pages/settings/GeneralSettings.tsx @@ -6,12 +6,12 @@ import { setLanguage } from '@renderer/store/settings' import { setProxyMode, setProxyUrl as _setProxyUrl } from '@renderer/store/settings' import { LanguageVarious } from '@renderer/types' import { isValidProxyUrl } from '@renderer/utils' +import { defaultLanguage } from '@shared/config/constant' import { Input, Select, Space, Switch } from 'antd' import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '.' -import { defaultLanguage } from '@shared/config/constant' const GeneralSettings: FC = () => { const { diff --git a/src/renderer/src/providers/AiProvider/GeminiProvider.ts b/src/renderer/src/providers/AiProvider/GeminiProvider.ts index 5ec4bf67..520ace22 100644 --- a/src/renderer/src/providers/AiProvider/GeminiProvider.ts +++ b/src/renderer/src/providers/AiProvider/GeminiProvider.ts @@ -38,13 +38,13 @@ import { mcpToolsToGeminiTools, upsertMCPToolResponse } from '@renderer/utils/mcp-tools' +import { MB } from '@shared/config/constant' import axios from 'axios' import { isEmpty, takeRight } from 'lodash' import OpenAI from 'openai' import { ChunkCallbackData, CompletionsParams } from '.' import BaseProvider from './BaseProvider' -import { MB } from '@shared/config/constant' export default class GeminiProvider extends BaseProvider { private sdk: GoogleGenerativeAI diff --git a/src/renderer/src/store/llm.ts b/src/renderer/src/store/llm.ts index b50f3f11..8e9c29fa 100644 --- a/src/renderer/src/store/llm.ts +++ b/src/renderer/src/store/llm.ts @@ -2,8 +2,8 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { isLocalAi } from '@renderer/config/env' import { SYSTEM_MODELS } from '@renderer/config/models' import { Model, Provider } from '@renderer/types' -import { uniqBy } from 'lodash' import { IpcChannel } from '@shared/IpcChannel' +import { uniqBy } from 'lodash' type LlmSettings = { ollama: { diff --git a/src/renderer/src/utils/index.ts b/src/renderer/src/utils/index.ts index 0584f8a9..7be1b5e0 100644 --- a/src/renderer/src/utils/index.ts +++ b/src/renderer/src/utils/index.ts @@ -1,5 +1,6 @@ import i18n from '@renderer/i18n' import { Model } from '@renderer/types' +import { KB, MB } from '@shared/config/constant' import { ModalFuncProps } from 'antd/es/modal/interface' import imageCompression from 'browser-image-compression' import * as htmlToImage from 'html-to-image' @@ -7,7 +8,6 @@ import * as htmlToImage from 'html-to-image' import { v4 as uuidv4 } from 'uuid' import { classNames } from './style' -import { KB, MB } from '@shared/config/constant' export const runAsyncFunction = async (fn: () => void) => { await fn() diff --git a/src/renderer/src/windows/mini/home/HomeWindow.tsx b/src/renderer/src/windows/mini/home/HomeWindow.tsx index 1904c438..1d483a67 100644 --- a/src/renderer/src/windows/mini/home/HomeWindow.tsx +++ b/src/renderer/src/windows/mini/home/HomeWindow.tsx @@ -4,6 +4,8 @@ import { useSettings } from '@renderer/hooks/useSettings' import i18n from '@renderer/i18n' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { uuid } from '@renderer/utils' +import { defaultLanguage } from '@shared/config/constant' +import { IpcChannel } from '@shared/IpcChannel' import { Divider } from 'antd' import dayjs from 'dayjs' import { isEmpty } from 'lodash' @@ -18,9 +20,6 @@ import ClipboardPreview from './components/ClipboardPreview' import FeatureMenus, { FeatureMenusRef } from './components/FeatureMenus' import Footer from './components/Footer' import InputBar from './components/InputBar' -import { IpcChannel } from '@shared/IpcChannel' - -import { defaultLanguage } from '@shared/config/constant' const HomeWindow: FC = () => { const [route, setRoute] = useState<'home' | 'chat' | 'translate' | 'summary' | 'explanation'>('home')