mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 23:55:13 +08:00
💐 Sync 2026-07-09 02:25:04
This commit is contained in:
1 parent
9cc2ec0f09
commit
3d0541ac96
37 files changed
+597
-329
No files matched your search
+1
-1
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=daed
|
||||
PKG_VERSION:=2026.07.05
|
||||
PKG_RELEASE:=19
|
||||
PKG_RELEASE:=20
|
||||
|
||||
PKG_SOURCE:=daed-src-2026.07.05-23793fb2bd76.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
|
||||
|
||||
@@ -46,6 +46,13 @@ stop_service() {
|
||||
daed_cleanup_runtime
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
sleep 1
|
||||
daed_cleanup_runtime
|
||||
start
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$CONF"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
From: kenzok8 <kenzok8@noreply>
|
||||
Date: 2026-07-08
|
||||
Subject: [PATCH] daed: restart process when dashboard reload hangs
|
||||
|
||||
Dashboard "Apply" can leave dae's runtime half-reloaded on some OpenWrt
|
||||
netns/veth setups. Bound the GraphQL reload request and let procd respawn daed
|
||||
so daed-guard can clean stale runtime state before starting again.
|
||||
|
||||
Reported: https://github.com/kenzok8/openwrt-daede/issues/31
|
||||
---
|
||||
--- a/graphql/service/config/mutation_utils.go
|
||||
+++ b/graphql/service/config/mutation_utils.go
|
||||
@@ -11,0 +12 @@
|
||||
+ "os"
|
||||
@@ -16,0 +18 @@
|
||||
+ "time"
|
||||
@@ -260,0 +263,9 @@
|
||||
+const reloadWaitTimeout = 75 * time.Second
|
||||
+
|
||||
+func restartAfterReloadTimeout() {
|
||||
+ go func() {
|
||||
+ time.Sleep(time.Second)
|
||||
+ os.Exit(1)
|
||||
+ }()
|
||||
+}
|
||||
+
|
||||
@@ -458 +469 @@
|
||||
- dae.ChReloadConfigs <- &dae.ReloadMessage{
|
||||
+ reloadMsg := &dae.ReloadMessage{
|
||||
@@ -462,3 +473,5 @@
|
||||
- errReload := <-chReloadCallback
|
||||
- if errReload != nil {
|
||||
- return 0, fmt.Errorf("failed to load new config: %w; see more in log", errReload)
|
||||
+ select {
|
||||
+ case dae.ChReloadConfigs <- reloadMsg:
|
||||
+ case <-time.After(reloadWaitTimeout):
|
||||
+ restartAfterReloadTimeout()
|
||||
+ return 0, fmt.Errorf("failed to submit reload within %s; restarting daed to recover runtime", reloadWaitTimeout)
|
||||
@@ -465,0 +479,9 @@
|
||||
+ select {
|
||||
+ case errReload := <-chReloadCallback:
|
||||
+ if errReload != nil {
|
||||
+ return 0, fmt.Errorf("failed to load new config: %w; see more in log", errReload)
|
||||
+ }
|
||||
+ case <-time.After(reloadWaitTimeout):
|
||||
+ restartAfterReloadTimeout()
|
||||
+ return 0, fmt.Errorf("reload timed out after %s; restarting daed to recover runtime", reloadWaitTimeout)
|
||||
+ }
|
||||
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-daede
|
||||
PKG_VERSION:=1.14.7
|
||||
PKG_RELEASE:=30
|
||||
PKG_RELEASE:=31
|
||||
PKG_MAINTAINER:=kenzok8
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
|
||||
@@ -4,9 +4,22 @@
|
||||
'require baseclass';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require uci';
|
||||
'require view.daede.widgets as widgets';
|
||||
|
||||
function applyUciChanges() {
|
||||
return uci.save().then(function() {
|
||||
return uci.changes().then(function(ch) {
|
||||
return (ch && Object.keys(ch).length) ? uci.apply() : null;
|
||||
});
|
||||
}).then(function() {
|
||||
return new Promise(function(resolve) { window.setTimeout(resolve, 1800); });
|
||||
}).then(function() {
|
||||
return ui.changes.init();
|
||||
});
|
||||
}
|
||||
|
||||
function renderDaedSettings() {
|
||||
let m, s, o;
|
||||
m = new form.Map('daed', null, null);
|
||||
@@ -96,12 +109,7 @@ function renderDaedSettings() {
|
||||
ev.preventDefault();
|
||||
save.disabled = true;
|
||||
m.save(null, true)
|
||||
.then(function() { return uci.save(); })
|
||||
.then(function() {
|
||||
return uci.changes().then(function(ch) {
|
||||
return (ch && Object.keys(ch).length) ? uci.apply() : null;
|
||||
});
|
||||
})
|
||||
.then(applyUciChanges)
|
||||
.then(function() {
|
||||
const enabled = uci.get('daed', 'config', 'subscribe_auto_update') === '1';
|
||||
return fs.exec('/usr/share/luci-app-daede/daed-sub-cron.sh', [ enabled ? 'enable' : 'disable' ]);
|
||||
|
||||
@@ -58,9 +58,6 @@ const CSS = [
|
||||
'.dd-geo-row input[type=text],.dd-geo-row select{font-size:12px;padding:4px 8px;border:1px solid rgba(128,128,128,.35);border-radius:5px;background:transparent;color:inherit;width:100%}',
|
||||
/* selects cap at 200px on wide screens, shrink to the column on mobile (no overflow) */
|
||||
'.dd-geo-row select{width:100%!important;max-width:200px;box-sizing:border-box}',
|
||||
'.dd-geo-auto{display:inline-flex;align-items:center;gap:6px}',
|
||||
/* Argon shifts label>checkbox down (top:.4rem); reset so flex centers it */
|
||||
'.dd-geo-auto input[type="checkbox"]{position:static;top:auto;right:auto;margin:0}',
|
||||
'.dd-geo-actions{margin-top:10px;display:flex;gap:10px;align-items:center}',
|
||||
'.dd-up-log{margin-top:10px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:11px;padding:10px;border:1px solid rgba(128,128,128,.14);border-radius:8px;max-height:200px;overflow:auto;white-space:pre-wrap;word-break:break-all;display:none;background:inherit;color:#4a8c63}',
|
||||
'.dd-up-log.show{display:block}',
|
||||
@@ -436,24 +433,25 @@ return view.extend({
|
||||
presetSel.addEventListener('change', syncCustom);
|
||||
syncCustom();
|
||||
|
||||
const autoCb = E('input', { 'type': 'checkbox' });
|
||||
autoCb.checked = auto0;
|
||||
const freqSel = E('select', {}, [
|
||||
const autoSel = E('select', {}, [
|
||||
E('option', { 'value': 'off' }, _('Disabled')),
|
||||
E('option', { 'value': 'daily' }, _('Daily')),
|
||||
E('option', { 'value': 'weekly' }, _('Weekly'))
|
||||
]);
|
||||
freqSel.value = freq0;
|
||||
autoSel.value = auto0 ? freq0 : 'off';
|
||||
|
||||
const saveBtn = E('button', { 'class': 'dd-up-btn dd-up-btn-primary' }, _('Save'));
|
||||
saveBtn.addEventListener('click', function() {
|
||||
const p = presetSel.value;
|
||||
let gi = '', gs = '';
|
||||
const geoAuto = autoSel.value !== 'off';
|
||||
const geoFreq = autoSel.value === 'weekly' ? 'weekly' : 'daily';
|
||||
if (p === 'v2fly') { gi = GEO_PRESETS.v2fly.geoip; gs = GEO_PRESETS.v2fly.geosite; }
|
||||
else if (p === 'custom') { gi = giInput.value.trim(); gs = gsInput.value.trim(); }
|
||||
uci.set('daede', 'config', 'geoip_url', gi);
|
||||
uci.set('daede', 'config', 'geosite_url', gs);
|
||||
uci.set('daede', 'config', 'geo_auto', autoCb.checked ? '1' : '0');
|
||||
uci.set('daede', 'config', 'geo_auto_freq', freqSel.value);
|
||||
uci.set('daede', 'config', 'geo_auto', geoAuto ? '1' : '0');
|
||||
uci.set('daede', 'config', 'geo_auto_freq', geoFreq);
|
||||
const orig = saveBtn.textContent;
|
||||
saveBtn.disabled = true; saveBtn.textContent = '...';
|
||||
uci.save().then(function() {
|
||||
@@ -463,7 +461,7 @@ return view.extend({
|
||||
if (changes && Object.keys(changes).length)
|
||||
return uci.apply();
|
||||
}).then(function() {
|
||||
return fs.exec('/usr/share/luci-app-daede/geo-cron.sh', [autoCb.checked ? 'enable' : 'disable']);
|
||||
return fs.exec('/usr/share/luci-app-daede/geo-cron.sh', [geoAuto ? 'enable' : 'disable']);
|
||||
}).then(function() {
|
||||
logPane.textContent = _('Geo data source saved.');
|
||||
logPane.classList.add('show');
|
||||
@@ -485,8 +483,8 @@ return view.extend({
|
||||
E('div', { 'class': 'dd-geo-row' }, [ E('label', {}, _('Source')), presetSel ]),
|
||||
customRows,
|
||||
E('div', { 'class': 'dd-geo-row' }, [
|
||||
E('label', { 'class': 'dd-geo-auto' }, [ E('span', {}, _('Auto-update')), autoCb ]),
|
||||
freqSel
|
||||
E('label', {}, _('Auto-update')),
|
||||
autoSel
|
||||
]),
|
||||
E('div', { 'class': 'dd-geo-actions' }, [ saveBtn ])
|
||||
])
|
||||
|
||||
@@ -22,6 +22,11 @@ function execInit(be, action) {
|
||||
}).catch(function() {});
|
||||
}
|
||||
|
||||
function restartService(be) {
|
||||
return execChecked(be.initd, ['restart'])
|
||||
.then(function() { return waitForService(be, true, 80); });
|
||||
}
|
||||
|
||||
function rejectIfOtherRunning(be, running) {
|
||||
const other = be.name === 'dae' ? 'daed' : 'dae';
|
||||
if (!running || !running[other])
|
||||
@@ -231,8 +236,21 @@ function renderStatusCard(ctx, listenAddr) {
|
||||
const restart = E('button', { 'class': 'cbi-button cbi-button-positive' }, _('Restart'));
|
||||
restart.addEventListener('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
if (busy) return;
|
||||
busy = true;
|
||||
restart.disabled = true;
|
||||
execInit(be, 'restart').finally(function() { restart.disabled = false; });
|
||||
lastError = '';
|
||||
swErr.style.display = 'none';
|
||||
restartService(be)
|
||||
.then(function() {
|
||||
busy = false;
|
||||
return refresh(true);
|
||||
})
|
||||
.catch(function(e) {
|
||||
busy = false;
|
||||
lastError = _('Restart failed: %s').format(e.message || e);
|
||||
return refresh(true);
|
||||
});
|
||||
});
|
||||
actions.push(restart);
|
||||
}
|
||||
|
||||
@@ -836,6 +836,9 @@ msgstr ""
|
||||
msgid "Auto-update"
|
||||
msgstr ""
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -1025,6 +1025,9 @@ msgstr "自定义"
|
||||
msgid "Auto-update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "关闭"
|
||||
|
||||
msgid "Daily"
|
||||
msgstr "每天"
|
||||
|
||||
|
||||
@@ -1025,6 +1025,9 @@ msgstr "自定义"
|
||||
msgid "Auto-update"
|
||||
msgstr "自动更新"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "关闭"
|
||||
|
||||
msgid "Daily"
|
||||
msgstr "每天"
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
- 兼容没有 `su` / `runuser` 的 OpenWrt 固件,微信安装、升级、登录和下线改用 `start-stop-daemon` 兜底以 `openclaw` 用户执行。
|
||||
- 微信安装网络探测优先使用 `curl`,避免低内存/精简 musl 固件上 Node `fetch` 触发 undici Wasm OOM。
|
||||
- 微信官方 CLI 安装触发 undici Wasm OOM 时,自动改用 npm 直装到 OpenClaw `npm/projects` 并继续注册插件配置。
|
||||
- 微信插件安装/升级不再预先停止 Gateway,避免反复安装触发 procd crash-loop。
|
||||
- LuCI 状态页和 `status_service` 增强 procd 状态识别,能区分真实启动中、stale pidfile 和 crash-loop 抑制,不再误显示“正在启动”。
|
||||
- 微信登录前补充 Node、python3、插件目录、账号状态目录和配置写权限检查,并清理残留登录进程与旧二维码状态。
|
||||
- 登录失败时在 LuCI 页面展示真实日志详情,不再只显示“登录失败”。
|
||||
- 二维码链接提取更稳,页面明确提示“点击链接后用微信扫码”。
|
||||
|
||||
@@ -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:=20
|
||||
PKG_RELEASE:=21
|
||||
|
||||
PKG_MAINTAINER:=10000ge10000 <10000ge10000@users.noreply.github.com>
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
@@ -85,6 +85,21 @@ define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] || {
|
||||
( . /etc/uci-defaults/99-openclaw ) && rm -f /etc/uci-defaults/99-openclaw
|
||||
OPENCLAW_INSTALL_BASE="$$(uci -q get openclaw.main.install_path 2>/dev/null || echo /opt)"
|
||||
if [ -r /usr/libexec/openclaw-paths.sh ]; then
|
||||
. /usr/libexec/openclaw-paths.sh
|
||||
oc_load_paths "$${OPENCLAW_INSTALL_BASE}" 2>/dev/null || true
|
||||
else
|
||||
OPENCLAW_INSTALL_BASE="$${OPENCLAW_INSTALL_BASE%/}"
|
||||
OC_DATA="$${OPENCLAW_INSTALL_BASE}/openclaw/data"
|
||||
fi
|
||||
if [ -n "$${OC_DATA:-}" ] && [ -d "$${OC_DATA}/.openclaw" ] && [ -x /usr/libexec/openclaw-permissions.sh ]; then
|
||||
/usr/libexec/openclaw-permissions.sh fix-state "$${OC_DATA}/.openclaw" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [ "$$(uci -q get openclaw.main.enabled 2>/dev/null || echo 0)" = "1" ] && [ -x /etc/init.d/openclaw ]; then
|
||||
/etc/init.d/openclaw enable >/dev/null 2>&1 || true
|
||||
/etc/init.d/openclaw start >/dev/null 2>&1 || true
|
||||
fi
|
||||
rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ fs.writeFileSync(configPath, JSON.stringify(d, null, 2) + '\n');
|
||||
"REG_RC=$?; " ..
|
||||
"if [ $REG_RC -eq 0 ]; then " ..
|
||||
"chown openclaw:openclaw " .. shellquote(config_file) .. " 2>/dev/null; " ..
|
||||
"[ -x /usr/libexec/openclaw-permissions.sh ] && /usr/libexec/openclaw-permissions.sh fix-state " .. shellquote(oc_data .. "/.openclaw") .. " >/dev/null 2>&1; " ..
|
||||
"echo 'Registered openclaw-weixin npm plugin in OpenClaw config.' >> " .. shellquote(log_file) .. "; " ..
|
||||
"else RC=$REG_RC; echo $RC > " .. shellquote(exit_file) .. "; echo 'Failed to register openclaw-weixin npm plugin in OpenClaw config.' >> " .. shellquote(log_file) .. "; fi; " ..
|
||||
"else RC=127; echo $RC > " .. shellquote(exit_file) .. "; echo 'Node.js not found, cannot register openclaw-weixin plugin.' >> " .. shellquote(log_file) .. "; fi; " ..
|
||||
@@ -238,7 +239,13 @@ const timer = setTimeout(() => controller.abort(new Error('timeout')), 10000);
|
||||
end
|
||||
|
||||
local function openclaw_user_runner_cmd()
|
||||
return "_oc_as_openclaw() { " ..
|
||||
return "_oc_raise_openclaw_limits() { " ..
|
||||
"ulimit -v unlimited 2>/dev/null || true; " ..
|
||||
"ulimit -m unlimited 2>/dev/null || true; " ..
|
||||
"ulimit -d unlimited 2>/dev/null || true; " ..
|
||||
"}; " ..
|
||||
"_oc_as_openclaw() { " ..
|
||||
"_oc_raise_openclaw_limits; " ..
|
||||
"if command -v su >/dev/null 2>&1; then su -s /bin/sh openclaw -c \"$1\"; " ..
|
||||
"elif command -v runuser >/dev/null 2>&1; then runuser -u openclaw -- sh -c \"$1\"; " ..
|
||||
"elif command -v start-stop-daemon >/dev/null 2>&1; then _oc_pid=/tmp/openclaw-user-$$.pid; _oc_cwd=$(pwd); rm -f \"$_oc_pid\"; start-stop-daemon -S -m -p \"$_oc_pid\" -c openclaw:openclaw -d \"$_oc_cwd\" -x /bin/sh -- -c \"$1\"; _oc_rc=$?; rm -f \"$_oc_pid\"; return $_oc_rc; " ..
|
||||
@@ -267,6 +274,25 @@ local function wechat_npm_fallback_install_cmd(install_path, log_file, exit_file
|
||||
"fi; "
|
||||
end
|
||||
|
||||
local function wechat_npm_direct_install_cmd(install_path, log_file, exit_file)
|
||||
local package_json = "{\n \"private\": true,\n \"dependencies\": {\n \"@tencent-weixin/openclaw-weixin\": \"latest\"\n }\n}\n"
|
||||
return "echo '使用 npm 直装微信插件,避免官方安装器进入扫码等待...' >> " .. shellquote(log_file) .. "; " ..
|
||||
"OC_WECHAT_NPM_PROJECT=\"$OC_WECHAT_DATA/.openclaw/npm/projects/tencent-weixin-openclaw-weixin-7783ac86ba\"; " ..
|
||||
"mkdir -p \"$OC_WECHAT_NPM_PROJECT\" \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" \"$OC_WECHAT_DATA/.openclaw/npm/projects\"; " ..
|
||||
"chown -R openclaw:openclaw \"$OC_WECHAT_NPM_PROJECT\" \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" \"$OC_WECHAT_DATA/.openclaw/npm/projects\" 2>/dev/null; " ..
|
||||
"cat > \"$OC_WECHAT_NPM_PROJECT/package.json\" <<'OC_WECHAT_PACKAGE_JSON'\n" ..
|
||||
package_json ..
|
||||
"OC_WECHAT_PACKAGE_JSON\n" ..
|
||||
"chown openclaw:openclaw \"$OC_WECHAT_NPM_PROJECT/package.json\" 2>/dev/null; " ..
|
||||
"cd \"$OC_WECHAT_NPM_PROJECT\" && " ..
|
||||
"_oc_as_openclaw 'HOME=$OC_WECHAT_DATA OPENCLAW_HOME=$OC_WECHAT_DATA OPENCLAW_STATE_DIR=$OC_WECHAT_DATA/.openclaw OPENCLAW_CONFIG_PATH=$OC_WECHAT_DATA/.openclaw/openclaw.json " ..
|
||||
"NODE_ICU_DATA=" .. install_path .. "/node/share/icu NPM_CONFIG_CACHE=$OC_WECHAT_DATA/.npm npm_config_cache=$OC_WECHAT_DATA/.npm TMPDIR=$OC_WECHAT_DATA/.tmp " ..
|
||||
"PATH=" .. install_path .. "/node/bin:" .. install_path .. "/global/bin:$PATH " ..
|
||||
"npm install --omit=dev --omit=peer --legacy-peer-deps --no-audit --no-fund --loglevel=error' >> " .. shellquote(log_file) .. " 2>&1; " ..
|
||||
"RC=$?; echo $RC > " .. shellquote(exit_file) .. "; " ..
|
||||
"if [ $RC -eq 0 ]; then echo '✅ npm 直装微信插件完成' >> " .. shellquote(log_file) .. "; else echo '❌ npm 直装微信插件失败 (exit: '$RC')' >> " .. shellquote(log_file) .. "; fi; "
|
||||
end
|
||||
|
||||
local function wechat_tail_detail(text, max_lines)
|
||||
if not text or text == "" then
|
||||
return ""
|
||||
@@ -524,21 +550,36 @@ function action_status()
|
||||
local gw_check = sys.exec(gw_check_cmd):gsub("%s+", "")
|
||||
result.gateway_running = (tonumber(gw_check) or 0) > 0
|
||||
|
||||
-- 如果端口未监听但 procd 进程存在,说明正在启动中 (gateway 初始化需要数分钟)
|
||||
-- 如果端口未监听,结合 procd 与真实进程判断状态。
|
||||
-- 不能只看 pid 字段或 pidfile:procd crash-loop / stale pidfile 会让 LuCI 误显示“正在启动”。
|
||||
if not result.gateway_running and enabled == "1" then
|
||||
local procd_pid = sys.exec("ubus call service list '{\"name\":\"openclaw\"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.pid' 2>/dev/null"):gsub("%s+", "")
|
||||
local procd_running = sys.exec("ubus call service list '{\"name\":\"openclaw\"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.running' 2>/dev/null"):gsub("%s+", "")
|
||||
local procd_exit = sys.exec("ubus call service list '{\"name\":\"openclaw\"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.exit_code' 2>/dev/null"):gsub("%s+", "")
|
||||
if procd_pid == "null" or not procd_pid:match("^%d+$") then procd_pid = "" end
|
||||
if procd_exit == "null" then procd_exit = "" end
|
||||
result.gateway_exit_code = procd_exit
|
||||
|
||||
local procd_pid_alive = false
|
||||
if procd_pid ~= "" then
|
||||
procd_pid_alive = (sys.exec("[ -d /proc/" .. procd_pid .. " ] && echo 1 || echo 0"):gsub("%s+", "") == "1")
|
||||
end
|
||||
local pidfile_pid = sys.exec("cat /var/run/openclaw.pid 2>/dev/null || true"):gsub("%s+", "")
|
||||
local pidfile_stale = false
|
||||
if pidfile_pid ~= "" and pidfile_pid:match("^%d+$") then
|
||||
pidfile_stale = (sys.exec("[ -d /proc/" .. pidfile_pid .. " ] && echo 0 || echo 1"):gsub("%s+", "") == "1")
|
||||
end
|
||||
local crash_loop = sys.exec("logread 2>/dev/null | grep -E 'Instance openclaw::gateway.*crash loop' | tail -1"):gsub("^%s+", ""):gsub("%s+$", "")
|
||||
|
||||
if procd_exit ~= "" and tonumber(procd_exit) and tonumber(procd_exit) ~= 0 and procd_running ~= "true" then
|
||||
result.gateway_failed = true
|
||||
elseif procd_pid ~= "" or procd_running == "true" then
|
||||
elseif crash_loop ~= "" and pidfile_stale and procd_running ~= "true" and not procd_pid_alive then
|
||||
result.gateway_failed = true
|
||||
result.gateway_crash_loop = true
|
||||
if result.gateway_exit_code == "" then result.gateway_exit_code = "crash-loop" end
|
||||
elseif procd_running == "true" or procd_pid_alive then
|
||||
result.gateway_starting = true
|
||||
else
|
||||
local fallback_pid = sys.exec("pgrep -f 'openclaw.*gateway' 2>/dev/null | head -1"):gsub("%s+", "")
|
||||
if fallback_pid ~= "" then
|
||||
result.gateway_starting = true
|
||||
end
|
||||
result.pid = procd_pid
|
||||
end
|
||||
end
|
||||
|
||||
@@ -637,10 +678,14 @@ function action_service_ctl()
|
||||
-- stop 后额外等待确保端口释放
|
||||
sys.exec("sleep 2")
|
||||
elseif action == "restart" then
|
||||
-- 先完整 stop (确保端口释放),再后台 start
|
||||
sys.exec("/etc/init.d/openclaw stop >/dev/null 2>&1")
|
||||
sys.exec("sleep 2")
|
||||
sys.exec("/etc/init.d/openclaw start >/dev/null 2>&1 &")
|
||||
-- 常规“重启”只重启 Gateway,不重启 Web PTY,避免 stop+start 带来的长时间等待。
|
||||
-- 如果 procd 没有 gateway 实例,再回退到 start。
|
||||
local procd_running = sys.exec("ubus call service list '{\"name\":\"openclaw\"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.running' 2>/dev/null"):gsub("%s+", "")
|
||||
if procd_running == "true" then
|
||||
sys.exec("/etc/init.d/openclaw restart_gateway >/dev/null 2>&1 &")
|
||||
else
|
||||
sys.exec("/etc/init.d/openclaw start >/dev/null 2>&1 &")
|
||||
end
|
||||
elseif action == "enable" then
|
||||
sys.exec("/etc/init.d/openclaw enable 2>/dev/null")
|
||||
elseif action == "disable" then
|
||||
@@ -1549,10 +1594,7 @@ function action_wechat_install()
|
||||
return
|
||||
end
|
||||
|
||||
-- 后台执行安装
|
||||
-- 在启动安装前,确保网关端口可用(自动清理残留 gateway 进程)
|
||||
local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
ensure_port_free(port)
|
||||
-- 后台执行安装。注意:插件安装不需要释放 Gateway 端口,避免误停正在运行的 Gateway 触发 procd crash-loop。
|
||||
-- 微信插件安装目录路径 (用于安装后权限修复)
|
||||
local extensions_dir = install_path .. "/data/.openclaw/extensions"
|
||||
local install_cmd = string.format(
|
||||
@@ -1569,13 +1611,7 @@ function action_wechat_install()
|
||||
"else mkdir -p \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" \"$OC_WECHAT_DATA/.openclaw/extensions\"; chown -R openclaw:openclaw \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" 2>/dev/null; chown openclaw:openclaw \"$OC_WECHAT_DATA/.openclaw\" 2>/dev/null; fi; " ..
|
||||
"if [ ! -w %s/.npm ] || [ ! -w %s/.tmp ]; then echo '❌ npm cache/tmp 目录不可写' >> /tmp/openclaw-wechat-install.log; echo 1 > /tmp/openclaw-wechat-install.exit; exit 0; fi; " ..
|
||||
"_oc_as_openclaw 'test -w %s/.npm && test -w %s/.tmp && test -w %s/.openclaw' || { echo '❌ openclaw 用户无法写入 npm cache/tmp/data 目录' >> /tmp/openclaw-wechat-install.log; echo 1 > /tmp/openclaw-wechat-install.exit; exit 0; }; " ..
|
||||
"cd %s && " ..
|
||||
"_oc_as_openclaw 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw " ..
|
||||
"OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json NPM_CONFIG_CACHE=%s/.npm npm_config_cache=%s/.npm TMPDIR=%s/.tmp " ..
|
||||
"PATH=%s/node/bin:%s/global/bin:$PATH " ..
|
||||
"%s -y @tencent-weixin/openclaw-weixin-cli install' >> /tmp/openclaw-wechat-install.log 2>&1; " ..
|
||||
"RC=$?; echo $RC > /tmp/openclaw-wechat-install.exit; " ..
|
||||
wechat_npm_fallback_install_cmd(install_path, "/tmp/openclaw-wechat-install.log", "/tmp/openclaw-wechat-install.exit") ..
|
||||
wechat_npm_direct_install_cmd(install_path, "/tmp/openclaw-wechat-install.log", "/tmp/openclaw-wechat-install.exit") ..
|
||||
wechat_register_plugin_cmd(install_path, node_bin, "/tmp/openclaw-wechat-install.log") ..
|
||||
-- 关键修复: 安装完成后强制修复插件目录权限 (确保 Gateway 可读取插件)
|
||||
-- 原因: npx/npm 以 root 身份创建目录,默认权限 700 导致其他用户无法读取
|
||||
@@ -1589,8 +1625,6 @@ function action_wechat_install()
|
||||
oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data,
|
||||
install_path, oc_data, oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data, oc_data,
|
||||
install_path, install_path, npx_bin,
|
||||
oc_data
|
||||
)
|
||||
sys.exec(install_cmd)
|
||||
@@ -1731,15 +1765,23 @@ function action_wechat_login()
|
||||
"if [ $RC -ne 0 ]; then echo '❌ 微信插件注册失败,无法登录' >> /tmp/openclaw-wechat-qrcode.txt; exit 0; fi; " ..
|
||||
"cd %s && " ..
|
||||
"_oc_as_openclaw 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json " ..
|
||||
"NODE_ICU_DATA=%s/node/share/icu " ..
|
||||
"NPM_CONFIG_CACHE=%s/.npm npm_config_cache=%s/.npm TMPDIR=%s/.tmp PATH=%s/node/bin:%s/global/bin:$PATH " ..
|
||||
"%s %s channels login --channel openclaw-weixin' >> /tmp/openclaw-wechat-qrcode.txt 2>&1; " ..
|
||||
"echo $? > /tmp/openclaw-wechat-login.exit; " ..
|
||||
") >/dev/null 2>&1 & echo $! > /tmp/openclaw-wechat-login.pid",
|
||||
install_path, oc_entry, wechat_plugin_dir, node_bin,
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data, oc_data,
|
||||
install_path, install_path, node_bin, oc_entry
|
||||
oc_data, oc_data, oc_data,
|
||||
oc_data,
|
||||
oc_data, oc_data, oc_data,
|
||||
oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data,
|
||||
install_path,
|
||||
oc_data, oc_data, oc_data, oc_data,
|
||||
install_path,
|
||||
oc_data, oc_data, oc_data,
|
||||
install_path, install_path,
|
||||
node_bin, oc_entry
|
||||
)
|
||||
sys.exec(login_cmd)
|
||||
|
||||
@@ -1798,8 +1840,15 @@ function action_wechat_login_status()
|
||||
end
|
||||
end
|
||||
end
|
||||
-- 检查是否登录成功
|
||||
local logged_in = qrcode:find("登录成功") ~= nil or qrcode:find("成功登录") ~= nil or qrcode:find("Login success") ~= nil or qrcode:find("Logged in") ~= nil
|
||||
-- 检查是否登录成功。微信插件在 OpenClaw 2026.6.11 中可能已经保存认证,
|
||||
-- 但随后通过 Gateway 动态启动渠道时报 "invalid channels.start channel" 并返回
|
||||
-- 非 0;这种情况账号已配对成功,LuCI 不应误判为失败。
|
||||
local logged_in = qrcode:find("登录成功") ~= nil
|
||||
or qrcode:find("成功登录") ~= nil
|
||||
or qrcode:find("Login success") ~= nil
|
||||
or qrcode:find("Logged in") ~= nil
|
||||
or qrcode:find("已将此 OpenClaw 连接到微信") ~= nil
|
||||
or qrcode:find("Local login saved auth for openclaw%-weixin") ~= nil
|
||||
|
||||
local state = "idle"
|
||||
if logged_in then
|
||||
@@ -1825,10 +1874,11 @@ function action_wechat_login_status()
|
||||
end
|
||||
end
|
||||
|
||||
-- 如果刚登录成功,触发一次重启,确保主进程加载微信账号
|
||||
-- 如果刚登录成功,触发一次轻量重启,确保主进程加载微信账号。
|
||||
-- 不使用完整 /etc/init.d/openclaw restart,避免同时重启 Web PTY 和拉长等待时间。
|
||||
if state == "success" and not nixio.fs.stat("/tmp/openclaw-wechat-restarted", "type") then
|
||||
sys.exec("touch /tmp/openclaw-wechat-restarted")
|
||||
sys.exec("/etc/init.d/openclaw restart &")
|
||||
sys.exec("/etc/init.d/openclaw restart_gateway >/dev/null 2>&1 &")
|
||||
message = "微信登录成功,正在重新加载微信账号"
|
||||
end
|
||||
http.prepare_content("application/json")
|
||||
@@ -2013,10 +2063,7 @@ function action_wechat_upgrade_plugin()
|
||||
return
|
||||
end
|
||||
|
||||
-- 后台执行升级 (其实就是重新安装最新版)
|
||||
-- 在启动升级前,确保网关端口可用(自动清理残留 gateway 进程)
|
||||
local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
ensure_port_free(port)
|
||||
-- 后台执行升级 (其实就是重新安装最新版)。不要释放 Gateway 端口,避免误停正在运行的 Gateway。
|
||||
-- 微信插件安装目录路径 (用于升级后权限修复)
|
||||
local extensions_dir = install_path .. "/data/.openclaw/extensions"
|
||||
local upgrade_cmd = string.format(
|
||||
@@ -2033,13 +2080,7 @@ function action_wechat_upgrade_plugin()
|
||||
"else mkdir -p \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" \"$OC_WECHAT_DATA/.openclaw/extensions\"; chown -R openclaw:openclaw \"$OC_WECHAT_DATA/.npm\" \"$OC_WECHAT_DATA/.tmp\" 2>/dev/null; chown openclaw:openclaw \"$OC_WECHAT_DATA/.openclaw\" 2>/dev/null; fi; " ..
|
||||
"if [ ! -w %s/.npm ] || [ ! -w %s/.tmp ]; then echo '❌ npm cache/tmp 目录不可写' >> /tmp/openclaw-wechat-install.log; echo 1 > /tmp/openclaw-wechat-install.exit; exit 0; fi; " ..
|
||||
"_oc_as_openclaw 'test -w %s/.npm && test -w %s/.tmp && test -w %s/.openclaw' || { echo '❌ openclaw 用户无法写入 npm cache/tmp/data 目录' >> /tmp/openclaw-wechat-install.log; echo 1 > /tmp/openclaw-wechat-install.exit; exit 0; }; " ..
|
||||
"cd %s && " ..
|
||||
"_oc_as_openclaw 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw " ..
|
||||
"OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json NPM_CONFIG_CACHE=%s/.npm npm_config_cache=%s/.npm TMPDIR=%s/.tmp " ..
|
||||
"PATH=%s/node/bin:%s/global/bin:$PATH " ..
|
||||
"%s -y @tencent-weixin/openclaw-weixin-cli install' >> /tmp/openclaw-wechat-install.log 2>&1; " ..
|
||||
"RC=$?; echo $RC > /tmp/openclaw-wechat-install.exit; " ..
|
||||
wechat_npm_fallback_install_cmd(install_path, "/tmp/openclaw-wechat-install.log", "/tmp/openclaw-wechat-install.exit") ..
|
||||
wechat_npm_direct_install_cmd(install_path, "/tmp/openclaw-wechat-install.log", "/tmp/openclaw-wechat-install.exit") ..
|
||||
wechat_register_plugin_cmd(install_path, node_bin, "/tmp/openclaw-wechat-install.log") ..
|
||||
-- 关键修复: 升级完成后强制修复插件目录权限 (确保 Gateway 可读取插件)
|
||||
-- 注意: 保持 root:root 属主 (OpenClaw v2026.4.9+ 安全要求),仅修复权限模式
|
||||
@@ -2052,8 +2093,6 @@ function action_wechat_upgrade_plugin()
|
||||
oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data,
|
||||
install_path, oc_data, oc_data, oc_data,
|
||||
oc_data, oc_data, oc_data, oc_data,
|
||||
install_path, install_path, npx_bin,
|
||||
oc_data
|
||||
)
|
||||
sys.exec(upgrade_cmd)
|
||||
@@ -2114,10 +2153,10 @@ function action_wechat_logout()
|
||||
|
||||
-- 在后台执行 logout
|
||||
local logout_cmd = string.format(
|
||||
openclaw_user_runner_cmd() .. "cd %s && _oc_as_openclaw 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json " ..
|
||||
openclaw_user_runner_cmd() .. "cd %s && _oc_as_openclaw 'HOME=%s OPENCLAW_HOME=%s OPENCLAW_STATE_DIR=%s/.openclaw OPENCLAW_CONFIG_PATH=%s/.openclaw/openclaw.json NODE_ICU_DATA=%s/node/share/icu " ..
|
||||
"PATH=%s/node/bin:%s/global/bin:$PATH " ..
|
||||
"%s %s channels logout --channel openclaw-weixin --account \"%s\"'",
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data, install_path, install_path, node_bin, oc_entry, account_id
|
||||
oc_data, oc_data, oc_data, oc_data, oc_data, install_path, install_path, install_path, node_bin, oc_entry, account_id
|
||||
)
|
||||
|
||||
sys.exec(logout_cmd .. " >/dev/null 2>&1")
|
||||
|
||||
@@ -149,7 +149,7 @@ local port = uci:get("openclaw", "main", "port") or "18789"
|
||||
loading.innerHTML = '<div style="text-align:center;color:#666;">' +
|
||||
'<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;">首次启动可能需要 2~5 分钟,请耐心等待,页面会自动刷新。</div>' +
|
||||
'<div style="font-size:12px;color:#999;">通常 20~40 秒;首次安装或路由器负载较高时会更久,页面会自动刷新。</div>' +
|
||||
'</div>';
|
||||
} else {
|
||||
statusTextEl.innerHTML = '<span style="color:#cf222e;">● 网关未运行</span>';
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
if (d.gateway_running) {
|
||||
gwEl.innerHTML = '<span class="oc-dot oc-dot-green"></span>监听中 :' + d.port;
|
||||
} else if (d.gateway_starting) {
|
||||
gwEl.innerHTML = '<span class="oc-dot oc-dot-gray"></span>初始化中,首次启动可能需要 2~5 分钟...';
|
||||
gwEl.innerHTML = '<span class="oc-dot oc-dot-gray"></span>初始化中,通常 20~40 秒;首次安装或负载较高时会更久...';
|
||||
} else if (d.gateway_failed) {
|
||||
gwEl.innerHTML = '<span class="oc-dot oc-dot-red"></span>启动失败,退出码 ' + (d.gateway_exit_code || '-');
|
||||
} else {
|
||||
|
||||
@@ -448,7 +448,13 @@ if(changed){
|
||||
fi
|
||||
fix_openclaw_state_permissions 2>/dev/null || true
|
||||
|
||||
rm -rf /tmp/jiti 2>/dev/null || true
|
||||
# 不再每次启动都清理 /tmp/jiti。
|
||||
# OpenClaw 在低性能 OpenWrt 设备上依赖 JITI/模块缓存降低冷启动成本;
|
||||
# 每次 rm -rf 会让 gateway 在第一条 "starting..." 日志前重新编译/装载模块,
|
||||
# 实测会额外拉长 20 秒以上。需要强制清理时再显式打开 UCI 开关。
|
||||
if [ "$(uci -q get openclaw.main.clear_jiti_cache_on_start 2>/dev/null || echo 0)" = "1" ]; then
|
||||
rm -rf /tmp/jiti 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# v2026.4.10: 优化配置迁移 - 只在版本变更时运行 doctor --fix
|
||||
# 原因: doctor --fix 耗时 ~50 秒,每次重启都运行严重影响启动速度
|
||||
@@ -637,6 +643,13 @@ _ensure_port_free() {
|
||||
}
|
||||
_ensure_port_free "$port"
|
||||
|
||||
# Node 22 原生编译缓存。OpenClaw 主入口在路由器上首次 import/compile 较慢;
|
||||
# 保留该缓存可以显著缩短后续重启时 gateway 第一条日志前的等待时间。
|
||||
local node_compile_cache="/tmp/openclaw-node-compile-cache"
|
||||
mkdir -p "$node_compile_cache" 2>/dev/null || true
|
||||
chown openclaw:openclaw "$node_compile_cache" 2>/dev/null || true
|
||||
chmod 700 "$node_compile_cache" 2>/dev/null || true
|
||||
|
||||
# 启动 OpenClaw Gateway (主服务, 前台运行)
|
||||
# v2026.4.7/4.9: 环境变量安全验证 (阻止危险变量注入)
|
||||
_validate_path() {
|
||||
@@ -660,13 +673,15 @@ _ensure_port_free "$port"
|
||||
OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \
|
||||
OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \
|
||||
OPENCLAW_GATEWAY_TOKEN="$gw_token" \
|
||||
NODE_COMPILE_CACHE="$node_compile_cache" \
|
||||
NODE_ICU_DATA="${NODE_BASE}/share/icu" \
|
||||
NODE_BASE="$NODE_BASE" \
|
||||
OC_GLOBAL="$OC_GLOBAL" \
|
||||
OC_DATA="$OC_DATA" \
|
||||
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
|
||||
procd_set_param term_timeout 2
|
||||
procd_set_param respawn 3600 1 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param pidfile /var/run/openclaw.pid
|
||||
@@ -689,6 +704,7 @@ procd_set_param env \
|
||||
OC_CONFIG_PORT="$pty_port" \
|
||||
OC_PTY_TOKEN="$pty_token" \
|
||||
OC_CONFIG_SCRIPT="/usr/share/openclaw/oc-config.sh" \
|
||||
NODE_COMPILE_CACHE="$node_compile_cache" \
|
||||
NODE_ICU_DATA="${NODE_BASE}/share/icu" \
|
||||
NODE_BASE="$NODE_BASE" \
|
||||
OC_GLOBAL="$OC_GLOBAL" \
|
||||
@@ -699,6 +715,7 @@ OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw" \
|
||||
OPENCLAW_CONFIG_PATH="$CONFIG_FILE" \
|
||||
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 term_timeout 2
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param pidfile /var/run/openclaw-pty.pid
|
||||
@@ -842,9 +859,10 @@ fi
|
||||
}
|
||||
|
||||
status_service() {
|
||||
local port pty_port
|
||||
local port pty_port enabled
|
||||
port=$(uci -q get openclaw.main.port || echo "18789")
|
||||
pty_port=$(uci -q get openclaw.main.pty_port || echo "18793")
|
||||
enabled=$(uci -q get openclaw.main.enabled || echo "0")
|
||||
|
||||
echo "=== OpenClaw 服务状态 ==="
|
||||
|
||||
@@ -908,10 +926,31 @@ local mins=$(( (uptime % 3600) / 60 ))
|
||||
echo "运行时间: ${hours}小时 ${mins}分钟"
|
||||
fi
|
||||
fi
|
||||
elif pgrep -f "openclaw.*gateway" >/dev/null 2>&1; then
|
||||
echo "网关: 正在启动 (首次启动可能需要 2~5 分钟)"
|
||||
else
|
||||
echo "网关: 已停止"
|
||||
local procd_running procd_pid procd_exit procd_pid_alive pidfile_pid pidfile_stale crash_loop
|
||||
procd_running=$(ubus call service list '{"name":"openclaw"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.running' 2>/dev/null | tr -d '[:space:]')
|
||||
procd_pid=$(ubus call service list '{"name":"openclaw"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.pid' 2>/dev/null | tr -d '[:space:]')
|
||||
procd_exit=$(ubus call service list '{"name":"openclaw"}' 2>/dev/null | jsonfilter -e '$.openclaw.instances.gateway.exit_code' 2>/dev/null | tr -d '[:space:]')
|
||||
[ "$procd_pid" = "null" ] && procd_pid=""
|
||||
[ "$procd_exit" = "null" ] && procd_exit=""
|
||||
procd_pid_alive=0
|
||||
[ -n "$procd_pid" ] && [ -d "/proc/$procd_pid" ] && procd_pid_alive=1
|
||||
pidfile_pid=$(cat /var/run/openclaw.pid 2>/dev/null | tr -d '[:space:]')
|
||||
pidfile_stale=0
|
||||
[ -n "$pidfile_pid" ] && [ ! -d "/proc/$pidfile_pid" ] && pidfile_stale=1
|
||||
crash_loop=$(logread 2>/dev/null | grep -E 'Instance openclaw::gateway.*crash loop' | tail -1)
|
||||
if [ "$enabled" != "1" ]; then
|
||||
echo "网关: 已禁用"
|
||||
elif [ -n "$procd_exit" ] && [ "$procd_exit" != "0" ] && [ "$procd_running" != "true" ]; then
|
||||
echo "网关: 启动失败 (退出码 $procd_exit)"
|
||||
elif [ -n "$crash_loop" ] && [ "$pidfile_stale" = "1" ] && [ "$procd_running" != "true" ] && [ "$procd_pid_alive" != "1" ]; then
|
||||
echo "网关: 启动失败 (procd crash-loop 抑制)"
|
||||
elif [ "$procd_running" = "true" ] || [ "$procd_pid_alive" = "1" ]; then
|
||||
echo "网关: 正在启动 (通常 20~40 秒,首次安装或负载较高时会更久)"
|
||||
[ -n "$procd_pid" ] && echo "进程ID: $procd_pid"
|
||||
else
|
||||
echo "网关: 已停止"
|
||||
fi
|
||||
fi
|
||||
|
||||
# PTY port
|
||||
|
||||
@@ -229,6 +229,35 @@ assert_node_runtime() {
|
||||
if command -v oc_assert_node_min_version >/dev/null 2>&1; then
|
||||
oc_assert_node_min_version "$NODE_BIN" "$required" || exit 1
|
||||
fi
|
||||
|
||||
# OpenClaw CLI 依赖 Unicode property escapes(例如 \p{Extended_Pictographic})。
|
||||
# ARM64 musl 自托管 Node 包必须带上 NODE_ICU_DATA,否则用户直接执行
|
||||
# `openclaw status` 等子命令会在 CLI 入口阶段抛 SyntaxError。
|
||||
if ! NODE_ICU_DATA="${NODE_BASE}/share/icu" "$NODE_BIN" -e "new RegExp('\\\\p{Extended_Pictographic}','u')" >/dev/null 2>&1; then
|
||||
log_error "Node.js ICU/Unicode 正则能力异常,请重新安装 Node.js 运行时"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_openclaw_cli_wrapper() {
|
||||
local oc_entry
|
||||
oc_entry=$(find_oc_entry)
|
||||
[ -n "$oc_entry" ] || return 1
|
||||
ensure_mkdir "$OC_GLOBAL/bin"
|
||||
# npm 默认生成的 openclaw 可能是指向 openclaw.mjs 的 symlink。
|
||||
# 写 wrapper 前必须先 unlink,否则重定向会顺着 symlink 覆盖真实 CLI 入口。
|
||||
rm -f "$OC_GLOBAL/bin/openclaw" 2>/dev/null || true
|
||||
cat > "$OC_GLOBAL/bin/openclaw" << EOF
|
||||
#!/bin/sh
|
||||
export HOME="${OC_DATA}"
|
||||
export OPENCLAW_HOME="${OC_DATA}"
|
||||
export OPENCLAW_STATE_DIR="${OC_DATA}/.openclaw"
|
||||
export OPENCLAW_CONFIG_PATH="${OC_DATA}/.openclaw/openclaw.json"
|
||||
export NODE_ICU_DATA="${NODE_BASE}/share/icu"
|
||||
export PATH="${NODE_BASE}/bin:${OC_GLOBAL}/bin:\$PATH"
|
||||
exec "${NODE_BIN}" "${oc_entry}" "\$@"
|
||||
EOF
|
||||
chmod +x "$OC_GLOBAL/bin/openclaw" 2>/dev/null || true
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
@@ -471,6 +500,7 @@ install_openclaw() {
|
||||
fi
|
||||
|
||||
if [ -n "$oc_ver" ]; then
|
||||
install_openclaw_cli_wrapper || true
|
||||
log_info "OpenClaw v${oc_ver} 安装成功"
|
||||
assert_node_runtime
|
||||
else
|
||||
@@ -510,6 +540,7 @@ do_setup() {
|
||||
|
||||
# 检查是否已安装
|
||||
if [ -x "$NODE_BIN" ] && [ -n "$(find_oc_entry)" ]; then
|
||||
install_openclaw_cli_wrapper || true
|
||||
local oc_ver=""
|
||||
local oc_entry="$(find_oc_entry)"
|
||||
local oc_pkg_dir="$(dirname "$oc_entry")"
|
||||
@@ -665,6 +696,7 @@ do_upgrade() {
|
||||
|
||||
echo ""
|
||||
if [ -n "$new_ver" ]; then
|
||||
install_openclaw_cli_wrapper || true
|
||||
assert_node_runtime
|
||||
if [ "$current_ver" = "$new_ver" ]; then
|
||||
log_info "当前已是最新版本 v${new_ver}"
|
||||
@@ -827,6 +859,7 @@ do_setup_offline() {
|
||||
local oc_entry=$(find_oc_entry)
|
||||
if [ -n "$oc_entry" ]; then
|
||||
local oc_ver=$("$NODE_BIN" "$oc_entry" --version 2>/dev/null | tr -d '[:space:]')
|
||||
install_openclaw_cli_wrapper || true
|
||||
log_info "OpenClaw v${oc_ver} 安装成功"
|
||||
assert_node_runtime
|
||||
else
|
||||
|
||||
@@ -338,7 +338,15 @@ async function restartGateway() {
|
||||
console.log(`\n${C.yellow}正在重启 Gateway...${C.reset}`);
|
||||
|
||||
try {
|
||||
await runCommand('/etc/init.d/openclaw', ['restart_gateway']);
|
||||
await runCommand('/bin/sh', ['-c', [
|
||||
"if [ \"$(uci -q get openclaw.main.enabled 2>/dev/null || echo 0)\" != \"1\" ]; then",
|
||||
" uci -q set openclaw.main.enabled='1';",
|
||||
" uci -q commit openclaw;",
|
||||
" /etc/init.d/openclaw enable >/dev/null 2>&1 || true;",
|
||||
'fi;',
|
||||
'/etc/init.d/openclaw restart_gateway >/dev/null 2>&1 || true;',
|
||||
'/etc/init.d/openclaw start >/dev/null 2>&1 || true'
|
||||
].join(' ')]);
|
||||
} catch {}
|
||||
|
||||
const spin = spinner({ text: 'Gateway 启动中,请稍候 (约 15-30 秒)...' });
|
||||
|
||||
@@ -558,12 +558,22 @@ restart_gateway() {
|
||||
# 修复数据目录权限 (root 用户操作可能改变了文件属主)
|
||||
fix_openclaw_state_permissions 2>/dev/null || true
|
||||
|
||||
# 首次安装后 UCI 默认保持 disabled。用户在配置向导中确认“立即重启”
|
||||
# 即表示希望当前配置生效,这里同步启用服务,避免提示重启但实际仍为“已禁用”。
|
||||
if [ "$(uci -q get openclaw.main.enabled 2>/dev/null || echo 0)" != "1" ]; then
|
||||
echo -e " ${CYAN}检测到 Gateway 未启用,正在启用服务...${NC}"
|
||||
uci -q set openclaw.main.enabled='1' 2>/dev/null || true
|
||||
uci -q commit openclaw 2>/dev/null || true
|
||||
/etc/init.d/openclaw enable >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
local port
|
||||
port=$(json_get gateway.port)
|
||||
port=${port:-18789}
|
||||
|
||||
# ── kill gateway 进程,让 procd respawn ──
|
||||
/etc/init.d/openclaw restart_gateway >/dev/null 2>&1
|
||||
/etc/init.d/openclaw start >/dev/null 2>&1
|
||||
|
||||
# ── 等待端口恢复 (最多 30 秒,含端口释放 + Node.js 冷启动) ──
|
||||
echo -e " ${YELLOW}⏳ Gateway 启动中,请稍候 (约 15-30 秒)...${NC}"
|
||||
|
||||
@@ -94,7 +94,9 @@ chmod +x "$DATA_DIR/etc/profile.d/openclaw.sh"
|
||||
# 计算安装大小
|
||||
INSTALLED_SIZE=$(du -sk "$DATA_DIR" | awk '{print $1}')
|
||||
|
||||
(cd "$DATA_DIR" && tar czf "$STAGING/data.tar.gz" .)
|
||||
# 强制 data.tar.gz 内文件归属为 root:root,避免 GitHub runner / 本地构建用户
|
||||
# 的 UID/GID 泄漏到用户机器(例如安装后出现 1001:1001)。
|
||||
(cd "$DATA_DIR" && tar --owner=0 --group=0 --numeric-owner -czf "$STAGING/data.tar.gz" .)
|
||||
|
||||
# ── 构建 control.tar.gz ──
|
||||
CTRL_DIR="$STAGING/control"
|
||||
@@ -169,10 +171,48 @@ cat > "$CTRL_DIR/postinst" << 'EOF'
|
||||
|
||||
# 清理 LuCI 缓存
|
||||
rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* /tmp/luci-indexcache.*.json 2>/dev/null
|
||||
|
||||
# 双保险:确保系统侧文件保持 root:root,避免非 SDK 打包时构建机 UID/GID
|
||||
# 泄漏到目标机器。不要触碰 /opt/openclaw 运行数据。
|
||||
for p in \
|
||||
/etc/init.d/openclaw \
|
||||
/etc/profile.d/openclaw.sh \
|
||||
/usr/bin/openclaw-env \
|
||||
/usr/libexec/openclaw-permissions.sh \
|
||||
/usr/lib/lua/luci/controller/openclaw.lua \
|
||||
/usr/lib/lua/luci/model/cbi/openclaw \
|
||||
/usr/lib/lua/luci/view/openclaw \
|
||||
/usr/lib/lua/openclaw \
|
||||
/usr/share/openclaw \
|
||||
/usr/share/rpcd/acl.d/luci-app-openclaw.json
|
||||
do
|
||||
[ -e "$p" ] && chown -R root:root "$p" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# 升级/重装后修复已存在的 OpenClaw 运行数据权限。尤其是 npm 外部插件:
|
||||
# npm 安装阶段需要 openclaw 可写,运行阶段插件源码目录必须 root:root,
|
||||
# 否则 OpenClaw 会因为 suspicious ownership 拒绝加载微信插件。
|
||||
OPENCLAW_INSTALL_BASE="$(uci -q get openclaw.main.install_path 2>/dev/null || echo /opt)"
|
||||
if [ -r /usr/libexec/openclaw-paths.sh ]; then
|
||||
. /usr/libexec/openclaw-paths.sh
|
||||
oc_load_paths "$OPENCLAW_INSTALL_BASE" 2>/dev/null || true
|
||||
else
|
||||
OPENCLAW_INSTALL_BASE="${OPENCLAW_INSTALL_BASE%/}"
|
||||
OC_DATA="${OPENCLAW_INSTALL_BASE}/openclaw/data"
|
||||
fi
|
||||
if [ -n "${OC_DATA:-}" ] && [ -d "${OC_DATA}/.openclaw" ] && [ -x /usr/libexec/openclaw-permissions.sh ]; then
|
||||
/usr/libexec/openclaw-permissions.sh fix-state "${OC_DATA}/.openclaw" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# 重启 Web PTY (使其加载新文件和新 token)
|
||||
PTY_PID=$(pgrep -f 'web-pty.js' 2>/dev/null | head -1)
|
||||
[ -n "$PTY_PID" ] && kill "$PTY_PID" 2>/dev/null || true
|
||||
|
||||
# 如果用户原本启用了 OpenClaw,opkg reinstall/upgrade 后恢复服务。
|
||||
if [ "$(uci -q get openclaw.main.enabled 2>/dev/null || echo 0)" = "1" ] && [ -x /etc/init.d/openclaw ]; then
|
||||
/etc/init.d/openclaw enable >/dev/null 2>&1 || true
|
||||
/etc/init.d/openclaw start >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -132,6 +132,24 @@ echo "正在安装文件..."
|
||||
ARCHIVE=$(awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' "$0")
|
||||
tail -n +$ARCHIVE "$0" | tar xzf - -C / 2>/dev/null
|
||||
|
||||
# 双保险:即使构建环境 tar 不支持 owner 规范化,也不要把构建机 UID/GID
|
||||
# 带到路由器系统文件中。这里仅修复本插件安装的系统侧文件,不触碰
|
||||
# /opt/openclaw 运行数据和 OpenClaw npm 插件状态目录。
|
||||
for p in \
|
||||
/etc/init.d/openclaw \
|
||||
/etc/profile.d/openclaw.sh \
|
||||
/usr/bin/openclaw-env \
|
||||
/usr/libexec/openclaw-permissions.sh \
|
||||
/usr/lib/lua/luci/controller/openclaw.lua \
|
||||
/usr/lib/lua/luci/model/cbi/openclaw \
|
||||
/usr/lib/lua/luci/view/openclaw \
|
||||
/usr/lib/lua/openclaw \
|
||||
/usr/share/openclaw \
|
||||
/usr/share/rpcd/acl.d/luci-app-openclaw.json
|
||||
do
|
||||
[ -e "$p" ] && chown -R root:root "$p" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# UCI 配置文件保护: 升级时不覆盖用户已有配置
|
||||
if [ -f /etc/config/openclaw ] && [ -f /etc/config/openclaw.default ]; then
|
||||
# 已有配置, 移除默认文件 (保留用户配置)
|
||||
@@ -261,7 +279,9 @@ echo "[4/4] 打包..."
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
# 创建 payload tarball
|
||||
(cd "$STAGING/payload" && tar czf "$STAGING/payload.tar.gz" .)
|
||||
# 强制 payload 内文件归属为 root:root,避免 GitHub runner / 本地构建用户
|
||||
# 的 UID/GID 泄漏到用户机器(例如安装后出现 1001:1001)。
|
||||
(cd "$STAGING/payload" && tar --owner=0 --group=0 --numeric-owner -czf "$STAGING/payload.tar.gz" .)
|
||||
|
||||
# 组合: installer header + payload
|
||||
RUN_FILE="$OUT_DIR/${PKG_NAME}_${PKG_VERSION}.run"
|
||||
|
||||
@@ -11,6 +11,12 @@ grep -q "NODE_VERSION_V2=\"22.23.0\"" root/usr/bin/openclaw-env || fail "default
|
||||
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"
|
||||
grep -q "install_openclaw_cli_wrapper" root/usr/bin/openclaw-env || fail "OpenClaw CLI wrapper must set runtime env"
|
||||
grep -q 'export NODE_ICU_DATA="${NODE_BASE}/share/icu"' root/usr/bin/openclaw-env || fail "OpenClaw CLI wrapper must export NODE_ICU_DATA"
|
||||
grep -q 'rm -f "$OC_GLOBAL/bin/openclaw"' root/usr/bin/openclaw-env || fail "OpenClaw CLI wrapper must unlink npm symlink before writing"
|
||||
grep -q "Extended_Pictographic" root/usr/bin/openclaw-env || fail "Node runtime must validate Unicode property escapes"
|
||||
grep -q "uci -q set openclaw.main.enabled='1'" root/usr/share/openclaw/oc-config.sh || fail "traditional config restart must enable gateway after first install"
|
||||
grep -q "uci -q set openclaw.main.enabled='1'" root/usr/share/openclaw/oc-config-interactive.js || fail "interactive config restart must enable gateway after first install"
|
||||
if grep -q 'v1_tarball' root/usr/bin/openclaw-env; then
|
||||
fail "installer must not silently fall back to legacy Node.js tarball"
|
||||
fi
|
||||
@@ -18,6 +24,10 @@ 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"
|
||||
grep -q "openclaw-permissions.sh" Makefile || fail "Makefile must install permission helper"
|
||||
grep -q 'openclaw-permissions.sh fix-state "$${OC_DATA}/.openclaw"' Makefile || fail "postinst must repair existing OpenClaw state permissions after reinstall"
|
||||
grep -q '/etc/init.d/openclaw start >/dev/null 2>&1' Makefile || fail "postinst must restart enabled OpenClaw service after reinstall"
|
||||
grep -q 'openclaw-permissions.sh fix-state "${OC_DATA}/.openclaw"' scripts/build_ipk.sh || fail "release ipk postinst must repair existing OpenClaw state permissions after reinstall"
|
||||
grep -q '/etc/init.d/openclaw start >/dev/null 2>&1' scripts/build_ipk.sh || fail "release ipk postinst must restart enabled OpenClaw service after reinstall"
|
||||
if grep -q "openclaw.zh-cn.lmo" Makefile; then
|
||||
fail "main package must not install openclaw.zh-cn.lmo"
|
||||
fi
|
||||
@@ -52,11 +62,19 @@ grep -q "packageName: '@tencent-weixin/openclaw-weixin'" luasrc/controller/openc
|
||||
grep -q "channels\\['openclaw-weixin'\\].enabled = true" luasrc/controller/openclaw.lua || fail "wechat channel enable registration missing"
|
||||
grep -q "Registered openclaw-weixin npm plugin" luasrc/controller/openclaw.lua || fail "wechat install log must confirm config registration"
|
||||
grep -q "wechat_network_probe_cmd" luasrc/controller/openclaw.lua || fail "wechat network probe helper missing"
|
||||
grep -q "NODE_ICU_DATA=%s/node/share/icu" luasrc/controller/openclaw.lua || fail "wechat LuCI CLI commands must export NODE_ICU_DATA"
|
||||
grep -q "openclaw_user_runner_cmd" luasrc/controller/openclaw.lua || fail "wechat commands need user runner compatibility helper"
|
||||
grep -q "ulimit -v unlimited" luasrc/controller/openclaw.lua || fail "wechat commands must lift LuCI inherited address-space limit before Node CLI"
|
||||
grep -q "start-stop-daemon -S -m -p" luasrc/controller/openclaw.lua || fail "wechat commands must support OpenWrt without su"
|
||||
grep -q "command -v curl" luasrc/controller/openclaw.lua || fail "wechat network probe should prefer curl"
|
||||
grep -q "%%{http_code}" luasrc/controller/openclaw.lua || fail "wechat curl probe percent must be escaped for string.format"
|
||||
grep -q "wechat_npm_fallback_install_cmd" luasrc/controller/openclaw.lua || fail "wechat install needs npm fallback for OpenWrt Node undici OOM"
|
||||
if awk '/function action_wechat_install\(\)/,/function action_wechat_install_log\(\)/' luasrc/controller/openclaw.lua | grep -q "ensure_port_free"; then
|
||||
fail "wechat install must not stop gateway before plugin installation"
|
||||
fi
|
||||
if awk '/function action_wechat_upgrade_plugin\(\)/,/function action_wechat_uninstall_plugin\(\)/' luasrc/controller/openclaw.lua | grep -q "ensure_port_free"; then
|
||||
fail "wechat upgrade must not stop gateway before plugin upgrade"
|
||||
fi
|
||||
grep -q "npm install --omit=dev --omit=peer" luasrc/controller/openclaw.lua || fail "wechat npm fallback install command missing"
|
||||
grep -q "tencent-weixin-openclaw-weixin-7783ac86ba" luasrc/controller/openclaw.lua || fail "wechat npm fallback project dir missing"
|
||||
grep -q "export OC_WECHAT_DATA" luasrc/controller/openclaw.lua || fail "wechat npm fallback must export data dir into openclaw user shell"
|
||||
@@ -66,6 +84,9 @@ grep -q "is_newer_version(latest_version, current_version)" luasrc/controller/op
|
||||
grep -q "ilinkai.weixin.qq.com" luasrc/controller/openclaw.lua || fail "wechat network probe endpoint missing"
|
||||
grep -q "微信接口连通性检查" luasrc/controller/openclaw.lua || fail "wechat network probe log missing"
|
||||
grep -q "error_detail" luasrc/controller/openclaw.lua || fail "wechat login failure detail response missing"
|
||||
grep -q "已将此 OpenClaw 连接到微信" luasrc/controller/openclaw.lua || fail "wechat login status must treat saved auth as success"
|
||||
grep -q "Local login saved auth for openclaw%-weixin" luasrc/controller/openclaw.lua || fail "wechat login status must tolerate channels.start restart warning"
|
||||
grep -q "/etc/init.d/openclaw restart_gateway >/dev/null 2>&1 &" luasrc/controller/openclaw.lua || fail "wechat login success should use lightweight gateway restart"
|
||||
grep -q "self_heal_wechat_npm_plugin_config" root/etc/init.d/openclaw || fail "init.d wechat npm plugin self-heal missing"
|
||||
grep -q "已自愈注册 openclaw-weixin npm plugin" root/etc/init.d/openclaw || fail "init.d wechat self-heal log missing"
|
||||
grep -q "OC_WECHAT_PLUGIN_DIR" root/etc/init.d/openclaw || fail "init.d wechat self-heal plugin dir env missing"
|
||||
@@ -74,6 +95,14 @@ grep -q "fix_openclaw_state_permissions" root/etc/init.d/openclaw || fail "init.
|
||||
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 "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"
|
||||
grep -q "procd_set_param term_timeout 2" root/etc/init.d/openclaw || fail "procd term timeout must be bounded for faster restart"
|
||||
grep -q "procd_set_param respawn 3600 1 5" root/etc/init.d/openclaw || fail "gateway respawn timeout must be short for faster restart_gateway"
|
||||
grep -q 'openclaw.main.clear_jiti_cache_on_start' root/etc/init.d/openclaw || fail "JITI cleanup must be guarded by UCI flag"
|
||||
grep -q "openclaw-node-compile-cache" root/etc/init.d/openclaw || fail "Node compile cache must be enabled for faster warm restarts"
|
||||
grep -q 'NODE_COMPILE_CACHE="$node_compile_cache"' root/etc/init.d/openclaw || fail "gateway and pty must receive Node compile cache env"
|
||||
grep -q "通常 20~40 秒" root/etc/init.d/openclaw luasrc/view/openclaw/status.htm luasrc/view/openclaw/console.htm || fail "startup hint must match measured OpenWrt timing"
|
||||
grep -q "restart_gateway >/dev/null 2>&1 &" luasrc/controller/openclaw.lua || fail "LuCI restart action should use lightweight gateway restart"
|
||||
grep -q "oc_fix_npm_projects_permissions" root/usr/libexec/openclaw-permissions.sh || fail "npm projects permission helper missing"
|
||||
grep -q "openclaw.plugin.json" root/usr/libexec/openclaw-permissions.sh || fail "npm plugin root detection must use plugin manifest"
|
||||
grep -q "node_modules/@tencent-weixin/openclaw-weixin" root/usr/libexec/openclaw-permissions.sh || fail "wechat npm plugin compatibility permission fix missing"
|
||||
@@ -125,6 +154,10 @@ 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"
|
||||
grep -q "for dep in luci-compat luci-base curl openssl-util script-utils tar libstdcpp6" scripts/build_run.sh || fail ".run installer must install runtime dependencies"
|
||||
grep -q -- "--owner=0 --group=0 --numeric-owner" scripts/build_run.sh || fail ".run payload must normalize file ownership to root"
|
||||
grep -q -- "--owner=0 --group=0 --numeric-owner" scripts/build_ipk.sh || fail ".ipk payload must normalize file ownership to root"
|
||||
grep -q "chown -R root:root" scripts/build_run.sh || fail ".run installer must repair root-owned system files after extraction"
|
||||
grep -q "chown -R root:root" scripts/build_ipk.sh || fail ".ipk postinst must repair root-owned system files after extraction"
|
||||
grep -q "先解压到临时目录并确认完整,再替换 NODE_BASE" root/usr/bin/openclaw-env || fail "Node install must not delete existing runtime before extraction succeeds"
|
||||
grep -q "OC_SETUP_FRESH_ROOT" root/usr/bin/openclaw-env || fail "setup cleanup must preserve existing runtime roots"
|
||||
|
||||
|
||||
@@ -16,10 +16,19 @@ grep -Fq "ubus call service list" "$CONTROLLER" || fail "status API should inspe
|
||||
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 "gateway_crash_loop" "$CONTROLLER" || fail "status API should expose procd crash-loop state"
|
||||
grep -Fq "procd_pid_alive" "$CONTROLLER" || fail "status API should ignore stale procd pidfiles"
|
||||
grep -Fq "pidfile_stale" "$CONTROLLER" || fail "status API should require current stale pidfile evidence for crash-loop"
|
||||
grep -Fq 'enabled=$(uci -q get openclaw.main.enabled' "$INIT_SCRIPT" || fail "status_service should honor disabled service state"
|
||||
grep -Fq "网关: 已禁用" "$INIT_SCRIPT" || fail "status_service should report disabled gateway before crash-loop"
|
||||
if grep -Fq 'pgrep -f "openclaw.*gateway"' "$CONTROLLER" "$INIT_SCRIPT" || grep -Fq "pgrep -f 'openclaw.*gateway'" "$CONTROLLER" "$INIT_SCRIPT"; then
|
||||
fail "status checks must not use broad pgrep fallback that can match the status shell itself"
|
||||
fi
|
||||
|
||||
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"
|
||||
grep -Fq "crash-loop 抑制" "$INIT_SCRIPT" || fail "status_service should report procd crash-loop suppression"
|
||||
|
||||
echo "ok"
|
||||
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-ssr-plus
|
||||
PKG_VERSION:=196
|
||||
PKG_RELEASE:=42
|
||||
PKG_RELEASE:=43
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
@@ -32,7 +32,7 @@ LUCI_PKGARCH:=all
|
||||
LUCI_DEPENDS:= \
|
||||
+libuci-lua +lua +luci-compat +coreutils +coreutils-base64 +dns2tcp +dnsmasq-full \
|
||||
+jq +ip-full +lua-neturl +libuci-lua +microsocks +ipt2socks +lyaml \
|
||||
+resolveip +curl +nping +unzip +xz-utils \
|
||||
+resolveip +curl +nping +unzip +xz-utils +xz \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:coreutils-timeout \
|
||||
+PACKAGE_$(PKG_NAME)_INCLUDE_Http_Proxy:3proxy \
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"test": "node --test tests/*.test.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eamonxg/aurora-tokens": "^1.0.0",
|
||||
"@eamonxg/aurora-tokens": "^1.0.1",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/node": "^24.0.0",
|
||||
"browserslist": "^4.28.2",
|
||||
|
||||
Generated
+112
-226
@@ -7,20 +7,22 @@ settings:
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
colorjs.io:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1
|
||||
devDependencies:
|
||||
'@eamonxg/aurora-tokens':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.11
|
||||
version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0))
|
||||
version: 4.3.2(vite@7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0))
|
||||
'@types/node':
|
||||
specifier: ^24.0.0
|
||||
version: 24.10.9
|
||||
browserslist:
|
||||
specifier: ^4.28.2
|
||||
version: 4.28.2
|
||||
colorjs.io:
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1
|
||||
lightningcss:
|
||||
specifier: ^1.32.0
|
||||
version: 1.32.0
|
||||
@@ -32,10 +34,10 @@ importers:
|
||||
version: 0.7.2(prettier@3.8.1)
|
||||
tailwind-scrollbar:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(react@19.1.1)(tailwindcss@4.1.18)
|
||||
version: 4.0.2(react@19.1.1)(tailwindcss@4.3.2)
|
||||
tailwindcss:
|
||||
specifier: ^4.1.11
|
||||
version: 4.1.18
|
||||
version: 4.3.2
|
||||
terser:
|
||||
specifier: ^5.43.1
|
||||
version: 5.46.0
|
||||
@@ -44,10 +46,13 @@ importers:
|
||||
version: 1.4.0
|
||||
vite:
|
||||
specifier: ^7.1.1
|
||||
version: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0)
|
||||
version: 7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0)
|
||||
|
||||
packages:
|
||||
|
||||
'@eamonxg/aurora-tokens@1.0.1':
|
||||
resolution: {integrity: sha512-AbqXZfEEDwxLiSjg+h4vFHeEE0GTb7vwyKvfh7GJK3TKCP0DNTfJpdIqI+6KhiXDLQI5nHuwYvbmx77o+baAjA==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.2':
|
||||
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -361,69 +366,69 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/node@4.1.18':
|
||||
resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
|
||||
'@tailwindcss/node@4.3.2':
|
||||
resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==}
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.1.18':
|
||||
resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-android-arm64@4.3.2':
|
||||
resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.1.18':
|
||||
resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.2':
|
||||
resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.1.18':
|
||||
resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.2':
|
||||
resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.1.18':
|
||||
resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.2':
|
||||
resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
|
||||
resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2':
|
||||
resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
|
||||
resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.2':
|
||||
resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.2':
|
||||
resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||
resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.2':
|
||||
resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.2':
|
||||
resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||
resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.2':
|
||||
resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
cpu: [wasm32]
|
||||
bundledDependencies:
|
||||
@@ -434,26 +439,26 @@ packages:
|
||||
- '@emnapi/wasi-threads'
|
||||
- tslib
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
|
||||
resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.2':
|
||||
resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.1.18':
|
||||
resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.2':
|
||||
resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==}
|
||||
engines: {node: '>= 20'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tailwindcss/oxide@4.1.18':
|
||||
resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
|
||||
engines: {node: '>= 10'}
|
||||
'@tailwindcss/oxide@4.3.2':
|
||||
resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
'@tailwindcss/vite@4.1.18':
|
||||
resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==}
|
||||
'@tailwindcss/vite@4.3.2':
|
||||
resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==}
|
||||
peerDependencies:
|
||||
vite: ^5.2.0 || ^6 || ^7
|
||||
vite: ^5.2.0 || ^6 || ^7 || ^8
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
@@ -502,8 +507,8 @@ packages:
|
||||
electron-to-chromium@1.5.372:
|
||||
resolution: {integrity: sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==}
|
||||
|
||||
enhanced-resolve@5.18.4:
|
||||
resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
|
||||
enhanced-resolve@5.21.6:
|
||||
resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
esbuild@0.27.2:
|
||||
@@ -532,77 +537,40 @@ packages:
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
jiti@2.6.1:
|
||||
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||
jiti@2.7.0:
|
||||
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
|
||||
hasBin: true
|
||||
|
||||
lightningcss-android-arm64@1.30.2:
|
||||
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
lightningcss-android-arm64@1.32.0:
|
||||
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
lightningcss-darwin-arm64@1.30.2:
|
||||
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-darwin-arm64@1.32.0:
|
||||
resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-darwin-x64@1.30.2:
|
||||
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-darwin-x64@1.32.0:
|
||||
resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
lightningcss-freebsd-x64@1.30.2:
|
||||
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
lightningcss-freebsd-x64@1.32.0:
|
||||
resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.32.0:
|
||||
resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.30.2:
|
||||
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.32.0:
|
||||
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -610,13 +578,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -624,13 +585,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.30.2:
|
||||
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.32.0:
|
||||
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -638,13 +592,6 @@ packages:
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-musl@1.32.0:
|
||||
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -652,34 +599,18 @@ packages:
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.30.2:
|
||||
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.32.0:
|
||||
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss-win32-x64-msvc@1.30.2:
|
||||
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss-win32-x64-msvc@1.32.0:
|
||||
resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
lightningcss@1.30.2:
|
||||
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
lightningcss@1.32.0:
|
||||
resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -798,11 +729,11 @@ packages:
|
||||
peerDependencies:
|
||||
tailwindcss: 4.x
|
||||
|
||||
tailwindcss@4.1.18:
|
||||
resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
|
||||
tailwindcss@4.3.2:
|
||||
resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==}
|
||||
|
||||
tapable@2.3.0:
|
||||
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
|
||||
tapable@2.3.3:
|
||||
resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
terser@5.46.0:
|
||||
@@ -868,6 +799,10 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@eamonxg/aurora-tokens@1.0.1':
|
||||
dependencies:
|
||||
colorjs.io: 0.6.1
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.2':
|
||||
optional: true
|
||||
|
||||
@@ -1045,73 +980,73 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc@4.57.1':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/node@4.1.18':
|
||||
'@tailwindcss/node@4.3.2':
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
enhanced-resolve: 5.18.4
|
||||
jiti: 2.6.1
|
||||
lightningcss: 1.30.2
|
||||
enhanced-resolve: 5.21.6
|
||||
jiti: 2.7.0
|
||||
lightningcss: 1.32.0
|
||||
magic-string: 0.30.21
|
||||
source-map-js: 1.2.1
|
||||
tailwindcss: 4.1.18
|
||||
tailwindcss: 4.3.2
|
||||
|
||||
'@tailwindcss/oxide-android-arm64@4.1.18':
|
||||
'@tailwindcss/oxide-android-arm64@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-arm64@4.1.18':
|
||||
'@tailwindcss/oxide-darwin-arm64@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-darwin-x64@4.1.18':
|
||||
'@tailwindcss/oxide-darwin-x64@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-freebsd-x64@4.1.18':
|
||||
'@tailwindcss/oxide-freebsd-x64@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
|
||||
'@tailwindcss/oxide-linux-arm64-gnu@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
|
||||
'@tailwindcss/oxide-win32-arm64-msvc@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.1.18':
|
||||
'@tailwindcss/oxide-win32-x64-msvc@4.3.2':
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/oxide@4.1.18':
|
||||
'@tailwindcss/oxide@4.3.2':
|
||||
optionalDependencies:
|
||||
'@tailwindcss/oxide-android-arm64': 4.1.18
|
||||
'@tailwindcss/oxide-darwin-arm64': 4.1.18
|
||||
'@tailwindcss/oxide-darwin-x64': 4.1.18
|
||||
'@tailwindcss/oxide-freebsd-x64': 4.1.18
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
|
||||
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
|
||||
'@tailwindcss/oxide-linux-arm64-musl': 4.1.18
|
||||
'@tailwindcss/oxide-linux-x64-gnu': 4.1.18
|
||||
'@tailwindcss/oxide-linux-x64-musl': 4.1.18
|
||||
'@tailwindcss/oxide-wasm32-wasi': 4.1.18
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.1.18
|
||||
'@tailwindcss/oxide-android-arm64': 4.3.2
|
||||
'@tailwindcss/oxide-darwin-arm64': 4.3.2
|
||||
'@tailwindcss/oxide-darwin-x64': 4.3.2
|
||||
'@tailwindcss/oxide-freebsd-x64': 4.3.2
|
||||
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2
|
||||
'@tailwindcss/oxide-linux-arm64-gnu': 4.3.2
|
||||
'@tailwindcss/oxide-linux-arm64-musl': 4.3.2
|
||||
'@tailwindcss/oxide-linux-x64-gnu': 4.3.2
|
||||
'@tailwindcss/oxide-linux-x64-musl': 4.3.2
|
||||
'@tailwindcss/oxide-wasm32-wasi': 4.3.2
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.3.2
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.3.2
|
||||
|
||||
'@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0))':
|
||||
'@tailwindcss/vite@4.3.2(vite@7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.1.18
|
||||
'@tailwindcss/oxide': 4.1.18
|
||||
tailwindcss: 4.1.18
|
||||
vite: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0)
|
||||
'@tailwindcss/node': 4.3.2
|
||||
'@tailwindcss/oxide': 4.3.2
|
||||
tailwindcss: 4.3.2
|
||||
vite: 7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0)
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
@@ -1147,10 +1082,10 @@ snapshots:
|
||||
|
||||
electron-to-chromium@1.5.372: {}
|
||||
|
||||
enhanced-resolve@5.18.4:
|
||||
enhanced-resolve@5.21.6:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.3.0
|
||||
tapable: 2.3.3
|
||||
|
||||
esbuild@0.27.2:
|
||||
optionalDependencies:
|
||||
@@ -1192,90 +1127,41 @@ snapshots:
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
jiti@2.6.1: {}
|
||||
|
||||
lightningcss-android-arm64@1.30.2:
|
||||
optional: true
|
||||
jiti@2.7.0: {}
|
||||
|
||||
lightningcss-android-arm64@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-darwin-arm64@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-darwin-arm64@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-darwin-x64@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-darwin-x64@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-freebsd-x64@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-freebsd-x64@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm-gnueabihf@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-gnu@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-musl@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-arm64-musl@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-gnu@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-gnu@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-musl@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-linux-x64-musl@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-x64-msvc@1.30.2:
|
||||
optional: true
|
||||
|
||||
lightningcss-win32-x64-msvc@1.32.0:
|
||||
optional: true
|
||||
|
||||
lightningcss@1.30.2:
|
||||
dependencies:
|
||||
detect-libc: 2.1.2
|
||||
optionalDependencies:
|
||||
lightningcss-android-arm64: 1.30.2
|
||||
lightningcss-darwin-arm64: 1.30.2
|
||||
lightningcss-darwin-x64: 1.30.2
|
||||
lightningcss-freebsd-x64: 1.30.2
|
||||
lightningcss-linux-arm-gnueabihf: 1.30.2
|
||||
lightningcss-linux-arm64-gnu: 1.30.2
|
||||
lightningcss-linux-arm64-musl: 1.30.2
|
||||
lightningcss-linux-x64-gnu: 1.30.2
|
||||
lightningcss-linux-x64-musl: 1.30.2
|
||||
lightningcss-win32-arm64-msvc: 1.30.2
|
||||
lightningcss-win32-x64-msvc: 1.30.2
|
||||
|
||||
lightningcss@1.32.0:
|
||||
dependencies:
|
||||
detect-libc: 2.1.2
|
||||
@@ -1364,16 +1250,16 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
tailwind-scrollbar@4.0.2(react@19.1.1)(tailwindcss@4.1.18):
|
||||
tailwind-scrollbar@4.0.2(react@19.1.1)(tailwindcss@4.3.2):
|
||||
dependencies:
|
||||
prism-react-renderer: 2.4.1(react@19.1.1)
|
||||
tailwindcss: 4.1.18
|
||||
tailwindcss: 4.3.2
|
||||
transitivePeerDependencies:
|
||||
- react
|
||||
|
||||
tailwindcss@4.1.18: {}
|
||||
tailwindcss@4.3.2: {}
|
||||
|
||||
tapable@2.3.0: {}
|
||||
tapable@2.3.3: {}
|
||||
|
||||
terser@5.46.0:
|
||||
dependencies:
|
||||
@@ -1397,7 +1283,7 @@ snapshots:
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.0):
|
||||
vite@7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0):
|
||||
dependencies:
|
||||
esbuild: 0.27.2
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
@@ -1408,6 +1294,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/node': 24.10.9
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
jiti: 2.7.0
|
||||
lightningcss: 1.32.0
|
||||
terser: 5.46.0
|
||||
@@ -11,7 +11,7 @@
|
||||
--text: oklch(0.21 0.02 264);
|
||||
--brand: oklch(0.58 0.14 233);
|
||||
--on-brand: oklch(1 0 0);
|
||||
--link: oklch(0.74 0.238 322.16);
|
||||
--link: oklch(0.58 0.14 233);
|
||||
--info: oklch(0.45 0.12 255);
|
||||
--warning: oklch(0.35 0.08 60);
|
||||
--success: oklch(0.32 0.09 165);
|
||||
@@ -53,7 +53,7 @@
|
||||
--text: oklch(0.985 0.002 264);
|
||||
--brand: oklch(0.6 0.13 188.745);
|
||||
--on-brand: oklch(1 0 0);
|
||||
--link: oklch(0.77 0.14 168);
|
||||
--link: oklch(0.6 0.13 188.745);
|
||||
--info: oklch(0.8 0.11 255);
|
||||
--warning: oklch(0.82 0.13 80);
|
||||
--success: oklch(0.72 0.13 158);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
|
||||
&:not(.btn):not(.cbi-button) {
|
||||
@apply border-hairline bg-surface rounded-2xl border;
|
||||
@apply border-hairline bg-surface min-w-52.5 max-w-full rounded-2xl border md:max-w-100;
|
||||
& > ul > li {
|
||||
&[placeholder] {
|
||||
@apply hidden;
|
||||
@@ -116,6 +116,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[empty] > .more {
|
||||
@apply flex-1;
|
||||
}
|
||||
|
||||
&[open] {
|
||||
& > ul.dropdown > li > form {
|
||||
@apply flex items-center;
|
||||
|
||||
@@ -6,7 +6,7 @@ input[type="text"],
|
||||
input[type="password"],
|
||||
.cbi-input-text,
|
||||
.cbi-input {
|
||||
@apply text-text border-hairline bg-surface-overlay dark:bg-surface-sunken placeholder-text-muted focus:border-brand focus:ring-focus-ring relative rounded-2xl border px-3 py-1.5 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:outline-none;
|
||||
@apply text-text border-hairline bg-surface-overlay dark:bg-surface-sunken placeholder-text-muted focus:border-brand focus:ring-focus-ring relative w-52.5 max-w-full rounded-2xl border px-3 py-1.5 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:outline-none;
|
||||
|
||||
.table.cbi-section-table & {
|
||||
@apply w-full;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
select {
|
||||
@apply text-text border-hairline bg-surface-overlay dark:bg-surface-sunken focus:border-brand focus:ring-focus-ring appearance-none rounded-2xl border px-3 py-1.5 pr-10 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:outline-none;
|
||||
@apply text-text border-hairline bg-surface-overlay dark:bg-surface-sunken focus:border-brand focus:ring-focus-ring min-w-52.5 max-w-full appearance-none md:max-w-100 rounded-2xl border px-3 py-1.5 pr-10 text-sm font-normal shadow-sm transition-[border-color,box-shadow] duration-150 focus:ring-2 focus:outline-none;
|
||||
@apply bg-[url('@assets/icons/arrow-down.svg')] bg-size-[16px] bg-position-[right_0.75rem_center] bg-no-repeat dark:bg-[url('@assets/icons/arrow-down-dark.svg')];
|
||||
&[disabled] {
|
||||
@apply cursor-not-allowed opacity-40 dark:opacity-30;
|
||||
|
||||
@@ -38,6 +38,13 @@ table.table,
|
||||
@apply max-md:border-hairline max-md:flex max-md:flex-wrap max-md:border-b max-md:px-2 max-md:py-2;
|
||||
@apply has-[.cbi-progressbar]:max-md:flex has-[.cbi-progressbar]:max-md:items-center has-[.cbi-progressbar]:max-md:justify-center;
|
||||
|
||||
&:first-child {
|
||||
& th,
|
||||
& .th {
|
||||
@apply first:rounded-tl-2xl last:rounded-tr-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@apply max-md:border-b-0;
|
||||
&[data-title] {
|
||||
@@ -102,7 +109,7 @@ table.table,
|
||||
|
||||
& th,
|
||||
& .th {
|
||||
@apply border-hairline bg-surface-sunken text-text-subtle border-b px-3 py-3 text-left text-xs font-semibold tracking-wider uppercase first:rounded-tl-2xl last:rounded-tr-2xl max-md:flex-[1_1_50%] max-md:border-0 max-md:bg-transparent;
|
||||
@apply border-hairline bg-surface-sunken text-text-subtle border-b px-3 py-3 text-left text-xs font-semibold tracking-wider uppercase max-md:flex-[1_1_50%] max-md:border-0 max-md:bg-transparent;
|
||||
|
||||
#cbi-samba4 & {
|
||||
@apply px-0.5 py-1.5;
|
||||
@@ -152,13 +159,32 @@ table.table,
|
||||
|
||||
& > input[type="text"],
|
||||
& > input[type="password"],
|
||||
& > select,
|
||||
& > .cbi-dropdown:not(.btn):not(.cbi-button) {
|
||||
& select,
|
||||
& .cbi-dropdown:not(.btn):not(.cbi-button) {
|
||||
@apply w-full;
|
||||
}
|
||||
|
||||
/* Widgets are nested (td > div > div > widget), so the fixed/min widths
|
||||
from _select.css/_dropdown.css must yield to the column width here. */
|
||||
& select,
|
||||
& .cbi-dropdown:not(.btn):not(.cbi-button) {
|
||||
@apply min-w-fit;
|
||||
}
|
||||
|
||||
&.cbi-value-field {
|
||||
@apply break-all;
|
||||
/* Mobile cards (bootstrap-style): value fields stack one per row —
|
||||
the row title and long match-rule cells get the full width — while
|
||||
display-only widgets below pair up two per row. */
|
||||
@apply break-all max-md:mb-1 max-md:basis-full max-md:self-start max-md:text-left;
|
||||
|
||||
&[data-widget="CBI.DummyValue"],
|
||||
&[data-widget="CBI.Button"],
|
||||
&[data-widget="CBI.FlagValue"],
|
||||
&[data-widget="dvalue"],
|
||||
&[data-widget="button"],
|
||||
&[data-widget="fvalue"] {
|
||||
@apply max-md:basis-1/2;
|
||||
}
|
||||
}
|
||||
|
||||
&.cbi-section-actions {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
.cbi-tooltip {
|
||||
@apply bg-surface-overlay text-text border-hairline absolute z-110 max-w-xs scale-95 rounded-xl border px-3 py-2 text-xs break-normal whitespace-normal opacity-0 shadow-xl transition-[visibility,opacity,scale] duration-150 ease-out;
|
||||
/* Hidden bubbles park off-screen (bootstrap's `left:-10000px` trick): a
|
||||
visibility-hidden absolute box left at its anchor still counts into the
|
||||
page's scrollable overflow, so the horizontal scrollbar would survive the
|
||||
bubble's disappearance and the page could never snap back. `:hover`
|
||||
returns it via `inset-s-auto`; the inset isn't transitioned, so the move
|
||||
is instant while opacity/scale animate. */
|
||||
@apply bg-surface-overlay text-text border-hairline absolute inset-s-[-10000px] z-110 w-max max-w-xs scale-95 rounded-xl border px-3 py-2 text-xs break-normal whitespace-normal opacity-0 shadow-xl transition-[visibility,opacity,scale] duration-150 ease-out;
|
||||
&.error {
|
||||
@apply border-hairline bg-danger-surface text-danger;
|
||||
}
|
||||
@@ -23,6 +29,6 @@
|
||||
}
|
||||
|
||||
&:hover .cbi-tooltip {
|
||||
@apply visible scale-100 opacity-100;
|
||||
@apply visible scale-100 opacity-100 inset-s-auto;
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,16 @@ test("tables get a hairline frame + sunken header, body stays unclipped", () =>
|
||||
assert.ok(!root.includes("overflow-hidden"), `body clipped: ${root}`);
|
||||
assert.ok(root.includes("overflow-visible"), `not overflow-visible: ${root}`);
|
||||
// Header carries the sunken surface.
|
||||
const th = t.match(/&\s*th,\s*&\s*\.th\s*\{\s*@apply\s+([^;]+);/)?.[1] ?? "";
|
||||
assert.ok(th.includes("bg-surface-sunken"), `header not sunken: ${th}`);
|
||||
const thRules = [...t.matchAll(/&\s*th,\s*&\s*\.th\s*\{\s*@apply\s+([^;]+);/g)].map((m) => m[1]);
|
||||
const th = thRules.find((rule) => rule.includes("bg-surface-sunken")) ?? "";
|
||||
assert.ok(th, `header not sunken: ${thRules.join(" | ")}`);
|
||||
// Top corners round only on the table's first row; a second header row
|
||||
// (e.g. .cbi-section-table-descr) must stay square.
|
||||
assert.ok(!th.includes("rounded-t"), `generic header cells carry corner radius: ${th}`);
|
||||
const firstRow =
|
||||
t.match(/&:first-child\s*\{\s*&\s*th,\s*&\s*\.th\s*\{\s*@apply\s+([^;]+);/)?.[1] ?? "";
|
||||
assert.ok(
|
||||
firstRow.includes("first:rounded-tl-2xl") && firstRow.includes("last:rounded-tr-2xl"),
|
||||
`first-row corner radius missing: ${firstRow}`,
|
||||
);
|
||||
});
|
||||
@@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=Aurora Theme (A modern browser theme built with Vite and Tailwind CSS)
|
||||
LUCI_DEPENDS:=+luci-base
|
||||
|
||||
PKG_VERSION:=1.0.10
|
||||
PKG_RELEASE:=45
|
||||
PKG_VERSION:=1.0.13
|
||||
PKG_RELEASE:=46
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
LUCI_MINIFY_CSS:=
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
||||
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-tracking:initial}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-widest:.1em;--radius-sm:calc(var(--radius-base) * .25);--radius-md:calc(var(--radius-base) * .75);--radius-lg:var(--radius-base);--radius-xl:calc(var(--radius-base) * 1.5);--radius-2xl:calc(var(--radius-base) * 2);--radius-3xl:calc(var(--radius-base) * 3);--radius-4xl:calc(var(--radius-base) * 4);--shadow-sm:var(--app-shadow-sm);--shadow-md:var(--app-shadow-md);--shadow-lg:var(--app-shadow-md);--shadow-xl:var(--app-shadow-lg);--shadow-2xl:var(--app-shadow-lg);--animate-spin:spin 1s linear infinite;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:calc(var(--radius-base) * .5);--container-max-width:var(--container-max-width)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacinLine truncated
|
||||
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-tracking:initial}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-widest:.1em;--radius-sm:calc(var(--radius-base) * .25);--radius-md:calc(var(--radius-base) * .75);--radius-lg:var(--radius-base);--radius-xl:calc(var(--radius-base) * 1.5);--radius-2xl:calc(var(--radius-base) * 2);--radius-3xl:calc(var(--radius-base) * 3);--radius-4xl:calc(var(--radius-base) * 4);--shadow-sm:var(--app-shadow-sm);--shadow-md:var(--app-shadow-md);--shadow-lg:var(--app-shadow-md);--shadow-xl:var(--app-shadow-lg);--shadow-2xl:var(--app-shadow-lg);--animate-spin:spin 1s linear infinite;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:calc(var(--radius-base) * .5);--container-max-width:var(--container-max-width)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacinLine truncated
|
||||
@@ -1,2 +1,2 @@
|
||||
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
||||
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0;--tw-scrollbar-thumb:#0000;--tw-scrollbar-track:#0000;--tw-leading:initial;--tw-tracking:initial;--tw-ease:initial;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-border-spacing-x:0;--tw-border-spacing-y:0}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-xs:20rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:calc(var(--radius-base) * .25);--radius-md:calc(var(--radius-base) * .75);--radius-lg:var(--radius-base);--radius-xl:calc(var(--radius-base) * 1.5);--radius-2xl:calc(var(--radius-base) * 2);--radius-3xl:calc(var(--radius-base) * 3);--radius-4xl:calc(var(--radius-base) * 4);--shadow-sm:var(--app-shadow-sm);--shadow-md:var(--app-shadow-md);--shadow-lg:var(--app-shadow-md);--shadow-xl:var(--app-shadow-lg);--shadow-2xl:var(--app-shadow-lg);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:calc(var(--radius-base) * .5);--container-max-width:var(--container-max-width)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-familyLine truncated
|
||||
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0;--tw-scrollbar-thumb:#0000;--tw-scrollbar-track:#0000;--tw-leading:initial;--tw-tracking:initial;--tw-ease:initial;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-space-y-reverse:0;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-border-spacing-x:0;--tw-border-spacing-y:0}}}@layer theme{:root,:host{--font-sans:var(--font-sans);--font-mono:var(--font-mono);--spacing:var(--spacing);--container-xs:20rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:calc(var(--radius-base) * .25);--radius-md:calc(var(--radius-base) * .75);--radius-lg:var(--radius-base);--radius-xl:calc(var(--radius-base) * 1.5);--radius-2xl:calc(var(--radius-base) * 2);--radius-3xl:calc(var(--radius-base) * 3);--radius-4xl:calc(var(--radius-base) * 4);--shadow-sm:var(--app-shadow-sm);--shadow-md:var(--app-shadow-md);--shadow-lg:var(--app-shadow-md);--shadow-xl:var(--app-shadow-lg);--shadow-2xl:var(--app-shadow-lg);--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--blur-md:12px;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:calc(var(--radius-base) * .5);--container-max-width:var(--container-max-width)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-familyLine truncated
|
||||
+2
-2
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=torrserver
|
||||
PKG_VERSION:=MatriX.142
|
||||
PKG_RELEASE:=12
|
||||
PKG_RELEASE:=13
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/YouROK/TorrServer.git
|
||||
@@ -73,7 +73,7 @@ define Package/$(PKG_NAME)/description
|
||||
TorrServer is a tool for streaming torrent files.
|
||||
endef
|
||||
|
||||
GO_HOST:=$(STAGING_DIR_HOSTPKG)/bin/go
|
||||
GO_HOST=$(firstword $(wildcard $(STAGING_DIR_HOSTPKG)/bin/go) $(wildcard $(STAGING_DIR_HOSTPKG)/bin/go[0-9].[0-9][0-9]) $(STAGING_DIR_HOSTPKG)/bin/go)
|
||||
UPX:=$(STAGING_DIR_HOST)/bin/upx
|
||||
UPX_AVAILABLE:=$(shell [ -x "$(UPX)" ] && echo yes || echo no)
|
||||
TARGET_CC:=$(TARGET_CROSS)gcc
|
||||
|
||||
Reference in new issue
Block a user