From 2206a0ea688f567942fe2e7930f005499b1f0001 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 May 2026 00:17:24 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8D=89=20Sync=202026-05-13=2000:17:24?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kai/Makefile | 6 +- kai/files/kai.config | 3 +- kai/files/kai.init | 99 +++++++++++++++++-- kai_session/Makefile | 6 +- luci-app-kai/Makefile | 10 +- luci-app-kai/luasrc/model/cbi/kai.lua | 25 ++++- luci-app-kai/luasrc/model/kai.lua | 54 ++++++++++ luci-app-kai/luasrc/view/kai/kai_status.htm | 2 +- luci-nginxer/Makefile | 8 +- .../root/etc/uci-defaults/50_luci-nginxer | 6 +- sqm-autorate/Makefile | 2 +- .../usr/share/sqm-autorate/config_template.sh | 2 +- 12 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 luci-app-kai/luasrc/model/kai.lua diff --git a/kai/Makefile b/kai/Makefile index 00cde69e7..caa4ced0e 100644 --- a/kai/Makefile +++ b/kai/Makefile @@ -10,10 +10,10 @@ include $(TOPDIR)/rules.mk PKG_ARCH_kai:=$(ARCH) PKG_NAME:=kai -PKG_VERSION:=0.0.2 -PKG_RELEASE:=3 +PKG_VERSION:=0.0.5 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/Carseason/openwrt-packages/releases/download/prebuilt/ +PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/ PKG_HASH:=skip PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION) diff --git a/kai/files/kai.config b/kai/files/kai.config index 9bcd08051..38b8756a1 100644 --- a/kai/files/kai.config +++ b/kai/files/kai.config @@ -1,3 +1,4 @@ config kai option 'enabled' '0' - option 'cwd' '/tmp/kai' + option 'data_dir' '' + option 'port' '8197' diff --git a/kai/files/kai.init b/kai/files/kai.init index c11b5e709..f6ba508ff 100755 --- a/kai/files/kai.init +++ b/kai/files/kai.init @@ -5,24 +5,95 @@ USE_PROCD=1 get_config() { config_get_bool enabled $1 enabled 1 - config_get cwd $1 cwd "/tmp/kai" + config_get data_dir $1 data_dir "" + config_get port $1 port "8197" +} + +http_get() { + local url="$1" + if command -v uclient-fetch >/dev/null 2>&1; then + uclient-fetch -O /dev/stdout "$url" 2>/dev/null + return $? + fi + if command -v wget >/dev/null 2>&1; then + wget -qO- "$url" 2>/dev/null + return $? + fi + if command -v curl >/dev/null 2>&1; then + curl -fsL "$url" 2>/dev/null + return $? + fi + return 1 +} + +maybe_refresh_opencode_skills_cache() { + [ -n "$data_dir" ] || return 0 + [ -n "$port" ] || return 0 + command -v jsonfilter >/dev/null 2>&1 || return 0 + + local cache_root="${data_dir}/cache/opencode/skills" + local state_root="${data_dir}/state/opencode" + local version_file="${state_root}/skills.manifest.version" + local managed_file="${state_root}/skills.managed.list" + local manifest_url="http://127.0.0.1:${port}/agentconf/skills/manifest.json" + + [ -d "$cache_root" ] || mkdir -p "$cache_root" + [ -d "$state_root" ] || mkdir -p "$state_root" + + local manifest version prev_version skills + manifest="$(http_get "$manifest_url")" || return 0 + version="$(printf '%s' "$manifest" | jsonfilter -e '@.version' 2>/dev/null)" + [ -n "$version" ] || return 0 + + prev_version="" + [ -f "$version_file" ] && prev_version="$(cat "$version_file" 2>/dev/null)" + [ "$version" = "$prev_version" ] && return 0 + + logger -t kai "opencode skills manifest changed; refreshing managed skill cache" + + if [ -f "$managed_file" ]; then + while IFS= read -r s; do + [ -n "$s" ] || continue + rm -rf "${cache_root}/${s}" + done <"$managed_file" + fi + + skills="$(printf '%s' "$manifest" | jsonfilter -e '@.skills[*]' 2>/dev/null)" + if [ -n "$skills" ]; then + printf '%s\n' "$skills" >"$managed_file" + printf '%s\n' "$skills" | while IFS= read -r s; do + [ -n "$s" ] || continue + rm -rf "${cache_root}/${s}" + done + else + : >"$managed_file" + fi + + printf '%s\n' "$version" >"$version_file" + return 0 } start_kai_bin(){ procd_open_instance kai_bin - procd_set_param command /usr/sbin/kai_bin + procd_set_param command /usr/sbin/kai_bin -a 0.0.0.0 -p "$port" procd_set_param stderr 1 procd_set_param respawn procd_close_instance } mkdir_cwd(){ - if [ ! -d $1 ]; then - mkdir -p $1 - fi + [ -d "$1" ] || mkdir -p "$1" } start_kai_session(){ procd_open_instance kai_session - procd_set_param env OPENCODE_CWD=$1 OPENCODE_CONFIG=http://127.0.0.1:8197/config/opencode/opencode.json + local root="${data_dir}" + local cwd="${data_dir}/cwd" + procd_set_param env \ + OPENCODE_CWD="${cwd}" \ + OPENCODE_CONFIG="http://127.0.0.1:${port}/agentconf/opencode.json" \ + XDG_CACHE_HOME="${root}/cache" \ + XDG_DATA_HOME="${root}/data" \ + XDG_CONFIG_HOME="${root}/config" \ + XDG_STATE_HOME="${root}/state" procd_set_param command /usr/sbin/kai_session procd_append_param command serve --port "8196" --hostname "127.0.0.1" procd_set_param stderr 1 @@ -35,14 +106,24 @@ start_service() { if [ $enabled != 1 ]; then return 1 fi + if [ -z "${data_dir}" ]; then + logger -t kai "data_dir is empty; please set option data_dir in /etc/config/kai" + return 1 + fi logger -t kai "Starting KAI Service" start_kai_bin sleep 1 - mkdir_cwd $cwd - start_kai_session $cwd + mkdir_cwd "${data_dir}" + mkdir_cwd "${data_dir}/cwd" + mkdir_cwd "${data_dir}/cache" + mkdir_cwd "${data_dir}/data" + mkdir_cwd "${data_dir}/config" + mkdir_cwd "${data_dir}/state" + maybe_refresh_opencode_skills_cache + start_kai_session logger -t kai "Starting KAI Service Completed" } service_triggers() { procd_add_reload_trigger "kai" -} \ No newline at end of file +} diff --git a/kai_session/Makefile b/kai_session/Makefile index 19898beb5..dcf0d79aa 100644 --- a/kai_session/Makefile +++ b/kai_session/Makefile @@ -10,10 +10,10 @@ include $(TOPDIR)/rules.mk PKG_ARCH_kai_session:=$(ARCH) PKG_NAME:=kai_session -PKG_VERSION:=0.0.2 -PKG_RELEASE:=3 +PKG_VERSION:=0.0.5 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/Carseason/openwrt-packages/releases/download/prebuilt/ +PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/ PKG_HASH:=skip PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION) diff --git a/luci-app-kai/Makefile b/luci-app-kai/Makefile index 8a9d1ff0c..c9cc7e7cb 100755 --- a/luci-app-kai/Makefile +++ b/luci-app-kai/Makefile @@ -7,9 +7,9 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=kai -PKG_VERSION:=1.0.0 -PKG_RELEASE:=4 -LUCI_DEPENDS:=+kai +kai_session +PKG_VERSION:=1.0.1 +PKG_RELEASE:=5 +LUCI_DEPENDS:=+kai +kai_session +luci-compat LUCI_MINIFY_CSS:=0 LUCI_MINIFY_JS:=0 @@ -17,7 +17,7 @@ define Package/luci-app-kai/conffiles /etc/config/kai endef -define Package/luci-nginxer/postrm +define Package/luci-app-kai/postrm #!/bin/sh rm -f /tmp/luci-indexcache exit 0 @@ -25,4 +25,4 @@ endef include $(TOPDIR)/feeds/luci/luci.mk -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-kai/luasrc/model/cbi/kai.lua b/luci-app-kai/luasrc/model/cbi/kai.lua index 997cd6784..8c8fb48a2 100644 --- a/luci-app-kai/luasrc/model/cbi/kai.lua +++ b/luci-app-kai/luasrc/model/cbi/kai.lua @@ -1,6 +1,6 @@ local m, s -m = Map("kai", translate("KAI"), translate("KAI is an efficient data transfer tool.")) +m = Map("kai", translate("KAI"), translate("KAI is an efficient AI tool.")) m:section(SimpleSection).template = "kai/kai_status" s=m:section(TypedSection, "kai", translate("Global settings")) @@ -8,6 +8,25 @@ s.addremove=false s.anonymous=true s:option(Flag, "enabled", translate("Enable")).rmempty=false + +local kai_model = require "luci.model.kai" +local blocks = kai_model.blocks() +local home = kai_model.home() + +local data_dir = s:option(Value, "data_dir", translate("Data directory")) +data_dir.rmempty = false +data_dir.description = translate("Required. KAI session will store cwd/cache/data/config/state under this directory (subfolders: cwd, cache, data, config, state).") + +local paths, default_path = kai_model.find_paths(blocks, home, "Configs") +for _, val in pairs(paths) do + data_dir:value(val, val) +end +data_dir.default = default_path + +local port = s:option(Value, "port", translate("API port")) +port.default = "8197" +port.rmempty = false +port.datatype = "port" +port.description = translate("Port for KAI HTTP server (kai_bin). kai_session will read OPENCODE_CONFIG via 127.0.0.1:.") + return m - - diff --git a/luci-app-kai/luasrc/model/kai.lua b/luci-app-kai/luasrc/model/kai.lua new file mode 100644 index 000000000..b4ef84996 --- /dev/null +++ b/luci-app-kai/luasrc/model/kai.lua @@ -0,0 +1,54 @@ +local jsonc = require "luci.jsonc" + +local kai = {} + +kai.blocks = function() + local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r") + local vals = {} + if f then + local ret = f:read("*all") + f:close() + local obj = jsonc.parse(ret) + for _, val in pairs(obj and obj["blockdevices"] or {}) do + local fsize = val["fssize"] + if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then + vals[#vals + 1] = val["mountpoint"] + end + end + end + return vals +end + +kai.home = function() + local uci = require "luci.model.uci".cursor() + local home_dirs = {} + home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root") + home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"] .. "/Configs") + home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"] .. "/Public") + home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"] .. "/Downloads") + home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"] .. "/Caches") + return home_dirs +end + +kai.find_paths = function(blocks, home_dirs, path_name) + local default_path = "" + local paths = {} + + default_path = home_dirs[path_name] .. "/KAI" + if #blocks == 0 then + table.insert(paths, default_path) + else + for _, val in pairs(blocks) do + table.insert(paths, val .. "/" .. path_name .. "/KAI") + end + local without_conf_dir = "/root/" .. path_name .. "/KAI" + if default_path == without_conf_dir then + default_path = paths[1] + end + end + + return paths, default_path +end + +return kai + diff --git a/luci-app-kai/luasrc/view/kai/kai_status.htm b/luci-app-kai/luasrc/view/kai/kai_status.htm index f2f50aab1..be616836d 100644 --- a/luci-app-kai/luasrc/view/kai/kai_status.htm +++ b/luci-app-kai/luasrc/view/kai/kai_status.htm @@ -14,7 +14,7 @@ XHR.poll(5, '<%=url("admin/services/kai_status")%>', null,function(x, st){ //]]>
- 状态 + <%:Status%>

<%:Collecting data...%>

diff --git a/luci-nginxer/Makefile b/luci-nginxer/Makefile index e3fd41e1e..3de417aee 100644 --- a/luci-nginxer/Makefile +++ b/luci-nginxer/Makefile @@ -8,17 +8,17 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Nginxer LUCI_DESCRIPTION:=Standard OpenWrt set including full admin with ppp support and the default Bootstrap theme -PKG_VERSION:=0.0.1 -PKG_RELEASE:=2 +PKG_VERSION:=0.0.2 +PKG_RELEASE:=3 LUCI_DEPENDS:=+luci-nginx define Package/luci-nginxer/postrm #!/bin/sh -/etc/init.d/uhttpd enabled +/etc/init.d/uhttpd enable /etc/init.d/uhttpd start exit 0 endef include $(TOPDIR)/feeds/luci/luci.mk -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-nginxer/root/etc/uci-defaults/50_luci-nginxer b/luci-nginxer/root/etc/uci-defaults/50_luci-nginxer index 9d01f3982..18e28cfdd 100644 --- a/luci-nginxer/root/etc/uci-defaults/50_luci-nginxer +++ b/luci-nginxer/root/etc/uci-defaults/50_luci-nginxer @@ -8,7 +8,11 @@ if [ "$nginxer" != 1 ]; then uci set nginx._redirect2ssl.access_log='off; # logd openwrt' uci set nginx.global.nginxer='1' uci commit nginx + + # fix firmware upload failed + sed -i 's/client_max_body_size 128M;/client_max_body_size 256M;/g' /etc/nginx/uci.conf.template + # /etc/init.d/uhttpd running || /etc/init.d/uhttpd disable /etc/init.d/nginx reload fi -exit 0 \ No newline at end of file +exit 0 diff --git a/sqm-autorate/Makefile b/sqm-autorate/Makefile index ac0ae79fb..03103a547 100644 --- a/sqm-autorate/Makefile +++ b/sqm-autorate/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=sqm-autorate PKG_VERSION:=0.1 -PKG_RELEASE:=1 +PKG_RELEASE:=2 include $(INCLUDE_DIR)/package.mk diff --git a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh index 1a340f1f8..094942192 100755 --- a/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh +++ b/sqm-autorate/files/usr/share/sqm-autorate/config_template.sh @@ -54,7 +54,7 @@ pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping') # so e.g. if 6 reflectors are specified and the number of pingers is set to 4, the first 4 reflectors will be used initially # and the remaining 2 reflectors in the list will be used in the event any of the first 4 go bad # a bad reflector will go to the back of the queue on reflector rotation -country="$(uci -q get omr-tracker.defaults.country)" +country="$(uci -q get omr-tracker.defaults.country || echo 'world')" reflectors=( $(uci -q get omr-tracker.${country}.hosts) ) #reflectors=( #"1.1.1.1" "1.0.0.1" # Cloudflare