From 01aa5b5f9e80f4d5c4c2c6f69c47e7dfe90842f6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 5 Sep 2026 21:18:46 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20Sync=202026-09-05=2021:18:46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agentflow/Makefile | 17 ++- agentflow/files/agentflow-plugin.json | 41 +++++++ agentflow/files/www/logo.svg | 21 ++++ .../tests/test_desktop_manifest_contract.py | 48 ++++++++ agentflow/tests/test_mise_runtime_contract.py | 21 +++- filebrowser/Makefile | 89 ++++++++------ filebrowser/files/config.yaml | 13 -- filebrowser/files/filebrowser.config | 2 + filebrowser/files/filebrowser.init | 49 +++++--- linkease-common-bin/Makefile | 4 +- linkease/Makefile | 4 +- linkeasefull/Makefile | 4 +- luci-app-agentflow/Makefile | 2 +- .../luasrc/controller/agentflow.lua | 114 ++++++++++++++++-- .../luasrc/view/agentflow/status.htm | 10 +- luci-app-agentflow/po/zh-cn/agentflow.po | 6 + .../test_agentflow_luci_open_contract.py | 32 +++++ .../Makefile | 1 + .../luci-static/resources/view/filebrowser.js | 60 ++++----- .../po/templates/filebrowser.pot | 0 luci-app-filebrowser-go/po/zh-cn | 1 + .../po/zh_Hans/filebrowser.po | 0 .../luci/menu.d/luci-app-filebrowser.json | 0 .../rpcd/acl.d/luci-app-filebrowser.json | 0 luci-app-filebrowser/po/zh-cn | 1 - .../share/ucitrack/luci-app-filebrowser.json | 4 - luci-app-filetransfer/Makefile | 2 +- .../luasrc/model/cbi/filetransfer.lua | 8 +- luci-theme-footstrap/Makefile | 2 +- luci-theme-footstrap/styles/02-tokens.css | 44 +++---- luci-theme-footstrap/styles/03-palettes.css | 99 ++++++++------- luci-theme-footstrap/styles/04-nocolormix.css | 9 -- luci-theme-footstrap/styles/base/95-luci.css | 8 -- .../styles/pages/40-sshkeys.css | 1 - .../styles/theme/15-wallpaper.css | 12 -- .../styles/theme/20-shell.css | 8 +- .../styles/theme/30-tables.css | 1 - .../styles/theme/35-alerts.css | 1 - luci-theme-footstrap/styles/theme/40-tabs.css | 1 - luci-theme-footstrap/styles/theme/45-misc.css | 2 - .../styles/theme/50-toplayout.css | 1 - .../styles/theme/60-inputs.css | 16 +-- .../styles/theme/75-search.css | 3 +- .../styles/theme/95-a11y-media.css | 11 +- .../styles/theme/97-print.css | 5 +- 45 files changed, 506 insertions(+), 272 deletions(-) create mode 100644 agentflow/files/agentflow-plugin.json create mode 100644 agentflow/files/www/logo.svg create mode 100644 agentflow/tests/test_desktop_manifest_contract.py delete mode 100644 filebrowser/files/config.yaml create mode 100644 luci-app-agentflow/tests/test_agentflow_luci_open_contract.py rename {luci-app-filebrowser => luci-app-filebrowser-go}/Makefile (85%) rename {luci-app-filebrowser => luci-app-filebrowser-go}/htdocs/luci-static/resources/view/filebrowser.js (61%) rename {luci-app-filebrowser => luci-app-filebrowser-go}/po/templates/filebrowser.pot (100%) create mode 120000 luci-app-filebrowser-go/po/zh-cn rename {luci-app-filebrowser => luci-app-filebrowser-go}/po/zh_Hans/filebrowser.po (100%) rename {luci-app-filebrowser => luci-app-filebrowser-go}/root/usr/share/luci/menu.d/luci-app-filebrowser.json (100%) rename {luci-app-filebrowser => luci-app-filebrowser-go}/root/usr/share/rpcd/acl.d/luci-app-filebrowser.json (100%) delete mode 100644 luci-app-filebrowser/po/zh-cn delete mode 100644 luci-app-filebrowser/root/usr/share/ucitrack/luci-app-filebrowser.json diff --git a/agentflow/Makefile b/agentflow/Makefile index 93257c12..d881f0f8 100644 --- a/agentflow/Makefile +++ b/agentflow/Makefile @@ -15,7 +15,7 @@ AGENTFLOW_HASH_aarch64:=6d733ebc49b095bf8670a1b655a13bb8ad98c90ced19701b67d5cdd4 PKG_NAME:=agentflow PKG_VERSION:=0.3.0 -PKG_RELEASE:=6 +PKG_RELEASE:=7 AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH) AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH)) @@ -52,6 +52,16 @@ define Package/$(PKG_NAME)/conffiles /etc/config/agentflow endef +define Package/$(PKG_NAME)/prerm +#!/bin/sh +if [ "$${IPKG_INSTROOT}" = "" ]; then + if [ "$$(readlink /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json 2>/dev/null)" = "/usr/share/agentflow/agentflow-plugin.json" ]; then + rm -f /usr/share/linkeasefull/desktop-apps.d/30-agentflow.json + fi +fi +exit 0 +endef + define Build/Prepare $(INSTALL_DIR) $(PKG_BUILD_DIR) $(CP) $(DL_DIR)/$(AGENTFLOW_DOWNLOAD) $(PKG_BUILD_DIR)/agentflow @@ -64,11 +74,14 @@ define Build/Compile endef define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config + $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/config $(1)/usr/share/agentflow/www $(1)/usr/share/linkeasefull/desktop-apps.d $(INSTALL_BIN) $(PKG_BUILD_DIR)/agentflow $(1)/usr/sbin/agentflow $(INSTALL_BIN) ./files/agentflow.init $(1)/etc/init.d/agentflow $(INSTALL_BIN) ./files/agentflow.uci-default $(1)/etc/uci-defaults/09-agentflow $(INSTALL_CONF) ./files/agentflow.config $(1)/etc/config/agentflow + $(INSTALL_DATA) ./files/agentflow-plugin.json $(1)/usr/share/agentflow/agentflow-plugin.json + $(INSTALL_DATA) ./files/www/logo.svg $(1)/usr/share/agentflow/www/logo.svg + ln -sf /usr/share/agentflow/agentflow-plugin.json $(1)/usr/share/linkeasefull/desktop-apps.d/30-agentflow.json endef $(eval $(call Download,agentflow)) diff --git a/agentflow/files/agentflow-plugin.json b/agentflow/files/agentflow-plugin.json new file mode 100644 index 00000000..12fbfa58 --- /dev/null +++ b/agentflow/files/agentflow-plugin.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "id": "agentflow", + "name": "AgentFlow", + "icon": "logo.svg", + "staticRoot": "/usr/share/agentflow/www", + "desktop": { + "mode": "module", + "entry": "desktop-entry.js", + "isolation": "shadow-dom" + }, + "standalone": { + "entry": "index.html", + "basePath": "/apps/agentflow/", + "url": "/cgi-bin/luci/admin/services/agentflow/open", + "externalOpen": { + "enabled": true, + "label": "Open AgentFlow" + } + }, + "auth": { + "mode": "passthrough" + }, + "backend": { + "type": "http", + "scheme": "http", + "host": "127.0.0.1", + "portFromUci": "agentflow.@agentflow[0].port", + "defaultPort": 9000, + "upstreamBasePath": "/apps/agentflow/", + "pathMode": "preserve", + "proxyMode": "app-base" + }, + "window": { + "width": 1180, + "height": 760, + "singleton": true + }, + "capabilities": ["agent", "coding", "workflow"], + "categories": ["development", "ai"] +} diff --git a/agentflow/files/www/logo.svg b/agentflow/files/www/logo.svg new file mode 100644 index 00000000..c4ab231a --- /dev/null +++ b/agentflow/files/www/logo.svg @@ -0,0 +1,21 @@ + + + + AF + + diff --git a/agentflow/tests/test_desktop_manifest_contract.py b/agentflow/tests/test_desktop_manifest_contract.py new file mode 100644 index 00000000..f5bec8f4 --- /dev/null +++ b/agentflow/tests/test_desktop_manifest_contract.py @@ -0,0 +1,48 @@ +import json +import pathlib +import unittest + + +APP_DIR = pathlib.Path(__file__).resolve().parents[1] + + +class DesktopManifestContractTest(unittest.TestCase): + def setUp(self): + self.manifest = json.loads( + (APP_DIR / "files" / "agentflow-plugin.json").read_text() + ) + + def test_manifest_uses_agentflow_app_base_proxy(self): + self.assertEqual(self.manifest["id"], "agentflow") + self.assertEqual(self.manifest["staticRoot"], "/usr/share/agentflow/www") + self.assertEqual(self.manifest["standalone"]["entry"], "index.html") + self.assertEqual(self.manifest["standalone"]["basePath"], "/apps/agentflow/") + self.assertEqual( + self.manifest["standalone"]["url"], + "/cgi-bin/luci/admin/services/agentflow/open", + ) + self.assertEqual( + self.manifest["standalone"]["externalOpen"], + {"enabled": True, "label": "Open AgentFlow"}, + ) + self.assertEqual(self.manifest["auth"]["mode"], "passthrough") + + backend = self.manifest["backend"] + self.assertEqual(backend["upstreamBasePath"], "/apps/agentflow/") + self.assertEqual(backend["pathMode"], "preserve") + self.assertEqual(backend["proxyMode"], "app-base") + + def test_desktop_entry_matches_manifest_contract(self): + desktop = self.manifest["desktop"] + self.assertEqual(desktop["mode"], "module") + self.assertEqual(desktop["entry"], "desktop-entry.js") + self.assertEqual(desktop["isolation"], "shadow-dom") + + self.assertFalse( + (APP_DIR / "files" / "www" / "desktop-entry.js").exists(), + "desktop-entry.js must be served by AgentFlow backend, not the static iframe wrapper", + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/agentflow/tests/test_mise_runtime_contract.py b/agentflow/tests/test_mise_runtime_contract.py index 4912c08a..31841f45 100644 --- a/agentflow/tests/test_mise_runtime_contract.py +++ b/agentflow/tests/test_mise_runtime_contract.py @@ -2,12 +2,27 @@ from pathlib import Path import unittest -ROOT = Path(__file__).resolve().parents[3] -APPLICATIONS = ROOT / "applications" +THIS_FILE = Path(__file__).resolve() def read(relative): - return (APPLICATIONS / relative).read_text() + relative_path = Path(relative) + package = relative_path.parts[0] + app = package[9:] if package.startswith("luci-app-") else package + remainder = Path(*relative_path.parts[1:]) + + candidates = [ + THIS_FILE.parents[index] / relative_path + for index in range(2, min(len(THIS_FILE.parents), 6)) + ] + candidates.append(THIS_FILE.parents[3] / app / package / remainder) + + for candidate in candidates: + if candidate.exists(): + return candidate.read_text() + + searched = "\n".join(str(candidate) for candidate in candidates) + raise FileNotFoundError(f"{relative} not found; searched:\n{searched}") class MiseRuntimeContractTest(unittest.TestCase): diff --git a/filebrowser/Makefile b/filebrowser/Makefile index c11bfb93..798f287d 100644 --- a/filebrowser/Makefile +++ b/filebrowser/Makefile @@ -1,47 +1,46 @@ +# SPDX-License-Identifier: GPL-3.0-only # -# Copyright (C) 2017-2024 -# -# This is free software, licensed under the GNU General Public License v2. -# +# Copyright (C) 2021 ImmortalWrt.org include $(TOPDIR)/rules.mk PKG_NAME:=filebrowser -PKG_VERSION:=1.5.6-stable -PKG_RELEASE=1 +PKG_VERSION:=2.63.23 +PKG_RELEASE:=21 -ifeq ($(ARCH),aarch64) - PKG_ARCH:=arm64 - PKG_HASH:=skip -else ifeq ($(ARCH),arm) - PKG_ARCH:=armv7 - PKG_HASH:=skip -else ifeq ($(ARCH),x86_64) - PKG_ARCH:=amd64 - PKG_HASH:=skip -endif +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/filebrowser/filebrowser/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=skip + +PKG_LICENSE:=Apache-2.0 +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +PKG_BUILD_DEPENDS:=golang/host node/host node-pnpm/host +PKG_BUILD_PARALLEL:=1 +PKG_BUILD_FLAGS:=no-mips16 + +GO_PKG:=github.com/filebrowser/filebrowser/v2 +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/version.CommitSHA=$(PKG_VERSION) \ + $(GO_PKG)/version.Version=v$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk define Package/filebrowser - SECTION:=net - CATEGORY:=Network - DEPENDS:=@(arm||aarch64||x86_64) - TITLE:=FileBrowser Quantum + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Web File Browser + URL:=https://github.com/filebrowser/filebrowser + DEPENDS:=$(GO_ARCH_DEPENDS) endef define Package/filebrowser/description - The best free self-hosted web-based file manager. -endef - -PKG_SOURCE:=linux-$(PKG_ARCH)-filebrowser -PKG_SOURCE_URL:=https://github.com/gtsteffaniak/filebrowser/releases/download/v$(PKG_VERSION) - -define Build/Prepare - $(call Build/Prepare/Default) -endef - -define Build/Compile + filebrowser provides a file managing interface within a specified directory + and it can be used to upload, delete, preview, rename and edit your files. + It allows the creation of multiple users and each user can have its own directory. + It can be used as a standalone app or as a middleware. endef define Package/filebrowser/conffiles @@ -49,15 +48,25 @@ define Package/filebrowser/conffiles /etc/config/filebrowser endef -define Package/filebrowser/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) $(CURDIR)/files/filebrowser.init $(1)/etc/init.d/filebrowser - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_CONF) $(CURDIR)/files/filebrowser.config $(1)/etc/config/filebrowser - $(INSTALL_DIR) $(1)/etc/filebrowser - $(INSTALL_CONF) $(CURDIR)/files/config.yaml $(1)/etc/filebrowser/config.yaml - $(INSTALL_DIR) $(1)/usr/bin/ - $(INSTALL_BIN) $(DL_DIR)/linux-$(PKG_ARCH)-filebrowser $(1)/usr/bin/filebrowser +define Build/Compile + ( \ + export PNPM_HOME="$(PKG_BUILD_DIR)/frontend" ; \ + pushd "$(PKG_BUILD_DIR)/frontend" ; \ + pnpm install --frozen-lockfile ; \ + pnpm run build ; \ + popd ; \ + $(call GoPackage/Build/Compile) ; \ + ) endef +define Package/filebrowser/install + $(call GoPackage/Package/Install/Bin,$(1)) + + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) $(CURDIR)/files/filebrowser.config $(1)/etc/config/filebrowser + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) $(CURDIR)/files/filebrowser.init $(1)/etc/init.d/filebrowser +endef + +$(eval $(call GoBinPackage,filebrowser)) $(eval $(call BuildPackage,filebrowser)) diff --git a/filebrowser/files/config.yaml b/filebrowser/files/config.yaml deleted file mode 100644 index b558ae19..00000000 --- a/filebrowser/files/config.yaml +++ /dev/null @@ -1,13 +0,0 @@ -server: - port: 8989 - database: "/etc/filebrowser/database.db" - sources: - - path: "/" # Do not use a root "/" directory or include the "/var" folder - config: - defaultEnabled: true -auth: - adminUsername: admin - adminPassword: "admin" -userDefaults: - ui: - locale: "cn" diff --git a/filebrowser/files/filebrowser.config b/filebrowser/files/filebrowser.config index b28f95d3..9624e3df 100644 --- a/filebrowser/files/filebrowser.config +++ b/filebrowser/files/filebrowser.config @@ -2,4 +2,6 @@ config filebrowser 'config' option enabled '0' option listen_port '8989' option root_path '/' + option base_url '' + option disable_exec '1' diff --git a/filebrowser/files/filebrowser.init b/filebrowser/files/filebrowser.init index 09b06298..5d586535 100644 --- a/filebrowser/files/filebrowser.init +++ b/filebrowser/files/filebrowser.init @@ -1,33 +1,50 @@ #!/bin/sh /etc/rc.common +USE_PROCD=1 START=99 -STOP=10 CONF="filebrowser" PROG="/usr/bin/filebrowser" -CONF_PATH="/etc/filebrowser/config.yaml" -PID_FILE="/var/run/filebrowser.pid" +DB_PATH="/etc/filebrowser/database.db" -start() { +start_service() { config_load "$CONF" local enabled config_get_bool enabled "config" "enabled" "0" [ "$enabled" -eq "1" ] || return 1 - local listen_port root_path base_url + mkdir -p "${DB_PATH%/*}" + + local listen_port root_path base_url disable_exec config_get listen_port "config" "listen_port" "8989" - config_get root_path "config" "root_path" "/" - - echo "Starting filebrowser..." - sed -e "s/ port:.*/ port: $listen_port/" \ - -e "s, - path:.*, - path: \"$root_path\"," \ - -i "$CONF_PATH" - start-stop-daemon -S -q -b -m -p "$PID_FILE" -x "$PROG" -- -c "$CONF_PATH" + config_get root_path "config" "root_path" "/mnt/" + config_get base_url "config" "base_url" + config_get_bool disable_exec "config" "disable_exec" "1" + + procd_open_instance + procd_set_param command "$PROG" + procd_append_param command --database "$DB_PATH" + procd_append_param command --address "[::]" + procd_append_param command --port "$listen_port" + procd_append_param command --root "$root_path" + procd_append_param command --disable-exec="$disable_exec" + [ -z "$base_url" ] || procd_append_param command --baseurl "$base_url" + if [ ! -e "$DB_PATH" ]; then + procd_append_param command --username "admin" + procd_append_param command --password "$("$PROG" hash "admin")" + fi + + procd_set_param limits core="unlimited" + procd_set_param limits nofile="1000000 1000000" + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param respawn + + procd_close_instance + } -stop() { - kill -9 `pidof filebrowser | sed "s/$$//g"` 2>/dev/null - rm -f "$PID_FILE" - echo "filebrowser stopped" +service_triggers() { + procd_add_reload_trigger "$CONF" } diff --git a/linkease-common-bin/Makefile b/linkease-common-bin/Makefile index 712884c9..b97d3072 100644 --- a/linkease-common-bin/Makefile +++ b/linkease-common-bin/Makefile @@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH) PKG_NAME:=linkease-common-bin # use PKG_SOURCE_DATE instead of PKG_VERSION for compitable PKG_SOURCE_DATE:=1.7.5 -PKG_RELEASE:=24 +PKG_RELEASE:=25 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) @@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel) ARCH_HEXCODE=1b0c endif -PKG_SOURCE_VERSION:=469e9a582af646e9d3df7aec4b31fcfda9e4a325 +PKG_SOURCE_VERSION:=7093bc8b705b7b239b8adde8e4d89928157de456 PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/ PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE) diff --git a/linkease/Makefile b/linkease/Makefile index 1bc0404d..74b61e24 100644 --- a/linkease/Makefile +++ b/linkease/Makefile @@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH) PKG_NAME:=linkease # use PKG_SOURCE_DATE instead of PKG_VERSION for compitable PKG_SOURCE_DATE:=1.7.5 -PKG_RELEASE:=27 +PKG_RELEASE:=28 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) @@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel) ARCH_HEXCODE=1b0c endif -PKG_SOURCE_VERSION:=469e9a582af646e9d3df7aec4b31fcfda9e4a325 +PKG_SOURCE_VERSION:=7093bc8b705b7b239b8adde8e4d89928157de456 PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/ PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE) diff --git a/linkeasefull/Makefile b/linkeasefull/Makefile index 2b14c44b..b3c9ed48 100644 --- a/linkeasefull/Makefile +++ b/linkeasefull/Makefile @@ -11,7 +11,7 @@ PKG_ARCH_LINKEASE:=$(ARCH) PKG_NAME:=linkeasefull # use PKG_SOURCE_DATE instead of PKG_VERSION for compitable PKG_SOURCE_DATE:=3.0.17 -PKG_RELEASE:=26 +PKG_RELEASE:=27 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) @@ -24,7 +24,7 @@ LINKEASE_RUNTIME_ARCH:=arm64 PKG_HASH:=skip endif -PKG_SOURCE_VERSION:=469e9a582af646e9d3df7aec4b31fcfda9e4a325 +PKG_SOURCE_VERSION:=7093bc8b705b7b239b8adde8e4d89928157de456 PKG_SOURCE:=linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH).tar.gz PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkeasefull-runtime-v$(PKG_SOURCE_DATE)/ PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH) diff --git a/luci-app-agentflow/Makefile b/luci-app-agentflow/Makefile index 4c3128b3..d5f2bcd9 100644 --- a/luci-app-agentflow/Makefile +++ b/luci-app-agentflow/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=AgentFlow PKG_VERSION:=1.0.0 -PKG_RELEASE:=3 +PKG_RELEASE:=4 LUCI_DEPENDS:=+agentflow +luci-compat LUCI_MINIFY_CSS:=0 LUCI_MINIFY_JS:=0 diff --git a/luci-app-agentflow/luasrc/controller/agentflow.lua b/luci-app-agentflow/luasrc/controller/agentflow.lua index 0b3db98f..c1b0924b 100644 --- a/luci-app-agentflow/luasrc/controller/agentflow.lua +++ b/luci-app-agentflow/luasrc/controller/agentflow.lua @@ -2,28 +2,128 @@ local http = require "luci.http" module("luci.controller.agentflow", package.seeall) +local APPS_PROXY_PREFIX = "/apps=http://127.0.0.1:19290" +local DEFAULT_BASE_PATH = "/apps/agentflow/" +local DEFAULT_PORT = 9000 + function index() + entry({"admin", "services", "agentflow_status"}, call("agentflow_status")) + local open = entry({"admin", "services", "agentflow", "open"}, call("agentflow_open")) + open.leaf = true + open.dependent = false + open.sysauth = false + if not nixio.fs.access("/etc/config/agentflow") then return end local page = entry({"admin", "services", "agentflow"}, cbi("agentflow"), _("AgentFlow"), 100) page.dependent = true - entry({"admin", "services", "agentflow_status"}, call("agentflow_status")) +end + +local function uhttpd_has_apps_proxy_prefix() + local uci = require "luci.model.uci".cursor() + local mappings = uci:get_list("uhttpd", "main", "proxy_prefix") or {} + + for _, mapping in ipairs(mappings) do + if mapping == APPS_PROXY_PREFIX then + return true + end + end + return false +end + +local function uhttpd_supports_proxy_prefix() + local sys = require "luci.sys" + return sys.call("grep -qr 'proxy_prefix' /etc/init.d/uhttpd /lib/functions /usr/share/uhttpd 2>/dev/null") == 0 +end + +local function uhttpd_apps_proxy_available() + return uhttpd_supports_proxy_prefix() and uhttpd_has_apps_proxy_prefix() +end + +local function linkeasefull_running() + local sys = require "luci.sys" + return sys.call("[ -x /etc/init.d/linkeasefull ] && /etc/init.d/linkeasefull running >/dev/null 2>&1") == 0 +end + +local function normalized_base_path(path) + path = path or DEFAULT_BASE_PATH + if path:sub(1, 1) ~= "/" then + path = "/" .. path + end + if path:sub(-1) ~= "/" then + path = path .. "/" + end + return path +end + +local function authority_host(authority) + if not authority or authority == "" then + return "" + end + if authority:sub(1, 1) == "[" then + return authority:match("^%[([^%]]+)%]") or "" + end + return authority:match("^([^:]+)") or authority +end + +local function url_authority(host, port) + if not host or host == "" then + host = "127.0.0.1" + end + if host:find(":") and host:sub(1, 1) ~= "[" then + host = "[" .. host .. "]" + end + return host .. ":" .. tostring(port) +end + +local function request_or_lan_host() + local uci = require "luci.model.uci".cursor() + local host = authority_host(http.getenv("HTTP_HOST") or "") + if host ~= "" then + return host + end + return uci:get("network", "lan", "ipaddr") or "127.0.0.1" +end + +local function agentflow_config() + local uci = require "luci.model.uci".cursor() + local port = tonumber(uci:get_first("agentflow", "agentflow", "port")) or DEFAULT_PORT + if port < 1 or port > 65535 then + port = DEFAULT_PORT + end + local base_path = normalized_base_path(uci:get_first("agentflow", "agentflow", "base_path")) + return port, base_path +end + +local function agentflow_entry_url() + local port, base_path = agentflow_config() + if linkeasefull_running() and uhttpd_apps_proxy_available() then + return base_path + end + return "http://" .. url_authority(request_or_lan_host(), port) .. base_path end function agentflow_status() local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - local port = tonumber(uci:get_first("agentflow", "agentflow", "port")) or 9000 - if port < 1 or port > 65535 then - port = 9000 - end + local port, base_path = agentflow_config() + local entry_url = agentflow_entry_url() local status = { running = (sys.call("pidof agentflow >/dev/null") == 0), - port = port + port = port, + base_path = base_path, + entry_url = entry_url, + proxy_prefix_supported = uhttpd_supports_proxy_prefix(), + proxy_prefix_enabled = uhttpd_apps_proxy_available(), + linkeasefull_running = linkeasefull_running() } http.prepare_content("application/json") http.write_json(status) end + +function agentflow_open() + local entry_url = agentflow_entry_url() + http.redirect(entry_url) +end diff --git a/luci-app-agentflow/luasrc/view/agentflow/status.htm b/luci-app-agentflow/luasrc/view/agentflow/status.htm index 6747f6e1..6e21cd83 100644 --- a/luci-app-agentflow/luasrc/view/agentflow/status.htm +++ b/luci-app-agentflow/luasrc/view/agentflow/status.htm @@ -1,12 +1,20 @@