diff --git a/root/etc/init.d/openclaw b/root/etc/init.d/openclaw index 7113a4c..70745cd 100755 --- a/root/etc/init.d/openclaw +++ b/root/etc/init.d/openclaw @@ -175,6 +175,9 @@ echo "openclaw 已禁用。请在 /etc/config/openclaw 中设置 enabled 为 1" return 0 } +mkdir -p "${OC_DATA}/.npm" "${OC_DATA}/.cache/corepack" "${OC_DATA}/tmp" 2>/dev/null +chown -R openclaw:openclaw "${OC_DATA}/.npm" "${OC_DATA}/.cache" "${OC_DATA}/tmp" 2>/dev/null || true + # 检查 Node.js if [ ! -x "$NODE_BIN" ]; then echo "未找到 Node.js: $NODE_BIN" @@ -311,6 +314,16 @@ NODE_ICU_DATA="${NODE_BASE}/share/icu" \ NODE_BASE="$NODE_BASE" \ OC_GLOBAL="$OC_GLOBAL" \ OC_DATA="$OC_DATA" \ +NPM_CONFIG_PREFIX="$OC_GLOBAL" \ +npm_config_prefix="$OC_GLOBAL" \ +NPM_CONFIG_CACHE="${OC_DATA}/.npm" \ +npm_config_cache="${OC_DATA}/.npm" \ +XDG_CACHE_HOME="${OC_DATA}/.cache" \ +COREPACK_HOME="${OC_DATA}/.cache/corepack" \ +PNPM_HOME="${OC_GLOBAL}/bin" \ +TMPDIR="${OC_DATA}/tmp" \ +TMP="${OC_DATA}/tmp" \ +TEMP="${OC_DATA}/tmp" \ PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" procd_set_param user openclaw procd_set_param respawn 3600 10 5 @@ -345,6 +358,16 @@ HOME="$OC_DATA" \ OPENCLAW_HOME="$OC_DATA" \ OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \ OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \ +NPM_CONFIG_PREFIX="$OC_GLOBAL" \ +npm_config_prefix="$OC_GLOBAL" \ +NPM_CONFIG_CACHE="${OC_DATA}/.npm" \ +npm_config_cache="${OC_DATA}/.npm" \ +XDG_CACHE_HOME="${OC_DATA}/.cache" \ +COREPACK_HOME="${OC_DATA}/.cache/corepack" \ +PNPM_HOME="${OC_GLOBAL}/bin" \ +TMPDIR="${OC_DATA}/tmp" \ +TMP="${OC_DATA}/tmp" \ +TEMP="${OC_DATA}/tmp" \ PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" procd_set_param respawn 3600 5 5 procd_set_param stdout 1 diff --git a/root/etc/profile.d/openclaw.sh b/root/etc/profile.d/openclaw.sh index bf6e69a..d8bcda9 100644 --- a/root/etc/profile.d/openclaw.sh +++ b/root/etc/profile.d/openclaw.sh @@ -19,6 +19,16 @@ esac # 设置 Node.js ICU 数据路径 export NODE_ICU_DATA="${NODE_BASE}/share/icu" +export NPM_CONFIG_PREFIX="$OC_GLOBAL" +export npm_config_prefix="$OC_GLOBAL" +export NPM_CONFIG_CACHE="${OC_DATA}/.npm" +export npm_config_cache="${OC_DATA}/.npm" +export XDG_CACHE_HOME="${OC_DATA}/.cache" +export COREPACK_HOME="${OC_DATA}/.cache/corepack" +export PNPM_HOME="${OC_GLOBAL}/bin" +export TMPDIR="${OC_DATA}/tmp" +export TMP="${OC_DATA}/tmp" +export TEMP="${OC_DATA}/tmp" # 设置 OpenClaw 核心环境变量 # 这些变量确保 openclaw 命令使用正确的配置路径 diff --git a/root/etc/uci-defaults/99-openclaw b/root/etc/uci-defaults/99-openclaw index 3032961..4e7d27b 100755 --- a/root/etc/uci-defaults/99-openclaw +++ b/root/etc/uci-defaults/99-openclaw @@ -74,6 +74,9 @@ if oc_install_root_uses_opt_workaround "$OPENCLAW_INSTALL_ROOT"; then fi fi mkdir -p "${OC_DATA}/.openclaw" +mkdir -p "${OC_DATA}/.npm" +mkdir -p "${OC_DATA}/.cache/corepack" +mkdir -p "${OC_DATA}/tmp" mkdir -p "$NODE_BASE" mkdir -p "$OC_GLOBAL" chown -R openclaw:openclaw "$OC_ROOT" 2>/dev/null || true diff --git a/root/usr/bin/openclaw-env b/root/usr/bin/openclaw-env index 1e986f9..40cd59e 100755 --- a/root/usr/bin/openclaw-env +++ b/root/usr/bin/openclaw-env @@ -68,6 +68,16 @@ NODE_RELEASE_PAGE_FALLBACK="${NODE_RELEASE_PAGE_FALLBACK:-https://gitea.jmsu.top export PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:$PATH" export NODE_ICU_DATA="${NODE_BASE}/share/icu" +export NPM_CONFIG_PREFIX="${OC_GLOBAL}" +export npm_config_prefix="${OC_GLOBAL}" +export NPM_CONFIG_CACHE="${OC_DATA}/.npm" +export npm_config_cache="${OC_DATA}/.npm" +export XDG_CACHE_HOME="${OC_DATA}/.cache" +export COREPACK_HOME="${OC_DATA}/.cache/corepack" +export PNPM_HOME="${OC_GLOBAL}/bin" +export TMPDIR="${OC_DATA}/tmp" +export TMP="${OC_DATA}/tmp" +export TEMP="${OC_DATA}/tmp" log_info() { echo " [✓] $1"; } log_warn() { echo " [!] $1"; } @@ -132,6 +142,14 @@ ensure_mkdir() { fi } +ensure_runtime_cache_dirs() { + ensure_mkdir "$OC_DATA" + ensure_mkdir "${OC_DATA}/.npm" + ensure_mkdir "${OC_DATA}/.cache" + ensure_mkdir "${OC_DATA}/.cache/corepack" + ensure_mkdir "${OC_DATA}/tmp" +} + # 检测 C 运行时类型 (glibc vs musl) detect_libc() { if ldd --version 2>&1 | grep -qi musl; then @@ -368,6 +386,7 @@ install_pnpm() { # 使用 npm 安装 pnpm 到全局目录 ensure_mkdir "$OC_GLOBAL" + ensure_runtime_cache_dirs "$NPM_BIN" install -g pnpm --prefix="$OC_GLOBAL" 2>/dev/null if [ -x "$OC_GLOBAL/bin/pnpm" ]; then @@ -422,6 +441,7 @@ install_openclaw() { local npm_ok=0 if [ -x "$NPM_BIN" ]; then ensure_mkdir "$OC_GLOBAL" + ensure_runtime_cache_dirs "$NPM_BIN" install -g "$oc_pkg" --prefix="$OC_GLOBAL" $install_flags 2>&1 | tail -10 # 检查是否安装成功 if [ -n "$(find_oc_entry)" ]; then @@ -458,6 +478,7 @@ install_openclaw() { if [ -x "$NPM_BIN" ]; then echo "" echo "=== 安装 Gemini CLI (Google OAuth 依赖) ===" + ensure_runtime_cache_dirs "$NPM_BIN" install -g @google/gemini-cli --prefix="$OC_GLOBAL" $install_flags 2>&1 | tail -3 if command -v gemini >/dev/null 2>&1 || [ -x "$OC_GLOBAL/bin/gemini" ]; then log_info "Gemini CLI 安装成功" @@ -628,6 +649,7 @@ do_upgrade() { echo "=== 正在升级 OpenClaw ===" echo "" + ensure_runtime_cache_dirs "$NPM_BIN" install -g openclaw@latest --prefix="$OC_GLOBAL" $install_flags 2>&1 # 验证升级结果 diff --git a/root/usr/share/openclaw/oc-config.sh b/root/usr/share/openclaw/oc-config.sh index 98bd843..4d4f30a 100755 --- a/root/usr/share/openclaw/oc-config.sh +++ b/root/usr/share/openclaw/oc-config.sh @@ -40,6 +40,16 @@ export OPENCLAW_HOME="$OC_DATA" export OPENCLAW_STATE_DIR="$OC_STATE_DIR" export OPENCLAW_CONFIG_PATH="$CONFIG_FILE" export NODE_ICU_DATA="${NODE_BASE}/share/icu" +export NPM_CONFIG_PREFIX="$OC_GLOBAL" +export npm_config_prefix="$OC_GLOBAL" +export NPM_CONFIG_CACHE="${OC_DATA}/.npm" +export npm_config_cache="${OC_DATA}/.npm" +export XDG_CACHE_HOME="${OC_DATA}/.cache" +export COREPACK_HOME="${OC_DATA}/.cache/corepack" +export PNPM_HOME="${OC_GLOBAL}/bin" +export TMPDIR="${OC_DATA}/tmp" +export TMP="${OC_DATA}/tmp" +export TEMP="${OC_DATA}/tmp" export PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # ── 查找 openclaw 入口 ── diff --git a/root/usr/share/openclaw/web-pty.js b/root/usr/share/openclaw/web-pty.js index 3eee025..d74bd21 100644 --- a/root/usr/share/openclaw/web-pty.js +++ b/root/usr/share/openclaw/web-pty.js @@ -200,6 +200,16 @@ class PtySession { OPENCLAW_HOME: OC_DATA, OPENCLAW_STATE_DIR: `${OC_DATA}/.openclaw`, OPENCLAW_CONFIG_PATH: `${OC_DATA}/.openclaw/openclaw.json`, + NPM_CONFIG_PREFIX: OC_GLOBAL, + npm_config_prefix: OC_GLOBAL, + NPM_CONFIG_CACHE: `${OC_DATA}/.npm`, + npm_config_cache: `${OC_DATA}/.npm`, + XDG_CACHE_HOME: `${OC_DATA}/.cache`, + COREPACK_HOME: `${OC_DATA}/.cache/corepack`, + PNPM_HOME: `${OC_GLOBAL}/bin`, + TMPDIR: `${OC_DATA}/tmp`, + TMP: `${OC_DATA}/tmp`, + TEMP: `${OC_DATA}/tmp`, PATH: `${NODE_BASE}/bin:${OC_GLOBAL}/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`, }; // 检测 script 命令是否可用 (OpenWrt 默认不包含 util-linux-script) diff --git a/tests/test_node_packaging_contract.sh b/tests/test_node_packaging_contract.sh index aff2bd9..4d328fa 100644 --- a/tests/test_node_packaging_contract.sh +++ b/tests/test_node_packaging_contract.sh @@ -17,6 +17,7 @@ UCI_DEFAULTS_SCRIPT="$REPO_ROOT/root/etc/uci-defaults/99-openclaw" INIT_SCRIPT="$REPO_ROOT/root/etc/init.d/openclaw" PATHS_HELPER="$REPO_ROOT/root/usr/libexec/openclaw-paths.sh" NODE_HELPER="$REPO_ROOT/root/usr/libexec/openclaw-node.sh" +WEB_PTY_SCRIPT="$REPO_ROOT/root/usr/share/openclaw/web-pty.js" fail() { echo "FAIL: $1" >&2 @@ -62,6 +63,11 @@ grep -Fq 'while IFS= read -r d; do' "$ENV_SCRIPT" || fail "installer should trav if grep -Fq 'echo "$search_dirs" | while read -r d; do' "$ENV_SCRIPT"; then fail "installer should not rely on a pipeline subshell for OpenClaw entry lookup" fi +grep -Fq 'NPM_CONFIG_PREFIX="${OC_GLOBAL}"' "$ENV_SCRIPT" || fail "installer should force npm global prefix into custom install root" +grep -Fq 'NPM_CONFIG_CACHE="${OC_DATA}/.npm"' "$ENV_SCRIPT" || fail "installer should force npm cache into custom data root" +grep -Fq 'XDG_CACHE_HOME="${OC_DATA}/.cache"' "$ENV_SCRIPT" || fail "installer should force generic caches into custom data root" +grep -Fq 'COREPACK_HOME="${OC_DATA}/.cache/corepack"' "$ENV_SCRIPT" || fail "installer should force corepack cache into custom data root" +grep -Fq 'TMPDIR="${OC_DATA}/tmp"' "$ENV_SCRIPT" || fail "installer should force temp files into custom data root" grep -Fq 'openclaw-paths.sh' "$MAKEFILE" || fail "package makefile should install path helper" grep -Fq 'openclaw-node.sh' "$MAKEFILE" || fail "package makefile should install node helper" @@ -97,6 +103,15 @@ PY grep -Fq 'local GITHUB_REPO = "hotwa/luci-app-openclaw"' "$CONTROLLER_SCRIPT" || fail "controller should default to hotwa repo" grep -Fq 'local GITHUB_RELEASES_URL = "https://github.com/" .. GITHUB_REPO .. "/releases"' "$CONTROLLER_SCRIPT" || fail "controller should derive release URLs from hotwa repo" grep -Fq 'local GITHUB_API_RELEASES_URL = "https://api.github.com/repos/" .. GITHUB_REPO .. "/releases"' "$CONTROLLER_SCRIPT" || fail "controller should derive API URLs from hotwa repo" +grep -Fq 'export NPM_CONFIG_PREFIX="$OC_GLOBAL"' "$PROFILE_SCRIPT" || fail "shell profile should export npm prefix into custom install root" +grep -Fq 'export NPM_CONFIG_CACHE="${OC_DATA}/.npm"' "$PROFILE_SCRIPT" || fail "shell profile should export npm cache into custom data root" +grep -Fq 'export XDG_CACHE_HOME="${OC_DATA}/.cache"' "$PROFILE_SCRIPT" || fail "shell profile should export cache home into custom data root" +grep -Fq 'NPM_CONFIG_PREFIX="$OC_GLOBAL" \' "$INIT_SCRIPT" || fail "service environment should pass npm prefix into custom install root" +grep -Fq 'NPM_CONFIG_CACHE="${OC_DATA}/.npm" \' "$INIT_SCRIPT" || fail "service environment should pass npm cache into custom data root" +grep -Fq 'XDG_CACHE_HOME="${OC_DATA}/.cache" \' "$INIT_SCRIPT" || fail "service environment should pass cache home into custom data root" +grep -Fq 'NPM_CONFIG_PREFIX: OC_GLOBAL' "$WEB_PTY_SCRIPT" || fail "web PTY environment should pass npm prefix into custom install root" +grep -Fq 'NPM_CONFIG_CACHE: `${OC_DATA}/.npm`' "$WEB_PTY_SCRIPT" || fail "web PTY environment should pass npm cache into custom data root" +grep -Fq 'COREPACK_HOME: `${OC_DATA}/.cache/corepack`' "$WEB_PTY_SCRIPT" || fail "web PTY environment should pass corepack cache into custom data root" grep -Fq "https://github.com/hotwa/luci-app-openclaw/releases/latest" "$BASIC_LUA" || fail "UI should link manual download to hotwa repo" grep -Fq "ARM64 musl" "$BASIC_LUA" || fail "UI should mention ARM64 musl specific guidance" grep -Fq "hotwa/luci-app-openclaw" "$BASIC_LUA" || fail "UI should point ARM64 musl guidance at hotwa repo"