Android Termux 跑小米Mimo Code[附脚本]

Android Termux 跑小米Mimo Code[附脚本]
Android Termux 跑小米Mimo Code[附脚本]

Screenshot_2026-06-11-18-18-14-07_84d3000e3f4017145260f7618db1d683

脚本

#!/data/data/com.termux/files/usr/bin/bash
set -euo pipefail

readonly SCRIPT_NAME="$(basename "$0")"
readonly MIMO_PACKAGE_NAME="@mimo-ai/cli"
readonly MIMO_PACKAGE_VERSION="${MIMO_CODE_VERSION:-${MIMOCODE_VERSION:-latest}}"
readonly PREFIX_DIR="${PREFIX:-/data/data/com.termux/files/usr}"
readonly HOST_MIMO_PATH="$PREFIX_DIR/bin/mimo"
readonly MIMO_CLI_PKG_DIR="$PREFIX_DIR/lib/node_modules/@mimo-ai/cli"
readonly MIMO_ARCH_PKG_NAME="@mimo-ai/mimocode-linux-arm64"
readonly MIMO_ARCH_PKG_DIR="$PREFIX_DIR/lib/node_modules/$MIMO_ARCH_PKG_NAME"
readonly TMP_ROOT="$HOME/tmp"
readonly BACKUP_DIR="$TMP_ROOT/mimocode-backups"
readonly WRAPPER_MARKER="# mimocode-termux-glibc-wrapper"

# Resolved by install_mimo_package() after locating the real glibc ELF.
MIMO_BINARY_PATH=""
MIMO_RESOLVED_VERSION=""

readonly C_BOLD_BLUE="\033[1;34m"
readonly C_BOLD_GREEN="\033[1;32m"
readonly C_BOLD_YELLOW="\033[1;33m"
readonly C_BOLD_RED="\033[1;31m"
readonly C_RESET="\033[0m"

info()    { printf '%b[INFO]%b %s\n' "$C_BOLD_BLUE"   "$C_RESET" "$*"; }
success() { printf '%b[ OK ]%b %s\n' "$C_BOLD_GREEN"  "$C_RESET" "$*"; }
warn()    { printf '%b[WARN]%b %s\n' "$C_BOLD_YELLOW" "$C_RESET" "$*" >&2; }
die()     { printf '%b[ERR ]%b %s\n' "$C_BOLD_RED"    "$C_RESET" "$*" >&2; exit 1; }

usage() {
    cat <<EOF
Usage:
  bash $SCRIPT_NAME

What it does (glibc-runner mode, no proot):
  1. Installs glibc-repo, refreshes apt metadata, installs glibc-runner.
  2. Installs nodejs-lts + npm in Termux (if missing).
  3. npm installs ${MIMO_PACKAGE_NAME} globally, then force-installs the
     ${MIMO_ARCH_PKG_NAME} native linux-arm64 package.
  4. Skips MiMoCode's postinstall script because Termux Node reports
     process.platform='android' and the upstream script looks for a
     non-existent @mimo-ai/mimocode-android-arm64 package.
  5. Replaces \$PREFIX/bin/mimo with a grun wrapper that runs the
     glibc ELF directly on Termux.

Environment overrides:
  MIMO_CODE_VERSION   npm package version/tag, default: ${MIMO_PACKAGE_VERSION}
                      examples: latest, preview, 0.1.0, v0.1.0
  MIMOCODE_VERSION    alias for MIMO_CODE_VERSION

Notes:
  - Official MiMoCode install docs: https://github.com/XiaomiMiMo/MiMo-Code
  - glibc-runner injects glibc via LD_LIBRARY_PATH; kernel calls are native.
EOF
}

command_exists() { command -v "$1" >/dev/null 2>&1; }

# ELF magic = 7f 45 4c 46; e_machine at offset 18 = 0xb7 for EM_AARCH64.
is_valid_aarch64_elf() {
    local f="$1"
    [ -f "$f" ] || return 1
    local magic machine
    magic=$(od -An -tx1 -N4 "$f" 2>/dev/null | tr -d ' \n')
    [ "$magic" = "7f454c46" ] || return 1
    machine=$(od -An -tx1 -j18 -N1 "$f" 2>/dev/null | tr -d ' \n')
    [ "$machine" = "b7" ]
}

find_arch_binary() {
    local candidate
    for candidate in \
        "$MIMO_ARCH_PKG_DIR/bin/mimo" \
        "$MIMO_CLI_PKG_DIR/bin/.mimocode"; do
        if is_valid_aarch64_elf "$candidate"; then
            MIMO_BINARY_PATH="$candidate"
            return 0
        fi
    done

    while IFS= read -r candidate; do
        if is_valid_aarch64_elf "$candidate"; then
            MIMO_BINARY_PATH="$candidate"
            return 0
        fi
    done < <(find "$MIMO_ARCH_PKG_DIR" "$MIMO_CLI_PKG_DIR" -type f -size +10M 2>/dev/null)
    return 1
}

ensure_tmp_root() {
    mkdir -p "$TMP_ROOT"
    [ -w "$TMP_ROOT" ] || die "Temp directory is not writable: $TMP_ROOT"
    export TMPDIR="$TMP_ROOT"
}

require_termux() {
    [ -d "$PREFIX_DIR" ] || die "This script must run in Termux."
    command_exists pkg || die "pkg not found. This script must run in Termux."
    if [ -r /proc/1/status ] && grep -q 'TracerPid:.*[1-9]' /proc/1/status 2>/dev/null; then
        warn "Detected non-zero TracerPid on PID 1 -- looks like a proot session."
        warn "Run this script from a plain Termux shell, not from inside proot-distro."
    fi
}

ensure_termux_package() {
    local package_name="$1"
    if dpkg -s "$package_name" >/dev/null 2>&1; then
        success "Termux package already installed: $package_name"
        return 0
    fi
    info "Installing Termux package: $package_name"
    pkg install -y "$package_name"
    success "Installed Termux package: $package_name"
}

ensure_glibc_runner() {
    ensure_termux_package "glibc-repo"

    if ! apt-cache show glibc-runner >/dev/null 2>&1; then
        info "Refreshing apt metadata so glibc-repo becomes visible"
        pkg update -y || apt-get update -y || true
    fi

    ensure_termux_package "glibc-runner"
    command_exists grun || die "grun not found after installing glibc-runner."
}

ensure_nodejs() {
    if command_exists node && command_exists npm; then
        success "Termux node present: $(node --version), npm $(npm --version)"
        return 0
    fi
    if dpkg -s nodejs >/dev/null 2>&1; then
        success "nodejs already installed"
    else
        ensure_termux_package "nodejs-lts"
    fi
    command_exists node && command_exists npm || die "node/npm not found after installing nodejs."
}

resolve_mimo_version() {
    local requested="$MIMO_PACKAGE_VERSION"
    if [ "$requested" != "latest" ]; then
        requested="${requested#v}"
    fi

    local pkg_spec="$MIMO_PACKAGE_NAME"
    if [ "$requested" != "latest" ]; then
        pkg_spec="${MIMO_PACKAGE_NAME}@${requested}"
    fi

    info "Resolving version for ${pkg_spec}"
    local resolved
    resolved=$(npm view "$pkg_spec" version 2>/dev/null | tail -n1) \
        || die "Failed to resolve version for ${pkg_spec} via npm view"
    [[ "$resolved" =~ ^[0-9]+\.[0-9]+ ]] \
        || die "npm view returned a bogus version: '$resolved'"

    MIMO_RESOLVED_VERSION="$resolved"
}

backup_existing_launcher() {
    mkdir -p "$BACKUP_DIR"
    [ -e "$HOST_MIMO_PATH" ] || return 0
    if grep -Fq "$WRAPPER_MARKER" "$HOST_MIMO_PATH" 2>/dev/null; then
        success "glibc-runner wrapper already in place"
        return 0
    fi
    local backup_path="$BACKUP_DIR/mimo.host-backup.$(date +%Y%m%d_%H%M%S)"
    cp -P "$HOST_MIMO_PATH" "$backup_path"
    success "Backed up existing launcher to $backup_path"
}

install_mimo_package() {
    resolve_mimo_version
    local main_version="$MIMO_RESOLVED_VERSION"

    local pinned_main="${MIMO_PACKAGE_NAME}@${main_version}"
    local arch_spec="${MIMO_ARCH_PKG_NAME}@${main_version}"

    info "Installing ${pinned_main} without upstream optional platform packages"
    npm install -g --force --ignore-scripts --omit=optional "$pinned_main"

    info "Installing ${arch_spec} for Termux via glibc-runner"
    npm install -g --force --ignore-scripts --os=linux --cpu=arm64 "$arch_spec"

    find_arch_binary || die "No valid aarch64 ELF found under $MIMO_ARCH_PKG_DIR. \
The arch package may not have unpacked correctly; inspect with: \
ls -la $MIMO_ARCH_PKG_DIR"

    success "MiMoCode native binary: $MIMO_BINARY_PATH ($(stat -c %s "$MIMO_BINARY_PATH" 2>/dev/null || echo '?') bytes)"
}

install_host_wrapper() {
    local tmp_wrapper
    tmp_wrapper="$(mktemp "$TMP_ROOT/mimo-grun.XXXXXX")"

    cat >"$tmp_wrapper" <<EOF
#!/data/data/com.termux/files/usr/bin/sh
$WRAPPER_MARKER
mkdir -p "\$HOME/tmp" 2>/dev/null || true
export TMPDIR="\${TMPDIR:-\$HOME/tmp}"
exec grun "$MIMO_BINARY_PATH" "\$@"
EOF

    chmod 755 "$tmp_wrapper"
    rm -f "$HOST_MIMO_PATH"
    mv "$tmp_wrapper" "$HOST_MIMO_PATH"
    chmod 755 "$HOST_MIMO_PATH"
    success "Installed Termux launcher: $HOST_MIMO_PATH"
}

verify_install() {
    info "Verifying binary via grun"
    grun "$MIMO_BINARY_PATH" --version
    info "Verifying Termux launcher"
    "$HOST_MIMO_PATH" --version

    local path_mimo=""
    path_mimo="$(command -v mimo 2>/dev/null || true)"
    if [ -n "$path_mimo" ] && [ "$path_mimo" != "$HOST_MIMO_PATH" ]; then
        warn "Your PATH resolves 'mimo' to $path_mimo, not $HOST_MIMO_PATH."
        warn "Move $PREFIX_DIR/bin earlier in PATH or remove the older launcher."
    fi

    success "MiMoCode setup completed (glibc-runner mode)"
}

main() {
    if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
        usage
        exit 0
    fi

    ensure_tmp_root
    require_termux
    ensure_glibc_runner
    ensure_nodejs
    backup_existing_launcher
    install_mimo_package
    install_host_wrapper
    verify_install

    cat <<EOF

Run MiMoCode with:
  mimo

Configuration:
  mode:     glibc-runner (no proot)
  binary:   $MIMO_BINARY_PATH
  launcher: $HOST_MIMO_PATH
  temp:     $TMP_ROOT

If the official installer previously added ~/.mimocode/bin before $PREFIX_DIR/bin,
that older launcher may shadow this Termux wrapper.

Troubleshooting:
  - If npm cannot resolve a preview version, install with:
      MIMO_CODE_VERSION=preview bash $SCRIPT_NAME
  - If subprocess errors mention libc/ld.so, the binary is loading Termux
    bionic libs via inherited LD_LIBRARY_PATH. Check glibc-runner docs.
EOF
}

main "$@"

1 个帖子 - 1 位参与者

阅读完整话题

来源: LinuxDo 最新话题查看原文