Files
hermes-agent/apps/desktop/electron/backend-resolution.ts
Austin Pickett dfcbef358a fix(desktop): find a source install through its published user-bin launcher
The PM rework dropped the resolver's "existing hermes on PATH" rung, so
Desktop only accepts HERMES_DESKTOP_HERMES or $HERMES_HOME/hermes-agent. A
healthy install elsewhere (install.sh --dir, a setup-hermes.sh clone) now
falls to bootstrap-needed and the first-run choice, offering to install a
second copy. The old rung also read raw process.env.PATH, which a
Finder/Dock launch inherits without ~/.local/bin.

Add a rung before bootstrap-needed: probe the launcher published at its
fixed user-bin location (~/.local/bin or $HERMES_HOME/bin; Windows:
%LOCALAPPDATA%\hermes\bin), read the install directory its --version
reports, and resolve that root through resolveSourceInstallationBackend,
the same validated path ACTIVE_HERMES_ROOT uses. HERMES_DESKTOP_IGNORE_EXISTING
and repair requests still skip it, and a miss is now logged instead of
silent. The launcher lookup is shared with resolveInstallationLauncher.

Fixes #73014

Co-authored-by: JonthanaHanh <92574114+JonthanaHanh@users.noreply.github.com>
2026-09-29 22:57:06 -04:00

37 lines
1.4 KiB
TypeScript

/**
* HERMES_DESKTOP_IGNORE_EXISTING=1 (`hermes desktop --ignore-existing`) keeps
* Desktop off installed runtimes (ACTIVE_HERMES_ROOT, or the install a
* published user-bin launcher reports). Backend resolution
* then falls through to bootstrap-needed, which shows the first-run choice
* (connect a remote, or install) instead of starting a local serve.
*
* The bundled payload, HERMES_DESKTOP_HERMES_ROOT, an unpackaged checkout and
* HERMES_DESKTOP_HERMES resolve before this rung and are not affected.
*
* A runtime this launch installed is always used. Skipping it would send the
* post-install re-resolve (and every later resolve) back to the installer.
*/
export function createInstalledRuntimeGate(env: NodeJS.ProcessEnv, log: (message: string) => void) {
let installedThisLaunch = false
return {
/** The ACTIVE_HERMES_ROOT rung: probe the installed runtime unless the flag skips it. */
async resolve<T>(root: string, probe: () => Promise<T | null>): Promise<T | null> {
if (env.HERMES_DESKTOP_IGNORE_EXISTING === '1' && !installedThisLaunch) {
log(`[bootstrap] HERMES_DESKTOP_IGNORE_EXISTING=1; skipping the installed runtime at ${root}`)
return null
}
return probe()
},
/** Re-resolve after a successful bootstrap; the new runtime is exempt from the flag. */
afterInstall<T>(resolveBackend: () => Promise<T>): Promise<T> {
installedThisLaunch = true
return resolveBackend()
}
}
}