fix(install): suppress gum ioctl errors and fix premature @next fallback

- Detect 'inappropriate ioctl' as a gum raw-mode failure so the
  installer falls back to running without a spinner instead of leaking
  the error to stdout.
- Capture gum stdout in run_with_spinner so ioctl messages don't leak
  even when gum returns success.
- Run ensure_openclaw_bin_link before resolve_openclaw_bin so the
  @next retry only triggers when the package genuinely failed to
  install, not when the bin symlink is simply missing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sam Elsner 2026-03-21 01:37:54 -04:00
parent 9fb78453e0
commit f00dba7233

View File

@ -402,7 +402,7 @@ is_shell_function() {
is_gum_raw_mode_failure() {
local err_log="$1"
[[ -s "$err_log" ]] || return 1
grep -Eiq 'setrawmode' "$err_log"
grep -Eiq 'setrawmode|inappropriate ioctl' "$err_log"
}
run_with_spinner() {
@ -410,13 +410,20 @@ run_with_spinner() {
shift
if [[ -n "$GUM" ]] && gum_is_tty && ! is_shell_function "${1:-}"; then
local gum_err
local gum_err gum_out
gum_err="$(mktempfile)"
if "$GUM" spin --spinner dot --title "$title" -- "$@" 2>"$gum_err"; then
gum_out="$(mktempfile)"
if "$GUM" spin --spinner dot --title "$title" -- "$@" >"$gum_out" 2>"$gum_err"; then
# Gum succeeded but may have leaked terminal errors to stdout
if is_gum_raw_mode_failure "$gum_out" || is_gum_raw_mode_failure "$gum_err"; then
GUM=""
GUM_STATUS="skipped"
GUM_REASON="gum raw mode unavailable"
fi
return 0
fi
local gum_status=$?
if is_gum_raw_mode_failure "$gum_err"; then
if is_gum_raw_mode_failure "$gum_err" || is_gum_raw_mode_failure "$gum_out"; then
GUM=""
GUM_STATUS="skipped"
GUM_REASON="gum raw mode unavailable"
@ -2038,16 +2045,19 @@ install_openclaw() {
install_openclaw_npm "${install_spec}"
fi
# Ensure bin link exists before checking resolve — npm may install the
# package without creating the bin symlink on some configurations.
ensure_openclaw_bin_link || true
if [[ "${OPENCLAW_VERSION}" == "latest" && "${package_name}" == "openclaw" ]]; then
if ! resolve_openclaw_bin &> /dev/null; then
ui_warn "npm install openclaw@latest failed; retrying openclaw@next"
cleanup_npm_openclaw_paths
install_openclaw_npm "openclaw@next"
ensure_openclaw_bin_link || true
fi
fi
ensure_openclaw_bin_link || true
ui_success "OpenClaw installed"
}