Add built-in proxy settings for Electron and Gateway (#239)
Co-authored-by: zuolingxuan <zuolingxuan@bytedance.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
c09b45832b
commit
e40f4b2163
@@ -17,6 +17,8 @@ import { ClawHubService } from '../gateway/clawhub';
|
||||
import { ensureClawXContext, repairClawXOnlyBootstrapFiles } from '../utils/openclaw-workspace';
|
||||
import { autoInstallCliIfNeeded, generateCompletionCache, installCompletionToProfile } from '../utils/openclaw-cli';
|
||||
import { isQuitting, setQuitting } from './app-state';
|
||||
import { applyProxySettings } from './proxy';
|
||||
import { getSetting } from '../utils/store';
|
||||
import { ensureBuiltinSkillsInstalled } from '../utils/skill-config';
|
||||
|
||||
// Disable GPU hardware acceleration globally for maximum stability across
|
||||
@@ -128,6 +130,9 @@ async function initialize(): Promise<void> {
|
||||
// Warm up network optimization (non-blocking)
|
||||
void warmupNetworkOptimization();
|
||||
|
||||
// Apply persisted proxy settings before creating windows or network requests.
|
||||
await applyProxySettings();
|
||||
|
||||
// Set application menu
|
||||
createMenu();
|
||||
|
||||
@@ -195,13 +200,18 @@ async function initialize(): Promise<void> {
|
||||
});
|
||||
|
||||
// Start Gateway automatically (this seeds missing bootstrap files with full templates)
|
||||
try {
|
||||
logger.debug('Auto-starting Gateway...');
|
||||
await gatewayManager.start();
|
||||
logger.info('Gateway auto-start succeeded');
|
||||
} catch (error) {
|
||||
logger.error('Gateway auto-start failed:', error);
|
||||
mainWindow?.webContents.send('gateway:error', String(error));
|
||||
const gatewayAutoStart = await getSetting('gatewayAutoStart');
|
||||
if (gatewayAutoStart) {
|
||||
try {
|
||||
logger.debug('Auto-starting Gateway...');
|
||||
await gatewayManager.start();
|
||||
logger.info('Gateway auto-start succeeded');
|
||||
} catch (error) {
|
||||
logger.error('Gateway auto-start failed:', error);
|
||||
mainWindow?.webContents.send('gateway:error', String(error));
|
||||
}
|
||||
} else {
|
||||
logger.info('Gateway auto-start disabled in settings');
|
||||
}
|
||||
|
||||
// Merge ClawX context snippets into the workspace bootstrap files.
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from '../utils/secure-storage';
|
||||
import { getOpenClawStatus, getOpenClawDir, getOpenClawConfigDir, getOpenClawSkillsDir, ensureDir } from '../utils/paths';
|
||||
import { getOpenClawCliCommand } from '../utils/openclaw-cli';
|
||||
import { getSetting } from '../utils/store';
|
||||
import { getAllSettings, getSetting, resetSettings, setSetting, type AppSettings } from '../utils/store';
|
||||
import {
|
||||
saveProviderKeyToOpenClaw,
|
||||
removeProviderFromOpenClaw,
|
||||
@@ -49,6 +49,8 @@ import { updateSkillConfig, getSkillConfig, getAllSkillConfigs } from '../utils/
|
||||
import { whatsAppLoginManager } from '../utils/whatsapp-login';
|
||||
import { getProviderConfig } from '../utils/provider-registry';
|
||||
import { deviceOAuthManager, OAuthProviderType } from '../utils/device-oauth';
|
||||
import { applyProxySettings } from './proxy';
|
||||
import { proxyAwareFetch } from '../utils/proxy-fetch';
|
||||
import { getRecentTokenUsageHistory } from '../utils/token-usage';
|
||||
|
||||
/**
|
||||
@@ -100,6 +102,9 @@ export function registerIpcHandlers(
|
||||
// App handlers
|
||||
registerAppHandlers();
|
||||
|
||||
// Settings handlers
|
||||
registerSettingsHandlers(gatewayManager);
|
||||
|
||||
// UV handlers
|
||||
registerUvHandlers();
|
||||
|
||||
@@ -1478,7 +1483,7 @@ async function performProviderValidationRequest(
|
||||
): Promise<{ valid: boolean; error?: string }> {
|
||||
try {
|
||||
logValidationRequest(providerLabel, 'GET', url, headers);
|
||||
const response = await fetch(url, { headers });
|
||||
const response = await proxyAwareFetch(url, { headers });
|
||||
logValidationStatus(providerLabel, response.status);
|
||||
const data = await response.json().catch(() => ({}));
|
||||
return classifyAuthResponse(response.status, data);
|
||||
@@ -1553,7 +1558,7 @@ async function performChatCompletionsProbe(
|
||||
): Promise<{ valid: boolean; error?: string }> {
|
||||
try {
|
||||
logValidationRequest(providerLabel, 'POST', url, headers);
|
||||
const response = await fetch(url, {
|
||||
const response = await proxyAwareFetch(url, {
|
||||
method: 'POST',
|
||||
headers: { ...headers, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -1755,6 +1760,67 @@ function registerAppHandlers(): void {
|
||||
});
|
||||
}
|
||||
|
||||
function registerSettingsHandlers(gatewayManager: GatewayManager): void {
|
||||
const handleProxySettingsChange = async () => {
|
||||
const settings = await getAllSettings();
|
||||
await applyProxySettings(settings);
|
||||
if (gatewayManager.getStatus().state === 'running') {
|
||||
await gatewayManager.restart();
|
||||
}
|
||||
};
|
||||
|
||||
ipcMain.handle('settings:get', async (_, key: keyof AppSettings) => {
|
||||
return await getSetting(key);
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:getAll', async () => {
|
||||
return await getAllSettings();
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:set', async (_, key: keyof AppSettings, value: AppSettings[keyof AppSettings]) => {
|
||||
await setSetting(key, value as never);
|
||||
|
||||
if (
|
||||
key === 'proxyEnabled' ||
|
||||
key === 'proxyServer' ||
|
||||
key === 'proxyHttpServer' ||
|
||||
key === 'proxyHttpsServer' ||
|
||||
key === 'proxyAllServer' ||
|
||||
key === 'proxyBypassRules'
|
||||
) {
|
||||
await handleProxySettingsChange();
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:setMany', async (_, patch: Partial<AppSettings>) => {
|
||||
const entries = Object.entries(patch) as Array<[keyof AppSettings, AppSettings[keyof AppSettings]]>;
|
||||
for (const [key, value] of entries) {
|
||||
await setSetting(key, value as never);
|
||||
}
|
||||
|
||||
if (entries.some(([key]) =>
|
||||
key === 'proxyEnabled' ||
|
||||
key === 'proxyServer' ||
|
||||
key === 'proxyHttpServer' ||
|
||||
key === 'proxyHttpsServer' ||
|
||||
key === 'proxyAllServer' ||
|
||||
key === 'proxyBypassRules'
|
||||
)) {
|
||||
await handleProxySettingsChange();
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
|
||||
ipcMain.handle('settings:reset', async () => {
|
||||
await resetSettings();
|
||||
const settings = await getAllSettings();
|
||||
await handleProxySettingsChange();
|
||||
return { success: true, settings };
|
||||
});
|
||||
}
|
||||
function registerUsageHandlers(): void {
|
||||
ipcMain.handle('usage:recentTokenHistory', async (_, limit?: number) => {
|
||||
const safeLimit = typeof limit === 'number' && Number.isFinite(limit)
|
||||
|
||||
22
electron/main/proxy.ts
Normal file
22
electron/main/proxy.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { session } from 'electron';
|
||||
import { getAllSettings, type AppSettings } from '../utils/store';
|
||||
import { buildElectronProxyConfig } from '../utils/proxy';
|
||||
import { logger } from '../utils/logger';
|
||||
|
||||
export async function applyProxySettings(
|
||||
partialSettings?: Pick<AppSettings, 'proxyEnabled' | 'proxyServer' | 'proxyBypassRules'>
|
||||
): Promise<void> {
|
||||
const settings = partialSettings ?? await getAllSettings();
|
||||
const config = buildElectronProxyConfig(settings);
|
||||
|
||||
await session.defaultSession.setProxy(config);
|
||||
try {
|
||||
await session.defaultSession.closeAllConnections();
|
||||
} catch (error) {
|
||||
logger.debug('Failed to close existing connections after proxy update:', error);
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Applied Electron proxy (${config.mode}${config.proxyRules ? `, server=${config.proxyRules}` : ''}${config.proxyBypassRules ? `, bypass=${config.proxyBypassRules}` : ''})`
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user