diff --git a/apfree-wifidog/Makefile b/apfree-wifidog/Makefile
index f79d58717..b5fd49175 100644
--- a/apfree-wifidog/Makefile
+++ b/apfree-wifidog/Makefile
@@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=apfree-wifidog
-PKG_VERSION:=9.09.2938
-PKG_RELEASE:=1
+PKG_VERSION:=9.09.2947
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/liudf0716/$(PKG_NAME)/tar.gz/$(PKG_VERSION)?
diff --git a/dae/Makefile b/dae/Makefile
index 33f29905f..7f4f58d5f 100644
--- a/dae/Makefile
+++ b/dae/Makefile
@@ -5,10 +5,10 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dae
-PKG_VERSION:=2026.09.18
-PKG_RELEASE:=45
+PKG_VERSION:=2026.09.20
+PKG_RELEASE:=46
-PKG_SOURCE:=dae-src-2026.09.18-dc29e60bab23.tar.gz
+PKG_SOURCE:=dae-src-2026.09.20-2a846ee5a7e4.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip
diff --git a/dae/patches_arm/0003-drop-kprobe-skb-5.patch b/dae/patches_arm/0003-drop-kprobe-skb-5.patch
index 49bfccb7c..6f68d4086 100644
--- a/dae/patches_arm/0003-drop-kprobe-skb-5.patch
+++ b/dae/patches_arm/0003-drop-kprobe-skb-5.patch
@@ -5,15 +5,20 @@
KPROBE_SKB_AT(3)
KPROBE_SKB_AT(4)
-KPROBE_SKB_AT(5)
-
+
SEC("kprobe/skb_lifetime_termination")
int kprobe_skb_lifetime_termination(struct pt_regs *ctx)
--- a/trace/trace.go
+++ b/trace/trace.go
-@@ -191,7 +191,6 @@ func attachBpfToTargets(objs *bpfObjects, targets map[string]int) (links []link.Link, err error) {
- 1: objs.KprobeSkb1,
- 2: objs.KprobeSkb2,
- 3: objs.KprobeSkb3,
- 4: objs.KprobeSkb4,
+@@ -191,11 +191,10 @@
+ progByPos := map[int]*ebpf.Program{
+ 1: objs.KprobeSkb1,
+ 2: objs.KprobeSkb2,
+ 3: objs.KprobeSkb3,
+ 4: objs.KprobeSkb4,
- 5: objs.KprobeSkb5,
- }
+ }
+ symbolsByPos := make(map[int][]string, len(progByPos))
+ for fn, pos := range targets {
+ if _, ok := progByPos[pos]; !ok {
+ continue
diff --git a/daed/Makefile b/daed/Makefile
index 3f7f8cae5..554d378ce 100644
--- a/daed/Makefile
+++ b/daed/Makefile
@@ -5,10 +5,10 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=daed
-PKG_VERSION:=2026.09.18
-PKG_RELEASE:=56
+PKG_VERSION:=2026.09.20
+PKG_RELEASE:=57
-PKG_SOURCE:=daed-src-2026.09.18-0d4c9d0c95b9.tar.gz
+PKG_SOURCE:=daed-src-2026.09.20-d00211e69e94.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip
diff --git a/daed/patches_arm/0003-drop-kprobe-skb-5.patch b/daed/patches_arm/0003-drop-kprobe-skb-5.patch
index 967807e83..c4854f03b 100644
--- a/daed/patches_arm/0003-drop-kprobe-skb-5.patch
+++ b/daed/patches_arm/0003-drop-kprobe-skb-5.patch
@@ -5,15 +5,20 @@
KPROBE_SKB_AT(3)
KPROBE_SKB_AT(4)
-KPROBE_SKB_AT(5)
-
+
SEC("kprobe/skb_lifetime_termination")
int kprobe_skb_lifetime_termination(struct pt_regs *ctx)
--- a/dae-core/trace/trace.go
+++ b/dae-core/trace/trace.go
-@@ -191,7 +191,6 @@ func attachBpfToTargets(objs *bpfObjects, targets map[string]int) (links []link.Link, err error) {
- 1: objs.KprobeSkb1,
- 2: objs.KprobeSkb2,
- 3: objs.KprobeSkb3,
- 4: objs.KprobeSkb4,
+@@ -191,11 +191,10 @@
+ progByPos := map[int]*ebpf.Program{
+ 1: objs.KprobeSkb1,
+ 2: objs.KprobeSkb2,
+ 3: objs.KprobeSkb3,
+ 4: objs.KprobeSkb4,
- 5: objs.KprobeSkb5,
- }
+ }
+ symbolsByPos := make(map[int][]string, len(progByPos))
+ for fn, pos := range targets {
+ if _, ok := progByPos[pos]; !ok {
+ continue
diff --git a/luci-app-agentflow/Makefile b/luci-app-agentflow/Makefile
index fbc2e99f6..1620a22c8 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.1
-PKG_RELEASE:=6
+PKG_RELEASE:=7
LUCI_DEPENDS:=+agentflow +luci-compat +luci-lib-taskd
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 3c7621859..9c4b25543 100644
--- a/luci-app-agentflow/luasrc/controller/agentflow.lua
+++ b/luci-app-agentflow/luasrc/controller/agentflow.lua
@@ -5,6 +5,13 @@ 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
+local AGENTS = {
+ { id = "codexcli", package = "@openai/codex" },
+ { id = "claude-code", package = "@anthropic-ai/claude-code" },
+ { id = "opencode", package = "opencode-ai" },
+ { id = "kimi", package = "@moonshot-ai/kimi-code" },
+ { id = "reasonix", package = "reasonix" }
+}
function index()
entry({"admin", "services", "agentflow_status"}, call("agentflow_status"))
@@ -133,10 +140,54 @@ local function agentflow_entry_url()
return "http://" .. url_authority(request_or_lan_host(), port) .. base_path
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_statuses()
+ local fs = require "nixio.fs"
+ local jsonc = require "luci.jsonc"
+ local root = node_modules_root()
+ 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
+ if type(package_json) == "table" 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 port, base_path = agentflow_config()
local entry_url = agentflow_entry_url()
+ local agents, agents_available = agent_statuses()
local status = {
running = (sys.call("pidof agentflow >/dev/null") == 0),
@@ -145,7 +196,9 @@ function agentflow_status()
entry_url = entry_url,
proxy_prefix_supported = uhttpd_supports_proxy_prefix(),
proxy_prefix_enabled = uhttpd_apps_proxy_available(),
- linkeasefull_running = linkeasefull_running()
+ linkeasefull_running = linkeasefull_running(),
+ agents_available = agents_available,
+ agents = agents
}
write_json(status)
end
@@ -158,20 +211,17 @@ function agentflow_agent_install()
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 agents = {
- codexcli = true,
- ["claude-code"] = true,
- opencode = true,
- kimi = true,
- reasonix = true
- }
+ 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 agents[agent] then
+ if not supported_agents[agent] then
write_json({ ok = false, error = "unsupported agent" })
return
end
diff --git a/luci-app-agentflow/luasrc/view/agentflow/status.htm b/luci-app-agentflow/luasrc/view/agentflow/status.htm
index 615acb0cf..90ffdad63 100644
--- a/luci-app-agentflow/luasrc/view/agentflow/status.htm
+++ b/luci-app-agentflow/luasrc/view/agentflow/status.htm
@@ -1,58 +1,378 @@
<%+tasks/embed%>
-
-
-
-
-
<%:Install agent%>
-
<%:Select a coding agent to install into the shared AgentFlow runtime.%>
-
-
-
+
+
+
+
...
+
+
<%:Checking AgentFlow service%>
+
<%:Collecting data...%>
+
+
-
-
-
+
+
+
+
+
+
+
<%:Open this address in a browser to access the AgentFlow Web interface.%>
+
+
+
+
+
+
A
+
+
<%:Agent installation%>
+
<%:Install coding agents into the shared AgentFlow runtime. Installed agents show their current version.%>
+
+
+
+
+
C
Codex
<%:OpenAI coding agent for software development tasks.%>
+
<%:Checking...%>|<%:Version%>: -
+
+
+
+
C
Claude Code
<%:Anthropic coding agent for code analysis and development.%>
+
<%:Checking...%>|<%:Version%>: -
+
+
+
+
O
OpenCode
<%:Open source coding agent with a flexible terminal workflow.%>
+
<%:Checking...%>|<%:Version%>: -
+
+
+
+
K
Kimi
<%:Moonshot AI coding agent for terminal-based development.%>
+
<%:Checking...%>|<%:Version%>: -
+
+
+
+
R
Reasonix
<%:AI coding agent for software engineering workflows.%>
+
<%:Checking...%>|<%:Version%>: -
+
+
+
+
+
+
diff --git a/luci-app-agentflow/po/zh-cn/agentflow.po b/luci-app-agentflow/po/zh-cn/agentflow.po
index 3b684b092..9367df20a 100644
--- a/luci-app-agentflow/po/zh-cn/agentflow.po
+++ b/luci-app-agentflow/po/zh-cn/agentflow.po
@@ -72,3 +72,84 @@ msgstr "任务日志窗口不可用。"
msgid "Failed to start agent installation."
msgstr "启动智能体安装失败。"
+
+msgid "Installed"
+msgstr "已安装"
+
+msgid "Not installed"
+msgstr "未安装"
+
+msgid "Status unavailable"
+msgstr "状态不可用"
+
+msgid "Install"
+msgstr "安装"
+
+msgid "Starting..."
+msgstr "正在启动……"
+
+msgid "Copied"
+msgstr "已复制"
+
+msgid "Copy"
+msgstr "复制"
+
+msgid "AgentFlow service is running"
+msgstr "AgentFlow 服务运行中"
+
+msgid "AgentFlow service is not running"
+msgstr "AgentFlow 服务未运行"
+
+msgid "The service is ready. You can open AgentFlow or install coding agents."
+msgstr "服务已就绪,可以打开 AgentFlow 或安装编码智能体。"
+
+msgid "Start the service to use AgentFlow. Agent installation remains available."
+msgstr "请启动服务后使用 AgentFlow;智能体安装仍然可用。"
+
+msgid "Checking AgentFlow service"
+msgstr "正在检查 AgentFlow 服务"
+
+msgid "Open AgentFlow"
+msgstr "打开 AgentFlow"
+
+msgid "Local network access"
+msgstr "局域网访问"
+
+msgid "Open this address in a browser to access the AgentFlow Web interface."
+msgstr "在浏览器中打开此地址即可访问 AgentFlow Web 界面。"
+
+msgid "Agent installation"
+msgstr "智能体安装"
+
+msgid "Install coding agents into the shared AgentFlow runtime. Installed agents show their current version."
+msgstr "将编码智能体安装到 AgentFlow 共享运行环境中;已安装的智能体会显示当前版本。"
+
+msgid "OpenAI coding agent for software development tasks."
+msgstr "OpenAI 提供的代码智能体,适用于软件开发任务。"
+
+msgid "Anthropic coding agent for code analysis and development."
+msgstr "Anthropic 提供的代码智能体,适用于代码分析与开发。"
+
+msgid "Open source coding agent with a flexible terminal workflow."
+msgstr "开源代码智能体,提供灵活的终端开发工作流。"
+
+msgid "Moonshot AI coding agent for terminal-based development."
+msgstr "Moonshot AI 提供的代码智能体,适用于终端开发。"
+
+msgid "AI coding agent for software engineering workflows."
+msgstr "面向软件工程工作流的 AI 代码智能体。"
+
+msgid "Checking..."
+msgstr "正在检查……"
+
+msgid "Version"
+msgstr "版本"
+
+msgid "Confirm agent installation"
+msgstr "确认安装智能体"
+
+msgid "The installer will download and install"
+msgstr "安装程序将下载并安装"
+
+msgid "into the shared AgentFlow runtime."
+msgstr "到 AgentFlow 共享运行环境。"
diff --git a/luci-app-agentflow/tests/test_agent_install_contract.py b/luci-app-agentflow/tests/test_agent_install_contract.py
index 99391e4a0..15f0ed992 100644
--- a/luci-app-agentflow/tests/test_agent_install_contract.py
+++ b/luci-app-agentflow/tests/test_agent_install_contract.py
@@ -16,37 +16,57 @@ class AgentInstallContractTest(unittest.TestCase):
self.assertIn("+luci-lib-taskd", makefile)
self.assertIn('<%+tasks/embed%>', status)
- self.assertIn('