Chen Tao 0ddcecabdf
feat: support Github Copilot (#2432)
* feat: support Github Copilot

* feat: finish i18n translate

* fix: add safeStorage

* clean code

* chore: remove vision model

*  feat: add Model Context Protocol (MCP) support (#2809)

*  feat: add Model Context Protocol (MCP) server configuration (main)

- Added `@modelcontextprotocol/sdk` dependency for MCP integration.
- Introduced MCP server configuration UI in settings with add, edit, delete, and activation functionalities.
- Created `useMCPServers` hook to manage MCP server state and actions.
- Added i18n support for MCP settings with translation keys.
- Integrated MCP settings into the application's settings navigation and routing.
- Implemented Redux state management for MCP servers.
- Updated `yarn.lock` with new dependencies and their resolutions.

* 🌟 feat: implement mcp service and integrate with ipc handlers

- Added `MCPService` class to manage Model Context Protocol servers.
- Implemented various handlers in `ipc.ts` for managing MCP servers including listing, adding, updating, deleting, and activating/deactivating servers.
- Integrated MCP related types into existing type declarations for consistency across the application.
- Updated `preload` to expose new MCP related APIs to the renderer process.
- Enhanced `MCPSettings` component to interact directly with the new MCP service for adding, updating, deleting servers and setting their active states.
- Introduced selectors in the MCP Redux slice for fetching active and all servers from the store.
- Moved MCP types to a centralized location in `@renderer/types` for reuse across different parts of the application.

* feat: enhance MCPService initialization to prevent recursive calls and improve error handling

* feat: enhance MCP integration by adding MCPTool type and updating related methods

* feat: implement streaming support for tool calls in OpenAIProvider and enhance message processing

* fix: finish_reason undefined

* fix migrate

* feat: add rate limit and warning

* feat: add delete copilot token file

feat: add login message

feat: add default headers and change getCopilotToken algorithm

* fix

* feat: add rate limit

* chore: change apihost

* fix: remove duplicate apikey

* fix: change api host

* chore: add vertify first tooltip

---------

Co-authored-by: 亢奋猫 <kangfenmao@qq.com>
Co-authored-by: LiuVaayne <10231735+vaayne@users.noreply.github.com>
2025-03-19 13:24:50 +08:00

164 lines
6.8 KiB
TypeScript

import { ElectronAPI } from '@electron-toolkit/preload'
import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server'
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
import type { MCPServer, MCPTool } from '@renderer/types'
import { AppInfo, FileType, KnowledgeBaseParams, KnowledgeItem, LanguageVarious, WebDavConfig } from '@renderer/types'
import type { LoaderReturn } from '@shared/config/types'
import type { OpenDialogOptions } from 'electron'
import type { UpdateInfo } from 'electron-updater'
import { Readable } from 'stream'
declare global {
interface Window {
electron: ElectronAPI
api: {
getAppInfo: () => Promise<AppInfo>
checkForUpdate: () => Promise<{ currentVersion: string; updateInfo: UpdateInfo | null }>
showUpdateDialog: () => Promise<void>
openWebsite: (url: string) => void
setProxy: (proxy: string | undefined) => void
setLanguage: (theme: LanguageVarious) => void
setTray: (isActive: boolean) => void
restartTray: () => void
setTheme: (theme: 'light' | 'dark') => void
minApp: (options: { url: string; windowOptions?: Electron.BrowserWindowConstructorOptions }) => void
reload: () => void
clearCache: () => Promise<{ success: boolean; error?: string }>
zip: {
compress: (text: string) => Promise<Buffer>
decompress: (text: Buffer) => Promise<string>
}
backup: {
backup: (fileName: string, data: string, destinationPath?: string) => Promise<Readable>
restore: (backupPath: string) => Promise<string>
backupToWebdav: (data: string, webdavConfig: WebDavConfig) => Promise<boolean>
restoreFromWebdav: (webdavConfig: WebDavConfig) => Promise<string>
}
file: {
select: (options?: OpenDialogOptions) => Promise<FileType[] | null>
upload: (file: FileType) => Promise<FileType>
delete: (fileId: string) => Promise<void>
read: (fileId: string) => Promise<string>
clear: () => Promise<void>
get: (filePath: string) => Promise<FileType | null>
selectFolder: () => Promise<string | null>
create: (fileName: string) => Promise<string>
write: (filePath: string, data: Uint8Array | string) => Promise<void>
open: (options?: OpenDialogOptions) => Promise<{ fileName: string; filePath: string; content: Buffer } | null>
openPath: (path: string) => Promise<void>
save: (
path: string,
content: string | NodeJS.ArrayBufferView,
options?: SaveDialogOptions
) => Promise<string | null>
saveImage: (name: string, data: string) => void
base64Image: (fileId: string) => Promise<{ mime: string; base64: string; data: string }>
download: (url: string) => Promise<FileType | null>
copy: (fileId: string, destPath: string) => Promise<void>
binaryFile: (fileId: string) => Promise<{ data: Buffer; mime: string }>
}
fs: {
read: (path: string) => Promise<string>
}
export: {
toWord: (markdown: string, fileName: string) => Promise<void>
}
openPath: (path: string) => Promise<void>
shortcuts: {
update: (shortcuts: Shortcut[]) => Promise<void>
}
knowledgeBase: {
create: ({ id, model, apiKey, baseURL }: KnowledgeBaseParams) => Promise<void>
reset: ({ base }: { base: KnowledgeBaseParams }) => Promise<void>
delete: (id: string) => Promise<void>
add: ({
base,
item,
forceReload = false
}: {
base: KnowledgeBaseParams
item: KnowledgeItem
forceReload?: boolean
}) => Promise<LoaderReturn>
remove: ({
uniqueId,
uniqueIds,
base
}: {
uniqueId: string
uniqueIds: string[]
base: KnowledgeBaseParams
}) => Promise<void>
search: ({ search, base }: { search: string; base: KnowledgeBaseParams }) => Promise<ExtractChunkData[]>
rerank: ({
search,
base,
results
}: {
search: string
base: KnowledgeBaseParams
results: ExtractChunkData[]
}) => Promise<ExtractChunkData[]>
}
window: {
setMinimumSize: (width: number, height: number) => Promise<void>
resetMinimumSize: () => Promise<void>
}
gemini: {
uploadFile: (file: FileType, apiKey: string) => Promise<UploadFileResponse>
retrieveFile: (file: FileType, apiKey: string) => Promise<FileMetadataResponse | undefined>
base64File: (file: FileType) => Promise<{ data: string; mimeType: string }>
listFiles: (apiKey: string) => Promise<ListFilesResponse>
deleteFile: (apiKey: string, fileId: string) => Promise<void>
}
selectionMenu: {
action: (action: string) => Promise<void>
}
config: {
set: (key: string, value: any) => Promise<void>
get: (key: string) => Promise<any>
}
miniWindow: {
show: () => Promise<void>
hide: () => Promise<void>
close: () => Promise<void>
toggle: () => Promise<void>
}
aes: {
encrypt: (text: string, secretKey: string, iv: string) => Promise<{ iv: string; encryptedData: string }>
decrypt: (encryptedData: string, iv: string, secretKey: string) => Promise<string>
}
shell: {
openExternal: (url: string, options?: OpenExternalOptions) => Promise<void>
}
mcp: {
// servers
listServers: () => Promise<MCPServer[]>
addServer: (server: MCPServer) => Promise<void>
updateServer: (server: MCPServer) => Promise<void>
deleteServer: (serverName: string) => Promise<void>
setServerActive: (name: string, isActive: boolean) => Promise<void>
// tools
listTools: () => Promise<MCPTool[]>
callTool: ({ client, name, args }: { client: string; name: string; args: any }) => Promise<any>
// status
cleanup: () => Promise<void>
}
copilot: {
getAuthMessage: (
headers?: Record<string, string>
) => Promise<{ device_code: string; user_code: string; verification_uri: string }>
getCopilotToken: (device_code: string, headers?: Record<string, string>) => Promise<{ access_token: string }>
saveCopilotToken: (access_token: string) => Promise<void>
getToken: (headers?: Record<string, string>) => Promise<{ token: string }>
logout: () => Promise<void>
getUser: (token: string) => Promise<{ login: string; avatar: string }>
}
isBinaryExist: (name: string) => Promise<boolean>
getBinaryPath: (name: string) => Promise<string>
installUVBinary: () => Promise<void>
installBunBinary: () => Promise<void>
}
}
}