fix: stop updater when Node.js version is wrong, match npm package to patch version
- install_node() now checks ver >= MIN_NODE_VERSION after install (was missing) - ensure_claude_code() accepts target_version, upgrades npm package if mismatched - cmd_update() hard-stops with clear message if Node.js can't be upgraded - Removes stale nodesource apt list before install to prevent version conflicts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -120,31 +120,40 @@ def install_node():
|
|||||||
# Linux — nodesource
|
# Linux — nodesource
|
||||||
print(f" Installing Node.js v24 via nodesource...")
|
print(f" Installing Node.js v24 via nodesource...")
|
||||||
try:
|
try:
|
||||||
|
# Remove old nodesource list if present (prevents version conflicts)
|
||||||
|
for old_list in ["/etc/apt/sources.list.d/nodesource.list"]:
|
||||||
|
if os.path.isfile(old_list):
|
||||||
|
os.remove(old_list)
|
||||||
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["bash", "-c", "curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs"],
|
["bash", "-c", "curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs"],
|
||||||
timeout=120, capture_output=True, text=True,
|
timeout=180, capture_output=True, text=True,
|
||||||
)
|
)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
ver = get_node_version()
|
ver = get_node_version()
|
||||||
if ver:
|
if ver and ver >= MIN_NODE_VERSION:
|
||||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||||
return True
|
return True
|
||||||
|
elif ver:
|
||||||
|
eprint(f" {Y}nodesource installed v{'.'.join(map(str, ver))} but need v{'.'.join(map(str, MIN_NODE_VERSION))}+{D}")
|
||||||
|
|
||||||
# Try dnf/yum fallback for RHEL/Fedora
|
# Try dnf/yum fallback for RHEL/Fedora
|
||||||
for pkg_mgr in ["dnf", "yum"]:
|
for pkg_mgr in ["dnf", "yum"]:
|
||||||
if shutil.which(pkg_mgr):
|
if shutil.which(pkg_mgr):
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["bash", "-c", f"curl -fsSL https://rpm.nodesource.com/setup_24.x | bash - && {pkg_mgr} install -y nodejs"],
|
["bash", "-c", f"curl -fsSL https://rpm.nodesource.com/setup_24.x | bash - && {pkg_mgr} install -y nodejs"],
|
||||||
timeout=120, capture_output=True, text=True,
|
timeout=180, capture_output=True, text=True,
|
||||||
)
|
)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
ver = get_node_version()
|
ver = get_node_version()
|
||||||
if ver:
|
if ver and ver >= MIN_NODE_VERSION:
|
||||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||||
return True
|
return True
|
||||||
|
elif ver:
|
||||||
|
eprint(f" {Y}Installed v{'.'.join(map(str, ver))} but need v{'.'.join(map(str, MIN_NODE_VERSION))}+{D}")
|
||||||
break
|
break
|
||||||
|
|
||||||
eprint(f" {R}Auto-install failed. Install manually: https://nodejs.org/{D}")
|
eprint(f" {R}Auto-install failed. Install Node.js v{'.'.join(map(str, MIN_NODE_VERSION))}+ manually: https://nodejs.org/{D}")
|
||||||
if result.stderr:
|
if result.stderr:
|
||||||
eprint(f" {result.stderr.strip()[:200]}")
|
eprint(f" {result.stderr.strip()[:200]}")
|
||||||
return False
|
return False
|
||||||
@@ -180,22 +189,39 @@ def ensure_node():
|
|||||||
# Claude Code auto-install
|
# Claude Code auto-install
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def ensure_claude_code():
|
def ensure_claude_code(target_version=None):
|
||||||
"""Install Claude Code via npm if not present. Returns True if OK."""
|
"""Install or update Claude Code via npm. Returns True if OK.
|
||||||
cli_js = find_cli_js()
|
|
||||||
if cli_js:
|
If target_version is set and the installed version doesn't match,
|
||||||
return True
|
reinstall to the exact version so cli.js patch is compatible.
|
||||||
|
"""
|
||||||
|
cli_js = find_cli_js()
|
||||||
|
|
||||||
|
# If already installed, check version compatibility
|
||||||
|
if cli_js and target_version:
|
||||||
|
installed_ver, _ = get_installed_version()
|
||||||
|
if installed_ver and ver_tuple(installed_ver) >= ver_tuple(target_version):
|
||||||
|
return True
|
||||||
|
# Version mismatch — need to update npm package to match patched cli.js
|
||||||
|
print(f" {Y}Claude Code {installed_ver} installed, need {target_version} for patch compatibility{D}")
|
||||||
|
print(f" Updating npm package to v{target_version}...")
|
||||||
|
pkg = f"@anthropic-ai/claude-code@{target_version}"
|
||||||
|
elif cli_js:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f" {Y}Claude Code not found. Installing via npm...{D}")
|
||||||
|
pkg = "@anthropic-ai/claude-code" + (f"@{target_version}" if target_version else "")
|
||||||
|
|
||||||
print(f" {Y}Claude Code not found. Installing via npm...{D}")
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["npm", "install", "-g", "@anthropic-ai/claude-code"],
|
["npm", "install", "-g", pkg],
|
||||||
capture_output=True, text=True, timeout=300,
|
capture_output=True, text=True, timeout=300,
|
||||||
)
|
)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
cli_js = find_cli_js()
|
cli_js = find_cli_js()
|
||||||
if cli_js:
|
if cli_js:
|
||||||
print(f" {G}Claude Code installed{D}")
|
new_ver, _ = get_installed_version()
|
||||||
|
print(f" {G}Claude Code {new_ver or ''} installed{D}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
eprint(f" {R}npm install failed{D}")
|
eprint(f" {R}npm install failed{D}")
|
||||||
@@ -709,22 +735,25 @@ def cmd_update(force=False, settings_only=False):
|
|||||||
"""Full update: git pull → install cli.js → patch settings."""
|
"""Full update: git pull → install cli.js → patch settings."""
|
||||||
print(f"\n{W}=== UClaude Updater ==={D}")
|
print(f"\n{W}=== UClaude Updater ==={D}")
|
||||||
|
|
||||||
# Check Node.js version
|
# Check Node.js version — HARD STOP if wrong
|
||||||
if not ensure_node():
|
if not ensure_node():
|
||||||
|
eprint(f"\n {R}Cannot continue without Node.js v{'.'.join(map(str, MIN_NODE_VERSION))}+{D}")
|
||||||
|
eprint(f" Install manually: https://nodejs.org/en/download/")
|
||||||
|
eprint(f" Then re-run: sudo python3 {sys.argv[0]} --force")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Ensure Claude Code is installed (npm install if missing)
|
# Git pull to get latest artifacts (before npm install so we know target version)
|
||||||
if not settings_only:
|
|
||||||
if not ensure_claude_code():
|
|
||||||
return 1
|
|
||||||
|
|
||||||
installed, cli_js = get_installed_version()
|
|
||||||
|
|
||||||
# Git pull to get latest artifacts
|
|
||||||
print(f"\n Pulling latest updates...")
|
print(f"\n Pulling latest updates...")
|
||||||
git_pull()
|
git_pull()
|
||||||
|
|
||||||
latest = get_latest_version()
|
latest = get_latest_version()
|
||||||
|
|
||||||
|
# Ensure Claude Code is installed at the right version
|
||||||
|
if not settings_only:
|
||||||
|
if not ensure_claude_code(target_version=latest):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
installed, cli_js = get_installed_version()
|
||||||
print(f" Installed: {installed or 'not found'}")
|
print(f" Installed: {installed or 'not found'}")
|
||||||
print(f" Latest: {latest or 'unknown'}")
|
print(f" Latest: {latest or 'unknown'}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user