fix: Provider sync on every startup + sandbox fixes (v2.0.4)

Critical fixes:
- ALWAYS sync active AG X provider to endpoints.json on startup
  (previously only synced on first run, causing LS to use stale data)
- Add --no-sandbox to proxy process spawns (fixes SIGTRAP crash on Linux)
- Add --no-sandbox for all Electron modes (not just headless)
- Add --ag-reset flag to re-trigger welcome screen
- Bump version to 2.0.4

Root causes fixed:
1. endpoints.json was never updated after first-run, so LS used wrong provider
2. Electron child processes (translation proxy) crashed due to SUID sandbox
3. No way to re-show provider selection after initial setup
This commit is contained in:
admin
2026-05-23 00:23:46 +04:00
Unverified
parent 1a033e7ab4
commit b3c7be44e6
4 changed files with 11 additions and 9 deletions

View File

@@ -238,7 +238,7 @@ function ensureProxyStarted() {
// Use Electron's built-in Node.js to run our translation proxy // Use Electron's built-in Node.js to run our translation proxy
const proxyScript = path_1.default.join(__dirname, 'services', 'translationProxy.js'); const proxyScript = path_1.default.join(__dirname, 'services', 'translationProxy.js');
const nodeBin = process.execPath; const nodeBin = process.execPath;
_proxyProcess = (0, child_process_1.spawn)(nodeBin, [proxyScript], { _proxyProcess = (0, child_process_1.spawn)(nodeBin, ['--no-sandbox', proxyScript], {
stdio: 'ignore', stdio: 'ignore',
detached: true, detached: true,
env: { ...process.env } env: { ...process.env }

14
dist/main.js vendored
View File

@@ -81,12 +81,15 @@ let apiProxy;
const HEADLESS = process.env.ELECTRON_OZONE_PLATFORM_HINT === 'headless'; const HEADLESS = process.env.ELECTRON_OZONE_PLATFORM_HINT === 'headless';
// When set, skip LS startup and load this URL directly (for dev iteration). // When set, skip LS startup and load this URL directly (for dev iteration).
const DEV_URL = process.env.DEV_URL; const DEV_URL = process.env.DEV_URL;
const AG_RESET = process.argv.includes('--ag-reset');
if (HEADLESS) { if (HEADLESS) {
electron_1.app.commandLine.appendSwitch('ozone-platform', 'headless'); electron_1.app.commandLine.appendSwitch('ozone-platform', 'headless');
electron_1.app.commandLine.appendSwitch('headless'); electron_1.app.commandLine.appendSwitch('headless');
electron_1.app.commandLine.appendSwitch('disable-gpu'); electron_1.app.commandLine.appendSwitch('disable-gpu');
electron_1.app.commandLine.appendSwitch('no-sandbox'); electron_1.app.commandLine.appendSwitch('no-sandbox');
} }
// Always disable sandbox for Linux compatibility (SUID sandbox issues)
electron_1.app.commandLine.appendSwitch('no-sandbox');
if (!electron_1.app.commandLine.hasSwitch('remote-debugging-port')) { if (!electron_1.app.commandLine.hasSwitch('remote-debugging-port')) {
electron_1.app.commandLine.appendSwitch('remote-debugging-port', '0'); electron_1.app.commandLine.appendSwitch('remote-debugging-port', '0');
} }
@@ -218,17 +221,16 @@ electron_1.app
const csrf = crypto.randomUUID(); const csrf = crypto.randomUUID();
console.log(`Starting app (v${electron_1.app.getVersion()}) with dynamic port…`); console.log(`Starting app (v${electron_1.app.getVersion()}) with dynamic port…`);
// Check if first run BEFORE starting LS so we can configure provider first // Check if first run BEFORE starting LS so we can configure provider first
const isFirstRun = !fs_1.existsSync(providerService.configPath); const isFirstRun = !fs_1.existsSync(providerService.configPath) || AG_RESET;
if (isFirstRun && !HEADLESS) { if (isFirstRun && !HEADLESS) {
console.log('[Welcome] First run detected — showing provider choice screen'); console.log('[Welcome] First run detected — showing provider choice screen');
await showWelcomeScreen('about:blank'); await showWelcomeScreen('about:blank');
console.log('[Welcome] User selected provider:', providerService.getActiveProvider()); console.log('[Welcome] User selected provider:', providerService.getActiveProvider());
// Sync to endpoints.json (for Google, the handler already set the endpoint;
// for custom, the settings save handler synced. This is a safety sync.)
if (providerService.getActiveProvider() !== 'google_gemini') {
syncProviderToEndpoints(providerService);
}
} }
// ALWAYS sync the active AG X provider to endpoints.json on every startup.
// This ensures the Language Server reads the correct provider config.
console.log('[Sync] Syncing active provider to endpoints.json on startup');
syncProviderToEndpoints(providerService);
let handle; let handle;
const targetPort = Number(process.env.JETSKI_LS_PORT) || constants_1.DYNAMIC_PORT; const targetPort = Number(process.env.JETSKI_LS_PORT) || constants_1.DYNAMIC_PORT;
try { try {

View File

@@ -71,7 +71,7 @@ class ApiProxy {
// Use Electron's Node.js binary to run our translation proxy // Use Electron's Node.js binary to run our translation proxy
const proxyScript = path.join(__dirname, 'translationProxy.js'); const proxyScript = path.join(__dirname, 'translationProxy.js');
const nodeBin = process.execPath; const nodeBin = process.execPath;
this.proxyProcess = child_process.spawn(nodeBin, [proxyScript], { this.proxyProcess = child_process.spawn(nodeBin, ['--no-sandbox', proxyScript], {
stdio: ['ignore', 'pipe', 'pipe'], stdio: ['ignore', 'pipe', 'pipe'],
detached: false, detached: false,
env: { ...process.env }, env: { ...process.env },

View File

@@ -1,7 +1,7 @@
{ {
"name": "ag-x", "name": "ag-x",
"productName": "AG X", "productName": "AG X",
"version": "2.0.3", "version": "2.0.4",
"description": "AG X - Agentic Desktop Application", "description": "AG X - Agentic Desktop Application",
"homepage": "https://ag-x.dev", "homepage": "https://ag-x.dev",
"author": { "author": {