341 lines
12 KiB
Bash
Executable File
341 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
PROJECT_DIR="$HOME/.openclaw-android"
|
|
PLATFORM_MARKER="$PROJECT_DIR/.platform"
|
|
OA_VERSION="1.0.27"
|
|
|
|
echo ""
|
|
echo -e "${BOLD}========================================${NC}"
|
|
echo -e "${BOLD} OpenClaw on Android - Updater v${OA_VERSION}${NC}"
|
|
echo -e "${BOLD}========================================${NC}"
|
|
echo ""
|
|
|
|
step() {
|
|
echo ""
|
|
echo -e "${BOLD}[$1/5] $2${NC}"
|
|
echo "----------------------------------------"
|
|
}
|
|
|
|
step 1 "Pre-flight Check"
|
|
|
|
if [ -z "${PREFIX:-}" ]; then
|
|
echo -e "${RED}[FAIL]${NC} Not running in Termux (\$PREFIX not set)"
|
|
exit 1
|
|
fi
|
|
echo -e "${GREEN}[OK]${NC} Termux detected"
|
|
|
|
if ! command -v curl &>/dev/null; then
|
|
echo -e "${RED}[FAIL]${NC} curl not found. Install it with: pkg install curl"
|
|
exit 1
|
|
fi
|
|
|
|
OLD_DIR="$HOME/.openclaw-lite"
|
|
if [ -d "$OLD_DIR" ] && [ ! -d "$PROJECT_DIR" ]; then
|
|
mv "$OLD_DIR" "$PROJECT_DIR"
|
|
echo -e "${GREEN}[OK]${NC} Migrated $OLD_DIR -> $PROJECT_DIR"
|
|
elif [ -d "$OLD_DIR" ] && [ -d "$PROJECT_DIR" ]; then
|
|
cp -rn "$OLD_DIR"/. "$PROJECT_DIR"/ 2>/dev/null || true
|
|
rm -rf "$OLD_DIR"
|
|
echo -e "${GREEN}[OK]${NC} Merged $OLD_DIR into $PROJECT_DIR"
|
|
else
|
|
mkdir -p "$PROJECT_DIR"
|
|
fi
|
|
|
|
if [ -f "$PROJECT_DIR/scripts/lib.sh" ]; then
|
|
source "$PROJECT_DIR/scripts/lib.sh"
|
|
fi
|
|
command -v resolve_npm_registry >/dev/null 2>&1 && resolve_npm_registry || true
|
|
|
|
# Define REPO_TARBALL after sourcing lib.sh to prevent old installs from overwriting it
|
|
REPO_TARBALL="https://github.com/AidanPark/openclaw-android/archive/refs/heads/main.tar.gz"
|
|
|
|
if ! declare -f detect_platform &>/dev/null; then
|
|
detect_platform() {
|
|
if [ -f "$PLATFORM_MARKER" ]; then
|
|
cat "$PLATFORM_MARKER"
|
|
return 0
|
|
fi
|
|
if command -v openclaw &>/dev/null; then
|
|
echo "openclaw"
|
|
mkdir -p "$(dirname "$PLATFORM_MARKER")"
|
|
echo "openclaw" > "$PLATFORM_MARKER"
|
|
return 0
|
|
fi
|
|
echo ""
|
|
return 1
|
|
}
|
|
fi
|
|
|
|
PLATFORM=$(detect_platform) || {
|
|
echo -e "${RED}[FAIL]${NC} No platform detected"
|
|
exit 1
|
|
}
|
|
if [ -z "$PLATFORM" ]; then
|
|
echo -e "${RED}[FAIL]${NC} No platform detected"
|
|
exit 1
|
|
fi
|
|
echo -e "${GREEN}[OK]${NC} Platform: $PLATFORM"
|
|
|
|
IS_GLIBC=false
|
|
if [ -f "$PROJECT_DIR/.glibc-arch" ]; then
|
|
IS_GLIBC=true
|
|
echo -e "${GREEN}[OK]${NC} Architecture: glibc"
|
|
else
|
|
echo -e "${YELLOW}[INFO]${NC} Architecture: Bionic (migration required)"
|
|
fi
|
|
|
|
SDK_INT=$(getprop ro.build.version.sdk 2>/dev/null || echo "0")
|
|
if [ "$SDK_INT" -ge 31 ] 2>/dev/null; then
|
|
echo -e "${YELLOW}[INFO]${NC} Android 12+ detected — if background processes get killed (signal 9),"
|
|
echo " see: https://github.com/AidanPark/openclaw-android/blob/main/docs/disable-phantom-process-killer.md"
|
|
fi
|
|
|
|
step 2 "Download Latest Release (tarball)"
|
|
|
|
mkdir -p "$PREFIX/tmp"
|
|
RELEASE_TMP=$(mktemp -d "$PREFIX/tmp/oa-update.XXXXXX") || {
|
|
echo -e "${RED}[FAIL]${NC} Failed to create temp directory"
|
|
exit 1
|
|
}
|
|
trap 'rm -rf "$RELEASE_TMP"' EXIT
|
|
|
|
echo "Downloading latest scripts..."
|
|
echo " (This may take a moment depending on network speed)"
|
|
if curl -sfL "$REPO_TARBALL" | tar xz -C "$RELEASE_TMP" --strip-components=1; then
|
|
echo -e "${GREEN}[OK]${NC} Downloaded latest release"
|
|
else
|
|
echo -e "${RED}[FAIL]${NC} Failed to download release"
|
|
exit 1
|
|
fi
|
|
|
|
REQUIRED_FILES=(
|
|
"scripts/lib.sh"
|
|
"scripts/setup-env.sh"
|
|
"platforms/$PLATFORM/config.env"
|
|
"platforms/$PLATFORM/update.sh"
|
|
)
|
|
for f in "${REQUIRED_FILES[@]}"; do
|
|
if [ ! -f "$RELEASE_TMP/$f" ]; then
|
|
echo -e "${RED}[FAIL]${NC} Missing required file: $f"
|
|
echo " The downloaded release may be corrupted. Try again."
|
|
exit 1
|
|
fi
|
|
done
|
|
echo -e "${GREEN}[OK]${NC} All required files verified"
|
|
|
|
source "$RELEASE_TMP/scripts/lib.sh"
|
|
|
|
step 3 "Update Core Infrastructure"
|
|
|
|
mkdir -p "$PROJECT_DIR/platforms" "$PROJECT_DIR/scripts" "$PROJECT_DIR/patches"
|
|
|
|
rm -rf "$PROJECT_DIR/platforms/$PLATFORM"
|
|
cp -r "$RELEASE_TMP/platforms/$PLATFORM" "$PROJECT_DIR/platforms/"
|
|
|
|
cp "$RELEASE_TMP/scripts/lib.sh" "$PROJECT_DIR/scripts/lib.sh"
|
|
cp "$RELEASE_TMP/scripts/setup-env.sh" "$PROJECT_DIR/scripts/setup-env.sh"
|
|
if [ -f "$RELEASE_TMP/scripts/backup.sh" ]; then
|
|
cp "$RELEASE_TMP/scripts/backup.sh" "$PROJECT_DIR/scripts/backup.sh"
|
|
fi
|
|
|
|
cp "$RELEASE_TMP/patches/glibc-compat.js" "$PROJECT_DIR/patches/glibc-compat.js"
|
|
cp "$RELEASE_TMP/patches/argon2-stub.js" "$PROJECT_DIR/patches/argon2-stub.js"
|
|
cp "$RELEASE_TMP/patches/spawn.h" "$PROJECT_DIR/patches/spawn.h"
|
|
cp "$RELEASE_TMP/patches/systemctl" "$PROJECT_DIR/patches/systemctl"
|
|
|
|
# Deploy supplementary glibc libraries (e.g., libcap.so.2 for native binary support)
|
|
if [ -d "$RELEASE_TMP/patches/glibc-libs" ] && [ -d "$PREFIX/glibc/lib" ]; then
|
|
for _lib in "$RELEASE_TMP/patches/glibc-libs"/*.so.*; do
|
|
[ -f "$_lib" ] || continue
|
|
_fn=$(basename "$_lib")
|
|
if [ ! -f "$PREFIX/glibc/lib/$_fn" ]; then
|
|
cp "$_lib" "$PREFIX/glibc/lib/$_fn"
|
|
_sn=$(echo "$_fn" | sed -E 's/^(lib[^.]+\.so\.[0-9]+)\..*/\1/')
|
|
[ "$_sn" != "$_fn" ] && ln -sf "$_fn" "$PREFIX/glibc/lib/$_sn"
|
|
echo -e "${GREEN}[OK]${NC} Installed glibc lib: $_sn"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Ensure glibc /etc/hosts exists (localhost resolution)
|
|
if [ -d "$PREFIX/glibc/etc" ] && [ ! -f "$PREFIX/glibc/etc/hosts" ]; then
|
|
cat > "$PREFIX/glibc/etc/hosts" <<'HOSTS'
|
|
127.0.0.1 localhost localhost.localdomain
|
|
::1 localhost ip6-localhost ip6-loopback
|
|
HOSTS
|
|
echo -e "${GREEN}[OK]${NC} Created glibc /etc/hosts"
|
|
fi
|
|
|
|
cp "$RELEASE_TMP/oa.sh" "$PREFIX/bin/oa"
|
|
chmod +x "$PREFIX/bin/oa"
|
|
|
|
cp "$RELEASE_TMP/update.sh" "$PREFIX/bin/oaupdate"
|
|
chmod +x "$PREFIX/bin/oaupdate"
|
|
|
|
cp "$RELEASE_TMP/uninstall.sh" "$PROJECT_DIR/uninstall.sh"
|
|
chmod +x "$PROJECT_DIR/uninstall.sh"
|
|
|
|
if [ "$IS_GLIBC" = false ]; then
|
|
echo ""
|
|
echo -e "${BOLD}[MIGRATE] Bionic -> glibc Architecture${NC}"
|
|
echo "----------------------------------------"
|
|
if bash "$RELEASE_TMP/scripts/install-glibc.sh" && bash "$RELEASE_TMP/scripts/install-nodejs.sh"; then
|
|
IS_GLIBC=true
|
|
echo -e "${GREEN}[OK]${NC} glibc migration complete"
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} glibc migration failed (non-critical)"
|
|
fi
|
|
fi
|
|
|
|
# Update Node.js if a newer version is available
|
|
if [ "$IS_GLIBC" = true ]; then
|
|
bash "$RELEASE_TMP/scripts/install-nodejs.sh" || true
|
|
fi
|
|
|
|
bash "$RELEASE_TMP/scripts/setup-env.sh"
|
|
|
|
GLIBC_NODE_DIR="$PROJECT_DIR/node"
|
|
GLIBC_BIN_DIR="$PROJECT_DIR/bin"
|
|
if [ "$IS_GLIBC" = true ]; then
|
|
# Migrate wrappers from node/bin/ to bin/ (safe from npm overwrites)
|
|
if [ ! -d "$GLIBC_BIN_DIR" ] || [ ! -x "$GLIBC_BIN_DIR/node" ]; then
|
|
echo ""
|
|
echo -e "${BOLD}[MIGRATE] Moving wrappers to $GLIBC_BIN_DIR${NC}"
|
|
bash "$RELEASE_TMP/scripts/install-nodejs.sh" || true
|
|
echo -e "${GREEN}[OK]${NC} Wrapper migration complete"
|
|
fi
|
|
export PATH="$GLIBC_BIN_DIR:$GLIBC_NODE_DIR/bin:$HOME/.local/bin:$PATH"
|
|
export OA_GLIBC=1
|
|
fi
|
|
export TMPDIR="$PREFIX/tmp"
|
|
export TMP="$TMPDIR"
|
|
export TEMP="$TMPDIR"
|
|
# Load platform-specific environment variables for current session
|
|
PLATFORM_ENV_SCRIPT="$RELEASE_TMP/platforms/$PLATFORM/env.sh"
|
|
if [ -f "$PLATFORM_ENV_SCRIPT" ]; then
|
|
eval "$(bash "$PLATFORM_ENV_SCRIPT")"
|
|
fi
|
|
|
|
step 4 "Update Platform"
|
|
|
|
if [ -f "$RELEASE_TMP/platforms/$PLATFORM/update.sh" ]; then
|
|
bash "$RELEASE_TMP/platforms/$PLATFORM/update.sh"
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} Platform update script not found"
|
|
fi
|
|
|
|
step 5 "Update Optional Tools"
|
|
|
|
if command -v code-server &>/dev/null; then
|
|
if bash "$RELEASE_TMP/scripts/install-code-server.sh" update; then
|
|
echo -e "${GREEN}[OK]${NC} code-server update step complete"
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} code-server update failed (non-critical)"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}[SKIP]${NC} code-server not installed"
|
|
fi
|
|
|
|
if command -v chromium-browser &>/dev/null || command -v chromium &>/dev/null; then
|
|
if [ -f "$RELEASE_TMP/scripts/install-chromium.sh" ]; then
|
|
bash "$RELEASE_TMP/scripts/install-chromium.sh" update || true
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}[SKIP]${NC} Chromium not installed"
|
|
fi
|
|
|
|
if [ "$IS_GLIBC" = false ]; then
|
|
echo -e "${YELLOW}[SKIP]${NC} OpenCode requires glibc architecture"
|
|
else
|
|
OPENCODE_INSTALLED=false
|
|
command -v opencode &>/dev/null && OPENCODE_INSTALLED=true
|
|
|
|
if [ "$OPENCODE_INSTALLED" = true ]; then
|
|
CURRENT_OC_VER=$(opencode --version 2>/dev/null || echo "")
|
|
LATEST_OC_VER=$(npm view opencode-ai version 2>/dev/null || echo "")
|
|
|
|
if [ -n "$CURRENT_OC_VER" ] && [ -n "$LATEST_OC_VER" ] && [ "$CURRENT_OC_VER" = "$LATEST_OC_VER" ]; then
|
|
echo -e "${GREEN}[OK]${NC} OpenCode $CURRENT_OC_VER is already the latest"
|
|
else
|
|
if [ -n "$CURRENT_OC_VER" ] && [ -n "$LATEST_OC_VER" ] && [ "$CURRENT_OC_VER" != "$LATEST_OC_VER" ]; then
|
|
echo "OpenCode update available: $CURRENT_OC_VER -> $LATEST_OC_VER"
|
|
fi
|
|
echo " (This may take a few minutes for package download and binary processing)"
|
|
if bash "$RELEASE_TMP/scripts/install-opencode.sh"; then
|
|
echo -e "${GREEN}[OK]${NC} OpenCode ${LATEST_OC_VER:-} updated"
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} OpenCode update failed (non-critical)"
|
|
fi
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}[SKIP]${NC} OpenCode not installed"
|
|
fi
|
|
fi
|
|
|
|
update_ai_tool() {
|
|
local cmd="$1"
|
|
local pkg="$2"
|
|
local label="$3"
|
|
|
|
if ! command -v "$cmd" &>/dev/null; then
|
|
return 1
|
|
fi
|
|
|
|
local current_ver latest_ver
|
|
current_ver=$(npm list -g "$pkg" 2>/dev/null | grep "${pkg##*/}@" | sed 's/.*@//' | tr -d '[:space:]')
|
|
latest_ver=$(npm view "$pkg" version 2>/dev/null || echo "")
|
|
|
|
if [ -n "$current_ver" ] && [ -n "$latest_ver" ] && [ "$current_ver" = "$latest_ver" ]; then
|
|
echo -e "${GREEN}[OK]${NC} $label $current_ver is already the latest"
|
|
elif [ -n "$latest_ver" ]; then
|
|
echo "Updating $label... ($current_ver -> $latest_ver)"
|
|
echo " (This may take a few minutes depending on network speed)"
|
|
if npm install -g "$pkg@latest" --no-fund --no-audit --ignore-scripts; then
|
|
echo -e "${GREEN}[OK]${NC} $label $latest_ver updated"
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} $label update failed (non-critical)"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}[WARN]${NC} Could not check $label latest version"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
AI_FOUND=false
|
|
# Migrate codex from upstream (static musl, broken DNS on Android) to Termux fork (dynamic Bionic)
|
|
if npm list -g @openai/codex &>/dev/null 2>&1; then
|
|
echo -e " ${YELLOW}[MIGRATE]${NC} Replacing @openai/codex with Termux-optimized @mmmbuto/codex-cli-termux..."
|
|
npm uninstall -g @openai/codex 2>/dev/null || true
|
|
fi
|
|
update_ai_tool "claude" "@anthropic-ai/claude-code" "Claude Code" && AI_FOUND=true
|
|
update_ai_tool "gemini" "@google/gemini-cli" "Gemini CLI" && AI_FOUND=true
|
|
update_ai_tool "codex" "@mmmbuto/codex-cli-termux" "Codex CLI (Termux)" && AI_FOUND=true
|
|
# Create/refresh codex CLI wrapper (DioNanos fork launcher fix)
|
|
_codex_bin="$PREFIX/bin/codex"
|
|
_codex_pkg="$PREFIX/lib/node_modules/@mmmbuto/codex-cli-termux/bin"
|
|
if [ -f "$_codex_pkg/codex.bin" ]; then
|
|
[ -L "$_codex_bin" ] && rm -f "$_codex_bin"
|
|
printf '#!%s/bin/bash\nPKG_BIN="%s"\nexport LD_LIBRARY_PATH="$PKG_BIN:${LD_LIBRARY_PATH:-}"\nexec "$PKG_BIN/codex.bin" "$@"\n' \
|
|
"$PREFIX" "$_codex_pkg" > "$_codex_bin"
|
|
chmod +x "$_codex_bin"
|
|
fi
|
|
if [ "$AI_FOUND" = false ]; then
|
|
echo -e "${YELLOW}[SKIP]${NC} No AI CLI tools installed"
|
|
fi
|
|
|
|
command -v fix_npm_global_shebangs >/dev/null 2>&1 && fix_npm_global_shebangs || true
|
|
|
|
echo ""
|
|
echo -e "${GREEN}${BOLD} Update Complete!${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}Run this to apply changes to the current session:${NC}"
|
|
echo ""
|
|
echo " source ~/.bashrc"
|