diff --git a/electron/main/init.ts b/electron/main/init.ts index 5602dc1cb..a4adad68e 100644 --- a/electron/main/init.ts +++ b/electron/main/init.ts @@ -18,6 +18,7 @@ import log from 'electron-log'; import fs from 'fs'; import * as http from 'http'; import * as net from 'net'; +import os from 'os'; import path from 'path'; import { promisify } from 'util'; import { PromiseReturnType } from './install-deps'; @@ -35,6 +36,52 @@ import { const execAsync = promisify(exec); +const DEFAULT_SERVER_URL = 'https://dev.eigent.ai/api'; + +function readEnvValue(filePath: string, key: string): string | undefined { + try { + if (!fs.existsSync(filePath)) return undefined; + const content = fs.readFileSync(filePath, 'utf-8'); + const lines = content.split(/\r?\n/); + const line = lines.find((l) => { + let trimmed = l.trim(); + if (!trimmed || trimmed.startsWith('#')) return false; + // Handle lines with 'export' prefix (e.g. export SERVER_URL=value) + if (trimmed.startsWith('export ')) { + trimmed = trimmed.slice(7).trim(); + } + return trimmed.startsWith(`${key}=`); + }); + if (!line) return undefined; + let raw = line.trim(); + // Strip 'export ' prefix before extracting value + if (raw.startsWith('export ')) { + raw = raw.slice(7).trim(); + } + let value = raw.slice(key.length + 1).trim(); + // Strip surrounding quotes (single or double) + if ( + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")) + ) { + value = value.slice(1, -1); + } + return value; + } catch (error) { + log.warn(`Failed to read ${key} from ${filePath}:`, error); + return undefined; + } +} + +function buildLocalServerUrl(proxyUrl: string | undefined): string | undefined { + if (!proxyUrl) return undefined; + const trimmed = proxyUrl.trim().replace(/\/+$/, ''); + if (!trimmed) return undefined; + // Avoid double /api suffix + if (trimmed.endsWith('/api')) return trimmed; + return `${trimmed}/api`; +} + // helper function to get main window export function getMainWindow(): BrowserWindow | null { const windows = BrowserWindow.getAllWindows(); @@ -183,10 +230,57 @@ export async function startBackend( } const uvEnv = getUvEnv(currentVersion); + const globalEnvPath = path.join(os.homedir(), '.eigent', '.env'); + + const envProxyEnabled = process.env.VITE_USE_LOCAL_PROXY === 'true'; + const envProxyUrl = process.env.VITE_PROXY_URL; + let resolvedServerUrl: string | undefined; + let resolvedSource = 'default'; + + if (envProxyEnabled) { + resolvedServerUrl = buildLocalServerUrl(envProxyUrl); + if (resolvedServerUrl) { + resolvedSource = 'process.env VITE_*'; + } else { + log.warn('VITE_USE_LOCAL_PROXY is true but VITE_PROXY_URL is empty or invalid, ignoring'); + } + } + + const devServerUrl = process.env.VITE_DEV_SERVER_URL; + if (!resolvedServerUrl && devServerUrl) { + const devEnvPath = path.join(app.getAppPath(), '.env.development'); + const devProxyEnabled = readEnvValue(devEnvPath, 'VITE_USE_LOCAL_PROXY') === 'true'; + const devProxyUrl = readEnvValue(devEnvPath, 'VITE_PROXY_URL'); + if (devProxyEnabled) { + resolvedServerUrl = buildLocalServerUrl(devProxyUrl); + if (resolvedServerUrl) { + resolvedSource = `dev env file (${devEnvPath})`; + } else { + log.warn(`VITE_USE_LOCAL_PROXY is true in ${devEnvPath} but VITE_PROXY_URL is empty or invalid, ignoring`); + } + } + } + + if (!resolvedServerUrl && process.env.SERVER_URL) { + resolvedServerUrl = process.env.SERVER_URL; + resolvedSource = 'process.env SERVER_URL'; + } + + if (!resolvedServerUrl) { + const serverUrlFromFile = readEnvValue(globalEnvPath, 'SERVER_URL'); + if (serverUrlFromFile) { + resolvedServerUrl = serverUrlFromFile; + resolvedSource = `global env file (${globalEnvPath})`; + } + } + + const serverUrl = resolvedServerUrl || DEFAULT_SERVER_URL; + log.info(`Backend SERVER_URL resolved to: ${serverUrl} (source: ${resolvedSource})`); + const env = { ...process.env, ...uvEnv, - SERVER_URL: 'https://dev.eigent.ai/api', + SERVER_URL: serverUrl, PYTHONIOENCODING: 'utf-8', PYTHONUNBUFFERED: '1', npm_config_cache: npmCacheDir,