(version: string)
| 875 | }; |
| 876 | |
| 877 | const promptInstallUpdate = async (version: string) => { |
| 878 | if (updateDialogOpen) return; |
| 879 | updateDialogOpen = true; |
| 880 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: dialog wrapper guarantees the open flag clears |
| 881 | try { |
| 882 | const response = await dialog.showMessageBox({ |
| 883 | type: "info", |
| 884 | title: "Update ready", |
| 885 | message: `Executor ${version} is ready to install.`, |
| 886 | detail: "Restart now to apply the update, or keep working — we'll prompt again later.", |
| 887 | buttons: ["Restart now", "Later"], |
| 888 | defaultId: 0, |
| 889 | cancelId: 1, |
| 890 | }); |
| 891 | if (response.response === 0) { |
| 892 | // Stop the sidecar cleanly before Squirrel.Mac swaps the bundle. A |
| 893 | // supervised daemon is left running — it's independent of this bundle. |
| 894 | stopSupervisedMonitor(); |
| 895 | if (connection) { |
| 896 | await stopConnection(connection); |
| 897 | connection = null; |
| 898 | } |
| 899 | autoUpdater.quitAndInstall(false, true); |
| 900 | return; |
| 901 | } |
| 902 | declinedUpdateVersion = version; |
| 903 | } finally { |
| 904 | updateDialogOpen = false; |
| 905 | } |
| 906 | }; |
| 907 | |
| 908 | // Re-check periodically so a long-running session picks up releases |
| 909 | // without requiring a quit + relaunch. The boot-time check still runs; |
no test coverage detected