mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-27 02:52:51 +08:00
🍓 Sync 2026-09-24 18:14:57
This commit is contained in:
1 parent
7f9547bc12
commit
7be562c4ff
11 files changed
+285
-19
No files matched your search
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=AgentFlow
|
||||
PKG_VERSION:=1.0.1
|
||||
PKG_RELEASE:=8
|
||||
PKG_RELEASE:=9
|
||||
LUCI_DEPENDS:=+agentflow +luci-compat +luci-lib-taskd +luci-lib-linkeaseauth +linkease-app-entry
|
||||
LUCI_MINIFY_CSS:=0
|
||||
LUCI_MINIFY_JS:=0
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
local http = require "luci.http"
|
||||
|
||||
module("luci.controller.agentflow", package.seeall)
|
||||
|
||||
local AGENTS = {
|
||||
{ id = "codexcli", package = "@openai/codex", command = "codex" },
|
||||
{ id = "claude-code", package = "@anthropic-ai/claude-code", command = "claude" },
|
||||
{ id = "opencode", package = "opencode-ai", command = "opencode" },
|
||||
{ id = "kimi", package = "@moonshot-ai/kimi-code", command = "kimi" },
|
||||
{ id = "reasonix", package = "reasonix", command = "reasonix" }
|
||||
}
|
||||
|
||||
function index()
|
||||
entry({"admin", "services", "agentflow_status"}, call("agentflow_status"))
|
||||
local open = entry({"admin", "services", "agentflow", "open"}, call("agentflow_open"))
|
||||
@@ -8,28 +18,241 @@ function index()
|
||||
open.sysauth = false
|
||||
|
||||
if not nixio.fs.access("/etc/config/agentflow") then return end
|
||||
|
||||
local install = entry({"admin", "services", "agentflow", "agent_install"}, call("agentflow_agent_install"))
|
||||
install.leaf = true
|
||||
|
||||
entry({"admin", "services", "agentflow"}, cbi("agentflow"), _("AgentFlow"), 100).dependent = true
|
||||
end
|
||||
|
||||
local function write_json(obj)
|
||||
http.prepare_content("application/json")
|
||||
http.write_json(obj)
|
||||
end
|
||||
|
||||
local function require_post_csrf()
|
||||
local dispatcher = require "luci.dispatcher"
|
||||
local context = dispatcher.context or {}
|
||||
local expected = context.authtoken or context.token
|
||||
|
||||
if (http.getenv("REQUEST_METHOD") or "") ~= "POST" then
|
||||
http.status(405, "Method Not Allowed")
|
||||
write_json({ ok = false, error = "method not allowed" })
|
||||
return false
|
||||
end
|
||||
|
||||
if not context.authsession or not expected or http.formvalue("token") ~= expected then
|
||||
http.status(403, "Forbidden")
|
||||
write_json({ ok = false, error = "invalid csrf token" })
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function compat()
|
||||
local dispatcher = require "luci.dispatcher"
|
||||
return require("luci.model.linkease.apps_compat").new({
|
||||
http = require "luci.http",
|
||||
http = http,
|
||||
resolver = require("luci.model.linkease.apps_openwrt").new(),
|
||||
auth_url = dispatcher.build_url("admin", "services", "linkease_auth", "auth")
|
||||
})
|
||||
end
|
||||
|
||||
local function node_modules_root()
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
local script = table.concat({
|
||||
'. /lib/functions/mise.sh 2>/dev/null || exit 1',
|
||||
'istore_runtime_env >/dev/null 2>&1 || exit 1',
|
||||
'mise_bin="$(command -v mise-istore || command -v mise)"',
|
||||
'[ -n "$mise_bin" ] || exit 1',
|
||||
'node_dir="$("$mise_bin" where node@lts 2>/dev/null)"',
|
||||
'[ -n "$node_dir" ] || exit 1',
|
||||
'printf "%s/lib/node_modules" "$node_dir"'
|
||||
}, "; ")
|
||||
local root = sys.exec("/bin/sh -c " .. util.shellquote(script)) or ""
|
||||
root = root:match("^%s*(.-)%s*$")
|
||||
if root == "" or root:sub(1, 1) ~= "/" then
|
||||
return nil
|
||||
end
|
||||
return root
|
||||
end
|
||||
|
||||
local function agent_commands_ready()
|
||||
local sys = require "luci.sys"
|
||||
local script = {
|
||||
'. /lib/functions/mise.sh 2>/dev/null || exit 1',
|
||||
'istore_runtime_env >/dev/null 2>&1 || exit 1',
|
||||
'probe_prefix="/tmp/agentflow-agent-probe.$$"',
|
||||
'cleanup_agentflow_probe() { rm -f "$probe_prefix".*; }',
|
||||
'trap cleanup_agentflow_probe 0 HUP INT TERM',
|
||||
'check_agent_version() {',
|
||||
'\tshim="$1"',
|
||||
'\toutput="$2"',
|
||||
'\t"$shim" --version >"$output" 2>/dev/null &',
|
||||
'\tchild_pid=$!',
|
||||
'\t(',
|
||||
'\t\ttimer_pid=""',
|
||||
'\t\tstop_timer() {',
|
||||
'\t\t\t[ -z "$timer_pid" ] || kill "$timer_pid" 2>/dev/null',
|
||||
'\t\t\texit 0',
|
||||
'\t\t}',
|
||||
'\t\ttrap stop_timer TERM INT',
|
||||
'\t\tsleep 5 &',
|
||||
'\t\ttimer_pid=$!',
|
||||
'\t\twait "$timer_pid" 2>/dev/null || exit 0',
|
||||
'\t\tkill "$child_pid" 2>/dev/null',
|
||||
'\t) &',
|
||||
'\twatchdog_pid=$!',
|
||||
'\twait "$child_pid"',
|
||||
'\trc=$?',
|
||||
'\tkill "$watchdog_pid" 2>/dev/null',
|
||||
'\twait "$watchdog_pid" 2>/dev/null',
|
||||
'\t[ "$rc" -eq 0 ] && [ -s "$output" ]',
|
||||
'}'
|
||||
}
|
||||
|
||||
for _, agent in ipairs(AGENTS) do
|
||||
script[#script + 1] = 'shim="$HOME/.local/share/mise/shims/' .. agent.command .. '"'
|
||||
script[#script + 1] = 'if [ -x "$shim" ] && check_agent_version "$shim" "$probe_prefix.' .. agent.id .. '"; then printf "ready:%s\\n" "' .. agent.id .. '"; fi'
|
||||
end
|
||||
|
||||
local output = sys.exec(table.concat(script, "\n")) or ""
|
||||
local ready = {}
|
||||
for id in output:gmatch("ready:([%w%-]+)") do
|
||||
ready[id] = true
|
||||
end
|
||||
return ready
|
||||
end
|
||||
|
||||
local function agent_statuses()
|
||||
local fs = require "nixio.fs"
|
||||
local jsonc = require "luci.jsonc"
|
||||
local root = node_modules_root()
|
||||
local command_ready = root and agent_commands_ready() or {}
|
||||
local statuses = {}
|
||||
|
||||
for _, agent in ipairs(AGENTS) do
|
||||
local status = { id = agent.id, installed = false }
|
||||
if root then
|
||||
local package_file = root .. "/" .. agent.package .. "/package.json"
|
||||
local package_data = fs.readfile(package_file)
|
||||
local package_json = package_data and jsonc.parse(package_data) or nil
|
||||
local package_valid = type(package_json) == "table"
|
||||
and type(package_json.version) == "string"
|
||||
and package_json.version ~= ""
|
||||
if package_valid and command_ready[agent.id] == true then
|
||||
status.installed = true
|
||||
status.version = package_json.version
|
||||
end
|
||||
end
|
||||
statuses[#statuses + 1] = status
|
||||
end
|
||||
|
||||
return statuses, root ~= nil
|
||||
end
|
||||
|
||||
function agentflow_status()
|
||||
local sys = require "luci.sys"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local agents, agents_available = agent_statuses()
|
||||
compat():legacy_status("agentflow", {
|
||||
running = sys.call("pidof agentflow >/dev/null") == 0,
|
||||
port = uci:get_first("agentflow", "agentflow", "port") or "9000",
|
||||
base_path = uci:get_first("agentflow", "agentflow", "base_path") or "/apps/agentflow/"
|
||||
base_path = uci:get_first("agentflow", "agentflow", "base_path") or "/apps/agentflow/",
|
||||
agents_available = agents_available,
|
||||
agents = agents
|
||||
})
|
||||
end
|
||||
|
||||
function agentflow_agent_install()
|
||||
local fs = require "nixio.fs"
|
||||
local jsonc = require "luci.jsonc"
|
||||
local sys = require "luci.sys"
|
||||
local util = require "luci.util"
|
||||
local task_id = "agentflow-agent-install"
|
||||
local task_script = "/tmp/agentflow-agent-install.sh"
|
||||
local installer_url = "https://fw.koolcenter.com/binary/geili/agentflow/releases/installapp/installapp-mise.sh"
|
||||
local supported_agents = {}
|
||||
for _, supported_agent in ipairs(AGENTS) do
|
||||
supported_agents[supported_agent.id] = true
|
||||
end
|
||||
|
||||
if not require_post_csrf() then
|
||||
return
|
||||
end
|
||||
|
||||
local agent = http.formvalue("agent") or ""
|
||||
if not supported_agents[agent] then
|
||||
write_json({ ok = false, error = "unsupported agent" })
|
||||
return
|
||||
end
|
||||
if not fs.access("/etc/init.d/tasks") then
|
||||
write_json({ ok = false, error = "taskd is not available" })
|
||||
return
|
||||
end
|
||||
if not fs.access("/lib/functions/mise.sh") then
|
||||
write_json({ ok = false, error = "mise environment helper is not available" })
|
||||
return
|
||||
end
|
||||
|
||||
local task_status = sys.exec("/etc/init.d/tasks task_status " .. task_id .. " 2>/dev/null")
|
||||
local status = jsonc.parse(task_status) or {}
|
||||
local running = type(status) == "table" and status.running
|
||||
if running == true or running == 1 or running == "1" or running == "true" then
|
||||
write_json({ ok = true, busy = true, task_id = task_id })
|
||||
return
|
||||
end
|
||||
|
||||
local install_script = table.concat({
|
||||
"set -e",
|
||||
"agent=" .. util.shellquote(agent),
|
||||
"installer_url=" .. util.shellquote(installer_url),
|
||||
'installer="/tmp/agentflow-installapp-mise.$$"',
|
||||
'cleanup() { rm -f "$installer" "$0"; }',
|
||||
"trap cleanup 0 HUP INT TERM",
|
||||
'. /lib/functions/mise.sh',
|
||||
'if ! istore_runtime_env; then echo "[agentflow] Failed to initialize the shared runtime environment" >&2; exit 1; fi',
|
||||
"set -u",
|
||||
"export MISE_YES=1",
|
||||
'echo "[agentflow] Downloading installer: $installer_url"',
|
||||
'if command -v wget >/dev/null 2>&1; then',
|
||||
'\twget -O "$installer" "$installer_url"',
|
||||
'elif command -v curl >/dev/null 2>&1; then',
|
||||
'\tcurl -fL -o "$installer" "$installer_url"',
|
||||
'elif command -v uclient-fetch >/dev/null 2>&1; then',
|
||||
'\tuclient-fetch -O "$installer" "$installer_url"',
|
||||
"else",
|
||||
'\techo "[agentflow] No HTTPS download tool is available" >&2',
|
||||
"\texit 1",
|
||||
"fi",
|
||||
'if [ ! -s "$installer" ]; then echo "[agentflow] Failed to download the agent installer" >&2; exit 1; fi',
|
||||
'chmod 0700 "$installer"',
|
||||
'echo "[agentflow] Running installapp-mise.sh for $agent in $HOME"',
|
||||
'/bin/sh "$installer" "$agent"'
|
||||
}, "\n")
|
||||
if not fs.writefile(task_script, install_script .. "\n") then
|
||||
write_json({ ok = false, error = "failed to create install task", task_id = task_id })
|
||||
return
|
||||
end
|
||||
if sys.call("chmod 0600 " .. util.shellquote(task_script)) ~= 0 then
|
||||
fs.unlink(task_script)
|
||||
write_json({ ok = false, error = "failed to secure install task", task_id = task_id })
|
||||
return
|
||||
end
|
||||
|
||||
local command = "/bin/sh " .. util.shellquote(task_script)
|
||||
local rc = sys.call("/etc/init.d/tasks task_add " .. task_id .. " " .. util.shellquote(command) .. " >/dev/null 2>&1")
|
||||
if rc ~= 0 then
|
||||
fs.unlink(task_script)
|
||||
write_json({ ok = false, error = "failed to start install task", task_id = task_id })
|
||||
return
|
||||
end
|
||||
|
||||
write_json({ ok = true, task_id = task_id })
|
||||
end
|
||||
|
||||
function agentflow_open()
|
||||
compat():open("agentflow")
|
||||
end
|
||||
@@ -61,6 +61,32 @@ class AgentInstallContractTest(unittest.TestCase):
|
||||
self.assertIn('installButton.disabled = !available || installed', status)
|
||||
self.assertIn('installed ? agentflowLabels.installed : agentflowLabels.install', status)
|
||||
|
||||
def test_status_requires_valid_package_and_healthy_mise_shim(self):
|
||||
controller = self.read("luasrc/controller/agentflow.lua")
|
||||
|
||||
for agent_id, package, command in (
|
||||
("codexcli", "@openai/codex", "codex"),
|
||||
("claude-code", "@anthropic-ai/claude-code", "claude"),
|
||||
("opencode", "opencode-ai", "opencode"),
|
||||
("kimi", "@moonshot-ai/kimi-code", "kimi"),
|
||||
("reasonix", "reasonix", "reasonix"),
|
||||
):
|
||||
self.assertIn(
|
||||
f'{{ id = "{agent_id}", package = "{package}", command = "{command}" }}',
|
||||
controller,
|
||||
)
|
||||
self.assertIn('probe_prefix="/tmp/agentflow-agent-probe.$$"', controller)
|
||||
self.assertIn('[ -x "$shim" ]', controller)
|
||||
self.assertIn('"$shim" --version', controller)
|
||||
self.assertIn('sleep 5', controller)
|
||||
self.assertIn('kill "$child_pid"', controller)
|
||||
self.assertIn('type(package_json.version) == "string"', controller)
|
||||
self.assertIn('package_json.version ~= ""', controller)
|
||||
self.assertIn('command_ready[agent.id] == true', controller)
|
||||
self.assertIn(
|
||||
'if package_valid and command_ready[agent.id] == true then', controller
|
||||
)
|
||||
|
||||
def test_modal_theme_prefers_body_attribute_then_system_theme(self):
|
||||
status = self.read("luasrc/view/agentflow/status.htm")
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import unittest
|
||||
|
||||
|
||||
APP_DIR = Path(__file__).resolve().parents[1]
|
||||
META_MAKEFILE = APP_DIR.parent / "app-meta-agentflow/Makefile"
|
||||
|
||||
|
||||
class AgentFlowLuciOpenContractTest(unittest.TestCase):
|
||||
@@ -13,9 +14,12 @@ class AgentFlowLuciOpenContractTest(unittest.TestCase):
|
||||
makefile = self.read("Makefile")
|
||||
controller = self.read("luasrc/controller/agentflow.lua")
|
||||
status = self.read("luasrc/view/agentflow/status.htm")
|
||||
meta = META_MAKEFILE.read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("+luci-lib-linkeaseauth", makefile)
|
||||
self.assertIn("+linkease-app-entry", makefile)
|
||||
self.assertIn("PKG_RELEASE:=3", meta)
|
||||
self.assertIn("META_LUCI_ENTRY:=/cgi-bin/luci/admin/services/agentflow", meta)
|
||||
self.assertIn('entry({"admin", "services", "agentflow", "open"}', controller)
|
||||
self.assertIn("open.sysauth = false", controller)
|
||||
self.assertIn("function agentflow_open()", controller)
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.9.16
|
||||
PKG_RELEASE:=288
|
||||
PKG_RELEASE:=289
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -528,7 +528,7 @@ o.default = 0
|
||||
o.rmempty = false
|
||||
o:depends({ _acl_node_bool = "1", _diff_global_node = "1" })
|
||||
|
||||
o = s:taboption("Log", ListValue, "loglevel", "Sing-Box/Xray " .. translate("Log Level"))
|
||||
o = s:taboption("Log", ListValue, "loglevel", translate("Log Level"))
|
||||
o.default = "warn"
|
||||
o:value("debug", "Debug")
|
||||
o:value("info", "Info")
|
||||
|
||||
@@ -645,7 +645,7 @@ o = s:taboption("log", Flag, "log_node", translate("Enable Node Log"))
|
||||
o.default = "0"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("log", ListValue, "loglevel", "Sing-Box/Xray " .. translate("Log Level"))
|
||||
o = s:taboption("log", ListValue, "loglevel", translate("Log Level"))
|
||||
o.default = "warn"
|
||||
o:value("debug", "Debug")
|
||||
o:value("info", "Info")
|
||||
|
||||
@@ -55,6 +55,7 @@ function gen_config(var)
|
||||
local local_http_password = var["local_http_password"]
|
||||
local local_redir_port = var["local_redir_port"]
|
||||
local local_redir_address = var["local_redir_address"] or "0.0.0.0"
|
||||
local loglevel = var["loglevel"]
|
||||
|
||||
if api.is_ipv6(server_host) then
|
||||
server_host = api.get_ipv6_only(server_host)
|
||||
@@ -100,7 +101,10 @@ function gen_config(var)
|
||||
}
|
||||
},
|
||||
locals = {},
|
||||
fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false
|
||||
fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false,
|
||||
log = {
|
||||
level = (loglevel == "debug") and 1 or 0
|
||||
}
|
||||
}
|
||||
if local_socks_address and local_socks_port then
|
||||
table.insert(config.locals, {
|
||||
|
||||
@@ -94,7 +94,7 @@ run_singbox() {
|
||||
[ "$type" != "sing-box" ] && [ -n "$SINGBOX_BIN" ] && type="sing-box"
|
||||
}
|
||||
[ -z "$type" ] && return 1
|
||||
[ -n "$log_file" ] || local log_file="/dev/null"
|
||||
[ -n "$log_file" ] || log_file="/dev/null"
|
||||
json_init
|
||||
if [ "$log_file" = "/dev/null" ]; then
|
||||
json_add_string "log" "0"
|
||||
@@ -102,7 +102,7 @@ run_singbox() {
|
||||
json_add_string "log" "1"
|
||||
json_add_string "logfile" "${log_file}"
|
||||
fi
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
[ -z "$loglevel" ] && loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
json_add_string "loglevel" "$loglevel"
|
||||
|
||||
[ -n "$flag" ] && json_add_string "flag" "$flag"
|
||||
@@ -213,8 +213,8 @@ run_xray() {
|
||||
}
|
||||
[ -z "$type" ] && return 1
|
||||
json_init
|
||||
[ -n "$log_file" ] || local log_file="/dev/null"
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warning")
|
||||
[ -n "$log_file" ] || log_file="/dev/null"
|
||||
[ -z "$loglevel" ] && loglevel=$(config_n_get @global[0] loglevel "warning")
|
||||
[ -n "$flag" ] && json_add_string "flag" "$flag"
|
||||
[ -n "$node" ] && json_add_string "node" "$node"
|
||||
[ -n "$use_proxy_list" ] && json_add_string "use_proxy_list" "$use_proxy_list"
|
||||
@@ -340,7 +340,7 @@ run_chinadns_ng() {
|
||||
}
|
||||
|
||||
run_socks() {
|
||||
local flag node bind socks_port config_file http_port http_config_file relay_port log_file no_run
|
||||
local flag node bind socks_port config_file http_port http_config_file relay_port log_file no_run loglevel
|
||||
eval_set_val "$@"
|
||||
[ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=$TMP_PATH/$config_file
|
||||
[ -n "$http_port" ] || http_port=0
|
||||
@@ -350,6 +350,7 @@ run_socks() {
|
||||
elif [ "${log_file#"$TMP_PATH/"}" = "$log_file" ]; then
|
||||
log_file=$TMP_PATH/$log_file
|
||||
fi
|
||||
loglevel=${loglevel:-warn}
|
||||
|
||||
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
|
||||
local remarks=$(config_n_get $node remarks)
|
||||
@@ -442,7 +443,7 @@ run_socks() {
|
||||
}
|
||||
[ -n "$relay_port" ] && _args="${_args} server_host=$server_host server_port=$server_port"
|
||||
[ -n "$no_run" ] && _args="${_args} no_run=1"
|
||||
run_singbox flag=$flag node=$node socks_address=$bind socks_port=$socks_port config_file=$config_file log_file=$log_file ${_args}
|
||||
run_singbox flag=$flag node=$node socks_address=$bind socks_port=$socks_port config_file=$config_file log_file=$log_file loglevel=$loglevel ${_args}
|
||||
;;
|
||||
xray)
|
||||
[ "$http_port" != "0" ] && {
|
||||
@@ -452,7 +453,7 @@ run_socks() {
|
||||
}
|
||||
[ -n "$relay_port" ] && _args="${_args} server_host=$server_host server_port=$server_port"
|
||||
[ -n "$no_run" ] && _args="${_args} no_run=1"
|
||||
run_xray flag=$flag node=$node socks_address=$bind socks_port=$socks_port config_file=$config_file log_file=$log_file ${_args}
|
||||
run_xray flag=$flag node=$node socks_address=$bind socks_port=$socks_port config_file=$config_file log_file=$log_file loglevel=$loglevel ${_args}
|
||||
;;
|
||||
naiveproxy)
|
||||
json_add_string "run_type" "socks"
|
||||
@@ -480,6 +481,7 @@ run_socks() {
|
||||
}
|
||||
json_add_string "local_socks_address" "$bind"
|
||||
json_add_string "local_socks_port" "$socks_port"
|
||||
json_add_string "loglevel" "$loglevel"
|
||||
lua $UTIL_SS gen_config "$(json_dump)" > $config_file
|
||||
[ -n "$no_run" ] || ln_run "$(first_type sslocal)" "sslocal" $log_file -c "$config_file" -v
|
||||
;;
|
||||
@@ -493,7 +495,10 @@ run_socks() {
|
||||
json_add_string "local_socks_address" "$bind"
|
||||
json_add_string "local_socks_port" "$socks_port"
|
||||
lua $UTIL_HYSTERIA2 gen_config "$(json_dump)" > $config_file
|
||||
[ -n "$no_run" ] || ln_run "$(first_type $(config_n_get @global_app[0] hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
[ -n "$no_run" ] || {
|
||||
HYSTERIA_LOG_LEVEL="$loglevel" \
|
||||
ln_run "$(first_type "$(config_n_get @global_app[0] hysteria_file)")" "hysteria" $log_file -c "$config_file" client
|
||||
}
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -792,6 +797,7 @@ start_global() {
|
||||
}
|
||||
local plugin_sh="${config_file%.json}_plugin.sh"
|
||||
json_add_string "plugin_sh" "$plugin_sh"
|
||||
json_add_string "loglevel" "$(config_n_get @global[0] loglevel "warn")"
|
||||
lua $UTIL_SS gen_config "$(json_dump)" > $config_file
|
||||
ln_run "$(first_type sslocal)" "sslocal" $log_file -c "$config_file" -v
|
||||
;;
|
||||
@@ -808,7 +814,9 @@ start_global() {
|
||||
}
|
||||
json_add_string "tcp_proxy_way" "${TCP_PROXY_WAY}"
|
||||
lua $UTIL_HYSTERIA2 gen_config "$(json_dump)" > $config_file
|
||||
ln_run "$(first_type $(config_n_get @global_app[0] hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
HYSTERIA_LOG_LEVEL="$loglevel" \
|
||||
ln_run "$(first_type "$(config_n_get @global_app[0] hysteria_file)")" "hysteria" $log_file -c "$config_file" client
|
||||
;;
|
||||
esac
|
||||
if [ -n "${_socks_flag}" ]; then
|
||||
@@ -1630,7 +1638,7 @@ acl_app() {
|
||||
run_${type} flag=$node node=$node redir_port=$redir_port ${_extra_param} config_file=$config_file log_file=$log_file loglevel=$loglevel
|
||||
else
|
||||
config_file="acl/${node}_SOCKS_${socks_port}.json"
|
||||
run_socks flag=$node node=$node bind=127.0.0.1 socks_port=$socks_port config_file=$config_file log_file=$log_file
|
||||
run_socks flag=$node node=$node bind=127.0.0.1 socks_port=$socks_port config_file=$config_file log_file=$log_file loglevel=$loglevel
|
||||
# log_file=$TMP_ACL_PATH/ipt2socks_${node}_${redir_port}.log
|
||||
log_file="/dev/null"
|
||||
run_ipt2socks flag=acl_${node} tcp_tproxy=${is_tproxy} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file
|
||||
|
||||
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=Argon Theme
|
||||
LUCI_DEPENDS:=+USE_APK:wget-any +!USE_APK:wget +jsonfilter
|
||||
PKG_VERSION:=2.4.7
|
||||
PKG_RELEASE:=19
|
||||
PKG_RELEASE:=20
|
||||
|
||||
CONFIG_LUCI_CSSTIDY:=
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
body{background:#1e1e1e;color:#ccc}.spinning::before{filter:invert(1)}.login-page .login-container{background-color:rgba(0,0,0,var(--blur-opacity-dark));-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark))}.login-page .login-container .login-form{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b!important;background-color:var(--dark-primary)!important}.login-page .login-container .login-form .form-login .cbi-button-apply:focus,.login-page .login-container .login-form .form-login .cbi-button-apply:hover{opacity:.9}header::after{background-color:#1e1e1e!important}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#ccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#ccc!important}.main .main-left .nav .slide .slide-menu .active::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .slide-menu li a{color:#ccc}.main .main-left .nav .slide .slide-menu li a:hover{background:0 0!important}.main .main-left .nav .slide .slide-menu li::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .menu.active{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left .nav .slide .menu.active a::after{background-color:#fff!important}.main .main-left .nav li a{color:#ccc!important}.main .main-left .nav li a:hover{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}h4{color:#8c6900}abbr{color:var(--dark-primary)!important}a:active,a:link,a:visited{color:#a5b2ff}input:-webkit-autofill{background-color:#3c3c3c!important}#channel_graph{background-color:transparent!important}.cbi-button-apply,.cbi-button-edit,.cbi-value-field .cbi-input-apply{color:#fff!important;background-color:#483d8b!important;background-color:var(--dark-primary)!important;border-color:#483d8b!important;border-color:var(--dark-primary)!important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e!important}.cbi-map-descr{color:#ccc}.cbi-section{background:0 0;box-shadow:0 0 .5rem 0 rgba(0,0,0,.35)}.panel-title{color:#ccc;background-color:#333}div>.table>.tr:nth-of-type(2n),div>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#conns>div>div,#membuff>div>div,#memfree>div>div,#memtotal>div>div,#swapfree>div>div,#swaptotal>div>div{background-color:var(--dark-primary)!important}#conns>div>div>div>small,#membuff>div>div>div>small,#memfree>div>div>div>small,#memtotal>div>div>div>small,#swapfree>div>div>div>small,#swaptotal>div>div>div>small{color:#ccc!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#ba8b00!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:#000 1px solid!important}.tr.cbi-section-table-titles.named::before,.tr[data-title]::before{background-color:#252526}#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2),.cbi-section-table-row::before,.tr>.td,.tr>.th,tr>td,tr>th{border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-down,.cbi-rowstyle-2 .cbi-button-up,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666!important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc}h4{background-color:#1e1e1f}.cLine truncated
|
||||
body{background:#1e1e1e;color:#ccc}.spinning::before{filter:invert(1)}.login-page .login-container{background-color:rgba(0,0,0,var(--blur-opacity-dark));-webkit-backdrop-filter:blur(var(--blur-radius-dark));backdrop-filter:blur(var(--blur-radius-dark))}.login-page .login-container .login-form{background-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.login-page .login-container .login-form .brand{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply{background-color:#483d8b!important;background-color:var(--dark-primary)!important}.login-page .login-container .login-form .form-login .cbi-button-apply:focus,.login-page .login-container .login-form .form-login .cbi-button-apply:hover{opacity:.9}header::after{background-color:#1e1e1e!important}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,.15)}.main .main-left .sidenav-header .brand{color:#ccc}.main .main-left .nav .slide .slide-menu .active a{color:#ccc}.main .main-left .nav .slide .slide-menu .active a::after{background-color:#ccc!important}.main .main-left .nav .slide .slide-menu .active::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .slide-menu li a{color:#ccc}.main .main-left .nav .slide .slide-menu li a:hover{background:0 0!important}.main .main-left .nav .slide .slide-menu li::after{background-color:var(--dark-primary)!important}.main .main-left .nav .slide .menu.active{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left .nav .slide .menu.active a::after{background-color:#fff!important}.main .main-left .nav li a{color:#ccc!important}.main .main-left .nav li a:hover{background-color:#483d8b!important;background-color:var(--dark-primary)!important;color:#fff!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}.main .main-left::-webkit-scrollbar-track{background-color:#333}.main .main-right{background-color:#1e1e1e}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}h4{color:#8c6900}abbr{color:var(--dark-primary)!important}a:active,a:link,a:visited{color:#a5b2ff}input:-webkit-autofill{background-color:#3c3c3c!important}#channel_graph{background-color:transparent!important}.cbi-button-apply,.cbi-button-edit,.cbi-value-field .cbi-input-apply{color:#fff!important;background-color:#483d8b!important;background-color:var(--dark-primary)!important;border-color:#483d8b!important;border-color:var(--dark-primary)!important}.cbi-section em{color:#ccc}header.bg-primary{background-color:#1e1e1e!important}.cbi-map-descr{color:#ccc}.cbi-section{background:0 0;box-shadow:0 0 .5rem 0 rgba(0,0,0,.35)}.panel-title{color:#ccc;background-color:#333}div>.table>.tr:nth-of-type(2n),div>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc}fieldset>table>tbody>tr:nth-of-type(2n){background-color:#252526}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{border-top:1px solid #252526}#conns>div>div,#membuff>div>div,#memfree>div>div,#memtotal>div>div,#swapfree>div>div,#swaptotal>div>div{background-color:var(--dark-primary)!important}#conns>div>div>div>small,#membuff>div>div>div>small,#memfree>div>div>div>small,#memtotal>div>div>div>small,#swapfree>div>div>div>small,#swaptotal>div>div>div>small{color:#ccc!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div{background-color:#ba8b00!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th{background-color:#252526;border-bottom:#000 1px solid!important}.tr.cbi-section-table-titles.named::before,.tr[data-title]::before{background-color:#252526}#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2),.cbi-section-table-row::before,.tr>.td,.tr>.th,tr>td,tr>th{border-top:0}.cbi-rowstyle-2{background-color:#1e1e1e}.cbi-rowstyle-1{background-color:#252526}.cbi-rowstyle-2 .cbi-button-down,.cbi-rowstyle-2 .cbi-button-up,body:not(.Interfaces) .cbi-rowstyle-2:first-child{background-color:#666!important}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc}h4{background-color:#1e1e1f}.cLine truncated
|
||||
.modal>pre,.modal>textarea{color: #ccc};
|
||||
Reference in new issue
Block a user