mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
fix(desktop): force app exit after update/uninstall handoff on macOS
Some checks are pending
CI / Detect affected areas (push) Waiting to run
CI / Python tests (push) Blocked by required conditions
CI / Python lints (push) Blocked by required conditions
CI / TypeScript (push) Blocked by required conditions
CI / Docs Site (push) Blocked by required conditions
CI / Deny unrelated histories (push) Blocked by required conditions
CI / Check contributors (push) Blocked by required conditions
CI / Check uv.lock (push) Blocked by required conditions
CI / Lint Docker scripts (push) Blocked by required conditions
CI / Build&Test Docker image (push) Blocked by required conditions
CI / Supply-chain scan (push) Blocked by required conditions
CI / OSV scan (push) Waiting to run
CI / All required checks pass (push) Blocked by required conditions
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
Some checks are pending
CI / Detect affected areas (push) Waiting to run
CI / Python tests (push) Blocked by required conditions
CI / Python lints (push) Blocked by required conditions
CI / TypeScript (push) Blocked by required conditions
CI / Docs Site (push) Blocked by required conditions
CI / Deny unrelated histories (push) Blocked by required conditions
CI / Check contributors (push) Blocked by required conditions
CI / Check uv.lock (push) Blocked by required conditions
CI / Lint Docker scripts (push) Blocked by required conditions
CI / Build&Test Docker image (push) Blocked by required conditions
CI / Supply-chain scan (push) Blocked by required conditions
CI / OSV scan (push) Waiting to run
CI / All required checks pass (push) Blocked by required conditions
Deploy Site / deploy-vercel (push) Waiting to run
Deploy Site / deploy-docs (push) Waiting to run
On macOS app.quit() closes windows but window-all-closed deliberately keeps the process alive (Dock convention). Every detached hand-off (update swap, relaunch, Windows bootstrap recovery, uninstall cleanup) waits for the desktop PID to exit before replacing/removing the bundle — so the process never dying means the script spins its full PID-wait and the user sees a blank app, or an uninstall that appears to do nothing. Add a module-level isQuittingForHandoff flag, set before every hand-off app.quit(); window-all-closed then quits on all platforms when it's set. Covers all five hand-off sites including the Linux relaunch path.
This commit is contained in:
parent
e54bedd8ea
commit
376d021fee
2 changed files with 23 additions and 1 deletions
|
|
@ -1971,6 +1971,16 @@ async function readCommitLog(cwd, branch) {
|
|||
|
||||
let updateInFlight = false
|
||||
|
||||
// Set to true when the desktop is about to quit so a detached swap/install/
|
||||
// uninstall script can take over. On macOS, app.quit() closes windows but
|
||||
// window-all-closed deliberately keeps the process alive (standard Electron
|
||||
// macOS convention). Without this flag the process never exits — the detached
|
||||
// hand-off script spins its PID-wait for the full timeout, and the user sees a
|
||||
// blank app with no window (and an uninstall that appears to do nothing). When
|
||||
// set, window-all-closed calls app.quit() on every platform so the process
|
||||
// actually dies and the hand-off script can proceed immediately.
|
||||
let isQuittingForHandoff = false
|
||||
|
||||
// Resolve the staged updater binary. The Tauri installer copies itself to
|
||||
// HERMES_HOME/hermes-setup.exe on a successful install (see
|
||||
// apps/bootstrap-installer paths::copy_self_to_hermes_home). That binary owns
|
||||
|
|
@ -2226,6 +2236,7 @@ async function applyUpdates(opts = {}) {
|
|||
// appears), THEN quit to release the venv shim. The updater rebuilds and
|
||||
// relaunches us when it's done. (#50419 — a 600ms quit looked like a crash
|
||||
// and lured users into the #50238 relaunch loop.)
|
||||
isQuittingForHandoff = true
|
||||
setTimeout(() => {
|
||||
app.quit()
|
||||
}, UPDATE_HANDOFF_DWELL_MS)
|
||||
|
|
@ -2283,6 +2294,7 @@ async function handOffWindowsBootstrapRecovery(reason) {
|
|||
// Same dwell as the in-app update hand-off (#50419): give the updater's
|
||||
// window time to appear before we vanish, so the recovery doesn't look like
|
||||
// a crash and provoke a mid-recovery relaunch.
|
||||
isQuittingForHandoff = true
|
||||
setTimeout(() => {
|
||||
app.quit()
|
||||
}, UPDATE_HANDOFF_DWELL_MS)
|
||||
|
|
@ -2490,6 +2502,7 @@ async function applyUpdatesPosixInApp() {
|
|||
`[updates] launched linux relaunch: ${scriptPath} -> ${process.execPath} ` +
|
||||
`(args=${relaunchArgs.length}, env=${Object.keys(relaunchEnv).length})`
|
||||
)
|
||||
isQuittingForHandoff = true
|
||||
setTimeout(() => app.quit(), UPDATE_HANDOFF_DWELL_MS)
|
||||
return { ok: true, handedOff: true }
|
||||
} catch (err) {
|
||||
|
|
@ -2595,6 +2608,7 @@ fi
|
|||
child.unref()
|
||||
rememberLog(`[updates] launched mac swap+relaunch: ${scriptPath} (${rebuiltApp} -> ${targetApp})`)
|
||||
|
||||
isQuittingForHandoff = true
|
||||
setTimeout(() => app.quit(), 600)
|
||||
return { ok: true, handedOff: true, rebuiltApp, targetApp }
|
||||
}
|
||||
|
|
@ -7359,6 +7373,7 @@ async function runDesktopUninstall(mode) {
|
|||
|
||||
// Give the renderer a beat to show its "uninstalling…" state, then quit so
|
||||
// the venv python shim + app bundle unlock and the cleanup script can run.
|
||||
isQuittingForHandoff = true
|
||||
setTimeout(() => app.quit(), 800)
|
||||
return { ok: true, mode, willRemoveAppBundle: Boolean(removeBundle), scriptPath }
|
||||
}
|
||||
|
|
@ -7564,5 +7579,11 @@ app.on('before-quit', () => {
|
|||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
// macOS convention: keep the process alive in the Dock when the user closes
|
||||
// the last window. But when we're handing off to a detached updater / swap /
|
||||
// uninstall script, the process MUST exit so the script can replace or remove
|
||||
// the bundle and relaunch — without this the script's PID-wait spins to its
|
||||
// full timeout and the user is left with an invisible app (or an uninstall
|
||||
// that appears to do nothing).
|
||||
if (process.platform !== 'darwin' || isQuittingForHandoff) app.quit()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ AUTHOR_MAP = {
|
|||
"prathamesh290504@gmail.com": "PRATHAMESH75", # PR #37550 salvage (ExecStopPost cgroup-orphan reaper to unblock systemd restart; #37454)
|
||||
"der@konsi.org": "konsisumer", # PR #19608 salvage (read-modify-write merge in write_credential_pool to preserve concurrently-added credentials; #19566)
|
||||
"linyubin@users.noreply.github.com": "linyubin", # PR #50228 salvage (eager fallback on persistent transport timeout/overloaded; #22277)
|
||||
"bradhallett@users.noreply.github.com": "bradhallett", # PR #46948 salvage (force app exit after update/uninstall handoff on macOS; #46948)
|
||||
"65363919+coygeek@users.noreply.github.com": "coygeek", # PR #37951 salvage (fail closed when provider env blocklist import fails; #37950)
|
||||
"5261694+djstunami@users.noreply.github.com": "djstunami", # PR #5316 salvage / co-author (suppress transient check_fn flakes so subagents keep file/terminal tools; #21658 / #5304)
|
||||
"jmmaloney4@gmail.com": "jmmaloney4", # PR #25206 salvage (re-select credential pool on primary runtime restore; #25205)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue