mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-05 18:44:03 +08:00
🦄 Sync 2026-03-27 20:25:23
This commit is contained in:
1 parent
a0bc1c2110
commit
a1ca858747
9 files changed
+408
-25
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_VERSION:=0.1.6
|
PKG_VERSION:=0.1.7
|
||||||
PKG_RELEASE:=7
|
PKG_RELEASE:=8
|
||||||
|
|
||||||
LUCI_TITLE:=LuCI support for OpenClaw Launcher
|
LUCI_TITLE:=LuCI support for OpenClaw Launcher
|
||||||
LUCI_PKGARCH:=all
|
LUCI_PKGARCH:=all
|
||||||
|
|||||||
@@ -282,6 +282,19 @@
|
|||||||
filter: brightness(1.03);
|
filter: brightness(1.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.oclm-button-community {
|
||||||
|
background: linear-gradient(180deg, #8b5cf6, #7c3aed);
|
||||||
|
color: #fff;
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: 0 8px 18px rgba(124, 58, 237, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
.oclm-button-community:hover {
|
||||||
|
color: #fff;
|
||||||
|
filter: brightness(1.05);
|
||||||
|
box-shadow: 0 10px 22px rgba(124, 58, 237, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.oclm-button-danger {
|
.oclm-button-danger {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: linear-gradient(180deg, #ff5d6d, #ef4444);
|
background: linear-gradient(180deg, #ff5d6d, #ef4444);
|
||||||
|
|||||||
@@ -39,7 +39,16 @@
|
|||||||
lastTaskRunning: false,
|
lastTaskRunning: false,
|
||||||
taskLogOpenTs: 0,
|
taskLogOpenTs: 0,
|
||||||
consoleReady: false,
|
consoleReady: false,
|
||||||
consoleCheckTimer: null
|
consoleCheckTimer: null,
|
||||||
|
updateCheck: {
|
||||||
|
checking: false,
|
||||||
|
checked: false,
|
||||||
|
hasUpdate: false,
|
||||||
|
upgrading: false,
|
||||||
|
localVersion: "",
|
||||||
|
remoteVersion: "",
|
||||||
|
error: ""
|
||||||
|
}
|
||||||
};
|
};
|
||||||
var styleText = "";
|
var styleText = "";
|
||||||
|
|
||||||
@@ -127,7 +136,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function statusText(status) {
|
function statusText(status) {
|
||||||
if (status.installing) return "安装中";
|
if (status.installing) return status.task_op === "upgrade" ? "更新中" : "安装中";
|
||||||
if (!status || !status.installed) return "未安装";
|
if (!status || !status.installed) return "未安装";
|
||||||
if (status.running) return "运行中";
|
if (status.running) return "运行中";
|
||||||
if (status.reachable) return "运行中(未托管)";
|
if (status.reachable) return "运行中(未托管)";
|
||||||
@@ -164,6 +173,52 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUpdateCheck() {
|
||||||
|
state.updateCheck = state.updateCheck || {
|
||||||
|
checking: false,
|
||||||
|
checked: false,
|
||||||
|
hasUpdate: false,
|
||||||
|
upgrading: false,
|
||||||
|
localVersion: "",
|
||||||
|
remoteVersion: "",
|
||||||
|
error: ""
|
||||||
|
};
|
||||||
|
return state.updateCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateActionLabel(status) {
|
||||||
|
var updateCheck = getUpdateCheck();
|
||||||
|
if (updateCheck.upgrading || (status && status.installing && status.task_op === "upgrade")) return "更新中";
|
||||||
|
if (updateCheck.checking) return "检测中…";
|
||||||
|
if (updateCheck.hasUpdate) return "更新 OpenClaw";
|
||||||
|
return "检测更新";
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusNoteText(status) {
|
||||||
|
var updateCheck = getUpdateCheck();
|
||||||
|
if (status && status.installing) {
|
||||||
|
return status.task_op === "upgrade"
|
||||||
|
? "更新任务正在后台运行,可打开任务日志查看进度。"
|
||||||
|
: "安装任务正在后台运行,可打开任务日志查看进度。";
|
||||||
|
}
|
||||||
|
if (updateCheck.checking) {
|
||||||
|
return "正在检测远程版本,请稍候…";
|
||||||
|
}
|
||||||
|
if (updateCheck.upgrading) {
|
||||||
|
return "更新任务已提交,请稍候查看版本变化。";
|
||||||
|
}
|
||||||
|
if (updateCheck.error) {
|
||||||
|
return updateCheck.error;
|
||||||
|
}
|
||||||
|
if (updateCheck.checked && updateCheck.localVersion && updateCheck.remoteVersion) {
|
||||||
|
if (updateCheck.hasUpdate) {
|
||||||
|
return "发现新版本:本地 " + updateCheck.localVersion + ",远程 " + updateCheck.remoteVersion;
|
||||||
|
}
|
||||||
|
return "当前已是最新版:本地 " + updateCheck.localVersion + ",远程 " + updateCheck.remoteVersion;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
function copyIcon(className) {
|
function copyIcon(className) {
|
||||||
return '' +
|
return '' +
|
||||||
'<svg class="' + escapeAttr(className || "") + '" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +
|
'<svg class="' + escapeAttr(className || "") + '" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +
|
||||||
@@ -250,6 +305,14 @@
|
|||||||
'</svg>';
|
'</svg>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function communityIcon(className) {
|
||||||
|
return '' +
|
||||||
|
'<svg class="' + escapeAttr(className || "") + '" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +
|
||||||
|
'<path d="M8 10h8M8 14h5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"></path>' +
|
||||||
|
'<path d="M7 19l-3 2V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H7Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"></path>' +
|
||||||
|
'</svg>';
|
||||||
|
}
|
||||||
|
|
||||||
function taskWindowAvailable() {
|
function taskWindowAvailable() {
|
||||||
return !!(window.taskd && window.taskd.show_log);
|
return !!(window.taskd && window.taskd.show_log);
|
||||||
}
|
}
|
||||||
@@ -375,14 +438,17 @@
|
|||||||
'</div>';
|
'</div>';
|
||||||
}).join("");
|
}).join("");
|
||||||
|
|
||||||
var installLabel = status.installing ? "安装中" : "立即安装";
|
var updateCheck = getUpdateCheck();
|
||||||
|
var installLabel = status.installing ? (status.task_op === "upgrade" ? "更新中" : "安装中") : "立即安装";
|
||||||
var installAcceleratedChecked = form.install_accelerated == null ? true : form.install_accelerated === true;
|
var installAcceleratedChecked = form.install_accelerated == null ? true : form.install_accelerated === true;
|
||||||
var showInstallAction = !status.installed || status.installing;
|
var showInstallAction = !status.installed;
|
||||||
|
var showUpdateAction = status.installed && !status.installing;
|
||||||
var showServiceActions = status.installed && !status.installing;
|
var showServiceActions = status.installed && !status.installing;
|
||||||
var activeTab = state.activeTab || "basic";
|
var activeTab = state.activeTab || "basic";
|
||||||
var savingBasic = state.savingSection === "basic";
|
var savingBasic = state.savingSection === "basic";
|
||||||
var savingAi = state.savingSection === "ai";
|
var savingAi = state.savingSection === "ai";
|
||||||
var savingAccess = state.savingSection === "access";
|
var savingAccess = state.savingSection === "access";
|
||||||
|
var noteText = statusNoteText(status);
|
||||||
|
|
||||||
var canStartService = !status.running && !status.reachable;
|
var canStartService = !status.running && !status.reachable;
|
||||||
var canStopService = !!status.running;
|
var canStopService = !!status.running;
|
||||||
@@ -415,9 +481,11 @@
|
|||||||
'<label class="oclm-check"><input type="checkbox" id="oclm-install-accelerated"' + (installAcceleratedChecked ? ' checked' : '') + ' />Kspeeder 加速安装</label>' +
|
'<label class="oclm-check"><input type="checkbox" id="oclm-install-accelerated"' + (installAcceleratedChecked ? ' checked' : '') + ' />Kspeeder 加速安装</label>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<button id="oclm-open-console" class="oclm-button oclm-button-primary' + ((status.running || status.reachable) ? '' : ' oclm-hidden') + '" type="button" data-open-console="1"' + (state.consoleReady ? '' : ' disabled') + '>' + openclawIcon("oclm-button-icon") + (state.consoleReady ? '打开控制台' : '控制台准备中…') + '</button>' +
|
'<button id="oclm-open-console" class="oclm-button oclm-button-primary' + ((status.running || status.reachable) ? '' : ' oclm-hidden') + '" type="button" data-open-console="1"' + (state.consoleReady ? '' : ' disabled') + '>' + openclawIcon("oclm-button-icon") + (state.consoleReady ? '打开控制台' : '控制台准备中…') + '</button>' +
|
||||||
|
'<button id="oclm-update-btn" class="oclm-button oclm-button-primary' + (showUpdateAction ? '' : ' oclm-hidden') + '" type="button" data-update-action="1"' + ((updateCheck.checking || updateCheck.upgrading) ? ' disabled' : '') + '>' + updateActionLabel(status) + '</button>' +
|
||||||
|
'<a id="oclm-open-community" class="oclm-button oclm-button-community" href="https://www.koolcenter.com/t/topic/19042" target="_blank" rel="noreferrer noopener">' + communityIcon("oclm-button-icon") + '玩家交流</a>' +
|
||||||
'<button id="oclm-cancel-install" class="oclm-button oclm-button-danger' + (status.installing ? '' : ' oclm-hidden') + '" type="button" data-op="cancel_install">停止安装</button>' +
|
'<button id="oclm-cancel-install" class="oclm-button oclm-button-danger' + (status.installing ? '' : ' oclm-hidden') + '" type="button" data-op="cancel_install">停止安装</button>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div id="oclm-status-note" class="oclm-status-note' + (status.installing ? '' : ' oclm-hidden') + '">安装任务正在后台运行,点击“安装中”可继续查看日志。</div>' +
|
'<div id="oclm-status-note" class="oclm-status-note' + (noteText ? '' : ' oclm-hidden') + '">' + escapeHtml(noteText) + '</div>' +
|
||||||
'</section>' +
|
'</section>' +
|
||||||
|
|
||||||
'<section class="oclm-card">' +
|
'<section class="oclm-card">' +
|
||||||
@@ -555,19 +623,28 @@
|
|||||||
|
|
||||||
var installInline = byId("oclm-install-inline");
|
var installInline = byId("oclm-install-inline");
|
||||||
var installBtn = byId("oclm-install-btn");
|
var installBtn = byId("oclm-install-btn");
|
||||||
|
var updateBtn = byId("oclm-update-btn");
|
||||||
var cancelInstallBtn = byId("oclm-cancel-install");
|
var cancelInstallBtn = byId("oclm-cancel-install");
|
||||||
var openConsoleBtn = byId("oclm-open-console");
|
var openConsoleBtn = byId("oclm-open-console");
|
||||||
var noteEl = byId("oclm-status-note");
|
var noteEl = byId("oclm-status-note");
|
||||||
|
var updateCheck = getUpdateCheck();
|
||||||
|
|
||||||
var showInstallAction = !status.installed || status.installing;
|
var showInstallAction = !status.installed;
|
||||||
|
var showUpdateAction = !!(status.installed && !status.installing);
|
||||||
if (installInline) {
|
if (installInline) {
|
||||||
if (showInstallAction) installInline.classList.remove("oclm-hidden");
|
if (showInstallAction) installInline.classList.remove("oclm-hidden");
|
||||||
else installInline.classList.add("oclm-hidden");
|
else installInline.classList.add("oclm-hidden");
|
||||||
}
|
}
|
||||||
if (installBtn) {
|
if (installBtn) {
|
||||||
installBtn.textContent = status.installing ? "安装中" : "立即安装";
|
installBtn.textContent = status.installing ? (status.task_op === "upgrade" ? "更新中" : "安装中") : "立即安装";
|
||||||
installBtn.disabled = !!status.installing;
|
installBtn.disabled = !!status.installing;
|
||||||
}
|
}
|
||||||
|
if (updateBtn) {
|
||||||
|
updateBtn.textContent = updateActionLabel(status);
|
||||||
|
updateBtn.disabled = !!(updateCheck.checking || updateCheck.upgrading);
|
||||||
|
if (showUpdateAction) updateBtn.classList.remove("oclm-hidden");
|
||||||
|
else updateBtn.classList.add("oclm-hidden");
|
||||||
|
}
|
||||||
if (cancelInstallBtn) {
|
if (cancelInstallBtn) {
|
||||||
if (status.installing) cancelInstallBtn.classList.remove("oclm-hidden");
|
if (status.installing) cancelInstallBtn.classList.remove("oclm-hidden");
|
||||||
else cancelInstallBtn.classList.add("oclm-hidden");
|
else cancelInstallBtn.classList.add("oclm-hidden");
|
||||||
@@ -579,7 +656,9 @@
|
|||||||
openConsoleBtn.innerHTML = openclawIcon("oclm-button-icon") + (state.consoleReady ? "打开控制台" : "控制台准备中…");
|
openConsoleBtn.innerHTML = openclawIcon("oclm-button-icon") + (state.consoleReady ? "打开控制台" : "控制台准备中…");
|
||||||
}
|
}
|
||||||
if (noteEl) {
|
if (noteEl) {
|
||||||
if (status.installing) noteEl.classList.remove("oclm-hidden");
|
var noteText = statusNoteText(status);
|
||||||
|
noteEl.textContent = noteText;
|
||||||
|
if (noteText) noteEl.classList.remove("oclm-hidden");
|
||||||
else noteEl.classList.add("oclm-hidden");
|
else noteEl.classList.add("oclm-hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,6 +875,81 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Array.prototype.forEach.call(root.querySelectorAll("[data-update-action]"), function(el) {
|
||||||
|
el.onclick = function() {
|
||||||
|
var updateCheck = getUpdateCheck();
|
||||||
|
if (!state.status || !state.status.installed || state.status.installing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCheck.hasUpdate) {
|
||||||
|
updateCheck.upgrading = true;
|
||||||
|
updateCheck.error = "";
|
||||||
|
state.status.installing = true;
|
||||||
|
state.status.task_running = true;
|
||||||
|
state.status.task_op = "upgrade";
|
||||||
|
render();
|
||||||
|
postForm(config.opUrl, { op: "upgrade" }).then(function(rv) {
|
||||||
|
if (!rv || !rv.ok) {
|
||||||
|
updateCheck.upgrading = false;
|
||||||
|
state.status.installing = false;
|
||||||
|
state.status.task_running = false;
|
||||||
|
state.status.task_op = "";
|
||||||
|
render();
|
||||||
|
if (rv && rv.busy && rv.running_task_id) {
|
||||||
|
showTaskLog(rv.running_task_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.alert((rv && rv.error) || "启动更新失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.lastTaskRunning = true;
|
||||||
|
showTaskLog((rv && (rv.running_task_id || rv.task_id)) || "openclawmgr");
|
||||||
|
scheduleStatusRefresh(10, 1000);
|
||||||
|
}).catch(function() {
|
||||||
|
updateCheck.upgrading = false;
|
||||||
|
state.status.installing = false;
|
||||||
|
state.status.task_running = false;
|
||||||
|
state.status.task_op = "";
|
||||||
|
render();
|
||||||
|
window.alert("启动更新失败");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCheck.checking = true;
|
||||||
|
updateCheck.error = "";
|
||||||
|
render();
|
||||||
|
postForm(config.checkUpdateUrl, {}).then(function(rv) {
|
||||||
|
updateCheck.checking = false;
|
||||||
|
if (!rv || !rv.ok) {
|
||||||
|
updateCheck.checked = false;
|
||||||
|
updateCheck.hasUpdate = false;
|
||||||
|
updateCheck.error = (rv && rv.error) || "检测更新失败";
|
||||||
|
updateCheck.localVersion = String((rv && rv.local_version) || (state.status && state.status.openclaw_version) || "");
|
||||||
|
updateCheck.remoteVersion = String((rv && rv.remote_version) || "");
|
||||||
|
render();
|
||||||
|
window.alert(updateCheck.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateCheck.checked = true;
|
||||||
|
updateCheck.hasUpdate = !!rv.has_update;
|
||||||
|
updateCheck.upgrading = false;
|
||||||
|
updateCheck.error = "";
|
||||||
|
updateCheck.localVersion = String(rv.local_version || (state.status && state.status.openclaw_version) || "");
|
||||||
|
updateCheck.remoteVersion = String(rv.remote_version || "");
|
||||||
|
render();
|
||||||
|
}).catch(function() {
|
||||||
|
updateCheck.checking = false;
|
||||||
|
updateCheck.checked = false;
|
||||||
|
updateCheck.hasUpdate = false;
|
||||||
|
updateCheck.error = "检测更新失败";
|
||||||
|
render();
|
||||||
|
window.alert("检测更新失败");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
Array.prototype.forEach.call(root.querySelectorAll("[data-toggle-password]"), function(el) {
|
Array.prototype.forEach.call(root.querySelectorAll("[data-toggle-password]"), function(el) {
|
||||||
el.onclick = function() {
|
el.onclick = function() {
|
||||||
var id = el.getAttribute("data-toggle-password");
|
var id = el.getAttribute("data-toggle-password");
|
||||||
@@ -987,6 +1141,24 @@
|
|||||||
function refreshStatus(done) {
|
function refreshStatus(done) {
|
||||||
request(config.statusUrl).then(function(data) {
|
request(config.statusUrl).then(function(data) {
|
||||||
state.status = data || {};
|
state.status = data || {};
|
||||||
|
var updateCheck = getUpdateCheck();
|
||||||
|
if (state.status && state.status.openclaw_version) {
|
||||||
|
updateCheck.localVersion = String(state.status.openclaw_version || "");
|
||||||
|
}
|
||||||
|
if (!state.status || !state.status.installed) {
|
||||||
|
updateCheck.upgrading = false;
|
||||||
|
updateCheck.hasUpdate = false;
|
||||||
|
updateCheck.checked = false;
|
||||||
|
} else if (state.status.installing && state.status.task_op === "upgrade") {
|
||||||
|
updateCheck.upgrading = true;
|
||||||
|
} else if (!state.status.installing) {
|
||||||
|
updateCheck.upgrading = false;
|
||||||
|
if (updateCheck.remoteVersion && updateCheck.localVersion && updateCheck.remoteVersion === updateCheck.localVersion) {
|
||||||
|
updateCheck.hasUpdate = false;
|
||||||
|
updateCheck.checked = true;
|
||||||
|
updateCheck.error = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
if (state.status && (state.status.running || state.status.reachable)) {
|
if (state.status && (state.status.running || state.status.reachable)) {
|
||||||
if (!state.consoleReady) {
|
if (!state.consoleReady) {
|
||||||
pollConsoleReady(20);
|
pollConsoleReady(20);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ function index()
|
|||||||
entry({"admin", "services", "openclawmgr", "status"}, call("action_status")).leaf = true
|
entry({"admin", "services", "openclawmgr", "status"}, call("action_status")).leaf = true
|
||||||
entry({"admin", "services", "openclawmgr", "ready"}, call("action_ready")).leaf = true
|
entry({"admin", "services", "openclawmgr", "ready"}, call("action_ready")).leaf = true
|
||||||
entry({"admin", "services", "openclawmgr", "op"}, call("action_op")).leaf = true
|
entry({"admin", "services", "openclawmgr", "op"}, call("action_op")).leaf = true
|
||||||
|
entry({"admin", "services", "openclawmgr", "check_update"}, call("action_check_update")).leaf = true
|
||||||
entry({"admin", "services", "openclawmgr", "config_data"}, call("action_config_data")).leaf = true
|
entry({"admin", "services", "openclawmgr", "config_data"}, call("action_config_data")).leaf = true
|
||||||
entry({"admin", "services", "openclawmgr", "apply_config"}, call("action_apply_config")).leaf = true
|
entry({"admin", "services", "openclawmgr", "apply_config"}, call("action_apply_config")).leaf = true
|
||||||
|
|
||||||
@@ -157,6 +158,78 @@ local function safe_int(v, def, minv, maxv)
|
|||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function trim(v)
|
||||||
|
return tostring(v or ""):gsub("^%s+", ""):gsub("%s+$", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function split_dots(v)
|
||||||
|
local parts = {}
|
||||||
|
for part in tostring(v or ""):gmatch("[^%.]+") do
|
||||||
|
parts[#parts + 1] = part
|
||||||
|
end
|
||||||
|
return parts
|
||||||
|
end
|
||||||
|
|
||||||
|
local function semver_compare(a, b)
|
||||||
|
a = trim(a):gsub("^v", "")
|
||||||
|
b = trim(b):gsub("^v", "")
|
||||||
|
if a == "" or b == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local a_core, a_pre = a:match("^([^%-]+)%-?(.*)$")
|
||||||
|
local b_core, b_pre = b:match("^([^%-]+)%-?(.*)$")
|
||||||
|
local a_nums = split_dots(a_core)
|
||||||
|
local b_nums = split_dots(b_core)
|
||||||
|
local max_len = math.max(#a_nums, #b_nums)
|
||||||
|
|
||||||
|
for i = 1, max_len do
|
||||||
|
local av = tonumber(a_nums[i] or "0") or 0
|
||||||
|
local bv = tonumber(b_nums[i] or "0") or 0
|
||||||
|
if av ~= bv then
|
||||||
|
return av > bv and 1 or -1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
a_pre = trim(a_pre)
|
||||||
|
b_pre = trim(b_pre)
|
||||||
|
if a_pre == "" and b_pre == "" then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if a_pre == "" then
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
if b_pre == "" then
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
local a_ids = split_dots(a_pre)
|
||||||
|
local b_ids = split_dots(b_pre)
|
||||||
|
max_len = math.max(#a_ids, #b_ids)
|
||||||
|
for i = 1, max_len do
|
||||||
|
local ai = a_ids[i]
|
||||||
|
local bi = b_ids[i]
|
||||||
|
if ai == nil then return -1 end
|
||||||
|
if bi == nil then return 1 end
|
||||||
|
|
||||||
|
local an = tonumber(ai)
|
||||||
|
local bn = tonumber(bi)
|
||||||
|
if an and bn then
|
||||||
|
if an ~= bn then
|
||||||
|
return an > bn and 1 or -1
|
||||||
|
end
|
||||||
|
elseif an and not bn then
|
||||||
|
return -1
|
||||||
|
elseif not an and bn then
|
||||||
|
return 1
|
||||||
|
elseif ai ~= bi then
|
||||||
|
return ai > bi and 1 or -1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
local function require_csrf()
|
local function require_csrf()
|
||||||
local http = require "luci.http"
|
local http = require "luci.http"
|
||||||
local disp = require "luci.dispatcher"
|
local disp = require "luci.dispatcher"
|
||||||
@@ -494,6 +567,59 @@ function action_ready()
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function action_check_update()
|
||||||
|
local sys = require "luci.sys"
|
||||||
|
local uci = require "luci.model.uci".cursor()
|
||||||
|
|
||||||
|
if not require_csrf() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local base_dir = uci:get("openclawmgr", "main", "base_dir") or ""
|
||||||
|
if trim(base_dir) == "" then
|
||||||
|
write_json({ ok = false, error = "请先配置数据目录" })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local st = trim(sys.exec("/usr/libexec/istorec/openclawmgr.sh status 2>/dev/null"))
|
||||||
|
local installed = (st == "running" or st == "stopped")
|
||||||
|
if not installed then
|
||||||
|
write_json({ ok = false, error = "OpenClaw 尚未安装", installed = false })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local local_ver = trim(sys.exec("/usr/libexec/istorec/openclawmgr.sh local_openclaw_version 2>/dev/null"))
|
||||||
|
if local_ver == "" then
|
||||||
|
local_ver = trim(sys.exec("/usr/libexec/istorec/openclawmgr.sh openclaw_version 2>/dev/null"))
|
||||||
|
end
|
||||||
|
if local_ver == "" then
|
||||||
|
write_json({ ok = false, error = "获取本地版本失败", installed = true })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local remote_ver = trim(sys.exec("/usr/libexec/istorec/openclawmgr.sh latest_openclaw_version 2>/dev/null"))
|
||||||
|
if remote_ver == "" then
|
||||||
|
write_json({ ok = false, error = "获取远程版本失败", installed = true, local_version = local_ver })
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local cmp = semver_compare(remote_ver, local_ver)
|
||||||
|
local has_update = false
|
||||||
|
if cmp == nil then
|
||||||
|
has_update = remote_ver ~= local_ver
|
||||||
|
else
|
||||||
|
has_update = cmp > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
write_json({
|
||||||
|
ok = true,
|
||||||
|
installed = true,
|
||||||
|
local_version = local_ver,
|
||||||
|
remote_version = remote_ver,
|
||||||
|
has_update = has_update,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
function action_apply_config()
|
function action_apply_config()
|
||||||
local sys = require "luci.sys"
|
local sys = require "luci.sys"
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
statusUrl: "<%=url('admin/services/openclawmgr/status')%>",
|
statusUrl: "<%=url('admin/services/openclawmgr/status')%>",
|
||||||
readyUrl: "<%=url('admin/services/openclawmgr/ready')%>",
|
readyUrl: "<%=url('admin/services/openclawmgr/ready')%>",
|
||||||
opUrl: "<%=url('admin/services/openclawmgr/op')%>",
|
opUrl: "<%=url('admin/services/openclawmgr/op')%>",
|
||||||
|
checkUpdateUrl: "<%=url('admin/services/openclawmgr/check_update')%>",
|
||||||
configUrl: "<%=url('admin/services/openclawmgr/config_data')%>",
|
configUrl: "<%=url('admin/services/openclawmgr/config_data')%>",
|
||||||
applyUrl: "<%=url('admin/services/openclawmgr/apply_config')%>",
|
applyUrl: "<%=url('admin/services/openclawmgr/apply_config')%>",
|
||||||
staticBase: "<%=resource%>/openclawmgr"
|
staticBase: "<%=resource%>/openclawmgr"
|
||||||
|
|||||||
@@ -381,6 +381,31 @@ openclaw_version() {
|
|||||||
sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$pkg" 2>/dev/null | head -n 1
|
sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$pkg" 2>/dev/null | head -n 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_openclaw_version() {
|
||||||
|
[ -x "$NPM_BIN" ] || return 0
|
||||||
|
HOME="$DATA_DIR" npm_config_cache="${BASE_DIR}/npm-cache" \
|
||||||
|
PATH="${NODE_DIR}/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
|
||||||
|
"$NPM_BIN" list -g openclaw --prefix="$GLOBAL_DIR" --depth=0 --json 2>/dev/null \
|
||||||
|
| "$NODE_BIN" -e 'let s="";process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>{try{let o=JSON.parse(s||"{}");let v=o&&o.dependencies&&o.dependencies.openclaw&&o.dependencies.openclaw.version;if(v)process.stdout.write(String(v));}catch(_){}})'
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_openclaw_version() {
|
||||||
|
local npm_registry=""
|
||||||
|
[ -x "$NPM_BIN" ] || return 0
|
||||||
|
if [ "${INSTALL_ACCELERATED:-1}" = "1" ]; then
|
||||||
|
npm_registry="https://registry.npmmirror.com"
|
||||||
|
fi
|
||||||
|
if [ -n "$npm_registry" ]; then
|
||||||
|
HOME="$DATA_DIR" npm_config_cache="${BASE_DIR}/npm-cache" npm_config_registry="$npm_registry" \
|
||||||
|
PATH="${NODE_DIR}/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
|
||||||
|
"$NPM_BIN" view openclaw version 2>/dev/null | tr -d '\r' | head -n 1
|
||||||
|
else
|
||||||
|
HOME="$DATA_DIR" npm_config_cache="${BASE_DIR}/npm-cache" \
|
||||||
|
PATH="${NODE_DIR}/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
|
||||||
|
"$NPM_BIN" view openclaw version 2>/dev/null | tr -d '\r' | head -n 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
have_openclaw_runtime() {
|
have_openclaw_runtime() {
|
||||||
[ -x "$NODE_BIN" ] || return 1
|
[ -x "$NODE_BIN" ] || return 1
|
||||||
find_entry >/dev/null 2>&1 || return 1
|
find_entry >/dev/null 2>&1 || return 1
|
||||||
@@ -921,6 +946,47 @@ install_openclaw() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upgrade_openclaw() {
|
||||||
|
local was_running=0
|
||||||
|
local st=""
|
||||||
|
|
||||||
|
if ! have_openclaw_runtime; then
|
||||||
|
write_installer_log "OpenClaw is not installed yet; fallback to fresh install."
|
||||||
|
install_openclaw
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
st="$(do_status 2>/dev/null || true)"
|
||||||
|
if [ "$st" = "running" ]; then
|
||||||
|
was_running=1
|
||||||
|
write_installer_log "Stopping OpenClaw service before update"
|
||||||
|
/etc/init.d/openclawmgr stop >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_installer_log "Updating OpenClaw via npm"
|
||||||
|
write_installer_log "Current version: $(openclaw_version || echo unknown)"
|
||||||
|
if ! install_openclaw; then
|
||||||
|
write_installer_log "npm update failed"
|
||||||
|
if [ "$was_running" = "1" ] || [ "${ENABLED:-0}" = "1" ]; then
|
||||||
|
write_installer_log "Trying to restore service after failed update"
|
||||||
|
/etc/init.d/openclawmgr start >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ensure_gateway_config || true
|
||||||
|
fix_data_permissions || true
|
||||||
|
|
||||||
|
if [ "$was_running" = "1" ] || [ "${ENABLED:-0}" = "1" ]; then
|
||||||
|
ensure_safe_port_for_start || return 1
|
||||||
|
write_installer_log "Restarting OpenClaw service after update"
|
||||||
|
/etc/init.d/openclawmgr restart >/dev/null 2>&1 || /etc/init.d/openclawmgr start >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_installer_log "OpenClaw updated: $(openclaw_version || echo unknown)"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
do_install() {
|
do_install() {
|
||||||
acquire_lock
|
acquire_lock
|
||||||
write_installer_log "== install begin =="
|
write_installer_log "== install begin =="
|
||||||
@@ -938,6 +1004,11 @@ install_openclaw() {
|
|||||||
ensure_gateway_config || true
|
ensure_gateway_config || true
|
||||||
|
|
||||||
if have_openclaw_runtime; then
|
if have_openclaw_runtime; then
|
||||||
|
if [ "$ACTION" = "upgrade" ]; then
|
||||||
|
write_installer_log "OpenClaw is already installed: $(openclaw_version || echo unknown)"
|
||||||
|
upgrade_openclaw
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
write_installer_log "OpenClaw is already installed: $(openclaw_version || echo unknown)"
|
write_installer_log "OpenClaw is already installed: $(openclaw_version || echo unknown)"
|
||||||
write_installer_log "Skip install. Use restart/apply config if you only need to refresh configuration."
|
write_installer_log "Skip install. Use restart/apply config if you only need to refresh configuration."
|
||||||
return 0
|
return 0
|
||||||
@@ -1325,6 +1396,12 @@ case "$ACTION" in
|
|||||||
openclaw_version)
|
openclaw_version)
|
||||||
openclaw_version
|
openclaw_version
|
||||||
;;
|
;;
|
||||||
|
local_openclaw_version)
|
||||||
|
local_openclaw_version
|
||||||
|
;;
|
||||||
|
latest_openclaw_version)
|
||||||
|
latest_openclaw_version
|
||||||
|
;;
|
||||||
diag)
|
diag)
|
||||||
diag_run "${1:-}" "${2:-}"
|
diag_run "${1:-}" "${2:-}"
|
||||||
;;
|
;;
|
||||||
@@ -1332,7 +1409,7 @@ case "$ACTION" in
|
|||||||
diag_poll "${1:-}"
|
diag_poll "${1:-}"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $0 {install|upgrade|uninstall|uninstall_openclaw|purge|rm|start|stop|restart|status|port|token|node_version|openclaw_version|diag|diag_poll}" >&2
|
echo "Usage: $0 {install|upgrade|uninstall|uninstall_openclaw|purge|rm|start|stop|restart|status|port|token|node_version|openclaw_version|local_openclaw_version|latest_openclaw_version|diag|diag_poll}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -540,17 +540,11 @@ function copy_node()
|
|||||||
local uuid = api.gen_short_uuid()
|
local uuid = api.gen_short_uuid()
|
||||||
uci:section(appname, "nodes", uuid)
|
uci:section(appname, "nodes", uuid)
|
||||||
for k, v in pairs(uci:get_all(appname, section)) do
|
for k, v in pairs(uci:get_all(appname, section)) do
|
||||||
local filter = k:find("%.")
|
if not k:match("^%.") and k ~= "group" then
|
||||||
if filter and filter == 1 then
|
if k == "remarks" then v = (v or "") .. "(1)" end
|
||||||
else
|
uci:set(appname, uuid, k, v)
|
||||||
xpcall(function()
|
|
||||||
uci:set(appname, uuid, k, v)
|
|
||||||
end,
|
|
||||||
function(e)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
uci:delete(appname, uuid, "group")
|
|
||||||
uci:set(appname, uuid, "add_mode", 1)
|
uci:set(appname, uuid, "add_mode", 1)
|
||||||
api.uci_save(uci, appname)
|
api.uci_save(uci, appname)
|
||||||
http.redirect(api.url("node_config", uuid))
|
http.redirect(api.url("node_config", uuid))
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=mtproxy
|
PKG_NAME:=mtproxy
|
||||||
PKG_VERSION:=3.4.0
|
PKG_VERSION:=3.5.0
|
||||||
PKG_RELEASE:=9
|
PKG_RELEASE:=10
|
||||||
|
|
||||||
PKG_MAINTAINER:=Kosntantine Shevlakov <shevlakov@132lan.ru>
|
PKG_MAINTAINER:=Kosntantine Shevlakov <shevlakov@132lan.ru>
|
||||||
PKG_LICENSE:=GPLv2
|
PKG_LICENSE:=GPLv2
|
||||||
@@ -10,7 +10,7 @@ PKG_LICENSE_FILES:=LICENSE
|
|||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://github.com/GetPageSpeed/MTProxy.git
|
PKG_SOURCE_URL:=https://github.com/GetPageSpeed/MTProxy.git
|
||||||
PKG_SOURCE_VERSION:=dbd89354dc8ef9f9c624afb9686fd3a0bc93f26b
|
PKG_SOURCE_VERSION:=b18e84d21e8385e4df0e486fe45b0904947c5903
|
||||||
|
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=v2ray-plugin
|
PKG_NAME:=v2ray-plugin
|
||||||
PKG_VERSION:=5.46.0
|
PKG_VERSION:=5.48.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/teddysun/v2ray-plugin/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/teddysun/v2ray-plugin/tar.gz/v$(PKG_VERSION)?
|
||||||
|
|||||||
Reference in new issue
Block a user