🎁 Sync 2026-08-22 20:30:10

This commit is contained in:
github-actions[bot] committed 2026-08-22 20:30:10 +08:00
1 parent 1f21cc80aa
commit 5a64dc251d
20 files changed
+272 -42

No files matched your search

+16 -3
View File
@@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk
PKG_ARCH_BAIDUDRIVE:=$(ARCH)
PKG_NAME:=baidudrive
PKG_VERSION:=linkeasefull-runtime-v3.0.11
PKG_RELEASE:=14
PKG_VERSION:=kaiplus-runtime-v1.0.5
PKG_RELEASE:=15
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/baidudrive-runtime-v$(PKG_VERSION)/
PKG_HASH:=skip
@@ -41,6 +41,16 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/baidudrive
endef
define Package/$(PKG_NAME)/prerm
#!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json 2>/dev/null)" = "/usr/share/baidudrive/baidudrive-plugin.json" ]; then
rm -f /usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json
fi
fi
exit 0
endef
define Build/Configure
endef
@@ -48,8 +58,11 @@ define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/baidudrive $(1)/opt/baidunas-sdk $(1)/opt/baidunas-glibc $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/baidudrive $(1)/usr/share/baidudrive/www $(1)/usr/share/linkeasefull/desktop-apps.d $(1)/opt/baidunas-sdk $(1)/opt/baidunas-glibc $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/baidudrive.$(PKG_ARCH_BAIDUDRIVE) $(1)/usr/sbin/baidudrive
$(CP) $(PKG_BUILD_DIR)/web/dist/. $(1)/usr/share/baidudrive/www/
$(INSTALL_DATA) ./files/baidudrive-plugin.json $(1)/usr/share/baidudrive/baidudrive-plugin.json
ln -sf /usr/share/baidudrive/baidudrive-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/10-baidudrive-plugin.json
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/baiduNas $(1)/opt/baidunas-sdk/baiduNas
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/P2PClient.bin $(1)/opt/baidunas-sdk/P2PClient.bin
$(INSTALL_DATA) $(PKG_BUILD_DIR)/nas_sdk/$(PKG_ARCH_BAIDUDRIVE)/libkernel.so $(1)/opt/baidunas-sdk/libkernel.so
+33
View File
@@ -0,0 +1,33 @@
{
"schemaVersion": 1,
"id": "baidudrive",
"name": "BaiduDrive",
"icon": "baidu-drive.png",
"staticRoot": "/usr/share/baidudrive/www",
"desktop": {
"mode": "module",
"entry": "desktop-entry.js",
"isolation": "shadow-dom"
},
"standalone": {
"entry": "index.html",
"basePath": "/apps/baidudrive/"
},
"backend": {
"type": "http",
"scheme": "http",
"host": "127.0.0.1",
"portFromUci": "baidudrive.@baidudrive[0].port",
"defaultPort": 10780,
"upstreamBasePath": "/apps/baidudrive/",
"apiPath": "api/",
"pathMode": "preserve"
},
"window": {
"width": 1180,
"height": 760,
"singleton": true
},
"capabilities": ["cloud-drive", "sync", "transfer"],
"categories": ["other"]
}
+1 -1
View File
@@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=filebrowser
PKG_VERSION:=1.5.2-stable
PKG_VERSION:=1.5.3-stable
PKG_RELEASE=1
ifeq ($(ARCH),aarch64)
+17 -4
View File
@@ -9,10 +9,10 @@ include $(TOPDIR)/rules.mk
PKG_ARCH_kaiplus:=$(ARCH)
PKG_NAME:=kaiplus
PKG_VERSION:=1.0.5
PKG_RELEASE:=4
PKG_VERSION:=kaiplus-runtime-v1.0.5
PKG_RELEASE:=5
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/kaiplus/
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/kaiplus-runtime-v$(PKG_VERSION)/
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION)
@@ -37,6 +37,16 @@ define Package/$(PKG_NAME)/conffiles
/etc/config/kaiplus
endef
define Package/$(PKG_NAME)/prerm
#!/bin/sh
if [ "$${IPKG_INSTROOT}" = "" ]; then
if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json 2>/dev/null)" = "/usr/share/kaiplus/kaiplus-plugin.json" ]; then
rm -f /usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json
fi
fi
exit 0
endef
define Build/Configure
endef
@@ -44,11 +54,14 @@ define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/kaiplus/www $(1)/usr/share/kaiplus/defaults $(1)/usr/share/kaiplus/helpers $(1)/etc/init.d $(1)/etc/config
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/kaiplus/www $(1)/usr/share/kaiplus/defaults $(1)/usr/share/kaiplus/helpers $(1)/usr/share/linkeasefull/desktop-apps.d $(1)/etc/init.d $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/kaiplus_bin.$(PKG_ARCH_kaiplus) $(1)/usr/sbin/kaiplus_bin
$(CP) $(PKG_BUILD_DIR)/www/* $(1)/usr/share/kaiplus/www/
$(INSTALL_DATA) ./files/logo.png $(1)/usr/share/kaiplus/www/logo.png
$(CP) $(PKG_BUILD_DIR)/defaults/* $(1)/usr/share/kaiplus/defaults/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helpers/kaiplus_workspace_tool.* $(1)/usr/share/kaiplus/helpers/
$(INSTALL_DATA) ./files/kaiplus-plugin.json $(1)/usr/share/kaiplus/kaiplus-plugin.json
ln -sf /usr/share/kaiplus/kaiplus-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/00-kaiplus-plugin.json
$(INSTALL_BIN) ./files/kaiplus.init $(1)/etc/init.d/kaiplus
$(INSTALL_CONF) ./files/kaiplus.config $(1)/etc/config/kaiplus
endef
+33
View File
@@ -0,0 +1,33 @@
{
"schemaVersion": 1,
"id": "kaiplus",
"name": "KaiPlus",
"icon": "logo.png",
"staticRoot": "/usr/share/kaiplus/www",
"desktop": {
"mode": "module",
"entry": "desktop-entry.js",
"isolation": "shadow-dom"
},
"standalone": {
"entry": "index.html",
"basePath": "/apps/kaiplus/"
},
"backend": {
"type": "http",
"scheme": "http",
"host": "127.0.0.1",
"portFromUci": "kaiplus.@kaiplus[0].port",
"defaultPort": 8189,
"upstreamBasePath": "/apps/kaiplus/",
"apiPath": "api/",
"pathMode": "preserve"
},
"window": {
"width": 1180,
"height": 760,
"singleton": true
},
"capabilities": ["assistant", "chat"],
"categories": ["other"]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+2 -2
View File
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease-common-bin
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=1.7.5
PKG_RELEASE:=12
PKG_RELEASE:=13
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c
endif
PKG_SOURCE_VERSION:=731629bd526b5215e0a0ad39eb740d45bb458ec5
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
+2 -2
View File
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=1.7.5
PKG_RELEASE:=15
PKG_RELEASE:=16
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c
endif
PKG_SOURCE_VERSION:=731629bd526b5215e0a0ad39eb740d45bb458ec5
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
+3 -3
View File
@@ -10,8 +10,8 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkeasefull
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=3.0.11
PKG_RELEASE:=14
PKG_SOURCE_DATE:=3.0.12
PKG_RELEASE:=15
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -24,7 +24,7 @@ LINKEASE_RUNTIME_ARCH:=arm64
PKG_HASH:=skip
endif
PKG_SOURCE_VERSION:=731629bd526b5215e0a0ad39eb740d45bb458ec5
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
PKG_SOURCE:=linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkeasefull-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH)
+26
View File
@@ -4,6 +4,32 @@
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/)。
## [2.0.12] - 2026-08-22
### 适配 OpenClaw v2026.7.1-2
- `OC_TESTED_VERSION` 更新为 `2026.7.1-2`(npm `latest` 稳定标签),稳定版安装走该版本号。
- Node.js 最低要求从 `22.19.0` 提升到 `22.22.3`,对齐 OpenClaw 2026.7.x 的 `engines.node`;默认 Node 仍为 `22.23.0`(musl LTS),无需重新下载。
- 微信插件维持 `@tencent-weixin/openclaw-weixin@2.4.6`(上游最新稳定版)。
- 适配 2026.7.x 插件目录所有权安全检查:`doctor --fix`(init.d 版本迁移)与配置终端的 `doctor` 诊断改为以 `openclaw` 服务用户执行,避免 root 上下文把 openclaw 属主的微信插件判为 suspicious ownership 后自动清理 `plugins.allow` / `channels` 配置。
- doctor 版本标记提取正则保留补丁后缀(`2026.7.1-2`),避免上游补丁版迭代时跳过配置迁移。
- 修复 CI 中 `OC_TESTED_VERSION` 提取正则无法匹配带连字符版本号(如 `2026.7.1-2`)的问题。
### 修复
- 修复微信插件安装/登录最后一步必然失败的问题:启用插件的内置 JS 使用了 `path.dirname` 却未 `require('path')`,导致 `ReferenceError`(对应 #88、#96)。
- 修复 LuCI 停止/重启网关时优雅停止命令失效的问题:裸 `openclaw gateway stop` 在 uhttpd 环境 PATH 不可达,改为调用安装目录 CLI wrapper 全路径(对应 #100)。
- LuCI 侧安全根目录白名单回退实现与 `paths.lua` 对齐(补 `/openclaw`、`/srv/*/openclaw`、`/overlay/upper/opt/openclaw`)。
- `/etc/config/openclaw` 补充 `pty_token` 字段声明,配置结构自文档化。
### 优化
- Node.js 下载增加 SHA256 完整性校验:官方 / unofficial-builds / npmmirror 镜像拉取同目录 `SHASUMS256.txt` 比对;自托管 `node-bins` 资产优先校验 `.sha256` 边车文件,旧资产无哈希时降级为体积检查并告警。
- CI 构建流程新增契约测试步骤(`tests/` 全部 shell + lua 测试),版本断言不同步将直接阻断发布。
- README 修正:移除目录结构中不存在的 `download_deps.sh`;Release 产物说明与 CI 实际行为对齐。
---
## [2.0.11] - 2026-07-10
### 修复微信扫码后 Gateway 丢失插件
+1 -1
View File
@@ -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:=24
PKG_RELEASE:=25
PKG_MAINTAINER:=10000ge10000 <10000ge10000@users.noreply.github.com>
PKG_LICENSE:=GPL-3.0
+4 -4
View File
@@ -27,8 +27,8 @@
| 组件 | 默认版本 | 说明 |
|------|----------|------|
| OpenClaw | `2026.6.11` | npm `latest` 稳定标签 |
| Node.js | `22.23.0` | Alpine musl LTS 包;OpenClaw 2026.6.x 要求 `>=22.19.0`,安装后会按 `engines.node` 做强校验 |
| OpenClaw | `2026.7.1-2` | npm `latest` 稳定标签 |
| Node.js | `22.23.0` | Alpine musl LTS 包;OpenClaw 2026.7.x 要求 `>=22.22.3`,安装后会按 `engines.node` 做强校验 |
| 微信插件 | `@tencent-weixin/openclaw-weixin@2.4.6` | CLI 使用 `@tencent-weixin/openclaw-weixin-cli@2.1.4` |
## 📦 安装
@@ -143,7 +143,7 @@ opkg install python3-light
## 已知说明
- OpenClaw 的 diagnostic heartbeat 可能在日志中出现类似周期性探测记录。它不是一次真实用户对话请求;如需降低噪音,优先在 OpenClaw 配置或日志采集侧降低诊断日志级别,不建议直接修改模型调用逻辑。
- 当前仓库提供源码、OpenWrt feeds 集成方式、本地 `.run` / `.ipk` 构建脚本入口;本次维护不自动生成 Release 产物。
- 当前仓库提供源码、OpenWrt feeds 集成方式、本地 `.run` / `.ipk` 构建脚本入口;推送 `v*` 标签后 CI 会自动构建并发布 Release 产物。
## 📂 目录结构
@@ -171,7 +171,7 @@ luci-app-openclaw/
├── scripts/
│ ├── build_ipk.sh # 本地 IPK 构建
│ ├── build_run.sh # .run 安装包构建
│ ├── download_deps.sh # 下载离线依赖 (Node.js + OpenClaw)
│ ├── gen-release-body.sh # Release 说明生成
│ └── build-node-musl.sh # 编译 Node.js musl 静态链接版本
└── .github/workflows/
├── build.yml # 在线构建 + 发布
+1 -1
View File
@@ -1 +1 @@
2.0.11
2.0.12
@@ -49,7 +49,9 @@ local function is_safe_openclaw_root(value)
if paths_ok and oc_paths.is_safe_openclaw_root then
return oc_paths.is_safe_openclaw_root(value)
end
return value == "/opt/openclaw" or value:match("^/mnt/[^/]+/openclaw$") ~= nil or value:match("^/media/[^/]+/openclaw$") ~= nil
-- 与 luasrc/openclaw/paths.lua 的白名单保持一致(此处仅作模块加载失败时的兜底)
if value == "/openclaw" or value == "/opt/openclaw" or value == "/overlay/upper/opt/openclaw" then return true end
return value:match("^/mnt/[^/]+/openclaw$") ~= nil or value:match("^/media/[^/]+/openclaw$") ~= nil or value:match("^/srv/[^/]+/openclaw$") ~= nil
end
local function compare_versions(a, b)
@@ -120,6 +122,7 @@ local function wechat_enable_plugin_config_cmd(install_path, node_bin, log_file,
local config_file = oc_data .. "/.openclaw/openclaw.json"
local register_js = [[
const fs = require('fs');
const path = require('path');
const configPath = process.env.OC_CONFIG;
let d = {};
try {
@@ -385,12 +388,19 @@ local function get_install_path()
end
-- 确保网关端口可用:检测占用并尝试优雅停止或强制杀死占用进程
-- 优雅停止必须走安装目录里的 CLI wrapper 全路径:uhttpd 进程不加载
-- /etc/profile.d,裸 `openclaw` 在 LuCI 环境下必然 PATH 不可达。
local function gateway_graceful_stop_cmd()
local oc_cli = get_install_path() .. "/global/bin/openclaw"
return "if [ -x " .. shellquote(oc_cli) .. " ]; then " .. shellquote(oc_cli) .. " gateway stop >/dev/null 2>&1 || true; fi"
end
local function ensure_port_free(port)
local sys = require "luci.sys"
if not port or port == "" then return end
if not tostring(port):match("^%d+$") then return end
-- 优先尝试使用 openclaw 自身的 stop 命令(如果已安装)
sys.exec("openclaw gateway stop >/dev/null 2>&1 || true")
sys.exec(gateway_graceful_stop_cmd())
-- 查询占用端口的行
local check_cmd = ""
@@ -407,7 +417,7 @@ local function ensure_port_free(port)
pid = pid and pid:gsub("%s+", "") or nil
if pid and pid ~= "" then
-- 再次尝试优雅停止
sys.exec("openclaw gateway stop >/dev/null 2>&1 || true")
sys.exec(gateway_graceful_stop_cmd())
-- 发送 SIGTERM
sys.exec("kill -TERM " .. pid .. " >/dev/null 2>&1 || true")
-- 等待释放,最多等待 5 次(每次 1s)
@@ -4,4 +4,5 @@ config openclaw 'main'
option bind 'lan'
option token ''
option pty_port '18793'
option pty_token ''
option install_path '/opt'
+25 -5
View File
@@ -607,13 +607,35 @@ if(changed){
# v2026.4.10: 优化配置迁移 - 只在版本变更时运行 doctor --fix
# 原因: doctor --fix 耗时 ~50 秒,每次重启都运行严重影响启动速度
# 策略: 使用标记文件记录已运行的版本,只在版本变化时才执行迁移
# v2026.7.1: doctor --fix 改为以 openclaw 服务用户执行。
# OpenClaw 2026.7.x 的插件安全检查按当前进程 uid 校验插件目录属主
# (属主必须等于进程 uid 或为 root)。root 身份运行 doctor 会把
# openclaw 属主的微信插件目录判为 suspicious ownership,进而自动
# 清理 plugins.allow / channels 中的微信配置。
_run_doctor_fix() {
local oc_entry="$1"
local _doc_cmd="HOME=\"${OC_DATA}\" OPENCLAW_HOME=\"${OC_DATA}\" OPENCLAW_STATE_DIR=\"${OC_DATA}/.openclaw\" OPENCLAW_CONFIG_PATH=\"${CONFIG_FILE}\" NODE_ICU_DATA=\"${NODE_BASE}/share/icu\" \"${NODE_BIN}\" \"${oc_entry}\" doctor --fix"
if id openclaw >/dev/null 2>&1; then
if command -v su >/dev/null 2>&1; then
su -s /bin/sh openclaw -c "${_doc_cmd}" >/dev/null 2>&1
elif command -v runuser >/dev/null 2>&1; then
runuser -u openclaw -- sh -c "${_doc_cmd}" >/dev/null 2>&1
else
start-stop-daemon -S -m -p /tmp/openclaw-doctor.pid -c openclaw:openclaw -x /bin/sh -- -c "${_doc_cmd}" >/dev/null 2>&1
fi
else
# openclaw 用户不存在时退回 root 执行,保证迁移仍可运行
eval "${_doc_cmd}" >/dev/null 2>&1
fi
}
_run_config_migration() {
local oc_entry="$1"
[ -z "$oc_entry" ] && return
# 获取当前 OpenClaw 版本号 (只取数字版本,如 2026.4.9)
# 获取当前 OpenClaw 版本号 (含补丁后缀,如 2026.7.1-2)
local current_ver=""
current_ver=$("$NODE_BIN" "$oc_entry" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
current_ver=$("$NODE_BIN" "$oc_entry" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?' | head -1)
[ -z "$current_ver" ] && current_ver="unknown"
# 检查标记文件
@@ -626,9 +648,7 @@ if(changed){
# 只在版本变化时才运行 doctor --fix
if [ "$current_ver" != "$last_ver" ]; then
logger -t openclaw "检测到版本变更 ($last_ver -> $current_ver),执行配置迁移 (doctor --fix)..."
OPENCLAW_HOME="$OC_DATA" OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \
NODE_ICU_DATA="${NODE_BASE}/share/icu" PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:$PATH" \
"$NODE_BIN" "$oc_entry" doctor --fix 2>/dev/null && \
_run_doctor_fix "$oc_entry" && \
logger -t openclaw "配置迁移完成" || \
logger -t openclaw "配置迁移失败,请手动检查"
# 更新标记文件
+60 -7
View File
@@ -7,22 +7,22 @@
# openclaw-env upgrade — 升级 OpenClaw 到最新版
# openclaw-env node — 仅下载/更新 Node.js
# 环境变量:
# OC_VERSION — 指定 OpenClaw 版本 (如 2026.6.11),不设置则安装已测试稳定版
# OC_VERSION — 指定 OpenClaw 版本 (如 2026.7.1-2),不设置则安装已测试稳定版
# ============================================================================
set -e
# ── Node.js 版本策略 (双版本兼容) ──
# V2: 当前推荐版本,用于 OpenClaw v2026.6.11+ (要求 >= 22.19.0,使用 Alpine musl LTS 包确保可运行)
# V2: 当前推荐版本,用于 OpenClaw v2026.7.1-2+ (要求 >= 22.22.3,使用 Alpine musl LTS 包确保可运行)
# V1: 旧版兼容,用于 OpenClaw v2026.3.8 及更早版本
NODE_VERSION_V2="22.23.0"
NODE_VERSION_V1="22.15.1"
# 默认使用 V2 版本 (可通过 NODE_VERSION 环境变量覆盖)
NODE_VERSION="${NODE_VERSION:-${NODE_VERSION_V2}}"
# 经过验证的 OpenClaw 稳定版本 (更新此值需同步测试)
OC_TESTED_VERSION="2026.6.11"
# OpenClaw 2026.6.x package.json engines.node 的最低要求。
OC_TESTED_VERSION="2026.7.1-2"
# OpenClaw 2026.7.x package.json engines.node 的最低要求。
# 如果未来上游提高要求,安装成功后还会从 package.json 再做一次强校验。
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.19.0}"
OC_NODE_MIN_VERSION="${OC_NODE_MIN_VERSION:-22.22.3}"
# 用户可通过 OC_VERSION 环境变量覆盖安装版本
OC_VERSION="${OC_VERSION:-}"
@@ -279,6 +279,55 @@ detect_arch() {
esac
}
# 计算文件 sha256 (优先 sha256sum,兜底 openssl;openssl-util 是本包硬依赖)
oc_sum256() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" 2>/dev/null | awk '{print $1}'
elif command -v openssl >/dev/null 2>&1; then
openssl dgst -sha256 -r "$1" 2>/dev/null | awk '{print $1}'
else
return 1
fi
}
# 校验 Node tarball 完整性:
# - 官方 / unofficial-builds / npmmirror 镜像: 拉取同目录 SHASUMS256.txt 比对
# - 自托管 node-bins: 优先下载同名 .sha256 边车文件; 旧资产没有哈希时降级为体积检查
# - 哈希源本身不可用时仅告警不阻断 (离线/镜像异常场景仍可继续)
verify_node_tarball() {
local file="$1" mirror_url="$2" filename
filename=$(basename "$mirror_url")
local actual
actual=$(oc_sum256 "$file") || { log_warn "无可用 sha256 工具,跳过完整性校验"; return 0; }
local expected=""
if [ "${mirror_url#*node-bins}" != "$mirror_url" ]; then
# 自托管 Release 资产: 尝试 .sha256 边车文件
if curl -fsSL --connect-timeout 10 --max-time 30 -o "${file}.sha256" "${mirror_url}.sha256" 2>/dev/null; then
expected=$(awk '{print $1}' "${file}.sha256" 2>/dev/null)
rm -f "${file}.sha256"
fi
else
# 官方系镜像: 同版本目录下的 SHASUMS256.txt
local shasum_url="${mirror_url%/*}/SHASUMS256.txt"
if curl -fsSL --connect-timeout 10 --max-time 30 -o "${file}.sums" "$shasum_url" 2>/dev/null; then
expected=$(awk -v f="$filename" '$2 == f {print $1}' "${file}.sums" 2>/dev/null)
rm -f "${file}.sums"
fi
fi
if [ -z "$expected" ]; then
log_warn "未获取到 ${filename} 的官方哈希,跳过强校验 (仅体积检查)"
return 0
fi
if [ "$actual" = "$expected" ]; then
log_info "SHA256 校验通过"
return 0
fi
log_error "SHA256 校验失败: ${filename}"
return 1
}
download_node() {
local node_ver="$1"
local node_arch
@@ -347,8 +396,12 @@ download_node() {
# 校验文件大小 (Node.js xz 压缩包至少 5MB; Alpine 精简包约 12MB, 官方完整包约 30MB)
local fsize=$(wc -c < "$tmp_file" 2>/dev/null || echo 0)
if [ "$fsize" -gt 5000000 ] 2>/dev/null; then
downloaded=1
break
if verify_node_tarball "$tmp_file" "$mirror_url"; then
downloaded=1
break
else
rm -f "$tmp_file"
fi
else
log_warn "文件大小异常 (${fsize} bytes), 跳过"
rm -f "$tmp_file"
@@ -102,6 +102,30 @@ oc_cmd() {
fi
}
# 以 openclaw 服务用户运行官方诊断。
# OpenClaw 2026.7.x 的插件安全检查按当前进程 uid 校验插件目录属主
# (属主必须等于进程 uid 或为 root)。本脚本在 PTY 中以 root 运行,
# root 身份执行 doctor 会把 openclaw 属主的微信插件目录判为
# suspicious ownership 并自动清理 plugins.allow / channels 配置。
oc_doctor_as_openclaw() {
if [ -z "$OC_ENTRY" ] || [ ! -x "$NODE_BIN" ]; then
echo "ERROR: OpenClaw 未安装或 Node.js 不可用"
return 1
fi
if ! id openclaw >/dev/null 2>&1; then
oc_cmd doctor
return $?
fi
local _doc_cmd="HOME=\"${OC_DATA}\" OPENCLAW_HOME=\"${OC_DATA}\" OPENCLAW_STATE_DIR=\"${OC_DATA}/.openclaw\" OPENCLAW_CONFIG_PATH=\"${CONFIG_FILE}\" NODE_ICU_DATA=\"${NODE_BASE}/share/icu\" \"${NODE_BIN}\" \"${OC_ENTRY}\" doctor"
if command -v su >/dev/null 2>&1; then
su -s /bin/sh openclaw -c "${_doc_cmd}" 2>&1
elif command -v runuser >/dev/null 2>&1; then
runuser -u openclaw -- sh -c "${_doc_cmd}" 2>&1
else
start-stop-daemon -S -m -p /tmp/openclaw-doctor-$$.pid -c openclaw:openclaw -x /bin/sh -- -c "${_doc_cmd}" 2>&1
fi
}
# ── JSON 读写 (使用 Node.js) ──
json_get() {
if [ ! -f "$CONFIG_FILE" ]; then echo ""; return; fi
@@ -2175,7 +2199,7 @@ health_check() {
echo ""
echo -e " ${CYAN}运行官方诊断...${NC}"
oc_cmd doctor 2>/dev/null || true
oc_doctor_as_openclaw 2>/dev/null || true
echo ""
echo -e " ${CYAN}最近日志 (最后 10 行):${NC}"
@@ -6,9 +6,9 @@ fail() {
exit 1
}
grep -q "OC_TESTED_VERSION=\"2026.6.11\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned"
grep -q "OC_TESTED_VERSION=\"2026.7.1-2\"" root/usr/bin/openclaw-env || fail "tested OpenClaw version not pinned"
grep -q "NODE_VERSION_V2=\"22.23.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_NODE_MIN_VERSION=\"\${OC_NODE_MIN_VERSION:-22.22.3}\"" 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"
grep -q "install_openclaw_cli_wrapper" root/usr/bin/openclaw-env || fail "OpenClaw CLI wrapper must set runtime env"
@@ -56,6 +56,10 @@ if grep -q "delete d.plugins.entries\\['openclaw-weixin'\\]" root/etc/init.d/ope
fi
grep -q "npm/projects" root/etc/init.d/openclaw || fail "npm plugin project ownership fix missing"
grep -q "! -path.*npm/projects" root/usr/libexec/openclaw-permissions.sh || fail "npm plugin projects should be excluded from generic ownership reset"
grep -q "_run_doctor_fix" root/etc/init.d/openclaw || fail "doctor --fix must run through the service-user wrapper"
grep -q "su -s /bin/sh openclaw -c" root/etc/init.d/openclaw || fail "doctor --fix must run as the openclaw service user (2026.7.x plugin ownership check)"
grep -q "oc_doctor_as_openclaw" root/usr/share/openclaw/oc-config.sh || fail "oc-config doctor must run as the openclaw service user"
grep -q "(-\[0-9]+)?" root/etc/init.d/openclaw || fail "doctor version marker must keep the patch suffix (e.g. 2026.7.1-2)"
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 "wechat_openclaw_plugin_install_cmd" luasrc/controller/openclaw.lua || fail "wechat install must use OpenClaw plugin installer"
@@ -105,7 +109,7 @@ grep -q "微信插件注册状态已有效,跳过重复刷新" root/etc/init.d
grep -q "d.plugins.entries\['openclaw-weixin'\].enabled===true" root/etc/init.d/openclaw || fail "init.d fast path must require the official enable entry"
grep -q "openclaw-permissions.sh" root/etc/init.d/openclaw || fail "init.d must use permission helper"
grep -q "fix_openclaw_state_permissions" root/etc/init.d/openclaw || fail "init.d final permission helper call missing"
grep -q 'NODE_ICU_DATA="${NODE_BASE}/share/icu" PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:$PATH"' root/etc/init.d/openclaw || fail "doctor migration must run with Node ICU data"
grep -q 'NODE_ICU_DATA=\\"${NODE_BASE}/share/icu\\"' root/etc/init.d/openclaw || fail "doctor migration must run with Node ICU data"
grep -q "Token 同步 (doctor 后): UCI -> JSON" root/etc/init.d/openclaw || fail "doctor must restore missing JSON token from UCI"
grep -q 'OPENCLAW_GATEWAY_TOKEN="$gw_token"' root/etc/init.d/openclaw || fail "gateway must receive token env fallback"
grep -q "clear_jiti_cache_on_start" root/etc/init.d/openclaw || fail "JITI cache cleanup must be opt-in to avoid slow startup"
+2 -2
View File
@@ -30,11 +30,11 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=wwand
PKG_RELEASE:=5
PKG_RELEASE:=6
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git
PKG_SOURCE_VERSION:=d83bad8714c85db500dfe429fc64428d4f7a26bc
PKG_SOURCE_VERSION:=57196fbe92f8d6fa18a3c3e4e8269c54328f2ffe
PKG_SOURCE_DATE:=2026-08-21
PKG_MIRROR_HASH:=skip