(version: string)
| 923 | }; |
| 924 | |
| 925 | const promptInstallUpdate = async (version: string) => { |
| 926 | if (updateDialogOpen) return; |
| 927 | updateDialogOpen = true; |
| 928 | // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: dialog wrapper guarantees the open flag clears |
| 929 | try { |
| 930 | const response = await dialog.showMessageBox({ |
| 931 | type: "info", |
| 932 | title: "Update ready", |
| 933 | message: `Executor ${version} is ready to install.`, |
| 934 | detail: "Restart now to apply the update, or keep working — we'll prompt again later.", |
| 935 | buttons: ["Restart now", "Later"], |
| 936 | defaultId: 0, |
| 937 | cancelId: 1, |
| 938 | }); |
| 939 | if (response.response === 0) { |
| 940 | // Stop the sidecar cleanly before Squirrel.Mac swaps the bundle. A |
| 941 | // supervised daemon is left running — it's independent of this bundle. |
| 942 | stopSupervisedMonitor(); |
| 943 | if (connection) { |
| 944 | await stopConnection(connection); |
| 945 | connection = null; |
| 946 | } |
| 947 | autoUpdater.quitAndInstall(false, true); |
| 948 | return; |
| 949 | } |
| 950 | declinedUpdateVersion = version; |
| 951 | } finally { |
| 952 | updateDialogOpen = false; |
| 953 | } |
| 954 | }; |
| 955 | |
| 956 | // Re-check periodically so a long-running session picks up releases |
| 957 | // without requiring a quit + relaunch. The boot-time check still runs; |
no test coverage detected