🤞 Sync 2026-09-06 22:50:31

This commit is contained in:
github-actions[bot]
2026-09-06 22:50:31 +08:00
parent cb845a1f2d
commit 65e584daaa
115 changed files with 8599 additions and 1391 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ AGENTFLOW_HASH_aarch64:=6d733ebc49b095bf8670a1b655a13bb8ad98c90ced19701b67d5cdd4
PKG_NAME:=agentflow
PKG_VERSION:=0.3.0
PKG_RELEASE:=7
PKG_RELEASE:=8
AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH)
AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH))
@@ -1,84 +0,0 @@
# AgentFlow 共享 Runtime HOME 实施里程碑
## 目标架构
AgentFlow 的应用数据和设备级开发运行时分离:
- AgentFlow 数据目录:`<quickstart.conf_dir>/AgentFlow`
- 共享 Runtime HOME`<quickstart.conf_dir>/Runtime/home`
共享 Runtime HOME 由 `mise` 包提供公共 helper 初始化,AgentFlow 和后续运行时感知应用复用同一套 `HOME`、XDG、`MISE_*``PATH`
## Milestone 1:公共 Runtime HOME 合约
目标:
- `mise` 包安装 `/etc/config/mise`
- `mise` 包安装 `/lib/functions/istore_runtime.sh`
- helper 自动从 `quickstart.main.conf_dir` 推导 `<conf_dir>/Runtime/home`
- helper 支持 `ISTORE_RUNTIME_CONF_DIR` 兜底,便于应用从自身 Configs 目录派生 Runtime。
- helper 统一导出 `HOME``XDG_DATA_HOME``XDG_CACHE_HOME``XDG_CONFIG_HOME``XDG_STATE_HOME``MISE_DATA_DIR``MISE_CACHE_DIR``MISE_CONFIG_DIR``MISE_STATE_DIR``PATH`
验收:
- 新安装 `mise` 后,存在 `/etc/config/mise``/lib/functions/istore_runtime.sh`
- 已配置 quickstart 时,初始化路径为 `<quickstart.conf_dir>/Runtime/home`
- 未配置 quickstart 但应用提供 `ISTORE_RUNTIME_CONF_DIR` 时,初始化路径为 `$ISTORE_RUNTIME_CONF_DIR/Runtime/home`
## Milestone 2AgentFlow 接入共享 Runtime HOME
目标:
- AgentFlow 不再使用 `$data_dir/global` 作为 `HOME` 或 mise shim 根。
- AgentFlow 启动时调用 `istore_runtime_export_env`
- `AGENT_FLOW_DATA` 继续固定在 AgentFlow 数据目录下的 `data` 子目录。
- AgentFlow 服务进程及其子进程继承共享 Runtime HOME。
验收:
- `/etc/init.d/agentflow start` 后,AgentFlow 进程环境中 `HOME=<conf_dir>/Runtime/home`
- `MISE_DATA_DIR=$HOME/.local/share/mise`
- `PATH``$MISE_DATA_DIR/shims:$HOME/.local/bin` 开头。
- AgentFlow 数据库仍写入 `<conf_dir>/AgentFlow/data/db/db.sqlite`
## Milestone 3LuCI 可见性
目标:
- AgentFlow LuCI 页面继续配置 AgentFlow 数据目录。
- 页面展示推导出的共享 Runtime HOME。
- 如果 `mise.runtime_dir` 被显式设置,页面展示其对应的 `home`
验收:
- quickstart `conf_dir=/mnt/vio3-1/Configs` 时,页面显示 `/mnt/vio3-1/Configs/Runtime/home`
- AgentFlow 数据目录仍显示 `/mnt/vio3-1/Configs/AgentFlow`
## Milestone 4:迁移与兼容
目标:
- 新安装默认使用共享 Runtime HOME。
- 老安装中已有 `$data_dir/global/.local/share/mise` 时,不自动移动大目录。
- 后续提供显式迁移命令或 LuCI 操作。
验收:
- 升级不会删除或搬移旧 runtime 数据。
- 用户确认迁移后,旧 mise data 可迁移到 `<conf_dir>/Runtime/home/.local/share/mise`
- 迁移失败不会影响 AgentFlow 私有数据。
## Milestone 5AgentFlow 后端项目环境集成
目标:
- OpenWrt 层面完成共享 HOME 后,再在 AgentFlow 后端引入项目环境 wrapper。
- coding agent 进程使用 `mise exec -- <agent> ...` 应用项目 `mise.toml`
- 运行期设置 `MISE_EXEC_AUTO_INSTALL=0`,缺失工具只在准备阶段安装。
验收:
- 单 repo 项目中,agent 看到项目声明的 Node/Python/Go 版本。
- 没有隐式运行期下载。
- Codex/Claude/Kimi 等 agent 凭据继续来自共享 Runtime HOME。
- 取消任务时 wrapper 和 agent 子进程都能退出。
+8 -27
View File
@@ -10,22 +10,6 @@ get_config() {
config_get port "$1" port "9000"
}
load_runtime_env() {
local conf_dir
[ -n "$data_dir" ] || return 1
conf_dir="$(dirname "$data_dir")"
export ISTORE_RUNTIME_CONF_DIR="$conf_dir"
if [ -r /lib/functions/istore_runtime.sh ]; then
. /lib/functions/istore_runtime.sh
istore_runtime_export_env
return $?
fi
return 1
}
start_service() {
config_load agentflow
config_foreach get_config agentflow
@@ -35,11 +19,16 @@ start_service() {
logger -t agentflow "missing executable: /usr/sbin/agentflow"
return 1
}
mkdir -p "$data_dir" "$data_dir/data" || return 1
if ! load_runtime_env; then
logger -t agentflow "shared runtime home is not configured"
[ -r /lib/functions/mise.sh ] || {
logger -t agentflow "missing mise environment helper"
return 1
}
. /lib/functions/mise.sh
if ! istore_runtime_env; then
logger -t agentflow "failed to initialize mise environment"
return 1
fi
mkdir -p "$data_dir" "$data_dir/data" || return 1
logger -t agentflow "starting AgentFlow on $host:$port"
procd_open_instance
@@ -49,14 +38,6 @@ start_service() {
"AGENT_FLOW_HOST=$host" \
"AGENT_FLOW_PORT=$port" \
"HOME=$HOME" \
"XDG_DATA_HOME=$XDG_DATA_HOME" \
"XDG_CACHE_HOME=$XDG_CACHE_HOME" \
"XDG_CONFIG_HOME=$XDG_CONFIG_HOME" \
"XDG_STATE_HOME=$XDG_STATE_HOME" \
"MISE_DATA_DIR=$MISE_DATA_DIR" \
"MISE_CACHE_DIR=$MISE_CACHE_DIR" \
"MISE_CONFIG_DIR=$MISE_CONFIG_DIR" \
"MISE_STATE_DIR=$MISE_STATE_DIR" \
"PATH=$PATH"
procd_set_param stdout 1
procd_set_param stderr 1
@@ -1,80 +0,0 @@
from pathlib import Path
import unittest
THIS_FILE = Path(__file__).resolve()
def read(relative):
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):
def test_mise_package_installs_shared_runtime_contract(self):
makefile = read("mise/Makefile")
config = read("mise/files/mise.config")
defaults = read("mise/files/mise.uci-default")
helper = read("mise/files/istore_runtime.sh")
self.assertIn("/etc/config/mise", makefile)
self.assertIn("/lib/functions/istore_runtime.sh", makefile)
self.assertIn("$(INSTALL_BIN) ./files/mise.uci-default", makefile)
self.assertIn("[ -f /etc/uci-defaults/mise ]", makefile)
self.assertIn("config mise 'main'", config)
self.assertIn("option runtime_dir ''", config)
self.assertIn("option auto_discover '1'", config)
self.assertIn(". /lib/functions/istore_runtime.sh", defaults)
self.assertIn("istore_runtime_init", defaults)
self.assertIn("config_get conf_dir main conf_dir", helper)
self.assertIn('"$conf_dir" "$ISTORE_RUNTIME_DEFAULT_SUBDIR"', helper)
self.assertIn("ISTORE_RUNTIME_HOME_SUBDIR=\"home\"", helper)
self.assertIn("ISTORE_RUNTIME_CONF_DIR", helper)
self.assertIn('export HOME="$runtime_home"', helper)
self.assertIn('export XDG_DATA_HOME="$HOME/.local/share"', helper)
self.assertIn('export MISE_DATA_DIR="$XDG_DATA_HOME/mise"', helper)
self.assertIn('export PATH="$MISE_DATA_DIR/shims:$HOME/.local/bin:$PATH"', helper)
def test_agentflow_consumes_shared_runtime_home(self):
init = read("agentflow/files/agentflow.init")
cbi = read("luci-app-agentflow/luasrc/model/cbi/agentflow.lua")
model = read("luci-app-agentflow/luasrc/model/agentflow.lua")
translations = read("luci-app-agentflow/po/zh-cn/agentflow.po")
self.assertIn(". /lib/functions/istore_runtime.sh", init)
self.assertIn("istore_runtime_export_env", init)
self.assertIn('AGENT_FLOW_DATA=$data_dir/data', init)
self.assertIn('HOME=$HOME', init)
self.assertIn('MISE_DATA_DIR=$MISE_DATA_DIR', init)
self.assertNotIn("$data_dir/global", init)
self.assertNotIn(".local/share/mise/shims:$PATH", init)
self.assertIn('translate("Shared runtime home")', cbi)
self.assertIn("agentflow_model.runtime_home", cbi)
self.assertIn('return runtime_dir .. "/home"', model)
self.assertIn('return conf_dir .. "/Runtime"', model)
self.assertIn('msgid "Shared runtime home"', translations)
self.assertIn('msgstr "共享运行时 HOME"', translations)
if __name__ == "__main__":
unittest.main()