Commit Graph

3 Commits

Author SHA1 Message Date
51789ee72e deploy: 标准目录部署 —— 运行时不再依赖源码目录
用户注意到:「当前 agentmail 是在源码目录部署的,应当改为标准目录部署」。
查证后有三处实证(都不是猜测):

1. ★ **失败通知钩子执行的是仓库里的脚本**
   (`/home/program/agentmail/deploy/service-failure-notify.mjs`,8 处引用:
   4 个 drop-in + zcode/zcode-mail-bridge 单元 + agentmail-failure-flush)。
   仓库一挪/一改名,故障通知就**静默失效** —— 而那条管线正是用来报告服务故障的。
2. **opencode-serve 的 cwd 就是源码目录**(`WorkingDirectory=/home/program/agentmail`)。
3. ★ **仓库里的 `deploy/*.service` 是旧的源码目录版本**(ExecStart 指向
   `/home/program/agentmail/plugins/...`),而机器上的已被改过 —— 也就是说
   **谁跑一次 install.sh 就会把部署退回源码目录**。drop-in 更是只存在于 /etc 里,
   仓库完全没有它们。

## 改动

- **唯一真相**:`deploy/systemd/` 镜像 systemd 目录结构,收进全部单元与 drop-in
  (8 个单元 + 12 个 drop-in),路径全部改到 `/opt`。
- 运行时脚本装到 **`/opt/agentmail/bin/service-failure-notify.mjs`**(自包含,
  无相对导入);`install.sh` 与 `redeploy-gateway.sh` 都会幂等地装它。
- opencode 的 cwd 改为 `/opt/agentmail`(与网关一致),已重启生效
  (`/proc/<pid>/cwd` 已核)。
- 删掉 `deploy/*.service` 的旧副本,避免两个真相。
- dsh 的 `cordis.patch.yml` 注释里的安装示例也改到标准位置(运行时用的是环境变量,
  那条注释是唯一残留)。

## 判据(`deploy/check-deploy-drift.mjs` 新增「标准目录部署」四条 + 自检)

① 任何 unit/drop-in 都不得引用源码目录;② 已安装单元与 `deploy/systemd/` 逐字节一致;
③ 通知脚本在标准位置且可执行;④ 各服务的 cwd/ExecStart 不在源码目录
(homeagent/dsh/zcode 是**别的产品**的标准位置,按白名单放行)。
自检两个样本:引用源码目录的必须红、干净样本必须绿(证明不是恒真)。

顺带修掉一处**真漂移**:仓库里 dsh 的 `dist/index.js` 落后于部署件(改了 src 没重建),
重建后 `check-deploy-drift` 报「四个宿主都在跑当前代码」。

## 复核

- `/etc/systemd/system/` 引用仓库:**0** 个文件;`/opt/agentmail` 下只剩旧二进制/备份里
  的构建路径(Go 嵌的源码路径,无害)与一条注释。
- 四个宿主都在跑当前代码;标准目录四项全绿。
- 全部服务 active,opencode/网关 cwd 均已在安装根下。
2026-09-14 08:38:33 +08:00
f9d757b5e5 chore: directory migration - gateway→server, web→client/electron 2026-09-08 19:16:35 +08:00
a101c2fada 停用/恢复文案说清密钥不会自动回来 + 原子部署脚本
## 起因

本会话踩到一次:浏览器测试点了 opencode 的「停用」按钮验证确认流程,
停用连带撤销全部密钥。插件从此拿着已撤销的密钥重试了 18 小时
(gateway 日志 2690 次 401),而 UI 只说了「已停用」。

恢复时同样没提示「密钥不会自动回来」,点完恢复以为就完事了。

## 文案

后端 `AdminSetAgentStatus`:
- 停用 detail 补一句「停用期间别人发信给它会收到 409」
- 恢复 detail 改成「停用时撤销的密钥不会自动回来 —— 必须在密钥面板
  重新签发一把并写进该插件的配置,否则它会一直拿旧密钥重试并被拒(401)」
- 恢复响应加 `needs_new_key: true` 字段,前端可据此做更强的提示

前端 QuotaPanel:恢复成功的 notice 不再是「已恢复」四个字,
把重新签发这一步说全;面板说明与按钮 title 同步。

## AdminDeleteAgent 两处修正

- 硬编码 `name == "jianf"` 改成按 `repo.IsHumanUser` 判定 —— 换管理员时
  硬编码会失效,而人类账号不该走 Agent 删除端点
- detail 原来说「日历事件已保留」,实际 `DeleteAgent` 把 active 事件置为
  cancelled(留着会由调度器一直触发,而发信人已不存在)。文案改成实际行为

## deploy/redeploy-gateway.sh(新)

日常改后端不必重跑 install.sh(它重装 npm 依赖、重写 systemd 单元、
重新生成 env)。这个脚本做手工 `stop → cp → start` 不做的四件事:

- `sqlite3 .backup` 备份数据库 + 立即 `PRAGMA integrity_check` 复核。
  不用 cp:WAL 模式下 cp 会拿到主库与 -wal 不同步的快照
- `install -m 0755` 原子替换二进制。install 本质是 rename,要么完整
  换掉要么原样不动;cp 是就地写入,中途失败会留下半截文件且旧的已被覆盖
- 旧二进制留档并打印可直接粘贴的回滚命令
- 后置验证清单:服务 active / /health 可达 / 近 2 分钟无 panic /
  SSE 重连计数。任一项不过**自动回滚**,不「先上着再修」

`--dry-run` 只打印动作,`--skip-tests` 急救用,`--skip-web` 跳过前端同步。
纪律来自 git-release-discipline skill 第五章。

## 验证

- 脚本 dry-run + 真实跑通一次:备份 integrity_check=ok、原子替换、
  9 个 SSE 客户端重连、验证四项全绿
- 停用/恢复文案线上实测;`DELETE /admin/agents/jianf` → 403「是人类用户」
- 端到端:jianf → opencode「部署脚本验收」→ 回信「部署验收 OK」
- 全量测试:gateway 全包 / web 176 / opencode 217 / pi 288 / dsh 241 /
  homeagent go ok;三方共用模块同源检查通过
2026-09-05 10:10:13 +08:00