fix: use spawn with ELECTRON_RUN_AS_NODE for packaged server

- Replace fork() with spawn() + ELECTRON_RUN_AS_NODE=1 so the
  standalone server runs correctly inside the packaged app
- Set cwd to standalone directory for proper dependency resolution
- Show error dialog on startup failure instead of silent quit
- Add Chinese README (README_CN.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-06 21:33:27 +08:00
1 parent 337eebb53c
commit 2f40bd2c62
1 file changed
+25 -8
+25 -8
View File
@@ -1,10 +1,11 @@
import { app, BrowserWindow, nativeImage } from 'electron';
import { app, BrowserWindow, nativeImage, dialog } from 'electron';
import path from 'path';
import { fork, ChildProcess } from 'child_process';
import { spawn, ChildProcess } from 'child_process';
import net from 'net';
let mainWindow: BrowserWindow | null = null;
let serverProcess: ChildProcess | null = null;
let serverPort: number | null = null;
const isDev = !app.isPackaged;
@@ -51,14 +52,20 @@ async function waitForServer(port: number, timeout = 30000): Promise<void> {
function startServer(port: number): ChildProcess {
const serverPath = path.join(process.resourcesPath, 'standalone', 'server.js');
const child = fork(serverPath, [], {
// Use the bundled Node.js from Electron's helper
const nodePath = process.execPath;
const child = spawn(nodePath, [serverPath], {
env: {
...process.env,
PORT: String(port),
HOSTNAME: '127.0.0.1',
CLAUDE_GUI_DATA_DIR: app.getPath('userData'),
// Tell Electron's Node not to load the Electron module
ELECTRON_RUN_AS_NODE: '1',
},
stdio: 'pipe',
cwd: path.join(process.resourcesPath, 'standalone'),
});
child.stdout?.on('data', (data: Buffer) => {
@@ -131,9 +138,14 @@ app.whenReady().then(async () => {
console.log('Server is ready');
}
serverPort = port;
createWindow(port);
} catch (err) {
console.error('Failed to start:', err);
dialog.showErrorBox(
'CodePilot - Failed to Start',
`The internal server could not start.\n\n${err instanceof Error ? err.message : String(err)}\n\nPlease try restarting the application.`
);
app.quit();
}
});
@@ -150,12 +162,17 @@ app.on('window-all-closed', () => {
app.on('activate', async () => {
if (BrowserWindow.getAllWindows().length === 0) {
const port = isDev ? 3000 : await getPort();
if (!isDev && !serverProcess) {
serverProcess = startServer(port);
await waitForServer(port);
try {
if (!isDev && !serverProcess) {
const port = await getPort();
serverProcess = startServer(port);
await waitForServer(port);
serverPort = port;
}
createWindow(serverPort || 3000);
} catch (err) {
console.error('Failed to restart server:', err);
}
createWindow(port);
}
});