Files
HomeAgent/.gitignore
JianFeeeee 198811253a feat(webui+guard): 内核重启/关机按钮,指令走心跳复用既有协议
## 需求

WebUI 加关机与重启按钮,内核提供对应内部接口。有些状态变更只能靠重启
生效(换 LLM 源、换主密钥),没有这条通道时用户只能 ssh 上去敲 systemctl。

## 设计:复用心跳,不新开通道(用户指出的方向)

guard 与 worker 之间已经有一条现成的、每 5s 一次的单向通报(心跳文件,
内容原本是 `t=<unix>`,只用来刷 mtime)。用户点按钮本质就是"我要你在
下一次心跳时知道这件事"——再开 unix socket / 信号 / 临时文件,只会多出
一套要防重、防丢、防竞态的机制。

    WebUI 点按钮
      → POST /api/v1/kernel/{restart,shutdown}
      → sdk.KernelControlAPI(只投递,立即返回)
      → 下一次心跳把 `cmd=restart|shutdown reason=...` 写进 <data>/heartbeat
      → 重启:worker 清理 → exit 42 → guard 重拉(**既有机制,零改动**)
        关机:guard 在 workerCleanExit 分支读到 cmd=shutdown
              → systemctl stop → 不再拉起

★ 关机为什么必须由 guard 做:
  unit 是 Restart=always,guard 自己 return 会被 systemd 立刻拉起
  (用户点了"关机"、几秒后服务又活了)。必须显式 systemctl stop。
  而不让 worker 自己停:它是被守护方,且**只有 guard 知道这次该不该重拉**。

★ 指令必须一次性消费:guard 读完立即原子重写文件清除 cmd 行,
  否则每次心跳都读到同一条 ⇒ 无限重启/关机。worker 侧还要检查
  "指令写过但文件里没了" ⇒ 已被消费 ⇒ 清本地 pending,否则又写回去。

## 顺带修的真缺陷:心跳文件无限增长

生产实测 **14.6MB**(纯 O_APPEND,约 70 天)。心跳的唯一职责是刷 mtime,
历史行没有任何读者 ⇒ 每次 consume 要整读 14.6MB(实测 27ms)。
改为 O_TRUNC 滚动写:只保留当前一行。真机验证 15,322,164 → 13 字节。
consume 也加了尺寸守卫(大文件只读尾部 8KB)。

## 安全:能力分级 + 白名单(两道)

1. proc 桥的 method 能力表:新增 `CapKernelControl` 一档。
   ★ 判据 `TestCapability_AllMethodsClassified` 当场报出
   "未登记 ⇒ 会按 CapCore 放行,绕过权限检查" —— 那意味着任何插件都能关机。
2. 内置插件走 `SDKConfig.KernelControl`,第一版我写成"有就发",
   等于全部内置插件都能关机。改为按名字白名单(目前只有 webui)。

## 判据(7 条)

心跳:解析 / 消费后必须清除 / worker 不得写回已消费指令 / 未消费时必须续写
能力:只有白名单插件拿得到 / 未装配时返回 nil 不 panic / SDK nil 安全
心跳文件:不得无限增长 / 大文件只读尾部且读后收敛

变异 6/6 咬住。全量 53 包 ok。

## UI

导航底栏两个图标按钮(与主题/语言/退出并列):重启有确认框 + 轮询等它
回来并自动刷新;关机有**二次确认且写清后果**(必须人工 systemctl start)。
两者都先把响应写回浏览器并 Flush,再让内核退出 —— 否则用户看到的是
connection reset,无法区分"正在重启"和"真出故障了"。
2026-10-17 21:18:07 +08:00

126 lines
4.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/homed
/waiter
*.exe
*.log
*.test
build/
*.so
*.db
data/
.tmp-plugins/
.go/
.local/
*.hmap
dev/
login.json
# GUI
cmd/gui/node_modules/
cmd/gui/dist/
.gopath/
# SDK 工具链 — 核心仓不追踪
#
# 外部插件与工具链维护在独立 SDK 仓(决策 sdk_repo_only),
# 本仓经 go.mod 的 replace => ./third_party/homeagent-sdk 引用。
# example/ 下已跟踪的 21 个文件(10 个示例的 plg.json + plugin.go,
# 加 qq/plugin_test.go)早于本规则,
# 靠「已跟踪文件不受 .gitignore 影响」保留——这是有意的,不要「修」。
third_party/homeagent-sdk/bin/
third_party/homeagent-sdk/tools/
third_party/homeagent-sdk/package/
third_party/homeagent-sdk/scripts/
# skills/ 是 SDK 仓的 skill 源(hmapdev skill install 的来源),
# 与 tools/、docs/ 同理属 SDK 仓自治范围,不进本仓。
third_party/homeagent-sdk/skills/
# .github/ 同理:SDK 仓的 workflow 由 SDK 仓自己管(它在那边被跟踪),
# 本仓不参与构建,不需要在这边重复一份。
third_party/homeagent-sdk/.github/
third_party/homeagent-sdk/.gitignore
third_party/homeagent-sdk/README*
third_party/homeagent-sdk/example/
# 文档站(mkdocs.yml + docs/ + 生成器)属于 SDK 仓,与 README* / tools/ 同理。
# 注意 docs/ 带前导路径限定,够精确:本仓自己的 docs/ 不受影响。
third_party/homeagent-sdk/docs/
third_party/homeagent-sdk/mkdocs.yml
third_party/homeagent-sdk/site_build/
# 主题覆盖目录(只覆盖 footer.html,补备案号)——同属文档站。
third_party/homeagent-sdk/overrides/
.codegraph/
# codegraph 本地索引配置(含嵌套 SDK 仓放行,仅本地生效)
codegraph.json
# 运行时产物(不提交)
#
# ⚠️ 这些必须带前导斜杠。不带斜杠的模式(如 `memory/`)会匹配**任意层级**的
# 同名目录,把 internal/memory/、internal/knowledge/、deploy/scripts/ 一起吞掉
# ——24 + 3 + 1 个已跟踪源码文件曾因此落在 ignore 规则下,只靠「已跟踪
# 文件不受 .gitignore 影响」这条 git 规则兜着,新增文件会默默不入库。
/adapters/
/knowledge/
/memory/
# 注:/scripts/ **不**忽略。它是作者维护的工具目录(模型导出、侧车、部署校验),
# 不是运行期产物:deploy/systemd/embed-sidecar.service 直接引用
# scripts/embed_sidecar.py,忽略它会让那份 unit 在别人的机器上指向不存在的文件。
# 只忽略其中的缓存。
/scripts/__pycache__/
__pycache__/
terminal_locked_log.txt
dist/
.pi-glla/
.omo/
.pi/
# HarmonyOS 构建工具链缓存(HVIGOR_USER_HOME / ohpm 生成,非源码)
.hvigor-home/
.npm-cache/
.ohpm/
# 漂移巡检的运行时状态(含时间戳与指纹,每次跑都变)
.drift-watch/
# ——— 本地运维脚本 / 一次性工具(不入库,克隆后需另行获取)———
# deploy-*.sh 是生产部署入口,含环境相关的 IP/路径约定;
# 文档见 docs/zh/deploy-runbook.md。换机器部署前先确认脚本来源。
/deploy-plan.sh
/deploy-waiter.sh
/deploy-sdk-site.sh
# 一次性跑分/设计提取脚本,用完即弃
/tmp_jinabench.py
/napcat-design-dna.json
# 已删除的动态工作文档(2e30e06)。曾被本机某进程恢复过一次 ——
# 它的 mtime 还是删除前的 Sep 26,说明是外部写回而不是 git 操作。
# 不加这行的话,恢复一次就重新入库一次。
/plan.md
# 临时探针目录(scripts/ 之外的临时 main.go 探针)
/tools/zz_*/
# 编译产物(迁移工具)
/homed-graph-migrate
# 构建产物落在仓库根(go build ./cmd/xxx 时最易发生)
/homed
/homed-graph-migrate
/homed-graph-distill
/homed-centroid
# ── 本机运维脚本(含 /home/newqqagent 等本机路径与凭据搬运逻辑,不进仓库)──
/deploy/scripts/deploy.sh
/scripts/verify_deploy.sh
/scripts/kernel-stress/
/scripts/gui-package-smoke.sh
# ── 本地 AI 工具的仓库级配置(每人偏好不同,不进仓库)──
.pi-lens.json
# agent 会话附件(本地产物,不进版本库)
.pi-web/