mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-12 08:51:53 +00:00
* fix(install): self-heal a stuck Electron download on the desktop build The desktop build downloads Electron (~114MB) from GitHub. A corrupt cached zip, or a blocked/throttled GitHub release host (the repeating "retrying" log), hard-failed the install — and install.sh had no recovery at all while install.ps1 / `hermes desktop` only purged the cache. All three build paths now escalate on a failed `npm run pack`: GitHub → purge corrupt electron-*.zip + stale *-unpacked and retry → one retry via a public Electron mirror (npmmirror.com). @electron/get SHASUM-verifies the download, and a user-pinned ELECTRON_MIRROR is always respected (never overridden). Adds a bash clear_electron_build_cache()/_desktop_pack() to mirror the existing PowerShell/Python helpers. * test(install): cover the Electron mirror fallback Verify `hermes desktop` falls back to a mirror when the cache purge finds nothing, and that a user-pinned ELECTRON_MIRROR is respected (no extra attempt, not overridden). * docs(desktop): troubleshoot a stuck Electron download Document the automatic cache-purge + mirror fallback, how to pin your own ELECTRON_MIRROR, and how to clear a corrupt cached zip by hand. * docs(install): correct the Electron mirror trust framing The mirror-fallback comments and the desktop troubleshooting doc implied `@electron/get`'s SHASUM check makes the npmmirror.com download safe against tampering. It doesn't: the SHASUMS256.txt is fetched from the same mirror, so the check guards against a corrupt/partial download, not a compromised mirror. Reframe all four surfaces (install.sh, install.ps1, `hermes desktop`, and the docs) to state the trust trade-off honestly — npmmirror.com is the de-facto Electron community mirror, we only fall back to it after the canonical GitHub download fails, and a user-pinned ELECTRON_MIRROR is never overridden. No behavior change. --------- Co-authored-by: xxxigm <tuancanhnguyen706@gmail.com>
This commit is contained in:
parent
5750d058fa
commit
ba44de06da
5 changed files with 222 additions and 11 deletions
|
|
@ -2248,6 +2248,24 @@ function Install-Desktop {
|
|||
$code = $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
# Still failing and the user hasn't pinned their own mirror: GitHub's
|
||||
# Electron release host is likely blocked/throttled (the repeating
|
||||
# "retrying" log). Retry once via npmmirror.com — the de-facto Electron
|
||||
# community mirror (Alibaba). @electron/get SHASUM-checks the download,
|
||||
# but the SHASUMS come from the same mirror, so that guards against a
|
||||
# corrupt/partial download, NOT a compromised mirror: an explicit trust
|
||||
# trade-off we only make AFTER the canonical GitHub download has failed,
|
||||
# and we never override a user-pinned ELECTRON_MIRROR.
|
||||
if ($code -ne 0 -and -not $env:ELECTRON_MIRROR) {
|
||||
$prevMirror = $env:ELECTRON_MIRROR
|
||||
$env:ELECTRON_MIRROR = "https://npmmirror.com/mirrors/electron/"
|
||||
Write-Warn "Desktop build still failing - the Electron download from GitHub looks blocked."
|
||||
Write-Warn "Retrying once via a public Electron mirror ($($env:ELECTRON_MIRROR)):"
|
||||
Write-Info " (set ELECTRON_MIRROR yourself to use a different/trusted mirror)"
|
||||
& $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
|
||||
$code = $LASTEXITCODE
|
||||
$env:ELECTRON_MIRROR = $prevMirror
|
||||
}
|
||||
$ErrorActionPreference = $prevEAP
|
||||
if ($code -ne 0) {
|
||||
$errText = Get-Content $buildLog -Raw -ErrorAction SilentlyContinue
|
||||
|
|
|
|||
|
|
@ -2281,6 +2281,93 @@ postinstall_mode() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Clear the cached Electron download + any half-written unpacked output so the
|
||||
# next `npm run pack` re-downloads and re-stages from scratch. A corrupt zip in
|
||||
# the per-user Electron download cache - most often a partial/resumed download
|
||||
# that leaves concatenated junk - makes electron-builder's `unpack-electron`
|
||||
# extract a tree MISSING the electron binary, so the `electron`->`Hermes` rename
|
||||
# dies with ENOENT and every re-run repeats the broken extraction forever. This
|
||||
# is the bash sibling of install.ps1's Clear-ElectronBuildCache and the Python
|
||||
# _purge_electron_build_cache() used by `hermes desktop`; install.sh was the only
|
||||
# build path lacking it. Echoes the removed paths (one per line); best-effort.
|
||||
clear_electron_build_cache() {
|
||||
local desktop_dir="$1"
|
||||
local removed=""
|
||||
|
||||
# Per-user Electron download cache dirs, honoring the overrides @electron/get
|
||||
# respects, then the platform defaults (macOS: ~/Library/Caches/electron,
|
||||
# Linux: $XDG_CACHE_HOME/electron or ~/.cache/electron).
|
||||
local cache_dirs=()
|
||||
[ -n "${electron_config_cache:-}" ] && cache_dirs+=("$electron_config_cache")
|
||||
[ -n "${ELECTRON_CACHE:-}" ] && cache_dirs+=("$ELECTRON_CACHE")
|
||||
if [ "$OS" = "macos" ]; then
|
||||
cache_dirs+=("$HOME/Library/Caches/electron")
|
||||
else
|
||||
[ -n "${XDG_CACHE_HOME:-}" ] && cache_dirs+=("$XDG_CACHE_HOME/electron")
|
||||
cache_dirs+=("$HOME/.cache/electron")
|
||||
fi
|
||||
|
||||
local dir zip
|
||||
for dir in "${cache_dirs[@]}"; do
|
||||
[ -d "$dir" ] || continue
|
||||
# Recurse: the bad copy may be the top-level zip OR a copy inside an
|
||||
# @electron/get hash subdir.
|
||||
while IFS= read -r zip; do
|
||||
[ -n "$zip" ] || continue
|
||||
if rm -f "$zip" 2>/dev/null; then
|
||||
removed="$removed$zip
|
||||
"
|
||||
fi
|
||||
done <<EOF
|
||||
$(find "$dir" -type f -name 'electron-*.zip' 2>/dev/null)
|
||||
EOF
|
||||
done
|
||||
|
||||
# A half-written unpacked dir from an interrupted prior pack poisons the
|
||||
# rename even after the zip is fixed (mac-arm64-unpacked / linux-unpacked).
|
||||
local release_dir="$desktop_dir/release"
|
||||
if [ -d "$release_dir" ]; then
|
||||
local unpacked
|
||||
while IFS= read -r unpacked; do
|
||||
[ -n "$unpacked" ] || continue
|
||||
if rm -rf "$unpacked" 2>/dev/null; then
|
||||
removed="$removed$unpacked
|
||||
"
|
||||
fi
|
||||
done <<EOF
|
||||
$(find "$release_dir" -maxdepth 1 -type d -name '*-unpacked' 2>/dev/null)
|
||||
EOF
|
||||
fi
|
||||
|
||||
printf '%s' "$removed"
|
||||
}
|
||||
|
||||
# Run the desktop pack in $1 (the apps/desktop dir). `npm run pack` = tsc +
|
||||
# vite build + electron-builder --dir, producing an unpacked app for the
|
||||
# current OS. Signing auto-discovery is disabled so electron-builder falls back
|
||||
# to an ad-hoc signature instead of grabbing an unrelated Developer ID from the
|
||||
# keychain (a real signed/notarized .dmg needs Apple credentials — a separate
|
||||
# release concern). Optional $2 = an ELECTRON_MIRROR base URL for this attempt,
|
||||
# used as a fallback when the default GitHub release download is blocked.
|
||||
_desktop_pack() {
|
||||
local desktop_dir="$1"
|
||||
local mirror="${2:-}"
|
||||
if [ -n "$mirror" ]; then
|
||||
( cd "$desktop_dir" && ELECTRON_MIRROR="$mirror" CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack )
|
||||
else
|
||||
( cd "$desktop_dir" && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack )
|
||||
fi
|
||||
}
|
||||
|
||||
# Public Electron mirror used as a last-resort fallback when GitHub's release
|
||||
# host is blocked/throttled (the repeating "retrying" symptom). npmmirror.com is
|
||||
# the de-facto Electron community mirror (Alibaba). @electron/get SHASUM-checks
|
||||
# the download, but the SHASUMS come from the same mirror — that guards against a
|
||||
# corrupt/partial download, NOT a compromised mirror. Reaching for it is an
|
||||
# explicit trust trade-off we only make AFTER the canonical GitHub download has
|
||||
# failed, and we never override a user-pinned ELECTRON_MIRROR.
|
||||
DESKTOP_ELECTRON_FALLBACK_MIRROR="https://npmmirror.com/mirrors/electron/"
|
||||
|
||||
# Build apps/desktop into a launchable native app. Mirrors install.ps1's
|
||||
# Install-Desktop: a root-level npm install so the apps/* workspace resolves
|
||||
# the desktop's own deps (Electron ~150MB), then `npm run pack`
|
||||
|
|
@ -2338,18 +2425,53 @@ install_desktop() {
|
|||
}
|
||||
log_success "Desktop workspace dependencies installed"
|
||||
|
||||
# 2. Build. `npm run pack` = tsc + vite build + electron-builder --dir,
|
||||
# producing an unpacked app for the current OS. We disable signing
|
||||
# auto-discovery so electron-builder falls back to an ad-hoc signature
|
||||
# instead of grabbing an unrelated Developer ID from the keychain; a
|
||||
# real signed/notarized .dmg needs Apple credentials and is a separate
|
||||
# release concern.
|
||||
# 2. Build, with up to three escalating attempts so a transient/blocked
|
||||
# Electron download self-heals instead of failing the whole install:
|
||||
# a) plain `npm run pack` (downloads Electron from GitHub),
|
||||
# b) on failure, purge a corrupt cached zip + stale unpacked dir and
|
||||
# retry (matches install.ps1 / `hermes desktop`),
|
||||
# c) on still-failing, fall back to a public Electron mirror — this is
|
||||
# the GitHub-blocked/throttled case (the repeating "retrying" log).
|
||||
log_info "Building desktop app (this takes 1-3 minutes)..."
|
||||
( cd "$desktop_dir" && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack ) || {
|
||||
local pack_ok=false
|
||||
if _desktop_pack "$desktop_dir"; then
|
||||
pack_ok=true
|
||||
else
|
||||
# (b) Corrupt cached Electron zip is the most common self-healable cause.
|
||||
local purged
|
||||
purged="$(clear_electron_build_cache "$desktop_dir")"
|
||||
if [ -n "$purged" ]; then
|
||||
log_warn "Desktop build failed; cleared cached Electron download and retrying once..."
|
||||
if _desktop_pack "$desktop_dir"; then
|
||||
pack_ok=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# (c) Still failing and the user hasn't pinned their own mirror: the GitHub
|
||||
# release host is likely blocked/throttled. Retry once via a public
|
||||
# Electron mirror (@electron/get still SHASUM-verifies the download).
|
||||
if [ "$pack_ok" = false ] && [ -z "${ELECTRON_MIRROR:-}" ]; then
|
||||
log_warn "Desktop build still failing — the Electron download from GitHub looks blocked."
|
||||
log_warn "Retrying once via a public Electron mirror ($DESKTOP_ELECTRON_FALLBACK_MIRROR)..."
|
||||
log_warn " (set ELECTRON_MIRROR yourself to use a different/trusted mirror)"
|
||||
if _desktop_pack "$desktop_dir" "$DESKTOP_ELECTRON_FALLBACK_MIRROR"; then
|
||||
pack_ok=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$pack_ok" = false ]; then
|
||||
log_error "Desktop app build failed"
|
||||
log_info "Run manually: cd $desktop_dir && npm run pack"
|
||||
# If the log shows repeated "retrying" lines fetching the Electron zip,
|
||||
# the binary download is blocked/throttled (firewall, proxy, region) and
|
||||
# the mirror fallback above also couldn't reach a host. Try a mirror you
|
||||
# trust and rebuild (@electron/get honors ELECTRON_MIRROR):
|
||||
log_info "If the log shows Electron download retries, rebuild via a reachable mirror:"
|
||||
log_info " ELECTRON_MIRROR=<mirror-base-url> \\"
|
||||
log_info " bash -c 'cd \"$desktop_dir\" && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack'"
|
||||
log_info "Otherwise build manually: cd $desktop_dir && npm run pack"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
local app=""
|
||||
if [ "$OS" = "linux" ]; then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue