revert: some proxy errors in main process (#2294)

This commit is contained in:
kangfenmao 2025-03-01 23:17:44 +08:00
parent efa9c6c546
commit 11bd55701c
7 changed files with 9 additions and 152 deletions

View File

@ -77,7 +77,6 @@
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"officeparser": "^4.1.1", "officeparser": "^4.1.1",
"tokenx": "^0.4.1", "tokenx": "^0.4.1",
"undici": "^7.3.0",
"webdav": "4.11.4" "webdav": "4.11.4"
}, },
"devDependencies": { "devDependencies": {

View File

@ -2,7 +2,7 @@ import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { Shortcut, ThemeMode } from '@types' import { Shortcut, ThemeMode } from '@types'
import { BrowserWindow, ipcMain, session, shell } from 'electron' import { BrowserWindow, ipcMain, ProxyConfig, session, shell } from 'electron'
import log from 'electron-log' import log from 'electron-log'
import { titleBarOverlayDark, titleBarOverlayLight } from './config' import { titleBarOverlayDark, titleBarOverlayLight } from './config'
@ -14,12 +14,12 @@ import FileService from './services/FileService'
import FileStorage from './services/FileStorage' import FileStorage from './services/FileStorage'
import { GeminiService } from './services/GeminiService' import { GeminiService } from './services/GeminiService'
import KnowledgeService from './services/KnowledgeService' import KnowledgeService from './services/KnowledgeService'
import { ProxyConfig, proxyManager } from './services/ProxyManager'
import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService' import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService'
import { TrayService } from './services/TrayService' import { TrayService } from './services/TrayService'
import { windowService } from './services/WindowService' import { windowService } from './services/WindowService'
import { getResourcePath } from './utils' import { getResourcePath } from './utils'
import { decrypt, encrypt } from './utils/aes' import { decrypt } from './utils/aes'
import { encrypt } from './utils/aes'
import { compress, decompress } from './utils/zip' import { compress, decompress } from './utils/zip'
const fileManager = new FileStorage() const fileManager = new FileStorage()
@ -40,9 +40,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
})) }))
ipcMain.handle('app:proxy', async (_, proxy: string) => { ipcMain.handle('app:proxy', async (_, proxy: string) => {
const proxyConfig: ProxyConfig = const sessions = [session.defaultSession, session.fromPartition('persist:webview')]
proxy === 'system' ? { mode: 'system' } : proxy ? { mode: 'custom', url: proxy } : { mode: 'none' } const proxyConfig: ProxyConfig = proxy === 'system' ? { mode: 'system' } : proxy ? { proxyRules: proxy } : {}
await proxyManager.configureProxy(proxyConfig) await Promise.all(sessions.map((session) => session.setProxy(proxyConfig)))
}) })
ipcMain.handle('app:reload', () => mainWindow.reload()) ipcMain.handle('app:reload', () => mainWindow.reload())

View File

@ -1,16 +1,14 @@
import { FileMetadataResponse, FileState, GoogleAIFileManager } from '@google/generative-ai/server' import { FileMetadataResponse, FileState, GoogleAIFileManager } from '@google/generative-ai/server'
import { FileType } from '@types' import { FileType } from '@types'
import fs from 'fs' import fs from 'fs'
import { ProxyAgent, setGlobalDispatcher } from 'undici'
import { CacheService } from './CacheService' import { CacheService } from './CacheService'
import { proxyManager } from './ProxyManager'
export class GeminiService { export class GeminiService {
private static readonly FILE_LIST_CACHE_KEY = 'gemini_file_list' private static readonly FILE_LIST_CACHE_KEY = 'gemini_file_list'
private static readonly CACHE_DURATION = 3000 private static readonly CACHE_DURATION = 3000
static async uploadFile(_: Electron.IpcMainInvokeEvent, file: FileType, apiKey: string) { static async uploadFile(_: Electron.IpcMainInvokeEvent, file: FileType, apiKey: string) {
setGlobalDispatcher(new ProxyAgent(proxyManager.getProxyUrl() || ''))
const fileManager = new GoogleAIFileManager(apiKey) const fileManager = new GoogleAIFileManager(apiKey)
const uploadResult = await fileManager.uploadFile(file.path, { const uploadResult = await fileManager.uploadFile(file.path, {
mimeType: 'application/pdf', mimeType: 'application/pdf',
@ -31,7 +29,6 @@ export class GeminiService {
file: FileType, file: FileType,
apiKey: string apiKey: string
): Promise<FileMetadataResponse | undefined> { ): Promise<FileMetadataResponse | undefined> {
setGlobalDispatcher(new ProxyAgent(proxyManager.getProxyUrl() || ''))
const fileManager = new GoogleAIFileManager(apiKey) const fileManager = new GoogleAIFileManager(apiKey)
const cachedResponse = CacheService.get<any>(GeminiService.FILE_LIST_CACHE_KEY) const cachedResponse = CacheService.get<any>(GeminiService.FILE_LIST_CACHE_KEY)
@ -55,13 +52,11 @@ export class GeminiService {
} }
static async listFiles(_: Electron.IpcMainInvokeEvent, apiKey: string) { static async listFiles(_: Electron.IpcMainInvokeEvent, apiKey: string) {
setGlobalDispatcher(new ProxyAgent(proxyManager.getProxyUrl() || ''))
const fileManager = new GoogleAIFileManager(apiKey) const fileManager = new GoogleAIFileManager(apiKey)
return await fileManager.listFiles() return await fileManager.listFiles()
} }
static async deleteFile(_: Electron.IpcMainInvokeEvent, apiKey: string, fileId: string) { static async deleteFile(_: Electron.IpcMainInvokeEvent, apiKey: string, fileId: string) {
setGlobalDispatcher(new ProxyAgent(proxyManager.getProxyUrl() || ''))
const fileManager = new GoogleAIFileManager(apiKey) const fileManager = new GoogleAIFileManager(apiKey)
await fileManager.deleteFile(fileId) await fileManager.deleteFile(fileId)
} }

View File

@ -13,10 +13,8 @@ import { getAllFiles } from '@main/utils/file'
import type { LoaderReturn } from '@shared/config/types' import type { LoaderReturn } from '@shared/config/types'
import { FileType, KnowledgeBaseParams, KnowledgeItem } from '@types' import { FileType, KnowledgeBaseParams, KnowledgeItem } from '@types'
import { app } from 'electron' import { app } from 'electron'
import { ProxyAgent, setGlobalDispatcher } from 'undici'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { proxyManager } from './ProxyManager'
import { windowService } from './WindowService' import { windowService } from './WindowService'
class KnowledgeService { class KnowledgeService {
@ -50,14 +48,13 @@ class KnowledgeService {
azureOpenAIApiVersion: apiVersion, azureOpenAIApiVersion: apiVersion,
azureOpenAIApiDeploymentName: model, azureOpenAIApiDeploymentName: model,
azureOpenAIApiInstanceName: getInstanceName(baseURL), azureOpenAIApiInstanceName: getInstanceName(baseURL),
configuration: { httpAgent: proxyManager.getProxyAgent() },
dimensions, dimensions,
batchSize batchSize
}) })
: new OpenAiEmbeddings({ : new OpenAiEmbeddings({
model, model,
apiKey, apiKey,
configuration: { baseURL, httpAgent: proxyManager.getProxyAgent() }, configuration: { baseURL },
dimensions, dimensions,
batchSize batchSize
}) })
@ -86,7 +83,6 @@ class KnowledgeService {
_: Electron.IpcMainInvokeEvent, _: Electron.IpcMainInvokeEvent,
{ base, item, forceReload = false }: { base: KnowledgeBaseParams; item: KnowledgeItem; forceReload: boolean } { base, item, forceReload = false }: { base: KnowledgeBaseParams; item: KnowledgeItem; forceReload: boolean }
): Promise<LoaderReturn> => { ): Promise<LoaderReturn> => {
setGlobalDispatcher(new ProxyAgent(proxyManager.getProxyUrl() || ''))
const ragApplication = await this.getRagApplication(base) const ragApplication = await this.getRagApplication(base)
const sendDirectoryProcessingPercent = (totalFiles: number, processedFiles: number) => { const sendDirectoryProcessingPercent = (totalFiles: number, processedFiles: number) => {

View File

@ -1,116 +0,0 @@
import { ProxyConfig as _ProxyConfig, session } from 'electron'
import { HttpsProxyAgent } from 'https-proxy-agent'
type ProxyMode = 'system' | 'custom' | 'none'
export interface ProxyConfig {
mode: ProxyMode
url?: string | null
}
export class ProxyManager {
private config: ProxyConfig
private proxyAgent: HttpsProxyAgent | null = null
private proxyUrl: string | null = null
constructor() {
this.config = {
mode: 'system',
url: ''
}
}
private async setSessionsProxy(config: _ProxyConfig): Promise<void> {
const sessions = [session.defaultSession, session.fromPartition('persist:webview')]
await Promise.all(sessions.map((session) => session.setProxy(config)))
}
async configureProxy(config: ProxyConfig): Promise<void> {
try {
this.config = config
if (this.config.mode === 'system') {
await this.setSystemProxy()
} else if (this.config.mode == 'custom') {
await this.setCustomProxy()
} else {
await this.clearProxy()
}
} catch (error) {
console.error('Failed to config proxy:', error)
throw error
}
}
private setEnvironment(url: string): void {
process.env.grpc_proxy = url
process.env.HTTP_PROXY = url
process.env.HTTPS_PROXY = url
process.env.http_proxy = url
process.env.https_proxy = url
}
private async setSystemProxy(): Promise<void> {
try {
this.proxyUrl = await this.resolveSystemProxy()
if (this.proxyUrl) {
this.proxyAgent = new HttpsProxyAgent(this.proxyUrl)
this.setEnvironment(this.proxyUrl)
await this.setSessionsProxy({ mode: 'system' })
}
} catch (error) {
console.error('Failed to set system proxy:', error)
throw error
}
}
private async setCustomProxy(): Promise<void> {
try {
if (this.config.url) {
this.proxyUrl = this.config.url
this.proxyAgent = new HttpsProxyAgent(this.config.url)
this.setEnvironment(this.config.url)
await this.setSessionsProxy({ proxyRules: this.config.url })
}
} catch (error) {
console.error('Failed to set custom proxy:', error)
throw error
}
}
private async clearProxy(): Promise<void> {
delete process.env.HTTP_PROXY
delete process.env.HTTPS_PROXY
await this.setSessionsProxy({})
this.config = { mode: 'none' }
}
private async resolveSystemProxy(): Promise<string | null> {
try {
return await this.resolveElectronProxy()
} catch (error) {
console.error('Failed to resolve system proxy:', error)
return null
}
}
private async resolveElectronProxy(): Promise<string | null> {
try {
const proxyString = await session.defaultSession.resolveProxy('https://dummy.com')
const [protocol, address] = proxyString.split(';')[0].split(' ')
return protocol === 'PROXY' ? `http://${address}` : null
} catch (error) {
console.error('Failed to resolve electron proxy:', error)
return null
}
}
getProxyAgent(): HttpsProxyAgent | null {
return this.proxyAgent
}
getProxyUrl(): string | null {
return this.proxyUrl
}
}
export const proxyManager = new ProxyManager()

View File

@ -1,12 +1,8 @@
import { WebDavConfig } from '@types' import { WebDavConfig } from '@types'
import Logger from 'electron-log' import Logger from 'electron-log'
import { HttpProxyAgent } from 'http-proxy-agent'
import { HttpsProxyAgent } from 'https-proxy-agent'
import Stream from 'stream' import Stream from 'stream'
import { BufferLike, createClient, GetFileContentsOptions, PutFileContentsOptions, WebDAVClient } from 'webdav' import { BufferLike, createClient, GetFileContentsOptions, PutFileContentsOptions, WebDAVClient } from 'webdav'
import { proxyManager } from './ProxyManager'
export default class WebDav { export default class WebDav {
public instance: WebDAVClient | undefined public instance: WebDAVClient | undefined
private webdavPath: string private webdavPath: string
@ -14,16 +10,11 @@ export default class WebDav {
constructor(params: WebDavConfig) { constructor(params: WebDavConfig) {
this.webdavPath = params.webdavPath this.webdavPath = params.webdavPath
const httpProxy = proxyManager.getProxyUrl() || ''
const httpsProxy = proxyManager.getProxyUrl() || ''
this.instance = createClient(params.webdavHost, { this.instance = createClient(params.webdavHost, {
username: params.webdavUser, username: params.webdavUser,
password: params.webdavPass, password: params.webdavPass,
maxBodyLength: Infinity, maxBodyLength: Infinity,
maxContentLength: Infinity, maxContentLength: Infinity
httpAgent: httpProxy ? new HttpProxyAgent(httpProxy) : undefined,
httpsAgent: httpsProxy ? new HttpsProxyAgent(httpsProxy) : undefined
}) })
this.putFileContents = this.putFileContents.bind(this) this.putFileContents = this.putFileContents.bind(this)

View File

@ -3093,7 +3093,6 @@ __metadata:
tinycolor2: "npm:^1.6.0" tinycolor2: "npm:^1.6.0"
tokenx: "npm:^0.4.1" tokenx: "npm:^0.4.1"
typescript: "npm:^5.6.2" typescript: "npm:^5.6.2"
undici: "npm:^7.3.0"
uuid: "npm:^10.0.0" uuid: "npm:^10.0.0"
vite: "npm:^5.0.12" vite: "npm:^5.0.12"
webdav: "npm:4.11.4" webdav: "npm:4.11.4"
@ -13943,13 +13942,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"undici@npm:^7.3.0":
version: 7.3.0
resolution: "undici@npm:7.3.0"
checksum: 10c0/62c5e335725cadb02e19950932c7823fc330cbfd80106e6836daa6db1379aa727510b77de0a4e6f912087b288ded93f7daf4b8c154ad36fd5c9c4b96b26888b8
languageName: node
linkType: hard
"unified@npm:^11.0.0": "unified@npm:^11.0.0":
version: 11.0.5 version: 11.0.5
resolution: "unified@npm:11.0.5" resolution: "unified@npm:11.0.5"