Skip to content

Commit 1fc3d3f

Browse files
committed
Capture server logs on startup failure and fix Windows spawn
- Pipe stdout/stderr from the spawned server process (capped at 8KB) so logs are available when the health check times out - Return captured logs in the IPC error response - Add expandable 'Show logs' viewer in the error banner UI - Remove PowerShell wrapper on Windows - spawn opencode.exe directly with windowsHide:true (fixes server never starting on Windows) - Exit code 0 no longer overrides the health timeout message (normal for binaries that daemonize)
1 parent 0ef7b2e commit 1fc3d3f

1 file changed

Lines changed: 11 additions & 23 deletions

File tree

opencode-bridge.mjs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,6 @@ export function setupOpenCodeBridge(ipcMain, getMainWindow) {
12771277

12781278
// Spawn detached so the server survives app close.
12791279
// Use piped stdio so we can capture logs on startup failure.
1280-
const isWindows = process.platform === "win32";
12811280
const serverArgs = ["serve", "--port", String(LOCAL_SERVER_PORT)];
12821281
console.log(
12831282
`[opencode-bridge] Spawning: ${binary} ${serverArgs.join(" ")} (platform: ${process.platform})`,
@@ -1295,27 +1294,12 @@ export function setupOpenCodeBridge(ipcMain, getMainWindow) {
12951294
}
12961295
};
12971296

1298-
let child;
1299-
if (isWindows) {
1300-
// On Windows, run via powershell to avoid visible console windows
1301-
const cmd = `& '${binary.replace(/'/g, "''")}' ${serverArgs.join(" ")}`;
1302-
child = spawn(
1303-
"powershell.exe",
1304-
["-WindowStyle", "Hidden", "-Command", cmd],
1305-
{
1306-
detached: true,
1307-
stdio: ["ignore", "pipe", "pipe"],
1308-
windowsHide: true,
1309-
env: { ...process.env },
1310-
},
1311-
);
1312-
} else {
1313-
child = spawn(binary, serverArgs, {
1314-
detached: true,
1315-
stdio: ["ignore", "pipe", "pipe"],
1316-
env: { ...process.env },
1317-
});
1318-
}
1297+
const child = spawn(binary, serverArgs, {
1298+
detached: true,
1299+
stdio: ["ignore", "pipe", "pipe"],
1300+
windowsHide: true,
1301+
env: { ...process.env },
1302+
});
13191303

13201304
if (child.stdout) child.stdout.on("data", appendLog);
13211305
if (child.stderr) child.stderr.on("data", appendLog);
@@ -1356,7 +1340,11 @@ export function setupOpenCodeBridge(ipcMain, getMainWindow) {
13561340
let errorMsg = healthErr.message ?? String(healthErr);
13571341
if (spawnError) {
13581342
errorMsg = `Spawn error: ${spawnError.message}`;
1359-
} else if (earlyExitCode !== null) {
1343+
} else if (earlyExitCode !== null && earlyExitCode !== 0) {
1344+
// Non-zero exit means the server actually crashed.
1345+
// Exit code 0 is normal when the binary daemonizes (spawns a
1346+
// background server and the launcher exits cleanly), so we
1347+
// keep the health-check timeout message instead.
13601348
errorMsg = `Server process exited with code ${earlyExitCode}`;
13611349
}
13621350
return {

0 commit comments

Comments
 (0)