fix: print resolved installer follow-up command

Signed-off-by: sallyom <somalley@redhat.com>
This commit is contained in:
sallyom
2026-05-07 16:00:58 -04:00
committed by Sally O'Malley
parent 6a8b4e422e
commit 56fe64e8e3
3 changed files with 63 additions and 5 deletions

View File

@@ -154,6 +154,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Docs/Docker: document a local Compose override for Docker Desktop DNS failures in the shared-network `openclaw-cli` sidecar, keeping the default compose setup hardened while unblocking `openclaw plugins install` when users opt in. Fixes #79018. Thanks @Jason-Vaughan.
- Installer: when npm installs `openclaw` outside the parent shell PATH, print follow-up commands with the resolved binary path instead of telling users to run `openclaw` from a shell that will report `command not found`. Fixes #72382. Thanks @jbob762.
- Compute plugin callback authorization dynamically [AI]. (#78866) Thanks @pgondhi987.
- fix(active-memory): require admin scope for global toggles [AI]. (#78863) Thanks @pgondhi987.
- Honor owner enforcement for native commands [AI]. (#78864) Thanks @pgondhi987.

View File

@@ -2006,6 +2006,24 @@ warn_shell_path_missing_dir() {
echo " export PATH=\"${dir}:\$PATH\""
}
openclaw_command_for_user() {
local claw="${1:-}"
if [[ -z "$claw" ]]; then
echo "openclaw"
return 0
fi
local claw_dir="${claw%/*}"
if [[ "$claw_dir" != "$claw" ]] && path_has_dir "$ORIGINAL_PATH" "$claw_dir"; then
echo "openclaw"
return 0
fi
local quoted_claw=""
printf -v quoted_claw '%q' "$claw"
echo "$quoted_claw"
}
ensure_npm_global_bin_on_path() {
local bin_dir=""
bin_dir="$(npm_global_bin_dir || true)"
@@ -2300,7 +2318,9 @@ run_bootstrap_onboarding_if_needed() {
fi
if [[ ! -r /dev/tty || ! -w /dev/tty ]]; then
ui_info "BOOTSTRAP.md found but no TTY; run openclaw onboard to finish setup"
local user_claw
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
ui_info "BOOTSTRAP.md found but no TTY; run ${user_claw} onboard to finish setup"
return
fi
@@ -2316,7 +2336,9 @@ run_bootstrap_onboarding_if_needed() {
fi
"$claw" onboard || {
ui_error "Onboarding failed; run openclaw onboard to retry"
local user_claw
user_claw="$(openclaw_command_for_user "$claw")"
ui_error "Onboarding failed; run ${user_claw} onboard to retry"
return
}
}
@@ -2702,11 +2724,15 @@ main() {
ui_warn "Doctor failed; skipping plugin updates"
fi
else
ui_info "No TTY; run openclaw doctor and openclaw plugins update --all manually"
local user_claw
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
ui_info "No TTY; run ${user_claw} doctor and ${user_claw} plugins update --all manually"
fi
else
if [[ "$NO_ONBOARD" == "1" || "$skip_onboard" == "true" ]]; then
ui_info "Skipping onboard (requested); run openclaw onboard later"
local user_claw
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
ui_info "Skipping onboard (requested); run ${user_claw} onboard later"
else
local config_path="${OPENCLAW_CONFIG_PATH:-$HOME/.openclaw/openclaw.json}"
if [[ -f "${config_path}" || -f "$HOME/.clawdbot/clawdbot.json" ]]; then
@@ -2731,7 +2757,9 @@ main() {
exec </dev/tty
exec "$claw" onboard
fi
ui_info "No TTY; run openclaw onboard to finish setup"
local user_claw
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
ui_info "No TTY; run ${user_claw} onboard to finish setup"
return 0
fi
fi

View File

@@ -161,6 +161,35 @@ describe("install.sh", () => {
expect(result?.stdout).toContain("using this user prefix");
expect(result?.stdout).not.toContain("has been saved");
});
it("uses a quoted absolute openclaw path in follow-up commands when npm bin is not on the original PATH", () => {
const tmp = mkdtempSync(join(tmpdir(), "openclaw-install-command-"));
const npmBin = join(tmp, "npm bin");
const visibleBin = join(tmp, "visible-bin");
mkdirSync(npmBin, { recursive: true });
mkdirSync(visibleBin, { recursive: true });
const openclawBin = join(npmBin, "openclaw");
writeFileSync(openclawBin, "#!/bin/sh\nexit 0\n");
chmodSync(openclawBin, 0o755);
let result: ReturnType<typeof runInstallShell> | undefined;
try {
result = runInstallShell(`
set -euo pipefail
source "${SCRIPT_PATH}"
ORIGINAL_PATH=${JSON.stringify(`${visibleBin}:/usr/bin:/bin`)}
printf 'missing=%s\\n' "$(openclaw_command_for_user "${openclawBin}")"
ORIGINAL_PATH=${JSON.stringify(`${npmBin}:${visibleBin}:/usr/bin:/bin`)}
printf 'present=%s\\n' "$(openclaw_command_for_user "${openclawBin}")"
`);
} finally {
rmSync(tmp, { recursive: true, force: true });
}
expect(result?.status).toBe(0);
expect(result?.stdout).toContain(`missing=${openclawBin.replace(/ /g, "\\ ")}`);
expect(result?.stdout).toContain("present=openclaw");
});
});
describe("install.sh macOS Homebrew Node behavior", () => {