mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-31 07:05:13 +08:00
🎈 Sync 2026-06-08 16:57:14
This commit is contained in:
1 parent
a75bbbe729
commit
e41d0593c1
37 files changed
+275
-10683
No files matched your search
@@ -0,0 +1,3 @@
|
||||
tests/ export-ignore
|
||||
docs/notes/ export-ignore
|
||||
.claude/ export-ignore
|
||||
@@ -4,6 +4,37 @@
|
||||
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/)。
|
||||
|
||||
## [2.0.6] - 2026-06-08
|
||||
|
||||
### 适配 OpenClaw v2026.6.1
|
||||
|
||||
- `OC_TESTED_VERSION` 更新为 `2026.6.1`,默认稳定版跟随 npm `latest` 稳定标签。
|
||||
- 默认 Node.js 运行时更新为 `24.15.0`,最低要求同步提升到 `22.19.0`,匹配 OpenClaw 2026.6.x 的 `engines.node`。
|
||||
- 安装脚本不再从当前 Node 版本静默回退到旧版 V1 tarball,避免下载失败后装入过低 Node.js 并在 OpenClaw 安装后失败。
|
||||
- ARM64 musl 预编译 Node.js 构建流程更新为 `24.15.0`,并校验默认路径和自定义安装路径均可运行。
|
||||
|
||||
### 修复安装、控制台与状态体验
|
||||
|
||||
- Node.js 下载失败时保留明确失败路径,避免 ARM64 musl 缺少当前版本资产时误判为可继续安装。
|
||||
- Web 控制台改为新窗口打开,继续强制使用 HTTP Gateway URL 和最新 token,规避 LuCI HTTPS、iframe 安全头和旧 token 混用问题。
|
||||
- 状态接口和页面继续区分“运行中 / 启动中 / 启动失败”,并保留 procd Gateway 退出码,便于定位升级后的启动失败。
|
||||
- 保留微信插件安装预检和权限修复链路,覆盖 `python3`、`openclaw` 用户、npm cache、tmp 和数据目录权限。
|
||||
|
||||
### 测试
|
||||
|
||||
- 更新 OpenClaw/Node.js 版本契约测试。
|
||||
- 新增控制台新窗口、状态失败展示、ARM64 musl Node 打包与路径兼容契约测试。
|
||||
|
||||
### 致谢
|
||||
|
||||
感谢以下用户通过 Issue 或 PR 提供问题反馈、复现信息和修复思路:
|
||||
|
||||
- @djbadboyvip (#94)、@alan9771 (#93, #82)、@luckymai3688 (#92, #91)、@lucian521 (#90)
|
||||
- @svgr110 (#89)、@Cuscito (#88)、@ayysama (#87)、@jameslau-tech (#86)、@hwliu11 (#84)
|
||||
- @zhuxf8 (#81)、@yiyibuguai (#80)、@nbagui (#79)、@sam528300-lab (#78)、@hotwa (#85)
|
||||
|
||||
---
|
||||
|
||||
## [2.0.5] - 2026-05-15
|
||||
|
||||
### 适配 OpenClaw v2026.5.12
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-openclaw
|
||||
PKG_VERSION:=$(strip $(shell cat $(CURDIR)/VERSION 2>/dev/null || echo "1.0.0"))
|
||||
PKG_RELEASE:=15
|
||||
PKG_RELEASE:=16
|
||||
|
||||
PKG_MAINTAINER:=10000ge10000 <10000ge10000@users.noreply.github.com>
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
| 组件 | 默认版本 | 说明 |
|
||||
|------|----------|------|
|
||||
| OpenClaw | `2026.5.12` | npm `latest` 稳定标签;不默认追 `2026.5.14-beta.2` |
|
||||
| Node.js | `22.16.0` | 安装后会按 OpenClaw `engines.node` 做强校验,低于要求会直接失败 |
|
||||
| OpenClaw | `2026.6.1` | npm `latest` 稳定标签;不默认追 `2026.6.5-beta.2` |
|
||||
| Node.js | `24.15.0` | OpenClaw 2026.6.x 要求 `>=22.19.0`;安装后会按 `engines.node` 做强校验,低于要求会直接失败 |
|
||||
| 微信插件 | `@tencent-weixin/openclaw-weixin@2.4.3` | CLI 使用 `@tencent-weixin/openclaw-weixin-cli@2.1.4` |
|
||||
|
||||
## 📦 安装
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.0.5
|
||||
2.0.6
|
||||
@@ -71,6 +71,21 @@ grep -q '^openclaw:' /etc/group 2>/dev/null || echo "openclaw:x:${OC_GID}:" >> /
|
||||
return uid ~= ""
|
||||
end
|
||||
|
||||
local function find_wechat_plugin_dir(install_path)
|
||||
local sys = require "luci.sys"
|
||||
local ext_dir = install_path .. "/data/.openclaw/extensions/openclaw-weixin"
|
||||
if nixio.fs.stat(ext_dir .. "/openclaw.plugin.json", "type") then
|
||||
return ext_dir
|
||||
end
|
||||
local npm_projects = install_path .. "/data/.openclaw/npm/projects"
|
||||
local cmd = "find " .. shellquote(npm_projects) .. " -path '*/node_modules/@tencent-weixin/openclaw-weixin/openclaw.plugin.json' -type f 2>/dev/null | head -n 1"
|
||||
local plugin_json = sys.exec(cmd):match("[^\r\n]+")
|
||||
if plugin_json and plugin_json ~= "" then
|
||||
return plugin_json:gsub("/openclaw%.plugin%.json$", "")
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function write_wechat_log_and_exit(log_file, exit_file, content, exit_code)
|
||||
local f = io.open(log_file, "w")
|
||||
if f then
|
||||
@@ -1206,9 +1221,9 @@ function action_wechat_status()
|
||||
}
|
||||
|
||||
-- 检测微信插件是否已安装
|
||||
local wechat_ext_dir = install_path .. "/data/.openclaw/extensions/openclaw-weixin"
|
||||
local wechat_plugin_json = wechat_ext_dir .. "/openclaw.plugin.json"
|
||||
local wechat_package_json = wechat_ext_dir .. "/package.json"
|
||||
local wechat_ext_dir = find_wechat_plugin_dir(install_path)
|
||||
local wechat_plugin_json = wechat_ext_dir and (wechat_ext_dir .. "/openclaw.plugin.json") or ""
|
||||
local wechat_package_json = wechat_ext_dir and (wechat_ext_dir .. "/package.json") or ""
|
||||
|
||||
if nixio.fs.stat(wechat_plugin_json, "type") then
|
||||
result.plugin_installed = true
|
||||
@@ -1629,7 +1644,7 @@ function action_wechat_check_upgrade()
|
||||
|
||||
-- 获取当前已安装版本
|
||||
local current_version = ""
|
||||
local wechat_ext_dir = install_path .. "/data/.openclaw/extensions/openclaw-weixin"
|
||||
local wechat_ext_dir = find_wechat_plugin_dir(install_path) or (install_path .. "/data/.openclaw/extensions/openclaw-weixin")
|
||||
local plugin_json = wechat_ext_dir .. "/openclaw.plugin.json"
|
||||
local pf = io.open(plugin_json, "r")
|
||||
if pf then
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%#
|
||||
luci-app-openclaw — Web 控制台页面
|
||||
嵌入 OpenClaw 官方 Web UI,用户可在此配置模型/渠道并直接对话
|
||||
打开 OpenClaw 官方 Web UI,用户可在此配置模型/渠道并直接对话
|
||||
-%>
|
||||
<%+header%>
|
||||
|
||||
@@ -51,8 +51,6 @@ local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
|
||||
}
|
||||
|
||||
#oc-console-iframe { width: 100%; height: 700px; border: none; display: block; }
|
||||
|
||||
.oc-console-loading {
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
height: 300px; color: #666; font-size: 14px; background: #fafafa;
|
||||
@@ -135,7 +133,7 @@ local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
statusTextEl.innerHTML = '<span style="color:#1a7f37;">● 网关运行中</span>';
|
||||
openBtn.href = url;
|
||||
openBtn.style.display = '';
|
||||
showIframe(url);
|
||||
showLaunch(url);
|
||||
} else if (d.gateway_failed) {
|
||||
statusTextEl.innerHTML = '<span style="color:#cf222e;">● 网关启动失败</span>';
|
||||
openBtn.style.display = 'none';
|
||||
@@ -169,22 +167,13 @@ local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
});
|
||||
}
|
||||
|
||||
function showIframe(url) {
|
||||
function showLaunch(url) {
|
||||
loading.style.display = 'none';
|
||||
var existing = document.getElementById('oc-console-iframe');
|
||||
if (existing) {
|
||||
if (existing.src !== url) existing.src = url;
|
||||
return;
|
||||
}
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.id = 'oc-console-iframe';
|
||||
iframe.src = url;
|
||||
iframe.style.width = '100%';
|
||||
iframe.style.height = '700px';
|
||||
iframe.style.border = 'none';
|
||||
iframe.setAttribute('allowfullscreen', 'true');
|
||||
container.appendChild(iframe);
|
||||
container.innerHTML = '<div class="oc-console-loading" style="height:220px;">' +
|
||||
'<div style="font-size:40px;margin-bottom:12px;">↗</div>' +
|
||||
'<div style="font-size:15px;margin-bottom:6px;">OpenClaw 控制台已就绪</div>' +
|
||||
'<div style="font-size:12px;color:#999;">请点击上方「新窗口打开」访问控制台。</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
checkAndLoad();
|
||||
|
||||
@@ -15,7 +15,7 @@ EXTRA_HELP=" setup 下载 Node.js 并安装 OpenClaw
|
||||
# 统一路径解析可以兼容 /mnt/data/openclaw 输入,避免双拼路径。
|
||||
[ -r /usr/libexec/openclaw-paths.sh ] && . /usr/libexec/openclaw-paths.sh
|
||||
[ -r /usr/libexec/openclaw-node.sh ] && . /usr/libexec/openclaw-node.sh
|
||||
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.14.0}"
|
||||
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.19.0}"
|
||||
OC_CONFIGURED_PATH="$(uci -q get openclaw.main.install_path 2>/dev/null || echo '/opt')"
|
||||
if command -v oc_load_paths >/dev/null 2>&1; then
|
||||
if ! oc_load_paths "$OC_CONFIGURED_PATH"; then
|
||||
@@ -252,6 +252,9 @@ if(Array.isArray(d.plugins.allow)){
|
||||
delete d.plugins[ns].weixin;
|
||||
}
|
||||
});
|
||||
if(d.plugins.entries&&d.plugins.entries['openclaw-weixin']){
|
||||
delete d.plugins.entries['openclaw-weixin'];
|
||||
}
|
||||
['channel','channels'].forEach(ns=>{
|
||||
if(d[ns]&&d[ns].weixin){
|
||||
if(!d[ns]['openclaw-weixin'])d[ns]['openclaw-weixin']=d[ns].weixin;
|
||||
@@ -365,10 +368,35 @@ fi
|
||||
# v2026.4.10 补充: 同时修复权限模式为 755,确保 Gateway 可读取插件
|
||||
# 原因: npm/npx 以 root 创建目录时默认权限 700,其他用户无法读取
|
||||
local ext_dir="${OC_DATA}/.openclaw/extensions"
|
||||
local npm_projects_dir="${OC_DATA}/.openclaw/npm/projects"
|
||||
local wechat_legacy_dir="${ext_dir}/openclaw-weixin"
|
||||
local wechat_npm_plugin=""
|
||||
if [ -d "$npm_projects_dir" ]; then
|
||||
wechat_npm_plugin=$(find "$npm_projects_dir" -path "*/node_modules/@tencent-weixin/openclaw-weixin/openclaw.plugin.json" -type f 2>/dev/null | head -n 1)
|
||||
fi
|
||||
if [ -n "$wechat_npm_plugin" ] && [ -d "$wechat_legacy_dir" ]; then
|
||||
local archive_root="${OC_DATA}/.openclaw/archived-extensions"
|
||||
mkdir -p "$archive_root" 2>/dev/null || true
|
||||
local archived_dir="${archive_root}/openclaw-weixin.legacy.$(date +%Y%m%d%H%M%S)"
|
||||
mv "$wechat_legacy_dir" "$archived_dir" 2>/dev/null && logger -t openclaw "已归档旧微信扩展目录: $archived_dir"
|
||||
fi
|
||||
if [ -n "$wechat_npm_plugin" ] && [ -d "$ext_dir" ]; then
|
||||
local archive_root="${OC_DATA}/.openclaw/archived-extensions"
|
||||
mkdir -p "$archive_root" 2>/dev/null || true
|
||||
for stale_dir in "$ext_dir"/openclaw-weixin.legacy.*; do
|
||||
[ -d "$stale_dir" ] || continue
|
||||
local stale_name="${stale_dir##*/}"
|
||||
mv "$stale_dir" "${archive_root}/${stale_name}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
if [ -d "$ext_dir" ]; then
|
||||
chown -R root:root "$ext_dir" 2>/dev/null || true
|
||||
chmod -R 755 "$ext_dir" 2>/dev/null || true
|
||||
fi
|
||||
if [ -d "$npm_projects_dir" ]; then
|
||||
chown -R root:root "$npm_projects_dir" 2>/dev/null || true
|
||||
chmod -R 755 "$npm_projects_dir" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# v2026.4.x: 清理 jiti 缓存目录 (修复微信插件加载权限问题)
|
||||
# jiti 编译 TypeScript 时会在 /tmp/jiti 创建缓存,如果由 root 创建则 openclaw 用户无法写入
|
||||
@@ -486,8 +514,16 @@ if(d.gateway&&d.gateway.auth&&d.gateway.auth.token)process.stdout.write(d.gatewa
|
||||
# v2026.4.10: 最终权限修复 - 确保 Gateway 启动前所有数据目录权限正确
|
||||
# doctor --fix 或 _ensure_critical_config 可能创建新的目录/文件
|
||||
# 关键: agents 目录下的 agent 子目录必须可被 openclaw 用户写入
|
||||
find "${OC_DATA}/.openclaw" -user root -type d -exec chown openclaw:openclaw {} \; 2>/dev/null || true
|
||||
find "${OC_DATA}/.openclaw" -user root -type f -exec chown openclaw:openclaw {} \; 2>/dev/null || true
|
||||
find "${OC_DATA}/.openclaw" -user root \
|
||||
! -path "${OC_DATA}/.openclaw/extensions*" \
|
||||
! -path "${OC_DATA}/.openclaw/archived-extensions*" \
|
||||
! -path "${OC_DATA}/.openclaw/npm/projects*" \
|
||||
-type d -exec chown openclaw:openclaw {} \; 2>/dev/null || true
|
||||
find "${OC_DATA}/.openclaw" -user root \
|
||||
! -path "${OC_DATA}/.openclaw/extensions*" \
|
||||
! -path "${OC_DATA}/.openclaw/archived-extensions*" \
|
||||
! -path "${OC_DATA}/.openclaw/npm/projects*" \
|
||||
-type f -exec chown openclaw:openclaw {} \; 2>/dev/null || true
|
||||
# 特别确保 agents/main/agent 目录权限 (模型配置写入目录)
|
||||
local agent_dir="${OC_DATA}/.openclaw/agents/main/agent"
|
||||
if [ -d "$agent_dir" ]; then
|
||||
@@ -500,6 +536,14 @@ if(d.gateway&&d.gateway.auth&&d.gateway.auth.token)process.stdout.write(d.gatewa
|
||||
chown -R root:root "${OC_DATA}/.openclaw/extensions" 2>/dev/null || true
|
||||
chmod -R 755 "${OC_DATA}/.openclaw/extensions" 2>/dev/null || true
|
||||
fi
|
||||
if [ -d "${OC_DATA}/.openclaw/archived-extensions" ]; then
|
||||
chown -R root:root "${OC_DATA}/.openclaw/archived-extensions" 2>/dev/null || true
|
||||
chmod -R 700 "${OC_DATA}/.openclaw/archived-extensions" 2>/dev/null || true
|
||||
fi
|
||||
if [ -d "${OC_DATA}/.openclaw/npm/projects" ]; then
|
||||
chown -R root:root "${OC_DATA}/.openclaw/npm/projects" 2>/dev/null || true
|
||||
chmod -R 755 "${OC_DATA}/.openclaw/npm/projects" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Patch iframe 安全头,允许 LuCI 嵌入
|
||||
patch_iframe_headers
|
||||
|
||||
@@ -7,22 +7,22 @@
|
||||
# openclaw-env upgrade — 升级 OpenClaw 到最新版
|
||||
# openclaw-env node — 仅下载/更新 Node.js
|
||||
# 环境变量:
|
||||
# OC_VERSION — 指定 OpenClaw 版本 (如 2026.3.1),不设置则安装最新版
|
||||
# OC_VERSION — 指定 OpenClaw 版本 (如 2026.6.1),不设置则安装已测试稳定版
|
||||
# ============================================================================
|
||||
set -e
|
||||
|
||||
# ── Node.js 版本策略 (双版本兼容) ──
|
||||
# V2: 当前推荐版本,用于 OpenClaw v2026.3.22+ (要求 >= 22.14.0,使用 22.16.0 确保兼容)
|
||||
# V2: 当前推荐版本,用于 OpenClaw v2026.6.1+ (要求 >= 22.19.0,使用 24.15.0 确保兼容)
|
||||
# V1: 旧版兼容,用于 OpenClaw v2026.3.8 及更早版本
|
||||
NODE_VERSION_V2="22.16.0"
|
||||
NODE_VERSION_V2="24.15.0"
|
||||
NODE_VERSION_V1="22.15.1"
|
||||
# 默认使用 V2 版本 (可通过 NODE_VERSION 环境变量覆盖)
|
||||
NODE_VERSION="${NODE_VERSION:-${NODE_VERSION_V2}}"
|
||||
# 经过验证的 OpenClaw 稳定版本 (更新此值需同步测试)
|
||||
OC_TESTED_VERSION="2026.5.12"
|
||||
# OpenClaw 2026.5.x package.json engines.node 的最低要求。
|
||||
OC_TESTED_VERSION="2026.6.1"
|
||||
# OpenClaw 2026.6.x package.json engines.node 的最低要求。
|
||||
# 如果未来上游提高要求,安装成功后还会从 package.json 再做一次强校验。
|
||||
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.14.0}"
|
||||
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.19.0}"
|
||||
# 用户可通过 OC_VERSION 环境变量覆盖安装版本
|
||||
OC_VERSION="${OC_VERSION:-}"
|
||||
|
||||
@@ -216,7 +216,11 @@ assert_node_runtime() {
|
||||
local required="$OC_NODE_MIN_VERSION"
|
||||
local from_pkg
|
||||
from_pkg=$(detect_oc_node_requirement 2>/dev/null || true)
|
||||
[ -n "$from_pkg" ] && required="$from_pkg"
|
||||
if [ -n "$from_pkg" ] && command -v oc_node_version_ge >/dev/null 2>&1; then
|
||||
if oc_node_version_ge "$from_pkg" "$required"; then
|
||||
required="$from_pkg"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v oc_assert_node_min_version >/dev/null 2>&1; then
|
||||
oc_assert_node_min_version "$NODE_BIN" "$required" || exit 1
|
||||
@@ -258,12 +262,8 @@ download_node() {
|
||||
assert_node_runtime
|
||||
return 0
|
||||
fi
|
||||
# ARM64 musl 使用 Alpine 打包,版本号可能不完全匹配
|
||||
# 只要主版本号相同即认为兼容 (如 22.15.1 vs 22.15.0)
|
||||
local cur_major=$(echo "$current_ver" | cut -d. -f1)
|
||||
local want_major=$(echo "$node_ver" | cut -d. -f1)
|
||||
if [ "$cur_major" = "$want_major" ]; then
|
||||
log_info "Node.js v${current_ver} 已安装 (兼容 v${node_ver}), 跳过下载"
|
||||
if command -v oc_node_version_ge >/dev/null 2>&1 && oc_node_version_ge "$current_ver" "$node_ver"; then
|
||||
log_info "Node.js v${current_ver} 已安装 (>= v${node_ver}), 跳过下载"
|
||||
assert_node_runtime
|
||||
return 0
|
||||
fi
|
||||
@@ -285,11 +285,6 @@ download_node() {
|
||||
mirror_list="${NODE_SELF_HOST}/${musl_tarball}"
|
||||
# 2) unofficial-builds (留作将来可能支持)
|
||||
mirror_list="$mirror_list ${NODE_MUSL_MIRROR}/v${node_ver}/${musl_tarball}"
|
||||
# 3) 回退到 V1 版本 (兼容旧环境,仅当请求 V2 时)
|
||||
if [ "$node_ver" = "$NODE_VERSION_V2" ]; then
|
||||
local v1_tarball="node-v${NODE_VERSION_V1}-${node_arch}-musl.tar.xz"
|
||||
mirror_list="$mirror_list ${NODE_SELF_HOST}/${v1_tarball}"
|
||||
fi
|
||||
else
|
||||
# x64 musl: unofficial-builds 提供
|
||||
# 1) unofficial-builds
|
||||
|
||||
@@ -606,7 +606,11 @@ show_current_config() {
|
||||
|
||||
# 检测微信渠道
|
||||
local wechat_ext_dir="${OC_STATE_DIR}/extensions/openclaw-weixin"
|
||||
if [ -d "$wechat_ext_dir" ] && [ -f "${wechat_ext_dir}/openclaw.plugin.json" ]; then
|
||||
local wechat_npm_plugin=""
|
||||
if [ -d "${OC_STATE_DIR}/npm/projects" ]; then
|
||||
wechat_npm_plugin=$(find "${OC_STATE_DIR}/npm/projects" -path "*/node_modules/@tencent-weixin/openclaw-weixin/openclaw.plugin.json" -type f 2>/dev/null | head -n 1)
|
||||
fi
|
||||
if { [ -d "$wechat_ext_dir" ] && [ -f "${wechat_ext_dir}/openclaw.plugin.json" ]; } || [ -n "$wechat_npm_plugin" ]; then
|
||||
echo -e "${GREEN}│${NC} 微信 .............. ${GREEN}✅ 已配置${NC}"
|
||||
else
|
||||
echo -e "${GREEN}│${NC} 微信 .............. ${YELLOW}❌ 未配置${NC}"
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
# ============================================================================
|
||||
set -e
|
||||
|
||||
INSTALL_PREFIX="/opt/openclaw/node"
|
||||
BUILD_MODE="${BUILD_MODE:-apk}"
|
||||
|
||||
echo "=== Node.js ARM64 musl Build ==="
|
||||
@@ -198,10 +197,10 @@ finalize_package() {
|
||||
|
||||
# 用 patchelf 修改 node 二进制
|
||||
echo "=== Patching ELF binary ==="
|
||||
patchelf --set-interpreter "${INSTALL_PREFIX}/lib/ld-musl-aarch64.so.1" "${PKG_DIR}/bin/node"
|
||||
patchelf --set-rpath "${INSTALL_PREFIX}/lib" "${PKG_DIR}/bin/node"
|
||||
echo " interpreter: ${INSTALL_PREFIX}/lib/ld-musl-aarch64.so.1"
|
||||
echo " rpath: ${INSTALL_PREFIX}/lib"
|
||||
patchelf --set-interpreter "/lib/ld-musl-aarch64.so.1" "${PKG_DIR}/bin/node"
|
||||
patchelf --set-rpath '$ORIGIN/../lib' "${PKG_DIR}/bin/node"
|
||||
echo " interpreter: /lib/ld-musl-aarch64.so.1"
|
||||
echo " rpath: \$ORIGIN/../lib"
|
||||
|
||||
# 创建 node wrapper 脚本
|
||||
cat > "${PKG_DIR}/bin/node-wrapper" << 'NODEWRAPPER'
|
||||
@@ -229,20 +228,21 @@ exec "${SELF_DIR}/node" "${SELF_DIR}/../lib/node_modules/npm/bin/npx-cli.js" "$@
|
||||
NPXWRAPPER
|
||||
chmod +x "${PKG_DIR}/bin/npm" "${PKG_DIR}/bin/npx"
|
||||
|
||||
# 验证
|
||||
echo "=== Verification ==="
|
||||
mkdir -p "${INSTALL_PREFIX}"
|
||||
cp -a "${PKG_DIR}"/* "${INSTALL_PREFIX}/"
|
||||
|
||||
# 设置库路径并测试
|
||||
export LD_LIBRARY_PATH="${INSTALL_PREFIX}/lib"
|
||||
|
||||
"${INSTALL_PREFIX}/bin/node" --version
|
||||
"${INSTALL_PREFIX}/bin/node" -e "console.log('execPath:', process.execPath)"
|
||||
"${INSTALL_PREFIX}/bin/node" -e "console.log(process.arch, process.platform, process.versions.modules)"
|
||||
NODE_ICU_DATA="${INSTALL_PREFIX}/share/icu" "${INSTALL_PREFIX}/bin/npm" --version 2>/dev/null || echo "npm needs ICU data"
|
||||
|
||||
rm -rf "${INSTALL_PREFIX}"
|
||||
verify_prefix() {
|
||||
local prefix="$1"
|
||||
echo "=== Verifying prefix: ${prefix} ==="
|
||||
rm -rf "$prefix"
|
||||
mkdir -p "$prefix"
|
||||
cp -a "${PKG_DIR}"/* "$prefix/"
|
||||
"${prefix}/bin/node" --version
|
||||
"${prefix}/bin/node" -e "console.log('execPath:', process.execPath)"
|
||||
"${prefix}/bin/node" -e "console.log(process.arch, process.platform, process.versions.modules)"
|
||||
NODE_ICU_DATA="${prefix}/share/icu" "${prefix}/bin/npm" --version 2>/dev/null || echo "npm needs ICU data"
|
||||
rm -rf "$prefix"
|
||||
}
|
||||
|
||||
verify_prefix /opt/openclaw/node
|
||||
verify_prefix /tmp/custom-openclaw-root/openclaw/node
|
||||
|
||||
# 打包
|
||||
echo "=== Creating tarball ==="
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
CONSOLE_VIEW="$REPO_ROOT/luasrc/view/openclaw/console.htm"
|
||||
|
||||
fail() {
|
||||
echo "FAIL: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
grep -Fq "var url = 'http://' + host + ':' + gwPort + '/'" "$CONSOLE_VIEW" || fail "console view should force HTTP gateway URL"
|
||||
grep -Fq '请点击上方「新窗口打开」访问控制台。' "$CONSOLE_VIEW" || fail "console view should direct users to a new window"
|
||||
|
||||
if grep -Fq "document.createElement('iframe')" "$CONSOLE_VIEW"; then
|
||||
fail "console view should not embed the OpenClaw UI in an iframe"
|
||||
fi
|
||||
|
||||
if grep -Fq 'window.location.protocol' "$CONSOLE_VIEW"; then
|
||||
fail "console view should not reuse the LuCI page protocol for the gateway URL"
|
||||
fi
|
||||
|
||||
cr=$(printf '\r')
|
||||
if LC_ALL=C grep -q "$cr" "$CONSOLE_VIEW"; then
|
||||
fail "console view should use LF line endings"
|
||||
fi
|
||||
|
||||
echo "ok"
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
BUILD_SCRIPT="$REPO_ROOT/scripts/build-node-musl.sh"
|
||||
WORKFLOW="$REPO_ROOT/.github/workflows/build-node-musl.yml"
|
||||
ENV_SCRIPT="$REPO_ROOT/root/usr/bin/openclaw-env"
|
||||
|
||||
fail() {
|
||||
echo "FAIL: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
grep -Fq 'patchelf --set-interpreter "/lib/ld-musl-aarch64.so.1"' "$BUILD_SCRIPT" || fail "build script should use system musl loader"
|
||||
grep -Fq '$ORIGIN/../lib' "$BUILD_SCRIPT" || fail "build script should use relative rpath"
|
||||
if grep -Fq 'patchelf --set-interpreter "${INSTALL_PREFIX}/lib/ld-musl-aarch64.so.1"' "$BUILD_SCRIPT"; then
|
||||
fail "build script should not hardcode interpreter to install prefix"
|
||||
fi
|
||||
|
||||
grep -Fq 'verify_prefix /opt/openclaw/node' "$BUILD_SCRIPT" || fail "build script should verify default install path"
|
||||
grep -Fq 'verify_prefix /tmp/custom-openclaw-root/openclaw/node' "$BUILD_SCRIPT" || fail "build script should verify custom install path"
|
||||
grep -Fq 'NODE_VER="24.15.0"' "$WORKFLOW" || fail "workflow should build current Node.js"
|
||||
grep -Fq 'BUILD_MODE=cross' "$WORKFLOW" || fail "workflow should use cross mode for current ARM64 musl package"
|
||||
|
||||
grep -Fq 'oc_node_version_ge "$current_ver" "$node_ver"' "$ENV_SCRIPT" || fail "installer should require installed Node.js to satisfy target version"
|
||||
if grep -Fq 'v1_tarball' "$ENV_SCRIPT"; then
|
||||
fail "installer should not auto-fallback from current Node.js to legacy tarball"
|
||||
fi
|
||||
|
||||
echo "ok"
|
||||
@@ -6,8 +6,14 @@ fail() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
grep -q "OC_TESTED_VERSION=\"2026.5.12\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned"
|
||||
grep -q "OC_TESTED_VERSION=\"2026.6.1\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned"
|
||||
grep -q "NODE_VERSION_V2=\"24.15.0\"" root/usr/bin/openclaw-env || fail "default Node.js version not pinned"
|
||||
grep -q "OC_NODE_MIN_VERSION=\"\${OC_NODE_MIN_VERSION:-22.19.0}\"" root/usr/bin/openclaw-env || fail "minimum Node.js version not pinned"
|
||||
grep -q "oc_assert_node_min_version" root/usr/bin/openclaw-env || fail "Node.js minimum version check missing"
|
||||
grep -q 'oc_node_version_ge "$from_pkg" "$required"' root/usr/bin/openclaw-env || fail "package Node.js requirement must not lower static minimum"
|
||||
if grep -q 'v1_tarball' root/usr/bin/openclaw-env; then
|
||||
fail "installer must not silently fall back to legacy Node.js tarball"
|
||||
fi
|
||||
|
||||
grep -q "wechat.htm" Makefile || fail "Makefile must install wechat.htm"
|
||||
grep -q "luci-app-openclaw.json" Makefile || fail "Makefile must install rpcd ACL"
|
||||
@@ -31,9 +37,18 @@ grep -q "command -v python3" luasrc/controller/openclaw.lua || fail "wechat inst
|
||||
grep -q "ensure_openclaw_user" luasrc/controller/openclaw.lua || fail "wechat install must ensure openclaw user"
|
||||
grep -q "NPM_CONFIG_CACHE" luasrc/controller/openclaw.lua || fail "wechat install must set npm cache"
|
||||
grep -q "openclaw-weixin" root/etc/init.d/openclaw || fail "weixin channel migration missing"
|
||||
grep -q "delete d.plugins.entries\\['openclaw-weixin'\\]" root/etc/init.d/openclaw || fail "weixin duplicate entries cleanup missing"
|
||||
grep -q "npm/projects" root/etc/init.d/openclaw || fail "npm plugin project ownership fix missing"
|
||||
grep -q "! -path.*npm/projects" root/etc/init.d/openclaw || fail "npm plugin projects should be excluded from openclaw ownership reset"
|
||||
grep -q "archived-extensions" root/etc/init.d/openclaw || fail "legacy weixin extension archive missing"
|
||||
grep -q "find_wechat_plugin_dir" luasrc/controller/openclaw.lua || fail "wechat npm plugin detection missing"
|
||||
grep -q "@tencent-weixin/openclaw-weixin/openclaw.plugin.json" root/usr/share/openclaw/oc-config.sh || fail "oc-config wechat npm detection missing"
|
||||
|
||||
grep -q "var url = 'http://'" luasrc/view/openclaw/console.htm || fail "console must force HTTP gateway URL"
|
||||
grep -q "existing.src" luasrc/view/openclaw/console.htm || fail "console iframe must refresh token URL"
|
||||
grep -q "新窗口打开" luasrc/view/openclaw/console.htm || fail "console must expose a new-window entry"
|
||||
if grep -q "document.createElement('iframe')" luasrc/view/openclaw/console.htm; then
|
||||
fail "console must not embed OpenClaw in an iframe"
|
||||
fi
|
||||
|
||||
grep -q "root/usr/libexec" scripts/build_ipk.sh || fail "ipk script must package shell helpers"
|
||||
grep -q "root/usr/libexec" scripts/build_run.sh || fail "run script must package shell helpers"
|
||||
|
||||
@@ -8,11 +8,11 @@ fail() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ "$(oc_normalize_node_version v22.16.0)" = "22.16.0" ] || fail "normalize v"
|
||||
oc_node_version_ge 22.16.0 22.16.0 || fail "exact version"
|
||||
oc_node_version_ge 22.16.1 22.16.0 || fail "patch version"
|
||||
oc_node_version_ge 23.0.0 22.16.0 || fail "major version"
|
||||
if oc_node_version_ge 22.15.1 22.16.0; then
|
||||
[ "$(oc_normalize_node_version v24.15.0)" = "24.15.0" ] || fail "normalize v"
|
||||
oc_node_version_ge 22.19.0 22.19.0 || fail "exact version"
|
||||
oc_node_version_ge 22.19.1 22.19.0 || fail "patch version"
|
||||
oc_node_version_ge 24.15.0 22.19.0 || fail "major version"
|
||||
if oc_node_version_ge 22.18.1 22.19.0; then
|
||||
fail "older minor accepted"
|
||||
fi
|
||||
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
||||
REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
CONTROLLER="$REPO_ROOT/luasrc/controller/openclaw.lua"
|
||||
STATUS_VIEW="$REPO_ROOT/luasrc/view/openclaw/status.htm"
|
||||
INIT_SCRIPT="$REPO_ROOT/root/etc/init.d/openclaw"
|
||||
|
||||
fail() {
|
||||
echo "FAIL: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
grep -Fq "ubus call service list" "$CONTROLLER" || fail "status API should inspect procd state via ubus"
|
||||
grep -Fq "openclaw.instances.gateway" "$CONTROLLER" || fail "status API should inspect gateway instance state"
|
||||
grep -Fq "gateway_failed" "$CONTROLLER" || fail "status API should report gateway failure state"
|
||||
grep -Fq "gateway_exit_code" "$CONTROLLER" || fail "status API should expose recent gateway exit code"
|
||||
|
||||
grep -Fq "启动失败" "$STATUS_VIEW" || fail "status panel should distinguish startup failure from startup in progress"
|
||||
grep -Fq "gateway_failed" "$STATUS_VIEW" || fail "status panel should render gateway failure state"
|
||||
|
||||
grep -Fq "ubus call service list" "$INIT_SCRIPT" || fail "status_service should inspect procd state via ubus"
|
||||
|
||||
echo "ok"
|
||||
Reference in new issue
Block a user