(conn: SidecarConnection)
| 583 | }; |
| 584 | |
| 585 | const createWindow = async (conn: SidecarConnection) => { |
| 586 | installBearerAuthHeader(conn.baseUrl, conn.authToken); |
| 587 | |
| 588 | const existingWindow = liveMainWindow(); |
| 589 | const window = existingWindow ?? createMainBrowserWindow({ show: false }); |
| 590 | |
| 591 | // A supervised daemon can pass the health probe and still disappear before |
| 592 | // navigation begins. Treat that as a failed connection instead of leaving the |
| 593 | // user with a visible BrowserWindow that only shows the black background. |
| 594 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: Electron navigation rejects when the sidecar vanishes during startup |
| 595 | try { |
| 596 | await window.loadURL(webUrlForConnection(conn)); |
| 597 | if (!window.isDestroyed() && !window.isVisible()) window.show(); |
| 598 | } catch (error) { |
| 599 | // The window was closed (or the app is quitting) while this navigation was |
| 600 | // in flight. Nothing failed — there is just nowhere left to navigate. |
| 601 | if (isTeardownNavigationError(error, window)) { |
| 602 | log.info("Executor web UI load aborted while the window was closing"); |
| 603 | return; |
| 604 | } |
| 605 | log.error("Failed to load Executor web UI", error); |
| 606 | if (!existingWindow) destroyWindow(window); |
| 607 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: caller decides whether to fall back or surface startup failure |
| 608 | throw error; |
| 609 | } |
| 610 | }; |
| 611 | |
| 612 | const showPortInUseDialog = async (port: number) => { |
| 613 | await dialog.showMessageBox({ |
no test coverage detected