feat(core): isolate dev and production environments

- Add IS_DEV_ENVIRONMENT flag to paths.ts for automatic detection
- Dev uses 'Gemini Nexus Dev' app data dir and '.geminiNexus-agent-dev' agent dir
- Dev proxy defaults to port 8046, production stays on 8045
- Move app.setName() before packetLogPath to ensure correct userData path
- Config, DB, logs, and ORPC packets fully isolated between dev and prod
This commit is contained in:
Gemini Nexus Bot committed 2026-05-02 00:28:22 -03:00
1 parent bf5a42c03e
commit 5c44a622a8
4 files changed
+38 -22

No files matched your search

+8 -6
View File
@@ -30,6 +30,12 @@ import { ConfigManager } from './ipc/config/manager';
import { AppConfig } from './types/config'; import { AppConfig } from './types/config';
import { isAutoStartLaunch, syncAutoStart } from './utils/autoStart'; import { isAutoStartLaunch, syncAutoStart } from './utils/autoStart';
import { safeStringifyPacket } from './utils/sensitiveDataMasking'; import { safeStringifyPacket } from './utils/sensitiveDataMasking';
import { IS_DEV_ENVIRONMENT } from './utils/paths';
// Set app name early so Electron's userData path reflects the environment
if (IS_DEV_ENVIRONMENT) {
app.setName('Gemini Nexus Dev');
}
const packetLogPath = path.join(app.getPath('userData'), 'orpc_packets.log'); const packetLogPath = path.join(app.getPath('userData'), 'orpc_packets.log');
@@ -63,7 +69,7 @@ if (squirrelStartup) {
process.exit(0); process.exit(0);
} }
const inDevelopment = process.env.NODE_ENV === 'development'; const inDevelopment = IS_DEV_ENVIRONMENT;
const debugHttpProxy = process.env.http_proxy?.trim() || process.env.HTTP_PROXY?.trim(); const debugHttpProxy = process.env.http_proxy?.trim() || process.env.HTTP_PROXY?.trim();
const debugHttpsProxy = process.env.https_proxy?.trim() || process.env.HTTPS_PROXY?.trim(); const debugHttpsProxy = process.env.https_proxy?.trim() || process.env.HTTPS_PROXY?.trim();
const debugNoProxy = process.env.no_proxy?.trim() || process.env.NO_PROXY?.trim(); const debugNoProxy = process.env.no_proxy?.trim() || process.env.NO_PROXY?.trim();
@@ -167,11 +173,7 @@ function showWindowsInstallNoticeIfNeeded() {
}); });
} }
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged; const isDev = IS_DEV_ENVIRONMENT;
if (isDev) {
app.setName('Gemini Nexus Dev');
}
const gotSingleInstanceLock = app.requestSingleInstanceLock(); const gotSingleInstanceLock = app.requestSingleInstanceLock();
+5 -6
View File
@@ -10,16 +10,15 @@ import os from 'os';
let sentryEnabled = false; let sentryEnabled = false;
try { try {
const home = os.homedir(); const home = os.homedir();
const isDev = process.env.NODE_ENV === 'development';
const appName = isDev ? 'Gemini Nexus Dev' : 'Gemini Nexus';
let appDataPath = ''; let appDataPath = '';
if (process.platform === 'win32') { if (process.platform === 'win32') {
appDataPath = path.join( appDataPath = path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), appName);
process.env.APPDATA || path.join(home, 'AppData', 'Roaming'),
'Gemini Nexus',
);
} else if (process.platform === 'darwin') { } else if (process.platform === 'darwin') {
appDataPath = path.join(home, 'Library', 'Application Support', 'Gemini Nexus'); appDataPath = path.join(home, 'Library', 'Application Support', appName);
} else { } else {
appDataPath = path.join(home, '.config', 'Gemini Nexus'); appDataPath = path.join(home, '.config', appName);
} }
const configPath = path.join(appDataPath, 'gui_config.json'); const configPath = path.join(appDataPath, 'gui_config.json');
+6 -1
View File
@@ -9,11 +9,16 @@ import { ProxyConfig } from '../types/config';
import { setServerConfig } from './server-config'; import { setServerConfig } from './server-config';
import { registerApiLogging } from './logging/api-logging.plugin'; import { registerApiLogging } from './logging/api-logging.plugin';
import { IS_DEV_ENVIRONMENT } from '../utils/paths';
let app: NestFastifyApplication | null = null; let app: NestFastifyApplication | null = null;
let currentPort: number = 0; let currentPort: number = 0;
/** Default port: 8046 in development, 8045 in production */
const DEFAULT_PORT = IS_DEV_ENVIRONMENT ? 8046 : 8045;
export async function bootstrapNestServer(config: ProxyConfig): Promise<boolean> { export async function bootstrapNestServer(config: ProxyConfig): Promise<boolean> {
const port = config.port || 8045; const port = config.port || DEFAULT_PORT;
if (app) { if (app) {
logger.info('NestJS server already running.'); logger.info('NestJS server already running.');
return true; return true;
+19 -9
View File
@@ -3,6 +3,16 @@ import os from 'os';
import fs from 'fs'; import fs from 'fs';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
/**
* Detects whether the app is running in development mode.
* Uses NODE_ENV as the single source of truth. This is evaluated once
* at module load time so every consumer gets a consistent answer.
*/
export const IS_DEV_ENVIRONMENT = process.env.NODE_ENV === 'development';
/** Directory name suffix applied in development to isolate from production data. */
const DEV_SUFFIX = ' Dev';
/** /**
* Checks if the current platform is WSL. * Checks if the current platform is WSL.
* @returns {boolean} True if the current platform is WSL, false otherwise. * @returns {boolean} True if the current platform is WSL, false otherwise.
@@ -75,29 +85,29 @@ function getWindowsUser(): string {
export function getAppDataDir(): string { export function getAppDataDir(): string {
const home = os.homedir(); const home = os.homedir();
const appName = IS_DEV_ENVIRONMENT ? `Gemini Nexus${DEV_SUFFIX}` : 'Gemini Nexus';
if (isWsl()) { if (isWsl()) {
const winUser = getWindowsUser(); const winUser = getWindowsUser();
return `/mnt/c/Users/${winUser}/AppData/Roaming/GeminiNexus`; const wslName = IS_DEV_ENVIRONMENT ? 'GeminiNexusDev' : 'GeminiNexus';
return `/mnt/c/Users/${winUser}/AppData/Roaming/${wslName}`;
} }
switch (process.platform) { switch (process.platform) {
case 'darwin': case 'darwin':
return path.join(home, 'Library', 'Application Support', 'Gemini Nexus'); return path.join(home, 'Library', 'Application Support', appName);
case 'win32': case 'win32':
return path.join( return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), appName);
process.env.APPDATA || path.join(home, 'AppData', 'Roaming'),
'Gemini Nexus',
);
case 'linux': case 'linux':
return path.join(home, '.config', 'Gemini Nexus'); return path.join(home, '.config', appName);
default: default:
return path.join(home, '.geminiNexus'); return path.join(home, IS_DEV_ENVIRONMENT ? '.geminiNexusDev' : '.geminiNexus');
} }
} }
export function getAgentDir(): string { export function getAgentDir(): string {
return path.join(os.homedir(), '.geminiNexus-agent'); const dirName = IS_DEV_ENVIRONMENT ? '.geminiNexus-agent-dev' : '.geminiNexus-agent';
return path.join(os.homedir(), dirName);
} }
export function getAccountsFilePath(): string { export function getAccountsFilePath(): string {