mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-02 02:03:56 +08:00
🎁 Sync 2026-03-23 17:00:57
This commit is contained in:
1 parent
42786ced0b
commit
190ca87b14
42 files changed
+244
-2159
No files matched your search
@@ -1,8 +1,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=0.1.5
|
||||
PKG_RELEASE:=6
|
||||
PKG_VERSION:=0.1.6
|
||||
PKG_RELEASE:=7
|
||||
|
||||
LUCI_TITLE:=LuCI support for OpenClaw Launcher
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -130,12 +130,14 @@
|
||||
if (status.installing) return "安装中";
|
||||
if (!status || !status.installed) return "未安装";
|
||||
if (status.running) return "运行中";
|
||||
if (status.reachable) return "运行中(未托管)";
|
||||
return "已停止";
|
||||
}
|
||||
|
||||
function statusDotClass(status) {
|
||||
if (status && status.installing) return "";
|
||||
if (status && status.running) return "is-success";
|
||||
if (status && status.reachable) return "";
|
||||
return "is-danger";
|
||||
}
|
||||
|
||||
@@ -382,11 +384,8 @@
|
||||
var savingAi = state.savingSection === "ai";
|
||||
var savingAccess = state.savingSection === "access";
|
||||
|
||||
var serviceButtons = showServiceActions ? (
|
||||
(!status.running ? '<button class="oclm-button" type="button" data-op="start">启动服务</button>' : '') +
|
||||
(status.running ? '<button class="oclm-button" type="button" data-op="stop">停止服务</button>' : '') +
|
||||
'<button class="oclm-button" type="button" data-op="restart">重启服务</button>'
|
||||
) : '';
|
||||
var canStartService = !status.running && !status.reachable;
|
||||
var canStopService = !!status.running;
|
||||
|
||||
root.innerHTML =
|
||||
'<style>' + styleText + '</style>' +
|
||||
@@ -415,7 +414,7 @@
|
||||
'<button id="oclm-install-btn" class="oclm-button oclm-button-primary" type="button" data-install-action="1"' + (status.installing ? ' disabled' : '') + '>' + installLabel + '</button>' +
|
||||
'<label class="oclm-check"><input type="checkbox" id="oclm-install-accelerated"' + (installAcceleratedChecked ? ' checked' : '') + ' />Kspeeder 加速安装</label>' +
|
||||
'</div>' +
|
||||
'<button id="oclm-open-console" class="oclm-button oclm-button-primary' + (status.running ? '' : ' 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-cancel-install" class="oclm-button oclm-button-danger' + (status.installing ? '' : ' oclm-hidden') + '" type="button" data-op="cancel_install">停止安装</button>' +
|
||||
'</div>' +
|
||||
'<div id="oclm-status-note" class="oclm-status-note' + (status.installing ? '' : ' oclm-hidden') + '">安装任务正在后台运行,点击“安装中”可继续查看日志。</div>' +
|
||||
@@ -438,7 +437,15 @@
|
||||
["auto", "自动"]
|
||||
])) +
|
||||
fieldInput("数据目录", '<input class="oclm-control" type="text" id="oclm-base-dir" list="oclm-base-dir-options" value="' + escapeAttr(form.base_dir || "") + '" /><datalist id="oclm-base-dir-options">' + baseDirOptions + '</datalist>') +
|
||||
'<div class="oclm-section-submit"><button class="oclm-button oclm-button-primary" type="button" id="oclm-save-basic"' + (savingBasic ? ' disabled' : '') + '>' + (savingBasic ? '应用中…' : '保存并应用') + '</button>' + serviceButtons + (state.lastAppliedAt ? '<span class="oclm-applied-hint">已于 ' + escapeHtml(state.lastAppliedAt) + ' 更新配置</span>' : '') + '</div>' +
|
||||
'<div class="oclm-section-submit">' +
|
||||
'<button class="oclm-button oclm-button-primary" type="button" id="oclm-save-basic"' + (savingBasic ? ' disabled' : '') + '>' + (savingBasic ? '应用中…' : '保存并应用') + '</button>' +
|
||||
'<span id="oclm-service-actions" class="oclm-inline-buttons' + (showServiceActions ? '' : ' oclm-hidden') + '">' +
|
||||
'<button id="oclm-btn-start" class="oclm-button' + (canStartService ? '' : ' oclm-hidden') + '" type="button" data-op="start">启动服务</button>' +
|
||||
'<button id="oclm-btn-stop" class="oclm-button' + (canStopService ? '' : ' oclm-hidden') + '" type="button" data-op="stop">停止服务</button>' +
|
||||
'<button id="oclm-btn-restart" class="oclm-button" type="button" data-op="restart">重启服务</button>' +
|
||||
'</span>' +
|
||||
(state.lastAppliedAt ? '<span class="oclm-applied-hint">已于 ' + escapeHtml(state.lastAppliedAt) + ' 更新配置</span>' : '') +
|
||||
'</div>' +
|
||||
'</div></div>' +
|
||||
|
||||
'<div class="' + (activeTab === "ai" ? '' : 'oclm-hidden') + '">' +
|
||||
@@ -485,6 +492,7 @@
|
||||
|
||||
function updateStatusDom(status) {
|
||||
status = status || {};
|
||||
var gatewayActive = !!(status.running || status.reachable);
|
||||
|
||||
function byId(id) {
|
||||
if (root.getElementById) return root.getElementById(id);
|
||||
@@ -565,15 +573,40 @@
|
||||
else cancelInstallBtn.classList.add("oclm-hidden");
|
||||
}
|
||||
if (openConsoleBtn) {
|
||||
if (status.running) openConsoleBtn.classList.remove("oclm-hidden");
|
||||
if (gatewayActive) openConsoleBtn.classList.remove("oclm-hidden");
|
||||
else openConsoleBtn.classList.add("oclm-hidden");
|
||||
openConsoleBtn.disabled = !(status.running && state.consoleReady);
|
||||
openConsoleBtn.disabled = !state.consoleReady;
|
||||
openConsoleBtn.innerHTML = openclawIcon("oclm-button-icon") + (state.consoleReady ? "打开控制台" : "控制台准备中…");
|
||||
}
|
||||
if (noteEl) {
|
||||
if (status.installing) noteEl.classList.remove("oclm-hidden");
|
||||
else noteEl.classList.add("oclm-hidden");
|
||||
}
|
||||
|
||||
var svcWrap = byId("oclm-service-actions");
|
||||
var btnStart = byId("oclm-btn-start");
|
||||
var btnStop = byId("oclm-btn-stop");
|
||||
var btnRestart = byId("oclm-btn-restart");
|
||||
var showServiceActions = !!(status.installed && !status.installing);
|
||||
var canStartService = !!(!status.running && !status.reachable);
|
||||
var canStopService = !!status.running;
|
||||
|
||||
if (svcWrap) {
|
||||
if (showServiceActions) svcWrap.classList.remove("oclm-hidden");
|
||||
else svcWrap.classList.add("oclm-hidden");
|
||||
}
|
||||
if (btnStart) {
|
||||
if (showServiceActions && canStartService) btnStart.classList.remove("oclm-hidden");
|
||||
else btnStart.classList.add("oclm-hidden");
|
||||
}
|
||||
if (btnStop) {
|
||||
if (showServiceActions && canStopService) btnStop.classList.remove("oclm-hidden");
|
||||
else btnStop.classList.add("oclm-hidden");
|
||||
}
|
||||
if (btnRestart) {
|
||||
if (showServiceActions) btnRestart.classList.remove("oclm-hidden");
|
||||
else btnRestart.classList.add("oclm-hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function fieldInput(label, control) {
|
||||
@@ -954,7 +987,7 @@
|
||||
function refreshStatus(done) {
|
||||
request(config.statusUrl).then(function(data) {
|
||||
state.status = data || {};
|
||||
if (state.status && state.status.running) {
|
||||
if (state.status && (state.status.running || state.status.reachable)) {
|
||||
if (!state.consoleReady) {
|
||||
pollConsoleReady(20);
|
||||
}
|
||||
|
||||
@@ -353,6 +353,46 @@ local function get_pid_uptime_human(pid)
|
||||
return fmt_elapsed(elapsed)
|
||||
end
|
||||
|
||||
local function probe_gateway_ready(port, base_dir, bind)
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
|
||||
if not port or not tostring(port):match("^%d+$") then
|
||||
return false, "", ""
|
||||
end
|
||||
if not base_dir or base_dir == "" then
|
||||
return false, "", ""
|
||||
end
|
||||
|
||||
local base_path = configured_base_path(base_dir)
|
||||
local candidates = {}
|
||||
|
||||
if bind == "lan" or bind == "auto" then
|
||||
local ip = lan_ipv4()
|
||||
if ip ~= "" then
|
||||
candidates[#candidates + 1] = ip
|
||||
end
|
||||
end
|
||||
candidates[#candidates + 1] = "127.0.0.1"
|
||||
|
||||
local last_code, last_url = "", ""
|
||||
for _, host in ipairs(candidates) do
|
||||
local url = "http://" .. host .. ":" .. port .. base_path
|
||||
last_url = url
|
||||
local cmd = string.format(
|
||||
"curl -fsS -o /dev/null --connect-timeout 1 --max-time 2 -w '%%{http_code}' %s 2>/dev/null",
|
||||
util.shellquote(url)
|
||||
)
|
||||
local code = sys.exec(cmd):gsub("%s+$", "")
|
||||
last_code = code
|
||||
local n = tonumber(code) or 0
|
||||
if n >= 200 and n < 400 then
|
||||
return true, code, url
|
||||
end
|
||||
end
|
||||
return false, last_code, last_url
|
||||
end
|
||||
|
||||
function action_status()
|
||||
local sys = require "luci.sys"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
@@ -373,6 +413,11 @@ function action_status()
|
||||
running = (st == "running")
|
||||
installed = (st == "running" or st == "stopped")
|
||||
end
|
||||
|
||||
local reachable, reachable_code, reachable_url = false, "", ""
|
||||
if installed and not running then
|
||||
reachable, reachable_code, reachable_url = probe_gateway_ready(port, base_dir, bind)
|
||||
end
|
||||
local lock_running, lock_pid = installer_lock_running()
|
||||
local installing = (task.running and (task.op == "install" or task.op == "upgrade")) or lock_running
|
||||
if not installing and task.running and not installed and not running then
|
||||
@@ -405,6 +450,9 @@ function action_status()
|
||||
enabled = enabled,
|
||||
installed = installed,
|
||||
running = running,
|
||||
reachable = reachable,
|
||||
reachable_http_code = reachable_code,
|
||||
reachable_url = reachable_url,
|
||||
task_running = task.running,
|
||||
task_op = task.op,
|
||||
installing = installing,
|
||||
@@ -423,11 +471,10 @@ function action_status()
|
||||
end
|
||||
|
||||
function action_ready()
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
local port = uci:get("openclawmgr", "main", "port") or "18789"
|
||||
local bind = uci:get("openclawmgr", "main", "bind") or "lan"
|
||||
local base_dir = uci:get("openclawmgr", "main", "base_dir") or ""
|
||||
|
||||
if not port:match("^%d+$") then port = "18789" end
|
||||
@@ -437,20 +484,13 @@ function action_ready()
|
||||
return
|
||||
end
|
||||
|
||||
local base_url = "http://127.0.0.1:" .. port .. configured_base_path(base_dir)
|
||||
local cmd = string.format(
|
||||
"curl -fsS -o /dev/null --connect-timeout 1 --max-time 2 -w '%%{http_code}' %s 2>/dev/null",
|
||||
util.shellquote(base_url)
|
||||
)
|
||||
local code = sys.exec(cmd):gsub("%s+$", "")
|
||||
local n = tonumber(code) or 0
|
||||
local ready = (n >= 200 and n < 400)
|
||||
local ready, code, url = probe_gateway_ready(port, base_dir, bind)
|
||||
|
||||
write_json({
|
||||
ok = true,
|
||||
ready = ready,
|
||||
http_code = code,
|
||||
url = base_url,
|
||||
url = url,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
@@ -559,15 +559,14 @@ if selected_env_key and selected_api_key ~= "" then
|
||||
end
|
||||
cfg.env = next(env) and env or nil
|
||||
|
||||
local models = {}
|
||||
models.mode = "merge"
|
||||
local providers = {}
|
||||
models.providers = providers
|
||||
cfg.models = models
|
||||
local models = ensure_table(cfg, "models")
|
||||
if type(models.mode) ~= "string" or models.mode == "" then
|
||||
models.mode = "merge"
|
||||
end
|
||||
local providers = ensure_table(models, "providers")
|
||||
|
||||
local current_provider_id = os.getenv("DEFAULT_AGENT_NAME") or "anthropic"
|
||||
local current_provider = {}
|
||||
providers[current_provider_id] = current_provider
|
||||
local current_provider_id = os.getenv("DEFAULT_AGENT_NAME") or "anthropic"
|
||||
local current_provider = ensure_table(providers, current_provider_id)
|
||||
|
||||
if current_provider_id == "openai" then
|
||||
current_provider.api = "openai-completions"
|
||||
@@ -600,13 +599,30 @@ elseif current_provider_id == "moonshot" then
|
||||
}
|
||||
end
|
||||
|
||||
local override_base = os.getenv("DEFAULT_AGENT_OVERRIDE_BASE_URL") or ""
|
||||
local base_url_mode = os.getenv("DEFAULT_AGENT_BASE_URL_MODE") or "default"
|
||||
if base_url_mode == "override" and override_base ~= "" then
|
||||
current_provider.baseUrl = override_base
|
||||
elseif base_url_mode == "default" then
|
||||
current_provider.baseUrl = os.getenv("DEFAULT_AGENT_BASE_URL") or current_provider.baseUrl
|
||||
end
|
||||
local override_base = os.getenv("DEFAULT_AGENT_OVERRIDE_BASE_URL") or ""
|
||||
local base_url_mode = os.getenv("DEFAULT_AGENT_BASE_URL_MODE") or "default"
|
||||
if base_url_mode == "override" and override_base ~= "" then
|
||||
current_provider.baseUrl = override_base
|
||||
elseif base_url_mode == "default" then
|
||||
current_provider.baseUrl = os.getenv("DEFAULT_AGENT_BASE_URL") or current_provider.baseUrl
|
||||
end
|
||||
|
||||
-- luci.jsonc encodes empty Lua tables as JSON arrays ([]). To avoid producing
|
||||
-- invalid provider entries like {"deepseek/deepseek-chat":[]}, drop provider
|
||||
-- records that are empty or look like a provider/model string.
|
||||
do
|
||||
local to_del = {}
|
||||
for k, v in pairs(providers) do
|
||||
if type(k) == "string" and k:find("/", 1, true) then
|
||||
table.insert(to_del, k)
|
||||
elseif type(v) == "table" and next(v) == nil then
|
||||
table.insert(to_del, k)
|
||||
end
|
||||
end
|
||||
for _, k in ipairs(to_del) do
|
||||
providers[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local agents = ensure_table(cfg, "agents")
|
||||
local defaults = ensure_table(agents, "defaults")
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Backward-compatible wrapper. New entry: openclawmgr-cli.sh
|
||||
|
||||
set -eu
|
||||
|
||||
exec /usr/share/openclawmgr/openclawmgr-cli.sh "$@"
|
||||
Reference in new issue
Block a user